@grant: Difference between revisions

From GreaseSpot Wiki
Jump to navigationJump to search
mNo edit summary
Update for 4.0
 
(8 intermediate revisions by 5 users not shown)
Line 1: Line 1:
Greasemonkey 1.0 adds a special [[Metadata Block]] imperative: <code>@grant</code>.
The <code>@grant</code> [[Metadata Block]] imperative controls which special [[API]]s (if any) your script uses.
As of version 1.0:
If no value is specified, <code>none</code> will be used by default.
 
If any value or values are specified, ''only those'' API methods will be provided.
* If a script does not specify any <code>@grant</code> values, Greasemonkey will attempt to auto-detect the right settings.
* If a script specifies any values (or they have been auto detected), then it will be provided with ''only those'' [[API Reference|API]] methods that it declares.
** The valid values are the names of those <code>GM_</code> prefixed values that you wish your script to be granted access to.
* Otherwise the script will be granted no special API privileges, and thus run without the security constraints Greasemonkey scripts have traditionally had.  If you want your script to operate in this mode, you should explicitly declare <code>@grant none</code>.


== Examples ==
== Examples ==


It's common for scripts ([http://www.greasespot.net/2009/11/greasemonkey-api-usage.html over half] when last counted) not to use any special APIs at all.
It's common for scripts not to use any special APIs at all.
In that case, use <code>@grant none</code>.
<!-- This doesn't apply in 4.0.  http://bugzil.la/1353468
For such scripts, explicitly asking to be granted no special privileges means that the script will execute directly in the content page.
For such scripts, explicitly asking to be granted no special privileges means that the script will execute directly in the content page.
This means no security sandbox, and none of its limitations, so accessing variables in the page just works, calling functions and reading their results also just works.
This means no security sandbox, and none of its limitations, so accessing variables in the page just works, calling functions and reading their results also just works.
To do so, simply:
To do so, simply:
-->


<pre class='sample-good'>
<pre class='sample-good'>
// ==UserScript==
// ==UserScript==
// @name       Grant None Example
// @name     Grant None Example
// @include     http*
// @include http*
// @grant       none
// @grant   none
// ==/UserScript==
// ==/UserScript==


console.log('This script grants no special privileges, so it runs without security limitations.');
console.log('This script uses no special privileges.');
</pre>
</pre>


If you ''do'' use one of Greasemonkey's [[API]]s, you should explicitly ask for it to be granted to your script:
If you specify no <code>@grant</code> at all, <code>none</code> will be assumed.


<pre class='sample-good'>
<pre class='sample'>
// ==UserScript==
// ==UserScript==
// @name       Grant Some Example
// @name     No Grant Example
// @include     http*
// @include http*
// @grant      GM_getValue
// @grant      GM_setValue
// ==/UserScript==
// ==/UserScript==


var counter = GM_getValue('counter', 0);
console.log('This script uses no special privileges, but doesn't declare that.');
console.log('This script has been run ' + counter + ' times.');
GM_setValue('counter', ++counter);
</pre>
</pre>


In this case, the script is asking to be granted access to both <code>GM_getValue</code> and <code>GM_setValue</code>, one on each <code>@grant</code> line.
If you specify <code>none</code> and something else, <code>none</code> takes precedence.
Specify the name of any Greasemonkey [[API]] to be granted access to it.
This can be confusing.
(All scripts always get <code>GM_info</code> without specifically requesting it.)
Check for a <code>none</code> to remove if you're adding [[API]]s you intend to use.
Temporarily, this would also work:


<pre class='sample-bad'>
<pre class='sample-bad'>
// ==UserScript==
// ==UserScript==
// @name       Grant Legacy Example
// @name     Mixed Grant Example
// @include    http*
// @include http*
// @grant    none
// @grant    GM.openInTab
// ==/UserScript==
 
// Will fail, because `@grant none` was specified.
GM.openInTab('http://www.example.org/');
</pre>
 
If you ''do'' use one or more of Greasemonkey's [[API]]s, you must ask for it to be granted to your script:
 
<pre class='sample-good'>
// ==UserScript==
// @name     Grant Some Example
// @include  http*
// @grant    GM.getValue
// @grant    GM.setValue
// ==/UserScript==
// ==/UserScript==


var counter = GM_getValue('counter', 0);
(async ()=>{
let counter = await GM.getValue('counter', 0);
console.log('This script has been run ' + counter + ' times.');
console.log('This script has been run ' + counter + ' times.');
GM_setValue('counter', ++counter);
GM.setValue('counter', ++counter);
})();
</pre>
</pre>


This example will work in Greasemonkey version 1.0.
In this case, the script is asking to be granted access to both [[GM.getValue]] and [[GM.setValue]], one on each <code>@grant</code> line.
When there are no <code>@grant</code> lines, Greasemonkey '''tries''' to detect which APIs are being used, and act as if those <code>@grant</code> lines had been specified.
Specify the name of any Greasemonkey [[API]] to be granted access to it.
This detection may fail in certain cases, especially when <code>eval()</code> is used.
(All scripts always get <code>GM.info</code> even without specifically requesting it.)


All scripts written before <code>@grant</code> should continue to work because of this, but you should change your scripts to specify <code>@grant</code> at your earliest convenience, so they don't break in the future.
== Compatibility Layer ==


== Compatibility Layer ==
Over time many of the Greasemonkey [[API]]s have been duplicated by web standards like [https://developer.mozilla.org/en/DOM/Storage DOM Storage].
If you only ever expect your script to operate on a single domain, you can use <code>@grant none</code> and these web APIs.


Many of the Greasemonkey [[API]]s have been duplicated by web standards like [https://developer.mozilla.org/en/DOM/Storage DOM Storage].
Or, use a [[Metadata Block#@require|@require]] library to emulate Greasemonkey [[API]]s with those web APIs:
If you only ever expect your script to operate on a single domain, you can use <code>@grant none</code> and its increased compatibility without any drawbacks immediately.
Simply use an [[Metadata Block#@require|@require]] library to emulate Greasemonkey [[API]]s with now-standard browser features:


<pre class='sample-good'>
<pre class='sample-good'>
Line 72: Line 83:
// @include    http://www.example.com/*
// @include    http://www.example.com/*
// @grant      none
// @grant      none
// @require    https://userscripts.org/scripts/source/145813.user.js
// @require    https://gist.githubusercontent.com/arantius/3123124/raw/grant-none-shim.js
// ==/UserScript==
// ==/UserScript==


Line 82: Line 93:
This script will work the same as the example above, except that the grant none shim is providing API emulation with standard browser features.
This script will work the same as the example above, except that the grant none shim is providing API emulation with standard browser features.
When the shim compatibility layer works well enough for your script, this is the best of both worlds.
When the shim compatibility layer works well enough for your script, this is the best of both worlds.
<!-- TODO: Restore as/when grant none works like it used to, in 4.x.
== Scope ==
In the grant none case, the user script still has its own global scope, distinct from the content page's global scope.
This means that a top-level <code>var x = 1;</code> will not be visible to the content scope, and thus will not break the page (i.e. if it depends on a variable <code>x</code> having a different value.)
To write values to the content scope, do <code>window.x = 1;</code>.
If you <code>@require</code> a version of jQuery, it will implicitly assign to <code>window.$</code> and <code>window.jQuery</code>.
If the page you run on depends on a different version of jQuery, then this may break the page.
To work around this problem, anywhere at the top level of your script do:
<pre class='sample'>
this.$ = this.jQuery = jQuery.noConflict(true);
</pre>
This code will save a jQuery reference (into <code>this</code>, the script's global scope when running in the grant none mode), while removing it from <code>window</code> (the content global scope) and restoring anything originally stored there.
-->
[[Category:Scripting_context]]

Latest revision as of 16:08, 3 November 2017

The @grant Metadata Block imperative controls which special APIs (if any) your script uses. If no value is specified, none will be used by default. If any value or values are specified, only those API methods will be provided.

Examples

It's common for scripts not to use any special APIs at all. In that case, use @grant none.

// ==UserScript==
// @name     Grant None Example
// @include  http*
// @grant    none
// ==/UserScript==

console.log('This script uses no special privileges.');

If you specify no @grant at all, none will be assumed.

// ==UserScript==
// @name     No Grant Example
// @include  http*
// ==/UserScript==

console.log('This script uses no special privileges, but doesn't declare that.');

If you specify none and something else, none takes precedence. This can be confusing. Check for a none to remove if you're adding APIs you intend to use.

// ==UserScript==
// @name     Mixed Grant Example
// @include  http*
// @grant    none
// @grant    GM.openInTab
// ==/UserScript==

// Will fail, because `@grant none` was specified.
GM.openInTab('http://www.example.org/');

If you do use one or more of Greasemonkey's APIs, you must ask for it to be granted to your script:

// ==UserScript==
// @name     Grant Some Example
// @include  http*
// @grant    GM.getValue
// @grant    GM.setValue
// ==/UserScript==

(async ()=>{
let counter = await GM.getValue('counter', 0);
console.log('This script has been run ' + counter + ' times.');
GM.setValue('counter', ++counter);
})();

In this case, the script is asking to be granted access to both GM.getValue and GM.setValue, one on each @grant line. Specify the name of any Greasemonkey API to be granted access to it. (All scripts always get GM.info even without specifically requesting it.)

Compatibility Layer

Over time many of the Greasemonkey APIs have been duplicated by web standards like DOM Storage. If you only ever expect your script to operate on a single domain, you can use @grant none and these web APIs.

Or, use a @require library to emulate Greasemonkey APIs with those web APIs:

// ==UserScript==
// @name        Grant None Example, With Shim
// @include     http://www.example.com/*
// @grant       none
// @require     https://gist.githubusercontent.com/arantius/3123124/raw/grant-none-shim.js
// ==/UserScript==

var counter = GM_getValue('counter', 0);
console.log('This script has been run ' + counter + ' times.');
GM_setValue('counter', ++counter);

This script will work the same as the example above, except that the grant none shim is providing API emulation with standard browser features. When the shim compatibility layer works well enough for your script, this is the best of both worlds.