Skip to content

Commit 33ede55

Browse files
committed
Remove usage of browser.contextMenus API events: onShown, onHidden
Remove usage of browser.contextMenus API events that don't exist in the chrome.contextMenus API.
1 parent ea899b0 commit 33ede55

File tree

7 files changed

+36
-181
lines changed

7 files changed

+36
-181
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77
## [Unreleased]
88

9+
## [1.7.0] - 2023-08-20
10+
11+
### Changed
12+
13+
- Remove usage of browser.contextMenus API events that don't exist in the
14+
chrome.contextMenus API.
15+
916
## [1.6.0] - 2023-07-16
1017

1118
### Changed
@@ -112,7 +119,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
112119

113120
- Initial release.
114121

115-
[Unreleased]: https://github.com/msmolens/treetop/compare/v1.6.0...HEAD
122+
[Unreleased]: https://github.com/msmolens/treetop/compare/v1.7.0...HEAD
123+
[1.7.0]: https://github.com/msmolens/treetop/releases/tag/v1.7.0
116124
[1.6.0]: https://github.com/msmolens/treetop/releases/tag/v1.6.0
117125
[1.5.0]: https://github.com/msmolens/treetop/releases/tag/v1.5.0
118126
[1.4.1]: https://github.com/msmolens/treetop/releases/tag/v1.4.1

_locales/en/messages.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@
136136
"message": "Error handling bookmark removal.",
137137
"description": "Message shown when an error occurs when handling bookmark removal."
138138
},
139+
"errorHandlingContextMenu": {
140+
"message": "Error handling context menu.",
141+
"description": "Message shown when an error occurs when handling a context menu event."
142+
},
139143
"errorHandlingHistoryVisit": {
140144
"message": "Error handling history visit.",
141145
"description": "Message shown when an error occurs when handling a history visit event."
@@ -148,10 +152,6 @@
148152
"message": "Error handling menu click.",
149153
"description": "Message shown when an error occurs when handling a menu click event."
150154
},
151-
"errorHandlingMenuShown": {
152-
"message": "Error handling menu shown.",
153-
"description": "Message shown when an error occurs when handling a menu shown event."
154-
},
155155
"errorLoadingPreferences": {
156156
"message": "Error loading preferences.",
157157
"description": "Message shown when an error occurs when loading the extension's preferences."

src/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"manifest_version": 2,
33
"name": "Treetop",
44
"description": "__MSG_extensionDescription__",
5-
"version": "1.6.0",
5+
"version": "1.7.0",
66
"author": "Max Smolens",
77
"homepage_url": "https://github.com/msmolens/treetop",
88
"default_locale": "en",

src/treetop/Treetop.svelte

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -426,25 +426,19 @@
426426
//
427427
428428
function onContextMenu(event: Event) {
429-
// Record the target element of the context menu
430-
if (menuManager && event.target instanceof HTMLElement) {
431-
menuManager.activeElement = event.target;
432-
}
433-
}
434-
435-
async function asyncOnMenuShown(info: Menus.OnShownInfoType, tab: Tabs.Tab) {
436-
await menuManager?.handleMenuShown(info, tab);
437-
}
438-
439-
function onMenuShown(info: Menus.OnShownInfoType, tab: Tabs.Tab) {
440-
asyncOnMenuShown(info, tab).catch((err) => {
429+
asyncOnContextMenu(event).catch((err) => {
441430
console.error(err);
442-
handleError(browser.i18n.getMessage('errorHandlingMenuShown'));
431+
handleError(browser.i18n.getMessage('errorHandlingContextMenu'));
443432
});
444433
}
445434
446-
function onMenuHidden() {
447-
menuManager?.handleMenuHidden();
435+
async function asyncOnContextMenu(event: Event) {
436+
// Record the target element of the context menu
437+
if (menuManager && event.target instanceof HTMLElement) {
438+
menuManager.activeElement = event.target;
439+
440+
await menuManager.updateEnabled();
441+
}
448442
}
449443
450444
async function asyncOnMenuClicked(info: Menus.OnClickData, tab?: Tabs.Tab) {
@@ -545,8 +539,6 @@
545539
546540
// Register menu event handlers
547541
document.addEventListener('contextmenu', onContextMenu);
548-
browser.contextMenus.onShown.addListener(onMenuShown);
549-
browser.contextMenus.onHidden.addListener(onMenuHidden);
550542
browser.contextMenus.onClicked.addListener(onMenuClicked);
551543
552544
// Initialize menu manager
@@ -578,8 +570,6 @@
578570
579571
// Unregister menu event handlers
580572
document.removeEventListener('contextmenu', onContextMenu);
581-
browser.contextMenus.onShown.removeListener(onMenuShown);
582-
browser.contextMenus.onHidden.removeListener(onMenuHidden);
583573
browser.contextMenus.onClicked.removeListener(onMenuClicked);
584574
585575
// Destroy menu manager

src/treetop/menus/MenuManager.ts

Lines changed: 9 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,71 +11,13 @@ export class MenuManager {
1111

1212
private readonly menuItems = new Map<string, MenuItem>();
1313

14-
// Track shown menu instance ID
15-
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/menus/onShown
16-
private lastMenuInstanceId = 0;
17-
private nextMenuInstanceId = 1;
18-
1914
/**
2015
* Register a menu item.
2116
*/
2217
registerMenuItem(id: string, item: MenuItem): void {
2318
this.menuItems.set(id, item);
2419
}
2520

26-
/**
27-
* Update whether menu items are enabled when the menu is shown.
28-
* The menu must have been opened in the 'link' context in the current Treetop
29-
* tab.
30-
*/
31-
async handleMenuShown(
32-
info: Menus.OnShownInfoType,
33-
tab: Tabs.Tab,
34-
): Promise<void> {
35-
if (!info.contexts.includes('link') || info.viewType !== 'tab') {
36-
return;
37-
}
38-
39-
// Get match pattern for the extension's origin
40-
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions
41-
const origin = browser.runtime.getURL('');
42-
if (!info.pageUrl || !info.pageUrl.startsWith(origin)) {
43-
return;
44-
}
45-
46-
// Store menu instance ID before calling async function
47-
const menuInstanceId = this.nextMenuInstanceId;
48-
++this.nextMenuInstanceId;
49-
this.lastMenuInstanceId = menuInstanceId;
50-
51-
const currentTab = await browser.tabs.getCurrent();
52-
if (currentTab.id !== tab.id) {
53-
return;
54-
}
55-
56-
// Check whether the same menu is still shown
57-
if (menuInstanceId !== this.lastMenuInstanceId) {
58-
return;
59-
}
60-
61-
// Update whether menu items are enabled based on the target bookmark
62-
const nodeId = this.activeElement?.dataset.nodeId;
63-
if (nodeId) {
64-
await this.updateEnabled(nodeId);
65-
}
66-
}
67-
68-
/**
69-
* Clean up state when the menu is hidden.
70-
*/
71-
handleMenuHidden(): void {
72-
// Reset the menu instance ID
73-
this.lastMenuInstanceId = 0;
74-
75-
// Clear the active element
76-
this.activeElement = null;
77-
}
78-
7921
/**
8022
* Call a registered menu item handler when a menu item is clicked.
8123
* The menu must have been clicked in the current Treetop tab.
@@ -103,12 +45,20 @@ export class MenuManager {
10345
const item = this.menuItems.get(info.menuItemId as string);
10446
item?.onClicked(nodeId);
10547
}
48+
49+
// Clear the active element
50+
this.activeElement = null;
10651
}
10752

10853
/**
10954
* Update whether menu items are enabled based on the target node.
11055
*/
111-
async updateEnabled(nodeId: string): Promise<void> {
56+
async updateEnabled(): Promise<void> {
57+
const nodeId = this.activeElement?.dataset.nodeId;
58+
if (!nodeId) {
59+
return;
60+
}
61+
11262
for (const [id, item] of this.menuItems.entries()) {
11363
const enabled = item.enabled(nodeId);
11464
await browser.contextMenus.update(id, { enabled });

test/treetop/Treetop.svelte.test.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ describe('Treetop', () => {
4444
//
4545

4646
// Menu event handlers
47-
mockBrowser.contextMenus.onShown.addListener.expect(expect.any(Function));
48-
mockBrowser.contextMenus.onHidden.addListener.expect(expect.any(Function));
4947
mockBrowser.contextMenus.onClicked.addListener.expect(expect.any(Function));
5048

5149
//
@@ -88,12 +86,6 @@ describe('Treetop', () => {
8886
// onDestroy
8987
//
9088

91-
mockBrowser.contextMenus.onShown.removeListener.expect(
92-
expect.any(Function),
93-
);
94-
mockBrowser.contextMenus.onHidden.removeListener.expect(
95-
expect.any(Function),
96-
);
9789
mockBrowser.contextMenus.onClicked.removeListener.expect(
9890
expect.any(Function),
9991
);

test/treetop/menus/MenuManager.test.ts

Lines changed: 4 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,6 @@ class TestMenuItem extends MenuItem {
2323
}
2424
}
2525

26-
const createOnShownInfo = (origin: string): Menus.OnShownInfoType => {
27-
return {
28-
menuIds: [faker.datatype.number()],
29-
contexts: ['link'],
30-
viewType: 'tab',
31-
editable: true,
32-
pageUrl: `${origin}/${faker.random.word()}`,
33-
targetElementId: faker.datatype.number(),
34-
};
35-
};
36-
3726
const createOnClickData = (menuItemId: string): Menus.OnClickData => {
3827
return {
3928
menuItemId,
@@ -68,112 +57,38 @@ beforeEach(() => {
6857
menuManager = new MenuManager();
6958
});
7059

71-
describe('handleMenuShown', () => {
72-
let origin: string;
73-
let info: Menus.OnShownInfoType;
74-
let tab: Tabs.Tab;
75-
60+
describe('updateEnabled', () => {
7661
beforeEach(() => {
7762
const callback: OnClickedCallback = (nodeId) => {
7863
void nodeId;
7964
};
8065

8166
menuManager.registerMenuItem('test1', new TestMenuItem(callback, true));
8267
menuManager.registerMenuItem('test2', new TestMenuItem(callback, false));
83-
84-
origin = faker.internet.url();
85-
info = createOnShownInfo(origin);
86-
tab = createTab();
8768
});
8869

8970
it('updates whether menu items are enabled', async () => {
90-
mockBrowser.runtime.getURL.expect('').andReturn(origin);
91-
mockBrowser.tabs.getCurrent.expect.andResolve(tab);
9271
mockBrowser.contextMenus.update.expect('test1', { enabled: true });
9372
mockBrowser.contextMenus.update.expect('test2', { enabled: false });
9473
mockBrowser.contextMenus.refresh.expect;
9574

9675
// @ts-ignore
9776
menuManager.activeElement = createElement();
9877

99-
await menuManager.handleMenuShown(info, tab);
100-
});
101-
102-
it("no-op if context is not 'link'", async () => {
103-
info.contexts = ['page'];
104-
105-
// @ts-ignore
106-
menuManager.activeElement = createElement();
107-
108-
await menuManager.handleMenuShown(info, tab);
109-
});
110-
111-
it("no-op if viewType is not 'tab'", async () => {
112-
info.viewType = 'popup';
113-
114-
// @ts-ignore
115-
menuManager.activeElement = createElement();
116-
117-
await menuManager.handleMenuShown(info, tab);
118-
});
119-
120-
it("no-op if pageUrl isn't provided", async () => {
121-
delete info.pageUrl;
122-
123-
mockBrowser.runtime.getURL.expect('').andReturn(origin);
124-
125-
// @ts-ignore
126-
menuManager.activeElement = createElement();
127-
128-
await menuManager.handleMenuShown(info, tab);
129-
});
130-
131-
it("no-op if pageUrl doesn't match", async () => {
132-
info.pageUrl = faker.internet.url();
133-
134-
mockBrowser.runtime.getURL.expect('').andReturn(origin);
135-
136-
// @ts-ignore
137-
menuManager.activeElement = createElement();
138-
139-
await menuManager.handleMenuShown(info, tab);
140-
});
141-
142-
it('no-op if not in current tab', async () => {
143-
mockBrowser.runtime.getURL.expect('').andReturn(origin);
144-
145-
const otherTab = createTab();
146-
mockBrowser.tabs.getCurrent.expect.andResolve(otherTab);
147-
148-
// @ts-ignore
149-
menuManager.activeElement = createElement();
150-
151-
await menuManager.handleMenuShown(info, tab);
78+
await menuManager.updateEnabled();
15279
});
15380

15481
it("no-op if active element isn't provided", async () => {
15582
menuManager.activeElement = null;
15683

157-
mockBrowser.runtime.getURL.expect('').andReturn(origin);
158-
mockBrowser.tabs.getCurrent.expect.andResolve(tab);
159-
160-
await menuManager.handleMenuShown(info, tab);
84+
await menuManager.updateEnabled();
16185
});
16286

16387
it("no-op if nodeId isn't available", async () => {
16488
// @ts-ignore
16589
menuManager.activeElement = createElement(false);
16690

167-
mockBrowser.runtime.getURL.expect('').andReturn(origin);
168-
mockBrowser.tabs.getCurrent.expect.andResolve(tab);
169-
170-
await menuManager.handleMenuShown(info, tab);
171-
});
172-
});
173-
174-
describe('handleMenuShown', () => {
175-
it('succeeds', () => {
176-
menuManager.handleMenuHidden();
91+
await menuManager.updateEnabled();
17792
});
17893
});
17994

0 commit comments

Comments
 (0)