quoid / userscripts

An open-source userscript manager for Safari

Home Page:https://quoid.github.io/userscripts/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can't access Browser Page via popup's `Open Extension Page` button

ar-rm opened this issue · comments

commented

Overview:

I've been unable to access the Browser Page for a few months.

Userscripts: 4.4.5 (82)
Safari: 16.5

Steps:

  • Click the Userscripts icon in the Safari toolbar
  • Click Open Extension Page

Result:

  • Nothing
  • No errors in the Safari console, Console.app, etc.

Other info:

  • All of my user scripts seems to be working as expected.
  • I tried running Inspect Element via the toolbar Popup menu. But it dismisses as soon as I try to interact with the Userscript popup.
  • I tired Develop > Web Extension Background Content > Userscripts. But again, no errors.
  • I've searched through the issues here and don't think I found anything similar. Apologies if I missed something.

I've been treating this mostly as an inconvenience, since I can edited my user scripts directly via their .js files in ~/Library/Containers/Userscripts/Data/Documents/scripts

But it does mean that I can't get to the Settings modal.

Questions:

  • Is there an alternate way I can reach the Browser Page?
    • Maybe directly via a URL?
  • What other steps could I take to help out the developers?

Thanks!

I am wondering if you would see an error in the background page if the openExtensionPage function failed from the popup...

You could try to open the browser dev tools for the popup by right clicking anywhere in the popup and selecting Inspect Element. From there you'd want to click Open Extension Page in the popup and see if any errors get logged, but I think doing that might close the popup. Alternatively, once the dev tools open and you navigate to the console, you could run document.querySelector(".link").click() and see if anything gets logged.

I don't have a Safari browser that old running on my machine.

Also, what OS version are you on?

This is strange because the code for the button is fairly simple:

export const extensionPaths = {
page: "/dist/entry-page.html",
popup: "/dist/entry-popup.html"
};
export async function openExtensionPage() {
const url = browser.runtime.getURL(extensionPaths.page);
const tabs = await browser.tabs.query({url});
const tab = tabs.find(e => e.url.startsWith(url));
if (!tab) return browser.tabs.create({url});
browser.tabs.update(tab.id, {active: true});
browser.windows.update(tab.windowId, {focused: true});
}

You can try to evaluate the code line by line in the popup console if you have basic JS knowledge.

But I think that's not the issue where is.
And yes you should be able to open the extension page this way.

I think it's more likely that there's a issue with some other part of the popup that's preventing further functionality.

One trick is that after you open the Inspect Element of the popup, press ⌘R(Command + R) in the interface, it will force reload the popup, see if any logs will appear in the console?

Then as @quoid said, use JS way to perform click operations in the console. (cause your interaction with the popup will cause both to close) But under normal circumstances, clicking the button will also cause both to close, but the extension page will be opened at the same time.

<button class="link" on:click={() => { openExtensionPage(); window.close(); }}>

At the end, if you'd like, send us a screen recording of your operation process. This will help us check for any details you might not have noticed.

commented

Thanks for the quick replies.

I am wondering if you would see an error in the background page if the openExtensionPage function failed from the popup...

Good thought.

Result:
No, I don't see any errors

You could try to open the browser dev tools for the popup by right clicking anywhere in the popup and selecting Inspect Element. From there you'd want to click Open Extension Page in the popup and see if any errors get logged, but I think doing that might close the popup.

Agreed. I've tried that too and you're right. The entire dev tools window closes.

Alternatively, once the dev tools open and you navigate to the console, you could run document.querySelector(".link").click() and see if anything gets logged.

Result:
Nothing

I also selected Open Extension Page and ran $0.click() with Open Extension Page selected.

Result:
The same. Dev tools closes and I don't see any errors.

Also, what OS version are you on?

macOS 12.6.5

(Sorry for leaving that out before.)


This is strange because the code for the button is fairly simple:

Agreed.

You can try to evaluate the code line by line in the popup console if you have basic JS knowledge.

I do. I'm also familiar with Svelte.

But I can't seem to get any type of readout because the dev tools closes too soon.

I've tried to set breakpoints, but again, it closes before I can inspect anything.

One trick is that after you open the Inspect Element of the popup, press ⌘R(Command + R) in the interface, it will force reload the popup, see if any logs will appear in the console?

Ahh. I didn't know about that.

Result:
No errors

At the end, if you'd like, send us a screen recording of your operation process. This will help us check for any details you might not have noticed.

I can do that eventually. But so far, there's nothing to report other than the button not working.


I was able to enable the All Events breakpoint in the Sources tab and then command-r (via the suggestion above).

It stopped in a few places but it was a little tricky to see what was going on because the popup-{hash}.js code is minified. But nothing weird jumped out at me (of course, I could be wrong).

The best I was able to generate was the following Warning in the console:

window.styleMedia is deprecated draft version of window.matchMedia API that is not implemented in Firefox and will be removed from the web platform in future.

I do. I'm also familiar with Svelte.
But I can't seem to get any type of readout because the dev tools closes too soon.

The problem is very strange if evaluating the original JS has no effect in the popup console.
And evaluating these codes should not close the console window immediately. (before executing the last 3 lines)
The console window should only disappear when the popup is closed. Which means unless a focus change occurs.
These APIs exist in the extension environment and can be executed directly, they have nothing to do with the popup code.
And, you can also execute the codes in the background page console.

browser.runtime.getURL("/dist/entry-page.html");

The above code should print out the URL of the extension page.
Or you pass window.location.href in the popup console and then manually splice the URL.
You can then paste it in the address bar of the new tab.
See if you can open the extension page.
Note that the extension URL will change every time you open Safari.
And the relative URL of the extension page will also change in future versions.

commented

The console window should only disappear when the popup is closed. Which means unless a focus change occurs.

I'm not sure what role losing focus is playing. I've tried opening the Inspector and clicking around with other Extensions, and they too lose focus pretty easily.

But in in the case of Ghostery, I'm able to click a button to its Settings page, which spawns a new tab in the main window. Which is what I expect (and use to work) with Userscripts.

And, you can also execute the codes in the background page console.

browser.runtime.getURL("/dist/entry-page.html");

The above code should print out the URL of the extension page.

Yes! Very helpful.

This worked. I was able to manually get to the Extension Page via the URL that it returns.

If I run the following from within the Popup's Inspector window, the url is opened... in the actual toolbar popover. Ha! But that's expected.

window.location.href = browser.runtime.getURL("/dist/entry-page.html");


I did some more testing and was able to enable the event breakpoint directly on <button class="link">Open Extension Page</button>

Screen Shot 2024-01-28 at 7 48 50 PM

Then I used document.querySelector(".link").click() to generate the event.

The debugger went to a spot in popup-{hash}.js.

The first part of the specifically highlighted code was:

const wt=()=>{Bt(),window.close()}

Screen Shot 2024-01-28 at 7 45 02 PM

I searched the repo for window.close() and found 3x results

I think this (Line 583) is the unminified/non-compiled equivalent, given the back-to-back function calls:

{#if !inactive && platform === "macos"}
<div class="footer">
<button
class="link"
on:click={() => {
openExtensionPage();
window.close();
}}
>
Open Extension Page
</button>
</div>
{/if}

(Although I can't say that with certainty because of the Svelte compile process.)

The above code looks exactly right (go to the Extension Page and then close() the popup). The other instances of window.close() seem correct as well.

I'm not sure what role losing focus is playing. I've tried opening the Inspector and clicking around with other Extensions, and they too lose focus pretty easily.

What I mean is when the popup window loses focus, like if you click on anything outside the popup it will cause the popup to close. browser.tabs.create(); will lead to the same result.

This is a Safari issue and it does make debugging extension popups more difficult, but there's nothing we can do about it. All we can do is understand its quirks and possibly work around those inconveniences.

So when I suggest that you evaluate that code line by line, I expect that you should debug the return value of each line of code, not just evaluate them all.

So I still look forward to your debugging to see if there are other possibilities, such as the inability to query the corresponding tab through browser.tabs.query() or the inability to create the tab through the API.

As for the issue of code minimization, maybe we should study SourceMap to make debugging the code less difficult while maintaining the advantages of code minimization. (but probably should be limited to beta versions)

I think this (Line 583) is the unminified/non-compiled equivalent...

I've actually given in the comment above where the code for this version is, it's obvious. Note that you should never use the latest code in the main branch for reference, it is different from the extension version you are running.

commented

So when I suggest that you evaluate that code line by line, I expect that you should debug the return value of each line of code, not just evaluate them all.

I had a feeling that's what you meant. I just wasn't looking forward to it :-)

In a relatively short amount of time, I was able to get the "Extension Page" to open as if it was triggered via the "Open Extension Page" button. But I think I'm going to need your help tracking down the precise reason.

Steps:

  • Enable the breakpoint for all events on .link
  • Go to the minimized popup.js in Sources
  • Set a breakpoint on Line 10 (which contains the window.close() that I think is the culprit)
  • Use $1.click() to trigger .link
  • Step over a few functions until... Voilà!

Result:

  • The popup closes and the "Extension page" opens in a new tab!

I have to repeat the steps above and copy the code that's highlighted just before the result. This is it:

, vt = () => t(6, f = !1), Ct = () => t(18, U = !1), yt = () => t(18, U = !1), It = () => { t(21, M = !1), ne() };
return r.$$.update = () => { r.$$.dirty[0] & 1 && t(24, l = i.sort((g, O) => g.name.localeCompare(O.name))), r.$$.dirty[0] & 2 && C && document.body.classList.add(C) }, [i, C, n, s, o, c, f, m, u, w, v, A, S, L, K, Z, q, z, U, y, W, M, le, te, l, b, $, ke, a, T, we, ne, ve, me, se, ut, at, _t, dt, mt, pt, bt, gt, ht, kt, wt, vt, Ct, yt, It]
}
class Ll extends ae { constructor(e) { super(), _e(this, e, Pl, Nl, de, {}, null, [-1, -1]) } } new Ll({ target: document.getElementById("app") });

I don't know why setting that breakpoint, and then stepping over (or into) the functions that followed, allowed the "Extension Page" to open.

I'm not sure how to track it down beyond this.

I hope this helps.

So I still look forward to your debugging to see if there are other possibilities, such as the inability to query the corresponding tab through browser.tabs.query() or the inability to create the tab through the API.

Running browser.tabs.query() in the console (while inspecting the popup) returns: Error: Invalid call to tabs.query(). A required argument is missing.

But I'm probably doing that wrong.

As for the issue of code minimization, maybe we should study SourceMap to make debugging the code less difficult while maintaining the advantages of code minimization. (but probably should be limited to beta versions)

👍🏻

window.close() that I think is the culprit

Yes, you reminded me of that, and I think that's the root cause of the issue.

We should:

{
	await openExtensionPage();
	window.close();
}

Otherwise, window closing may interrupt the previous async function.

But I'm probably doing that wrong.

Yes, I am just referencing the API, it is not the code that can be run directly. You need to refer to the original code line to fill in the parameters.

Anyway, thanks for helping us find the issue, I'll fix it in the next version.

@ar-rm Please try the latest beta version to see if your issue is resolved:
https://github.com/quoid/userscripts/releases/tag/v4.5.0-beta.5

Please note that in the beta version the settings page also has a new entrance in the Safari -> settings/preferences -> extensions.

commented

window.close() that I think is the culprit

Yes, you reminded me of that, and I think that's the root cause of the issue.

We should:

{
  await openExtensionPage();
  window.close();
}

Otherwise, window closing may interrupt the previous async function.

Great idea.

But I'm probably doing that wrong.

Yes, I am just referencing the API, it is not the code that can be run directly.

It tripped me up because saw how browser, browser.tabs, and browser.tabs.query() are all available in the DevTools for the popup.

But as I found, don't work as I expected (and what you wrote).

Anyway, thanks for helping us find the issue, I'll fix it in the next version.

Cool. Thank you!

@ar-rm Please try the latest beta version to see if your issue is resolved: https://github.com/quoid/userscripts/releases/tag/v4.5.0-beta.5

✅ Confirmed working.

Please note that in the beta version the settings page also has a new entrance in the Safari -> settings/preferences -> extensions.

Good idea. I was thinking that too.

Also, thanks for enabling Source Maps:

Screen Shot 2024-01-31 at 9 56 03 PM

So much nicer to debug :-)

It would be handy if they could be user-enabled in production builds (Maybe: In "Settings"?) because of exactly cases like this. But I can also understand why that might be a bad idea and maybe not even possible.


Thank you again for looking into this and for the very useful (and well made) extension.

commented

Also, thanks for enabling Source Maps:

So much nicer to debug :-)

I may have spoke a moment too soon.

The original bug is fixed. But I'm noticing that one of my scripts isn't working as it did just before installing v4.5.0-beta.5:

Open-Source Alternative Redirector

It's definitely injecting and working/redirecting for some domains, but not YouTube.

I think there might be a conflict between the addition of the sourcemaps (Global scope?) and whatever one of the billion scripts YT does:

Screen Shot 2024-01-31 at 10 15 04 PM

If this is a necessary consequence of a beta build + sourcemaps, that's ok. I can just downgrade until the next normal release.

It tripped me up because saw how browser, browser.tabs, and browser.tabs.query() are all available in the DevTools for the popup.
But as I found, don't work as I expected (and what you wrote).

I don't understand what you are saying.

It would be handy if they could be user-enabled in production builds (Maybe: In "Settings"?) because of exactly cases like this. But I can also understand why that might be a bad idea and maybe not even possible.

We would like to do this, but considering that the usage of this feature is not high, and it will greatly increase the size of the installation package, bringing it to all general users is unnecessary, which will cause a waste of traffic and space.
So we think that turning it on only in the beta version is a compromise. Users who need to test and perform debugging can simply be advised to install the beta version.

It's definitely injecting and working/redirecting for some domains, but not YouTube.
I think there might be a conflict between the addition of the sourcemaps (Global scope?) and whatever one of the billion scripts YT does:

Can't reproduce, it works as expected on me. And I don't think there will be a conflict between them.
BTW, A better way to implement this type of redirection is through declarativeNetRequest (@run-at request).

commented

I don't understand what you are saying.

  • Open the Devtools for the popup
  • Go to the Console
  • Enter browser or browser.tabs
  • RESULT: Both are available objects
  • The query() function is also available on browser.tabs, but executing it generates the error: Error: Invalid call to tabs.query(). A required argument is missing.

It would be handy if they could be user-enabled in production builds (Maybe: In "Settings"?) because of exactly cases like this. But I can also understand why that might be a bad idea and maybe not even possible.

We would like to do this, but considering that the usage of this feature is not high, and it will greatly increase the size of the installation package, bringing it to all general users is unnecessary, which will cause a waste of traffic and space.

Understood.

So we think that turning it on only in the beta version is a compromise. Users who need to test and perform debugging can simply be advised to install the beta version.

Yeah.

I was thinking of the cases where a bug in the most recent version is found but there isn't yet a beta version of it to test.

Or is there always an available corresponding TestFlight equivalent of the currently released version?


It's definitely injecting and working/redirecting for some domains, but not YouTube.
I think there might be a conflict between the addition of the sourcemaps (Global scope?) and whatever one of the billion scripts YT does:

Can't reproduce, it works as expected on me. And I don't think there will be a conflict between them.

Hum. Ok.

  • I installed the new version.
  • Confirmed the popup fix.
  • And then immediately noticed the error/lack of redirect.
  • Which made me think it must have had something to do with the sourcemaps (or whatever else changed between version).

I'll reinstall the Userscripts beta and try to debug the script.

BTW, A better way to implement this type of redirection is through declarativeNetRequest (@run-at request).

Oh, that's cool.

Maybe I'll rewrite the relevant portions of the script using that.

Will this make the redirects faster (iow: happen earlier in the injection) or is it just more robust? (or both)

Thanks.

commented

@ar-rm Will this make the redirects faster (iow: happen earlier in the injection) or is it just more robust? (or both)

I just did some experimenting with this.

Yes much faster!

But I did run into this issues as well: #491

I need to do more testing.

The query() function is also available on browser.tabs...

I think I explained it clearly enough above, this is an browser extension API and you need to fill in the parameters. Just like the error text tells you.

I was thinking of the cases where a bug in the most recent version is found but there isn't yet a beta version of it to test.
Or is there always an available corresponding TestFlight equivalent of the currently released version?

We don't care about peer versions or historical versions. Because we can always only fix bugs in the latest version.
Usually there will be a newer beta version out there, if not, please just wait.
You can always compile and run any version from source, or fix and contribute code yourself.
Pushing to the App store and TestFlight is a convenience, for which developers need to pay annual fees and time maintenance. Enable sourcemap is also a balanced convenience, and we can't cater for all edge cases.

Will this make the redirects faster (iow: happen earlier in the injection) or is it just more robust? (or both)

Yes, it's earlier, could before the request is sent. Please read the API documentation for more information.

commented

The query() function is also available on browser.tabs...

I think I explained it clearly enough above, this is an browser extension API and you need to fill in the parameters. Just like the error text tells you.

You did. I was just clarifying.

Usually there will be a newer beta version out there, if not, please just wait.

Ok.

You can always compile and run any version from source, or fix and contribute code yourself. Pushing to the App store and TestFlight is a convenience, for which developers need to pay annual fees and time maintenance. Enable sourcemap is also a balanced convenience, and we can't cater for all edge cases.

Understood.

Thank you for the time and expense.

@ar-rm Thank you also for taking the time to report and debug this issue, and thank you for your contribution to the project.