Основы Opera Unite для разработчиков — обновлённые

By Vadim Makeev

В соавторстве с Arve, Chris, Zi Bin и Lissy.

Введение

Opera Unite представляет из себя веб-сервер, работающий внутри браузера Opera, который позволяет делать удивительные вещи. Одним нажатием на кнопку вы можете поделиться картинками, документами, видео, музыкой, совместными играми и множеством других вещей с друзьями и коллегами. В рамках Opera Labs несколько месяцев назад мы выпустили раннюю версию сервера Opera Unite, сегодня же речь пойдёт о бета-версии Opera 10.10, представляющей новую улучшенную версию Opera Unite.

Эта статья поможет вам начать путь по дороге разработки приложений Opera Unite — она рассказывает о том, как сервер Opera Unite работает и что он может. Ниже я коротко расскажу вам о базовых идеях Opera Unite, покажу как запустить веб-сервер в вашем браузере и продемонстрирую пример того, как написать приложение для Opera Unite в виде простого блога.

Содержание статьи по порядку:

Основные понятия

Эта часть расскажет об основах работы Opera Unite и о том, как собираются приложения для Opera Unite.

Что такое Opera Unite?

Opera Unite — это веб-сервер, который работает внутри браузера Opera. Он позволяет пользователю устанавливать приложения и использовать их вместе с друзьями, коллегами или даже сразу со всеми, при желании. Всё взаимодействие происходит через центральный сервер Opera Unite, для чего Opera Unite использует прокси между сервером и его клиентами (доступными на unite.opera.com), чтобы избежать дополнительной настройки файрвола.

Прокси Opera Unite

Когда пользователь запускает веб-сервер в домашней сети, в этой сети есть устройство, которое выступает в роли файрвола, нуждающееся в дополнительной настройке. См. рисунок 1:

Традиционная конфигурация веб-сервера

Рисунок 1: традиционная конфигурация веб-сервера

Обычно, пользователю нужно открыть порты и настроить их переадресацию на локальный компьютер для того, чтобы люди за файрволом могли иметь доступ к серверу.

Однако когда вы используете Opera Unite, никакой настройки не требуется, что видно на рисунке 2.

Конфигурация при использовании сервера Opera Unite в браузере

Рисунок 2: конфигурация при использовании сервера Opera Unite в браузере

Веб-сервер инициализирует подключение к прокси и использует это подключение для передачи обратно информации о входящих запросах.

Обратите внимание, что прокси — это всего лишь запасной механизм, который используется, чтобы наверняка передать ваши данные, в случае когда работа с NAT по какой-то причине невозможна. Также, Opera Unite поддерживает работу через UPnP, что позволяет передавать данные через прямое подключение, если эта возможность доступна. Это может значительно ускорить работу ваших приложений за счёт работы без прокси-сервера. Однако использование прямого подключение остаётся на совести каждого отдельного приложения и не всегда гарантирует более быструю работу приложения. UPnP не имеет механизма авторизации и подразумевает, что все локальные системы и их пользователи являются доверенными.

Приложения Opera Unite

Приложение Opera Unite состоит из файла config.xml, содержащего базовую информацию о приложении, и вполне обычной для сайта структуры файлов. В этом смысле, они очень похожи на виджеты для Opera, хотя то, каким образом приложения Opera Unite запускаются и используется, сильно отличается от виджетов. Другое отличие состоит в том, что, в отличие от виджетов Opera, файл config.xml для приложений Opera Unite должен содержать элемент feature:

<feature name="http://xmlns.opera.com/webserver">
  <param name="type" value="service"/>
  <param name="servicepath" value="blog"/>
</feature>

В этом случае, для приложения становится доступен специальный JavaScript-объект opera.io.webserver. Более подробно об этом можно прочитать в документации по JavaScript API для сервера Opera Unite.

Поскольку приложения Opera Unite используют те же технологии, что и виджеты Opera, то, запустив сервер Opera Unite, вы сможет легко контролировать и настраивать его при помощи HTML, CSS и JavaScript. Хотя, приложения Opera Unite получают доступ к функциям, обычно недоступным для виджетов или веб-страниц, например — изолированная файловая система (песочница).

Если вы хотите узнать больше о виджетах Opera, вы можете найти всю информацию в статьях о виджетах на сайте Dev.Opera.

Двигаемся дальше — запускаем Opera Unite и начинаем собирать простое приложение.

Запуск веб-сервера

Для большей безопасности и производительности веб-сервер не запускается по умолчанию про запуске Opera. Для запуска сервера нужно выбрать в меню Инструменты > Сервер Opera Unite > Включить Opera Unite, либо запустить одно из приложений Opera Unite. Сразу после этого появится диалог, который предложит вам ввести логин и пароль — те же, что используются на My Opera.

Обратите внимание, что для использования в Opera Unite подходят только те логины My Opera, что не содержат недопустимых для URL символов: «/», «.», «_» и пробелов.

На следующем шаге вам нужно назвать устройство. Вы можете выбрать имя из выпадающего списка или указать любое другое. Имя устройства будет идентифицировать ваш сервер для прокси. Сервер будет доступен по адресам вроде этих:

http://devicename.username.proxyaddress/applicationname

Таким образом, для того, чтобы увидеть приложение test на сервере your_device на operaunite.com вам нужно открыть этот URL:

http://your_device.your_username.operaunite.com/test

Создание приложения Opera Unite: простой блог

А теперь короткий рассказ об изготовлении простого приложения для ведения блога, который позволит пользователю публиковать записи. Сохранённые записи немедленно становятся доступны всему миру при помощи сервера.

Приложение состоит из двух частей: первая — это те страницы, которые позволяют владельцу приложения управлять и настраивать его, вторая — это страницы, видимые всем пользователям, которые и отдаёт сервер.

Те, кому не терпится попробовать, могут загрузить код блога для Opera Unite. Он упакован в файл с расширением .ua — такое расширение по умолчанию имеют все приложения Opera Unite. Вы можете разархивировать пакет, чтобы взглянуть на исходный код или просто перетянуть пакет в браузер Opera, чтобы запустить пример блога для Opera Unite.

Файлы и папки приложения

Наше приложение будет содержать файлы и папки, изображённые на рисунке 3:

Структура папки приложения

Рисунок 3: структура папки приложения

  • config.xml: файл настроек приложения.
  • index.html: логическое начало приложения, куда подключаются скрипты.
  • script/script.js: непосредственный код приложения.

Из указанных файлов строго необходимы только config.xml и index.html.

Также вы можете включить в состав пакета папку public_html — волшебную папку для приложений Opera Unite. Обычно файлы и папки внутри вашего приложения недоступны пользователям, запрашивающим приложение, поэтому, если вы захотите отдать пользователю какой нибудь файл стилей, статические картинки или что-нибудь вроде этого, то положите файлы именно в эту папку. Эти файлы будут привязаны к относительному корню вашего приложения и, к примеру, файл cats.png внутри папки public_html приложения helloOperaUnite будет доступен по адресу:

http://your_device.your_username.operaunite.com/helloOperaUnite/cats.png

Настройки приложения: config.xml

Это приложение будет собрано точно так же, как виджет Opera, поэтому нам будет нужно задать настройки в файле config.xml. Этот файл по сути является обычным файлом настройки для виджетов Opera, за исключением некоторых дополнительных особенностей. Для того, чтобы обозначить ваше приложение как приложение Opera Unite, вам потребуется включить элемент feature в элемент widget файла config.xml.

Обратите внимание, что виджеты Opera упакованы в обычные zip-файлы и переименованы с расширением .wgt, тогда как приложения Opera Unite упакованы и переименованы в файлы с расширением .ua для указания на приложения Opera Unite, т.е. «Unite Application».

<widget>
  <widgetname>My blogging application</widgetname>
  <description>Blogging application example from the Opera Unite applications primer.</description>
  <author>
    <name>Hans S. Toemmerholt</name>
    <organisation>Opera Software ASA</organisation>
  </author>
  <feature name="http://xmlns.opera.com/webserver">
    <param name="type" value="service"/>
    <param name="servicepath" value="blog"/>
  </feature>
</widget>

Элемент widgetname также является названием вашего приложения. Это название будет показано пользователю во время установки и использования приложения.

Вы также можете добавить в config.xml элемент servicepath. Содержимое этого элемента должно быть валидным URI и будет являться именем приложения, что присутствует в URI. Если этот элемент отсутствует, Opera попытается использовать в качестве URI приложения содержимое элемента widgetname. Но если это имя не окажется валидным URI, установка прервётся с ошибкой.

После того, как приложение упаковано и запущено, упомянутый выше config.xml сделает его доступным по адресу:

http://your_device.your_username.operaunite.com/blog/

Соединяем всё вместе: index.html

У нашего приложения нет интерфейса, кроме тех страниц, что он создаёт. Файл index.html — это начальная точка приложения и, по сути, весь его интерфейс. В нашем пример мы используем минимальный файл HTML 5 со ссылкой на используемый файл скриптов:

<!DOCTYPE html>
<script src="script/script.js"></script>

Пишем скрипт: script.js

Обратите внимание на то, как мы подключили файл script.js в предыдущем примере. Веб-сервер слушает запросы от пользователей, которые в данный момент ходят по страницам приложения, и создаёт ответы, которые отправляются обратно. Ответом обычно является сгенерированная страница, содержащая информацию.

Функциональность Opera Unite доступна разработчикам через набор JavaScript API, делающий доступными объекты, представляющие веб-сервер, соединения, входящие запросы и исходящие ответы.

Шаг за шагом рассмотрим скрипт:

Обработчики запросов

Веб-сервер принимает запросы от клиентов и посылает им ответы обратно. Сервер Opera Unite основан на событийной модели и вызывает событие в DOM каждый раз, когда браузер обращается к серверу, запрашивая файлы имеющие отношение к приложению Opera Unite. Чтобы иметь возможность обрабатывать эти события, нужно повесить на них обработчики. Это делается при помощи window.onload:

var webserver;
var entries = [];
window.onload = function () {
  webserver = opera.io.webserver
  if (webserver)
  {
    // Handle requests for various URLs
    webserver.addEventListener('_index', showEntryList, false);
    webserver.addEventListener('entry', showEntry, false);
    webserver.addEventListener('form', showForm, false);
    webserver.addEventListener('save', saveEntry, false);
  }
}

Что же здесь происходит?

Первым делом мы проверяем, что наше приложения действительно является веб-приложением, проверяя существование объекта webserver. Если он существует, то мы добавляем четыре обработчика событий: _index, entry, form и save.

Когда обработчики установлены, сервер будет вызывать одну из указанных функций каждый раз, когда пользователь посетит один из следующих URL’ов:

http://your_device.your_username.operaunite.com/blog/
http://your_device.your_username.operaunite.com/blog/entry/
http://your_device.your_username.operaunite.com/blog/form/

Запрос _index особенный потому, что является запросом к корню приложения. Как мы увидим дальше, пользователь не сможет получить доступ к «save» напрямую, а только через форму.

Показываем список записей

Код функции showEntryList для запроса _index довольно простой. После получения запроса, функция в ответ создаёт HTML-документ со списком сохранённых записей.

function showEntryList(e)
{
  var response = e.connection.response;
  response.write( '<!DOCTYPE html>'
    + '<html><head><title>Entries</title></head>'
    + '<body><ul>'
  );

  for ( var i = 0, entry; entry = entries[i]; i++ )
  {
    response.write('<li>'+entry.date+': <a href="entry?id='+i+'">'+entry.title+'</a></li>');
  }

  response.write('</ul>'
    + '<p><a href="form">Add en entry</a></p>'
    + '</body></html>'
  );
  response.close();
}

Шаг за шагом, функция делает следующее:

Первым делом создаётся переменная, содержащая объект response. Этот объект содержит все необходимые методы для отправки данных клиенту:

var response = e.connection.response;

Дальше идёт метод write, который записывает данные в документ для браузера, который запросил страницу. Для начала создадим простую HTML-обёртку:

response.write('<!DOCTYPE html>'
  + '<html><head><title>Entries</title></head>'
  + '<body><ul>'
);

Существующие записи мы оформим списком ссылок:

for ( var i = 0, entry; entry = entries[i]; i++ )
{
  response.write('<li>'+entry.date+': <a href="entry?id='+i+'">'+entry.title+'</a></li>');
}

И, наконец, закрываем подключение:

response.close();

Показываем запись

Дальше нам нужно вывести что-нибудь, когда пользователь кликнул по ссылке на запись:

function showEntry(e)
{
  var index = e.connection.request.queryItems['id'][0];
  var entry = entries[index];
  // ToDo Should have error handling here
  var response = e.connection.response;
  response.write('<!DOCTYPE html>'
    + '<html><head><title>'+entry.title+'</title></head>'
    + '<body><h1>'+entry.title+'</h1>'
    + '<p>'+entry.date+'</p>'
    + '<div>'+entry.text+'</div>'
    + '</body></html>'
  );
  response.close();
}

Шаг за шагом, функция делает следующее:

Первым делом мы создаём переменную, содержащую объект request, который содержит информацию о входящем запросе:

var request = e.connection.request;

Аргументы CGI GET содержатся в свойстве queryItems запроса. Мы получаем id записи, которую хотим вывести. Обратите внимание, что один и тот же CGI-аргумент может иметь несколько значений:

var index = request.queryItems['id'][0];

Дальше мы получаем соответствующую запись в блоге:

var entry = entries[index];

Метод write записывает данные в документ, запрошенный браузером. Заголовок, дата и текст записи заворачиваются в подходящую разметку:

response.write('<!DOCTYPE html>'
  + '<html><head><title>'+entry.title+'</title></head>'
  + '<body><h1>'+entry.title+'</h1>'
  + '<p>'+entry.date+'</p>'
  + '<div>'+entry.text+'</div>'
  + '</body></html>'
);

Показываем форму для добавления записи

После нажатия на ссылку «Добавить запись» вы увидите знакомую форму:

function showForm(e)
{
  var response = e.connection.response;
  response.write('<!DOCTYPE html>'
    + '<html><head><title>Add entry</title></head>'
    + '<body><h1>Add entry</h1>'
    + '<form method="post" action="save">'
    + '<p><label for="namefield">Title</label> <input id="nameField" type="text" name="title"></p>'
    + '<p><label for="textArea">Text</label> <textarea id="textArea" name="text"></textarea></p>'
    + '<p><input type="submit" name="Add entry"></p>'
    + '</form>'
    + '</body></html>'
  );
  response.close();
}

Эта форма может быть гораздо сложнее, например: поддерживать обработку ошибок, вывод уже введённых данных и так далее. Также стоит придумать механизм авторизации для потенциально деструктивных операций с данными, но не будем увлекаться — всё-таки у нас простой пример.

Сохранение записи

Наконец, после отправки формы, новая запись должна быть сохранена. В данном примере записи хранятся в простом массиве, который будет утерян после перезапуска приложения, однако расширить пример и добавить механизм сохранения записей будет довольно просто:

function saveEntry(e)
{
  var request = e.connection.request
  var response = e.connection.response;
  // Get POST data
  var title = request.bodyItems['title'][0];
  var text = request.bodyItems['text'][0];
  entries.push({
    'title' : title,
    'text' : text,
    'date' : new Date()
  });
  // Redirect back to the index of the application
  response.setStatusCode(302);
  response.setResponseHeader( 'Location', webserver.currentServicePath );
  response.close();
}

Вместо request.queryItems мы используем свойство bodyItems, чтобы получить доступ к данным, отправленным при помощи POST — в нашем случае это заголовок и содержимое новой записи.

var title = request.bodyItems['title'][0];
var text = request.bodyItems['text'][0];

Отправка формы сохраняет запись в массив:

entries.push({
  'title' : title,
  'text' : text,
  'date' : new Date()
});

И, наконец, когда новая запись сохранена, мы возвращаемся обратно к списку записей:

response.setStatusCode(302);
response.setResponseHeader( 'Location', webserver.currentServicePath );
response.close();

Таким образом мы создаём стандартный HTTP-редирект обратно к корню нашего приложения, который хранится в свойстве webserver.currentServicePath. Этот редирект вызовет запрос _index и мы снова получим список всех записей.

Как уже упоминалось, для полноценного использования этого примера, к нему стоит добавить обработку ошибок и статусные сообщения.

Использование приложения Opera Unite

Для того, чтобы запустить приложени Opera Unite, вам сначала нужно его установить. Перетяните config.xml или полную zip-версию вашего приложения в окно браузера или откройте через файловый диалог. Если вы до сих пор не запускали приложения Opera Unite, то перед вам появится окно настройки Opera Unite, которое уже упоминалось в начале статьи.

Если вы кликнете дважды по приложению My blogging service в панели приложений Opera Unite, вы должны увидеть страницу как на рисунке 4:

Главная страница приложения-блога

Рисунок 4: главная страница приложения-блога

Клик по ссылке Добавить запись покажет форму, которая позволит вам добавить новую запись в блог, как на рисунке 5:

Форма для публикации записи

Рисунок 5: форма для публикации записи

Если ввести в эту форму какой-то текст и нажать кнопку отправки, вы вернётесь на главную страницу блога, где уже будет видна ваша новая запись. Кликните по её заголовку, чтобы посмотреть запись. Добавьте несколько других записей, поиграйте со страницами и вы увидите что-нибудь вроде рисунка 6:

Несколько записей в блоге Полный вид одной записи в блоге

Рисунок 6: наш блог успешно заселён

Просмотр приложения Opera Unite

Если вы следовали всем описанным шагам и запустили приложение в браузере Opera, то теперь у вас есть полноценное веб-приложение. И любой желающий может увидеть его по ссылке:

http://devicename.username.proxyaddress/applicationname

В нашем случае, если устройство называется your_device и на нём запущен приложение-блог, то его URL будет выглядеть так:

http://your_device.username.operaunite.com/blog

Как вы могли заметить, запуская пример, вы также можете зайти в корень устройства и увидеть все установленные на нём приложения, например:

http://your_device.username.operaunite.com/

Эта страница будет содержать информацию о всех установленных на данном устройстве приложениях, а также, если эти данные будут найдены в config.xml, более подробную информацию о приложении и его авторе.

Загрузка приложения Opera Unite на unite.opera.com

Итак, вы собрали классное приложение Opera Unite и хотите, чтобы им могли пользоваться не только посетители вашего сервера Opera Unite — вы также хотите сделать его доступным для загрузки и установки на другие сервера Opera Unite, ведь так? Хорошо. И что же для этого нужно сделать? Ответ прост: приложение нужно загрузить на unite.opera.com — этот сайт предназначен для распространения приложений. Данная часть статьи расскажет вам о том, как это сделать.

Перед публикацией

В идеале, перед публикацией вам стоит протестировать приложение на наличие ошибок. Если это возможно, то протестируйте его на разных платформах, устройствах версиях браузера Opera. Также не забывайте, что пользователи ваших приложений могут использовать любой браузер, а не только Opera, поэтому протестируйте приложение в различных браузерах (Firefox, Safari, и т.п.).

Если вы столкнулись с проблемами в работе вашего приложения, но уверены, что с его кодом всё в порядке, то проверьте файл config.xml на наличие ошибок. Он необходим для правильной работы приложения. Если вы откроете его в других браузерах, то сможете проверить его на корректность синтаксиса. Также стоит проверить, содержит ли config.xml достаточное количество информации, ведь он будет использоваться для получения всей информации о приложении для репозитария unite.opera.com, а также для пользователей на страницах уже установленных приложений.

Также стоит подумать о переводе приложения на другие языки.

И, наконец, сделайте скриншот работающего приложения, как описано ниже.

Публикация приложения

Для публикации вашего приложения вам нужно посетить страницу загрузки. Выберите приложение в файловом диалоге и загрузите его. Внимательно прочтите и, при необходимости, уточните информацию из config.xml. При желании, вы можете добавить более подробное описание.

Дальше выберите скриншот приложения в файловом диалоге, чтобы другие пользователи смогли понять что из себя представляет ваше приложение, прежде чем они попробуют его установить.

Помимо этого, вам нужно будет выбрать устройства для использования на которых ваше приложение было создано. Убедитесь, что оно был протестировано на указанных устройствах и выберите подходящую группу. Последним шагом будет выбор языков, поддерживаемых вашим приложением. Убедитесь, что вы предусмотрели перевод для всех выбранных языков.

Как я могу предложить воспользоваться моим приложением?

После того, как вы потратили кучу времени на изготовление приложения, вполне естественно, что вам захочется показать его другим людям. Чтобы увеличить число просмотров, вам нужно рассказать потенциальным пользователям каких возможностей стоит ожидать от вашего приложения. У каждого приложения есть короткое описание, которое автоматические копируется из файла config.xml и длинное описание, где вы можете более подробно рассказать о приложении и особенностях его работы.

Используйте короткое описание, чтобы привлечь внимание пользователя, расскажите ему что ваше приложение может и какую пользу можно из него извлечь. Это может быть даже короткий подзаголовок, но он должен быть информативным. Вам стоит избегать фраз вроде «Скачай меня» или «Это супер-крутое приложение». Используйте длинное описание для того, чтобы объяснить пользователям какие возможности предоставляет ваше приложение, как они реализованы. Также полезно будет рассказать про изменения в различных версиях приложения, правила игры и так далее.

И, наконец, не забудьте сделать скриншот приложения в работе. В качестве примера, вы можете вдохновиться приложениями команды Opera Unite.

Обратите внимание, что идеальные размеры для скриншота составляют 445 × 230 пикселов — именно эти размеры используются на сайте Opera Unite. Если ваши скриншоты будут разных размеров, то они будут приведены к единым размерам, что может привести к нежелательным результатам.

Одобрение приложений Opera Unite

Все приложения Opera Unite должны быть одобрены специальными сотрудниками Opera Software. Мы проверим их на ошибки, чтобы убедиться в том, что все пользователи смогут их запустить, однако мы не несём ответственности за содержимое этих приложений и не даём гарантий касательно их функциональности. Подробнее об этом в читайте в правилах.

Каким правилам нужно соответствовать для одобрения приложения?

Некоторые требования, которые мы предъявляем к приложениям:

  • Приложение должно иметь внятное название и описание.
  • Приложение не должно иметь очевидных ошибок, поэтому протестируйте его перед загрузкой.
  • Приложение не должно содержать намеренно опасного кода.
  • Приложение не должно содержать информации, на которую вы не имеете авторского права.
  • Приложение не должно содержать или ссылаться на информацию «для взрослых» или провокационную информацию.
  • Приложение должно отдавать HTML-страницы совместимые со стандартами, которые доступны для всех современных браузеров и устройств.

Дальнейшее чтение

Теперь вы разбираетесь в основах создания и загрузки приложений Opera Unite, и вам, возможно, будет интересно узнать больше:

Author of pepelsbey.net blog, advocating web standards, semantic coding and microformats. Permanent member of Russian IT conference movement as organizer and speaker. Web Evangelist, founder of "Web Standards" Russian development community.


This article is licensed under a Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.

Comments

The forum archive of this article is still available on My Opera.

No new comments accepted.