科学是实事求是的学问,来不得半点虚假。
DBMNG数据库管理与应用
当前位置:首页 > 经验分享 > WEB
谷歌浏览器Chrome扩展插件开发

1. 简介

Chrome插件是一个用Web技术开发、用来增强浏览器功能的软件,Chrome浏览器扩展开发算是相当简单的,基本只要掌握HTML+CSS+Javascript,即可快速开发一个属于你的Chrome插件!它其实就是一个由HTML、CSS、JS、图片等资源组成的一个.crx后缀的压缩包.

2. 学习Chrome插件开发有什么意义?

增强浏览器功能,轻松实现属于自己的“定制版”浏览器,等等。
Chrome插件提供了很多实用API供我们使用,包括但不限于:

  • 书签控制;

  • 下载控制;

  • 窗口控制;

  • 标签控制;

  • 网络请求控制,

  • 各类事件监听;

  • 自定义原生菜单;

  • 完善的通信机制;
    等等;

4.  开发与调试

Chrome插件没有严格的项目结构要求,只要保证本目录有一个manifest.json即可,普通的web开发工具即可。
从右上角菜单->更多工具->扩展程序可以进入 插件管理页面,也可以直接在地址栏输入
chrome://extensions 访问。

5. 核心介绍

manifest.json是一个Chrome插件最重要也是必不可少的文件,用来配置所有和插件相关的配置,必须放在根目录。

下面给出的是一些常见的配置项,均有中文注释,完整的配置文档请戳 这里

{ //必选
/*
  指定您的应用包要求的清单文件格式的版本。从 Chrome 18 开始,开发人员应该指定 2
*/
"manifest_version": 2, "name":"我的应用名称", "version":"我的应用版本", //推荐
/*
  清单文件-默认语言 指定_locales中的子目录,包含该应用默认字符串。
  对于含有 _locales 目录的应用来说这一属性是必需的,
  在没有 _locales 目录的应用中该属性不能存在
*/
"default_locale":"en",

/*
  这个描述在安装应用之后可以看见
*/
"description":"关于应用的描述",

/*一个或多个代表应用、应用或主题背景的图标*/
"icons":{   "16":"icon16.png",   "48":"icon48.png"
}, /*
 选择某一个(或者无)
 browser_action(浏览器按钮)
 page_action(页面按钮)
*/

// 如果有 browser_action, 即在 chrome toolbar 的右边添加了一个 icon
"browser_action": {   "default_icon": "advicedog.jpg",   "default_title": "Google Mail",      // tooltip, 光标停留在 icon 上时显示
  "default_popup": "popup.html"  // 如果有 popup 的页面, 则用户点击图标就会渲染此 HTML 页面
}, // 如果并不是对每个网站页面都需要使用插件, 可以使用 page_action(页面按钮) 而不是 browser_action(浏览器按钮)
// browser_action 应用更加广泛
// 如果 page_action 并不应用在当前页面, 会显示灰色

"page_action":{   "default_icon": {                    // 可选
    "19": "images/icon19.png",           // 可选
    "38": "images/icon38.png"            // 可选
  },   "default_title": "Google Mail",      // 可选,在工具提示中显示
  "default_popup": "popup.html"        // 可选
}, //可选
"author":"开发者", "automation":"", /*
后台网页
1.应用通常需要有一个长时间运行的脚本来管理一些任务或状态,而后台网页就是为这一目的而设立。
通常情况下,后台页面不需要任何 HTML 标记,这种情况下后台页面可以单独使用 JavaScript文件实现。
后台页面将由应用系统生成,包含 scripts 属性中列出的每一个文件。

2.page:如果您需要在您的后台页面中指定 HTML,您可以改用 page 属性:

3.persistent:应用和应用通常需要长时间运行的脚本来管理某些任务或状态,这就是事件页面的作用。
事件页面只在需要时加载,当事件页面不活动时就会卸载,以便释放内存和其他系统资源。
如何得到事件页面 就是设置一个"persistent"键,如果没有设置,你将得到一个普通的后台页面。
*/
"background":{   "scripts":["background.js"],   "page": "background.html",   "persistent":false
}, /*
  内容脚本:其实就是向你想要的网页中插入一个脚本代码,执行你想要做的事情
  内容脚本是在网页的上下文中运行的 JavaScript 文件,
  它们可以通过标准的文档对象模型(DOM)来获取浏览器访问的网页详情,或者作出更改。
 
  1.run_at 可选。
  控制 js 中的 JavaScript 文件何时插入,
  可以为 "document_start"、
  "document_end" 或 "document_idle",默认为 "document_idle"。


  1.1如果是 "document_start",这些文件将在 css 中指定的文件之后,但是在所有其他 DOM 构造或脚本运行之前插入。

  1.2.如果是 "document_end",文件将在 DOM 完成之后立即插入,但是在加载子资源(如图像与框架)之前插入。

  1.3.如果是 "document_idle",浏览器将在 "document_end" 和刚发生 window.onload 事件这两个时刻之间选择合适的时候插入,
  具体的插入时间取决于文档的复杂程度以及加载文档所花的时间,并且浏览器会尽可能地为加快页面加载速度而优化。

  2.all_frames 可选。
  控制内容脚本运行在匹配页面的所有框架中还是仅在顶层框架中。 默认为 false,意味着仅在顶层框架中运行
 
  content_scripts还有一些其他不是很常用的属性
*/

"content_scripts": [{   "matches": ["https://*.pingan.com.cn/*"], //匹配的地址网页
  "exclude_matches":[],   "js": ["jquery.js","ideacome.js"], //插入的js
  "css": ["mystyles.css"], //css改变样式
  "run_at":"document_idle",   "all_frames": true //该匹配下面的所有窗口
},{   "matches": ["*://*/*.png", "*://*/*.jpg", "*://*/*.gif", "*://*/*.bmp"],   "js": ["js/show-image-content-size.js"] //可以针对不同的规则插入不同的内容
}],// 普通页面能够直接访问的插件资源列表,如果不设置是无法直接访问的"web_accessible_resources": [   "images/*.png",   "style/double-rainbow.css",   "script/double-rainbow.js",   "script/main.js",   "templates/*"
],/**
 如果不是通过 chrome web store 自动更新插件

  我们希望扩展能自动升级,理由和让chrome自动升级一样:修改程序bug和安全漏洞 ,增加新功能,提升性能,改善体验。
  一个扩展的manifest文件里面必须指定一个"update_url"来执行升级检测。

  扩展可以托管在Chrome Web Store,也可以发布到极速浏览器应用开放平台上。
  如果托管在Chrome Web Store则update_url应该是:http://clients2.google.com/service/update2/crx    
**/
"update_url": "https://clients2.google.com/service/update2/crx",// 插件主页,这个很重要,不要浪费了这个免费广告位"homepage_url": "https://www.baidu.com",/*  
  扩展或app将使用的一组权限。每个权限是一列已知字符串列表中的一个,
  如geolocatioin或者一个匹配模式,来指定可以访问的一个或者多个主机。
  权限可以帮助限定危险,如果你的扩展或者app被攻击。
  一些权限在安装之前,会告知用户
*/
"permissions":[   "tabs", //Required if the extension uses the chrome.tabs or chrome.windows module.
  "bookmarks", //使用chrome.bookmarks模块来创建、组织和管理书签
  "http://www.blogger.com/",    
  "http://*.google.com/",    
  "unlimitedStorage", //提供了一个无限的HTML5配额来存储客户端数据,如数据库和本地存储文件。没有这个权限,扩展仅限于5 MB的本地存储
  "history" //历史记录的使用权限  chrome.history
  "notifications",//提示
  "cookies",//Required if the extension uses the chrome.cookies module.
],/**开发时为扩展指定的唯一标识值。
注意:通常您并不需要直接使用这个值,而是在您的代码中使用相对路径或者chrome.extension.getURL()得到的绝对路径。
这个值并不是开发时显式指定的,而是Chrome在安装.crx时辅助生成的。(开发时可以通过上传扩展或者手工打包生成crx文件)。 安装完crx,在Chrome的用户数据目录下的Default/Extensions/<extensionId>/<versionString>/manifest.json文件中,您可以看到这个扩展的key。**/key:'',"commands": {     // commands API 用来添加快捷键
    // 需要在 background page 上添加监听器绑定 handler
  "toggle-feature-foo": {     "suggested_key": {       "default": "Ctrl+Shift+Y",       "mac": "Command+Shift+Y"
    },     "description": "Toggle feature foo",     "global": true
      // 当 chrome 没有 focus 时也可以生效的快捷键
      // 仅限 Ctrl+Shift+[0..9]
  },   "_execute_browser_action": {     "suggested_key": {       "windows": "Ctrl+Shift+Y",       "mac": "Command+Shift+Y",       "chromeos": "Ctrl+Shift+U",       "linux": "Ctrl+Shift+J"
    }
  },   "_execute_page_action": {     "suggested_key": {       "default": "Ctrl+Shift+E",       "windows": "Alt+Shift+P",       "mac": "Alt+Shift+P"
    }
  },
  ...
}, "content_capabilities": ..., "optional_permissions": ["tabs"], // 其他需要的 permission, 在使用 chrome.permissions API 时用到, 并非安装插件时需要

"short_name": "Short Name", // 插件名字简写"storage": {   "managed_schema": "schema.json"
}, //  使用 storage.managed api 的话, 需要一个 schema 文件指定存储字段类型等, 类似定义数据库表的 column......//还有很多其他的配置}
5.1 content-scripts

所谓content-scripts,其实就是Chrome插件中向页面注入脚本的一种形式(虽然名为script,其实还可以包括css的),借助content-scripts我们可以实现通过配置的方式轻松向指定页面注入JS和CSS,最常见的比如:广告屏蔽、页面CSS定制,等等。

content-scripts和原始页面共享DOM,但是不共享JS,如要访问页面JS(例如某个JS变量),只能通过injected js来实现。content-scripts不能访问绝大部分chrome.xxx.api,除了下面这4种:

  • chrome.extension(getURL , inIncognitoContext , lastError , onRequest , sendRequest)

  • chrome.i18n

  • chrome.runtime(connect , getManifest , getURL , id , onConnect , onMessage , sendMessage)

  • chrome.storage

这些API绝大部分时候都够用了,非要调用其它API的话,你还可以通过通信来实现让background来帮你调用。

5.2 background

后台y页面,这是一个常驻的页面,它的生命周期是插件中所有类型页面中最长的,它随着浏览器的打开而打开,随着浏览器的关闭而关闭,所以通常把需要一直运行的、启动就运行的、全局的代码放在background里面。

background的权限非常高,几乎可以调用所有的Chrome扩展API(除了devtools),而且它可以无限制跨域,也就是可以跨域访问任何网站而无需要求对方设置CORS。

经过测试,其实不止是background,所有的直接通过chrome-extension://id/xx.html这种方式打开的网页都可以无限制跨域。

配置中,background可以通过page指定一张网页,也可以通过scripts直接指定一个JS,Chrome会自动为这个JS生成一个默认的网页:

{    // 会一直常驻的后台JS或后台页面
   "background":
   {        // 2种指定方式,如果指定JS,那么会自动生成一个背景页
       "page": "background.html"
       //"scripts": ["js/background.js"]
   },
}

#######5.3 event-pages
这里顺带介绍一下event-pages,它是一个什么东西呢?鉴于background生命周期太长,长时间挂载后台可能会影响性能,所以Google又弄一个event-pages,在配置文件上,它与background的唯一区别就是多了一个persistent参数:

{    "background":
   {        "scripts": ["event-page.js"],        "persistent": false
   },
}

它的生命周期是:在被需要时加载,在空闲时被关闭,什么叫被需要时呢?比如第一次安装、插件更新、有content-script向它发送消息,等等。

5.4 popup

popup是点击browser_action或者page_action图标时打开的一个小窗口网页,焦点离开网页就立即关闭,一般用来做一些临时性的交互。


image.png

popup可以包含任意你想要的HTML内容,并且会自适应大小。可以通过default_popup字段来指定popup页面,也可以调用setPopup()方法。

需要特别注意的是,由于单击图标打开popup,焦点离开又立即关闭,所以popup页面的生命周期一般很短,需要长时间运行的代码千万不要写在popup里面。

在权限上,它和background非常类似,它们之间最大的不同是生命周期的不同,popup中可以直接通过chrome.extension.getBackgroundPage()获取background的window对象。

5.5 homepage_url

开发者或者插件主页设置


image.png
5.6 injected-script

指的是通过DOM操作的方式向页面注入的一种JS。为什么需要通过这种方式注入JS呢?

这是因为content-script有一个很大的“缺陷”,也就是无法访问页面中的JS,虽然它可以操作DOM,但是DOM却不能调用它,也就是无法在DOM中通过绑定事件的方式调用content-script中的代码(包括直接写onclick和addEventListener2种方式都不行),但是,“在页面上添加一个按钮并调用插件的扩展API”是一个很常见的需求,那该怎么办呢?其实这就是本小节要讲的。

在content-script中通过DOM方式向页面注入inject-script代码示例:

// 向页面注入JSfunction injectCustomJs(jsPath){
   jsPath = jsPath || 'js/inject.js';    var temp = document.createElement('script');
   temp.setAttribute('type', 'text/javascript');    // 获得的地址类似:chrome-extension://ihcokhadfjfchaeagdoclpnjdiokfakg/js/inject.js
   temp.src = chrome.extension.getURL(jsPath);
   temp.onload = function()    {        // 放在页面不好看,执行完后移除掉
       this.parentNode.removeChild(this);
   };    document.head.appendChild(temp);
}

manifest.json
{    // 普通页面能够直接访问的插件资源列表,如果不设置是无法直接访问的
   "web_accessible_resources": ["js/inject.js"],
}

6. Chrome插件的7种展示形式

6.1 browserAction(浏览器右上角)

通过配置browser_action可以在浏览器的右上角增加一个图标,一个browser_action可以拥有一个图标,一个tooltip(即划过显示title),一个badge(图标上面的文字,有字数限制)和一个popup。


tooltip,badge,popup
6.2 pageAction(地址栏右侧)

pageAction和普通的browserAction一样也是放在浏览器右上角,也可以说地址栏的右侧更为准确。只不过没有点亮时是灰色的,点亮了才是彩色的,灰色时无论左键还是右键单击都是弹出选项:

// manifest.json{  "name": "测试",  "description": "........",  "version": "1.0",  "permissions": [    "declarativeContent"
 ],  "background":{    "scripts":["background.js"]
 },  
 "page_action": {    "default_icon": "icon.png",    "default_title": "我是pageAction",    "default_popup": "popup.html"
 },  "manifest_version": 2}// background.jschrome.runtime.onInstalled.addListener(function(){
   chrome.declarativeContent.onPageChanged.removeRules(undefined, function(){
       chrome.declarativeContent.onPageChanged.addRules([
           {                conditions: [                    // 只有打开百度才显示pageAction
                   new chrome.declarativeContent.PageStateMatcher({pageUrl: {urlContains: 'baidu.com'}})
               ],                actions: [new chrome.declarativeContent.ShowPageAction()]
           }
       ]);
   });
});
6.3 右键菜单(api地址

通过开发Chrome插件可以自定义浏览器的右键菜单,主要是通过chrome.contextMenusAPI实现,右键菜单可以出现在不同的上下文,比如普通页面、选中的文字、图片、链接,等等

//manifest.json
 "permissions": [    "declarativeContent",    "contextMenus",    "tabs"
 ],  "background":{    "scripts":["background.js"]
 },  

//background.js//可以右键看看chrome.contextMenus.create({    title: "测试右键菜单",    onclick: function(){alert('您点击了右键菜单!');}
});//选择某些文字才出现这个右键菜单chrome.contextMenus.create({    title: '使用度娘搜索:%s', // %s表示选中的文字
   contexts: ['selection'], // 只有当选中文字时才会出现此右键菜单
   onclick: function(params)    {        // 注意不能使用location.href,因为location是属于background的window对象
       chrome.tabs.create({url: 'https://www.baidu.com/s?ie=utf-8&wd=' + encodeURI(params.selectionText)});
   }
});
6.3.2 右键菜单一些基本的api
hrome.contextMenus.create({    type: 'normal', // 类型,可选:["normal", "checkbox", "radio", "separator"],默认 normal
   title: '菜单的名字', // 显示的文字,除非为“separator”类型否则此参数必需,如果类型为“selection”,可以使用%s显示选定的文本
   contexts: ['page'], // 上下文环境,可选:["all", "page", "frame", "selection", "link", "editable", "image", "video", "audio"],默认page
   onclick: function(){}, // 单击时触发的方法
   parentId: 1, // 右键菜单项的父菜单项ID。指定父菜单项将会使此菜单项成为父菜单项的子菜单
   documentUrlPatterns: 'https://*.baidu.com/*' // 只在某些页面显示此右键菜单
});
// 删除某一个菜单项
chrome.contextMenus.remove(menuItemId);
// 删除所有自定义右键菜单
chrome.contextMenus.removeAll();
// 更新某一个菜单项
chrome.contextMenus.update(menuItemId, updateProperties);
6.4. override(覆盖特定页面)

使用override页可以将Chrome默认的一些特定页面替换掉,改为使用扩展提供的页面。

//一个扩展只能替代一个页面;"chrome_url_overrides":
 {      "newtab": "newtab.html"
      "history": "history.html",      "bookmarks": "bookmarks.html"
 }
6.5 option(选项页)

为了让用户自定义您的应用的行为,您可能会提供一个选项页面。

所谓选项(options)页,就是插件的设置页面,有2个入口,一个是右键图标有一个“选项”菜单,还有一个在插件管理页面:


image.png
//manifest.json//Chrome40以前的插件配置页写法"options_page":"xx.html",//Chrome40以后的插件配置页写法,只是样式不一样了,以弹出框的形式显示"options_ui":
 {      "page": "options.html",      // 添加一些默认的样式,推荐使用
     "chrome_style": true
},//为了兼容,建议2种都写,如果都写了,Chrome40以后会默认读取新版的方式;
Chrome40以后的插件配置页写法

页面内容看你自己发挥了。这边有一个示例可以看看

6.6 omnibox

omnibox是向用户提供搜索建议的一种方式。具体看api

6.7 桌面通知

Chrome提供了一个chrome.notificationsAPI以便插件推送桌面通知,暂未找到chrome.notifications和HTML5自带的Notification的显著区别及优势。

在后台JS中,无论是使用chrome.notifications还是Notification都不需要申请权限(HTML5方式需要申请权限),直接使用即可。

"permissions": [    "notifications"
 ],
chrome.contextMenus.create({    title: "测试右键菜单",
   onclick: function(){
     chrome.notifications.create(null, {
         type: 'basic',
         iconUrl: 'icon.png',
         title: '这是标题',
         message: '您刚才点击了自定义右键菜单!'
     });
   }
});
image.png
实战1:(platform项目险企报价)

为了实现险企账号的管理,使得出单人员在各个险企报价时,不需要自己记录管理险企的登录地址,以后手动输入账号密码。
或者在报价页面插入一些已知的报价填写信息。

文件目录

项目文件目录
  • manifest.json 清单文件
    具体配置:

image.png
  • popup.html :根据上面的描述我们知道,这是点击浏览器按钮会弹出显示。

  • icon.png :browser_action里面配置的icon显示图标

  • ideacome.js: 除了本脚本之外,其他的脚本都是依赖。
    在这个脚本里面我们可以访问其插入的页面的dom元素,cookie,localStorage,发送ajax请求等等操作。来完成我们想要的效果。

完成上面的工作,我们如何使自己的代码转换成一个可在ChromeL浏览器里面安装扩展程序呢?

接下来我们需要对我们编写的文件进行打包。应用打包为已签名的 ZIP 文件,文件扩展名为“crx”,如:myextension.crx。

当您为应用打包时,应用将获得唯一的密钥对,应用的标识符基于公钥的散列,私有密钥用来为每一个版本的应用签名,必须严格保护,不能由公众访问。注意千万不要将您的私有密钥包含在应用中!

打包步骤:

  • 进入以下URL,打开应用管理页面:
    chrome://extensions

  • 确保右上角的开发者模式复选框已选中。

  • 单击打包应用按钮,出现一个对话框。

  • 在应用根目录字段中,指定应用所在文件夹的路径,例如,C:\myext。(忽略其他字段,您第一次为一个应用打包时不需要指定私有密钥文件。)

  • 单击打包应用。打包程序将创建两个文件:一个 .crx 文件,是实际的可安装的应用;另一个是 .pem 文件,包含私有密钥。

安装图片:

确保已经勾选开发者模式
打开扩展页面
将.crx文件拖入扩展页面
点击添加扩展程序即可

不要丢失私有密钥!确保 .pem 文件保密,并存放在安全的地方。如果您今后需要做如下事情,您需要这一文件:

  • 更新应用: 更新应用与安装步骤一样。不同的是此时密钥已经存在。

学习参考文件

  1. https://chajian.baidu.com/developer/extensions/api_index.html

  2. http://open.chrome.360.cn/extension_dev/samples.html#a1f7cf79dd555b04fa8d603247a040e644996293

  3. https://developer.chrome.com/extensions/runtime



作者:overflow_hidden
链接:https://www.jianshu.com/p/88f4a1bd5398
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。



本站文章内容,部分来自于互联网,若侵犯了您的权益,请致邮件chuanghui423#sohu.com(请将#换为@)联系,我们会尽快核实后删除。
关于我们 - 版权声明 - 服务条款 - RSS订阅 - 工作机会 - 友情链接 - 联系我们 - 在线留言
Copyright © 2006-2018 DBMNG.COM All Rights Reserved. Powered by DEVSOARTECH   豫ICP备11002312号-2

豫公网安备 41010502002439号