Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Content scripts are executed in an <a href="https://developer.chrome.com/extensions/content_scripts#execution-environment" rel="noreferrer">"isolated world" environment</a>. You have to inject your <code>state()</code> method into the page itself.</p> <p>When you want to use one of the <code>chrome.*</code> APIs in the script, you have to implement a special event handler, as described in this answer: <a href="https://stackoverflow.com/a/9636008/938089?chrome-extension-retrieving-gmails-original-message">Chrome extension - retrieving Gmail's original message</a>.</p> <p>Otherwise, if you don't have to use <code>chrome.*</code> APIs, I strongly recommend to inject all of your JS code in the page via adding a <code>&lt;script&gt;</code> tag:</p> <h1>Table of contents</h1> <ul> <li>Method 1: Inject another file</li> <li>Method 2: Inject embedded code</li> <li>Method 2b: Using a function</li> <li>Method 3: Using an inline event</li> <li>Dynamic values in the injected code</li> </ul> <h2>Method 1: Inject another file</h2> <p><em>This is the easiest/best method when you have lots of code.</em> Include your actual JS code in a file within your extension, say <code>script.js</code>. Then let your content script be as follows (explained here: <a href="https://stackoverflow.com/a/9310273/938089?google-chome-application-shortcut-custom-javascript">Google Chome “Application Shortcut” Custom Javascript</a>):</p> <pre><code>var s = document.createElement('script'); // TODO: add "script.js" to web_accessible_resources in manifest.json s.src = chrome.extension.getURL('script.js'); s.onload = function() { this.remove(); }; (document.head || document.documentElement).appendChild(s); </code></pre> <p><strong>Note: If you use this method, the injected <code>script.js</code> file has to be added to the <a href="https://developer.chrome.com/extensions/manifest/web_accessible_resources.html" rel="noreferrer"><code>"web_accessible_resources"</code></a> section</strong> (<a href="https://stackoverflow.com/a/10529675/938089?google-chrome-extension-script-injections">example</a>). If you do not, Chrome will <strong>refuse</strong> to load your script and display the following error in the console:</p> <blockquote> <p>Denying load of chrome-extension://[EXTENSIONID]/script.js. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension. </p> </blockquote> <h2>Method 2: Inject embedded code</h2> <p>This method is useful when you want to quickly run a small piece of code. (See also: <a href="https://stackoverflow.com/a/8994454/938089?how-to-disable-facebook-hotkeys-with-chrome-extension">How to disable facebook hotkeys with Chrome extension?</a>).</p> <pre><code>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(); </code></pre> <p>Note: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals" rel="noreferrer">template literals</a> are only supported in Chrome 41 and above. If you want the extension to work in Chrome 40-, use:</p> <pre><code>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 -----&gt;'].join('\n'); </code></pre> <h2>Method 2b: Using a function</h2> <p>For a big chunk of code, quoting the string is not feasible. Instead of using an array, a function can be used, and stringified:</p> <pre><code>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(); </code></pre> <p>This method works, because the <code>+</code> operator on strings and a function converts all objects to a string. If you intend on using the code more than once, it's wise to create a function to avoid code repetition. An implementation might look like:</p> <pre><code>function injectScript(func) { var actualCode = '(' + func + ')();' ... } injectScript(function() { alert("Injected script"); }); </code></pre> <p>Note: Since the function is serialized, the original scope, and all bound properties are lost!</p> <pre><code>var scriptToInject = function() { console.log(typeof scriptToInject); }; injectScript(scriptToInject); // Console output: "undefined" </code></pre> <h2>Method 3: Using an inline event</h2> <p>Sometimes, you want to run some code immediately, e.g. to run some code before the <code>&lt;head&gt;</code> element is created. This can be done by inserting a <code>&lt;script&gt;</code> tag with <code>textContent</code> (see method 2/2b).</p> <p>An alternative, <strong>but not recommended</strong> is to use inline events. It is not recommended because if the page defines a Content Security policy that forbids inline scripts, then inline event listeners are blocked. Inline scripts injected by the extension, on the other hand, still run. If you still want to use inline events, this is how:</p> <pre><code>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'); </code></pre> <p>Note: This method assumes that there are no other global event listeners that handle the <code>reset</code> event. If there is, you can also pick one of the other global events. Just open the JavaScript console (F12), type <code>document.documentElement.on</code>, and pick on of the available events.</p> <h2>Dynamic values in the injected code</h2> <p>Occasionally, you need to pass an arbitrary variable to the injected function. For example:</p> <pre><code>var GREETING = "Hi, I'm "; var NAME = "Rob"; var scriptToInject = function() { alert(GREETING + NAME); }; </code></pre> <p>To inject this code, you need to pass the variables as arguments to the anonymous function. Be sure to implement it correctly! The following will <strong>not</strong> work:</p> <pre><code>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! </code></pre> <p>The solution is to use <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify" rel="noreferrer"><code>JSON.stringify</code></a> before passing the argument. Example:</p> <pre><code>var actualCode = '(' + function(greeting, name) { ... } + ')(' + JSON.stringify(GREETING) + ',' + JSON.stringify(NAME) + ')'; </code></pre> <p>If you have many variables, it's worthwhile to use <code>JSON.stringify</code> once, to improve readability, as follows:</p> <pre><code>... } + ')(' + JSON.stringify([arg1, arg2, arg3, arg4]) + ')'; </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload