diff --git a/apps/content/package.json b/apps/content/package.json
index 40d4942..5e21431 100644
--- a/apps/content/package.json
+++ b/apps/content/package.json
@@ -26,7 +26,7 @@
"svelte-preprocess": "^5.1.3",
"svelte-sequential-preprocessor": "^2.0.1",
"ts-loader": "^9.5.1",
- "typescript": "^5.3.3",
+ "typescript": "^5.4.5",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
diff --git a/apps/extensions/lib/ext-browser.json b/apps/extensions/lib/ext-browser.json
index e9ebae6..c216f04 100644
--- a/apps/extensions/lib/ext-browser.json
+++ b/apps/extensions/lib/ext-browser.json
@@ -1,4 +1,10 @@
{
+ "browserAction": {
+ "url": "chrome://bextensions/content/parent/ext-browserAction.js",
+ "schema": "chrome://bextensions/content/schemas/browser_action.json",
+ "scopes": ["addon_parent"],
+ "manifest": ["browser_action"]
+ },
"pageAction": {
"url": "chrome://bextensions/content/parent/ext-pageAction.js",
"schema": "chrome://extensions/content/schemas/page_action.json",
diff --git a/apps/extensions/lib/parent/ext-browser.js b/apps/extensions/lib/parent/ext-browser.js
index 5f2a7b2..da609c5 100644
--- a/apps/extensions/lib/parent/ext-browser.js
+++ b/apps/extensions/lib/parent/ext-browser.js
@@ -13,6 +13,7 @@ const { lazyESModuleGetters } = typedImportUtils
const lazy = lazyESModuleGetters({
WindowTracker: 'resource://app/modules/BrowserWindowTracker.sys.mjs',
+ EBrowserActions: 'resource://app/modules/EBrowserActions.sys.mjs',
EPageActions: 'resource://app/modules/EPageActions.sys.mjs',
ExtensionParent: 'resource://gre/modules/ExtensionParent.sys.mjs',
})
@@ -36,8 +37,10 @@ class TabTracker extends TabTrackerBase {
}
/**
+ * @template {import('@browser/tabs').WindowTab | null} T
* @param {number} tabId
- * @param {import('@browser/tabs').WindowTab} default_
+ * @param {T} default_
+ * @returns {T}
*/
getTab(tabId, default_) {
const { tab } = lazy.WindowTracker.getWindowWithBrowserId(tabId) || {
diff --git a/apps/extensions/lib/parent/ext-browserAction.js b/apps/extensions/lib/parent/ext-browserAction.js
new file mode 100644
index 0000000..e3138c2
--- /dev/null
+++ b/apps/extensions/lib/parent/ext-browserAction.js
@@ -0,0 +1,38 @@
+// @ts-check
+///
+///
+///
+
+this.browserAction = class extends ExtensionAPIPersistent {
+ /** @type {import("resource://app/modules/EBrowserActions.sys.mjs").IBrowserAction | undefined} */
+ browserAction
+
+ async onManifestEntry() {
+ const { extension } = this
+ /** @type {browser_action__manifest.WebExtensionManifest__extended['browser_action']} */
+ const options = extension.manifest.browser_action
+
+ if (!options) {
+ return
+ }
+
+ this.browserAction = lazy.EBrowserActions.BrowserAction(extension.id, {
+ icons: lazy.ExtensionParent.IconDetails.normalize(
+ {
+ path: options.default_icon || extension.manifest.icons,
+ iconType: 'browserAction',
+ themeIcon: options.theme_icons,
+ },
+ extension,
+ ),
+ title: options.default_title || extension.id,
+ popupUrl: options.default_popup,
+ })
+
+ lazy.EBrowserActions.actions.addKey(extension.id, this.browserAction)
+ }
+
+ onShutdown() {
+ lazy.EBrowserActions.actions.removeKey(this.extension.id)
+ }
+}
diff --git a/apps/extensions/lib/parent/ext-pageAction.js b/apps/extensions/lib/parent/ext-pageAction.js
index 5339ca1..9dd939e 100644
--- a/apps/extensions/lib/parent/ext-pageAction.js
+++ b/apps/extensions/lib/parent/ext-pageAction.js
@@ -14,6 +14,10 @@ this.pageAction = class extends ExtensionAPIPersistent {
const { extension } = this
const options = extension.manifest.page_action
+ if (!options) {
+ return
+ }
+
this.pageAction = new lazy.EPageActions.PageAction({
extensionId: extension.id,
tooltip: options.default_title,
@@ -27,7 +31,7 @@ this.pageAction = class extends ExtensionAPIPersistent {
{
path: options.default_icon || extension.manifest.icons,
iconType: 'browserAction',
- themeIcon: options.theme_icons || extension.theme_icons,
+ themeIcon: options.theme_icons,
},
extension,
),
diff --git a/apps/extensions/lib/parent/ext-tabs.js b/apps/extensions/lib/parent/ext-tabs.js
index a2d209e..d91a4ff 100644
--- a/apps/extensions/lib/parent/ext-tabs.js
+++ b/apps/extensions/lib/parent/ext-tabs.js
@@ -5,7 +5,7 @@
// @ts-check
///
///
-///
+///
/**
* @param {tabs__tabs.QueryInfo} queryInfo
diff --git a/apps/extensions/lib/schemas/browser_action.json b/apps/extensions/lib/schemas/browser_action.json
new file mode 100644
index 0000000..684d8e2
--- /dev/null
+++ b/apps/extensions/lib/schemas/browser_action.json
@@ -0,0 +1,43 @@
+[
+ {
+ "namespace": "manifest",
+ "types": [
+ {
+ "$extend": "WebExtensionManifest",
+ "properties": {
+ "browser_action": {
+ "type": "object",
+ "optional": true,
+ "properties": {
+ "default_icon": {
+ "optional": true,
+ "$ref": "IconPath"
+ },
+ "default_popup": {
+ "optional": true,
+ "type": "string"
+ },
+ "default_title": {
+ "optional": true,
+ "type": "string"
+ },
+ "theme_icons": {
+ "optional": true,
+ "type": "array",
+ "items": { "$ref": "ThemeIcons" }
+ },
+ "browser_style": {
+ "optional": true,
+ "type": "boolean"
+ },
+ "default_area": {
+ "optional": true,
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+]
diff --git a/apps/extensions/lib/schemas/tabs.json b/apps/extensions/lib/schemas/tabs.json
index 40b0ef7..064190b 100644
--- a/apps/extensions/lib/schemas/tabs.json
+++ b/apps/extensions/lib/schemas/tabs.json
@@ -8,7 +8,6 @@
"types": [
{
"$extend": "OptionalPermission",
- "id": "ExtraPerms1",
"choices": [
{
"type": "string",
diff --git a/apps/extensions/lib/types/utils.d.ts b/apps/extensions/lib/types/utils.d.ts
index 67febf3..15d7e8b 100644
--- a/apps/extensions/lib/types/utils.d.ts
+++ b/apps/extensions/lib/types/utils.d.ts
@@ -155,6 +155,14 @@ declare global {
[LISTENERS]: Map;
[ONCE_MAP]: WeakMap