|
|
(98 intermediate revisions by 15 users not shown) |
Line 1: |
Line 1: |
| {{lowercase}} | | {{DISPLAYTITLE:unsafeWindow}} |
| {{security}} | | {{security}} |
| __NOTOC__
| |
| {{Greasemonkey Manual TOC}}
| |
|
| |
|
| == Description == | | == Description == |
|
| |
|
| This [[API_reference|API]] object allows a [[User script]] to access "custom" properties--variable and functions defined in the page--set by the web page. The unsafeWindow object is shorthand for <code>window.wrappedJSObject</code>. It is the raw window object inside the XPCNativeWrapper provided by the Greasemonkey [[sandbox]]. | | This object allows a [[User script]] to access "custom" properties set by the web page. |
| | The user script is otherwise isolated from these properties. |
|
| |
|
| :*'''USE OF UNSAFEWINDOW IS INSECURE, AND IT SHOULD BE AVOIDED WHENEVER POSSIBLE.''' | | :*'''USE OF UNSAFEWINDOW IS INSECURE, AND IT SHOULD BE AVOIDED WHENEVER POSSIBLE.''' |
|
| |
|
| unsafeWindow bypasses [[Greasemonkey]]'s [[XPCNativeWrapper]]-based [[security]] model, which exists to make sure that malicious web pages cannot alter objects in such a way as to make greasemonkey scripts (which execute with more privileges than ordinary Javascript running in a web page) do things that their authors or users did not intend. User scripts should therefore avoid calling or in any other way depending on any properties on unsafeWindow - especally if if they are executed for arbitrary web pages, such as those with <code>@[[Include and exclude rules|include]] *</code>, where the page authors may have subverted the environment in this way. | | unsafeWindow bypasses [[Greasemonkey]]'s security model, which exists to make sure that malicious web pages cannot alter objects in such a way as to make user scripts (which execute with more privileges than ordinary JavaScript running in a web page) do things that their authors or users did not intend. |
| | User scripts should therefore avoid calling or in any other way depending on any properties on unsafeWindow - especially if they are executed for arbitrary web pages, such as those with <code>@[[Include and exclude rules|include]] *</code>. |
|
| |
|
| [[User script]] authors are '''strongly''' encouraged to learn how [[XPCNativeWrapper]]s work, and how to perform the desired function within their security context, instead of using unsafeWindow to break out.
| | == Examples == |
| | |
| [[#Examples|Examples]] | [[#Alternatives_to_unsafeWindow|Alternatives to unsafeWindow]] | [[#Notes|Notes]]
| |
| | |
| == Syntax == | |
|
| |
|
| '''unsafeWindow''' | | <pre class='sample-bad'> |
| | |
| :Value: Object
| |
| :Returns: Variant
| |
| :Compatibility: [[Version_history#0.5_beta|Greasemonkey 0.5b+]]
| |
| | |
| [[#top|top]]
| |
| | |
| == Examples ==
| |
| <code><pre>
| |
| unsafeWindow.SomeVarInPage = "Testing"; | | unsafeWindow.SomeVarInPage = "Testing"; |
| </pre></code> | | </pre> |
|
| |
|
| <code><pre>
| | <pre class='sample-bad'> |
| unsafeWindow.SomeFunctionInPage("Test"); | | unsafeWindow.SomeFunctionInPage("Test"); |
| </pre></code> | | </pre> |
|
| |
|
| <code><pre>
| | <pre class='sample-bad'> |
| var oldFunction = unsafeWindow.SomeFunctionInPage; | | var oldFunction = unsafeWindow.SomeFunctionInPage; |
| unsafeWindow.SomeFunctionInPage = function(text) { | | unsafeWindow.SomeFunctionInPage = function(text) { |
| alert("Hijacked! Argument was " + text + "."); | | alert('Hijacked! Argument was ' + text + '.'); |
| return oldFunction(text); | | return oldFunction(text); |
| }; | | }; |
| </pre></code> | | </pre> |
| | |
| :For issues with GM_getValue, GM_setValue and GM_xmlhttpRequest, see see [[0.7.20080121.0_compatibility]].
| |
| | |
| <code><pre>
| |
| window.addEventListener("DOMTitleChanged", function(){
| |
| | |
| var redirectURL = window.name;
| |
| | |
| }, false);
| |
| | |
| var sGetter = document.createElement('script');
| |
| sGetter.type = "text/javascript";
| |
| sGetter.innerHTML = "function uXHR(url){"+
| |
| " var httpRequest = new XMLHttpRequest();"+
| |
| " httpRequest.onreadystatechange = function() { "+
| |
| " if(httpRequest.status == 301||httpRequest.status == 302){"+
| |
| " window.name=httpRequest.getResponseHeader('Location');"+
| |
| " document.title=document.title;"+
| |
| " }"+
| |
| " };"+
| |
| " httpRequest.open('HEAD', url, true);"+
| |
| " httpRequest.send(null);"+
| |
| "}";
| |
| | |
| document.body.appendChild(sGetter);
| |
| | |
| unsafeWindow.uXHR(url);
| |
| | |
| </pre></code>
| |
| | |
| [[#top|top]]
| |
|
| |
|
| == Alternatives to unsafeWindow == | | == Alternatives to unsafeWindow == |
|
| |
|
| [[#Events|Events]] | [[#Functions_defined_in_the_page|Functions defined in the page]] | [[#Attach_script_to_page | Attach script to page]]
| | ''Sometimes'', you just can't get around using unsafeWindow. |
| | | Most of the time, however, you can! |
| === Events ===
| | See [[:Category:Coding Tips:Interacting With The Page]] for details on various methods to interact with the page that do '''not''' use unsafeWindow. |
| | |
| :Event listeners never need to be created on unsafeWindow. Rather than using
| |
| | |
| <code>unsafeWindow.onclick = function(event) { ... };</code>
| |
| | |
| use:
| |
| | |
| <code><pre>window.addEventListener("click", function(event) { /* some code */ }, false);</pre></code>
| |
| | |
| :See also [http://developer.mozilla.org/en/docs/DOM:element.addEventListener addEventListener at MDC]
| |
| | |
| [[#top|top]] | [[#Alternatives_to_unsafeWindow|back]]
| |
| | |
| === Functions defined in the page ===
| |
| | |
| :If a user script must execute a page function, it can use the '''[[location hack]]''' to call it safely. This involves setting location.href to a <code>javascript:</code> URL, which is like using a bookmarklet. For example:
| |
| | |
| :<code><pre>location.href = "javascript:void(pageFunc(123));";</pre></code>
| |
| | |
| :Larger blocks of code independent of the Greasemonkey context/APIs can also be executed this way:
| |
| | |
| :<code><pre>location.href = "javascript:(" + encodeURI(uneval(function() { /* some code */ })) + ")();";</pre></code>
| |
| | |
| :This code will run in the page context without leaking the [[sandbox]]. This code is completely separate from the rest of the script scope, sometimes limiting its usefulness. For example, data cannot be returned by the function.
| |
| | |
| :Another drawback is that this technique is rather ugly. Still, it is preferred over unsafeWindow.
| |
| | |
| [[#top|top]] | [[#Alternatives_to_unsafeWindow|back]]
| |
| | |
| === Attach script to page ===
| |
| | |
| ==== Method 1 ====
| |
| <code><pre>
| |
| function myScript() {
| |
| for(var x in document) {
| |
| // do something with x
| |
| }
| |
| /// blah blah blah
| |
| }
| |
| | |
| // attach script to page; script can therefore reference variables on the page, but likewise
| |
| // cannot use greasemonkey API methods
| |
| document.body.appendChild(document.createElement("script")).innerHTML="("+myScript+")()";
| |
| </pre></code>
| |
| | |
| [[#top|top]] | [[#Alternatives_to_unsafeWindow|back]] | |
| | |
| ==== Method 2 ====
| |
| This way is interesting for those who want:
| |
| * execute the init() function NOT in GM address space
| |
| * inject multiple css hacks
| |
| * inject multiple .js files
| |
| | |
| TODO: Confirm that @unwrap IS or IS NOT required for this to work ''(e.g. Should this example include the metadata block)''
| |
| | |
| <code><pre>
| |
| /*
| |
| Filename: hello-world.js
| |
| */
| |
| | |
| (function()
| |
| {
| |
| inject_css();
| |
|
| |
| var scripts = [
| |
| "http://mydomain.gov/misc/hello-injection.js",
| |
| "http://mydomain.gov/misc/hello-injection2.js"
| |
| ];
| |
| | |
| /*
| |
| Be aware that the GM script, when executed on a webpage will fail to include this:
| |
| 'file:///home/user/.mozilla/firefox/43obuw3o.default/gm_scripts/hello_world/lab-injection.js'
| |
| with the error: Error: init is not defined Sourcefile: javascript:void(init()); Line: 1
| |
| and you will get an security alert as well that elements from a remote site can't access local
| |
| files (which is good)
| |
| | |
| Be aware that the GM script, when executed on a webpage will fail to include this:
| |
| '/home/user/.mozilla/firefox/43obuw3o.default/gm_scripts/hello_world/lab-injection.js'
| |
| with the error: Error: init is not defined Sourcefile: javascript:void(init()); Line: 1
| |
| | |
| BE AWARE THAT THE PROTECTION FAULT ERROR WON'T BE SHOWN since no 'file://' is there.
| |
| this took me a lot of my time to figure out... ;P
| |
| - in this example we have two .js files, you can remove the second entry AND the , at the first one
| |
| if you only want one .js file
| |
| */
| |
|
| |
| for (i in scripts) {
| |
| var script = document.createElement("script");
| |
| script.src = scripts[i];
| |
| | |
| document.getElementsByTagName("head")[0].appendChild(script);
| |
| }
| |
|
| |
| /* When the window is finished loading, attach the Shake-It on-click event. */
| |
| | |
| window.addEventListener(
| |
| "load"',
| |
| function(event) {
| |
| // Grab a reference to the Effect object which was loaded by the scriptaculous library earlier.
| |
| location.href = "javascript:void(init());";
| |
| },
| |
| "false"
| |
| );
| |
|
| |
| }
| |
| )();
| |
| | |
|
| |
| function addGlobalStyle(css) {
| |
| var head = document.getElementsByTagName("head")[0];
| |
| | |
| if (!head) {
| |
| return;
| |
| }
| |
| | |
| var style = document.createElement("style");
| |
| style.type = "text/css";
| |
| style.innerHTML = css;
| |
| | |
| head.appendChild(style);
| |
| }
| |
| | |
|
| |
| function inject_css() {
| |
| document.title = document.title + " dynamically modified version";
| |
|
| |
| addGlobalStyle(
| |
| ".somedivclassname {" +
| |
| " margin: 0px 10px 0px 10px;" +
| |
| " margin-right: -12px;" +
| |
| " padding: 4px 0px 9px 0px;" +
| |
| "}"
| |
| );
| |
| }
| |
| </pre></code>
| |
| | |
| <code><pre>
| |
| /*
| |
| Filename: hello-injecting.js
| |
| */
| |
| | |
| function init() {
| |
| alert('tut');
| |
| }
| |
| </pre></code>
| |
| | |
| [[#top|top]] | [[#Alternatives_to_unsafeWindow|back]]
| |
| | |
| == Notes ==
| |
| [[#top|top]]
| |
|
| |
|
| [[Category:API_Reference|U]] | | [[Category:API_Reference|U]] |
| [[Category:Scripting context]] | | [[Category:Scripting context]] |
| [[Category:Security]] | | [[Category:Security]] |