Error: Permission denied to access property 'handler' - javascript

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

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());
});
});
})();

Why does "#grant randominvalidsetting" activate the sandbox?

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.)

Calling a function before the document loads up in JS

My friend asks me to do this.
He needs to prevent his children from going to certain websites.
He has tamper monkey installed with chrome. I have to make a script in tamper-monkey so that when it reaches the website it will change the web content.
The source code is:
// ==UserScript==
// #name My Fancy New Userscript
// #namespace http://use.i.E.your.homepage/
// #version 0.1
// #description enter something useful
// #match http://www.harmful-website.com/*
// #copyright 2012+, You
// ==/UserScript==
document.write("<b>You are not allowed to visit this site</b>");
This script works only after the web-site is loaded full. But his children stop the loading of website in the middle and they are able to view a part of it.
Even document.onload=function(){document.write("...");} works after load. Are there any way to make the script run before the document is loaded i.e. Immediately after the web address is typed on the address bar or hyperlink is clicked.
Your code will work, you just need to set #run-at document-startDoc, like so:
// ==UserScript==
// #name site blocker
// #match http://www.harmful-website.com/*
// #run-at document-start
// ==/UserScript==
document.write ("<b>You are not allowed to visit this site</b>");
Important:
This will work, for now, on Chrome and with Tampermonkey, but it does not work on other browsers. For example, on Firefox, the document.write call will throw the error:
Error: The operation is insecure.
(But the page will still be completely blank.)
Although a userscript like this will work (mostly); it is a klugey, brittle, low performance approach and is easily defeated. Here are just a few ways that are better, faster, easier, and harder for savvy kids to kibosh:
Use your home router's siteblock and/or parental controls. Almost every router and/or modem has this feature, these days.
Install one of the many extensions that do this kind of blocking.
Block the site with an Adblock rule.
Block the site with the machine's hosts file.
Use a proxy server.
Search on Super User for more options.
Just call the function right after you define it. Like in the header or somehwere.
However, you need to consider if the function has actually everything it requires, like HTML elements on the page if it access any of them, as those won't necessarily be loaded when calling your function.
HTML file is parsed row by row. So if your write your < script > just after < html > tag it will be executed before anything else.

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().

Greasemonkey #require jQuery not working "Component not available"

I've seen the other question on here about loading jQuery in a Greasemonkey. Having tried that method, with this require statement inside my ==UserScript== tags:
// #require http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
I still get the following error message in Firefox's error console:
Error: Component is not available
Source File: file:///Users/greg/Library/Application%20Support/
Firefox/Profiles/xo9xhovo.default/gm_scripts/myscript/jquerymin.js
Line: 36
This stops my greasemonkey code from running. I've made sure I included the #require for jQuery and saved my js file before installing it, as required files are only loaded on installation.
Code:
// ==UserScript==
// #name My Script
// #namespace http://www.google.com
// #description My test script
// #include http://www.google.com
// #require http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
// ==/UserScript==
GM_log("Hello");
I have Greasemonkey 0.8.20091209.4 installed on Firefox 3.5.7 on my Macbook Pro, Leopard (10.5.8). I've cleared my cache (except cookies) and have disabled all other plugins except Flashblock 1.5.11.2, Web Developer 1.1.8 and Adblock Plus 1.1.3.
My config.xml with my Greasemonkey script installed:
<UserScriptConfig>
<Script filename="myscript.user.js" name="My Script"
namespace="http://www.google.com" description="My test script" enabled="true"
basedir="myscript">
<Include>http://www.google.com</Include>
<Require filename="jquerymin.js"/>
</Script>
I can see jquerymin.js sat in the gm_scripts/myscript/ directory.
Additionally, is it common for this error to occur in the console when installing a Greasemonkey script?
Error: not well-formed
Source File: file:///Users/Greg/Documents/myscript.user.js
Line: 1, Column: 1
Source Code:
// ==UserScript==
I found a non-ideal way to use it with jQuery 1.4.1 -- this seems to fix it. It's the new browser sniffing that seems to "break" it.
jquery-1.4.1.min.js:
[old] 36: var o=r.createElement("div");n="on"+n;var m=n in o;
[new] 36: var o=r.createElement("div");n="on"+n;var m=true;
jquery-1.4.1.js
[old] 934: var isSupported = (eventName in el);
[new] 934: var isSupported = true;
Ok, so i looked into this a bit more deeper. I used your script exactly, but used our JQuery version, making it look like this:
// ==UserScript==
// #name My Script
// #namespace http://www.google.com
// #description My test script
// #include http://www.google.se/*
// #include http://www.dn.se/*
// #require http://myserver/jquery-1.3.2.js
// ==/UserScript==
GM_log("Hello");
This works just fine for me, my guess, the JQuery up on the google api is missing some functions. Because this code above, works just fine. Also note the /* at the end of each url, please include that.
Try another JQuery and change the urls and it should world properly.
I was stumbling around trying to deal with this issue with GM 0.8 and jquery 1.4.2 and found this: http://forum.jquery.com/topic/importing-jquery-1-4-1-into-greasemonkey-scripts-generates-an-error
It looks to me like the definitive answer to the question and how to work around it. The workaround worked for me.
Good news and updating all postings:
The above patch allowed pre-1.5.2 jQuery versions to be run in Greasemonkey scripts, but fortunately the patch is no longer required if you use the current jQuery 1.5.2 version.
I checked its code and noticed that the eventSupported function code in jQuery
var eventSupported = function(eventName) { ... }
has been updated with the consequence that unpatched jQuery 1.5.2 now runs in Greasemonkey 0.9.2.
Patch for jquery-1.4.3.min.js
[old] line 41
u.createElement("div");s="on"+s;var
B=s in v; [new] line 41
u.createElement("div");s="on"+s;var
B=true;
The #require attribute doesn't work correctly in Greasemonkey and jQuery...this same error can occur in FireBug as well.
An alternative is to include jQuery in the page via Greasemonkey by creating the script tag. Here's how to do that.
Not entirely true, it seems like jQuery 1.4 tries to detect something using a call that just doesn't work in the greasemonkey environment. #require does normally work as it should.
So reverting to 1.3.2 does do the trick, but I'd rather find a solution that lets me use 1.4.
btw, I use this, slightly different:
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js
Here's a minified version of jQuery 1.4.4 for Greasemonkey:
http://userscripts.org/scripts/show/92329
Hope it helps,
yah

Categories