Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebExt: Support all GM APIs #2484

Closed
arantius opened this issue Mar 3, 2017 · 19 comments
Closed

WebExt: Support all GM APIs #2484

arantius opened this issue Mar 3, 2017 · 19 comments
Milestone

Comments

@arantius
Copy link
Collaborator

arantius commented Mar 3, 2017

https://wiki.greasespot.net/Greasemonkey_Manual:API

The Greasemonkey APIs are generally privileged actions, and generally all synchronous actions. Content scripts have (almost) no API access, and thus must pass messages to perform privileged actions. Web extensions only get asynchronous message passing (citation needed).

So each method has its own challenges.

Easier:

  • GM_getResourceURL must produce a result synchronously, but is trivial to calculate.
  • GM_addStyle is trivial.
  • GM_log should probably be retired, or just mapped to console.log.
  • GM_openInTab functionally produces no result, even ordering is not critical.
  • GM_registerMenuCommand has no synchronous behaviors.
  • GM_setClipboard produces no result.
  • GM_xmlhttpRequest is fully asynchronous.

Harder:

  • GM_deleteValue produces no result. Ordering still matters (i.e. delete of X must happen before any future set of X).
  • GM_setValue is equivalent to delete. No synchronous result, but ordering matters.

Very hard:

  • GM_getValue must produce a result synchronously.
  • GM_listValues must produce a result synchronously. (Plus AFAICT storage gives no good backing API. The only option is to fetch one value by name, or fetch all names and values. With no way to even segregate e.g. by script.)
  • GM_getResourceText must produce a result synchronously, and they may be very large values. (I.e. pre-caching them all in memory is likely too expensive.)
@arantius arantius added this to the 4.0 milestone Mar 3, 2017
@the8472
Copy link
Contributor

the8472 commented Mar 12, 2017

bug1323433 and bug1332273 may be of interest here.

@arantius
Copy link
Collaborator Author

Thanks for the pointers, I agree those are both super useful.

@arantius
Copy link
Collaborator Author

Oh, maybe some amount of synchronous message passing is possible!

https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/onMessage#Sending_a_synchronous_response

Test this. Does this make it possible to use a simple synchronous implementation (backed by background-only APIs) for those methods called out above?

@the8472
Copy link
Contributor

the8472 commented Mar 13, 2017

That returns a promise on the content side, so it is effectively async. i think "synchronous" is a misnomer here, it's more like pairing a message from child to parent with a response so that one does not have to manually keep track of pending responses.

Afaik the only synchronous API available are sync XHRs which then could be intercepted with webrequest or something like that.

@ArkadiuszMichalski
Copy link

ArkadiuszMichalski commented May 1, 2017

Sync XHR not work properly in content script: https://bugzilla.mozilla.org/show_bug.cgi?id=1360968, so at now we don't have any sync channel from content > background.

Looks like GM_setValue and GM_getValue was designed as sync operation and in single procecss browser they works just fine when we operate in multiple tabs, but in e10s no (#2427). With the old extenstion API it can be easily repaired, but in WebExt not. Without sync message (even for small data, just only emit short value) we can't properly sync value beetwen more tabs. at some point this will always be a race condition.

Regardless how you solve the above issues in WebExt version we should get new set/get method designed in async manner, so where it's important we can write the script in a async way. Documentations should have some information about lack GM_setValue and GM_getValue behaviour when operate on multiple tabs.

@tiansh
Copy link
Contributor

tiansh commented May 2, 2017

imo, it is rare use cases that using GM_setValue / GM_getValue on multiple tabs and the order must be followed. as a result, storage a copy (cache) of GM_values in content script, read always from cache, write back async, and update cache with events triggered by background script should be an acceptable solution.


btw, if so, add an API equivalent to GM_addValueChangeListener is great if possible. (and i dislike the name addValueChangeListener something else should be better maybe

@arantius
Copy link
Collaborator Author

In my dev branch there is support for:

  • GM.getResourceURL
  • GM.deleteValue, GM.getValue, GM.listValues, GM.setValue

I plan to never add:

  • GM_log
  • GM_addStyle

We still need:

  • GM_xmlhttpRequest

I plan to delay (or maybe drop):

  • GM_registerMenuCommand (this one has always been a huge support cost)
  • GM_getResourceText

Which means progress here is actually quite close.

@arantius arantius reopened this Jul 25, 2017
arantius added a commit to arantius/greasemonkey that referenced this issue Jul 25, 2017
@arantius
Copy link
Collaborator Author

Good feedback at above commit, don't forget.

@tiansh
Copy link
Contributor

tiansh commented Jul 27, 2017

I just have a try on the new add-on. It seems that cross domain xhr request had already been enabled without GM_xhr features. Is this indeed behavior?

Just try a userscript grant none with following codes:

fetch(prompt()).then(resp => resp.text()).then(text => alert(text)).catch(error => alert(error));

@arantius
Copy link
Collaborator Author

Ugh, confirmed. We're currently executing user scripts as "content scripts" -- of the extension, with all the extension's permissions.

@arantius
Copy link
Collaborator Author

I've looked into this a bit but so far I'm in the dark as to how to execute unprivileged ("web scope" -- what do we call this now that "content" scope is ambiguous?!) code. The closest thing I can find is all about creating script tags, which can/will be blocked by the page's CSP, which I definitely don't want.

@the8472
Copy link
Contributor

the8472 commented Aug 16, 2017

Currently the only way to modify CSP is intercepting and modifying the headers for every Document request. There are open issues to exempt webextensions from content CSPs but there doesn't seem to be much activity on those.

Besides injecting <script> tags window.eval should also run in the page scope, I think.

The official terms are "content script scope" vs. "page scope".

Another issue is that they would need string-processing to wrap them in a separate scope that could define the GM APIs.

I have also filed a bug for Sandbox equivalents in webextensions, but it's not high priority either.

@arantius
Copy link
Collaborator Author

AIUI both script and eval are vulnerable to blockage by CSP. But I have confirmed that eval drops privileges.

@arantius
Copy link
Collaborator Author

https://bugzilla.mozilla.org/show_bug.cgi?id=1391669

We must have <all_urls> if we're going to potentially run a content script at any page. If we ask for that, then our content script gets that, and thus can XHR to anywhere.

At least in Firefox ( https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts#Using_eval()_in_content_scripts ) we can drop down to page scope, but then we're truly page scope and we can't safely expose APIs to the script without exposing it to anything/everything running in the page (AFAIK), which is even worse.

@quilloss
Copy link

Can fetch and xhr be overwritten in the content script?
Maybe provide a modified fetch that does its own CORS check.

@arantius
Copy link
Collaborator Author

@jakwings
Copy link
Contributor

jakwings commented Sep 4, 2017

@the8472 See my implementation of withUnsafeWindow() in #2232 (comment)

It mimics the behavior of the old with (object) ... function, just a little bit safer. (Need modern browsers.)

@adamhotep
Copy link

@arantius wrote on Jul 25:

I plan to never add:

GM_log
GM_addStyle

These were denoted in the creation of this ticket (by @arantius on Mar 3) as trivial (assuming a mapping of GM_log to console.log).

In my experience, these are two of the most commonly used API calls. Wouldn't abandoning them break a lot of old scripts for no reason? Or were you exclusively referring to the dev branch?

@eight04
Copy link

eight04 commented Sep 14, 2017

In Tampermonkey, GM_addStyle has a special ability to inject style which can bypass CSP restriction (in case inline <style> is forbidden). I'll be glad if we can have this feature in Greasemonkey too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants