Why does "#grant randominvalidsetting" activate the sandbox? - javascript

I saw some code that used this setting to activate the sandbox:
#grant sandbox
When I run the following basic Greasemonkey script in Firefox:
// ==UserScript==
// #name Test
// #namespace user12345678
// #include http://example.com
// #version 1
// #grant sandbox
// ==/UserScript==
console.log(window.toString());
It seems that the sandbox is setup:
[object XrayWrapper [object Window]]
...unlike when you use #grant none:
[object Window]
It appears to work just the same as adding unsafeWindow or GM_log, but I can't seem to find anything about this in the documentation (yes, I've searched). I even tested it with some gibberish:
#grant randominvalidsetting34234239482389482394
That had the same effect as putting #grant sandbox or a Greasemonkey function as the value.
If it is not in the documentation, is it actually valid? And if it isn't, why does it appear to work?

Where did you hear that? Nevertheless, it's true but I don't recommend it.
From the #grant documentation (not what was linked in the question):
The valid values are the names of those GM_ prefixed values that you wish your script to be granted access to.
(Plus none, plus unsafeWindow.)
While using sandbox will work, for now, I prefer a value that's more "future proof", EG GM_addStyle.
As you can see from Greasemonkey's source code (now superceded), unless the script is operating in grant none mode, it is always sandboxed (wrapped in an XPCNativeWrapper), hence the [object XrayWrapper [object Window]] that you got.
This means that just about anything besides none for a #grant value will activate the sandbox, for Greasemonkey, for now, but it's not guaranteed to always work the same way for Greasemonkey, Scriptish, Tampermonkey, etc. So use one of the known valid values to activate your sandbox.
(And for maximum portability and to eliminate "time bomb code", I recommend always using the sandbox.)

Related

How to manipulate JWPLAYER with Tampermonkey?

I've been trying to manipulate a JWPlayer externally, using tampermonkey.
The problem I get is that "JWPlayer" is not Defined.
var player = jwplayer("myVideo");
Simply declaring a player as a jwplayer is not possible.
To fix I've been to "import" the jwplayer.js:
// #require https://vidstreaming.io/js/jw8.9/jwplayer.js
Which didn't work...
My objective: is to to the following through tampermonkey
When I'm at browser, using developer tools I can use
getPosition() to get the current playtime of the video
then seek() to play from there..
jwplayer().getPosition()
jwplayer().seek(X)
Any idea how to "import" jwpalyer.js into Tampermonkey script?
If this works for you from dev tools:
jwplayer().getPosition()
then what you want is to access window.jwplayer global variable. If you are not using any GM specific features, all you need is to make sure your script starts after the player is loaded. Eg. this should be late enough:
// #run-at document-idle
If you're using some #grant privileges, it is still possible, via unsafe window permission:
#grant unsafeWindow
Then, this is what you run:
unsafeWindow.jwplayer().getPosition()
Please pay attention to the warning:
This command can open certain security holes in your user script, and it is recommended to use this command sparingly.
Please be sure to read the entire article and understand it before using it in a script.
So make sure to read the article and understand not to expose any greasemonkey functions to the outside webpages. Never use it with #include *.
// #grant unsafeWindow
// #require https://urlto/jwplayer.js
;(function() {
'use strict';
document.addEventListener("DOMContentLoaded", function(event) {
var ownPlayer = jwplayer();
ownPlayer.on("ready",function(e) {
console.log(this.getPlaylist());
});
});
})();

Greasemonkey swallows JS errors without logging them [duplicate]

I am having issues with this very basic Greasemonkey script, most likely with the metadata configuration.
Here is the full source of the basic file
// ==UserScript==
// #name Google Hello
// #namespace https://google.com
// #description Basic Google Hello
// #include *
// #version 1
// ==/UserScript==
alert("hi google!");
This script should run when I access Google.com, but the alert is not popping up. What is the issue?
I am attempting to run this script on Ubuntu with Firefox.
If alerts() are not firing, chances are you may have clicked Firefox's Prevent this page from creating additional dialogs option, or set a browser preference (older versions of Firefox), or Firefox may have become unstable in memory.
Universal Greasemonkey debug steps:
(With one step added for problems with alert().)
First make sure that the script is even firing for the page in question.
While browsing that page, click on the down-triangle next to the Greasemonkey icon (Alternatively, you can Open Tools -> Greasemonkey on the Firefox menu.) and verify that the expected script name appears and is checked. EG:
See if there are any relevant messages/errors on Firefox's Browser Console.
Activate the console by pressing CtrlShiftJ, or equivalent.
Here's a screenshot showing how both messages and errors appear in the Browser Console -- caused by both the web page and the Greasemonkey script:
Open about:config, search for capability.policy.default.Window.alert and delete or reset the value, if it is found.
Uninstall the Greasemonkey script.
Completely clear the browser cache.
Shutdown Firefox completely. Use Task Manager, or equivalent, to verify that there is no Firefox thread/task/process in memory.
Restart Firefox.
Install the Greasemonkey script afresh.
If it still doesn't work, create a new Firefox profile or try a different computer altogether.
Additional issues:
Please supply your versions of three things: (1) The OS, (2) Firefox, (3) Greasemonkey or Tampermonkey or Scriptish, etc.
#include * means that the script will fire for every page! This is almost always a poor practice. (There are some exceptions, but your case is not one.)
#namespace does not control where the page runs. The only thing #namespace does is allow more than one script to have the same name (as long as their #namespaces are different). See the #namespace documentation.
Avoid using alert() for debugging. It's annoying and can mask timing problems.
Use console.log(). You can see the results, and helpful error messages (hint, hint) on the Browser Console.
Google almost always uses/redirects to www.google.com (For English USA users). So, // #include  https://google.com will almost never work like you want.
Recommend you use:
// #match *://www.google.com/*
as a starting point.
In Firefox Greasemonkey, you can also use the magic .tld to support most of Google's international domains, like so:
// #include http://www.google.tld/*
// #include https://www.google.tld/*
Use both lines. Note that this does not perform as well as the #match line does. So, if you only care about one nation/locale, just use #match.
Putting it all together:
Uninstall your script.
Restart Firefox.
Install this script:
// ==UserScript==
// #name Google Hello
// #namespace John Galt
// #description Basic Google Hello
// #match *://www.google.com/*
// #version 1
// #grant none
// ==/UserScript==
console.log ("Hi Google!");
Visit Google and note the results on Firefox's Browser Console.
If there is still a problem, follow all of the debug steps above.
If there is still a problem, Open a new question and supply ALL of the following:
The three versions, mentioned above.
The relevant errors and messages you get on the Browser Console.
The exact code and steps needed to duplicate the problem. Make an MCVE for this!
A short summary of what you have tried to solve the problem.

Using document.evaluate in Greasemonkey [duplicate]

I am having issues with this very basic Greasemonkey script, most likely with the metadata configuration.
Here is the full source of the basic file
// ==UserScript==
// #name Google Hello
// #namespace https://google.com
// #description Basic Google Hello
// #include *
// #version 1
// ==/UserScript==
alert("hi google!");
This script should run when I access Google.com, but the alert is not popping up. What is the issue?
I am attempting to run this script on Ubuntu with Firefox.
If alerts() are not firing, chances are you may have clicked Firefox's Prevent this page from creating additional dialogs option, or set a browser preference (older versions of Firefox), or Firefox may have become unstable in memory.
Universal Greasemonkey debug steps:
(With one step added for problems with alert().)
First make sure that the script is even firing for the page in question.
While browsing that page, click on the down-triangle next to the Greasemonkey icon (Alternatively, you can Open Tools -> Greasemonkey on the Firefox menu.) and verify that the expected script name appears and is checked. EG:
See if there are any relevant messages/errors on Firefox's Browser Console.
Activate the console by pressing CtrlShiftJ, or equivalent.
Here's a screenshot showing how both messages and errors appear in the Browser Console -- caused by both the web page and the Greasemonkey script:
Open about:config, search for capability.policy.default.Window.alert and delete or reset the value, if it is found.
Uninstall the Greasemonkey script.
Completely clear the browser cache.
Shutdown Firefox completely. Use Task Manager, or equivalent, to verify that there is no Firefox thread/task/process in memory.
Restart Firefox.
Install the Greasemonkey script afresh.
If it still doesn't work, create a new Firefox profile or try a different computer altogether.
Additional issues:
Please supply your versions of three things: (1) The OS, (2) Firefox, (3) Greasemonkey or Tampermonkey or Scriptish, etc.
#include * means that the script will fire for every page! This is almost always a poor practice. (There are some exceptions, but your case is not one.)
#namespace does not control where the page runs. The only thing #namespace does is allow more than one script to have the same name (as long as their #namespaces are different). See the #namespace documentation.
Avoid using alert() for debugging. It's annoying and can mask timing problems.
Use console.log(). You can see the results, and helpful error messages (hint, hint) on the Browser Console.
Google almost always uses/redirects to www.google.com (For English USA users). So, // #include  https://google.com will almost never work like you want.
Recommend you use:
// #match *://www.google.com/*
as a starting point.
In Firefox Greasemonkey, you can also use the magic .tld to support most of Google's international domains, like so:
// #include http://www.google.tld/*
// #include https://www.google.tld/*
Use both lines. Note that this does not perform as well as the #match line does. So, if you only care about one nation/locale, just use #match.
Putting it all together:
Uninstall your script.
Restart Firefox.
Install this script:
// ==UserScript==
// #name Google Hello
// #namespace John Galt
// #description Basic Google Hello
// #match *://www.google.com/*
// #version 1
// #grant none
// ==/UserScript==
console.log ("Hi Google!");
Visit Google and note the results on Firefox's Browser Console.
If there is still a problem, follow all of the debug steps above.
If there is still a problem, Open a new question and supply ALL of the following:
The three versions, mentioned above.
The relevant errors and messages you get on the Browser Console.
The exact code and steps needed to duplicate the problem. Make an MCVE for this!
A short summary of what you have tried to solve the problem.

Error: Permission denied to access property 'handler'

I have a greasemonkey script for Firefox, which yesterday was working perfectly. I tried using it today (no code was modified) and I noticed that it stopped working. Upon further inspection, the script is now throwing the following error:
Error: Permission denied to access property 'handler'
This error is being thrown in the following block of code:
$('body').click(function() {
// code here
});
This error magically started happening today when the script was working just fine yesterday. I'm not understanding why this error is happening when just trying to do something so basic such as adding an event handler in jQuery.
My script uses jQuery which is already being used in the page the script executes on, so I used this code to make it accessible to GM:
var $ = unsafeWindow.jQuery;
For reference if need be, here are the following Greasemonkey functions I use in my script:
// #grant GM_getResourceText
// #grant GM_addStyle
// #grant GM_xmlhttpRequest
// #grant GM_getResourceURL
I have tried researching this error and I can't find any answer. All of the questions that look like they might be helpful involve iframes and there is not a single iframe to be found in my code or the website it's run on. I've also tried deleting and re-installing the script and that didn't fix the problem.
Greasemonkey 2.0 has just been pushed to all Firefox browsers set to auto-update. (GM 2 was released on June 17, 2014, but it can take a few weeks to get through the review process.)
Greasemonkey 2.0 radically changed unsafeWindow handling:
Backwards incompatible changes:
For stability, reliability, and security the privileged sandbox has been updated to match the new changes to unsafeWindow for the Add-on SDK. In order to write values to unsafeWindow you will need to use the new methods cloneInto(), exportFunction(), and/or createObjectIn().
The #grant none mode is now the default, and grants will no longer be implied when not explicitly provided. See the post Sandbox API Changes in Greasemonkey 2.0 for more detail.
Ordinarily, to spot-access a page function or variable, you could switch to the new methods but, in your case you are using var $ = unsafeWindow.jQuery; -- which was always a bad practice.
jQuery is a special case and cloning it back and forth is going to break things.
#require jQuery instead, EG:
// ==UserScript==
// #name _YOUR_SCRIPT_NAME
// #include http://YOUR_SERVER.COM/YOUR_PATH/*
// #require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// #grant GM_getResourceText
// #grant GM_addStyle
// #grant GM_xmlhttpRequest
// #grant GM_getResourceURL
// ==/UserScript==
...
You're using unsafeWindow – that, as the name suggested, is not necessary "safe" to use – the problem probably relies there; a change was made in Firefox about objects across compartments:
https://blog.mozilla.org/addons/2014/04/10/changes-to-unsafewindow-for-the-add-on-sdk/
The blog post mention Add-on SDK, but the changes is in the platform, so it will affect Greasemonkey too.
So you basically try to get an object from one compartment (jQuery, from "unsafeWindow") and use in your greasemonkey sandbox. The way you're doing now probably can't work anymore. You can try to use the API mentioned in the article, but I'm afraid that a whole library like jQuery could have some issue to be cloned. In fact, the best way is probably load jQuery also in your Greasemonkey compartment instead of reuse the one from the page's one.
The error probably started "magically" 'cause you have updated your version of Firefox – or it gets the autoupdated.
This page explains how to load jQuery in a Greasemonkey script: http://wiki.greasespot.net/Third-Party_Libraries
The relevant parts are:
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
...
this.$ = this.jQuery = jQuery.noConflict(true);
According to the docs, jQuery.noConflict() will make sure the version of jQuery for your script won't interfere with the page.
See also: jQuery in Greasemonkey 1.0 conflicts with websites using jQuery

How to convert a bookmarklet into a Greasemonkey userscript?

Is there a easy way to do this. And is there anything that needs to be changed due to differences in how it is ran?
The easiest way to do this:
Run the bookmarklet code through a URL decoder. so that javascript:alert%20('Hi%20Boss!')%3B, for example, becomes:
javascript:alert ('Hi Boss!');
Strip the leading javascript: off.   Result: alert ('Hi Boss!');
Add this code to the end of your Greasemonkey file. For example, create a file named,
Hello World.user.js, with this code:
// ==UserScript==
// #name Hello World!
// #description My first GM script from a bookmarklet
// #include https://stackoverflow.com/questions/*
// #grant none
// ==/UserScript==
alert ('Hi Boss!');
Open Hello World.user.js with Firefox (CtrlO ).   Greasemonkey will prompt to install the script.
Now the bookmarklet code will run automatically on whatever pages you specified with the #include and #exclude directives.
Update: To ensure maximum compatibility, use the #grant none directive that was added in later versions of Greasemonkey and Tampermonkey.
IMPORTANT:
The userscript will run much sooner than you could ever activate a bookmark. Normally, this is not a problem.
But in some cases, you might need to wait for some part of the page to fully load.
In that case, you can use techniques/utilities like waitForKeyElements.
See also, Choosing and activating the right controls on an AJAX-driven site .
If you still can't get your new script to work, be sure to read My very simple Greasemonkey script is not running?. Follow the steps and include the specified information in any question you open about problems with the new script.
Here is a very good article to avoid common pitfalls because of differences between "normal" JS and Greasemonkey.
The most important things at the beginning:
Do not use functions as strings, like: window.setTimeout("my_func()", 1000); but rather
window.setTimeout(my_func, 1000); or
window.setTimeout(function(){doSomething(); doSomethingOther();}, 1000);
Do not set element.onclick but rather element.addEventListener("click", my_func, true);
Some code that normally returns various DOM objects, in Greasemonkey environment returns those objects wrapped in XPCNativeWrapper. This is for security reasons.
Some methods and properties are "transparent" and you can invoke them on wrapped object, but some not. Read in the mentioned article about how to circumvent this; you can also use (this is not recommended generally, but for testing etc.) wrappedJSObject property. It is, when obj.something/obj.something() doesn't work in Greasemonkey, try obj.wrappedJSObject.something/obj.wrappedJSObject.something().

Categories