風柳メモ

ソフトウェア・プログラミング関連の覚書が中心。

Google Chromeで、スクリプトが拡張機能として動作しているかどうかを判別するには?

furyu.hatenablog.com
等では、単体でユーザースクリプト(Greasemonkey/Tampermonkey)としても動作するスクリプトを、Google Chrome 拡張機能用として転用している。

このとき、

  • ユーザースクリプトとして動作する際には、スクリプト内で定義したデフォルト値を使用
  • 拡張機能として動作する際には、ユーザーが設定可能なオプション値を優先的に使用

という条件を満たさねばならず、そうすると、スクリプト自身が「今、自分はどちらとして動作しているか」を判別する必要が出てくる。

これをお手軽に知る方法はないか、検索をかけてみたのだけれど、探し方が悪いのか、なかなかしっくりくる方法が見つからない。
そこで、苦肉の策として以下のような方法を用いているのだが、もし読者の方でより簡便な方法をご存知の方がおられれば、ご教示願いたい。

1. manifest.json にて、初期化用スクリプトとメインスクリプトを、別々のタイミングで起動

"content_scripts" : [
    {
        "matches" : [ "https://twitter.com/*" ],
        "js" : [ "js/init.js" ],
        "run_at" : "document_start"
    },
    {
        "matches" : [ "https://twitter.com/*" ],
        "js" : [ "js/main.js" ],
        "run_at" : "document_end"
    }
],
"background" : {
    "scripts" : [ "js/background.js" ]
}

例の中の init.js が初期化用(document_start: DOM構築開始時に起動)で、main.js がユーザースクリプトを兼ねたメインスクリプト(document_end: DOM構築完了時に起動)。

なおバックグラウンドスクリプト(background.js)では、chrome.runtime.onMessage.addListener() で設定したリスナーにより、localStorageから取り出したユーザーオプション値を返す処理を定義しておく。

2. 初期化用スクリプト(init.js)内にて、ユーザーが設定したオプション値を取得する関数を定義

window.init_extension = function( callback ) {
    /* 任意の前処理 */
    chrome.runtime.sendMessage( {
        /* background.js で規定の処理を呼び出すためのパラメータ */
    }, function ( response ) {
        var user_options;
        /* response を解析して、ユーザーオプションを取得する処理 */
        callback( user_options );
    } );
};

background.js に対してchrome.runtime.sendMessage()にてメッセージを送信し、必要なユーザーオプションを取得した上で、コールバック関数に渡してやる関数を定義しておく。

3. メインスクリプト(main.js)内にて、2. の関数が定義されているかどうかで、処理を振り分け

if ( typeof window.init_extension == 'function' ) {
    // 拡張機能として動作
    window.init_extension( function( user_options ) {
        main( user_options ); // ユーザーオプションを設定
    } );
}
else {
    // ユーザースクリプトとして動作
    main(); // オプション未指定→デフォルト値を使用
}

2. で定義する関数が存在するかどうかにより、

  • 存在する場合: 拡張機能として動作しているとみなして当該関数を呼び出し、ユーザーオプションを取得して使用
  • 存在しない場合: ユーザースクリプトとして動作しているとみなし、デフォルト値を使用