Sidepanel must be opened in response to a user gesture

1,602 views
Skip to first unread message

Cory Cooper

unread,
Jul 24, 2024, 3:16:14 PMJul 24
to Chromium Extensions
After Chrome 127, some users and developer are seeing the following error:
sidePanel.open()` may only be called in response to a user gesture

We open the sidepanel from clicks in the content script and our web app app Scribehow.com and they no longer work in Chrome 127. The documentation says that you should be able to trigger an open from a click in the content script.

This appears to be a bug in a change behind some flag (not everyone can reproduce).

We're suspicious of this deprecation given the language around "3rd party storage and communications".

Any help is appreciated.


Eduardo Fungairino

unread,
Jul 24, 2024, 3:26:17 PMJul 24
to Chromium Extensions, Cory Cooper
We are observing the same behavior in our extension, our e2e test that opens the sidepanel based on user gesture is consistently failing.

Todd Schiller

unread,
Jul 24, 2024, 5:09:10 PMJul 24
to Eduardo Fungairino, Chromium Extensions, Cory Cooper
We've opened a bug ticket because we also see Chrome crash consistently when a user gesture is performed for some users on Version 127.0.6533.73 (Official Build) (arm64): https://issues.chromium.org/issues/355266358

--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/32f9f344-06a5-41c5-a02b-17abf004faffn%40chromium.org.

Ja Wattanawong

unread,
Jul 25, 2024, 3:39:36 AMJul 25
to Chromium Extensions, Todd Schiller, Chromium Extensions, Cory Cooper, Eduardo Fungairino
We're seeing this issue for users of our extension on Chrome 127 who also have 1Password (2.26.1) installed on both macOS and Windows.

Patrick Kettner

unread,
Jul 25, 2024, 9:17:31 AMJul 25
to Ja Wattanawong, Chromium Extensions, Todd Schiller, Cory Cooper, Eduardo Fungairino
Thanks for the report!

@eduardo - can you share the specific reproduction you are seeing fail?

@Todd Can you provide specific crash IDs? You can find them in chrome://crashes/



Graham Langford

unread,
Jul 25, 2024, 2:23:41 PMJul 25
to Chromium Extensions, Patrick Kettner, Chromium Extensions, Todd Schiller, Cory Cooper, Eduardo Fungairino, Ja Wattanawong
Here's a crash id: 71bc12c4089532de

The crash appears to require 1password to be installed _and_ the devtools to be open and docked. 

Also, if the devtools are undocked, then redocked, then the crash does not occur.

I'm currently working on a minimal reproduction. For additional context, the user is triggering an event using an affordance (button or context menu) injected by a content script. The service worker is then calling the sidePanel.open API and throwing the user gesture error. We have a fallback in case of the error to try again (user clicks a button in an injected dialog), and that is succeeding if 1password is _not_ installed. If it is installed, then the error is thrown again. 

We are not seeing this behavior in previous versions of Chrome

Graham Langford

unread,
Jul 25, 2024, 3:56:06 PMJul 25
to Chromium Extensions, Graham Langford, Patrick Kettner, Chromium Extensions, Todd Schiller, Cory Cooper, Eduardo Fungairino, Ja Wattanawong
I've created a minimum repro that can be found here: https://github.com/pixiebrix/chrome-user-gesture-repro

The readme includes detailed instructions to reproduce
Message has been deleted

Graham Langford

unread,
Jul 25, 2024, 4:56:45 PMJul 25
to Chromium Extensions, Graham Langford, Patrick Kettner, Chromium Extensions, Todd Schiller, Cory Cooper, Eduardo Fungairino, Ja Wattanawong
I should also note that the crash looks to be caused by an unhandled exception in our Extension that was exposed by the thrown user gesture error. 

We are also seeing the error be thrown with and without 1password installed. Though 1Password must be installed to replicate in the minimal repro. I'm not certain what is causing the difference

Aaron Podolny

unread,
Jul 26, 2024, 2:59:02 AMJul 26
to Chromium Extensions, Graham Langford, Patrick Kettner, Chromium Extensions, Todd Schiller, Cory Cooper, Eduardo Fungairino, Ja Wattanawong
@Patrick - Just wanted to emphasize that from our perspective the bigger problem here is that `sidePanel.open` no longer works from a content script, which breaks meaningful functionality in our (and other) extensions. Maybe the root cause is also what is causing the crash, but regardless hoping the Chrome team can get a fix out for this soon. Thanks for your help!

Aaron Podolny

unread,
Jul 26, 2024, 2:59:02 AMJul 26
to Chromium Extensions, Graham Langford, Patrick Kettner, Chromium Extensions, Todd Schiller, Cory Cooper, Eduardo Fungairino, Ja Wattanawong
@Patrick - Just wanted to emphasize that from our perspective the bigger problem here is that `sidePanel.open` no longer works from a content script, which breaks meaningful functionality in our (and other) extensions. Maybe the root cause is also what is causing the crash, but regardless hoping the Chrome team can get a fix out for this soon. Thanks for your help!
On Thursday, July 25, 2024 at 12:56:06 PM UTC-7 Graham Langford wrote:

Aaron Podolny

unread,
Jul 26, 2024, 2:59:02 AMJul 26
to Chromium Extensions, Graham Langford, Patrick Kettner, Chromium Extensions, Todd Schiller, Cory Cooper, Eduardo Fungairino, Ja Wattanawong
@Patrick - Just wanted to emphasize that from our perspective the bigger problem here is that `sidePanel.open` no longer works from a content script, which breaks meaningful functionality in our (and other) extensions. Maybe the root cause is also what is causing the crash, but regardless hoping the Chrome team can get a fix out for this soon. Thanks for your help!
On Thursday, July 25, 2024 at 12:56:06 PM UTC-7 Graham Langford wrote:

Graham Langford

unread,
Jul 26, 2024, 9:11:46 AMJul 26
to Chromium Extensions, Aaron Podolny, Graham Langford, Patrick Kettner, Chromium Extensions, Todd Schiller, Cory Cooper, Eduardo Fungairino, Ja Wattanawong
It looks that the root cause of `sidePanel.open` no longer working from a content script is reproducible by including a mousedown listener in the content script. See the repro here: https://github.com/pixiebrix/chrome-user-gesture-repro. No need to have 1Password installed

Aamir Mansoor

unread,
Jul 30, 2024, 3:16:25 PMJul 30
to Chromium Extensions, Cory Cooper
I can confirm this issue affects our users on v127+ too, with no workaround available.

A bug report at https://issues.chromium.org/issues/40929586 was marked as “won’t fix”.

Any updates, Chrome team?

Cory Cooper

unread,
Jul 31, 2024, 5:09:03 AMJul 31
to Chromium Extensions, Aamir Mansoor, Cory Cooper
Here I have documented our learnings:

https://issues.chromium.org/issues/40929586#comment20

Patrick Kettner

unread,
Jul 31, 2024, 6:37:38 AMJul 31
to Cory Cooper, Chromium Extensions, Aamir Mansoor
Hi everyone!
This was a unintended side effect from this change. A fix was added yesterday, which lands it in 129.0.6628.0. The team is working on backporting it to Chrome 128, as of now it is unlikely to be fixed in 127.

patrick

--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.

Graham Langford

unread,
Jul 31, 2024, 11:45:21 AMJul 31
to Chromium Extensions, Patrick Kettner, Chromium Extensions, Aamir Mansoor, Cory Cooper
Hi Patrick, 

Thanks for the update! I've confirmed that I'm no longer able to reproduce the issue in Chrome Canary. Is there any update on backporting to Chrome 128? Also, this is a pretty major issue for our Extension, is there no chance we can get it in a hotfix for 127?

Patrick Kettner

unread,
Jul 31, 2024, 11:50:32 AMJul 31
to Graham Langford, Chromium Extensions, Aamir Mansoor, Cory Cooper
Hey Graham!
No change since my last update - the team is working on backporting it to Chrome 128, as of now it is unlikely to be fixed in 127.

Cory Cooper

unread,
Sep 15, 2024, 12:17:57 PMSep 15
to Kaj Kandler, Chromium Extensions, Patrick Kettner, Aamir Mansoor, Graham Langford
If you are calling sidepanel.open() in a callback, .then(), or after an “await”, that does not work on any occasion. You must call it synchronously after the click handler is fired (i.e. synchronously in your browser message event handler). 

On Sun, Sep 15, 2024 at 9:11 AM Kaj Kandler <confic...@gmail.com> wrote:
Hi Patrik, hi Cory,
I face this very same issue in the `chrome.action.onClicked.addListener(function () {...}`

It seems not be fixed for my use case in current Beta `Version 129.0.6668.42 (Official Build) beta (arm64)`

I try to get the current tabId (tabs.query) and get the sidepanel options for the tab, then toggle the sidepanel. All inside my worker script.

Should that case be fixed as well?

Kaj Kandler

unread,
Sep 15, 2024, 1:21:30 PMSep 15
to Chromium Extensions, Patrick Kettner, Chromium Extensions, Aamir Mansoor, Cory Cooper, Graham Langford
Hi Patrik, hi Cory,
I face this very same issue in the `chrome.action.onClicked.addListener(function () {...}`

It seems not be fixed for my use case in current Beta `Version 129.0.6668.42 (Official Build) beta (arm64)`

I try to get the current tabId (tabs.query) and get the sidepanel options for the tab, then toggle the sidepanel. All inside my worker script.

Should that case be fixed as well?
On Wednesday, July 31, 2024 at 5:50:32 PM UTC+2 Patrick Kettner wrote:

Kaj Kandler

unread,
Sep 15, 2024, 1:21:30 PMSep 15
to Chromium Extensions, Cory Cooper, Chromium Extensions, Patrick Kettner, Aamir Mansoor, Graham Langford, Kaj Kandler
Thanks Cory for your reply

Are you sure about that? For me this works just fine (in 128...)

chrome.action.onClicked.addListener(function () {

console.log("extension button clicked");
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
const activeTab = tabs[0];
const tabId = activeTab.id;
console.log("open sidepanel");
chrome.sidePanel.setOptions({
tabId,
path: 'sidepanel.html',
enabled: true
});
chrome.sidePanel.open({
tabId
});
});
});

Only when I start reading the `chrome.sidepanel.getOptions();` It starts failing

Cory Cooper

unread,
Sep 15, 2024, 10:37:11 PMSep 15
to Kaj Kandler, Chromium Extensions, Patrick Kettner, Aamir Mansoor, Graham Langford
I guess not 100% but that’s been my experience thus far. Also, I think you can run setOptions after it’s already opened which might address your issue?

Max Nikulin

unread,
Sep 18, 2024, 7:07:43 AMSep 18
to chromium-...@chromium.org
On 15/09/2024 23:17, 'Cory Cooper' via Chromium Extensions wrote:
> If you are calling sidepanel.open() in a callback, .then(), or after an
> “await”, that does not work on any occasion. You must call it
> synchronously after the click handler is fired (i.e. synchronously in
> your browser message event handler).

User gesture context is a rather bizarre beast. In Firefox it is
insanely strict and really does not allow even a callback to read
settings from storage. In Chromium it seems single step callback (e.g.
the slowest one when multiple API calls are fired in parallel) works well.

Even await is possible if
1. The extension has the scripting permission,
2. The menu option is selected fast enough after opening context menu.

The following works for permissions.request as well. Credits: Rob Wu
<https://stackoverflow.com/questions/28060485/can-a-chrome-extensions-content-script-guarantee-that-a-dom-event-was-user-init>

---- 8< -----

{
"manifest_version": 3,
"name": "Open sidebar",
"description": "sidePanel.open() and user gesture context",
"version": "0.1",
"permissions": ["scripting", "activeTab", "contextMenus", "sidePanel"],
"background": { "service_worker": "asp_bg.js" }
}

---- 8< ----

"use strict";

async function aspOnClicked(tab, click) {
const frameId = click?.frameId;
const tabId = click?.tabId ?? tab.id;
await chrome.sidePanel.setOptions({ path: "asp_panel.html" });
// Fails
try {
console.log("after await", await chrome.sidePanel.open({tabId}));
} catch (ex) {
console.error("after await", ex);
}

// May work
console.log(
"content script",
await chrome.scripting.executeScript({
target: { tabId, allFrames: false, frameIds: [ frameId ] },
func: async function asp_cs(tabId) {
return await chrome.runtime.sendMessage(
{type: "open", tabId});
},
args: [ tabId ],
}));
}

chrome.contextMenus.onClicked.addListener(
(clickData, tab) => void aspOnClicked(tab, clickData));
chrome.runtime.onInstalled.addListener(async () => {
await chrome.contextMenus.removeAll();
chrome.contextMenus.create({
id: "ASP",
title: "open sidebar", contexts: ["all"]
});
});

chrome.runtime.onMessage.addListener((msg, _port, sendResponse) => {
async function asp_msg(tabId) {
try {
console.log(
"from content script",
await chrome.sidePanel.open({tabId}));
return true;
} catch (ex) {
console.error("from content script", ex);
return false;
}
}
asp_msg(msg.tabId).then(r => sendResponse(r));
return true;
});

Kaj Kandler

unread,
Sep 19, 2024, 7:34:46 AMSep 19
to Chromium Extensions, Max Nikulin

Thank you Max,
for helping to collect more information.

However, I don't try to react to a user event in the host page space (injected script). All I try to do is get a sidepanel to be only open for the tabs I ever opened it.

For that I had to set NO default_panel in the manifest. Only then I receive the `chrome.action.onClicked` event in the background script. Interesting difference, in 128 it does only fire once, in 129 it fires every time it is clicked.

I'm able to `chrome.sidePanel.setOptions` and then `chrome.sidePanel.open`.

There is no `chrome.sidePanel.close` to close it on a second click. But the Little (x) button does hide it again.

It's really a pain to not have a documented way to open a side panel only on select tabs, such as the "Developer Tools" behave.

I'd wish that there was simply a mode to have a side panel global or only where ever opened. I don't want to inject a user script on every page after I activated my sidepanel.

Kaj Kandler

unread,
Sep 19, 2024, 11:07:15 AMSep 19
to Chromium Extensions, Max Nikulin
Heureka,
I got it working the way I wanted it - https://github.com/KajKandler/ext_sidepanel_per_tab

The sidepanel is only active per tab and I believe I only inject the user script into the pages where it the sidepanel has been opened once. I hav eno idea if it ever has been closed.

The user script sends the current URL via message to the worker and from there to the sidepanel.

I'm open to comments or suggestions how to make this better.

On Wednesday, September 18, 2024 at 1:07:43 PM UTC+2 Max Nikulin wrote:
Reply all
Reply to author
Forward
0 new messages