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

Firefox window/tab is closed when reloading source code

Open slhck opened this issue 5 years ago • 5 comments

Is this a feature request or a bug?

Both, I guess?

What is the current behavior?

  • Run a web extension using web-ext run
  • Open a source file (e.g. HTML) belonging to the web extension in one tab
  • Modify the underlying source code and save
  • The tab with the open file closes, along with it the entire Firefox window

This is quite frustrating when, e.g., editing a complex HTML layout. Every time the layout is saved, the tab is closed. If it is the last tab, the entire Firefox window disappears (under macOS, at least). In order to get back to the HTML file I was editing, I have to open a new tab and copy-paste the URL I was previously editing, or find it in the history.

What is the expected or desired behavior?

When opening one or more tabs, and saving a source file of the extension, the currently open tab(s) should not close, but instead remain open and get reloaded.

Particularly, when only one tab is open, reloading the source code should not close the Firefox window.

This behavior may not be wanted, so a command line flag or option to prevent this kind of reloading would also come in handy. Note that I am not talking about --no-reload, as the code should be reloaded, but it's the tab(s) that should not be closed.

Version information (for bug reports)

  • Firefox version: 64.0
  • Your OS and version: macOS 10.13
  • Paste the output of these commands:
$  node --version && npm --version && web-ext --version
v11.5.0
6.4.1
2.9.3

slhck avatar Jan 03 '19 11:01 slhck

@slhck That's true, any tab which contains an extension page related to the extension being reloaded is going to be closed, but it is not web-ext run that is closing these tabs, they are actually closed by Firefox itself when the extension is shutting down as part of the extension reload (e.g. you can verify that the behavior would be the same if you open "about:debugging#addons" into a separate window and reload the extension from there).

Nevertheless, I agree that during development this behavior can be annoying, and so I'm not closing this bug as invalid even if technically this is a behavior implemented on the Firefox side, and I'm going to take a look into which strategy we may prefer to improve it (e.g. we may implement it on the Firefox side as some sort of "dev-mode only behavior", or web-ext run may check if there is any extension page opened in a tab before reloading the extension, navigate it to about:blank before reloading the extension and then navigate it back to the extension page once the extension has been reloaded).

In the meantime, as a workaround that can be achieved from the web-ext run side:

you may keep open at least one additional tab that is not an extension page (e.g. you may add a tab open on "about:addons" or "about:debugging" by including additional --start-url options to the web-ext run command), this way the Firefox window will not be closed automatically when the "extension tab page" is closed automatically by the auto-reload, and then pressing the keyboard shortcut for re-opening the last closed tab should bring the closed extension tab page back.

rpl avatar Jan 03 '19 12:01 rpl

Thanks for your reply! I now understand the underlying issue.

The workaround with keeping one other tab open is manageable, but of course it would be great if a more native kind of reloading was supported.

slhck avatar Jan 03 '19 13:01 slhck

I found a simple workaround to this. When the extension is reloading i have a simple background script that opens the options-ui page.

browser.management.getSelf().then(({ optionsUrl: url }) => {
  browser.tabs.create({ active: true, url })
})

For other pages u can simply get the extension id and open another page:

browser.management.getSelf().then((ext) => {
  const match = ext.optionsUrl.match(/moz-extension:\/\/(.+)\/.*/)
  if (match) {
    const id = match[1]
    browser.tabs.create({ active: true, url: `moz-extension://${id}/options.html` })
  }
})

You need to have the tabs permission enabled.

janstuemmel avatar Jul 06 '22 14:07 janstuemmel

To open the options page, you could just use the browser.runtime.openOptionsPage() method instead - https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/openOptionsPage

Rob--W avatar Jul 07 '22 13:07 Rob--W

Another hack.

It creates a new window with one empty tab and one tab with desired page. Saves window-id to localStorage. (Session storage is cleared between reloads).

On reload it check if the window exists and reuse it.

Point being one can resize, position, reuse, ... same window.

Optionally use a window-id from another routine (e.g. the returned window_id).

Optionally set default size, position etc. via the rect argument.

(Intended for temporary use.)

const open_page = async (url = '/popup/index.html', window_id = null, rect = {}) => {
	// Key used for localStorage
	const key = 'wid-' + browser.runtime.getURL(url);
	window_id = window_id || parseInt(localStorage.getItem(key));
	if (isNaN(window_id))
		window_id = null;
	// Check if window still exists.
	if (window_id !== null) {
		await browser.windows
		.get(window_id)
		.catch(() => window_id = null);
	}
	// Create new window if old not found.
	if (window_id === null) {
		await browser.windows.create(rect)
		.then(win => {
			window_id = win.id;
			localStorage.setItem(key, window_id);
		});
	}
	// Add desired tab.
	browser.tabs.create({url, windowId: window_id});
	return window_id;
};

Nickwiz avatar Aug 08 '23 10:08 Nickwiz