|
|
(11 intermediate revisions by 4 users not shown) |
Line 1: |
Line 1: |
| The '''location hack''' is an ugly but useful way to interact with the content scope of the page being [[user script]]ed. It does this by indirectly [http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:eval evaling] strings within that scope. | | The location hack is an older technique for crossing the barrier between the user script scope and the content window scope, when it exists. |
| | The previous version of this page may be read [http://wiki.greasespot.net/index.php?title=Location_hack&oldid=7202 via history]. |
|
| |
|
| , | | In Firefox version 39.0.3 Mozilla patched a known [https://www.mozilla.org/en-US/security/advisories/mfsa2015-78/ security vulnerability]. |
| | As a side effect, this broke the location hack. |
|
| |
|
| == Basic usage: page functions ==
| | Thankfully in modern versions of Firefox and Greasemonkey, the location hack is no longer necessary. |
| | | Read about how to execute code in the content scope, like previously possible with the location hack, at [[Content Script Injection]]. |
| Suppose the page contains a function called <code>pageFunc</code>, or <code>window.pageFunc</code>.
| |
| The user script knows this function as <code>unsafeWindow.pageFunc</code>.
| |
| | |
| The user script could simply call <code>unsafeWindow.pageFunc()</code>, but this can leak the sandbox.
| |
| Instead, the user script can take advantage of <code>javascript:</code> URLs, which always run in the content scope.
| |
| Just entering this URL into the browser's location bar does not leak a GreaseMonkey sandbox:
| |
| | |
| javascript:pageFunc();void(0)
| |
| | |
| A user script can programmaticaly navigate to this URL, to safely call the function:
| |
| | |
| location.assign( "javascript:pageFunc();void(0)" );
| |
| | |
| That, in a nutshell, is the location hack!
| |
| Essentially, it is wrapping a [[wikipedia:bookmarklet|bookmarklet]] into a user script.
| |
| | |
| It's important to add the <code>javascript:</code> scheme to the front, to turn it into a URL, and the <code>;void(0)</code> to the end, which keeps the browser from actually navigating to this URL after it is run.
| |
| | |
| == Modifying the page ==
| |
| | |
| The location hack can do anything a page script or bookmarklet can do, so it can modify content variables and such as easily as it can access them. For example:
| |
| | |
| location.href = "javascript:void(window.someVariable = 'someValue')";
| |
| | |
| == Executing large blocks of code ==
| |
| | |
| Executing more than one statement can become unreadable very easily. Luckily, JavaScript can convert functions to strings, so you can use:
| |
| | |
| location.href = "javascript:(" + function() {
| |
| // do something
| |
| } + ")()";
| |
| | |
| Even though the function is defined in the sandbox, it is not a closure of the sandbox scope. It is converted to a string and then back to a function in page scope. It cannot access anything in the sandbox scope, which is a limitation, but is also essential to making this technique secure.
| |
| | |
| == Percent encoding issue ==
| |
| | |
| Sometimes percent-encoding the percent symbol is required. For example,
| |
| | |
| location.href = ("javascript:(" + function() {
| |
| var n = 44;
| |
| if(!('''n%22''')) alert('n is a multiple of 22');
| |
| } + ")()");
| |
| | |
| The above code will cause error because %22 is interpreted as double quotation mark. The workaround is:
| |
| | |
| location.href = "javascript:(" + encodeURI(
| |
| function() {
| |
| var n = 44;
| |
| if(!(n%22)) alert('n is a multiple of 22');
| |
| }) + ")()";
| |
| | |
| See also [http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:encodeURI encodeURI()].
| |
| | |
| == Returning values ==
| |
| | |
| The location hack is really handy for passing values to the content scope, or to call functions defined there.
| |
| It is not, however, capable of directly reading a variable or value returned from a function.
| |
| Furthermore, it is run asynchronously, much like <code>setTimeout()</code>, so you cannot immediately rely on side effects.
| |
| (If you use the location hack to, for example, store a value in the DOM and then attempt to read it, it will only be available at some other later point in time.)
| |
| For reading javascript values from the content scope inside the sandbox, see [[Reading Content Globals]] for a reliable example.
| |
| | |
| == See Also ==
| |
| | |
| * [[Reading Content Globals]]
| |
| * [[Content Script Injection]]
| |
|
| |
|
| [[Category:Coding Tips:Interacting With The Page]] | | [[Category:Coding Tips:Interacting With The Page]] |