Content Script Injection: Difference between revisions

From GreaseSpot Wiki
Jump to navigationJump to search
(add @require section)
(Update for 4.0)
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
Very similar to the [[location hack]] but without either the <code>void()</code> to avoid navigation or escaping issues is the content script injection method.
<div style="border: 3px dotted; color: red; font-size: 1.2em; padding: 0.5em; margin: 1em; text-align: center">
Simply put, Greasemonkey scripts have safe and easy access to modify the DOM of the page, so they can add a <script> tag with any contents.
Warning: The contents of this page are not accurate when used with Greasemonkey 4.0.
</div>


This is, then, in effect an <code>eval()</code> function that runs code in the content page scope, rather than the Greasemonkey sandbox.
For scripts which <code>@grant</code> any privileged APIs, these methods are provided in a privileged scope which is intentionally isolated from the content page.
The same functionality is available by calling <code>window.eval()</code> to explicitly target the content window scope for execution.
(Note that a bare <code>eval()</code> executes in the script scope.)


<pre class='sample'>
<pre class='sample'>
function contentEval(source) {
// ==UserScript==
  // Check for function input.
// @name        Content Script Example, grant none
  if ('function' == typeof source) {
// @grant      none
    // Execute this function with no arguments, by adding parentheses.
// ==/UserScript==
    // One set around the function, required for valid syntax, and a
    // second empty set calls the surrounded function.
    source = '(' + source + ')();'
  }


  // Create a script node holding this  source code.
// Because I am a "@grant none" script, I operate right in the content scope.
  var script = document.createElement('script');
// I can call functions defined by the page with no problems.
  script.setAttribute("type", "application/javascript");
var result = functionFromContentScope();
  script.textContent = source;


  // Insert the script node into the page, so it will run, and immediately
// Similarly, I can export values or functions to that scope for it to call.
  // remove it to clean up.
window.someVariable = 'someValue';
  document.body.appendChild(script);
  document.body.removeChild(script);
}
</pre>
</pre>


This function can be called with a simple string, which it will run:
<pre class='sample'>
// ==UserScript==
// @name        Content Script Example, privileged grant
// @grant      GM_log
// ==/UserScript==


<pre class='sample'>contentEval("alert('running in the page')");</pre>
// Because I am *not* a "@grant none" script, I operate in my own private,
// privileged scope.  I can call functions defined by the page only by
// explicitly referencing the window:
var result = window.eval('functionFromContentScope();')


Or it can accept a function, which it will turn into a string and run.
// Similarly, I can export values or functions to that scope for it to call.
 
window.eval("window.someVariable = 'someValue';");
<pre class='sample'>contentEval( function() { alert("This function is running in the page scope.") } );</pre>
</pre>
 
== Via @require ==
 
Use this function with just one line:
 
<pre class='sample'>// @require http://userscripts.org/scripts/source/100842.user.js</pre>


== See Also ==
== See Also ==

Latest revision as of 16:28, 3 November 2017

Warning: The contents of this page are not accurate when used with Greasemonkey 4.0.

For scripts which @grant any privileged APIs, these methods are provided in a privileged scope which is intentionally isolated from the content page. The same functionality is available by calling window.eval() to explicitly target the content window scope for execution. (Note that a bare eval() executes in the script scope.)

// ==UserScript==
// @name        Content Script Example, grant none
// @grant       none
// ==/UserScript==

// Because I am a "@grant none" script, I operate right in the content scope.
// I can call functions defined by the page with no problems.
var result = functionFromContentScope();

// Similarly, I can export values or functions to that scope for it to call.
window.someVariable = 'someValue';
// ==UserScript==
// @name        Content Script Example, privileged grant
// @grant       GM_log
// ==/UserScript==

// Because I am *not* a "@grant none" script, I operate in my own private,
// privileged scope.  I can call functions defined by the page only by
// explicitly referencing the window:
var result = window.eval('functionFromContentScope();')

// Similarly, I can export values or functions to that scope for it to call.
window.eval("window.someVariable = 'someValue';");

See Also