3

I have been trying to migrate an userScript into my own extension but for some reason I am not able to run the following code:

// ==/UserScript==
console.info('BEFORE Hooked! MONKEY');
(function() {
    'use strict';
    // Reference [Augular loaded detect]: https://stackoverflow.com/a/31970556/9182265
    var initWatcher = setInterval(function () {
        if (window.MegaUtils) {
            console.info(window.MegaUtils);
            clearInterval(initWatcher);
            hookImport();
            hookFull();
            console.info('FUNtions Hooked! MONKEY');
        }
    }, 500);
})();

But for some reason the IF statement is never TRUE, but the same exact code is run from ViolentMonkey, it works right away.

So window.MegaUtils is not been detected at all and i have no idea why. I was told that my extension might not have access to the DOM object but why ViolentMonkey does have access to it.

This is the manifest i am using when importing the extension in Chrome:

{
    "manifest_version": 2,
    "content_scripts": [ {
        "exclude_globs":    [  ],
        "include_globs":    [ "*" ],
        "js":               [ "mega.user.js" ],
        "matches":          [   "https://mega.nz/*",
                                "http://mega.nz/*" ],
        "run_at": "document_end"
    } ],
    "converted_from_user_script": true,
    "description":  "testing extension",
    "permissions": [],
    "name":         "MegaByPass",
    "icons": {
        "16": "images/mega-cloud-icon.png",
        "32": "images/mega-cloud-icon.png",
        "48": "images/download.png",
        "128": "images/873133.png"
      },
    "version":      "1.0"
}

source

Thanks in advance.

Chop Labalagun
  • 592
  • 1
  • 6
  • 19
  • Where is above code running? background script or content script? How is it injected? – erosman Jul 26 '20 at 04:42
  • I believe this is what you are asking: // @run-at document-end full source in: https://greasyfork.org/en/scripts/397876-mega-nz-ultimately-import/code – Chop Labalagun Jul 26 '20 at 05:10
  • No. I was asking how des the adon inject the above script? via `manifest.json` or `tabs.executeScript` or `contentScripts.register()` or `userScripts.register()` etc? – erosman Jul 26 '20 at 09:50
  • that is a good question, i am using a manifest.json but not sure how ViolentMonkey does it. how to find that out? I added my manifest to the question. – Chop Labalagun Jul 26 '20 at 18:58
  • Reply updated again with more info. – erosman Jul 28 '20 at 17:50

2 Answers2

1

To start with, remove the glob as it can cause issues.

"content_scripts": [
  {
    "matches": ["http://mega.nz/*", "https://mega.nz/*"],
    "js": ["mega.user.js"]
  }
]

ViolentMonkey injects by default at document-end. However, GM/VM/TM inject user-scripts manually and not using the dedicated API (FireMonkey in Firefox uses dedicated API), therefore the injection time may be later than when browser API injects.

Try with "document_idle" which is the default (you can leave it out).

Using "document_end" may result in the script running before the external Angualr is loaded and that can be the reason for the issue.

For proper testing, the actual extension is needed.

Update 1

Content scripts are injected into a different scope/context than the page that they are in. Therefore they can not directly interact with JS on the page and vice versa.

The global window behaviour is not uniform between different browsers (e.g. eval() in chrome always run in the context of the content script but in Firefox eval() runs in content scope but window.eval() in page scope).

After a quick testing, the content script doesn't have access to the global window & window.MegaUtils. There are ways to fix that but why the user-script works may have something to do with the way ViolentMonkey inject it or grants access to window object without using unsafewindow.

Have you tested the script with any other script managers?!! Does the script work on all script managers or only ViolentMonkey?

More Info:
Accessing all the window variables of the current tab in chrome extension
Insert code into the page context using a content script

PS. I only tested on Firefox as I don't use Chrome.

Update 2

Looking at Can't find page variables when used GM_ functions, it appears that GM|TM|VM may be injecting user-scripts into the page contents when there is @grant none (needs proper confirmation). That would explain why above user-script with @grant none works and can get window.MegaUtils in GM|TM|VM (not FM). In that case you would need to inject the script in the page JS.

Here is an example:

const script = document.createElement('script');
script.textContent = `(function() {
    'use strict';
    // Reference [Augular loaded detect]: https://stackoverflow.com/a/31970556/9182265
    var initWatcher = setInterval(function () {
        if (window.MegaUtils) {
            clearInterval(initWatcher);
            hookImport();
            hookFull();
            console.info('FUNtions Hooked!');
        }
    }, 500);
})();

....`;
document.body.appendChild(script);

Update 3 CSP

At the moment, browsers adhere to page CSP (Content Security Policy) which is the issue you refereed to in the comment.
ref:
[meta] Page CSP should not apply to content inserted by content scripts (V2 issue)
CSP 'sandbox' directive prevents content scripts from matching, due to unique origin, breaking also browser features [Screenshots]

There are ways around that but they are not standard and extensions shouldn't circumvent browser or page CSP.

erosman
  • 7,094
  • 7
  • 27
  • 46
  • Chrome will complain about removing matches and js fields so they have to be there to be able to import it. I give it a try with document_idle but the same behavior it never detects that window.MegaUtils. – Chop Labalagun Jul 27 '20 at 05:38
  • @ChopLabalagun For proper testing, the actual extension is needed. – erosman Jul 27 '20 at 11:58
  • You can get it from here: https://drive.google.com/drive/folders/1WFUfK7gl60rue-AweRc3qPPGeUGK6Hma?usp=sharing – Chop Labalagun Jul 27 '20 at 21:12
  • @ChopLabalagun Answer updated.. although the issue is not solved. – erosman Jul 28 '20 at 06:04
  • thank you for trying, this is very weird. i was expecting a very straight forward integration. – Chop Labalagun Jul 28 '20 at 17:04
  • Have you tested the script with any other script managers?!! yes, i have tried GreaseMonkey,ViolentMonkey and TamperMonkey all work just fine but the idea was to avoid a 3rd party app. – Chop Labalagun Jul 28 '20 at 20:56
  • @ChopLabalagun I asked about other script-manager to see if there was anything specific about ViolentMonkey (not to suggest using user-script) – erosman Jul 29 '20 at 04:38
  • thank you for your time, ill see if the link provided will take me somewhere but i am not JS developer so it might take me a while to get it. – Chop Labalagun Jul 29 '20 at 06:18
  • @ChopLabalagun check Update 2 – erosman Aug 01 '20 at 06:27
  • Thank you for your time, i am not sure if i am doing this wrong i am not a JS developer but when i did the modifications i got this: Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' *.mega.co.nz *.mega.nz data: blob:". Either the 'unsafe-inline' keyword, a hash ('sha256-GsXU05kU86ZbZmQ15AGDoOOUtnYnbKHnScj9JDmfWT4='), or a nonce ('nonce-...') is required to enable inline execution. can you review if i did it right: https://drive.google.com/file/d/1ZXyo5ZO1hviEYoQq0gd__IhuypSLiBUS/view?usp=sharing – Chop Labalagun Aug 01 '20 at 07:22
  • @ChopLabalagun Check Update 3 ..not a solution but just for information – erosman Aug 01 '20 at 08:33
  • Thanks, ill investigate to see if there is a workaround. – Chop Labalagun Aug 01 '20 at 09:19
  • content_security_policy on the manifest did the trick, you'll be getting the answer to this. thank you for your time, i really appreciate it. – Chop Labalagun Aug 01 '20 at 09:37
0

I'm pretty sure user_script instead of content_script is the way to go.

This API offers similar capabilities to contentScripts but with features suited to handling third-party scripts:

  • access to the window and document global values related to the webpage the user script is attached to.

https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/userScripts

It works a bit different though, still trying to understand it :)