Новости из Блогов Невидимый Flash

Discussion in 'Мировые новости. Обсуждения.' started by Suicide, 13 Sep 2012.

  1. Suicide

    Suicide Super Moderator
    Staff Member

    Joined:
    24 Apr 2009
    Messages:
    2,484
    Likes Received:
    7,075
    Reputations:
    693
    Невидимый Flash
    Совершенствование Web-приложений с помощью скрытого использования Flash Player

    Дата: 11.09.2012
    Майкл Галпин, инженер по программному обеспечению, Vitria Technology
    https://www.ibm.com/developerworks/ru/library/wa-aj-flash/
    http://www.ibm.com/developerworks/web/library/wa-aj-flash/index.html?S_TACT=105AGX99&S_CMP=CP



    Итак, приступим

    Как уже упоминалось, в этой статье мы рассмотрим, как использовать Flash, чтобы создать дополнительные возможности для Web-приложений. Для этого требуется знакомство с JavaScript, но и опыт работы с ActionScript не помешает. Существуют разные способы компиляции ActionScript, некоторые из которых зависят от коммерческих инструментов Adobe. Однако можно просто использовать SDK Flex с открытым исходным кодом от Adobe. Для примера из этой статьи использовался Flex SDK 4.0.0.10485 (бета-версия 2). Для исполнения примеров потребуется Flash Player версии 10 или выше. Для этой статьи я использовал версию 10.0.42.34. См. ссылки в разделе Ресурсы.


    Локальное хранилище Flash

    Многим Web-приложениям необходимо хранить данные о состоянии клиента. Иногда это может быть просто идентификатор сеанса, который можно использовать для получения состояния на сервере из памяти или базы данных. Однако многие Web-приложения сознательно избегают хранения состояния на сервере ради масштабируемости. В этом случае состояние должно храниться на клиентском компьютере. Кроме того, часто желательно, чтобы это состояние сохранялось после окончания текущего сеанса работы пользователя.

    В течение многих лет способом по умолчанию для этого были cookies HTTP. Однако у этого способа есть свои недостатки. Он труден в использовании с точки зрения разработчика, потому что физически это просто HTTP-заголовок. Еще важнее, что это потенциальный пробел в системе безопасности. При каждом запросе cookies HTTP пересылаются туда и обратно между клиентом и сервером, так что любые содержащиеся в них данные можно перехватить. Этот факт часто используют для "кражи cookies" с применением межсайтового скриптинга/подлога. Если злоумышленники украдут cookies, они смогут легко вскрыть и использовать соответствующую учетную запись.

    Но самый большой недостаток cookies HTTP – их ограниченный размер. Разные браузеры устанавливают разные ограничения на максимальный размер cookies HTTP, выделенный на домен. Спецификация HTTP устанавливает предел в 4 Кб, и это все, на что можно рассчитывать. Так что же делать, если на клиенте нужно хранить больше 4 КБ? Если вы когда-нибудь думали о том, что хорошо бы написать алгоритм сжатия в стиле GZIP на Java™Script, то это ваш шанс. Или можно использовать альтернативу, такую как Flash.


    Локальные общие объекты

    Flash Player создает локальное пространство для хранения данных Flash-приложений. По умолчанию оно ограничено 100 КБ на домен. Правильно: вы получаете в двадцать пять раз больше места, чем при использовании cookies HTTP. Есть и некоторые другие важные различия. Данные Flash на стороне клиента никогда не передаются на сервер, так как не имеют ничего общего с HTTP. Конечно, при желании можно взять эти данные и отправить его их сервер. Ничто не мешает это сделать. Однако можно выбрать, какие данные отправлять и как их передавать. Если эти данные действительно нужны как на стороне клиента, так и на стороне сервера, то придется немного повозиться. Зато это, как правило, гораздо безопаснее, потому что нужно явно "представить" эти данные через сеть.

    Flash API для хранения и извлечения локальных данных называется SharedObject. В технологии Flash есть понятие общих объектов SharedObject, которые могут быть удаленными, поэтому те, что хранятся только в клиенте, часто называют локальными SharedObject. API очень прост и позволяет произвольно хранить и извлекать сложные объекты с использованием парадигмы ключ-значение. В листинге 1 показан простой код для хранения и извлечения SharedObjects.

    Листинг 1. Хранение и извлечение SharedObjects
    Code:
    package{
    
        import flash.display.Sprite;
        import flash.net.SharedObject;
    
        public class JsHelper extends Sprite{
            private const SO_NAME:String = "helperSo";
    
            private function saveLocal(name:String, value:Object):void{
                var so:SharedObject = SharedObject.getLocal(SO_NAME);
                so.data[name] = value;
                so.flush();
            }
    
            private function readLocal(name:String):Object{
                var so:SharedObject = SharedObject.getLocal(SO_NAME);
                return so.data[name];
            }
        }
    }
    Тем, кто не знаком с ActionScript, код в листинге 1 может показаться немного странным. ActionScript очень похож на JavaScript; на самом деле, это производное от стандартного ECMAScript. Однако он имеет много особенностей, характерных для таких языков, как C++ и Java. Переменные строго типизированы, и существует наследование на основе классов. Код, приведенный в листинге 1, это класс, который расширяет класс Sprite. Такой класс компилируется в файл Shockwave Flash (SWF), который может быть встроен в Web-страницу. У этого класса есть два метода. Один называется saveLocal. Он берет имя (это просто строка) и значение (которое может быть объектом любого типа). Затем он получает определенный SharedObject с использованием метода класса getLocal.

    Каждый экземпляр SharedObject имеет свойство данных, которое можно рассматривать как хеш-таблицу для хранения данных. Это то, что делает вторая строка функции saveLocal. Последняя строка сохраняет объект SharedObject на диске (flush). Вот и все, что необходимо сделать, чтобы сохранить данные локально. Если вы интенсивно пользуетесь SharedObjects и начали приближаться к пределу в 100 KБ, то можете добавить к этому детекторы событий. Это позволит реагировать на такие события, как "flush завершен" или "flush не удался".

    Считывание из локального хранилища выполняется так же просто (функция readLocal в листинге 1). В данном случае SharedObject просматривается, и параметр name используется для поиска сохраненного объекта в данных хеш-таблицы. Если имя не соответствует ключу в хеш-таблице, то просто будет возвращен нуль. Теперь, когда вы увидели, как получить доступ к SharedObjects, достаточно разместить этот Flash (невидимо) на Web-странице – и обращаться к нему через JavaScript.


    Как сделать его невидимым

    По умолчанию ни одна из функций, показанных в листинге 1, не доступна за пределами класса JsHelper. Однако Flash значительно упрощает передачу функций в JavaScript. Все, что нужно, это API Flash ExternalInterface, как показано в листинге 2.

    Листинг 2. Передача функций JsHelper JavaScript
    Code:
    package{
    
        import flash.external.ExternalInterface;
        import flash.net.SharedObject;
    
        public class JsHelper extends Sprite{
            private const SO_NAME:String = "helperSo";
            private const SAVE_LOCAL:String = "saveLocal";
            private const READ_LOCAL:String = "readLocal";
    
            public function JsHelper(){
                ExternalInterface.addCallback(SAVE_LOCAL, saveLocal);
                ExternalInterface.addCallback(READ_LOCAL, readLocal);
            }
            // функции опущены для краткости 
        }
    }
    В листинге 2 просто показано, что было добавлено в класс JsHelper из листинга 1. Главное, обратите внимание на то, что мы добавили явный конструктор. Как и следовало ожидать, он будет вызываться всякий раз при создании экземпляра этого класса. В нем используется API ExternalInterface для представления двух функций, saveLocal и readLocal, любому JavaScript на любой Web-странице, куда будет встроен этот SWF. Функция addCallback принимает строку в качестве первого параметра. Это будет имя, используемое клиентами JavaScript для идентификации функции. Оно может отличаться от имени функции в классе, но в данном случае они совпадают. Второй параметр – это замыкание (closure) функции. Как и JavaScript, ActionScript является функциональным языком, так что функции представляют собой первый класс и могут передаваться. Вот все, что нужно для представления двух функций. Теперь рассмотрим сценарий JavaScript вложения и доступа к SWF. Он показан в листинге 3.

    Листинг 3. Вложение невидимого Flash
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Flash Helper for JavaScript</title>
    <script type="text/javascript" src="swfobject.js"></script>
    <script type="text/javascript">
        function writeFlash(){
            var attrs = {id : "JsHelper"};
            swfobject.embedSWF("JsHelper.swf", "flashContainer", "1", "1", "10.0.0", 
                "playerProductInstall.swf", null, null, attrs);
        }
        function save(name, value){
            var helper = document.getElementById("JsHelper");
            helper.saveLocal(name, value);
        }
        function load(name){
            var helper = document.getElementById("JsHelper");
            return helper.readLocal(name);        
        }
    </script>
    </head>
    <body onload="writeFlash()">
        <div id="flashContainer"></div>
    </body>
    </html>
    Первое, что нужно отметить в этом коде, это то, что он использует внешнюю библиотеку JavaScript под названием swfobject. Эта библиотека – стандарт де-факто для встраивания SWF. Это программа с открытым исходным кодом, которая распространяется Adobe, хотя была разработана другими. Ее функция embedSWF используется для внедрения SWF, скомпилированного из листинга 2. Первый параметр – это URL SWF. В данном случае SWF передается с того же сервера и по тому же пути, что и файл HTML, так что отлично работает относительный URL. Второй параметр – идентификатор HTML-элемента на странице, в которую будет внедрен SWF. В данном случае это "flashContainer" – и заметьте, что в теле HTML-документа есть HTML div с этим идентификатором.

    Следующие два параметра embedSWF – высота и ширина SWF. В данном случае оба они равны 1. Это означает, что SWF будет иметь высоту и ширину в один пиксель. Вот и невидимость SWF! Следующий параметр – минимальная версия Flash, которую будет проверять ваш код JavaScript. Если Flash установлен в браузере, но это более ранняя версия, чем минимальная версия, переданная embedSWF, то embedSWF будет использовать следующий параметр "playerProductInstall.swf". Это URL-адрес другого SWF с предложением пользователю установить последнюю версию Flash. В случае невидимого Flash в этом нет большого смысла – SWF "Вам необходимо установить последнюю версию Flash" тоже будет невидимым (1х1 пиксель). Последний параметр, передаваемый embedSWF, важен. Это атрибуты объекта, который может содержать различные дополнительные параметры. Один из таких необязательных параметров – идентификатор SWF. Для такого случая использования, как в этой статье, данный параметр – не желательный, а обязательный! Он присваивает SWF идентификатор HTML, который потребуется для получения программного доступа к нему с помощью JavaScript.

    Теперь рассмотрим две функции JavaScript, приведенные в листинге 3. Они очень похожи. Обе используют знакомую функцию getElementById для получения ссылки на SWF. Обратите внимание, что используется ID, указанный в объекте attrs, в функции writeFlash. После того как вы получите ссылку на SWF, вы можете напрямую вызывать функции ActionScript, показанные в листинге 2. Ключевым моментом здесь является то, что имя функции, используемое в JavaScript, должно совпадать с именем, полученным посредством функции ExternalInterface.addCallback, или первым параметром, переданным addCallback.

    Для метода save объект JavaScript передается в качестве параметра. Это может быть любой объект, даже с глубоко вложенной структурой. Однако передаются только его данные. Если объект содержит какие-либо функции, они не будут переданы. Обратите внимание, что метод load возвращает все, что пришло из SWF. Что это будет? Ответ прост: все, что вы передали. Если вы храните скалярное значение, такое как число или строка, это и будет возвращено. Если вы храните сложный объект, то будет возвращен объект JavaScript – не требующий разбора, и т.п. Единственное исключение – если объект имеет функции, они, очевидно, не могут быть сериализованы и сохранены. Так что это только данные вашего объекта, ни больше, ни меньше. Вот и все, что необходимо знать об использовании Flash для локального хранения данных. Прежде чем перейти к междоменному Ajax с использованием Flash, рассмотрим некоторые доступные альтернативы локального хранения данных.


    Другие способы локального хранения

    Я упомянул, что Flash может быть привлекательным способом хранения данных на стороне клиента по сравнению с cookies HTTP. Однако существуют другие Web-технологии, принявшие ту же парадигму, что и SharedObjects из Flash. В самом деле, в течение многих лет различные браузеры предлагают очень похожие API. Однако эти API, как правило, различается от одного браузера к другому. Поэтому нужно определить браузер и использовать соответствующий API. Flash же дает согласованную альтернативу. Код, разработанный в этой статье, будет работать практически на любом браузере: От Internet Explorer 6 и Firefox 2 вплоть до самой последней версии этих браузеров. Однако новые версии тоже обеспечивают согласованную альтернативу. Спецификация HTML 5 включает в себя API localStorage. Он реализован в последней версии основных браузеров, включая IE 8 и Firefox 3.5. Так что если нужно заботиться только об этих браузерах, localStorage – хорошая возможность. Если же нужно беспокоиться и о старых браузерах (IE 6, IE 7 и т.п.), проще прибегнуть к Flash. Теперь рассмотрим еще одно место, где Flash может открыть новые возможности: междоменный Ajax.


    Междоменный Ajax

    Ajax стал вездесущим инструментом Web-программирования, это неотъемлемая часть любого Web-приложения. Одно из основных ограничений Ajax – пресловутое правило одного и того же источника. Если Web-страница передается с сайта a.com, можно делать вызовы Ajax (точнее, XMLHttpRequest) только к a.com. Нельзя обратиться, например, к b.com. Не важно, что и a.com, и b.com принадлежат вашей компании; браузер тоже не имеет значения. Однако к Flash-приложениям это не относится.

    Flash-приложениям может быть предоставлена возможность обращаться к другим доменам. Это делается с помощью файла междоменной политики. По умолчанию, при исполнении Flash ищет этот файл политики в корневом каталоге документов сервера: http://<your domain>/crossdomain.xml. Например, в листинге 4 представлен файл политики для домена поиска Twitter, http://search.twitter.com/crossdomain.xml.

    Листинг 4. Файл политики для домена поиска Twitter
    Code:
    <!DOCTYPE cross-domain-policy 
    SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
    
    <cross-domain-policy>
        <allow-access-from domain="*" />
    </cross-domain-policy>
    Это особенно интересный файл политики. Он предоставляет доступ к SWF из любого домена (это указано подстановочным знаком "*"). Таким образом, любое Flash-приложение может вызвать API поиска Twitter. Такие файлы политики – обычное явление для крупных Web-сайтов с публичными API. Однако некоторые сайты используют более ограничительные политики, которые разрешают доступ только из тех доменов, которыми владеют или с которыми поддерживают партнерские отношения. С помощью файлов политики вы получаете детальный контроль над тем, кто может обращаться к вашим серверам, а кто не может. Рассмотрим, как можно распространить эти же возможности на Ajax-приложения.

    Продолжение ->
     
  2. Suicide

    Suicide Super Moderator
    Staff Member

    Joined:
    24 Apr 2009
    Messages:
    2,484
    Likes Received:
    7,075
    Reputations:
    693
    Продолжение


    Достижение межддоменности

    Если приложение должно обращаться только к конкретному домену, можно написать код ActionScript, который вызывает этот домен, а затем представить его с помощью ExternalInterface сценарию JavaScript в своем приложении. Однако я выберу немного более амбициозный путь и попытаюсь представить это в общем виде. Итак, в листинге 5 представлен служебный класс для вызова из ActionScript любого домена.

    Листинг 5. Междоменная утилита SWF
    Code:
    package{
    
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.external.ExternalInterface;
        import flash.net.URLLoader;
        import flash.net.URLRequest;
    
        public class JsHelper extends Sprite{
            private const SEND_REQUEST:String = "sendRequest";
    
            public function JsHelper(){
                ExternalInterface.addCallback(SEND_REQUEST, sendRequest);
            }
    
            public function sendRequest(url:String, handlerName:String, 
                    method:String="GET", content:Object=null, 
                    headers:Object=null):void{
                var loader:URLLoader = new URLLoader();
                var request:URLRequest = new URLRequest(url);
                if (method){
                    request.method = method;
                }
                if (headers){
                    for each (var name:String in headers){
                        request.requestHeaders[name] = headers[name];
                    }
                }
                if (content){
                    request.data = content;
                }
                loader.addEventListener(Event.COMPLETE, 
                    function(e:Event):void{
                        ExternalInterface.call(handlerName, loader.data);
                });
                loader.load(request);
            }
        }
    }
    Этот класс представляет свою функцию sendRequest сценарию JavaScript с помощью ExternalInterface. Это делается в конструкторе объекта, так же, как в предыдущем примере из листинга 2. Функция sendRequest немного сложнее: она имеет два обязательных параметра. Первый параметр – это URL, который нужно вызывать. Это полная строка URL, включая любые параметры запроса. Далее идет имя функции JavaScript, которую Flash должен вызывать, получив ответ от сервера. Как и стандартный Ajax, Flash делает асинхронные вызовы к удаленным серверам, так что основной поток пользовательского интерфейса не замораживается в ожидании ответа от удаленного сервера. Поэтому, как и в случае с Ajax, нужно написать функцию callback, которая вызывается после получения ответа от сервера. Она передается в Flash в виде строки, но это должно быть точное имя функции.

    Функция sendRequest также имеет три необязательных параметра. ActionScript допускает дополнительные параметры, но они должны иметь значения по умолчанию. Первый – это используемый метод HTTP, как правило, либо GET, либо POST. В этой статье я сделал методом по умолчанию GET, но его можно легко заменить на POST, если этого требует удаленный сервер. Следующий дополнительный параметр называется content. Это родовой объект данных, который может содержать любые пары имя-значение, которые нужно отправить на удаленный сервер. Его нужно использовать при передаче данных на удаленный сервер. Наконец, последний необязательный параметр – другой родовой объект данных для заголовков. Он служит для установки специальных HTTP-заголовков, передаваемых в рамках вызова на удаленный сервер.

    Код берет все эти параметры и составляет HTTP-запрос с использованием Flash-объекта URLRequest, а затем отправляет запрос с помощью Flash-класса URLLoader. К URLLoader подключен детектор событий, так что можно обработать ответ, как только он возвратится. Здесь создается замыкание, как в JavaScript, чтобы создать анонимную встроенную функцию, которая будет вызываться при инициировании загрузчиком события COMPLETE. Это замыкание использует ExternalInterface для вызова функции, имя которой было передано объекту sendRequest. Оно передает все данные с удаленного сервера в эту функцию. Безусловно, это несколько сложнее, чем использование локального хранения. В листинге 6 приведен пример вызова Twitter Search.

    Листинг 6. Вызов Twitter Search
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Calling Twitter from the client</title>
    <script type="text/javascript" src="swfobject.js"></script>
    <script type="text/javascript">
        function writeFlash(){
            var attrs = {id : "JsHelper"};
            swfobject.embedSWF("JsHelper.swf", "flashContainer", "1", "1", "10.0.0",
                "playerProductInstall.swf", null, null, attrs);
        }
        function search(){
            var keyword = document.getElementById("keyword").value;
            var helper = document.getElementById("JsHelper");
            helper.sendRequest("http://search.twitter.com/search.json?q=" + keyword, 
    "showResults");
        }
        function showResults(responseStr){
            var response = eval("(" + responseStr +")");
            var results = response.results;
            alert("#Results = " + results.length);
        }
    </script>
    </head>
    <body onload="writeFlash()">
        <div id="flashContainer"></div>
        <div id="inputDiv">
            <label for="id">Search Twitter</label>
            <input type="text" id="keyword" name="keyword"/>
            <input type="button" value="Search Twitter" onclick="search()"/>
        </div>
    </body>
    </html>
    Этот код похож на HTML/JS из листинга 3. Опять же, для введения SWF в эту страницу используется библиотека swfobject. Этот код содержит простую форму, которая предлагает пользователю ввести ключевое слово для поиска в Twitter. Функция поиска вызывается при нажатии кнопки "Поиск". Ключевое слово извлекается из поля ввода и используется для создания строки URL, которую нужно вызывать. Она передается в JsHelper SWF, как в листинге 3, извлекая ссылку на SWF с использованием своего идентификатора, а затем непосредственно вызывает функцию, переданную с использованием ExternalInterface. URL и строка с именем функции передаются функции обратного вызова. После извлечения данных из Twitter они передаются функции showResults. Это будет строка JSON, потому что она возвращается из Twitter, так что можно просто использовать функцию JavaScript eval, чтобы превратить ее в объект. В данном случае мы просто отображаем ряд результатов, возвращенных из Twitter. Однако можно легко создать на странице код HTML, который оформит каждый из этих результатов, это уже вопрос стандартного форматирования кода DOM. Так мы совершили междоменный вызов Ajax благодаря Flash. Как и в случае с использованием Flash для локального хранения данных, существуют и другие возможности, о которых нужно знать.


    Альтернативы междоменного вызова

    В течение многих лет Flash позволял делать междоменные вызовы, как и локально хранить данные. Как и в случае локального хранения, некоторые Web-браузеры предлагают собственный способ, и предпринимались попытки стандартизации. Но они не увенчались таким же успехом, как в случае с локальным хранением. Хотя в настоящее время существует стандарт междоменных вызовов Ajax, он не реализован в IE 8. Вместо этого, IE 8 предлагает собственный способ делать междоменные вызовы Ajax. Эта нестандартная реализация – новинка IE 8, и в старых версиях IE ее нет. Опять же, Flash предоставляет модель, которая работает на всех браузерах.

    Наконец, если провести некоторое исследование в области междоменного Ajax, вы обязательно найдете другие способы, не требующие применения Flash или каких-либо новых функций браузеров. Метод, который часто называют JSONP (JSON с Padding) или "тегом динамического сценария", использует тот факт, что браузер не требует соблюдения политики одного источника для файлов JavaScript. Поэтому создается тег сценария, источник которого указывает на URL, к которому нужно обратиться, и вставляется в DOM. Обычно URL содержит параметр callback, имя функции обратного вызова, которую нужно инициировать. Затем сервер обертывает данные именем функции, так что функция вызывается с переданными ей данными из сервера. Этот метод широко используется в Интернете (например, эту технику поддерживает API поиска Twitter, показанный выше), но чреват серьезным риском с точки зрения безопасности – отсюда и стремление к стандартному, безопасному способу, подобному тому, который предлагает Flash.


    Заключение

    В этой статье объясняется, как использовать Flash для расширения возможностей Web-приложений. Теперь вы можете значительно увеличить емкость локальной памяти, доступной для своего приложения. Это позволяет кэшировать большие объемы данных на стороне клиента. Вы научились также делать междоменные Ajax-вызовы из Web-приложений с использованием Flash. Это всего лишь небольшая часть тех возможностей, которые предоставляет Flash. Если вы найдете что-то еще, что помогло вам, вы можете использовать те же методы: Сделать Flash невидимым и вставлять его функции с помощью ExternalInterface.


    Загрузка

    Исходный код примера для статьи JsHelper.zip 12 КБ HTTP
     
  3. scanislav

    scanislav Elder - Старейшина

    Joined:
    25 Jun 2010
    Messages:
    87
    Likes Received:
    22
    Reputations:
    31
    В последних хроме и файрфоксе флеш активируется только по клику, поэтому невидимые объекты уже не будут выполняться. эх... :(
     
  4. De-visible

    De-visible [NDC] Network develope c0ders

    Joined:
    6 Jan 2008
    Messages:
    916
    Likes Received:
    550
    Reputations:
    66
    Можно заставитькликнуть.