Chrome 扩展(插件) 开发教程

    官方中文版教程

    Blog

    Github

    官方中文版教程

    Blog

    Github

    ## # 设计交互界面 扩展的交互界面应该是有目的且最简单的。 就像扩展本身一样,界面 UI 应该是自定义或能增强浏览体验,而不会分散用户注意力。 本指南探讨了必需的和可选的用户界面功能,了解如何以及何时在扩展中实现不同的 UI 元素。 ### # 在所有页面上激活扩展 当扩展程序的功能在大多数情况下都可以使用时,请使用 browser_action 。 #### # 注册 browseraction browseraction 在 manifest 中注册。
    1. {
    2. "name": "My Awesome browseraction Extension",
    3. "browseraction": {
    4. }
    5. }
    声明 browseraction 会使图标保持彩色,表示扩展名可供用户使用。 #### # 增加标记 标记在浏览器图标上方会显示一个彩色横幅,最多包含四个字符。它们只能在其 manifest 中声明 browseraction 的扩展使用。 使用标记显示扩展的状态。 Drink Water Event 示例显示带有 ON 的标志,以向用户显示他们已成功设置警报,而在扩展空闲时不显示任何内容。 badge_on_example badge_off_example 通过调用 chrome.browserAction.setBadgeText 设置标记文本,并通过调用chrome.browserAction.setBadgeBackgroundColor 设置横幅颜色。
    1. chrome.browserAction.setBadgeText({text: 'ON'});
    2. chrome.browserAction.setBadgeBackgroundColor({color: '#4688F1'});
    ### # 在所选页面上激活扩展名 当扩展程序的功能仅在定义的情况下可用时,请使用 page_action。 #### # 定义 Page Action page_action 在 manifest 中注册。
    1. {
    2. "name": "My Awesome page_action Extension",
    3. "page_action": {
    4. }
    5. }
    声明 page_action 只会在扩展对用户可用时使图标着色,否则它将以灰度显示。 page_action_active page_action_inactive #### # 定义激活扩展的规则 通过在后台脚本中的 runtime.onInstalled 监听器下调用 chrome.declarativeContent 来定义扩展何时可用的规则。Page action by URL 这个扩展设置了一个条件,即网址必须包含“g”。如果满足条件,则扩展将调用declarativeContent.ShowPageAction()
    1. chrome.runtime.onInstalled.addListener(function() {
    2. // Replace all rules …
    3. chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
    4. // With a new rule …
    5. chrome.declarativeContent.onPageChanged.addRules([
    6. {
    7. // That fires when a page's URL contains a 'g' …
    8. conditions: [
    9. new chrome.declarativeContent.PageStateMatcher({
    10. pageUrl: { urlContains: 'g' },
    11. })
    12. ],
    13. // And shows the extension's page action.
    14. actions: [ new chrome.declarativeContent.ShowPageAction() ]
    15. }
    16. ]);
    17. });
    18. });
    #### # 激活禁用扩展 使用 page_action 的扩展可以通过调用pageAction.show 和 pageAction.hide 来动态激活和禁用。 Mappy 示例将扫描网页中的地址,并在弹出窗口的静态地图上显示其位置。由于扩展取决于页面内容,因此无法声明规则来预测哪些页面将是相关的。相反,如果在页面上找到地址,它将调用 pageAction.show 使图标变色并表示该扩展名在该选项卡上可用。
    1. chrome.runtime.onMessage.addListener(function(req, sender) {
    2. chrome.storage.local.set({'address': req.address})
    3. chrome.pageAction.show(sender.tab.id);
    4. chrome.pageAction.setTitle({tabId: sender.tab.id, title: req.address});
    5. });
    ### # 提供扩展图标 扩展程序至少需要一个图标来表示它。尽管可以接受 WebKit 支持的任何格式,包括 BMP,GIF,ICO 和 JPEG,但以 PNG 格式提供的图标可以提供最佳视觉效果。 #### # 指定工具栏图标 工具栏指定的图标注册在 manifest 中 browser_action 或 page_action 下的default_icon 字段中。鼓励包含多个尺寸以适应16*16 空间。 建议至少使用 16x16 和 32x32 尺寸。
    1. {
    2. "name": "My Awesome page_action Extension",
    3. "page_action": {
    4. "default_icon": {
    5. "16": "extension_toolbar_icon16.png",
    6. "32": "extension_toolbar_icon32.png"
    7. }
    8. }
    9. }
    所有图标应为正方形,否则可能会变形。如果没有提供图标,则 Chrome 会将通用图标添加到工具栏。 #### # 创建注册额外的图标 在工具栏外使用以下尺寸的其他图标。 addtion_icon 在 manifest 中的 “icons” 字段下注册图标。
    1. {
    2. "name": "My Awesome Extension",
    3. "icons": {
    4. "16": "extension_icon16.png",
    5. "32": "extension_icon32.png",
    6. "48": "extension_icon48.png",
    7. "128": "extension_icon128.png"
    8. }
    9. }
    ### # 其他 UI 功能 #### # popup 弹出窗口 弹出窗口是一个 HTML 文件,当用户单击工具栏图标时,它将显示在特殊窗口中。弹出窗口的工作原理与网页非常相似;它可以包含指向样式表和脚本标签的链接,但不允许内联 JavaScript。 Drink Water Event示例弹出窗口显示可用的计时器选项。用户通过点击提供的按钮之一来设置警报。 popup
    1. <html>
    2. <head>
    3. <title>Water Popup</title>
    4. </head>
    5. <body>
    6. <img src='./stay_hydrated.png' id='hydrateImage'>
    7. <button id='sampleSecond' value='0.1'>Sample Second</button>
    8. <button id='15min' value='15'>15 Minutes</button>
    9. <button id='30min' value='30'>30 Minutes</button>
    10. <button id='cancelAlarm'>Cancel Alarm</button>
    11. <script src="popup.js"></script>
    12. </body>
    13. </html>
    可以在 manifest 中的 browser action 或 page action 下注册弹出窗口。
    1. {
    2. "name": "Drink Water Event",
    3. "browser_action": {
    4. "default_popup": "popup.html"
    5. }
    6. }
    也可以通过调用 browserAction.setPopup 或pageAction.setPopup 动态设置弹出窗口。
    1. chrome.storage.local.get('signed_in', function(data) {
    2. if (data.signed_in) {
    3. chrome.browserAction.setPopup({popup: 'popup.html'});
    4. } else {
    5. chrome.browserAction.setPopup({popup: 'popup_sign_in.html'});
    6. }
    7. });
    #### # Tooltip 工具提示 将鼠标悬停在浏览器图标上时,请使用工具提示向用户提供简短说明或说明。 tooltip 工具提示注册在 browser_action 或 page_action 的 default_title 字段下
    1. {
    2. "name": "Tab Flipper",
    3. "browser_action": {
    4. "default_title": "Press Ctrl(Win)/Command(Mac)+Shift+Right/Left to flip tabs"
    5. }
    6. }
    也可以通过调用 browserAction.setTitle 和pageAction.setTitle 来设置或更新工具提示。
    1. chrome.browserAction.onClicked.addListener(function(tab) {
    2. chrome.browserAction.setTitle({tabId: tab.id, title: "You are on tab:" + tab.id});
    3. });
    专用语言环境字符串是通过国际化实现的。创建目录以将特定于语言的消息放在名为_locales 的文件夹中。下图显示了支持英语和西班牙语语言环境的扩展名的文件路径。 locales_messages 在每种语言的 messages.json 中的格式化消息。
    1. {
    2. "__MSG_tooltip": {
    3. "message": "Hello!",
    4. "description": "Tooltip Greeting."
    5. }
    6. }
    1. {
    2. "__MSG_tooltip": {
    3. "message": "Hola!",
    4. "description": "Tooltip Greeting."
    5. }
    6. }
    在工具提示字段中包括消息的名称,而不是在消息中启用本地化。
    1. {
    2. "name": "Tab Flipper",
    3. "browser_action": {
    4. "default_title": "__MSG_tooltip"
    5. }
    6. }
    #### # Omnibox 地址栏 用户可以通过地址栏调用扩展功能。在 manifest 中包括 Omnibox 字段,并指定一个关键字。Omnibox New Tab Search示例使用 “nt” 作为关键字。
    1. {
    2. "name": "Omnibox New Tab Search",\
    3. "omnibox": { "keyword" : "nt" },
    4. "default_icon": {
    5. "16": "newtab_search16.png",
    6. "32": "newtab_search32.png"
    7. }
    8. }
    当用户在地址栏中输入 “nt” 时,它将激活扩展。 为了向用户发出信号,它会对提供的 16x16 图标进行灰度处理,并将其包含在扩展名旁边的地址栏中。 omnibox 该扩展程序监听 omnibox.onInputEntered 事件。触发后,扩展程序将打开一个新选项卡,其中包含用户输入的 Google 搜索。
    1. chrome.omnibox.onInputEntered.addListener(function(text) {
    2. // Encode user input for special characters , / ? : @ & = + $ #
    3. var newURL = 'https://www.google.com/search?q=&#39; + encodeURIComponent(text);
    4. chrome.tabs.create({ url: newURL });
    5. });
    #### # Context Menu 上下文菜单 通过在 manifest 中赋予 “contextMenus” 权限来添加新的上下文菜单选项。
    1. {
    2. "name": "Global Google Search",
    3. "permissions": ["contextMenus", "storage"],
    4. "icons": {
    5. "16": "globalGoogle16.png",
    6. "48": "globalGoogle48.png",
    7. "128": "globalGoogle128.png"
    8. }
    9. }
    16x16 图标显示在新菜单项的旁边。 contexticon 通过在后台脚本中调用 contextMenus.create 来创建上下文菜单。这应该在 runtime.onInstalled 监听器事件下完成。
    1. chrome.runtime.onInstalled.addListener(function() {
    2. for (let key of Object.keys(kLocales)) {
    3. chrome.contextMenus.create({
    4. id: key,
    5. title: kLocales[key],
    6. type: 'normal',
    7. contexts: ['selection'],
    8. });
    9. }
    10. });
    1. const kLocales = {
    2. 'com.au': 'Australia',
    3. 'com.br': 'Brazil',
    4. 'ca': 'Canada',
    5. 'cn': 'China',
    6. 'fr': 'France',
    7. 'it': 'Italy',
    8. 'co.in': 'India',
    9. 'co.jp': 'Japan',
    10. 'com.ms': 'Mexico',
    11. 'ru': 'Russia',
    12. 'co.za': 'South Africa',
    13. 'co.uk': 'United Kingdom'
    14. };
    Global Google Search context menu 示例从 locales.js 中的列表创建多个选项。如果扩展程序包含多个上下文菜单,则 Google Chrome 浏览器会自动将其折叠为一个父菜单。 contextmenu #### # Commands 命令 扩展可以定义特定的命令并将其绑定到组合键。 在 manifest “commands”字段下注册一个或多个命令。
    1. {
    2. "name": "Tab Flipper",
    3. "commands": {
    4. "flip-tabs-forward": {
    5. "suggested_key": {
    6. "default": "Ctrl+Shift+Right",
    7. "mac": "Command+Shift+Right"
    8. },
    9. "description": "Flip tabs forward"
    10. },
    11. "flip-tabs-backwards": {
    12. "suggested_key": {
    13. "default": "Ctrl+Shift+Left",
    14. "mac": "Command+Shift+Left"
    15. },
    16. "description": "Flip tabs backwards"
    17. }
    18. }
    19. }
    命令可用于提供新的或替代的浏览器快捷方式。 Tab Flipper 监听后台脚本中的 commands.onCommand 事件,并定义每个已注册组合的功能。
    1. chrome.commands.onCommand.addListener(function(command) {
    2. chrome.tabs.query({currentWindow: true}, function(tabs) {
    3. // Sort tabs according to their index in the window.
    4. tabs.sort((a, b) => { return a.index < b.index; });
    5. let activeIndex = tabs.findIndex((tab) => { return tab.active; });
    6. let lastTab = tabs.length - 1;
    7. let newIndex = -1;
    8. if (command === 'flip-tabs-forward')
    9. newIndex = activeIndex === 0 ? lastTab : activeIndex - 1;
    10. else // 'flip-tabs-backwards'
    11. newIndex = activeIndex === lastTab ? 0 : activeIndex + 1;
    12. chrome.tabs.update(tabs[newIndex].id, {active: true, highlighted: true});
    13. });
    14. });
    命令还可以创建与它的扩展特别配合的键绑定。 Hello Extensions 示例给出了打开弹出窗口的命令。
    1. {
    2. "name": "Hello Extensions",
    3. "description" : "Base Level Extension",
    4. "version": "1.0",
    5. "browser_action": {
    6. "default_popup": "hello.html",
    7. "default_icon": "hello_extensions.png"
    8. },
    9. "manifest_version": 2,
    10. "commands": {
    11. "_execute_browser_action": {
    12. "suggested_key": {
    13. "default": "Ctrl+Shift+F",
    14. "mac": "MacCtrl+Shift+F"
    15. },
    16. "description": "Opens hello.html"
    17. }
    18. }
    19. }
    由于扩展定义了 broswer_action,因此可以在命令中指定 “execute_browser_action” 以打开弹出文件,而无需包含后台脚本。如果使用 page_action,则可以将其替换为 “execute_page_action”。 浏览器命令和扩展程序命令都可以在同一扩展程序中使用。 #### # Override Pages 覆盖页面 扩展程序可以覆盖历史记录,新建选项卡或书签网页,并用自定义 HTML 文件替换。像弹出窗口一样,它可以包含专门的逻辑和样式,但不允许内联 JavaScript。单个扩展名仅限于覆盖三个可能的页面之一。 在 manifest 的 “chrome_url_overrides” 字段下注册替代页面。
    1. {
    2. "name": "Awesome Override Extension",
    3. "chrome_url_overrides" : {
    4. "newtab": "override_page.html"
    5. },
    6. }
    覆盖这些页面时,应将 “newtab” 字段替换为“bookmarks” 或 “history”。
    1. <html>
    2. <head>
    3. <title>New Tab</title>
    4. </head>
    5. <body>
    6. <h1>Hello World</h1>
    7. <script src="logic.js"></script>
    8. </body>
    9. </html>
    - - - 关注 微信公众号「程序化思维」 获取最新 Chrome 插件开发教程。 mp_wechat 使用后台脚本管理事件 内容脚本 Content Scripts