コンテンツスクリプトは、「孤立した世界」環境で実行されます。state()
メソッドをページ自体に挿入する必要があります。
chrome.*
スクリプトでいずれかのAPI を使用する場合は、この回答で説明されているように、特別なイベントハンドラーを実装する必要があります:Chrome拡張機能-Gmailの元のメッセージを取得します。
それ以外の場合、chrome.*
API を使用する必要がない場合は、<script>
タグを追加してページにすべてのJSコードを挿入することを強くお勧めします。
目次
- 方法1:別のファイルを挿入する
- 方法2:埋め込みコードを挿入する
- 方法2b:関数を使用する
- 方法3:インラインイベントを使用する
- 挿入されたコードの動的な値
方法1:別のファイルを挿入する
これは、多くのコードがある場合に最も簡単で最善の方法です。実際のJSコードを拡張機能内のファイルに含めますscript.js
。次に、コンテンツスクリプトを次のようにします(ここで説明します:Google Chomeの「アプリケーションショートカット」カスタムJavascript):
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.runtime.getURL('script.js');
s.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
注:この方法を使用する場合は、挿入されたscript.js
ファイルを"web_accessible_resources"
セクションに追加する必要があります(例)。そうしないと、Chromeはスクリプトの読み込みを拒否し、コンソールに次のエラーを表示します。
chrome-extension:// [EXTENSIONID] /script.jsの負荷を拒否します。拡張機能の外部のページでリソースをロードするには、リソースをweb_accessible_resourcesマニフェストキーにリストする必要があります。
方法2:埋め込みコードを挿入する
このメソッドは、小さなコードをすばやく実行したい場合に役立ちます。(参照:Chrome拡張機能でFacebookのホットキーを無効にする方法は?)
var actualCode = `// Code here.
// If you want to use a variable, use $ and curly braces.
// For example, to use a fixed random number:
var someFixedRandomValue = ${ Math.random() };
// NOTE: Do not insert unsafe variables in this way, see below
// at "Dynamic values in the injected code"
`;
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();
注:テンプレートリテラルはChrome 41以降でのみサポートされています。拡張機能をChrome 40で機能させる場合は、次を使用します。
var actualCode = ['/* Code here. Example: */' + 'alert(0);',
'// Beware! This array have to be joined',
'// using a newline. Otherwise, missing semicolons',
'// or single-line comments (//) will mess up your',
'// code ----->'].join('\n');
方法2b:関数を使用する
コードの大きなチャンクの場合、文字列を引用することはできません。配列を使用する代わりに、関数を使用して文字列化できます。
var actualCode = '(' + function() {
// All code is executed in a local scope.
// For example, the following does NOT overwrite the global `alert` method
var alert = null;
// To overwrite a global variable, prefix `window`:
window.alert = null;
} + ')();';
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();
+
文字列と関数の演算子がすべてのオブジェクトを文字列に変換するため、このメソッドは機能します。コードを複数回使用する場合は、コードの繰り返しを避けるための関数を作成することをお勧めします。実装は次のようになります。
function injectScript(func) {
var actualCode = '(' + func + ')();'
...
}
injectScript(function() {
alert("Injected script");
});
注:関数はシリアル化されるため、元のスコープとすべてのバインドされたプロパティは失われます!
var scriptToInject = function() {
console.log(typeof scriptToInject);
};
injectScript(scriptToInject);
// Console output: "undefined"
方法3:インラインイベントを使用する
<head>
要素を作成する前にコードを実行するなど、コードをすぐに実行したい場合があります。これは、<script>
タグを挿入することで実行できますtextContent
(方法2 / 2bを参照)。
別の方法ですが、お勧めできませんが、インラインイベントを使用します。インラインスクリプトを禁止するコンテンツセキュリティポリシーがページで定義されている場合、インラインイベントリスナーはブロックされるため、これはお勧めできません。一方、拡張機能によって挿入されたインラインスクリプトは引き続き実行されます。それでもインラインイベントを使用する場合は、次のようにします。
var actualCode = '// Some code example \n' +
'console.log(document.documentElement.outerHTML);';
document.documentElement.setAttribute('onreset', actualCode);
document.documentElement.dispatchEvent(new CustomEvent('reset'));
document.documentElement.removeAttribute('onreset');
注:このメソッドは、reset
イベントを処理する他のグローバルイベントリスナーがないことを前提としています。ある場合は、他のグローバルイベントのいずれかを選択することもできます。JavaScriptコンソール(F12)を開き、「document.documentElement.on
」と入力して、使用可能なイベントを選択します。
挿入されたコードの動的な値
場合によっては、注入された関数に任意の変数を渡す必要があります。例えば:
var GREETING = "Hi, I'm ";
var NAME = "Rob";
var scriptToInject = function() {
alert(GREETING + NAME);
};
このコードを挿入するには、変数を引数として無名関数に渡す必要があります。正しく実装してください!以下は機能しません:
var scriptToInject = function (GREETING, NAME) { ... };
var actualCode = '(' + scriptToInject + ')(' + GREETING + ',' + NAME + ')';
// The previous will work for numbers and booleans, but not strings.
// To see why, have a look at the resulting string:
var actualCode = "(function(GREETING, NAME) {...})(Hi, I'm ,Rob)";
// ^^^^^^^^ ^^^ No string literals!
解決策はJSON.stringify
、引数を渡す前に使用することです。例:
var actualCode = '(' + function(greeting, name) { ...
} + ')(' + JSON.stringify(GREETING) + ',' + JSON.stringify(NAME) + ')';
多くの変数がある場合JSON.stringify
、次のように、読みやすくするために一度使用する価値があります。
...
} + ')(' + JSON.stringify([arg1, arg2, arg3, arg4]) + ')';
player.addEventListener("onStateChange", state);