Chrome Extension是什么呢?

简而言之,就是Chrome扩展,它是基于Chrome浏览器的,我们可以理解它为一个独立运行在Chrome浏览器下的APP,当然核心编程语言就是JavaScript咯,然后结合HTML以及CSS来开发。重点是,这个“APP”功能强大,可以独自运行,亦可以与打开的网页、Chrome控制面板(DevTools)、第三方插件等等进行通信,且,Google允许ChromeExtension不必受限于跨域限制,结合以上种种优点,固,我们可以使用ChromeExtension,结合自身业务,开发出许多提高工作效率的工具。

部署ChromeExtension也很简单,如下:

好了,现在来听听属于ChromeExtension它的故事。

一、概要及manifest.json

ChromeExtension是Chrome提出来的一个概念,其实正如上文所说,核心编程语言就是JavaScript,然后提供一切通信、存储接口,大致就差不多了。

需要注意的是,ChromeExtension都包含一个Manifest文件——manifest.json,这个文件可以告诉Chrome关于这个扩展的相关信息,它是整个扩展的入口,也是Chrome扩展必不可少的部分。且必须包含name、version和manifest_version属性,其他常用的可选属性还有browser_action、page_action、background、permissions、options_page、content_scripts。

所以我们可以保留一份manifest.json模板,当编写新的扩展时直接填入相应的属性值就OK了。

manifest.json模板及相关属性解释如下:

{
"manifest_version": 2,
//定义chrome扩展的名称
"name": "My Extension",
//定义chrome扩展的版本
"version": "versionString",
"default_locale": "en",
//定义chrome扩展的描述
"description": "A plain text description",
//定义了扩展相关图标文件的位置
"icons": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
},
/*
Browser Actions将扩展图标置于Chrome浏览器工具栏中,地址栏的右侧。如果声明了popup页面,当用户点击图标时,在图标的下侧会打开这个页面。同时图标上面还可以附带badge——一个带有显示有限字符空间(只能显示4字节长度信息)的区域——用以显示一些有用的信息,如未读邮件数等。且Badge目前只能够通过JavaScript设定显示的内容,同时Chrome还提供了更改badge背景的方法。如果不定义badge的背景颜色,默认将使用红色。例如,显示了一个背景颜色为蓝色,内容为“Dog”的badge:
chrome.browserAction.setBadgeBackgroundColor({color: '#0000FF'});
chrome.browserAction.setBadgeText({text: 'Dog'});
*/
"browser_action": {
//通过setIcon方法可以动态更改扩展的图标,chrome.browserAction.setIcon(details, callback)
"default_icon": {
"19": "images/icon19.png",
"38": "images/icon38.png"
},
//定义了当用户鼠标悬停于扩展图标上所显示的文字,chrome.browserAction.setTitle({title: 'This is a new title'})
"default_title": "Extension Title",
/*
定义了当用户单击扩展图标时所显示页面的文件位置, 值得注意的是Chrome不允许将JavaScript代码段直接内嵌入HTML文档,所以我们需要通过外部引入的方式引用JS文件。由于其在关闭后,就相当于用户关闭了相应的标签页,这个页面不会继续运行。当用户再次打开这个页面时,所有的DOM和js空间变量都将被重新创建,所以不要在popup页面的js空间变量中保存数据,而是利用localStorage和chrome.storage将数据保存在用户的硬盘上。
*/
"default_popup": "popup.html"
},
/*
Page Actions与Browser Actions非常类似,除了Page Actions没有badge外,其他Browser Actions所有的方法Page Actions都有。另外的区别就是,Page Actions并不像Browser Actions那样一直显示图标,而是可以在特定标签特定情况下显示或隐藏,所以它还具有独有的show和hide方法。
chrome.pageAction.show(integer tabId);
chrome.pageAction.hide(integer tabId);
另,tabId为标签(下面会具体讲解)id,可以通过tabs接口获取。
*/
"page_action": {
"default_icon": {
"19": "images/icon19.png",
"38": "images/icon38.png"
},
"default_title": "Extension Title",
"default_popup": "popup.html"
},
/*
在Manifest中指定background域可以使扩展常驻后台。background可以包含三种属性,分别是scripts、page和persistent。如果指定了scripts属性,则Chrome会在扩展启动时自动创建一个包含所有指定脚本的页面;如果指定了page属性,则Chrome会将指定的HTML文件作为后台页面运行。通常我们只需要使用scripts属性即可,除非在后台页面中需要构建特殊的HTML——但一般情况下后台页面的HTML我们是看不到的。persistent属性定义了常驻后台的方式——当其值为true时,表示扩展将一直在后台运行,无论其是否正在工作;当其值为false时,表示扩展在后台按需运行,这就是Chrome后来提出的Event Page。Event Page可以有效减小扩展对内存的消耗,如非必要,请将persistent设置为false。注意,persistent的默认值为true。
*/
"background": {
"scripts": ["background.js"]
},
/*
可以指定将哪些脚本何时注入到哪些页面中,当用户访问这些页面后,相应脚本即可自动运行,从而对页面DOM进行操作。属性值为数组类型,数组的每个元素可以包含matches、exclude_matches、css、js、run_at、all_frames、include_globs和exclude_globs等属性其中matches属性定义了哪些页面会被注入脚本,exclude_matches则定义了哪些页面不会被注入脚本,css和js对应要注入的样式表和JavaScript,run_at定义了何时进行注入,all_frames定义脚本是否会注入到嵌入式框架中,include_globs和exclude_globs则是全局URL匹配,最终脚本是否会被注入由matches、exclude_matches、include_globs和exclude_globs的值共同决定.     注意:content_scripts中的脚本只是共享页面的DOM(DOM中的自定义属性不会被共享),而并不共享页面内嵌JavaScript的命名空间。也就是说,如果当前页面中的JavaScript有一个全局变量a,content_scripts中注入的脚本也可以有一个全局变量a,两者不会相互干扰。当然你也无法通过content_scripts访问到页面本身内嵌JavaScript的变量和函数。
*/
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"css": ["mystyles.css"],
"js": ["jquery.js", "myscript.js"]
}
],
/*
有一些扩展允许用户进行个性化设置,这样就需要向用户提供一个选项页面。Chrome通过Manifest文件的options_page属性为开发者提供了这样的接口,可以为扩展指定一个选项页面。当用户在扩展图标上点击右键,选择菜单中的“选项”后,就会打开这个页面
*/
"options_page": "options.html",
/*
浏览器出于安全考虑是不允许跨域, 但这个规则如果同样限制Chrome扩展应用,就会使其能力大打折扣,所以Google允许Chrome扩展应用不必受限于跨域限制。但出于安全考虑,需要在Manifest的permissions属性中声明需要跨域的权限。
*/
"permissions": [
"*://www.google.com/*"
],
// 为notification服务,桌面通知功能
"web_accessible_resources": [
"images/*.png"
]
}
二、存储

对于网站来说,用户的设置通常保存在Cookies中,或者保存在网站服务器的数据库中。对于JavaScript来说,一些数据可以保存在变量中。
但,如果用户重新启动浏览器,这些数据就会消失。那么如何在扩展中保存用户的设置呢?我们可以使用HTML5新增的localStorage接口。
当然,Chrome为扩展应用提供了存储API,以便将扩展中需要保存的数据写入本地磁盘。Chrome提供的存储API可以说是对localStorage的改进,它与localStorage相比有以下区别:
  1.如果储存区域指定为sync,数据可以自动同步;
  2.content_scripts可以直接读取数据,而不必通过background页面;
  3.在隐身模式下仍然可以读出之前存储的数据;
  4.读写速度更快;
  5.用户数据可以以对象的类型保存。
对于第二点需要说明一下。首先localStorage是基于域名的,而content_scripts是注入到用户当前浏览页面中的,如果content_scripts直接读取localStorage,所读取到的数据是用户当前浏览页面所在域中的。所以通常的解决办法是“content_scripts”通过runtime.sendMessage和“background”通信,由“background”读写扩展所在域(通常是chrome-extension://extension-id/)的localStorage,然后再传递给content_scripts。

使用Chrome存储API必须要在Manifest的permissions中声明"storage",之后才有权限调用。Chrome存储API提供了2种储存区域,分别是sync和local。两种储存区域的区别在于,sync储存的区域会根据用户当前在Chrome上登陆的Google账户自动同步数据,当无可用网络连接可用时,sync区域对数据的读写和local区域对数据的读写行为一致。对于每种储存区域,Chrome又提供了5个方法,
分别是get、getBytesInUse、set、remove和clear,如下:

/*
StorageArea为sync或则local
例, chrome.storage.sync.get(...)
*/
chrome.storage.StorageArea.get(keys, function(result){
  console.log(result);
});
chrome.storage.StorageArea.getBytesInUse(keys, function(bytes){
  console.log(bytes);
});
chrome.storage.StorageArea.set(items, function(){
  //do something
});
chrome.storage.StorageArea.remove(keys, function(){
  //do something
});
chrome.storage.StorageArea.clear(function(){
  //do something
});

Chrome同时还为存储API提供了一个onChanged事件,当存储区的数据发生改变时,这个事件会被触发,如下:

/*
callback会接收到两个参数,第一个为changes,第二个是StorageArea。changes是个对象,键为更改的属性名称,值包含两个属性,分别为oldValue和newValue
*/
chrome.storage.onChanged.addListener(function(changes, areaName){
  console.log('Value in '+areaName+' has been changed:');
  console.log(changes);
});
三、通信

Chrome提供了4个有关ChromeExtension页面间相互通信的接口,分别是runtime.sendMessageruntime.onMessageruntime.connectruntime.onConnect。

且,Chrome提供的大部分API是不支持在"content_scripts"中运行的,但runtime.sendMessageruntime.onMessage可以在"content_scripts"中运行,所以扩展的其他页面也可以同content_scripts相互通信。

/*
extensionId(optional)为所发送消息的目标扩展,如果不指定这个值,则默认为发起此消息的扩展本身;
message(required)为要发送的内容,类型随意,内容随意
options(optional)
callback(optional)用于接收返回结果
*/
chrome.runtime.sendMessage(extensionId, message, options, callback)
/*
callback(required)接收到的参数有三个,分别是message、sender和sendResponse。
其中sender对象包含4个属性,分别是tab、id、url和tlsChannelId,tab是发起消息的标签(下节会详讲)
*/
chrome.runtime.onMessage.addListener(callback)

例如,popup.html与backgroud可以如下通信:

//popup.html
chrome.runtime.sendMessage('Hello', function(response){
document.write(response);
}); //background
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
if(message == 'Hello'){
sendResponse('Hello from background.');
}
});

查看popup.html页面会发现有输出“Hello from background.”

四、标签

标签的意思就是在浏览器中打开的一个个页面,如下:

Chrome通过tabs方法提供了管理标签的方法与监听标签行为的事件,大多数方法与事件是无需声明特殊权限的,但有关标签的urltitlefavIconUrl的操作(包括读取),都需要声明tabs权限。

"permissions": [
"tabs"
]

获取标签信息。Chrome提供了三种获取标签信息的方法,分别是getgetCurrentqueryget方法可以获取到指定id的标签,getCurrent则获取运行的脚本本身所在的标签,query可以获取所有符合指定条件的标签。

以getCurrent为例,代码如下:

chrome.tabs.getCurrent(function(tab){
console.log(tab);
});

重点是,ChromeExtension也可以与指定的标签通信(标签中注入了"content_scripts"),方法如下:

chrome.tabs.sendMessage(tabId, message, function(response){
console.log(response);
});
五、拓展阅读

[1]. Chrome Extensions

[2]. Chrome扩展及应用开发

ChromeExtension那些事儿的更多相关文章

  1. 说说Makefile那些事儿

    说说Makefile那些事儿 |扬说|透过现象看本质 工作至今,一直对Makefile半知半解.突然某天幡然醒悟,觉得此举极为不妥,只得洗心革面从头学来,以前许多不明觉厉之处顿时茅塞顿开,想想好记性不 ...

  2. 总结iOS开发中的断点续传那些事儿

    前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...

  3. setTimeout那些事儿

    一.setTimeout那些事儿之单线程 一直以来,大家都在说Javascript是单线程,浏览器无论在什么时候,都且只有一个线程在运行JavaScript程序. 但是,不知道大家有疑问没——就是我们 ...

  4. Javascript中关于cookie的那些事儿

    Javascript-cookie 什么是cookie? 指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密).简单点来说就是:浏览器缓存. cookie由什 ...

  5. webpack那些事儿

    webpack那些事儿01-webpack到底是什么 webpack那些事儿02-从零开始 webpack那些事儿03-热插拔 hot webpack那些事儿04-spa项目实战分析 webpack那 ...

  6. 关于JSON的那些事儿

    JSON的那些事儿 曾经有一段时间,XML是互联网上传输结构化数据的事实标准,其突出特点是服务器与服务器间的通信.但是业内不少人认为XML过于繁琐.冗长,后面为了解决这个问题也出现了一些方案,但是由于 ...

  7. MVC之前的那点事儿系列(10):MVC为什么不再需要注册通配符(*.*)了?

    文章内容 很多教程里都提到了,在部署MVC程序的时候要配置通配符映射(或者是*.mvc)到aspnet_ISPAI.dll上,在.NET4.0之前确实应该这么多,但是.NET4.0之后已经不要再费事了 ...

  8. MVC之前的那点事儿系列(8):UrlRouting的理解

    文章内容 根据对Http Runtime和Http Pipeline的分析,我们知道一个ASP.NET应用程序可以有多个HttpModuel,但是只能有一个HttpHandler,并且通过这个Http ...

  9. CSS知识回顾--读《CSS 那些事儿》笔记

    由于之前有了解过CSS的相关知识,有了一定的基础,所以读起<CSS 那些事儿>不是很有难度,况且我现在读起来时,CSS3和HTML5比较流行,这里只是记录一些CSS知识记录,不做详细铺开, ...

随机推荐

  1. 浏览器怎么解析一个hmtl文档

    注意 link里面的css文件是并行请求下载的 script里面的js文件是同步请求下载的 html页面中的语句都是从上往下执行的 浏览器是同步加载 JavaScript 脚本,即渲染引擎遇到 def ...

  2. Oracle 11g服务器安装详细步骤——图文教程

    1.大家可以根据自己的操作系统是多少位(32位或64位)的,到官网下载相应的安装程序,如下图所示. 有一点需要注意,Oracle的安装程序分成2个文件,下载后将2个文件解压到同一目录即可. 2.下载完 ...

  3. Ubuntu 12.04嵌入式交叉编译环境arm-linux-gcc搭建过程

    Ubuntu 12.04嵌入式交叉编译环境arm-linux-gcc搭建过程Linux版本:Ubuntu 12.04 内核版本:Linux 3.5.0 交叉编译器版本:arm-linux-gcc-4. ...

  4. 简单聊聊java中如何判定一个对象可回收

    背景 说到java的特性,其中一个最重要的特性便是java通过new在堆中分配给对象的内存,不需要程序员主动去释放,而是由java虚拟机自动的回收.这也是java和C++的主要区别之一:那么虚拟机是如 ...

  5. Java面试宝典

    相关概念 面向对象的三个特征 封装,继承,多态.这个应该是人人皆知.有时候也会加上抽象. 多态的好处 允许不同类对象对同一消息做出响应,即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消 ...

  6. struts2中struts.xml配置文件详解

    struts.xml的常用配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts ...

  7. webStorm恢复误删除文件或工程

    背景: 提交git时可能由于没有提交所有文件,不知什么原因导致最近几天所写文件全部消失,所改文件全部恢复到以前.最终通过webstorm找回项目.下面总结通过webstorm找回误删文件,或恢复到历史 ...

  8. word中表格第一列序号的设置

    表格中序号问题 1.新建一个表格.第一列选择编号后,编号后有tab,如下图 2.选中表格的编号,点击新建列表样式, 3.将编号后的字符改成nothing,在将单元格改成居中即可 4.在将单元格改成居中 ...

  9. Jdbc访问数据库篇

    一万年太久,只争朝夕 What JDBC 上部 JDBC(Java DataBase Connectivity)Java 数据库连接,主要提供编写 Java 数据库应用程序的 API 支持 java. ...

  10. salesforce零基础学习(八十三)analytics:reportChart实现Dashboard(仪表盘)功能效果

    项目中经常会用到Report以及Dashboard来分析汇总数据,Dashboard可以指定view as user,如果针对不同的用户需要显示其允许查看的数据,比如  根据role hierarch ...