web-ext icon indicating copy to clipboard operation
web-ext copied to clipboard

Unable to open the Extensions page with --start-url when running in Chrome

Open ghostwords opened this issue 5 years ago • 29 comments

Is this a feature request or a bug?

Bug

What is the current behavior?

Running an extension in Chrome with --start-url "chrome://extensions" (or "about:extensions") fails to open the Extensions page. (The extensions page is useful for inspecting your extension's background page.)

Using --start-url to open about:debugging does work in Firefox.

Versions

Chrome 84 web-ext 5.0.0

ghostwords avatar Jul 29 '20 17:07 ghostwords

It seems that Chrome does ignore chrome://extensions (also other chrome:// urls, like chrome://version) passed on the command line, e.g. executing on the command line

google-chrome http://developer.mozilla.org

does start Chrome with the given url loaded in the first tab

On the contrary:

google-chrome chrome://version

does start Chrome but it doesn't load that chrome url in the first tab.

I have the feeling that this may be an intended behavior, I briefly looked if Chrome does provide a command line flag to override this behavior, but at the moment I haven't spotted any that may be related.

We may have to close this as a wontfix if we don't have a way to tell Chrome to allow chrome:// urls as start urls, but for now I'm keeping this open to take another look and think a bit if there may be other options to achieve that.

rpl avatar Jul 31 '20 18:07 rpl

Chrome extensions can open many chrome:-pages.

Rob--W avatar Jul 31 '20 18:07 Rob--W

Chrome extensions can open many chrome:-pages.

that's true, and I just verified that chrome://extensions is one of those that can be opened successfully using chrome.tabs.create, and so one option to fix this in web-ext would be to special case the chrome://extension url (or any chrome url) in the chrome extension runner and make the companion extension that we install automatically to auto-reload the target extension able to call chrome.tabs.create for us.

rpl avatar Jul 31 '20 18:07 rpl

I'll mentor this bug.

Rob--W avatar Aug 06 '20 13:08 Rob--W

Hi @Rob--W !

May I work on this bug? If yes, can I have the STR? I went through https://extensionworkshop.com/documentation/develop/getting-started-with-web-ext/, but a little more clarity on where chrome comes into the picture will be more helpful. Thanks!

DeepikaKaranji avatar Aug 10 '20 12:08 DeepikaKaranji

@DeepikaKaranji Taking a step back, the core of the issue is that trying to open chrome://extensions doesn't work from the command line. Extensions are able to do so though, by passing that url to chrome.tabs.create.

web-ext uses a helper extension (via createReloadManagerExtension) in Chrome to support its functionality. To resolve this bug you have to forward the URL to that helper extension instead of the command line. The relevant source code is around these lines: https://github.com/mozilla/web-ext/blob/9353e260d016a6c301cac520fbdc57d5e3e89375/src/extension-runners/chromium.js#L153-L227

With those two code snippets, you can probably get started. Let me know if there are still questions!

Rob--W avatar Aug 11 '20 00:08 Rob--W

Hey @DeepikaKaranji, how's it going with this issue?

caitmuenster avatar Sep 14 '20 16:09 caitmuenster

Hello @caitmuenster , I was AFK for a bit, I've set up the environment, and I have gotten started with this issue yesterday.

DeepikaKaranji avatar Sep 15 '20 06:09 DeepikaKaranji

@Rob--W

How I thought I'll approach this was:

  1. See what gets called when I run google-chrome http://developer.mozilla.org from command line.
  2. From that, understand which variable exactly holds the URL that is being passed in command line.
  3. See where that http URL is getting passed.
  4. Find out when the createReloadManagerExtension is actually called.
  5. And of course, other in-between things I need check as I work.

What I've understood/ not understood so far:

  1. createReloadManagerExtension() is called everytime ChromiumExtensionRunner object is instantiated.
  2. bg.js is run as a background task, but I'm not sure where to find bg.js to see what it does, and if I actually need to worry about it.
  3. I can see that setEnabled has some extensionID and values in it, which is what I think I should carry the chrome:- URL, but I'm not too clear on why its being passed as a string to setEnabled. I could also use some help in understanding how to log these values to see if chrome:- URL is actually getting passed there when I do eventually write my logic. https://github.com/mozilla/web-ext/blob/bd2974b47c2ed80dd5f6d7b3afb755aed6660c61/src/extension-runners/chromium.js#L312-L331
  4. Can you also please tell me how I can achieve Step-1 in my above approach? Thank you.

DeepikaKaranji avatar Sep 23 '20 16:09 DeepikaKaranji

@Rob--W

How I thought I'll approach this was:

  1. See what gets called when I run google-chrome http://developer.mozilla.org from command line.

This step is incorrect. I think that the misunderstanding is that you think that you need to change the behavior of how google-chrome [url] is handled. That is not the case; how Chrome handles command-line flags is not something that we can control.

google-chrome http://developer.mozilla.org works, and is not a surprise.
google-chrome chrome://extensions does not, however. That's why we want to filter that URL, and open it via the helper extension (in bg.js) instead. So the part to change is what parameters are passed to the Chrome binary (i.e. without chrome://extensions) and forward the URL in a different way instead (see below).

  1. bg.js is run as a background task, but I'm not sure where to find bg.js to see what it does, and if I actually need to worry about it.

bg.js is written to a temporary directory that is loaded as a background page of the helper extension. That directory is loaded as an extension via the --load-extension flag for Chrome.

  1. I can see that setEnabled has some extensionID and values in it, which is what I think I should carry the chrome:- URL, but I'm not too clear on why its being passed as a string to setEnabled. I could also use some help in understanding how to log these values to see if chrome:- URL is actually getting passed there when I do eventually write my logic.

setEnabled is not the interesting part. Rather, the part that handles the communication between the web-ext application and the helper extension is. A WebSocket is used for communication, and the message is received and handled at the ws.onmessage listener in bg.js. I suggest to look at how the (only) existing message is sent (you can search/grep for the message type in the code base) to try and understand how the communication happens.

Rob--W avatar Sep 23 '20 22:09 Rob--W

Hey @DeepikaKaranji, how's it going with this issue?

caitmuenster avatar Oct 12 '20 16:10 caitmuenster

Hi @caitmuenster ! I already spoke to @Rob--W and told him that have some exams going on right now. I will resume work on 20th October. He said its alright, so I hope its okay.

DeepikaKaranji avatar Oct 12 '20 16:10 DeepikaKaranji

No worries at all, @DeepikaKaranji! :) Good luck on your exams!

caitmuenster avatar Oct 12 '20 16:10 caitmuenster

@Rob--W @caitmuenster can I work on this issue, I have a rough idea about the solution now after reading the above conversation...

ariain avatar Oct 13 '20 19:10 ariain

Hi @ariain , I have already started working on this, will make the PR soon. I hope that is okay. Thanks for understanding :)

DeepikaKaranji avatar Oct 13 '20 19:10 DeepikaKaranji

Hi @ariain, there are some other good-first-bugs in our add-ons repositories if you'd like to work on one of those. It looks like this issue on the code manager repo is currently open, as is this issue in the webextension-polyfill repo.

caitmuenster avatar Oct 13 '20 19:10 caitmuenster

@DeepikaKaranji I totally understand... @caitmuenster I would like to work on them, thanks for suggesting...

ariain avatar Oct 13 '20 20:10 ariain

@Rob--W I wrote a small test in test-chromium.js (which I know isn't entirely right), so as to pass the "chrome://" urls and catch them.

it('does open chrome:// urls', async () => {
   const {params} = prepareExtensionRunnerParams({
      params: {startUrl: 'chrome://extensions'},
    });
    const runnerInstance = new ChromiumExtensionRunner(params);
    await runnerInstance.run();

    const {reloadManagerExtension} = runnerInstance;

    sinon.assert.calledOnce(params.chromiumLaunch);
    sinon.assert.calledWithMatch(params.chromiumLaunch, {
      ignoreDefaultFlags: true,
      enableExtensions: true,
      chromePath: undefined,
      chromeFlags: [
        ...DEFAULT_CHROME_FLAGS,
        '--load-extension=${reloadManagerExtension},/fake/sourceDir',
      ],
      startingUrl: 'chrome://extensions',
    });
    await runnerInstance.exit();
  });

I added the below snippet at line 221 in chromium.js:

if (startingUrl.startsWith('chrome://')) {
        console.log('*********** CAUGHT ************');
        console.log(this.params.extensions);

        this.reloadManagerExtension = await this.createReloadManagerExtension();
        // Start chrome pointing it to a given profile dir
        const PseudoExtension = [this.reloadManagerExtension].concat(
          this.params.extensions.map(({sourceDir}) => sourceDir)
        ).join(',');
        console.log(PseudoExtension);
      }
      chromeFlags.push(...startingUrls);
    }

I called it PseudoExtension because from you have mentioned that Extensions are able launch "chrome://" URLs. I also think I should remove chromeFlags.push(), because my assumption is that any normal url is being added to the chromeFlags string array - to be executed by command line.

But in this case, I need to prevent that from happening, and pass the "chrome://" url to the createReloadManagerExtension helper extension.

The test however does not work, but I just wanted to check if I'm on the right track. Thank you!

DeepikaKaranji avatar Oct 20 '20 18:10 DeepikaKaranji

The test expectation is incorrect. The chrome://extensions URL shouldn't be on the command line at all (because Chrome's command line does not support the chrome:-URL, which is what this bug is about).

I don't know what you're trying to do with the PseudoExtension. There is already an extension (the reload manager). You don't have to load a new extension or anything like that, just send a message to the existing extension.

Rob--W avatar Oct 20 '20 20:10 Rob--W

Alright, I'll do that, thanks.

DeepikaKaranji avatar Nov 10 '20 06:11 DeepikaKaranji

Hey @DeepikaKaranji, just wanted to check in with you about this issue. Are you still interested in working on it?

caitmuenster avatar Mar 01 '21 17:03 caitmuenster

Hey @DeepikaKaranji, we are going to open this up to other contributors since we haven't heard from you in awhile. If you'd like to finish it off, please feel free to come back to it! O

caitmuenster avatar Mar 15 '21 16:03 caitmuenster

Hello @caitmuenster, I was looking for good-first-issues in the add-ons repositories and this one seemed ideal - may I work on it?

CatWithNineLives avatar Aug 10 '21 19:08 CatWithNineLives

Go for it, @CatWithNineLives! If you need any help, please tag [@]Rob--W in a comment.

caitmuenster avatar Aug 10 '21 20:08 caitmuenster

Hey @CatWithNineLives, we haven't heard from you in awhile so we're going to open this up to other contributors. If you want to work on it, please feel free to submit a PR. :)

caitmuenster avatar Sep 13 '21 16:09 caitmuenster

Hi @caitmuenster, I saw this issue a few days ago and realized that it's open for contribution. I would like to work on this bug and hopefully fix it if I may? :)

kodergeek avatar Sep 16 '21 18:09 kodergeek

Hey @Rob--W. I have looked a bit in the code and based on your comments above, I believe I have an understanding how to fix this bug.

I have made some changes at chromium.js to detect presence of chrome://extensins in the url array list, and have added necessary code for Websocket communications also at chromium.js and chromium.js

My issue at the moment is that I can't seem to find the appropriate location in code to invoke the new websocket communication openTabWithExtensionsUrl() method which is supposed to communicates with bg.js, and get it to work. I invoke openTabWithExtensionsUrl() in chromium.js method setupInstance() after line this.chromiumInstance = await this.chromiumLaunch is run, which supposedly would launch chrome. But this has no effect, and when I look closely, at that stage wssBroadcast() isn't able to send messages to bg.js, because number of wss clients is zero. (code execution ends up in if (clients.size === 0) )

I tried to confirm this by testing what happens when I swap the current websocket message with the new one I created when R is pressed, so that whenever you press R to reload it sends the new message instead of webExtReloadAllExtensions, and then I can see that a new tab is being opened and loads chrome's extension page.

I'm not sure if there is some extra action taking place outside of chromium.js before which chrome is fully loaded, and asynchronous JavaScript isn't my strong side, so I'm a bit confused in the multitude of asyncs and promises used in code, so I'd appreciate if you could give me some tips. My current commit is available at https://github.com/kodergeek/web-ext/blob/bug-1979/src/extension-runners/chromium.js

kodergeek avatar Sep 22 '21 07:09 kodergeek

You could wait for the first WebSocket connection and post the initialization message to open the extension tab.

Feel free to open a pull request for work-in-progress code; then it is easier to provide feedback at specific lines.

Rob--W avatar Sep 22 '21 09:09 Rob--W

Thanks for your feedback. I have created a pull request so you can point to specific lines easily.

https://github.com/mozilla/web-ext/pull/2321

kodergeek avatar Sep 22 '21 17:09 kodergeek