一、设计准则

扩展程序的用户界面的设计准则是有目的性最小型。这和扩展程序本身的设计准则是一样的,UI 应该增强体验而不会分散注意力。

二、在所有页面上都能使用扩展程序

多数情况下,扩展程序正常调用时,可以使用 browser_action 配置一些行为

1、注册 browser_action

browser_action 是在 manifest 中注册的:

 {
    "name": "My Awesome browser_action Extension",
    ...
    "browser_action": {
      ...
    }
    ...
  }

声明 browser_action 能够使工具栏的图标变成彩色,成为激活状态,用户能够使用这个扩展程序。

2、增加一个 badge

badge 在浏览器图标顶部显示最多四个字符的彩色横幅。

它们只能由在其 manifest 中声明 browser_action 中使用。

badge 能够说明当前扩展的状态,下面的这个水滴示例说明已经成功设置了某种操作 ON 为开启状态,并且在扩展程序没有任何动作的时候,不会显示任何内容。

1.jpg

通过调用 chrome.browserAction.setBadgeBackgroundColor 设置 badge 的文本,调用 chrome.browserAction.setBadgeText 设置 banner 的颜色。

background.js 中写入下面的代码:

chrome.browserAction.setBadgeText({text: 'ON'});
chrome.browserAction.setBadgeBackgroundColor({color: '#4688F1'});

最终效果:

2.jpg

需要注意的是,browser_actionpage_action 并不能共存,只能存在一个

比如这里的完整 manifest 是:

{
    "name": "Getting Started Example",
    "version": "1.0",
    "description": "Build an Extension!",
    "permissions": ["storage", "declarativeContent", "activeTab"],
    "background": {
      "scripts": ["background.js"],
      "persistent": false
    },
    "browser_action":{
        "badge": "images/badge_off_example.png"
    },
    "icons": {
        "16": "images/get_started16.png",
        "32": "images/get_started32.png",
        "48": "images/get_started48.png",
        "128": "images/get_started128.png"
    },
    "manifest_version": 2
  }

三、在某些页面上激活扩展程序

通过配置 page_action 可以选择在某些条件的页面中才能激活扩展程序(比如 react-devtool 和 vue-devtool 是这种类型)

1、声明 page_action

manifest 中的 page_action 字段:

{
    "name": "My Awesome page_action Extension",
    ...
    "page_action": {
      ...
    }
    ...
  }

声明 page_action 仅在扩展程序可供用户使用时才会着色图标,否则将以灰色显示。

2、定义扩展程序激活的条件

可以通过在后台脚本中使用 runtime.onInstalled 这个事件监听中调用 chrome.declarativeContent,定义扩展程序可用规则。

如果满足条件的话,可以调用 declarativeContent.showPageAction() 激活扩展程序。


chrome.runtime.onInstalled.addListener(() => {
    // 当 url 变更的时候,首先移除所有的规则
    chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
        // 增加新规则
        chrome.declarativeContent.onPageChanged.addRules([
            {
                // 规则的条件是 URL 中包含 ptbird
                conditions: [
                    new chrome.declarativeContent.PageStateMatcher({
                        pageUrl: { urlContains: 'ptbird' }
                    })
                ],
                 // 如果负责规则进行的动作
                 actions: [ new chrome.declarativeContent.ShowPageAction() ]
            }
        ])
    })
});

上面插件调用之后,会发现,只有当我的页面跳转到 包含 ptbird 的页面的时候,才能激活扩展程序。

3、激活或禁用扩展程序

使用 page_action 的扩展程序能够通过 pageAction.showpageAction.hide 动态的激活和禁用。

当一个扩展程序依赖页面的内容或者其他页面相关的元素的时候,你是无法声明规则来预测使用哪些页面条件这个时候,就可以用到上面两个 API

chrome.runtime.onMessage.addListener(function(req, sender) {
    chrome.storage.local.set({'address': req.address})
    chrome.pageAction.show(sender.tab.id);
    chrome.pageAction.setTitle({tabId: sender.tab.id, title: req.address});
  });

四、提供扩展程序的图标

扩展程序至少需要一个图标来。提供 PNG 格式的图标有最佳的视觉效果,但 WebKit 支持的任何格式(包括BMP,GIF,ICO和JPEG)都可以使用。

1、指定工具栏的图标

设定工具栏的图标在 manifest 中的 browser_actionpage_action 下的 default_icon 字段中注册。

可以同时设定多种尺寸,最小是 16x16 的,图标应该是正方形的,如果没有提供,chrome 会提供一个默认的图标。

  {
    "name": "My Awesome page_action Extension",
    ...
    "page_action": {
      "default_icon": {
        "16": "extension_toolbar_icon16.png",
        "32": "extension_toolbar_icon32.png"
      }
    }
    ...
  }

2、创建并且注册其他图标

其他的图标是在 manifest 的 icons 中设置的,尺寸包含了下面几种:16x1632x32, 48x48, 128x128

{
    "name": "My Awesome Extension",
    ...
    "icons": {
      "16": "extension_icon16.png",
      "32": "extension_icon32.png",
      "48": "extension_icon48.png",
      "128": "extension_icon128.png"
    }
    ...
  }

五、其他 UI 特性

1、popup

弹出窗口是一个HTML文件,当用户单击工具栏图标时,该文件将显示在特殊窗口中。

弹出窗口与网页的工作方式非常相似; 它可以包含 stylesheet 和 脚本标记的链接,但不允许内联 JavaScript。

popup 是在 manifest 中的 browser_action 或者是 page_action 中定义的:

    "browser_action":{
        "default_popup": "popup.html"
    },

同时 popup 页面可以通过调用 browserAction.setPopuppageAction.setPopup 来设置

比如实现一个 chrome 官方的水滴的例子:

popup.html

<html>
    <head>
      <title>Water Popup</title>
      <style>
        button {
          width: 100%;
          border:1px solid #FF5000;
          background-color: #F2F2F2;
          margin-top: 3px;
        }
      </style>
    </head>
    <body>
        <img src='./images/badge_off_example.png' id='hydrateImage'>
        <button id='sampleSecond' value='0.1'>Sample Second</button>
        <button id='15min' value='15'>15 Minutes</button>
        <button id='30min' value='30'>30 Minutes</button>
        <button id='cancelAlarm'>Cancel Alarm</button>
     <script src="popup.js"></script>
    </body>
  </html>

3.jpg

2、Tooltip

tooltip 可以在鼠标悬停在浏览器图标上的时候,使用工具提示向用户提供简短说明

tooltip 可以在 browser_action 或者 page_action 上配置 default_title 字段:

 {
  "name": "Tab Flipper",
   ...
    "browser_action": {
      "default_title": "Press Ctrl(Win)/Command(Mac)+Shift+Right/Left to flip tabs"
    }
  ...
 }

1.png

tooltup 可以通过 browserAction.setTitlepageAction.setTitle 设置

chrome.browserAction.onClicked.addListener(function(tab) {
    chrome.browserAction.setTitle({tabId: tab.id, title: "You are on tab:" + tab.id});
  });

3、Omnibox

通过可以通过 omnibox 多功能框调用扩展程序的功能,可以在 manifest 中设置 omnibox 来配置,多功能框新标签搜索示例扩展使用 "nt" 作为关键字。

{
    "name": "Omnibox New Tab Search",
    ...
    "omnibox": { "keyword" : "nt" },
    "default_icon": {
      "16": "newtab_search16.png",
      "32": "newtab_search32.png"
    }
    ...
  }

当用户在多功能框中键入 nt 时,它会激活扩展程序。

要向用户发出此信号,它会将提供的 16x16 灰色图标,并将其包含在扩展名旁边的多功能框中。

4、Context Menu

通过在 manifest 中配置 "contextMenus" 权限来添加新的上下文菜单选项。

{
    "name": "Global Google Search",
    ...
    "permissions": ["contextMenus", "storage"],
  }

然后通过在后台脚本中调用 contextMenus.create 来创建上下文菜单。这应该在 runtime.onInstalled 监听器事件下完成。

// 创建上下文菜单
const kLocales = {
    'com.au': 'Australia',
    'com.br': 'Brazil',
    'ca': 'Canada',
    'cn': 'China',
    'fr': 'France',
    'it': 'Italy',
    'co.in': 'India',
    'co.jp': 'Japan',
    'com.ms': 'Mexico',
    'ru': 'Russia',
    'co.za': 'South Africa',
    'co.uk': 'United Kingdom'
  };
chrome.runtime.onInstalled.addListener(() => {
    for (let key of Object.keys(kLocales)) {
        chrome.contextMenus.create({
            id: key,
            title: kLocales[key],
            type: 'normal',
            contexts: ['selection'],
        });
    }
});

所谓上下文菜单是与内容有关的,比如上面的代码中,当你选中了一个文字之后, 右击,就会出现我们自定义的上下文菜单。

当扩展程序包含多个上下文菜单时,Google Chrome会自动将其折叠为单个父菜单。

4.jpg

5、Commands

扩展程序可以定义特殊的命令并将它们绑定到快捷键中。

可以在 manifest 中的 commands 字段注册。

{
    "name": "Tab Flipper",
    ...
    "commands": {
      "flip-tabs-forward": {
        "suggested_key": {
          "default": "Ctrl+Shift+Right",
          "mac": "Command+Shift+Right"
        },
        "description": "Flip tabs forward"
      },
      "flip-tabs-backwards": {
        "suggested_key": {
          "default": "Ctrl+Shift+Left",
          "mac": "Command+Shift+Left"
        },
        "description": "Flip tabs backwards"
      }
    }
    ...
  }

commands 可用于提供新的或替代的浏览器快捷方式,可以使用快捷键直接打开扩展程序。

6、Override Pages

扩展程序可以覆盖并替换历史记录、包含自定义HTML文件的新标签页或书签网页。

popup,它可以包含专门的逻辑和样式,但不允许内联 JavaScript。

单个扩展程序仅限于覆盖三个可能页面中的一个。

在 manifest 的 chrome_url_overrides 字段下注册覆盖页面。

{
    "name": "Awesome Override Extension",
    ...

    "chrome_url_overrides" : {
      "newtab": "override_page.html"
    },
    ...
  }

覆盖这些页面时,newtab 字段应替换为 bookmarkshistory

override_page.html

 <html>
   <head>
    <title>New Tab</title>
   </head>
   <body>
      <h1>Hello World</h1>
    <script src="logic.js"></script>
   </body>
  </html>

六、代码示例:

github: https://github.com/postbird/chrome-extensions-demo/tree/master/demo4