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

Support document-start script run time #2526

Closed
arantius opened this issue Jul 25, 2017 · 17 comments
Closed

Support document-start script run time #2526

arantius opened this issue Jul 25, 2017 · 17 comments
Labels
bankruptcy Issues that have been closed for "bug bankruptcy". Usually very old non-active issues.
Milestone

Comments

@arantius
Copy link
Collaborator

Support document-start for @run-at.

See #2483 for more detail. This may be "impossible".

@ExE-Boss
Copy link

You can use the run_at property of the content_scripts manifest key.

@jakwings
Copy link
Contributor

jakwings commented Sep 4, 2017

I shared the pity about Chrome with you 4 years ago. Now again for Firefox. 😭

I'd like to rephrase my suggestion in https://bugs.chromium.org/p/chromium/issues/detail?id=257956

tabs.insertCSS/executeScript should insert CSS/JS until URL of the tab is set non-empty(not null, not undefined, not empty string ""), and be canceled if the tab is removed/changed

The WebExtension APIs should be improved.

@ExE-Boss
Copy link

ExE-Boss commented Sep 4, 2017

@iology why did you downvote my suggestion? It is perfectly valid. Plus, one can just use the content script to insert script tags into the document that contain the user scripts.

The following should explain how to do so using my method: (should work reliably)

/**
 * @typedef UserScript
 * @property {Object} header The parsed header of a script
 * @property {String} script The raw script data
 * @property {String} type The script media type (in case a script is WebAssembly
 *                         or something other than JavaScript)
 */

/** The load state of this script. Used by the `matches()` function */
const READY_STATE = document.readyState;

(async () => {
    (await (browser.storage.local.get({scripts: []}) // Excuse this horrible code style
        .then(ret => ret.scripts)))                  // of combining `await` and `.then()`
        .forEach(/* @param {UserScript} script */ script => {
            if (matches(script.header)) {
                let scriptTag = document.createElement("script");
                scriptTag.setAttribute("type", script.type)
                scriptTag.textContent = script.script;
                document.appendChild(scriptTag);
            }
        });
})();

/**
 * Checks if this script matches this page and @run-at property.
 * 
 * @param {Object} scriptHeader The parsed header of a script
 * @return {boolean} `true` if this page matches, `false` otherwise
 */
function matches(scriptHeader) {
    // Uses window.location and READY_STATE.
    // TODO: Implement
}

@jspenguin2017
Copy link

jspenguin2017 commented Sep 12, 2017

@ExE-Boss By the time you retrieve scripts from extension storage part of the page would already be loaded.

@ExE-Boss
Copy link

I am aware of that, but I don’t really see another way to do so because of the fact that WebExtensions are inherently asynchronous.

@Sxderp
Copy link
Contributor

Sxderp commented Sep 12, 2017

@ExE-Boss, there's a bugzilla, https://bugzilla.mozilla.org/show_bug.cgi?id=1332273, that looks like it's progressing nicely and should help resolve the @document-start issue. Whether it'll land for FF57, I'm not sure.

@jspenguin2017
Copy link

I am aware of that, but I don’t really see another way to do so because of the fact that WebExtensions are inherently asynchronous.

@ExE-Boss That's literally the problem we are trying to solve.

@ExE-Boss
Copy link

I am trying to solve it as well, but my solution really only works well enough for #2525, because by that point the entire page has fully loaded.

@jspenguin2017
Copy link

Violentmonkey has this problem as well, not sure what black magic Tampermonkey uses, but it is able to inject script reliably on the real document-start.

@ExE-Boss
Copy link

ExE-Boss commented Sep 12, 2017

Tampermonkey 2.9 and earlier was GPL-3.0 and published on GitHub. I’ve tried looking into it, and at first I thought it was using sync XHR, but after looking into it a bit, I have no idea how it achieves that, but it does that somehow because support for that was added in version 2.6.2767.

See here as to why Tampermonekey went closed source:

@jspenguin2017
Copy link

I'm not interested in pirating stuff, it won't be too hard to reverse Tampermonkey's logic but it's not legal to do that.

@Sxderp
Copy link
Contributor

Sxderp commented Sep 24, 2017

@ExE-Boss
Copy link

@Sxderp That’s only for Firefox 57, that bug might still be resolved in 58+.

@trlkly
Copy link

trlkly commented Oct 28, 2017

FYI, Tampermonkey isn't reliable at document-start, either. There is an "instant" injection option (which is extremely hacky) that speeds things up, but on simple pages like xkcd.com, I still get a flash before my CSS (which is always injected at document start) loads. I also occasionally get a flash on other sites.

Reversing Tampermonkey's code is not a way to figure this out. Plus, well, the actual methods they use can be found in their forums, suggested by other users. Copying a method isn't a copy-vio, just copying the code itself.

But we know it's an imperfect solution, and we want a perfect one.

@ccd0
Copy link

ccd0 commented Nov 16, 2017

If a method is found to make this work, could there be a way to for a script to read at least a subset of its configuration options synchronously? As an example of the kind of issues this would solve, see ccd0/4chan-x#1627. Here i need to disable some code on the page, but I also want to have an option not to disable the code. And many users clear localStorage at the end of each browser session.

@Sxderp
Copy link
Contributor

Sxderp commented Nov 16, 2017

If a method is found to make this work, could there be a way to for a script to read at least a subset of its configuration options synchronously?

Not in any short term. There's no way to communicate with the (get|set)Value storage in a synchronous manner. Perhaps some kind of injection on the part of GM wherein variables with config values are injected into the global scope of the script. That's the best I can think of, and that's not very nice.

@ccd0
Copy link

ccd0 commented Nov 16, 2017

Perhaps some kind of injection on the part of GM wherein variables with config values are injected into the global scope of the script. That's the best I can think of, and that's not very nice.

Presumably it would be part of the GM object. Something like GM.initValues.yourVariable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bankruptcy Issues that have been closed for "bug bankruptcy". Usually very old non-active issues.
Projects
None yet
Development

No branches or pull requests

7 participants