$git clone https://github.com/GoogleChrome/chrome-app-samples.git
今回は上のコマンドでダウンロードしたサンプルアプリ群の中から、「identity」というプロジェクトを参考にした。
Packaged Apps ではOAuth2認証に Chrome Identity API というのを使う。
Googleアカウント以外の認証にも使えるが、今回はなるべく理解を容易にするためにGoogleアカウント認証のサンプルのみ。
これはログインしたGoogleアカウントに紐づくユーザ名を画面に表示するだけの超簡単なサンプルアプリである。
要する作業は以下の通りとなる。
(1)manifest.jsonにpermissionsを与える。
(2)既にインストールされているアプリのmanifest.jsonから "key"項目をコピーして、ソースのmanifest.jsonへペースト。
これがどういうことかというと、ソース上のmanifest.jsonのテキトーな"key"もインストール後は適切な値に変わってるので、正式にリリースするときはこれを使ってねってこと(だと思う)。
ちなみにアプリがインストールされている場所は、
Windows7の場合:
C:/Users/<USER>/AppData/Local/Google/Chrome/User Data/Default/Extensions
MacOSの場合:
~/Library/Application Support/Google/Chrome/Default/Extensions
(3)Client IDを取得する。
Google APIs Consoleに行って Client ID を新規発行する。
(4)取得したClient IDをmanifest.jsonへコピペ。
(5)以上でAuth Token が取得可能。ログインが必要なGoogle APIへアクセスできる。
以上。
ではmanifest.jsonから見てみよう。
{ "name": "Identity API", "version": "1", "manifest_version": 2, "minimum_chrome_version": "23", "key": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh", "app": { "background": { "scripts": ["main.js"] } }, "permissions": ["experimental"], "oauth2": { "client_id": "503955758982.apps.googleusercontent.com", "scopes": ["https://www.googleapis.com/auth/userinfo.profile"] } }見てのとおり、 key には"abcdefg...."とテキトーな文字列が入力されている。
permissionsは権限を設定、oauth2.client_idにはGoogle APIs Consoleで取得したClient IDを、oauth2.scopesには利用するGoogle APIをURLを登録する。
次は画面HTMLだ。
index.html
<html> <head> <title>Identity API Sample App</title> <script src="identity.js"></script> </head> <body> <div id="user_info"></div> <button id="signin" style="display:none">Sign in</button> </body> </html>「Sign in」ボタンだけの簡単な画面だ。
実際の処理がコーディングされている identity.js をscriptタグで読み込んでいる。
まー特に説明するまでもないだろう。
次はmain.js
chrome.app.runtime.onLaunched.addListener(function() { chrome.app.window.create('index.html', { "bounds": { "width": 1024, "height": 768 } }); });Packaged Appsの画面描画の際の振る舞いが記述されている。
このファイルはmanifest.jsonのapp.background.scriptsで定義されている。
最後は最も重要な identity.js だ。
function onImageFetched(e) { var elem = document.getElementById('user_info'); if (!elem) return; if (this.status != 200) return; var imgElem = document.createElement('img'); imgElem.src = window.webkitURL.createObjectURL(this.response); elem.appendChild(imgElem); } function fetchImageBytes(user_info) { if (!user_info || !user_info.picture) return; var xhr = new XMLHttpRequest(); xhr.open('GET', user_info.picture, true); xhr.responseType = 'blob'; xhr.onload = onImageFetched; xhr.send(); } function populateUserInfo(user_info) { var elem = document.getElementById('user_info'); if (!elem) return; var nameElem = document.createElement('div'); nameElem.innerHTML = "<b>Hello " + user_info.name + "</b>"; elem.appendChild(nameElem); fetchImageBytes(user_info); } function onUserInfoFetched(e) { if (this.status != 200) return; console.log("Got the following user info: " + this.response); var user_info = JSON.parse(this.response); populateUserInfo(user_info); } function onGetAuthToken(auth_token) { var userInfoDiv = document.getElementById('user_info'); if (!auth_token) { var signinButton = document.createElement('button'); signinButton.id = 'signin'; signinButton.appendChild(document.createTextNode('Sign In')); signinButton.onclick = getUserInfoInteractive; userInfoDiv.appendChild(signinButton); return; } // Remove the sign in button if it exists. if (userInfoDiv.firstChild) { userInfoDiv.removeChild(userInfoDiv.firstChild); } // Use the auth token to do an XHR to get the user information. var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json'); xhr.setRequestHeader('Authorization', 'Bearer ' + auth_token); xhr.onload = onUserInfoFetched; xhr.send(); } function getUserInfo() { chrome.experimental.identity.getAuthToken({ 'interactive': false }, onGetAuthToken); } function getUserInfoInteractive() { chrome.experimental.identity.getAuthToken({ 'interactive': true }, onGetAuthToken); } window.onload = getUserInfo;処理の流れをおおまかに書くと、
1.window.onload時にgetUserInfo()が呼ばれる。
2.chrome.experimental.identity.getAuthToken()がinteractive=false(つまり対話無しログインモード)で呼ばれる。
3.AuthToken取得時の非同期処理onGetAuthToken()が呼ばれる。
4.AuthTokenが取得できなければログイン画面へ。AuthTokenが取得出来たら(つまりログイン状態なら)ユーザ情報取得APIをXMLHttpRequest(xhr)で叩く。
5.xhr.onloadに登録されたonUserInfoFetched()でユーザ情報取得APIからのレスポンスJSONを受け取る。
6.受け取ったユーザ情報JSONをパースして画面へ表示。
7.ユーザ情報にプロフィール画像があればそれも描画。
となる。
念のために書いておくが、このサンプルアプリはChromeへインストールしないと動作しない。アプリのインストール方法は以前のエントリをご参照あれ。
参考
Identify User - Google Chrome chrome-app-samples/Identity at master・GoogleChrome/chrome-app-samples・GitHub
関連エントリ
【Chrome】Packaged Apps アプリをHelloWorld【Google】
スマホOSの主導権争いの行方