@grant: Difference between revisions
No edit summary |
Ika syafika (talk | contribs) |
||
Line 16: | Line 16: | ||
<pre class='sample-good'> | <pre class='sample-good'> | ||
// ==UserScript== | // ==UserScript== | ||
// @name | // @name Grant None Example | ||
// @include http* | // @include http* | ||
// @grant none | // @grant none |
Revision as of 16:00, 24 July 2013
Greasemonkey 1.0 adds a special Metadata Block imperative: @grant
.
As of version 1.0:
- If a script does not specify any
@grant
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 methods that it declares.
- The valid values are the names of those
GM_
prefixed values that you wish your script to be granted access to.
- The valid values are the names of those
- 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
@grant none
.
Examples
It's common for scripts (over half when last counted) not to use any special APIs at all. 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. To do so, simply:
// ==UserScript== // @name Grant None Example // @include http* // @grant none // ==/UserScript== console.log('This script grants no special privileges, so it runs without security limitations.');
If you do use one of Greasemonkey's APIs, you should explicitly ask for it to be granted to your script:
// ==UserScript== // @name Grant Some Example // @include http* // @grant GM_getValue // @grant GM_setValue // ==/UserScript== var counter = 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
without specifically requesting it.)
Temporarily, this would also work:
// ==UserScript== // @name Grant Legacy Example // @include http* // ==/UserScript== var counter = GM_getValue('counter', 0); console.log('This script has been run ' + counter + ' times.'); GM_setValue('counter', ++counter);
This example will work in Greasemonkey version 1.0.
When there are no @grant
lines, Greasemonkey tries to detect which APIs are being used, and act as if those @grant
lines had been specified.
This detection may fail in certain cases, especially when eval()
is used.
All scripts written before @grant
should continue to work because of this, but you should change your scripts to specify @grant
at your earliest convenience, so they don't break in the future.
Compatibility Layer
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 its increased compatibility without any drawbacks immediately.
Simply use an @require library to emulate Greasemonkey APIs with now-standard browser features:
// ==UserScript== // @name Grant None Example, With Shim // @include http://www.example.com/* // @grant none // @require https://userscripts.org/scripts/source/145813.user.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.
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 var x = 1;
will not be visible to the content scope, and thus will not break the page (i.e. if it depends on a variable x
having a different value.)
To write values to the content scope, do window.x = 1;
.
If you @require
a version of jQuery, it will implicitly assign to window.$
and window.jQuery
.
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:
this.$ = this.jQuery = jQuery.noConflict(true);
This code will save a jQuery reference (into this
the script's global scope when running in the grant none mode), while removing it from window
(the content global scope) and restoring anything originally stored there.