NBPF のコアアーキテクチャ概観(1)~Widget Service の位置づけ ~

皆様、こんにちは。Mobage Platfrorm シニアアーキテクトの@zigorou です。

今回は前回ご紹介した NBPF (=Next Browser Platform) とは何かの続編として NBPF と銘打ったプラットフォーム構想のコアアーキテクチャの概観について説明していきたいと思います。

今回は、従来のサービスタグの代わりとなるコミュニケーションや決済などといったMobage上の機能をUIパーツとして組み込む事が出来るようになる Widget Service について説明したいと思います。

 

Widget Service の構想とコンセプト

Proxy Server モデルで提供している、いわゆるサービスタグの仕組みに関しては画面遷移モデルが強制されている為、スマートフォンブラウザに対する UX としては、もはやマッチしていないなと考えていました。

またサービスタグで提供するような機能は実のところ、我々自身も再利用可能であるべきと考えていました。

いわゆる Server-Side API は当初、オープン化という観点でのみ再利用可能という設計としていた為、我々自身がその機能を再利用するスタイルを取っていなかったのですが、ここ数年では SOA 化と Internal API 化を推進しており、部分的に API を利用した開発を進めて来ました。

サービスタグも API で行って来たようなアプローチで疎結合な使い勝手の良い物にしたいと考え、これを Widget Service と名付けて新しく作り直す事にしました。

いわゆるサービスタグのような物は「対話的な API」として捉えた上で、再利用可能な形式としつつ、本質的な処理以外は呼び出し元に処理を丸投げするようなスタイルが良いと考えていて、本質的ではない処理とは何かを考えた時に、多くは「画面遷移をベースとしているから」と考えました。

いわゆるサービスタグの起動から終了までは以下の図のように同一タブで画面遷移ベースで起動します。

image2.png

画面の白い部分はプラットフォーム側の機能ですが、得てしてゲームのタイトルを表示したり、ゲームの画像を出すなどする必要があり、これは最終的に再び画面遷移してゲームに戻るというフローを考えるとある程度やむを得ない所です。

こう考えると画面遷移というのはある程度前後関係に応じた UX をどうしても考えざるを得ないのだなと考えた所でした。

 

一方で JavaScript SDK を用いた Widget Service との連携について図示すると次のようになります。

image3.png

プラットフォームが持つ「対話的な API」に対して呼び出しも結果の受け取りもまずは JavaScript でハンドリングするようなスタイルになっているのが分かるかと思います。

このように画面遷移ではなく iframe で overlay するなり、新しい window を window.open() で作る事によって画面遷移ではなく別のシーケンスが走ると見せる事によって、極力本質的ではない処理を排するようにしています。

こうして特定のドメインにでしか使わないアドホックな処理が機能にまぎれる事が無い様に、コアアーキテクチャとして複雑化を防止出来ないかという事をここ数年思案しながら少しずつ実践しています。このアプローチはその一つの事例です。

また実際のUXについては古いテクノロジーと新しいテクノロジーの融合になっています。

実際のUXで該当する部分は Widget Service のレスポンスを返す際になります。

コンセプトコードとしては以下のようなコードになります。

Widget Service 側がレスポンスを返す際は概ね次のような処理を行います。

function renderResponse(response, clientOriginUri) {
    // レスポンスの送信
    window.opener.postMessage(response, clientOriginUri);
    // 呼び出し元 window の focus
    window.opener.focus();
}

一方で JavaScript SDK 側がそのレスポンスを受信する際のコンセプトコードは次のようになります。

window.addEventListener(“message”, function(evt) {
    if (evt.origin != “https://widget.mobage.jp”)
        return;

    var response = evt.data;
    // Widget Service の window を閉じる
    evt.source.close();
    callback(response);
}, false);

これによって、Native Application がアプリ間連携する際の UX に近いものがタブブラウザのタブ間で実現されています。つまり、

  • 古い技術

    • window.open()

    • window.close()

    • window.focus()
  • 新しい技術

    • window.postMessage()

これらの組み合わせによって、異なるタブ間で連携を行うというコンセプトになっています。window.open() メソッドの target 属性も上手く使う事によって異なる Web Application 間での連携をメッセージングベースで行うという事も上手く実現していきたいと考えています。

また似たような仕組みではあるのですが、呼び出し元に対して Push 型で情報を通知するのが postMessage() だとすると、呼び出し元に復帰した際に状態を取りに行く形式を Pull 型であると見なせるかと思いますが、Widget Service では一部この Pull 型を取っている箇所があります。(必要であれば拡充するつもりではありますが)

この部分は Page Visibility API (とその Polyfill) を利用しています。

 

Widget Service とセキュリティ

JavaScript から起動される Widget Service に、

  • iframe で overlay する方式 (display=touch_popup)

  • window.open() で新しいタブを開く方式 (display=touch)

の二つの形式があることを、しれっと述べた所ですがこの二つの形式は単なる使い勝手の話だけではなく、セキュリティを意識した観点で使い分けています。主に気をつけなければならない点は、iframe を利用した際にはざっと思いつくだけでも次のような事を気にする必要があります。

  • フィッシング

    • これは Mobage が提供する対話形式の画面を模した機能を overlay させる事によってユーザーを騙し、不正にデータを入手するような行為です

    • これはユーザーがアクセスしている機能を提供する url をロケーションバーで確認出来ない事が問題の一つだと言えます

  • クリックジャッキング

    • 同様に対話形式の画面への入力を、その画面の前面に画面を重ねる事によって帆捕捉し、やはり不正にデータを入手するような行為です

  • 3rd party cookie

    • iframe の場合は 3rd party cookie と見なされる為に、意図した Set-Cookie が行われないケースがあります

などです。

つまり次のような結論が言えます。

  • ユーザーに大事な情報の入力を行わせる機能を iframe で提供しない

  • ステート管理の為の Set-Cookie を行う機能(例えばログインフォーム)を iframe で提供しない

この条件に当てはまる機能に関しては新しいタブを開き、ユーザーがアクセスしている url を特に何もせずとも確認出来る状態にしておかねばならないと考えて、機能別に使い分けております。

単に見た目が良いからだとか、シンプルだとかでセキュリティを疎かにする例をしばしば見ますが、こういう部分はエンジニアとしては譲れない点です^^;


Widget Service と API の位置づけ

Widget Service と API ですが Mobage Connect (OAuth 2.0/OpenID Connect Server) と JavaScript SDK によってどのような関連性があるかについて図示したのが以下になります。

image4.png

この図から見ると JavaScript SDK から見ると Mobage Connect との認証連携を行った後に、Mobage プラットフォームに対するシステム連携手段に Widget Service と API Server という二つの機能が提供されていると見る事が出来ると思います。

そのうちの一つである「対話的な API」である Widget Service ですが、一般的な RESTful API とは違って通常は次のような違いがあると思います。

image5.png

API へのアクセス権限である OAuth 2.0 のアクセストークンの管理を行うのと同様に、Widget Service は Mobage Connect とセッション連携し、Mobage Connect のステートに追従するような仕組みになっています。この辺りの仕組みについてもいずれ機会があれば触れたいと思います。

体裁はともかくして、対話とはキャッチボールが何度か行われる行為だとするならば、ステートフルな状態を維持し続けるのが自然であり、今回は JavaScript SDK という事でプレゼンテーションが HTML と JavaScript で行うという事からレスポンス形式を message イベントによるメッセージング形式としましたが、これがもし Native で提供するとなるならば、おそらくは HAL (Hypermedia Application Language) と Objective-C/Java などで組み合わせて、サーバーサイドのコンセプトは変えないようなスタイルを取るんじゃないかと思います。

 

まとめ

だいぶ突っ込んだ話となってしまいましたが、JavaScript SDK から見た場合に一つのコンポーネントに過ぎない Widget Service だけでもシステム設計や UX の観点からコンセプトがあり、それを実現するテクノロジーがある事がご理解頂けたのではないかと思っています。

私は何かのプロジェクトをやる際に、やるべき事を定義する事や、満たさねばならない事を満たすのは当たり前の事だと考えています。エンジニアである限りはその上で技術的にも面白く、理に適った物を作りたいと考えております。こうする事によって現場のエンジニアも、ただ要件だけをこなすのではなく、システム面での思想をどのようにコードに落とし込んでいくかという「こだわりポイント」を作って行く事が出来ると思っています。


JavaScript SDK をご利用頂く際に、ちょっとこの話を思い出して頂けると幸いです。