Chrome Extension

Google ChromeのExtension作成メモ

基本的に自分がつくったextensionに必要な箇所のメモ

Overview

http://code.google.com/chrome/extensions/docs.html

  • HTML, CSS, JavaScript, 画像をzipでバンドルするという非常にWidgetに近いアーキテクチャーで
  • XMLHttpRequestやHTML5 local storageなどを使って機能を作成でき
  • さらにChromeからは browser actionsやpage actions、bookmarks、tabsなどの機能が提供される

ブラウザアクション

  • ブラウザに常駐するextensionは基本的にbackgroundページ(html)というのを持つ
  • さらにpopupを表示するなど別のページ(html)を持つことができ、別ページからbackgoundページの関数を実行したりできる
  • popupで表示するページはmanifestにてブラウザアクションを定義することで呼び出せる
    • {
        "name": "My extension",
        ...
        "browser_action": {
          "default_icon": "images/icon19.png", // required
          "default_title": "Google Mail",      // optional; shown in tooltip
          "popup": "popup.html"                // optional
        },
        ...
      }

つまりbackgounrd.htmlでアイコンで状態だけを表示しておいて、ユーザの呼び出し(クリック)によって詳細な情報だけをpopupで表示するということが extensionのひとつのやり方になると思われる。

browser-action.png

ページでの連携

popup, option -> background

  • extensionにとってbackgroundは親玉でありで以下で取れる
    var background = chrome.extension.getBackgroundPage();
    • これでとれるのはbackground.htmlのwindowオブジェクトなので例えばbackground.htmlにあるグローバルな関数にアクセスするには以下のようにできる
      • background.html
        <script>
        function foo() { alert("bar"); }
        </script>
      • popup.html
        <script>
        var background = chrome.extension.getBackgroundPage();
        background.foo();
        </script>
    • Google Calendar for Todayでは機能を別のオブジェクトにまとめており面倒くさいので以下のようにしてアクセスさせている
      • background.html
        <script>
        (function($){
        	$(document).ready(function() {
        		var w = Blz.Widget, 
        			gcal = Blz.Google.Calendar,
        			app = MyGoogleCal.Application;
        		// ....
        		window.Blz = Blz;
        		window.MyGoogleCal = app;
        	});
        })(jQuery);
        </script>
      • popup.html
        <script>
        var background = chrome.extension.getBackgroundPage(), Blz = background.Blz, w = Blz.Widget, app = background.MyGoogleCal
        </script>

background > others

  • 他のページはbackgoundのようにgetPopupPageとかは用意されていないのでsendRequestを使う、Google Calendar for Todayではbackgoundが予定を取得してpopupへ更新を支持するために以下のようにしている
    • background.html
      <script>
      function update() {
      	chrome.extension.sendRequest({update:true});
      }
      </script>
    • popup.html
      <script>
      chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
      	if (request.update) update();
      });
      function update() {
      	...
      }
      </script>

ページアクション

  • Chromeが開いているページに対して機能を提供する場合は、background.htmlを持たないでページアクションをつかって機能を提供できる
    • なおmanifestにはブラウザアクションとページアクションの両方を指定することはできない
    • page-action.png

Content Scripts

  • manifestにcontent_scriptsを設定することで既存のHTMLにスクリプトをつっこんで操作することができる
    {
      "name": "My extension",
      ...
      "content_scripts": [
        {
          "matches": ["http://www.google.com/*"],
          "css": ["mystyles.css"],
          "js": ["jquery.js", "myscript.js"]
        }
      ],
      ...
    }
    • matchesにどのURLのページにつっこむか、css,jsにextensionのどのファイルを突っ込むかを指定する
    • さらにrun_atにはいつスクリプトを実行するかを指定できる、指定できる値には以下のようなものがある
      • document_start: DOMが作成される前
      • document_end: DOMが作成されたあと
      • document_idle(デフォルト): window.loadの後

manifest

XMLHttpRequest

  • XMLHttpRequestで別ドメインにアクセスする場合はそのURLを予めmanifest.jsonのpermissionへ書いておく必要がある
{
  "name": "My extension",
  ...
  "permissions": [
    "http://www.google.com/"
  ],
  ...
}

設定について

  • Extensionは設定ページを持つことができてmanifest.jsonにoptions_pageというのを指定してhtmlをつくればいい
    {
      "name": "Google Calendar for Today",
      ...
      "options_page": "options.html",
      ...
    }
  • デザインについてはhtmlなので単純にinput要素などつくればよい
  • データの読み書きについてはHTML5のlocalStorageで行う
  • localStorage(Storage interface)はgetItemやsetItemもあるが属性でのアクセスもできるので以下のようにも書ける
    localStorage["favorite_color"] = color;
     var favorite = localStorage["favorite_color"];
  • window.loadや保存ボタンのclickイベントをハンドリングするなどしてlocalStoragに読み書きするのがよいだろう

TODO: localStorageのlifetimeについて理解する

国際化について

  • _locales/localeCode/messages.jsonというファイルを作成すれば良い
  • 開発中のunpackageなextensionの場合、messages.jsonがおかしいと容赦なくChromeから削除されてしまう。再度起動するためにいちいちディレクトリを選択しないといけないのであらけじめjsonの検証ツールでチェックしておくのがよいと思われる
  • 日英なら_locales/en/messages.json, _locales/ja/messages.jsonを準備する
    • i18n-hierarchy.gif
  • 文言はkey-valueの形で設定するらしいが文言自体はvalue["message"]に設定する
  • パラメータを埋め込みたい場合は、パラメータに名前をつけて文言の中に$で囲い埋め込む、でvalue["placeholders"][key]["content"]へ変数の何番目に指定してもらうかを$1とかで入れる
    •   "hello": {
          "message": "Hello, $USER$",
          "description": "Greet the user",
          "placeholders": {
            "user": {
              "content": "$1",
              "example": "Cira"
            }
          }
        },
  • message.jsonで指定した文言をつかう場合、manifestなどでは__MSG_messagename__で指定する、javascriptからはchrome.i18n.getMessageを使う
    • chrome.i18n.getMessage("messagename")
    • パラメータを渡す場合は第二引数に配列で渡す
       var message = chrome.i18n.getMessage("click_here", ["string1", "string2"]);

開発方法

  1. 適当なフォルダにファイル一式を置く
  2. Chromeの拡張機能を選択し、デベロッパーモードというのを有効にする
  3. パッケージ化されていない拡張機能を読み込みます...からフォルダを選択
  4. 実行中はアクティブな閲覧数を確認:からDeveloper Toolsを起動する
    • Consoleよりログが確認できる
      • Consoleにログを出すにはjavascriptでconsole.log('')を使う
    • Storageから保存したデータを参照できる

トラブルメモ

messages.jsonがおかしいとextensionが読み込めない

  • messages.jsonというファイルがちゃんとないと読み込めない
  • default_localeをmaniest.jsonに指定していないと読み込めない。

ポップアップでaタグのリンクが開けない

どうやらtarget=_blankがいるらしい。

外部ファイルを変更しても動作が変わらない(キャッシュされている?)

コードビハインドを利用するためにcssやjsを別ファイルで管理してたら、たまに変更が反映されなくなった。extensionを再読み込みしたり、キャッシュを消したりChromeを再起動したりしてたが解決したり、解決しなかったり。(ファイルにエラーがあると更新されない?) よくわからないので結局htmlにstyleもscriptも書くようにした。

公開されているextensionのソースを読む技

  • 自分の環境(Windows Vista以降)ではインストールしたextensionたちはUserAppDataにはいっていた
    C:\Users\makoto_kw\AppData\Local\Google\Chrome\User Data\Default\Extensions
Powered by PukiWiki

No Trackbacks

Trackback URL:

2 Comments

  1. yotaroo
    February 26th, 2010 10:39 AM | #1

    Chrome extensionのWorld Clocksを作ったmakoto_kwと同一人物ですか?

    サイズを変えるときの挙動が変。

  2. February 26th, 2010 10:44 AM | #2

    同一人物っす。なんだか怪しいことは認識してますがまだpopupのサイズ変更をよくわかってないので保留。

Comments