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. で定義する関数が存在するかどうかにより、
- 存在する場合: 拡張機能として動作しているとみなして当該関数を呼び出し、ユーザーオプションを取得して使用
- 存在しない場合: ユーザースクリプトとして動作しているとみなし、デフォルト値を使用