From 90249bc95603cc17e04409a5fae357a3acee5aa0 Mon Sep 17 00:00:00 2001 From: amysteamdev <37001393+AmySteam@users.noreply.github.com> Date: Wed, 21 Aug 2024 05:53:13 -0600 Subject: [PATCH] [New sample] Open Chrome API reference page (omnibox, alarms, messaging sample) (#848) * First draft * Rename folder * Tweak comments * Update index.html * remove extra closing div * Rename sw file * Apply first round of @sebastianbenz suggestions * Fix import * Update popover * Second tech review round --- .../tutorial.open-api-reference/api-list.js | 81 ++++++++++++++++++ .../tutorial.open-api-reference/content.js | 30 +++++++ .../tutorial.open-api-reference/icon-128.png | Bin 0 -> 7057 bytes .../tutorial.open-api-reference/icon-16.png | Bin 0 -> 7057 bytes .../tutorial.open-api-reference/manifest.json | 25 ++++++ .../service-worker.js | 2 + .../tutorial.open-api-reference/sw-omnibox.js | 37 ++++++++ .../sw-suggestions.js | 23 +++++ .../tutorial.open-api-reference/sw-tips.js | 28 ++++++ 9 files changed, 226 insertions(+) create mode 100644 functional-samples/tutorial.open-api-reference/api-list.js create mode 100644 functional-samples/tutorial.open-api-reference/content.js create mode 100644 functional-samples/tutorial.open-api-reference/icon-128.png create mode 100644 functional-samples/tutorial.open-api-reference/icon-16.png create mode 100644 functional-samples/tutorial.open-api-reference/manifest.json create mode 100644 functional-samples/tutorial.open-api-reference/service-worker.js create mode 100644 functional-samples/tutorial.open-api-reference/sw-omnibox.js create mode 100644 functional-samples/tutorial.open-api-reference/sw-suggestions.js create mode 100644 functional-samples/tutorial.open-api-reference/sw-tips.js diff --git a/functional-samples/tutorial.open-api-reference/api-list.js b/functional-samples/tutorial.open-api-reference/api-list.js new file mode 100644 index 00000000..72554e9c --- /dev/null +++ b/functional-samples/tutorial.open-api-reference/api-list.js @@ -0,0 +1,81 @@ +export default [ + { + content: 'commands', + description: + 'Use the Commands API to add a keyboard shortcuts.' + }, + { + content: 'contextmenus', + description: + "Use the ContextMenus API to add a custom item to Chrome's context menu." + }, + { + content: 'declarativeNetRequest', + description: + 'Use the DeclarativeNetRequest API to block or modify network requests.' + }, + { + content: 'downloads', + description: + 'Use the Downloads API to programmatically manipulate downloads.' + }, + { + content: 'i18n', + description: 'Use the i18n API to localize your extension' + }, + { + content: 'identity', + description: + 'Use the Identity API to get OAuth2 access tokens.' + }, + { + content: 'notifications', + description: + 'Use the Notifications API show notifications to users in the system tray.' + }, + { + content: 'offscreen', + description: + 'Use the Offscreen API to create and manage offscreen documents.' + }, + { + content: 'omnibox', + description: + "Use the Omnibox API to register a keyword with Chrome's address bar." + }, + { + content: 'permissions', + description: + 'Use the Permissions API to request optional permissions at run time.' + }, + { + content: 'runtime', + description: + 'Use the Runtime API pass messages, manage extension lifecycle, and access other helper utils.' + }, + { + content: 'scripting', + description: + 'Use the Scripting API to execute scripts in different contexts.' + }, + { + content: 'storage', + description: + 'Use the Storage API to store, retrieve, and track changes to user data.' + }, + { + content: 'tabs', + description: + 'Use the Tabs API to create, update and manipulate tabs.' + }, + { + content: 'topSites', + description: + 'Use the TopSites API to access the most visited sites that are displayed on the new tab page.' + }, + { + content: 'webNavigation', + description: + 'Use the WebNavigation API to receive notifications about the status of navigation requests in-flight.' + } +]; diff --git a/functional-samples/tutorial.open-api-reference/content.js b/functional-samples/tutorial.open-api-reference/content.js new file mode 100644 index 00000000..1a5f65d4 --- /dev/null +++ b/functional-samples/tutorial.open-api-reference/content.js @@ -0,0 +1,30 @@ +// Popover API https://chromestatus.com/feature/5463833265045504 + +(async () => { + const nav = document.querySelector('.navigation-rail__links'); + + const { tip } = await chrome.runtime.sendMessage({ greeting: 'tip' }); + + const tipWidget = createDomElement(` + + `); + + const popover = createDomElement( + `
${tip}
` + ); + + document.body.append(popover); + nav.append(tipWidget); +})(); + +function createDomElement(html) { + const dom = new DOMParser().parseFromString(html, 'text/html'); + return dom.body.firstElementChild; +} diff --git a/functional-samples/tutorial.open-api-reference/icon-128.png b/functional-samples/tutorial.open-api-reference/icon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..8fb1368633a771bf1adc750fb74ddaf67a98f407 GIT binary patch literal 7057 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 E1324-?*IS* literal 0 HcmV?d00001 diff --git a/functional-samples/tutorial.open-api-reference/icon-16.png b/functional-samples/tutorial.open-api-reference/icon-16.png new file mode 100644 index 0000000000000000000000000000000000000000..4537f9d574bc8ccd0fa7e756e664630cc3b3f9d1 GIT binary patch literal 7057 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 Fe*nUEgvbB@ literal 0 HcmV?d00001 diff --git a/functional-samples/tutorial.open-api-reference/manifest.json b/functional-samples/tutorial.open-api-reference/manifest.json new file mode 100644 index 00000000..e88d16a1 --- /dev/null +++ b/functional-samples/tutorial.open-api-reference/manifest.json @@ -0,0 +1,25 @@ +{ + "manifest_version": 3, + "name": "Open extension API reference", + "version": "1.0.0", + "icons": { + "16": "icon-16.png", + "128": "icon-128.png" + }, + "background": { + "service_worker": "service-worker.js", + "type": "module" + }, + "minimum_chrome_version": "102", + "omnibox": { + "keyword": "api" + }, + "permissions": ["alarms", "storage"], + "content_scripts": [ + { + "matches": ["https://developer.chrome.com/docs/extensions/reference/*"], + "js": ["content.js"] + } + ], + "host_permissions": ["https://extension-tips.glitch.me/*"] +} diff --git a/functional-samples/tutorial.open-api-reference/service-worker.js b/functional-samples/tutorial.open-api-reference/service-worker.js new file mode 100644 index 00000000..1af54df2 --- /dev/null +++ b/functional-samples/tutorial.open-api-reference/service-worker.js @@ -0,0 +1,2 @@ +import './sw-omnibox.js'; +import './sw-tips.js'; diff --git a/functional-samples/tutorial.open-api-reference/sw-omnibox.js b/functional-samples/tutorial.open-api-reference/sw-omnibox.js new file mode 100644 index 00000000..005869bf --- /dev/null +++ b/functional-samples/tutorial.open-api-reference/sw-omnibox.js @@ -0,0 +1,37 @@ +import { getApiSuggestions } from './sw-suggestions.js'; + +console.log('sw-omnibox.js'); + +// Initialize default API suggestions +chrome.runtime.onInstalled.addListener(({ reason }) => { + if (reason === 'install') { + chrome.storage.local.set({ + apiSuggestions: ['tabs', 'storage', 'scripting'] + }); + } +}); + +const URL_CHROME_EXTENSIONS_DOC = + 'https://developer.chrome.com/docs/extensions/reference/'; +const NUMBER_OF_PREVIOUS_SEARCHES = 4; + +// Displays the suggestions after user starts typing +chrome.omnibox.onInputChanged.addListener(async (input, suggest) => { + const { description, suggestions } = await getApiSuggestions(input); + await chrome.omnibox.setDefaultSuggestion({ description }); + suggest(suggestions); +}); + +// Opens the reference page of the chosen API +chrome.omnibox.onInputEntered.addListener((input) => { + chrome.tabs.create({ url: URL_CHROME_EXTENSIONS_DOC + input }); + // Saves the latest keyword + updateHistory(input); +}); + +async function updateHistory(input) { + const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions'); + apiSuggestions.unshift(input); + apiSuggestions.splice(NUMBER_OF_PREVIOUS_SEARCHES); + await chrome.storage.local.set({ apiSuggestions }); +} diff --git a/functional-samples/tutorial.open-api-reference/sw-suggestions.js b/functional-samples/tutorial.open-api-reference/sw-suggestions.js new file mode 100644 index 00000000..42dd477a --- /dev/null +++ b/functional-samples/tutorial.open-api-reference/sw-suggestions.js @@ -0,0 +1,23 @@ +import apiList from './api-list.js'; + +/** + * Returns a list of suggestions and a description for the default suggestion + */ +export async function getApiSuggestions(input) { + const suggestions = apiList.filter((api) => api.content.startsWith(input)); + + // return suggestions if any exist + if (suggestions.length) { + return { + description: 'Matching Chrome APIs', + suggestions: suggestions + }; + } + + // return past searches if no match was found + const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions'); + return { + description: 'No matches found. Choose from past searches', + suggestions: apiList.filter((item) => apiSuggestions.includes(item.content)) + }; +} diff --git a/functional-samples/tutorial.open-api-reference/sw-tips.js b/functional-samples/tutorial.open-api-reference/sw-tips.js new file mode 100644 index 00000000..912d236d --- /dev/null +++ b/functional-samples/tutorial.open-api-reference/sw-tips.js @@ -0,0 +1,28 @@ +console.log('sw-tips.js'); + +// Fetch tip & save in storage +const updateTip = async () => { + const response = await fetch('https://extension-tips.glitch.me/tips.json'); + const tips = await response.json(); + const randomIndex = Math.floor(Math.random() * tips.length); + await chrome.storage.local.set({ tip: tips[randomIndex] }); +}; + +// Create a daily alarm and retrieves the first tip when extension is installed. +chrome.runtime.onInstalled.addListener(({ reason }) => { + if (reason === 'install') { + chrome.alarms.create({ delayInMinutes: 1, periodInMinutes: 1440 }); + updateTip(); + } +}); + +// Retrieve tip of the day +chrome.alarms.onAlarm.addListener(updateTip); + +// Send tip to content script via messaging +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.greeting === 'tip') { + chrome.storage.local.get('tip').then(sendResponse); + return true; + } +});