diff --git a/api-samples/contextMenus/global_context_search/background.js b/api-samples/contextMenus/global_context_search/background.js index f504b6ad43..9f56df3e91 100644 --- a/api-samples/contextMenus/global_context_search/background.js +++ b/api-samples/contextMenus/global_context_search/background.js @@ -3,31 +3,46 @@ // found in the LICENSE file. // When you specify "type": "module" in the manifest background, -// you can include the service worker as an ES Module, +// you can include the service worker as an ES Module. import { tldLocales } from './locales.js'; // Add a listener to create the initial context menu items, // context menu items only need to be created at runtime.onInstalled chrome.runtime.onInstalled.addListener(async () => { for (const [tld, locale] of Object.entries(tldLocales)) { - chrome.contextMenus.create({ - id: tld, - title: locale, - type: 'normal', - contexts: ['selection'] - }); + chrome.contextMenus.create( + { + id: tld, + title: `Search Google ${locale} for "%s"`, + type: 'normal', + contexts: ['selection'] + }, + () => { + if (chrome.runtime.lastError) { + console.warn( + `Failed to create menu item for "${tld}":`, + chrome.runtime.lastError.message + ); + } + } + ); } }); -// Open a new search tab when the user clicks a context menu +// Open a new search tab when the user clicks a context menu item. +// tab can be undefined in some contexts (e.g. chrome://extensions), +// so we only set index if tab is available. chrome.contextMenus.onClicked.addListener((item, tab) => { const tld = item.menuItemId; const url = new URL(`https://google.${tld}/search`); url.searchParams.set('q', item.selectionText); - chrome.tabs.create({ url: url.href, index: tab.index + 1 }); + chrome.tabs.create({ + url: url.href, + ...(tab && { index: tab.index + 1 }) + }); }); -// Add or removes the locale from context menu +// Add or remove the locale from context menu // when the user checks or unchecks the locale in the popup chrome.storage.onChanged.addListener(({ enabledTlds }) => { if (typeof enabledTlds === 'undefined') return; @@ -43,14 +58,31 @@ chrome.storage.onChanged.addListener(({ enabledTlds }) => { for (const { tld, added, removed } of changes) { if (added) { - chrome.contextMenus.create({ - id: tld, - title: tldLocales[tld], - type: 'normal', - contexts: ['selection'] - }); + chrome.contextMenus.create( + { + id: tld, + title: tldLocales[tld], + type: 'normal', + contexts: ['selection'] + }, + () => { + if (chrome.runtime.lastError) { + console.warn( + `Failed to create menu item for "${tld}":`, + chrome.runtime.lastError.message + ); + } + } + ); } else if (removed) { - chrome.contextMenus.remove(tld); + chrome.contextMenus.remove(tld, () => { + if (chrome.runtime.lastError) { + console.warn( + `Failed to remove menu item for "${tld}":`, + chrome.runtime.lastError.message + ); + } + }); } } }); diff --git a/api-samples/contextMenus/global_context_search/manifest.json b/api-samples/contextMenus/global_context_search/manifest.json index 20be806b2f..6632a7e370 100644 --- a/api-samples/contextMenus/global_context_search/manifest.json +++ b/api-samples/contextMenus/global_context_search/manifest.json @@ -1,13 +1,13 @@ { "name": "Global Google Search", - "description": "Uses the context menu to search a different country's Google", - "version": "1.1", + "version": "1.2", + "description": "Right-click selected text to search on a regional Google site.", "manifest_version": 3, - "permissions": ["contextMenus", "storage"], "background": { "service_worker": "background.js", "type": "module" }, + "permissions": ["contextMenus", "tabs", "storage"], "action": { "default_popup": "popup.html" }, @@ -16,4 +16,4 @@ "48": "globalGoogle48.png", "128": "globalGoogle128.png" } -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b3bd176c70..3605872dde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@eslint/js": "9.19.0", "chrome-types": "0.1.335", - "eslint": "9.19.0", + "eslint": "^9.19.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-jest": "28.11.0", "eslint-plugin-prettier": "5.4.1", @@ -405,7 +405,6 @@ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -717,7 +716,6 @@ "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -777,7 +775,6 @@ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -1820,7 +1817,6 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -2517,8 +2513,7 @@ "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true, - "peer": true + "dev": true }, "acorn-jsx": { "version": "5.3.2", @@ -2732,7 +2727,6 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "dev": true, - "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -2783,7 +2777,6 @@ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "peer": true, "requires": {} }, "eslint-plugin-jest": { @@ -3467,8 +3460,7 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", - "dev": true, - "peer": true + "dev": true }, "prettier-linter-helpers": { "version": "1.0.0", diff --git a/package.json b/package.json index 0474d3495d..9ee783df1d 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "devDependencies": { "@eslint/js": "9.19.0", "chrome-types": "0.1.335", - "eslint": "9.19.0", + "eslint": "^9.19.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-jest": "28.11.0", "eslint-plugin-prettier": "5.4.1", @@ -39,5 +39,7 @@ "**/*.{md,html,json}": [ "npx prettier --write" ] - } + }, + "main": "eslint.config.js", + "type": "commonjs" }