From 35ad3836ccc79e16e18b4aaf3d0f75327286cc9e Mon Sep 17 00:00:00 2001 From: Misha Holtz Date: Wed, 31 Aug 2022 16:18:53 -0700 Subject: [PATCH 1/7] Add alert for failed sidebar injection in extension console --- src/background/browserAction.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/background/browserAction.ts b/src/background/browserAction.ts index 04a85a9d1b..bbbdc470fd 100644 --- a/src/background/browserAction.ts +++ b/src/background/browserAction.ts @@ -20,14 +20,25 @@ import { ensureContentScript } from "@/background/util"; import { Tabs } from "webextension-polyfill"; import { rehydrateSidebar } from "@/contentScript/messenger/api"; import { executeScript, isScriptableUrl } from "webext-content-scripts"; +import webextAlert from "@/background/webextAlert"; +import { isMac } from "@/utils"; // The sidebar is always injected to into the top level frame const TOP_LEVEL_FRAME_ID = 0; async function handleBrowserAction(tab: Tabs.Tab): Promise { const url = String(tab.url); + + const extensionConsoleUrl = browser.runtime.getURL(""); + + if (url.startsWith(extensionConsoleUrl)) { + const keyboardShortcut = `${isMac() ? "Cmd+Opt" : "Ctrl+Shift"}+C`; + webextAlert( + `Tip: If you want to create a new blueprint, first navigate to the page you want to modify, then open PixieBrix in DevTools (${keyboardShortcut}).` + ); + } + if (!url.startsWith("http") || !isScriptableUrl(url)) { - // Page not supported. Open the options page instead void browser.runtime.openOptionsPage(); return; } From 92035bc2191826edef2aaa2dc0c91291221241c6 Mon Sep 17 00:00:00 2001 From: Misha Holtz <36575242+mnholtz@users.noreply.github.com> Date: Thu, 1 Sep 2022 09:25:38 -0700 Subject: [PATCH 2/7] target the options page specifically to display alert Co-authored-by: Federico Brigante --- src/background/browserAction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/background/browserAction.ts b/src/background/browserAction.ts index bbbdc470fd..ae62ba5170 100644 --- a/src/background/browserAction.ts +++ b/src/background/browserAction.ts @@ -29,7 +29,7 @@ const TOP_LEVEL_FRAME_ID = 0; async function handleBrowserAction(tab: Tabs.Tab): Promise { const url = String(tab.url); - const extensionConsoleUrl = browser.runtime.getURL(""); + const optionsPage = browser.runtime.getURL("options.html"); if (url.startsWith(extensionConsoleUrl)) { const keyboardShortcut = `${isMac() ? "Cmd+Opt" : "Ctrl+Shift"}+C`; From 5f2e91323988f63f76dc31326d086bdf7244d06f Mon Sep 17 00:00:00 2001 From: Misha Holtz <36575242+mnholtz@users.noreply.github.com> Date: Thu, 1 Sep 2022 09:25:57 -0700 Subject: [PATCH 3/7] remove keyboard shortcut nesting Co-authored-by: Federico Brigante --- src/background/browserAction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/background/browserAction.ts b/src/background/browserAction.ts index ae62ba5170..53e784e142 100644 --- a/src/background/browserAction.ts +++ b/src/background/browserAction.ts @@ -32,7 +32,7 @@ async function handleBrowserAction(tab: Tabs.Tab): Promise { const optionsPage = browser.runtime.getURL("options.html"); if (url.startsWith(extensionConsoleUrl)) { - const keyboardShortcut = `${isMac() ? "Cmd+Opt" : "Ctrl+Shift"}+C`; + const keyboardShortcut = isMac() ? "Cmd+Opt+C" : "Ctrl+Shift+C"; webextAlert( `Tip: If you want to create a new blueprint, first navigate to the page you want to modify, then open PixieBrix in DevTools (${keyboardShortcut}).` ); From ee426461f00eec2e8b4f84d323d7f35d07728468 Mon Sep 17 00:00:00 2001 From: Misha Holtz Date: Thu, 1 Sep 2022 10:06:58 -0700 Subject: [PATCH 4/7] add options page to alert condition --- src/background/browserAction.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/background/browserAction.ts b/src/background/browserAction.ts index 53e784e142..fd68de9b72 100644 --- a/src/background/browserAction.ts +++ b/src/background/browserAction.ts @@ -31,7 +31,7 @@ async function handleBrowserAction(tab: Tabs.Tab): Promise { const optionsPage = browser.runtime.getURL("options.html"); - if (url.startsWith(extensionConsoleUrl)) { + if (url.startsWith(optionsPage)) { const keyboardShortcut = isMac() ? "Cmd+Opt+C" : "Ctrl+Shift+C"; webextAlert( `Tip: If you want to create a new blueprint, first navigate to the page you want to modify, then open PixieBrix in DevTools (${keyboardShortcut}).` From 36944008240c1cd103dd73599c91c5fc8972d92f Mon Sep 17 00:00:00 2001 From: Misha Holtz Date: Fri, 2 Sep 2022 13:53:33 -0700 Subject: [PATCH 5/7] add messenger to options --- src/background/browserAction.ts | 21 +++++++++++++++ src/options/messenger/api.ts | 25 +++++++++++++++++ src/options/messenger/registration.ts | 39 +++++++++++++++++++++++++++ src/options/options.tsx | 2 ++ 4 files changed, 87 insertions(+) create mode 100644 src/options/messenger/api.ts create mode 100644 src/options/messenger/registration.ts diff --git a/src/background/browserAction.ts b/src/background/browserAction.ts index fd68de9b72..9b4d08e27e 100644 --- a/src/background/browserAction.ts +++ b/src/background/browserAction.ts @@ -22,6 +22,12 @@ import { rehydrateSidebar } from "@/contentScript/messenger/api"; import { executeScript, isScriptableUrl } from "webext-content-scripts"; import webextAlert from "@/background/webextAlert"; import { isMac } from "@/utils"; +import pMemoize from "p-memoize"; +import webextAlert from "./webextAlert"; +import { notify } from "@/options/messenger/api"; + +const ERR_UNABLE_TO_OPEN = + "PixieBrix was unable to open the Sidebar. Try refreshing the page."; // The sidebar is always injected to into the top level frame const TOP_LEVEL_FRAME_ID = 0; @@ -64,6 +70,21 @@ async function handleBrowserAction(tab: Tabs.Tab): Promise { new Error("Error opening sidebar via browser action", { cause: error }) ); } + + // NOTE: at this point, the sidebar should already be visible on the page, even if not ready. + // Avoid showing any alerts or notifications: further messaging can appear in the sidebar itself. + // Any errors are automatically reported by the global error handler. + await contentScriptPromise; + await rehydrateSidebar({ + tabId, + }); +} + +async function handleBrowserAction(tab: Tabs.Tab): Promise { + notify.info({ tabId: tab.id, page: "any" }, "hello"); + // The URL might not be available in certain circumstances. This silences these + // cases and just treats them as "not allowed on this page" + await toggleSidebar(tab.id, String(tab.url)); } export default function initBrowserAction() { diff --git a/src/options/messenger/api.ts b/src/options/messenger/api.ts new file mode 100644 index 0000000000..a0e4baadd8 --- /dev/null +++ b/src/options/messenger/api.ts @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2022 PixieBrix, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/* Do not use `registerMethod` in this file */ +import { getNotifier } from "webext-messenger"; + +export const notify = { + info: getNotifier("NOTIFY_INFO"), + error: getNotifier("NOTIFY_ERROR"), + success: getNotifier("NOTIFY_SUCCESS"), +}; diff --git a/src/options/messenger/registration.ts b/src/options/messenger/registration.ts new file mode 100644 index 0000000000..40292bba52 --- /dev/null +++ b/src/options/messenger/registration.ts @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 PixieBrix, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/* Do not use `getMethod` in this file; Keep only registrations here, not implementations */ +import { registerMethods } from "webext-messenger"; +import { expectContext } from "@/utils/expectContext"; +import notify from "@/utils/notify"; + +expectContext("extension"); + +declare global { + interface MessengerMethods { + NOTIFY_INFO: typeof notify.info; + NOTIFY_ERROR: typeof notify.error; + NOTIFY_SUCCESS: typeof notify.success; + } +} + +export default function registerMessenger(): void { + registerMethods({ + NOTIFY_INFO: notify.info, + NOTIFY_ERROR: notify.error, + NOTIFY_SUCCESS: notify.success, + }); +} diff --git a/src/options/options.tsx b/src/options/options.tsx index 9c6d0bf839..a5078b7abc 100644 --- a/src/options/options.tsx +++ b/src/options/options.tsx @@ -27,11 +27,13 @@ import React from "react"; import App from "@/options/App"; import initGoogle from "@/contrib/google/initGoogle"; import { initToaster } from "@/utils/notify"; +import registerMessenger from "@/options/messenger/registration"; function init(): void { render(, document.querySelector("#container")); } +registerMessenger(); initGoogle(); initToaster(); init(); From b099a2ae41c293c2d75ca06ea3a4f807465e9f43 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Sun, 4 Sep 2022 00:40:49 +0700 Subject: [PATCH 6/7] Move comment; extract user message; avoid duplicates --- src/background/browserAction.ts | 16 ++++++++++------ src/utils.ts | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/background/browserAction.ts b/src/background/browserAction.ts index 2cd18f81ec..6284fb443c 100644 --- a/src/background/browserAction.ts +++ b/src/background/browserAction.ts @@ -27,6 +27,9 @@ import { notify } from "@/options/messenger/api"; const ERR_UNABLE_TO_OPEN = "PixieBrix was unable to open the Sidebar. Try refreshing the page."; +const keyboardShortcut = isMac() ? "Cmd+Opt+C" : "Ctrl+Shift+C"; +const MSG_NO_SIDEBAR_ON_OPTIONS_PAGE = `PixieBrix Tip 💜\n If you want to create a new blueprint, first navigate to the page you want to modify, then open PixieBrix in the DevTools (${keyboardShortcut}).`; + // The sidebar is always injected to into the top level frame const TOP_LEVEL_FRAME_ID = 0; @@ -74,21 +77,22 @@ async function _toggleSidebar(tabId: number, tabUrl: string): Promise { } async function handleBrowserAction(tab: Tabs.Tab): Promise { + // The URL might not be available in certain circumstances. This silences these + // cases and just treats them as "not allowed on this page" const url = String(tab.url); - const optionsPage = browser.runtime.getURL("options.html"); if (url.startsWith(optionsPage)) { - const keyboardShortcut = isMac() ? "Cmd+Opt+C" : "Ctrl+Shift+C"; notify.info( { tabId: tab.id, page: "any" }, - `PixieBrix Tip 💜\n If you want to create a new blueprint, first navigate to the page you want to modify, then open PixieBrix in the DevTools (${keyboardShortcut}).` + { + id: "MSG_NO_SIDEBAR_ON_OPTIONS_PAGE", + message: MSG_NO_SIDEBAR_ON_OPTIONS_PAGE, + } ); } - // The URL might not be available in certain circumstances. This silences these - // cases and just treats them as "not allowed on this page" - await toggleSidebar(tab.id, String(tab.url)); + await toggleSidebar(tab.id, url); } export default function initBrowserAction() { diff --git a/src/utils.ts b/src/utils.ts index 486e56ec8f..1aa445fd85 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -541,7 +541,7 @@ export async function logPromiseDuration

( export function isMac(): boolean { // https://stackoverflow.com/a/27862868/402560 - return navigator.platform.includes("Mac"); + return globalThis.navigator?.platform.includes("Mac"); } /** Tests a target string against a list of strings (full match) or regexes (can be mixed) */ From 90f5d759861a3070bfb30c10bae692ef6ebe1622 Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Sun, 4 Sep 2022 00:41:49 +0700 Subject: [PATCH 7/7] Limit message to options.html; don't try to toggleSidebar --- src/background/browserAction.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/background/browserAction.ts b/src/background/browserAction.ts index 6284fb443c..6729bb6be2 100644 --- a/src/background/browserAction.ts +++ b/src/background/browserAction.ts @@ -84,15 +84,15 @@ async function handleBrowserAction(tab: Tabs.Tab): Promise { if (url.startsWith(optionsPage)) { notify.info( - { tabId: tab.id, page: "any" }, + { tabId: tab.id, page: "/options.html" }, { id: "MSG_NO_SIDEBAR_ON_OPTIONS_PAGE", message: MSG_NO_SIDEBAR_ON_OPTIONS_PAGE, } ); + } else { + await toggleSidebar(tab.id, url); } - - await toggleSidebar(tab.id, url); } export default function initBrowserAction() {