$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の主導権争いの行方