|
|
(69 intermediate revisions by 14 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 xhr = new XMLHttpRequest();" +
| |
| " xhr.onreadystatechange = function() { " +
| |
| " if (xhr.status == 301 || xhr.status == 302) {" +
| |
| " window.name = xhr.getResponseHeader('Location');" +
| |
| " document.title = document.title;" +
| |
| " }" +
| |
| " };" +
| |
| " xhr.open('HEAD', url, true);" +
| |
| " xhr.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) { /* some code */ };</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 ===
| |
| | |
| ==== Attach Method 1 ====
| |
| <code><pre>
| |
| function myScript() {
| |
| for (var x in document) {
| |
| // some code with x
| |
| }
| |
| // some code
| |
| }
| |
| | |
| // 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]]
| |
| | |
| ==== Attach 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 (even from different domains)
| |
| | |
| <code><pre>
| |
| /* Filename: hello-world.user.js */
| |
| | |
| (function()
| |
| {
| |
| inject_css();
| |
|
| |
| /*
| |
| Define single/multiple script(s) to inject
| |
| NOTES:
| |
| Schemes of file:// type, absolute or implied, are not supported with this method due to
| |
| browser security restrictions.
| |
| | |
| Schemes of http:// or https:// must be present, see pitfall 1 and 2 below.
| |
| */
| |
| | |
| var scripts = [
| |
| "http://localhost:8080/hello-injecting.js",
| |
| "http://www.example.com/inject-this-script1.js",
| |
| "http://www.example.com/inject-this-script2.js"
| |
| ];
| |
| | |
| var script;
| |
| for (i in scripts) {
| |
| script = document.createElement("script");
| |
| script.src = scripts[i];
| |
| script.type = "text/javascript";
| |
| | |
| document.getElementsByTagName("head")[0].appendChild(script);
| |
| }
| |
|
| |
| window.addEventListener(
| |
| "load",
| |
| function(event) {
| |
| location.href = "javascript:void(init());";
| |
| },
| |
| false
| |
| );
| |
| }
| |
| )();
| |
| | |
|
| |
|
| |
| function inject_css() {
| |
| document.title += ' dynamically modified version';
| |
| GM_addStyle("body { color:white; background-color:black } img { border:0 }");
| |
| }
| |
| </pre></code>
| |
| | |
| <code><pre>
| |
| /*
| |
| Filename: http://localhost:8080/hello-injecting.js
| |
| | |
| NOTES:
| |
| This means you are running your own web server on port 8080 and hosting this script locally and NOT remotely.
| |
| */
| |
| | |
| function init() {
| |
| alert('Hello, world!');
| |
| }
| |
| </pre></code>
| |
| | |
| [[#top|top]] | [[#Alternatives_to_unsafeWindow|back]]
| |
| | |
| ===== Attach Method 2 Pitfall 1 =====
| |
| :The method of hosting hello-injecting.user.js in Greasemonkey was tested on:
| |
| ::Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.0.6) Gecko/2009011912 Firefox/3.0.6
| |
| ::Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.0.7) Gecko/2009021906 Firefox/3.0.7
| |
| :and ''failed to execute init()'' with the following error:
| |
| | |
| ::Error: init is not defined
| |
| ::Source file: javascript:void(init());
| |
| ::Line: 1
| |
| | |
| :Possible solution:
| |
| | |
| :Always write the URL your .js file is in with the protocol as:
| |
| | |
| ::* correct: http://localhost:8080/hello-injecting.user.js
| |
| ::* incorrect: localhost:8080/hello-injecting.user.js
| |
| | |
| :''NOTE:'' also check that the file is there.
| |
| | |
| ===== Attach Method 2 Pitfall 2 =====
| |
| :The method of hosting hello-injecting.js on a local web server as well as a remote web server was tested on:
| |
| ::Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.0.6) Gecko/2009011912 Firefox/3.0.6
| |
| ::Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.0.7) Gecko/2009021906 Firefox/3.0.7
| |
| :and ''returned Component failure code'' with the following error:
| |
| | |
| ::Error: Component returned failure code: 0x805e000a [nsIDOMLocation.href] = <unknown>
| |
| ::Source file: file://~/.mozilla/firefox/randomseed.default/extensions/{class-id}/components/greasemonkey.js
| |
| ::Line: 377
| |
| | |
| == Notes ==
| |
| [[#top|top]]
| |
|
| |
|
| [[Category:API_Reference|U]] | | [[Category:API_Reference|U]] |
| [[Category:Scripting context]] | | [[Category:Scripting context]] |
| [[Category:Security]] | | [[Category:Security]] |