Google Chrome Extensions Manifest Version 2 対応メモ


さてそろそろ Pediator の辞書でも最新化しますかねと思い、
Wikipedia からタイトルリストを取得してごにょごにょやっていると、何だかちゃんと動かない。

あれー Chrome の仕様が変わったんかいなと思って調べてみると、いつの間にか Google Chrome Extension の
Manifest Version 2 なるものが出ていました。え、いつの間に?

そんなアナウンスあったっけなーとメールボックスを漁ってみると、2012/07/04 に来てました。orz

Manifest_Version 1: Manifest Version 1 has been deprecated since Chrome 18, and when Chrome 21 hits stable in mid-August the Chrome Web Store will no longer accept new items with manifest_version 1. Converting to manifest_version 2 should be very simple for the majority of developers, and we encourage all developers to update their extensions and packaged apps as soon as possible. Review our deprecation schedule to determine when to update your items in the store.

だってさ。今はもう Chrome23 ですがな。

仕方ないので Pediator と A HREF++(あ・は~ふ)を Manifest Version 2 に対応しました。
その時の対応メモを書いておきます。

Manifest Version 1 と Manifest Version 2 の違い

一応 このページ にまとまってるのですが、いまいち分かりにくいので、
とりあえず Pediator で修正を入れたものを列挙すると

  • manifest.json のバージョン表記
  • background_page の廃止
  • パッケージ同梱リソースへのアクセス制限
  • Content Security Policy (CSP) の導入
    • eval の使用禁止
    • インライン Javascript の使用禁止
  • chrome.tabs.getSelected がいつの間にか deprecated 扱いに

あとは Browser action と Page action にも変更がありましたが、影響はありませんでした。
とりあえず上から見ていきますかね。

manifest.json のバージョン表記

これは manifest.json にバージョン表記を追加するだけです。

  "manifest_version": 2,

これで動くだろーと思ったらこの一行足しただけで挙動がガラッと変わりやがった。うへー。

background_page の廃止

manifest.json に指定する background_page は、background になり script と page のプロパティを持つようになりました。

■ Before

  "background_page": "background.html",

■ After

  "background": {
    "scripts":["background.js"]
  },

これはもともとの background.html が Javascirpt しか含まれていなかった為、拡張子を変更するだけで良かったパターンです。
もし background.html に静的コンテンツとスクリプトの両方が含まれていた場合は、scripts と page の二つに
分割しないといけないんじゃないかな。

パッケージ同梱リソースへのアクセス制限

地味にはまったのがこれ。
パッケージに含めたイメージファイルには chrome.extension.getURL でその特殊パスを取得できますが、
ページに埋め込んだリンクからその URL を指定しても画像が表示されない。
何だろーと思ってたら、manifest.json に web_accessible_resources の指定が必要になったようです。

  "web_accessible_resources": [ "img/loading.gif",
                                "img/pediatorworking.png",
                                "img/pediatorpercent.png",
                                "img/pediatorClose16.png",
                                "img/pediator_menubar_close.png",
                                "img/pediator_menubar_open.png",
                                "img/pediatorBackOn24.png",
                                "img/pediatorForwardOn24.png",
                                "img/pediatorClose24.png",
                                "css/pediator.css" ],

Content Security Policy (CSP) の導入

これがわりと厄介でした。
詳細は ここのページ にありますが、結構厳しい。

・eval の使用禁止

Perl じゃあるまいし、eval なんて使わないだろ普通、と思ってたら、setTimeout が eval していました。
なん、、、だと、、?

  pediatorMenuController.timer = setTimeout("pediatorMenuController.ScrollPediatorMenu(" + from + "," + to + ",'" + flag + "')",20);

こんなの。
一応動くけど何か変だよなと思ってたら eval だったのかこれ。

あれ、んじゃ setTimeout に渡す関数に変数を渡したい時ってどうすんのよ?
と少し悩んだのですが、結局こうなりました。

  pediatorMenuController.timer = setTimeout(function(){pediatorMenuController.ScrollPediatorMenu(from, to, flag)},20);

なるほど。無名関数にすれば良いのね。

・インライン Javascript の使用禁止

オプションページで使いまくってたから地味に辛かった。
HTML タグの CENTER を禁止されたような気分だ。

■ Before
options.html

<body onload="restore_options();" onscroll="setPosition();" onresize="setPosition();">

■ After
pediator_options.js

window.addEventListener("load", restore_options);
window.addEventListener("resize", setPosition);
window.addEventListener("scroll", setPosition);

まあ、これは良いとして。

■ Before
options.html

<input type="radio" name="pediator-segment" value="1"> 短い → <span class="jp-irts-pediator" onclick="pediator_demo(this);">ストロベリー</span> 
<span class="jp-irts-pediator" onclick="pediator_demo(this);">・</span> <span class="jp-irts-pediator" onclick="pediator_demo(this);">フィールズ</span> 
<span class="jp-irts-pediator" onclick="pediator_demo(this);">・</span> <span class="jp-irts-pediator" onclick="pediator_demo(this);">フォーエバー</span><br>

■ After
options.html

<input type="radio" name="pediator-segment" value="1"> 短い → <span class="jp-irts-pediator" id="pediator_demo-short">ストロベリー</span> 
<span class="jp-irts-pediator" id="pediator_demo-short-dot">・</span> <span class="jp-irts-pediator" id="pediator_demo-short-fields">フィールズ</span> 
<span class="jp-irts-pediator" id="pediator_demo-short-dot2">・</span> <span class="jp-irts-pediator" id="pediator_demo-short-forever">フォーエバー</span><br>

pediator_options.js

document.getElementById("pediator_demo-short").addEventListener("click", function(){pediator_demo(document.getElementById("pediator_demo-short"))});
document.getElementById("pediator_demo-short-dot").addEventListener("click", function(){pediator_demo(document.getElementById("pediator_demo-short-dot"))});
document.getElementById("pediator_demo-short-fields").addEventListener("click", function(){pediator_demo(document.getElementById("pediator_demo-short-fields"))});
document.getElementById("pediator_demo-short-dot2").addEventListener("click", function(){pediator_demo(document.getElementById("pediator_demo-short-dot2"))});
document.getElementById("pediator_demo-short-forever").addEventListener("click", function(){pediator_demo(document.getElementById("pediator_demo-short-forever"))});

くっ
これはめんどくさい。

chrome.tabs.getSelected がいつの間にか deprecated 扱いに

ここらへんに書いてあった けど、気づきませんって。
一応 chrome.tabs.getSelected もまだ動くんだけど、何か気になるので直しておきました。
代わりに chrome.tabs.query を使いますが、今開いてる tab の url くらい何か簡単に取得できたらいいのにね。

■ Before

// 拡張機能ページ、オプションページ以外(URLがchromeから始まるページは除外)
chrome.tabs.getSelected(null,
  function(currentTab) {
    if ( currentTab.url.search(/^chrome/) ) {
      chrome.browserAction.setIcon({path:pediator_icon_on});
      chrome.browserAction.setBadgeBackgroundColor({color:[255, 0, 0, 200]});
      pediator_status.pediator_page_status     = "on";
      pediator_status.pediator_automode_status = "on";

      chrome.tabs.executeScript(null, {code: "pediatorInsert.insertMenu()",allFrames: false});
      chrome.tabs.executeScript(null, {file: "js/pediatorStart.js",allFrames: true});
    } else {
      alert("特殊ページでは動作しません");
    }
  }
);

■ After

// 拡張機能ページ、オプションページ以外(URLがchromeから始まるページは除外)
chrome.tabs.query({active: true},
  function(current) {
    // search は文頭からマッチすると 0(偽)を返す。無かったら -1(真)
    if ( !current[0].url.search(/^chrome/) ) {
      alert("特殊ページでは動作しません");
    } else if ( !current[0].url.search(/^https\:\/\/chrome\.google\.com/) ) {
      alert("Chromeウェブストアでは動作しません");
    } else {
      chrome.browserAction.setIcon({path:pediator_icon_on});
      chrome.browserAction.setBadgeBackgroundColor({color:[255, 0, 0, 200]});
      pediator_status.pediator_page_status     = "on";
      pediator_status.pediator_automode_status = "on";
      chrome.tabs.executeScript(null, {code: "pediatorInsert.insertMenu()",allFrames: false});
      chrome.tabs.executeScript(null, {file: "js/pediatorStart.js",allFrames: true});
    }
  }
);

というわけで、辞書を最新化しようと思っただけなのに結構時間食っちゃったという話でした。

Google Chrome Extensions Manifest Version 2 対応メモ」への2件のフィードバック

  1. 名無し

    setTimeout に渡す関数に変数を渡したい時は第3引数以降に記述します

    返信
  2. murachika 投稿作成者

    > setTimeout に渡す関数に変数を渡したい時は第3引数以降に記述します
    ふお、マジですか。
    setTimeout って第三引数以降があったんですね。知らなかった。
    ありがとうございますー。

    返信

コメントを残す

メールアドレスが公開されることはありません。