I'm new to greasemonkey and trying to understand how greasemonkey is different from the embedded web console. A simple script which works perfectly on web console does not work on greasemonkey, and I have no idea why.
Firefox 74.0 on Arch Linux
Greasemonkey 4.9
Here is the test script I use:
(function() {
"use strict";
const w = window.open('https://www.google.com/', 'w');
console.log("Hello");
w.onload = () => {
console.log("World");
};
})();
When I access https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr&pws=0 (Google US top page), copy and paste the script into web console, and then execute it,
A new window w
loading https://www.google.com/ is opened.
The string Hello
is printed.
The string World
is printed.
Everything is as expected.
On greasemonkey, I use the script below. The header part is the only difference.
// ==UserScript==
// @name test
// @namespace n
// @match https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr&pws=0
// ==/UserScript==
(function() {
"use strict";
const w = window.open('https://www.google.com/', 'w');
console.log("Hello");
w.onload = () => {
console.log("World");
};
})();
When I access https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr&pws=0 (Google US top page),
A new window w
loading https://www.google.com/ is opened.
The string Hello
is printed.
SecurityError
is thrown saying
Script error in [Greasemonkey script n/test]:
SecurityError: Permission denied to access property "onload" on cross-origin object test:42:19
user-script:n/test:42
When I use unsafeWindow
instead of window
,
A new window w
loading https://www.google.com/ is opened.
The string Hello
is printed.
And nothing else happens. (No error, no World
)
How should I modify the script so that is can be executed on greasemonkey?
Update
According to this comment, the script works on Tampermonkey or Violentmonkey under Chrome.
I haven't confirmed this but have confirmed that the script works on Tampermonkey 4.10.6105
or Violentmonkey 2.12.7
under Firefox.
Web Console is part of browser scope while a GreaseMonkey script is injected into a page content and its scope it limited to that page only.
You can open a new tab/window from page content with GM but that window/tab will have its own page content scope which is separate from the first one. Therefore, you can not access properties belonging to another tab/window from a page content of different tab.
This separation is for all content scripts and not only for GM. Otherwise, it would have created a great security risk if JS in one tab/page could access data on other tabs.
Update:
As pointed out by wOxxOm, the CSP and cross-origin policy prevents Cross-Origin Resource Sharing (CORS).
In your example, in Firefox, the first issue is that Firefox will "Block pop-up windows" from the content script.
Testing Firefox dedicated userScripts API on FireMonkey, after allowing popup, still causes an error:
SecurityError: Permission denied to access property "onload" on cross-origin object
In this case, I believe it is due to the sandboxing of userScripts for security.
GM/TM/VM do not use the userScripts API and use other means to inject userSripts which results in different outcome.