» Mozilla Hacks ブログ翻訳

HiDPI サポート、HTML5 notifications、Parallel JS、asm.js など – Firefox Development Highlights

原文: HiDPI support, HTML5 notifications, Parallel JS, asm.js and more – Firefox Development Highlights on April 25, 2013 by Robert Nyman [Editor], Jean-Yves Perrier and Paul Rouget

Firefox の最新の開発状況をご覧いただく機会がやってきました。本記事は Bleeding Edge および Firefox Development Highlights シリーズの一環であり、ほとんどのサンプルは Firefox Nightly のみで動作します (また、変更される場合もあります)。

HiDPI サポート

複数の画像を持つ ico/icns をサポートしたことをうれしく思います: もっとも高い解像度のアイコンは、HiDPI/Retina ディスプレイで使用されるようになりました。

Favicon の実装については bug 828508 で、ico/icns については bug 419588 でそれぞれ言及しています。

パフォーマンスの向上/Snappy:

多くのパフォーマンス向上策が実施されており、スタートアップの高速化、タッチパッドにおけるスクロールの改善、スムーズなアニメーションなどがあります。

しかしもっとも重要な改善はおそらく、マルチスレッド化された画像デコーダーでしょう。その成果として、ページの読み込みやタブの切り替えが高速になるでしょう。核心的な詳細のすべてについて、bug 716140 で言及しています。

HTML5

HTML5 や HTML5 関連技術の仲間に入ったため、良好な追加サポートを行ったものがあります:

<input type=”range”>

フォームで <input type=”range”> 要素をサポートしました。これにスタイルを設定するには、::-moz-range-progress を使用できます:

::-moz-range-progress {
    background: #f00;
}

<input type="range">

jsFiddle で <input type=”range”> の実動デモをご覧いただけます。

HTML5 notifications

HTML5 notifications を実装しました。要するに、許可を要求した上で通知を作成できます:

function authorizeNotification() {
    Notification.requestPermission(function(perm) {
        alert(perm);
    });
}

function showNotification() {
    var notification = new Notification("This is a title", {
        dir: "auto",
        lang: "",
        body: "This is a notification body",
        tag: "sometag",
    });
}

jsFiddle で、HTML5 notification の実動デモをご覧いただけます。

WebAudio API をデフォルトでアクティブ化

Firefox Nightly で、WebAudio API をデフォルトでアクティブにしました。リリース可能になるまでの作業はまだありますが、テスターは歓迎します。

JavaScript

Parallel JS

Parallel JS の最初のバージョンを Firefox に追加しました。Parallel JS Lands の記事で、より多くの詳細をご覧いただけます。

asm.js

Firefox 22 でリリースする予定で、asm.js を Firefox に内蔵したことをうれしく思います! Luke Wagner 氏が、asm.js in Firefox Nightly の記事で詳細を著しています。

ES6 Arrow function 構文

ES6 の Arrow function 構文をサポートしました。

let square = x => x*x;
console.log(square(3));

CSS

@supports をデフォルトでアクティブ化

これは Firefox 22 でリリースする予定です。詳しくは MDN の @supports をご覧ください。

min-width および min-height の ‘auto’ キーワード

min-width および min-height の ‘auto’ キーワードは今後サポートしません。これは CSS3 Flexbox から削除されました。詳しくは bug 848539 をご覧ください。

CSS Flexbox を再び有効化しました

Firefox 22 で CSS Flexbox を再びデフォルトで有効にしたことをお伝えできて幸いです。Firefox 22 は現在 Firefox Aurora になっています!

Font Inspector、<time> および <data> 要素 – Firefox Development Highlights

原文: Font Inspector and <time> and <data> elements – Firefox Development Highlights on March 13, 2013 by Robert Nyman [Editor] and Paul Rouget

Firefox の最新の開発状況をご覧いただく機会がやってきました。本記事は Bleeding Edge および Firefox Development Highlights シリーズの一環であり、ほとんどのサンプルは Firefox Nightly のみで動作します (また、変更される場合もあります)。

Font Inspector

Firefox の開発ツールで Font Inspector が利用可能になりました。

Firefox の調査ツールで、“Fonts” パネルを利用できます。これは、ページ内で使用される @font-faces に関するさまざまな情報を明らかにします:

  • フォント名およびフォントファミリ
  • フォントの場所 (system あるいは remote および URL)
  • プレビュー (変えることができます)
  • @font-face のコード

HTML5 および要素のサポート

私たちは、新たに 2 つの要素をサポートしました:

<time> 要素

HTML の time 要素は、24 時間制の時刻またはグレゴリオ暦の正確な日付 (時刻とタイムゾーン情報を付加することもできます) を表します。この要素は、コンピュータが読み取れる形式で日付や時刻を提供するために使用することが想定されています。ユーザエージェントが、ユーザのカレンダーへイベントスケジュールを登録することに役立つでしょう。

例:

<p>The concert took place on <time datetime="2001-05-15 19:00">May 15</time>.</p>

詳しい情報は、<time> 要素に関する MDN のドキュメントW3C の仕様書でご覧いただけます。

<data> 要素

data 要素はそのコンテンツと、コンピュータが読み取れる形式で表したコンテンツを収めた value 属性とを併せて表現します。value 属性は必須であり、またその値は要素のコンテンツをコンピュータが読み取れる形式で表したものでなければなりません。

<data> 要素には新たに value 属性が追加されており、それにはデータを文字列で表したものを収めます。スクリプトでは、反映された値を取得するために .value プロパティを使用できます:

例:

<data id="user" value="humphd">David Humphrey</data>
document.getElementById("user").value; // "humphd"

これは WHATWG の仕様書に記載されており、また David Humphrey 氏が HTML5 time and data elements in Firefox の記事に詳しく記述しています。

Open Web Apps を始めよう – なぜ、そしてどのように

原文: Getting started with Open Web Apps – why and how on February 5, 2013 by Robert Nyman [Editor]

私たちは最近 Open Web AppsFirefox OS などについて数多く話してきましたが、これに加えて、始める方法やさらに重要になるかもしれない理由についても扱いたいと思います。

なぜ Web App か?

モバイル開発の情勢を見るとたいてい、開発者は自身のプラットフォームとスキルを選ばなければならないという選択肢に行き着きます。それはきっと、iOS と Objective-C または Android と Java になるでしょう。

ここでの大きな課題はもちろん、コンテンツを複数のプラットフォームで提供したい場合に、いくつか選択肢があることです:

  • ひとつのプラットフォームを選択して、他は考慮しない
  • プログラミング言語をいくつか学習する
  • プラットフォームごとに分かれた開発チームを作る

大手の組織では複数のチームを持つことが可能ですが、他の多くの組織ではそれに苦労しています。また当然ながら、多くのモバイルアプリはメンテナンスやサポートや開発が必要なものとして、企業やサービスの Web サイトに加えて積み上げられます。

従ってコスト削減や単一の開発言語による容易さなどの理由で多くの開発者は PhoneGapTitanium などに飛びつき、それゆえに HTML5 および JavaScript で開発を行い、さまざまなモバイルオペレーティングシステム向けにパッケージ化しています。

これは優れた、また興味深い手法ですが、おそらくほとんどのケースにおいて最適な状況とはかけ離れているでしょう。Mozilla の私たちは、あなたが苦労することなく Web 開発者として既知のスキルを使用できるようにしたいと考えており、またあなたにさらなる可能性や力を与えて発展させるプラットフォームを求めています。

これは価値ある強力なプラットフォームとしての Web レイヤーを作るために、多くの WebAPIWeb Activities などを開発者であるあなたが利用できるようにすることで実現します。

Open Web Apps のアイデアは新しいプラットフォームを選択させたり、他のプラットフォームを排斥するものではありません。そうではなく、既存のコードを再利用や、必要に応じてアプリとしてインストール可能にするために小さな変更を加えることに関するものです。

アプリを構築するべきか?

多くの他のプラットフォームではあなたをプラットフォームに結び付けることや自身のアプリストアの提供などに強い関心を持っていますが、私はあなたが自身に問いかけるべき最初の質問を投げかけたいと思います:

私はこれをアプリにする必要が本当にあるのか?

明らかにそのとおりである場合もあるでしょう! しかし他のケースではあなたがプロフェッショナルになって、アプリ化が付加価値を与えることはなさそうだという判断が必要になります。アプリで行う必要がないいくつかのケースについては No, I’m not going to download your bullshit appPackaged HTML5 Apps: Are we emulating failure? の記事で述べられています。

そのためだけにアプリを作るように、あるいは他の人がするからあなたもするだろうというように、あなたをだましたいのではありません。むしろあなたは公平に判断すると考えていますし、あなたのアプリのアイデアがエンドユーザやユーザ体験全体に付加価値を与えるのでしたら、アプリで行うことを考えるべきです。

では、どのようなケースがあり得るのでしょうか? 例えば以下のようなものでしょう:

  • Web ページで提供するものよりすばらしい体験を提供したいとき、例えばプラットフォームやデバイスに固有の WebAPI にアクセスするなど
  • localStorage や IndexedDB に大量の情報を保管したいとき
  • ユーザが実際にインストールするアプリを求めているとき
  • ユーザが簡単にアクセスできるよう、ホームスクリーンやデスクトップにきれいなアイコンを置きたがっているとき

Open Web Apps のタイプ

インストール可能な Open Web Apps には、基本的に2 つのタイプがあります:

  • ホスト型アプリ
  • パッケージ型アプリ

ホスト型アプリ

ホスト型アプリは、URL から実行されるがアプリの状態であるアプリです。これはアプリを実行するためにオンラインであることが必要で、またすべてのリソース (例えばファイルや画像など) はサーバ側にあり、あなたが運営しているでしょう。

接続性が必要であることを回避する選択肢のひとつは、アプリをオフラインでも動作可能にすることです。これはオフラインで動作可能にするためアセットを一覧化した appcache ファイルを追加して、これをメインページから参照することで実現します:

HTML ファイル

<html manifest="manifest.appcache">

Appcache ファイル

CACHE MANIFEST
# Version 1.0

index.html
css/base.css
js/base.js
js/webapp.js
js/offline.js

NETWORK:
*

FALLBACK:
/ fallback.html

オフラインサポートやその注意点について詳しく学ぶために、以下のリソースをご覧いただくことを強く推奨します:

長所

  • アップデートのプロセスを完全に制御可能
  • 既存のコードを単に実行または再利用する

短所

  • 接続性が必要 (オフラインサポートを実装していない場合)
  • アクセスできる API はパッケージ型アプリほど多くない

パッケージ型アプリ

パッケージ型アプリは、すべてのアセットを ZIP ファイルに詰め込むものであり、ZIP ファイルをインストールするパッケージ一式として提供ます。これはファイルをいつでも使用可能にするとともに、インストール前にすべてのコードをセキュリティ的にクリアにできることから、ファイルへ高い権限を与えます (すなわちより多くの API にアクセスできます)。

長所

  • デフォルトでオフライン実行可能
  • より多くの API にアクセス可能

短所

  • 管理が難しくなる
  • 新バージョン公開のためのアップデートプロセス

結局のところ、あなたはホスト型アプリとパッケージ型アプリのどちらを望むかでよい判断をするために、ニーズ、ワークフロー、動作に必要な API などを評価しなければなりません。

Open Web Apps を始めよう

ここまでお話してきましたが、Open Web App を構築するため実際には何が必要なのでしょうか? 結論から言うと、多くはありません。私たちはそれを MDN の Getting started with making apps に文書化していますが、ここでも簡単にお伝えしましょう。

基本的にあなたが行わなければならないことは、あなたの既存の Web サイトやサービスを用意して、マニフェストファイルを追加することです。これだけです! これは本当です。なお、インストールすることは当然必要です。

マニフェストファイル

マニフェストファイルではアプリの名前、アイコン、開発者などだけでなく、ローカライズのサポート、起動元のパス、特定の API への許可要求などの情報を記述します。マニフェストの全フィールドを MDN の App manifest に掲載しています。

シンプルなマニフェストは以下のようになります:

{
    "version": "1",
    "name": "Firefox OS Boilerplate App",
    "launch_path": "/Firefox-OS-Boilerplate-App/index.html",
    "description": "Boilerplate Firefox OS app with example use cases to get started",
    "icons": {
        "16": "/Firefox-OS-Boilerplate-App/images/logo16.png",
        "32": "/Firefox-OS-Boilerplate-App/images/logo32.png",
        "48": "/Firefox-OS-Boilerplate-App/images/logo48.png",
        "64": "/Firefox-OS-Boilerplate-App/images/logo64.png",
        "128": "/Firefox-OS-Boilerplate-App/images/logo128.png"
    },
    "developer": {
        "name": "Robert Nyman",
        "url": "http://robertnyman.com"
    },
    "installs_allowed_from": ["*"],
    "default_locale": "en"
}

(訳注: url の値は、URL をダブルクォーテーションで括った文字列です。<a> タグはブログシステムの機能により自動的に追加されたものです。)

このファイルを拡張子 .webapp (例えば manifest.webapp) で保存します。注意すべき重要事項として、このファイルは Content-type: application/x-web-app-manifest+json で提供されることが必要です。

これはサーバの設定が必要になります。例えば Apache では .htaccess ファイルを使用します:

AddType application/x-web-app-manifest+json .webapp

マニフェストが完成したら、アプリが正しい形式であるかを検証するようにしましょう。

アプリのインストール

マニフェストが正常で正しい Content-type で提供されるようになったら、インストールの手段を与えましょう。あなたの Web ページに、以下のコードを呼び出すインストールボタンを追加しましょう:

var installApp = navigator.mozApps.install(manifestURL);

// インストール成功
installApp.onsuccess = function(data) {
    console.log("Success, app installed!");
};

// インストール失敗
installApp.onerror = function() {
    console.log("Install failed\n\n:" + installApp.error.name);

マニフェストの URL は絶対パスにしてください。簡単な方法はインストールボタンを置いたカレントページから URL を取り出すことで、マニフェストファイルは同じ場所に置きます:

var manifestURL = location.href.substring(0, location.href.lastIndexOf("/")) + "/manifest.webapp";

install メソッドは任意で第 2 引数である receipts を指定でき、これは JSON オブジェクトです。詳しくは、install メソッドのドキュメントに記載しています。

パッケージ型アプリのインストール

前出のマニフェストファイルと install の呼び出しによる方法は、ホスト型アプリで動作します。パッケージ型アプリでは、いくつか追加の作業が必要になります:

アプリの全コンテンツを ZIP 圧縮する

通常のマニフェストファイルを含む全ファイル (ファイルを収めているフォルダは除く) を ZIP で圧縮してください。マニフェストファイルのファイル名は manifest.webapp にしなければなりません。

ミニマニフェストの作成

もうひとつのマニフェストファイルを、例えば package.webapp という名前で作成して、package_path が ZIP ファイルを置いている場所を絶対パスで示すようにしてください。

また、開発者名や情報がミニマニフェストと ZIP ファイル内にある通常のマニフェストとで一致しなければなりません。

{
    "name": "Firefox OS Boilerplate App",
    "package_path" : "http://localhost/Firefox-OS-Boilerplate-App/Firefox-OS-Boilerplate-App.zip",
    "version": "1",
    "developer": {
        "name": "Robert Nyman",
        "url": "http://robertnyman.com"
    }
}

(訳注: package_path および url の値は、URL をダブルクォーテーションで括った文字列です。<a> タグはブログシステムの機能により自動的に追加されたものです。)

パッケージのインストール

通常の install メソッドを使用する代わりに、installPackage を呼び出します。こちらはミニマニフェストを指し示して、ミニマニフェストが ZIP ファイルおよびパッケージを指し示します。

var manifestURL = location.href.substring(0, location.href.lastIndexOf("/")) + "/package.webapp";
var installApp = navigator.mozApps.installPackage(manifestURL);

Developer Mode の有効化

これを Firefox OS Simulator で実行するには、 Developer Mode の有効化が必要です:

Settings > Device Information > More Information > Developer > Developer mode

注意: 未完成であるため、このオプションが変更される場合や、Simulator のバージョンや実際の Firefox OS デバイスによっては利用できない場合があります。

Firefox OS Simulator の全リリース版およびプレリリース版は Mozilla の FTP サーバから入手できます

許可設定

パッケージ型アプリのみがアクセスできる API を利用しようとしている場合は、通常のマニフェストファイル (manifest.webapp) に 2 つの項目を追加しなければなりません:

  • type プロパティの追加 (例えば “type” : “privileged”)
  • 許可設定の指定
"permissions": {
    "contacts": {
        "description": "Required for autocompletion in the share screen",
        "access": "readcreate"
    },
    "alarms": {
        "description": "Required to schedule notifications"
    }
}

また興味深いオプションとして、packaged-app-server と呼ばれるものがあります。これは、実行時に要求されたときにパッケージとしてファイルを ZIP 圧縮します。

$ cd ~/myapp
$ python ~/serve_packaged_apps.py

サンプルアプリ

サンプルアプリとして (分析しやすさを調べたい、手直ししたい、あるいはここから始めたいのなら)、Firefox OS Boilerplate App を自由にお試しください。これは以下の機能をサポートしています:

  • ホスト型アプリとしてインストールする機能を提供するインストールボタン
  • Web Activities ― 多くのサンプルや利用例
  • 動作する WebAPI
  • オフラインサポート (デフォルトでは無効)
  • パッケージ型アプリ ― ZIP ファイルのアプリをインストール

サポートしているプラットフォームは?

Open Web Apps の現状を見ていきましょう。Open Web Apps は以下の環境でサポートされています:

Firefox OS

Firefox OS (Simulator またはデバイス) に Open Web App をインストールでき、ほとんどの WebAPI や Web Activities が動作します。

Android 版 Firefox

Android 版 Firefox にアプリをインストールでき、ホームスクリーン上に適切なアイコンでインストールされます。ただし、WebAPI や Web Activities はサポートしません。

デスクトップ版の Nightly/Aurora バージョン

Firefox Nightly/Firefox Aurora にスタンドアロンのアプリをインストールして実行できますが、多くの WebAPI にアクセスできず、また Web Activities は利用できません。

現時点でまず強く注力しているのはモバイルでのサポートですが、希望および目標は必要な API などのサポートを追加することで Open Web Apps がすべてのプラットフォームおよびデバイスで動作することです。

Marketplace

Open Web Apps では、アプリをどこからでも利用およびインストールできます。完全にあなた次第です。しかし、一覧化やホスティングなどに興味があるのでしたら、Firefox Marketplace をご覧になることをお勧めします。

また、アプリ開発に関する多くの情報を得るために Developer Hub を訪れましょう。

終わりに

Open Web Apps は、あなたの開発方法を変えるために存在するのではありません。あなたの既存の Web ソリューションをアプリとしてインストールしたり、デバイス固有の API にアクセスしたりするなどのために存在します。

車輪を再発明しないでください。車輪を少し強化するだけです!

WebRTC の有効化、Win 7 で H.264/MP3 をデフォルトでサポート、Windows 8 向け Metro UI など – Firefox Development Highlights

原文: WebRTC enabled, H.264/MP3 support in Win 7 on by default, Metro UI for Windows 8 + more – Firefox Development Highlights on February 20, 2013 by Paul Rouget and Robert Nyman [Editor]

Firefox の最新の開発状況をご覧いただく機会が再びやってきました。本記事は Bleeding Edge および Firefox Development Highlights シリーズの一環であり、ほとんどのサンプルは Firefox Nightly のみで動作することにご注意ください (また、変更される場合もあります)。

デフォルトで WebRTC を有効化

以前は Firefox の about:config で設定項目 media.peerconnection.enabledtrue に設定することが必要でしたが、デフォルトで有効になりました。これは Web ブラウザで特別な設定や構成を必要とせず、ただちに WebRTC を実行可能にするための大きな前進です。

この決断の背景について詳しくは、Pref on WebRTC by default をご覧ください。

WebRTC を使い始めたいと思いますか? そうでしたら、私たちが著した記事 Cross-browser camera capture with getUserMedia/WebRTC をお勧めします。

Metro UI

Windows 8 向けに Firefox の新しいインターフェイスを搭載しました (Firefox Nightly をデフォルトのブラウザにしていた場合は、新しい UI を使用するために再設定を行ってください)。


さらに多くのスクリーンショットをご覧いただけます。

Windows 7 で H.264 & MP3 のサポートをデフォルトで有効化

以前 H.264 & MP3 のサポートについてお話ししました (日本語訳) が、これがデフォルトで有効になりました。

Mac OS X および Linux でのサポートについては、引き続き作業中です。

WebAudio API の進捗

私たちは WebAudio API の実装に取り組んでおり、最初のサポート箇所をご覧いただけるようになりました。

こちらは about:config の設定項目 media.webaudio.enabled preference で利用できます。この項目を true に設定すると、AudioContext.decodeAudioData などの API を利用できます。

Crypto API: window.crypto.getRandomValues

window.crypto.getRandomValues は、整数値の型付き配列 (すなわち Int8Array、Uint8Array、Int16Array、Uint16Array、Int32Array、Uint32Array) を与えると、暗号理論的な乱数でその配列を埋めます:

/* window.crypto.getRandomValues が利用可能と仮定 */

var array = new Uint32Array(10);
window.crypto.getRandomValues(array);

console.log("Your lucky numbers:");
for (var i = 0; i < array.length; i++) {
    console.log(array[ i ]);
}

canvas: ctx.isPointInStroke

これは Firefox 19 beta で実現しました。

WHATWG メーリングリストより引用 (訳注: 以下は引用文の訳):

“私たちは最近、Firefox に isPointInStroke(x,y) を実装しました (https://bugzilla.mozilla.org/show_bug.cgi?id=803124)。これは isPointInPath(x,y) と類似しており、点がパスのストロークに含まれる領域の中にある場合に true を返します。”

JavaScript: Math.imul

Math.imul は、C 言語のような意味論による高速な 32 ビット整数値の乗算を可能にします。この機能は Emscripten といったプロジェクトで有用です。

ポリフィル:

function imul(a, b) {
    var ah  = (a >>> 16) & 0xffff;
    var al = a & 0xffff;
    var bh  = (b >>> 16) & 0xffff;
    var bl = b & 0xffff;
    // 0 ビットのシフト演算は、上位部分の符号を修正する
    return (al * bl) + (((ah * bl + al * bh) << 16) >>> 0);
}

ハロー Chrome, こちら Firefox です!

原文: Hello Chrome, it’s Firefox calling! on February 4, 2013 by Maire Reavy and Robert Nyman [Editor]

Mozilla は WebRTC の開発において大きなマイルストーンに到達したことに興奮しています。Firefox と Chrome 間での RTCPeerConnection の相互運用に成功したのです。この取り組みが成し遂げられたのは、オープン Web コミュニティと Mozilla, Google の密な協調の成果です。

RTCPeerConnection (PeerConnection や PC と略されます) の相互運用性の確保により、サードパーティ製プラグインをインストールすることなく、Firefox の WebRTC アプリケーションと Chrome の WebRTC アプリケーション間で、音声・ビデオ発信が直接行えます。この機能がブラウザに搭載されたことにより、ユーザーは初めてのプラグインインストールに戸惑ったり、バグに悩まされることがありません。また開発者も自身のアプリを簡単に、そして幅広い対象に公開できます。

この大きなマイルストーン到達を祝うにあたり 、私たちは Google の友人と WebRTC で会話すると楽しいのではないかと考えました。次のビデオは、Mozilla の Chief Innovation Officer である Todd Simpson と、Google の Director of Product Management である Hugh Finnan による、Firefox―Chrome 間のデモンストレーションコールです。

Google もこの大きなニュースについて彼らのブログで取り上げています。そちらもご覧ください。

このマイルストーンは、昨年末に紹介した WebRTC と Social API のデモの上にできています。昨年末のポストでは、DetaChannel という WebRTC の強力なコンポーネントを業界初で実装したことを報告しました。DataChannel と音声/ビデオチャットを組み合わせることで、ユーザーは自分のコンピューターもしくはデバイス上のほとんどすべてを共有できます。旅行の写真、メモリアルなビデオ、ニュースのリンクなどをビデオチャットのウインドウ上にドラッグ&ドロップするだけで相手に送れるのです。

WebRTC は W3C と IETF という2つの標準化団体が共同で策定中のオープン標準で、すべてのデバイスに音声/ビデオのリアルタイム通信を行う共通プラットフォームを提供することを目的としています。これは相互運用性と、Web で真にオープンなリアルタイム通信の実現への第一歩です。

Posted by:
Serge Lachapelle, Chrome Product Manager and Maire Reavy, Firefox Media Product Lead

Firefox で RTCPeerConnection を使う

まだ RTCPeerConnection を Firefox で試していない JavaScript 開発者の方は、最新の Firefox Nightly で media.peerconnection.enabled の設定を “true” にすることで RTCPeerConnection を利用できます (pref の設定は about:config にアクセスして検索してください)。以下は Firefox で RTCPeerConnection を利用し、WebRTC コールの開始、受け取り、終了を行うサンプルアプリのコードです。

function initiateCall(user) {
  document.getElementById("main").style.display = "none";
  document.getElementById("call").style.display = "block";

  // Here's where you ask user permission to access the camera and microphone streams
  navigator.mozGetUserMedia({video:true, audio:true}, function(stream) {
    document.getElementById("localvideo").mozSrcObject = stream;
    document.getElementById("localvideo").play();
    document.getElementById("localvideo").muted = true;

    // Here's where you set up a Firefox PeerConnection
    var pc = new mozRTCPeerConnection();
    pc.addStream(stream);

    pc.onaddstream = function(obj) {
      log("Got onaddstream of type " + obj.type);
      document.getElementById("remotevideo").mozSrcObject = obj.stream;
      document.getElementById("remotevideo").play();
      document.getElementById("dialing").style.display = "none";
      document.getElementById("hangup").style.display = "block";
    };

    pc.createOffer(function(offer) {
      log("Created offer" + JSON.stringify(offer));
      pc.setLocalDescription(offer, function() {
        // Send offer to remote end.
        log("setLocalDescription, sending to remote");
        peerc = pc;
        jQuery.post(
          "offer", {
            to: user,
            from: document.getElementById("user").innerHTML,
            offer: JSON.stringify(offer)
          },
          function() { console.log("Offer sent!"); }
        ).error(error);
      }, error);
    }, error);
  }, error);
}

function acceptCall(offer) {
  log("Incoming call with offer " + offer);
  document.getElementById("main").style.display = "none";
  document.getElementById("call").style.display = "block";

  // Here's where you ask user permission to access the camera and microphone streams
  navigator.mozGetUserMedia({video:true, audio:true}, function(stream) {
    document.getElementById("localvideo").mozSrcObject = stream;
    document.getElementById("localvideo").play();
    document.getElementById("localvideo").muted = true;

    // Here's where you set up a Firefox PeerConnection
    var pc = new mozRTCPeerConnection();
    pc.addStream(stream);

    pc.onaddstream = function(obj) {
      document.getElementById("remotevideo").mozSrcObject = obj.stream;
      document.getElementById("remotevideo").play();
      document.getElementById("dialing").style.display = "none";
      document.getElementById("hangup").style.display = "block";
    };

    pc.setRemoteDescription(JSON.parse(offer.offer), function() {
      log("setRemoteDescription, creating answer");
      pc.createAnswer(function(answer) {
        pc.setLocalDescription(answer, function() {
          // Send answer to remote end.
          log("created Answer and setLocalDescription " + JSON.stringify(answer));
          peerc = pc;
          jQuery.post(
            "answer", {
              to: offer.from,
              from: offer.to,
              answer: JSON.stringify(answer)
            },
            function() { console.log("Answer sent!"); }
          ).error(error);
        }, error);
      }, error);
    }, error);
  }, error);
}

function endCall() {
  log("Ending call");
  document.getElementById("call").style.display = "none";
  document.getElementById("main").style.display = "block";

  document.getElementById("localvideo").mozSrcObject.stop();
  document.getElementById("localvideo").mozSrcObject = null;
  document.getElementById("remotevideo").mozSrcObject = null;

  peerc.close();
  peerc = null;
}

標準化団体がまだ策定を終えていないため、Firefox ではまだ RTCPeerConnection API を mozRTCPeerConnection と接頭辞をつけコールしています。Chrome も webkitRTCPeerConnection と接頭辞をつけています。標準化が終了したら、接頭辞を省き同じ API を利用できますが、それまでの間は Firefox, Chrome どちらでも動くことのできるよう、どちらの接頭辞もサポートしてください。

試してみよう

Firefox―Chrome 間の通信を試したい方は、試す手順を記したページをご覧ください。

Firefox と Chrome 間の PeerConnection の相互運用性はまだ初期段階です。初期段階のリリースにはバグがつきものですし、まだすべてのネットワーク環境での相互運用性が担保されていません。しかし、この新しい Web の機能、そして Web そのものにとって、今回の出来事は大きな一歩なのです。私たちは標準化団体ならびに WebRTC コミュニティの貢献者すべてに感謝します。まだまだやる事はたくさんありますが、Web がもっと素晴らしいものになることに皆さんが同意してくれると期待しています。

Web Activitiesの紹介

原文: Introducing Web Activities on January 24, 2013 by Robert Nyman

スマートフォンが持つアプリ向けの強力な機能のひとつに、インテントがあります。インテントは、特定のアクションを扱うため、どのようなサポートをあなたがアプリに求めているかを指定するため、またはあなたがやろうとしていることをアプリに登録する仕組みです。

インテント機能は Firefox OS において特に重要です。あなたの Web アプリがそもそも良いものだとしても、アプリを次のレベルに持っていくには、他のアプリやデバイス上の行動とのインタラクションが不可欠です。

そこで登場するのが Web Activities です。

Web Activities は基本的に、私達が Web をより強力なプラットフォームとすべく取り組んでいる WebAPI のひとつです。Web Activities は、インテントとアクティビティを結びつけ、またあなたのアプリが他のアプリからのアクションを受け付けることを宣言するシンプルな API です。

ちなみに、Mozilla Web Apps をご存知ない方は、Getting started with making apps を読むと良いでしょう。簡単に言うと、Mozilla Web App は HTML5, CSS, JavaScript に app manifest を追加したものです。

Web Activities の使い方

Web Activities を使う方法にはいくつかあります。

  • アクティビティを呼び、それを処理できるアプリを提示させる
  • サポートするアクティビティを、あなたのアプリのマニフェストファイルから登録する
  • アクティビティのサポートをオンザフライで登録する
  • アクティビティが発生した際に、あなたのアプリへのハンドラを付加する

アクティビティを呼び出す

たとえば、あなたのアプリにはボタンがあり、そこから画像を取得するようにしたいとしましょう。画像の取得先は、ギャラリー、カメラのほか、 Firefox OS 上のアプリのうち画像の取得というアクティビティをサポートするものがよいでしょう。こういった場合は、pick アクティビティを呼び出します。

var pick = new MozActivity({
   name: "pick",
   data: {
       type: ["image/png", "image/jpg", "image/jpeg"]
   
}
});

この例では、アクティビティ名に pick を、そしてデータに PNG もしくは JPEG を指定しています。こうすると、Firefox OS では利用できるアクティビティのメニューが次のように表示されます。

利用者は、画像を取得したいアプリを選ぶか、カメラ起動し写真を撮れます。それが終わると、結果がアクティビティをリクエストしたアプリに送られます。(注: 何が返されるか、あるいはは何も返さないかは、そのアクティビティを処理するアプリの中から選ばれます)

レスポンスの処理

Web Activities をはじめほとんどの WebAPI は onsuccess, onerror イベントハンドラを持ちます。画像・ファイルの場合、返されるのは Blob です。Blob が返されたら、その画像 (Blob) をあなたのアプリ上で直接表示させられます。

pick.onsuccess = function () {

    // 画像を生成し、返ってきた Blob を src にセット
    var img = document.createElement("img");
    img.src = window.URL.createObjectURL(this.result.blob);
 
    // アプリ内に画像を表示
    var imagePresenter = document.querySelector("#image-presenter");
    imagePresenter.appendChild(img);
};
 
pick.onerror = function () {

    // エラーの場合、もしくはユーザーがアクティビティをキャンセルした場合
    alert("画像を表示できません");
};

アプリにアクティビティを登録する

先述のとおり、特定のアクティビティに対しアプリをハンドラとしてセットできます。これには2通りの方法があります。

マニフェストファイルからセット ― 明示的な登録

{
    "name": "My App",
    "description": "Doing stuff",
    "activities": {
       "view": {
            "filters": {
                "type": "url",
                "url": {
                    "required": true, 
                    "regexp":"/^https?:/"
                }
            }
        }
    }
}

アクティビティハンドラの登録 ― 動的な登録

var register = navigator.mozRegisterActivityHandler({
    name: "view", 
    disposition: "inline", 
    filters: {
        type: "image/png"
    }

});
 
register.onerror = function () {
    console.log("アクティビティの登録に失敗しました");

}

そして、アクティビティを処理します。

navigator.mozSetMessageHandler("activity", function (a) {

    var img = getImageObject();

    img.src = a.source.url;

    /*
      アクティビティが値を返すなら
      a.postResult() もしくは a.postError() を呼ぶ
    */
});

利用可能なアクティビティ

現時点で利用可能なアクティビティは次のとおりです。

  • configure
  • costcontrol/balance
  • costcontrol/data_usage
  • costcontrol/telephony
  • dial
  • new (例 type: “websms/sms”, “webcontacts/contact”)
  • open
  • pick (例 type: “image/png”)
  • record
  • save-bookmark
  • share
  • test
  • view

いくつか例を紹介します。

電話をかける

var call = new MozActivity({
    name: "dial",
    data: {
        number: "+46777888999"
    }
});

新しい SMS

var sms = new MozActivity({
    name: "new",
    data: {
        type: "websms/sms",
        number: "+46777888999"
    }
});

新しい連絡先

var newContact = new MozActivity({
    name: "new",
    data: {
        type: "webcontacts/contact",
        params: { // "data" 内の動的なプロパティとして移動したほうが良いかも
            giveName: "Robert",
            familyName: "Nyman",
            tel: "+44789",
            email: "robert@mozilla.com",
            address: "Sweden",
            note: "This is a note",
            company: "Mozilla"
        }
    }
});

URL を開く

var openURL = new MozActivity({
    name: "view",
    data: {
        type: "url", // 将来的に text/html になるかも
        url: "http://robertnyman.com"
    }
});

ブックマークする

var savingBookmark = new MozActivity({
    name: "save-bookmark",
    data: {
        type: "url",
        url: "http://robertnyman.com",
        name: "Robert's talk",
        icon: "http://robertnyman.com/favicon.png"
    
}
});

試してみよう!

Web Activities はもう試せます。
Mozilla Web App を作り、Web Activities を呼ぶだけです。アプリは Firefox OS Simulator で試せます。

Web Activities は進行中

Web Activities はまだ進行中のため、アクティビティ名、データ型などが変わる可能性があります。しかし、現時点でほとんどの機能が動作します (mozRegisterActivityHandlermozSetMessageHandler はまだ実装されていないため動作しません)。

私は Web Activitiesが与えてくれる可能性、数多く考えられる応用例、あなたのアプリがほかのアプリとの連携でより協力になることに興奮しています。この記事であなたが Web Activities に興味をもっていただければ幸いです。

Firefox Development Highlights – Windows での H.264 & MP3 サポート、スコープが設定されたスタイルシート など

原文: Firefox Development Highlights – H.264 & MP3 support on Windows, scoped stylesheets + more on January 23, 2013 by Paul Rouget and Robert Nyman [Editor]

Firefox の最新の開発状況をご覧いただく、今年最初の機会がやってきました。本記事は Bleeding Edge および Firefox Development Highlights シリーズの一環であり、ほとんどのサンプルは Firefox Nightly のみで動作します (また、変更される場合もあります)。

Windows での H.264 & MP3 サポート

Android 版 Firefox および Firefox OS は、すでに H.264 と MP3 をサポートしています。私たちは、これらの形式のサポートをデスクトップ版 Firefox にももたらそうとしています。Windows 7 以降では、about:config で設定項目 media.windows-media-foundation.enabled を有効にすることでテストが可能になっています。デコードは OS 側で行われます(WebM や Ogg Theora とは異なり、Firefox のソースコードにデコーダは含まれません)。Linux および Mac 向けは現在作業中です。

新しいダウンロードパネルが使用可能になりました

新しいダウンロードパネルを利用可能にしました:

スコープが設定された style 属性

スコープが設定された style 要素を定義できるようになりました。通常、スタイルシートを記述するときは <style>...</style> を使用して、CSS コードはドキュメント全体に適用されます。<style> タグがノード (例えば <div>) の内部にネストしており、また <style> タグが scoped 属性を含む (<style scoped>) 場合、CSS コードはドキュメントで <style> 要素の親ノードから始まるサブツリーにのみ適用されます。サブツリーのルートを :scope 擬似クラスで参照することもできます。

デモ

Scoped style support

私たちの友人が HTML5Rocks の記事 A New Experimental Feature: scoped stylesheets でこの点について掲載しています。

@supports および CSS.supports

Firefox 17 で、@supports CSS @-規則をサポートしました。 これは、ある機能がサポートされている場合にのみ特定の CSS コードを定義することを可能にします。例えば:

@supports not (display: flex) {
  /* flex box モデルがサポートされていない場合、別のレイアウトを使用する */
  #main {
      width: 90%;
  }
}

Firefox 20 では、同じことが JavaScript でも可能になります:

if (CSS.supports("display", "flex")) {
  // flexbox に依存する処理を行う
}

 

ハッキング Firefox OS

ハッキング Firefox OS

原文:Hacking Firefox OS on November 14, 2012 by Luca Greco

このブログ記事は、Mozilla コミュニティのメンバーで、特に JavaScript や Web 関連技術のハッキングを愛する Luca Greco が書いたものです。

多くの開発者は、既に Web 技術を使ったモバイルアプリケーションを(一例としては Phonegap や Cordova のようなコンテナを利用して)作成している。大抵はクロスプラットフォームアプリケーションの開発をするためだったり、現在あるコードや自分の専門知識の両方もしくは片方を活用するためだ。

結果として Firefox OS が非常に好奇心を掻き立てられるプロジェクトとなっているのには、たくさんの理由がある。

  • Web アプリが、プラットフォームに最上級レベルのアクセスができる
  • Web アプリがネイティブ(抽象化レベルをより少なくし、かつパフォーマンスを向上できる)
  • プラットフォーム自体が Web ベース(そして Web 技術を使用してカスタマイズ可能)

将来的には、モバイルプラットフォームは Web 技術に基づいたものになるに違いないが、我々は今それに触れることができるし、それ以上に大事なのは、完全にオープンに開発されたプラットフォーム(Firefox OS)のおかげで、我々がそれを定義したり、より進んだ形に推し進める手助けが可能だということだ。私は、誘惑に抗えなかったので、MXR を使ってコードを収集したり、Wiki にあるドキュメントを研究したりして、Firefox OS のコードに没頭し始めた。

Firefox OS をハッキングする

2 週間ほどで、私は、アプリの実例と非公式なプレゼンテーションを作成した(地元で行われた LinuxDay 2012 でプレゼンしたものだ):

スライド: “Hack On Firefox OS”

アプリの実例: Chrono for Gaia (Firefox OS のユーザインタフェース)

このプレゼンテーションで、私が Firefox OS と Firefox が共に持っていると信じる強みについて強調してみた。

“ビルドがドンヨリしてるんじゃなくて、イキイキしてるんだ!本当のインタラクティブ環境。Web みたいにね”

B2G インスタンスの内部に Telnet できたので、興味深いものを探し回ったり、JavaScript スニペットを実行して新しい WebAPI をインタラクティブに実験してみたりした。B2G の内部にあるリモート JavaScript シェルを取得するオプションはいくつか存在している。

  • Marionette 主に自動化テストに使用される
  • B2G Remote JS Shell オプションで tcp ポートに公開される最小構成の JavaScript シェル(今後のリリースで廃止されるかもしれない)

あいにく、現時点では、これらのツールに調査用ユーティリティが統合されていないので(例えば、console.log や console.dir とか、MozRepl の repl.inspect や repl.search )、プレゼンテーションでは、 B2G シミュレータ上に拡張機能として MozRepl をインストールすることにしたが、ここ数週間で Firefox ナイトリーに Remote Web Console が搭載された。

Remote Web Console が、まだ完全に出来上がっていないのは明らかで、我々はバグや出力されないエラーに対処する必要がある(例えば、B2G では“remote debugger”を有効にする必要があるが、そうしなければ、失敗してもエラーを出さないからだ)。しかし、オブジェクトの調査、ネットワーク処理のログ、 JavaScript や CSS のエラーに対しては( 我らが Firefox Web コンソールみたいに )機能するんだ。

Firefox OS 向けの開発

私の経験からすると、Firefox OS 用 オープン Web アプリの開発は、Phonegap 的な技術に基づいたハイブリッドアプリとたいした違いはない。

我々は、デスクトップブラウザとブラウザの開発ツール上で、アプリケーションの主要な部分のコードを書いたりテストをしようとして、ネイティブ機能の代わりに mock-up や shim を使っている。しかし 2 週間の研究で、共有すると良さそうな、面白い作業メモの数々を集めることができたので、次のセクションでこんな話をするつもりだ。

  • 開発ワークフローとツールの見直し
  • 2 つの便利なティップスと技法のまとめ
  • 一般へのリリース(独自に行う場合と、Mozilla Marketplace で行う場合)

アプリの実例として、シンプルな時計を作成することにした。

ワークフローとツール

この経験で、私のツールセットは次の構成になった。

  • VoloJS – 開発用サーバとプロダクションビルドの自動化(js/css の圧縮、manifest.appcache の生成)
  • Firefox Nightly Web Developer Tools – Markup View、3D ビュー、レスポンシブデザインビュー、Web コンソール
  • R2D2B2G – B2G と Firefox アドオンを統合し、同時に動作させる

Volo を使用することで、私は http サーバに統合した volo でアプリのテストができた。JavaScript のコードは Require.js を使用してモジュールに分割され、最終的にはプロダクションバージョンを生成し、圧縮され、オプションで自動生成した manifest.appcache を用意してくれる。

私が開発サイクルで繰り返したことは:

  • 変更する
  • デスクトップブラウザで再読み込みして、変更を確認する
  • R2D2B2G を使用して、b2g シミュレータ上で変更を確認する
  • デスクトップブラウザか、リモートログインした b2g シミュレータでデバッグする
  • 最初に戻る :-)

お気に入りのデスクトップブラウザ(もちろん Firefox :-P)を使うことで、ものすごく強力な調査・デバッグツールを使うことができた。通常のモバイル Web ランタイム上では利用できないものだ。

  • Markup Viewer:DOM ツリーの状態の調査・変更をする
  • スタイルエディタ:CSS プロパティの調査・変更をする
  • 3D ビュー:DOM エレメントの位置が画面の表示領域を超えていないかどうか確認する
  • Web コンソール:JavaScript 実行環境の調査・変更をする

“Firefox OS”や“Android 版 Firefox”のような新しい Mozilla のプロジェクトのおかげで、こんな感じのツールが“Remote Web Tools”としてどんどん新しく使えるようになったし、リモートインスタンスへの接続もできるようになったんだ。

ティップスと技法

Gaia UI ビルディングブロック

Gaia は単なる B2G に実装された UI ではなく、以下のガイドラインに記述されている、デザインスタイルの指針や、既定の CSS スタイルのことだ。

上記のリポジトリからコンポーネントスタイルをインポートし、自分のアプリにアーカイブを適用すると、Firefox OS 独自の超イケてるルック・アンド・フィールになる。コンポーネントには安定版ではないものもある。これは、他のコンポーネントのスタイルと相性が悪かったり、全てのプラットフォーム(例えば、デスクトップ版 Firefox もしくは Android 版 Firefox )で完全に動くわけではないとか、そういう意味だ。でも、大抵、なんらかのカスタムを使ったり、CSS ルールをもっと限定して使用したりすれば、修正できないものなんてない。

しっかり練り上げられた完璧な CSS フレームワーク(例えば Bootstrap)という感じではないが、もっと良くなっていくことが約束されているし、私もそうに違いないと思っている。

レスポンシブデザインビューを使うと、異なる解像度(と方向)でテストができるので、Firefox OS や Android デバイス版 Firefox で自分のアプリをテストしなくても、同様に、きちんと画面に対応する結果を得る手助けをしてくれる。但し、我々は dpi 絡みの微調整には気を配るべきだから、デスクトップブラウザを使用してどのように見えるか、というのは、現時点では完全な確認にはならないけどね。

アプリパネル

多くのアプリは一つ以上のパネルが必要となるので、まず、私は公式 Gaia アプリケーションで、ネイティブアプリがこのほぼ必須ともいうべき機能をどのように実装しているか、内部を確認した。これは Gaia Clock アプリケーションを“3Dビュー”で表示したものだ。

パネルはシンプルな DOM エレメント(例えば、section とか div タグ)で、初期位置は画面の表示領域外で、CSS transitions を使用して画面上に移動する。

“Chrono”アプリの、Drawer( 安定版ではない Gaia UI ビルディングブロック)でこんな使い方に気が付くだろう。

それから、Laps と About パネルの内容(:target 疑似クラスとの組み合わせ)

魅力的な -moz-element 技法

これは、とても魅力的な技法で、Firefox OS の time selector コンポーネントに使われているものだ。

デスクトップ版 Firefox ナイトリーの Markup Viewer で見てみたもの(現在は無効)

この非標準 CSS 機能のおかげで、我々は DOM エレメントを他のものの背景画像として使用することが可能だ。例えば、画面の表示領域外にある複雑な視覚的コンポーネントを、一つの DOM エレメントとして、可視空間に融合させたりするなど。

index.html より抜粋
...
<section role="chrono">
  <p>
    <!-- render offscreen DOM elements as backgrounds -->
    <span style="background-image: -moz-element(#hours);"></span>
    <span style="background-image: -moz-element(#minutes);"></span>
    <span style="background-image: -moz-element(#seconds);"></span>
  </p>
  <!-- real DOM elements moved offscreen -->
  <div>
    <ul id="hours" role="listbox">
    </ul>
  </div>
  <div>
    <ul id="minutes" role="listbox">
    </ul>
  </div>
  <div>
    <ul id="seconds" role="listbox">
    </ul>
  </div>
</section>
...
chrono.css より抜粋
...
/* NOTE: set fixed size on empty visible elements
[role="chrono"] > p span {
  width: -moz-calc(100% / 3);
  height: 100%;
  ...
}
...
/* NOTE: move real offscreen DOM elements
[role="chrono"] > div {
  position: absolute;
  left: -moz-calc((100%) + 10px);
  ...
}
 
...
chrono.js より抜粋
...
  // NOTE: generate seconds, minutes and hours elements
  for (var i=0; i<60; i++) {
    var txt = i < 10 ? "0"+i : i;
    var el = $("<li>", {role: "option", class: txt}).html(txt);
    $("#seconds").append(el);
  }
...
  // NOTE: scroll current seconds/minutes/hours element 
  //       inside offscreen containers
  function scroll(element, parent, val){
    var pos = $(element).get(0).clientHeight * val;
    $(parent).animate({ scrollTop: pos },
                      { duration: "0.3s", easing: 'swing',
                        step: function() {
                          force_redraw(element.get(0));
                        }
                      });
  }

-moz-element-moz-calc (コンポーネントのサイズを CSS ルールに合わせて計算するもので、CSS3 には calc として既にインクルードされている)の使い方は本当に簡単だが、MDN でこの件についてもっと詳しく知ることができる。

一般へのリリース

Web アプリマニフェスト

開発サイクルでは、R2D2B2G メニューオプションを使用して B2G シミュレータにアプリケーションをインストールするので、実際の manifest.webappは必要じゃないが、一般向けのリリース準備をする場合や、テストユーザ向けにリリースする際は、実物を作成する必要がある。

manifest.webapp の作成は難しくはない。単純なだけではなく、きちんとドキュメントになっている JSON ファイル形式だ:MDN の アプリマニフェスト

このマニフェストファイルに関連するデバッグ問題は未だに解明されていないが、有益なティップスはいくつかある。

  • マニフェストファイルに構文エラーがあるか、マニフェストファイルがダウンロードできなかった場合は、エラーはこっそり古いエラーコンソールに出力されている(というか、新しい Web コンソールには出力されない)
  • もしアプリケーションをドメイン内のサブディレクトリとしてアクセス可能にするなら、マニフェストで指定するリソースパスの中に、このパスを含める必要がある(例としては、launch_path、appcache_path、icons)。この件については後ほど詳しくやるつもりだ
  • アンインストールボタンをアプリに追加できる。これは、開発者(やテストユーザ)が、プラットフォームに依存しないやり方でアプリをアンインストールする手助けをするためのものだ。(なぜって、インストールされた Web アプリの“アンインストール方法”は、デスクトップ版なのか Android版 なのか、それとも Firefox OS 版なのかで違うからね)

オープン Web アプリ API を使って、私は“Chrono”に、ユーザがインストール可能にするためのコードを付け加えた。

ブラウザからデスクトップシステムにアプリをインストールする

/* Mozilla/Firefox installation */
var base = location.href.split("#")[0]; // WORKAROUND: remove hash from url
base = base.replace("index.html",""); // WORKAROUND: remove index.html
install.mozillaInstallUrl = base + '/manifest.webapp'; 
 
install.mozillaInstall = function () {
  var installRequest = navigator.mozApps.install(install.mozillaInstallUrl);
 
  installRequest.onsuccess = function (data) {
    triggerChange('installed');
  };
 
  installRequest.onerror = function (err) {
    install.error = err;
    triggerChange('error');
  };
};

既にインストールされているか確認する(Web アプリのランタイムアプリ、もしくは、ブラウザタブのセルフサービスインストーラとして):

function get_chrono_installed(success,error) {
  try1();
 
  // TRY1: get our application management object using getSelf()
  //       this works correctly when running into the webapp runtime container 
  function try1() {
    req1 = navigator.mozApps.getSelf();
    req1.onsuccess = function () {
      if (req1.result === null) {
        try2();
      } else {
        success(req1.result);
      }
    };
    req1.onerror = function () {
      try2();
    }
  }
 
  // TRY1: get our application management object using getInstalled()
  //       this works correctly when running as "self service installer"
  //       in a Firefox browser tab
  function try2() {
    req2 = navigator.mozApps.getInstalled();
    req2.onsuccess = function () {
      var result = null;
      var myorigin = window.location.protocol + "//" + window.location.host;
      if (req2.result !== null) {
        req2.result.forEach(function (app) {
          if (app.origin == myorigin)
            result = app;
        });
      }
      success(result);
    }
    req2.onerror = error;
  }
}

Linux デスクトップ環境では、Firefox からオープン Web アプリをインストールする際に、新しいランチャ(“.desktop”ファイル)を隠しディレクトリの“.local/share/applications”に作成する。

$ cat ~/.local/share/applications/owa-http\;alcacoop.github.com.desktop 
[Desktop Entry]
Name=Chrono
Comment=Gaia Chronometer Example App
Exec="/home/rpl/.http;alcacoop.github.com/webapprt-stub"
Icon=/home/rpl/.http;alcacoop.github.com/icon.png
Type=Application
Terminal=false
Actions=Uninstall;
[Desktop Action Uninstall]
Name=Uninstall App
Exec=/home/rpl/.http;alcacoop.github.com/webapprt-stub -remove

ご存知の通り、現在の規約(と実装)では 1 ドメインに対して 1 アプリケーションのみがサポートされている。Web アプリがインストールされた隠しディレクトリの中を見てみると、webapp.json 設定ファイルが一つ入っているのがわかるだろう。

$ ls /home/rpl/.http;alcacoop.github.com/
Crash Reports  icon.png  profiles.ini  webapp.ini  webapp.json  webapprt-stub  
z8dvpe0j.default

この制限の理由は MDN のドキュメントに書いてある: アプリマニフェストに関する FAQ

デバッグ問題を自分でなんとかするには、Web アプリランタイムで自分のアプリを実行する際に、コマンドラインから実行し、古い(けど、今でも便利な)エラーコンソールを有効にしておくことだ。

$ ~/.http\;alcacoop.github.com/webapprt-srt -jsconsole


オープン Web アプリのアンインストールはすごく簡単だ。手動で削除するなら、“オープン Web アプリ の隠しディレクトリ”(プラットフォーム依存のメソッド)の中から“wbapprt-stub”実行可能ファイルを使用する。

$ ~/.http\;alcacoop.github.com/webapprt-stub -remove

もしくは、JavaScript コードで、私が“Chrono”でやったみたいに、Firefox ブラウザタブから、ユーザがアプリをアンインストールすることができるようにしておく。

function uninstall_error() { $('.install-error').html("UNINSTALL ERROR: retry later."); }
function uninstall_success() { 
  install.state = "uninstalled";
  updateInstallButton(); 
  $('.install-error').html("UNINSTALL: app removed."); 
}
 
function uninstall() {
  get_chrono_installed(function (app) {
    var req2 = app.uninstall();
    req2.onsuccess = uninstall_success;
    req2.onerror = uninstall_error;
  }, uninstall_error);  
  
  return false;
}

AppCache マニフェスト

これはだいぶ前に主要なブラウザに統合された機能だが、今では、オープン Web アプリのおかげでほとんど必須機能になっている。manifest.appcache と JavaScript コードによる適切な更新がなければ、Web アプリはオフラインで正しい動作ができないし、実際にインストールされたアプリケーションみたいな感じがしないだろう。

現在の AppCache は黒魔術の一種で、チャック・ノリスみたいな“Facts Page”と呼ばれるにふさわしいものだ:AppCache の真実

volo-appcache コマンドのおかげで、manifest.appcache は、たった 1 行のコマンドで生成できる。

  $ volo appache
  ...
  $ ls -l www-build/manifest.appcache
  ...
  $ tar cjvf release.tar.bz2 www-build
  ...

残念ながら manifest.appcache のデバッグやテストをする必要がある場合は、自分でなんとかするしかない。なぜって、現時点で Firefox に統合されているデバッグツールは使いやすくはないんだ。

  • appcache のダウンロード進行状況(とエラー)は現在 Web コンソールに出力されない
  • appcache エラーには、エラーメッセージや説明が含まれていない
  • Android 版 Firefox と Firefox OS には、ApplicationCache を削除する UI がない

appcache デバッグ問題は非常にやっかいなので、この実験で私が学んだ二つの技法を紹介しよう。

  • window.applicationCache イベント(‘error’、‘checking’、‘noupdate’、‘progress’、‘downloading’、‘cached’、‘updateready’等)毎にサブスクライブし、開発やデバッグを行っている間に受け取るイベントやエラーメッセージの全てをログにとる
  • 最初の一般リリースにアップグレード処理用コードを追加する(そうじゃなかったら、一件一件ユーザがアップグレードするのを手伝う覚悟をしないとね :-D)
  • デスクトップ版 Firefox では、基本設定ダイアログから ApplicationCache を削除できる
  • サーバサイドのログを解析して、”appcache updating”がどこで固まったのか理解する
  • Firefox や B2G を実行時にどのような理由で固まるのかを理解するのに、ApplicationCache 内部のログを有効化する (https://mxr.mozilla.org/mozilla-central/source/uriloader/prefetch/nsOfflineCacheUpdate.cpp#62 より):
export NSPR_LOG_MODULES=nsOfflineCacheUpdate:5
export NSPR_LOG_FILE=offlineupdate.log
firefox -no-remote -ProfileManager &
 
tail -f offlineupdate.log
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::Init [7fc55959ce50]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::AddObserver [7fc56a9fcc08] to update [7fc55959ce50]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::AddObserver [7fc55c3264d8] to update [7fc55959ce50]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::Schedule [7fc55959ce50]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdateService::Schedule [7fc57428dac0, update=7fc55959ce50]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdateService::ProcessNextUpdate [7fc57428dac0, num=1]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::Begin [7fc55959ce50]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::NotifyState [7fc55959ce50, 2]
-1614710976[7fc59e91f590]: 7fc559d0df00: Opening channel for http://html5dev:8888/gaia-chrono-app/manifest.appcache
-1614710976[7fc59e91f590]: loaded 3981 bytes into offline cache [offset=0]
-1614710976[7fc59e91f590]: Update not needed, downloaded manifest content is byte-for-byte identical
-1614710976[7fc59e91f590]: done fetching offline item [status=0]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::LoadCompleted [7fc55959ce50]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::NotifyState [7fc55959ce50, 3]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::Finish [7fc55959ce50]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdateService::UpdateFinished [7fc57428dac0, update=7fc55959ce50]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdateService::ProcessNextUpdate [7fc57428dac0, num=0]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::NotifyState [7fc55959ce50, 10]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::RemoveObserver [7fc56a9fcc08] from update [7fc55959ce50]
-1614710976[7fc59e91f590]: nsOfflineCacheUpdate::RemoveObserver [7fc55c3264d8] from update [7fc55959ce50]


applicationCache サポートを“Gaia Chrono アプリ”に追加して、私はこの技法を全て使うことで、ついに Firefox が“updateready”イベントを送信しないことを発見した。そのため、私はユーザにページを更新して新しい(既にキャッシュされている)バージョンを使い始めるように伝えることができなかった。問題をよく理解するために、MXR にあるコードと Bugzilla のチケットを検索して、ようやく、チケットが既に存在することがわかった:bugtracker: Bug 683794: onupdateready event not fired when an html5 app cache app is updated

このバグの回避方法自体は実に単純で(動かないのを追跡するよりよっぽどね)、ダミーの“updateready”リスナを script タグの ApplicationCache オブジェクトに追加すれば、トリガになることを確認した。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"> 
    <link rel="stylesheet" href="styles/main.css">
    <script>
// WORKAROUND BUG: https://bugzilla.mozilla.org/show_bug.cgi?id=683794
window.applicationCache.addEventListener('updateready', function () {
 // dummy, fired
}, false);
    </script>
    <script data-main="js/app" src="js/lib/require.js"></script>
   ...

もし、この機能を使い始めるつもりがあるなら(今すぐなのか、後でなのかは君次第だけど)、こんな感じに考えておくといい。

  • 標準が示している通りに実装する
  • なぜ、そうあるべき動作にならないのかを考えてデバッグする
  • 既知のバグを検索して、未報告ならバグ報告する(注:これ超重要だからね!!!:-D)
  • 回避方法を見つける

これは、もちろん Web 開発ツールがもっとサポートする必要がある機能だ。普通の Web 開発者なら、“ブラウザ内部”の視点から、自分の Web アプリをデバッグしたくなんてないからね。

Android 版 Firefox への移植

オープン Web アプリの面白い特徴は “(ほとんど)何の変更もしないで、サポートされているどんなプラットフォームにもインストール可能”っていうことだ。例えば、我らが“Chrono”アプリは Firefox ナイトリを使えばデスクトップに、 Android 版 Firefox ナイトリを使えば Android にインストールできる。

私自身の意見では、Android 版 Firefox は Firefox OS と同じくらい、オープン Web アプリの未来にとって極めて重要なプラットフォームとなり得る。Android は既に一般的なモバイルプラットフォームだから、同一コードベースで Firefox OS と Android にアプリケーションをリリースするというオプションを、開発者に提供するということは大きな利点だ。

私が“Chrono”アプリを Android に移植する際に発生した唯一の問題は、Android 版 Firefox のレンダリング動作の差異に関連するもの(とアプリケーションに含まれている WebAppRT の影響によるもの)だ。

GeckoScreenshot サービスは、変更を検知した時に変更箇所のみ再描画を強制する。この機能は -moz-element 技法に悪影響を及ぼすので、実際に何を再描画する必要があるのかを、理解させる多少の手助けが必要になる。

// Firefox For Android: force redraw workaround
define(function (require) {
  var is_firefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
  var is_android = navigator.userAgent.toLowerCase().indexOf("android") > -1;
 
  var n = document.createTextNode(' ');
 
  return {
    force_redraw: function (element) {
      if(is_firefox && is_android) {
        rafId = window.mozRequestAnimationFrame(
          function(){
            element.appendChild(n);
            n.parentNode.removeChild(n)
            window.mozCancelRequestAnimationFrame(rafId);
          }
        );
      }
    }
  }
});

一般へのリリース

GitHub ページには、素早く簡単にアプリを一般にリリースするオプションがあるけど、volo-ghdeployコマンドを使うともっと簡単にできる:

  $ volo appcache && volo ghdeploy
  ...

与えられたドメインのサブディレクトリにオープン Web アプリを展開する場合(例えば Github ページを使う時もそうだけど)は、manifest.webapp に必要なのは配信元(プロトコル + ホスト名 + ポート番号)に対するパスで、現在の URL ではない。

{
  ...
  "launch_path": "/gaia-chrono-app/index.html",
  "appcache_path": "/gaia-chrono-app/manifest.appcache",
  ...
  "icons": {
    "128": "/gaia-chrono-app/icons/chrono-128.png",
    "64": "/gaia-chrono-app/icons/chrono-64.png"
  },
  ...
}

一つの配信元から、インストールできるオープン Web アプリは一つだけなので、もし Github ページから一つ以上のアプリを展開したかったら、Github ページをカスタムドメインで公開するように設定する必要がある:Github Help – ページにカスタムドメインを設定する

ようやくアプリがオンラインで一般の人々がアクセス可能になった時点で、Mozilla Marketplace に投稿して、もっと知名度を上げることができるようになる。

アプリの投稿手順の中で、manifest.webapp が認証され、微調整が必要かどうか、また、どのように微調整すれば投稿が完了するのか、について警告を受ける:

  • 情報が不足していることに関するエラー(例 名前やアイコン)
  • 不正な値に関するエラー(例 方向)

他のモバイル marketplace と同様に、投稿は次の内容をまとめて記入しなければならない。

  • manifest.webapp の URL(注意:developer panel で読み込み専用となり、変更できない)
  • 長めの説明と機能リスト
  • 簡単なリリースの説明
  • 一つ以上のスクリーンショット

Mini Market

Mozilla Marketplace の目標はオープン Web アプリがもっと注目を集める手助けをすることで、その他のモバイルストアも現在自分たちのエコシステムで同様のことを行っているが、Mozilla がこのプロジェクトにオープン Web アプリと名付けているのは次のような理由からだ:

Mozilla はオープン Web アプリ用の Marketplace を作った唯一の団体なのではない!Mozilla は 我々が Web で享受しているのと同様の自由を得られるように Marketplace をデザインした。それ以上でもそれ以下でもない。

これは非常に強力な機能で、開発者が多くの面白い使用法ができるようになっている:

  • Firefox OS デバイス用キャリア・アプリ・マーケット
  • 非公開アプリ用インストーラ・マネジャ
  • イントラネットアプリ用インストーラ・マネジャ

最後に

明らかに、 Firefox OS とオープン Web アプリは現時点では完全に完成されたものではない(しかし、すごい勢いで改善されている)。Firefox OS には公式にリリースされた SDK がない。でも、Web には公式の SDK なんてないけど、我々は毎日それを使ってイケてる仕事をやってるよね。

だから、君がモバイルプラットフォームに興味があって、モバイルプラットフォームがどんなふうに生まれて育っていくかを知りたい、とか、君が Web 開発者でもっともっとモバイルエコシステムに Web 技術を使っていきたいなら…

真面目な話、Firefox OS をやってみるべきだ。

我々には、もっとオープンなモバイルエコシステムがふさわしいはずだ。今すぐその活動を開始して、オープン Web アプリや Firefox OS が新しい強力なツールになるよう手助けしようじゃないか!

ハッピー・ハッキング!

HTML5 にまつわる誤解を解く

原文: HTML5 mythbusting on November 1, 2012 by Chris Heilmann

HTML5 の実用性を巡って昨今繰り広げられている議論は、多くの間違った憶測に基づいています。それは、一度言われてからずっと繰り返されている、そして多くの場合正しいのかどうかまったく検証されていない、HTML5 に関する誤解につながっています。

HTML5 は遅い?

HTML5 の問題について話したがる人たちが必ず主張することと言えばパフォーマンスです。ここでの一番の問題は、そうした比較のほとんどがリンゴとナシの比較に過ぎないという事実を見落としている点です。

HTML5 アプリとネイティブアプリのパフォーマンスを比較することは、オーダースーツと既製品のスーツを比較するようなものです。もちろんオーダースーツは手袋のように体になじみ、見た目は素晴らしいですが、もし後でそれを売りたい、あるいは誰かに譲りたいと思っても、残念ながら難しいでしょう。他の人にも同じようになじむとは限らないからです。

IMG_4197.jpg by Hello Turkey Toe, on Flickr

ネイティブアプリとはまさにそういうもので、特定の環境と目的のために開発、最適化され、その状態に固定されるものなのです。これに関しては後ほど詳しく述べたいと思います。

一方 HTML5 は、その定義にも書かれているように、環境、ディスプレイ、あるいは技術とは独立して動作する Web 技術です。Web 上で成功するため柔軟性を最大限に備えています。そして Web もその定義通り解釈すれば、すべての人のために存在するのであって、非常に高価なハードウェアを購入する余裕があり一企業によって管理された固定環境に縛られることもいとわない、少数の恵まれた人たちのためだけのものではありません。

ネイティブアプリは端末やプラットフォームごとに一から開発しなければなりませんが、HTML5 アプリなら、スマートフォンからタブレット、デスクトップまで、ひとつの製品で対応できます。また、想定画面サイズや機能を固定せずユーザ環境をチェックして適宜対応することも可能であり、新しい携帯電話を買えない人たちを閉め出さなくても、より高速な最新端末を使用している人たちのユーザ体験を向上させられます。

一方でネイティブアプリは、多くの場合アップグレードを求めてきます。エンドユーザは新たなハードウェアの購入を強いられ、さもなければ製品自体を手に入れられません。柔軟性という観点から見れば HTML5 アプリは見事な役割を果たしており、逆にネイティブアプリはユーザを特定のハードウェアに依存させ、購入する余裕のない、あるいはあえて避けたいアップグレードが提供された場合、行き場を失わせることになります。その最たる例は、最近話題となった iOS 上での Apple 独自地図アプリへの移行です。多くのユーザが不満を抱え Google マップを使い続けたいと思っていますが、それは不可能です。


HexGLWebGL ベースのレースゲーム

HTML5 は、デスクトップではパフォーマンスの点でネイティブアプリに十分勝る能力を備えており、スクロールのパフォーマンス、動画の即時解析・編集、さらには 超高フレームレートでのフル 3D ゲームの実行高速レースゲーム の実現まで見る限り、パフォーマンスに関する問題がどこにあるのか自問しなくてはなりません。

その答えはハードウェアアクセスです。HTML5 アプリは、iOS や Android 向けに開発されたモバイルハードウェア上では二級市民として扱われており、最高のパフォーマンスを得られる部分にはアクセスできません。iOS の Web ビューは、ネイティブアプリと変わらない原理を用いているにもかかわらず、同じように高速に動作することを OS によって妨げられています。Android では、標準ブラウザがモタモタしているのに比べて、Chrome も Firefox もブラウザがどれほど高速に動作するかを証明しています

Android の標準ブラウザは、長期間改良されることなく Web の進化を妨げる脅威となっていた 90 年代の Internet Explorer を思い起こさせます。思えば、それこそまさに Mozilla と Firefox が誕生したきっかけでした。

要するに HTML5 は砂利道でも運転できるよう設計された F1 レースカーですが、今はまだ回避するすべのない多くの重荷を OS によって課されている状態と言えるでしょう。

HTML5 はカネにならない?

HTML5 はオープンな Web 技術をベースとした技術の集合体です。HTML5 はマネタイズモデルを持ち合わせていないという見方は、Web がマネタイズできないというのと同じことです (広告で支えられているニュースサイトにそうした論調の記事が載った場合、特に皮肉っぽく聞こえます)。

閉鎖的なアプリマーケットは、一見すれば自社製品を売るのに簡単な方法と思われますが、その成功には多くの誇張表現があり、実際のところ閉鎖的なマーケットでひとつのアプリを売って生計を立てられている開発者はほんの一握りです。アプリマーケットでの発見性や検索性がますます低下していく中、素早く見つけられること、そしてマーケット内の検索結果で 1 ページ目に載ることが最重要課題となり、多くの開発者はひとつのアプリを集中して開発する代わりに同じようなアプリを量産しています (例えば、話す犬、話す猫、話すロバ… といった具合で)。

ネイティブアプリを揃えた閉鎖的なマーケットが開発者にとって実際にデメリットであると言えるのはこのためです。アプリは Web 上での住所 (URL) も持たず、マーケットの外から見つけることはできません。作ったアプリはひとつずつ別々のマーケットに手作業で登録する必要があり、またそれぞれの審査と登録のプロセスに従わなければならず、製品の機能停止を避けてアプリを簡単に更新する方法はありません。

HTML5 アプリは Web 上にあって URL を持ち、Adobe PhoneGap Build のようなツールでパッケージ化すれば iOS や Android 向けのネイティブアプリに変換することも可能です。その逆は不可能です。

長期的な視点に立った場合、開発者にとってより最適な戦略は何かという問題が提起されるでしょう。マーケット側の独断でいつでも製品を取り下げられる可能性のある特定の閉鎖的な環境に賭けるか、あるいは世界的でオープンな配布ネットワークを通じてアプリを提供しつつ閉鎖的なマーケットもカバーするか、です。

Android と iOS のマーケットにある多くのアプリは実際、HTML5 で書かれ PhoneGap で変換されたものですし、Financial Times が自社アプリを HTML5 で開発し、ネイティブアプリより多くの収益を上げているというニュースは大きな話題となりました。最近でも New York Times が同様に Web アプリ化を行うと発表しています

HTML5 はオフラインで使えない?

HTML5 は Web 技術の集合体であることから、使用中ずっとオンラインでいなければならないと思い込んでいる人たちがいるようですが、そうした考えは完全に間違っています。HTML5 アプリでは、コンテンツをオフラインに保存しておく方法がいくつもあります。最も簡単な方法は、すべてのモダンブラウザが対応している Web Storage API です (ただし特別な例として Opera mini は除きます。このブラウザはクラウドサービスを通じてコンテンツを受信しており、独自のストレージツールを備えています)。また、Internet Explorer 以外の全ブラウザが対応している アプリケーションキャッシュ を使えば、アプリ自体をオフラインに保存しておけます。Web Storage API が提供する機能以上に複雑なデータを保存したいときは (Chrome と Firefox が対応している) IndexedDB か (iOS と Safari が対応している) WebSQL を使用できます。Lawnchair のような、互換性の問題を回避し開発者の使い勝手を高めるライブラリも公開されています。

HTML5 には開発環境がない?

よく言われる懸念のひとつに、HTML5 には開発者向けのツールが不足しているという点が挙げられます。不思議なことに、そのような声を開発者自身から聞くことはありませんが、自社の開発者に効率を上げる方法を考えさせる代わりにソフトウェアを購入することで解決したいと考える経営陣などからはそうした意見も耳にします。

HTML5 開発は基本的には Web 開発であり、驚くほど実用的な開発環境が整っています。繰り返しになりますが、本質的な問題は Web にまつわる誤解です。どこでもまったく同じに見えて同じように動作する製品を開発するのではありません。それは Web 本来の強みを奪おうとする考え方です。真の Web アプリとは、どのような環境でも動作しつつ、主要なプラットフォームではより優れたパフォーマンスを発揮する製品です。そのため、開発環境は特定の万能な製品ではなく一連のツールということになります。何を開発するかによって、その中からいくつでも選べるのです。もちろんひとつだけでも構いませんが。

Web がメディアとして大きな成功を納めているのは、開発者でなくても自由にコンテンツを公開できるためです。ブログプラットフォーム、CMS、あるいは OS に付属しているシンプルなテキストエディタを使って HTML ページを書き始められます。開発者としてのキャリアを積むにつれ、気に入ったツールをたくさん見つけ、それらに慣れ効率性を高めていくことでしょうが、ひとつの定番ツールというのは存在しません。Visual Studio や Eclipse のような統合開発環境 (IDE) を好む開発者もいますし、Dreamweaver のような WYSIWYG スタイルのエディタを求める人たちもいます。ただ Web 開発者の多くはテキストエディタかコマンドラインを使っているでしょう。秀丸、Jedit から、Vim、Emacs に至るまで、それらはすべて実用的なツールであり、実際に多くの開発者が Web コンテンツを開発するため日常的に使用しています。

デバッグやテストについても、最近ではツールが充実してきています。私たちが作り、エンドユーザ必ず目にするソフトウェア、つまり Web ブラウザも、デバッグ環境やテスト環境を兼ねているからです。変更箇所をリアルタイムで確認し直接編集可能な Firebug アドオン を追加できる Firefox をはじめ、Opera には Dragonfly、Safari や Chrome には開発ツールが付属しており、今やすべてのブラウザに開発者用の機能が多数搭載されています。Firefox の新しい開発ツール はさらに進んでおり、単なるデバッグ環境を超え、それ自体開発者が自分のニーズに応じて拡張可能なツール群として設計されています。

今では リモートデバッガ機能 まで提供されています。つまり開発者は、自分の開発マシン上で、モバイル端末上で動作しているアプリケーションに直接変更を加えられます。スマートフォン向けに開発し、それを端末に転送して、インストールし、テストし、間違いを見つけて… といった作業の繰り返しはもう不要です。これにより開発期間が劇的に短縮されるでしょう。


Firefox のリモートデバッガ機能

視覚的な環境を求める開発者が増える中、Adobe が最近 Edge スイート を公開しました。これは WYSIWYG スタイルによる HTML5 アプリ開発を実現するツールとサービス群で、例えば Photoshop からドラッグ&ドロップで画像を配置するといったことも可能です。Edge Inspect は複数端末での同時テストを効率化し、PhoneGap Build を使えば HTML5 アプリを iOS や Android 向けのネイティブアプリとしてパッケージできます。

配布とパッケージに関して言えば、Google がつい最近 Yeoman プロジェクトを公開しました。これは、Web 開発者が Web 製品をアプリケーションとしてパッケージ、配布する手間を大幅に削減するもので、高速な動作を実現する機能まですべて備えています。

結局のところ、HTML5 はプラットフォーム中立であることから、決まった開発環境というのはありません。それが Web というものであり、自分に最も合ったツールを選べば良いのです。

ネイティブアプリにできず HTML5 にできること

HTML5 にまつわる誤解の多くは、突き詰めると、あるプラットフォームに特化して開発されテストされたアプリと、そのプラットフォームにも対応しているアプリとの比較だったという点に集約されるでしょう。競艇用モーターボートとホバークラフトの速度比較のように、同じ予測可能な結果になるのと似たようなものです。より興味深い質問を挙げるとすれば、開発者やエンドユーザにとって HTML5 を素晴らしいものにしている要素は何か、つまりネイティブアプリができないこと、あるいはしないことは何かということです。

  • 一度書けばどこでも動く — HTML5 アプリは、ブラウザ内、タブレット上、そしてデスクトップで実行でき、iOS や Android に対応するネイティブコードへ変換することも可能です。その逆は不可能です。
  • Web を通じた共有 — HTML5 アプリは URL を持っていることから、Web を通じて共有したり Web 検索で発見できたりします。マーケットに足を運んで、混み合い限られたスペースの中から探す必要はありません。一方、他の Web コンテンツを宣伝するのと同じ方法がここでは使えます。より多くの人たちがあなたのアプリを気に入ってリンクすれば、それに伴って Web 検索の順位が上がり見つけやすくなるでしょう。
  • 合意されたマルチベンダー標準に基づく技術 — HTML5 は現在の Web を形成している様々な企業の共同成果であり、開発者が不満を持つ方向へ傾く可能性のある、単独企業によって規定された仕様ではありません。
  • 大勢の開発者 — 近年 Web 開発に何らかの形で携わった人たちは誰でもアプリを開発する準備ができていると言えます。もはや小さく専門的なコミュニティではありません。
  • 消費ツールと開発ツールは同じもの — まず最初に必要なものは、テキストエディタとブラウザだけです。
  • 小規模で部分的な更新が可能 — ネイティブアプリを更新するには、アプリケーション全体を再度ダウンロードする必要があります (例えば Angry Birds の新バージョンは 23 MB あり、それを 3G 接続でダウンロードする人もいます)。HTML5 アプリならデータを必要なだけダウンロードしオフラインに保存することができ、その上更新もはるかに簡単です。
  • シンプルな機能のアップグレード — ネイティブアプリはインストール時にハードウェアへのアクセス許可を求め、後からそれを変更することができません。あらゆるアプリがあらかじめ様々なアクセス許可を求めてくるのはそのためです (これはもちろんプライバシーやセキュリティに関わるリスクとなります)。HTML5 アプリは、ハードウェアやデータへのアクセス許可を、必要なときに更新や再インストールなしに求めることが可能です。
  • 様々な環境への適応 — HTML5 アプリは、レスポンシブデザインを使って、コードに変更を加えることなく環境ごとに最適なユーザ体験を提供できます。デスクトップからスマートフォンへ、あるいはタブレットへ、それぞれに別々のアプリをインストールすることなくスムーズに移動できます。

ネイティブアプリでこうしたことが可能か考えてみてください。

ハードウェアからの締め出しを破り、マネタイズを簡単にするために

HTML5 が開発者にとって未だ確実な選択肢となっていない理由は、上述したハードウェアからの締め出しという問題によるところが大きいでしょう。iOS 端末では WebKit 以外のエンジンを搭載したブラウザの提供が許可されておらず、カメラやアドレス帳、バイブレーション、通話、テキストメッセージへのアクセスも HTML5 に許可されていません。それらはすべて、開発者にとってモバイル端末を面白いものにし、アプリにとって必須の機能と言えます。

このような問題を解決するため、Mozilla はいくつかの企業と共同で一連の API を開発し、標準化された方法による端末へのアクセス手段を定義してきました。これが Web API と呼ばれるものです。この API を使用すれば、あらゆるブラウザがハードウェアへのアクセス許可を安全な方法で取得することが可能となり、締め出しを破れます。

Web API を実装した最初の環境が Firefox OS で、来年には端末が出荷される予定です。Firefox OS では、ネイティブアプリと同じようにハードウェアへのアクセス権を持った HTML5 アプリを提供できます。開発者はハードウェアへ直接アクセスすることが可能であり、そのためより高速で、また重要なことにより小さなアプリを開発できるのです。エンドユーザにとってのメリットは端末が非常に安くなるということで、Firefox OS は、例えば最新の Android へアップグレードできない非常に低スペックのハードウェアでも動作します。

マネタイズに関して言えば、Mozilla は独自の HTML5 アプリ向けマーケットプレイス を開設しようと取り組んでいます。ここでは単に HTML5 アプリを登録できるだけでなく、単純な Web 検索でも発見可能となります。エンドユーザがアプリを簡単に購入できるよう、モバイルキャリアと提携し通話料と併せて請求する仕組みも整えようとしています。これによって、クレジットカードを持たないユーザでもアプリを購入し、モバイル Web 革命に参加できます。

HTML5 の実用性はどのぐらいか?

全体的に見れば HTML5 は急速に成長しており、アプリ開発者にとって非常に面白く信頼できるプラットフォームとなりつつあります。取り除かなければならない大きな障壁はハードウェアアクセスですが、Web API の標準化作業や PhoneGap のようなツールによって、従来考えられていたよりはるかに問題は小さくなってきています。

上で述べたネイティブアプリを超える HTML5 のメリットは、プラットフォームごとに別々のコードを書く時間を費やす代わりに、HTML5 アプリ開発に取り掛かるだけの十分な理由となるはずです。たとえ対応したいのがひとつの特定のプラットフォームだけで、HTML5 を選択する必要がなくても、そうした決定について HTML5 の問題のせいにするのは的外れでしょう。

HTML5 開発はプラットフォームやブラウザとは独立したものです。そうした考えを受け入れられない場合、その可能性に自ら制約を課していることになります。歴史的に、閉鎖的なプラットフォームは浮かんでは消えてきましたが、Web は今でも力強さを増しながら、世界中の膨大な数のユーザにリーチすること、そして誰かに許可を求めたり複雑な開発環境をインストールすることなく開発を始めることを可能にしています。これこそ多くの人たちが Web 上で何かを始めてきた大きな理由であり、今もそれは変わりません。そして Web では誰も閉め出されることはありません。さあ、あなたも HTML5 アプリ開発に挑戦してみましょう。

Camera API で写真撮影 – WebAPI の一部

原文: Taking pictures with the Camera API – part of WebAPI (on April 2, 2012 by Robert Nyman)

WebAPI の一部である Camera API を通じて、端末のカメラで写真を撮り、表示中の Web ページにアップロードすることが可能になります。これは、input 要素に type="file"accept 属性を指定することで撮影した写真画像の入力を実現しています。

HTML は次のようになります:

<input type="file" id="take-picture" accept="image/*">

ユーザがこの HTML 要素を使用すると、入力する画像をファイルから選ぶか端末のカメラで写真を撮るかの選択肢が表示されます。カメラを選択すると写真撮影モードになります。

写真を撮影した後、その写真を受け入れるか破棄するかを選びます。受け入れると、<input type="file"> 要素に送信され、この要素の onchange イベントが発生します。

写真への参照を取得する

File API の助けにより、撮影した写真や選んだファイルにアクセスすることができます:

var takePicture = document.querySelector("#take-picture");
takePicture.onchange = function (event) {
    // 写真やファイルへの参照を取得
    var files = event.target.files,
        file;
    if (files && files.length > 0) {
        file = files[0];
    }
};

Web ページに撮影した写真を表示する

撮影した写真 (画像ファイル) への参照を取得したら、createObjectURL を使用して写真を参照する URL を作成し、その URL を画像の src に設定してください:

// 画像要素を参照
var showPicture = document.querySelector("#show-picture");
 
// window.URL オブジェクトを取得
var URL = window.URL || window.webkitURL;
 
// ObjectURL を作成
var imgURL = URL.createObjectURL(file);
 
// img src に ObjectURL を設定
showPicture.src = imgURL;
 
// パフォーマンス上の理由から使用済みの ObjectURL を破棄
URL.revokeObjectURL(imgURL);

createObjectURL がサポートされていない場合は、代わりに FileReader にフォールバックしてください:

// createObjectURL が未サポートの場合にフォールバックする
var fileReader = new FileReader();
fileReader.onload = function (event) {
    showPicture.src = event.target.result;
};
fileReader.readAsDataURL(file);

完全なデモとコード例

完全に動作する Camera API デモ のページを作成しました。以下は、このデモで使われている HTML ページと JavaScript ファイルのコードです:

HTML ページ

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Camera API</title>
        <link rel="stylesheet" href="css/base.css" type="text/css" media="screen">
    </head>
 
    <body>
 
        <div class="container">
            <h1>Camera API</h1>
 
            <section class="main-content">
                <p>A demo of the Camera API, currently implemented in Firefox and Google Chrome on Android. Choose to take a picture with your device's camera and a preview will be shown through createObjectURL or a FileReader object (choosing local files supported too).</p>
 
                <p>
                    <input type="file" id="take-picture" accept="image/*">
                </p>
 
                <h2>Preview:</h2>
                <p>
                    <img src="about:blank" alt="" id="show-picture">
                </p>
 
                <p id="error"></p>
 
            </section>
 
            <p class="footer">All the code is available in the <a href="https://github.com/robnyman/robnyman.github.com/tree/master/camera-api">Camera API repository on GitHub</a>.</p>
        </div>
 
 
        <script src="js/base.js"></script>
 
 
    </body>
</html>

JavaScript ファイル

(function () {
    var takePicture = document.querySelector("#take-picture"),
        showPicture = document.querySelector("#show-picture");
 
    if (takePicture &amp;&amp; showPicture) {
        // Set events
        takePicture.onchange = function (event) {
            // Get a reference to the taken picture or chosen file
            var files = event.target.files,
                file;
            if (files && files.length > 0) {
                file = files[0];
                try {
                    // Get window.URL object
                    var URL = window.URL || window.webkitURL;
 
                    // Create ObjectURL
                    var imgURL = URL.createObjectURL(file);
 
                    // Set img src to ObjectURL
                    showPicture.src = imgURL;
 
                    // Revoke ObjectURL
                    URL.revokeObjectURL(imgURL);
                }
                catch (e) {
                    try {
                        // Fallback if createObjectURL is not supported
                        var fileReader = new FileReader();
                        fileReader.onload = function (event) {
                            showPicture.src = event.target.result;
                        };
                        fileReader.readAsDataURL(file);
                    }
                    catch (e) {
                        //
                        var error = document.querySelector("#error");
                        if (error) {
                            error.innerHTML = "Neither createObjectURL or FileReader are supported";
                        }
                    }
                }
            }
        };
    }
})();

Web ブラウザのサポート

  • Camera API は現在、Android 端末上の Firefox と Google Chrome でサポートされています。
  • createObjectURL は、Firefox と Google Chrome、Internet Explorer 10 以降でサポートされています。
  • FileReader は、Firefox と Google Chrome、Internet Explorer 10 以降、Opera 11.6 以降でサポートされています。

未来

WebRTC (ブラウザ間で音声と動画、データのリアルタイム通信をサポートしています) と navigator.getUserMedia のアプローチにより、いくつもの主要な Web ブラウザでこれらの機能を目にすることができるでしょう。詳しい情報は、Firefox の Web Platform Roadmap をご覧ください。

しかし今は、写真の撮影とキャプチャを楽しんでください!