Chrome插件是令人惊讶的简单,一旦你弄懂它的工作和实现原理。它是由一部分HTML,一部分Js,然后混合了一个叫做manifest.json的Json文件组合而成的整体。这意味着你可以使用你最擅长的js框架去实现它。

  如果你还是一个Chrome插件的新手并且想尝试写一个的话,下面的文章将会带领大家并且尝试让大家理解Chrome插件的工作机制。这篇文章将会讲述每一块架构,以及相互之间的联系和插件的一般化形式。

架构

  Chrome插件中的文件大体上可以分成2部分:Chrome插件中确确实实存在的文件,并且是应用程序级别的,如上图的Chrome Extension Scripts以及注入到每个网页Dom当中的文件(如Content Scripts 或者Injected Scripts).这些文件都被放在manifest.json当中,Chrome内部会自动识别不同个文件的作用。

  在任何时候,popup和background都只有一份,相比较起来,如果你有多个Tab(这里的Tab指的是Chrome当中的选项卡,也就是一个窗口页面),那么Content Scripts和 Injected Scripts会运行在每一个Tab当中,也就是可以跨选项卡。当然,你可以指定往哪个Tab当中去注入Scripts,也就是说,注入操作是可选择的。

  下面是一些它们如何工作的细节:

Manifest.json

  • 这个Json文件是把backgrounds, popups, content scripts 和injected scripts 放在一起,并以结构化的方式书写。
  • 设置扩展,如Permission。
  • 设置扩展的基本信息。

Background

  • Javascript文件总是运行在后台(在老版本的Chrome当中,background是html文件并且嵌入了javascript).
  • 没有显示界面。
  • 有Chrome应用程序级别命令的访问权限。
  • 有使用所有Chrome API的权限

Popup

  • 点击插件图标会显示出Html和Javascirpt.
  • 也拥有应用程序级别的权限(和background一样)
  • 只有当Chrome插件的图标点击的时候才触发。
  • 对所有的pop-up Chrome API有使用权限。

Content Scripts

  • 拥有一部分Api的使用权限(比如从backgorund监听消息)
  • 对于页面Dom有完整的访问权限,但是对于任何window级别的对象没有访问权限(比如全局变量),对于frame也没有访问权限;这是因为安全限制。
  • Content scripts运行在介于插件和页面之间,全局的window对象是和页面/插件全局命名空间完全不同的。

Injected Scripts

  • 和Contente Scripts 一样,只拥有部分Api的使用权限
  • 注入当前Tab的网页当中,并不与插件进行通信。

关联关系

  他们之间的联系只要你弄懂了整体的架构,我相信就会很明了。

  在应用程序级别的部分是可以有互相访问的权限的。比如Popup文件能用chrome.extension.getBackgroundPage()访问background里面的东西,这就好像Backbone 视图可以访问他们的Model和Collection。

  Content Scripts是存在于每个独立的Dom页面,和background和popup用message的方式进行通信交流。特别的,它可以使用chrome.tabs.sendMessage和chrome.runtime.onMessage.addListener去向对方发送消息。这和Backbone 的事件系统很像.

  Injected Scripts和Content Scripts的不同在于它不能监听或者发送消息给其他的Chrome插件部分。

结构

  组织你的Chrome插件,能更好的让你分清楚不同的文件的不同作用。不同的项目的组织结构都可以是相似的,下面列举了一种组织形式,大家可以参考一下。

  Manifest.json把所有的需要的文件都放在一起了,需要注意的一点是文件是按顺序被编译的,所以被依赖的文件往往是放在实际的script文件之前的,下面的代码中,jquery.js实在content scripts中的recorder.js和player.js之前的。  

{
"manifest_version": 2, # 插件基本信息
"name": "MyExtension",
"description": "MyExtension",
"version": "1.0.0", # popup弹出窗文件位置
"browser_action": {
"default_icon": "img/icon.png",
"default_popup": "popups/popup.html"
}, # 设置 content scripts 以及什么时候注入什么类型的页面
"content_scripts": [{
"matches": ["http://*/*","https://*/*"],
"css":["styles/styles.css"],
"js": [
"bower_components/jquery/dist/jquery.min.js",
"content-scripts/recorder.js",
"content-scripts/player.js",
]
}], # 设置background的scripts
"background": {
"scripts": [
"bower_components/jquery/dist/jquery.min.js",
"bg/background.js"
]
}, # 脚本的权限
"permissions": [
"<all_urls>",
"tabs",
"storage",
"unlimitedStorage"
]
}

动手做一个Chrome插件

  说了再多,不做也是没用的。我们先新建一个Manifest.json文件,复制如下代码:

{
"manifest_version": 2, "name": "GTmetrix Analyzer Plugin",
"description": "This extension will analyze a page using GTmetrix",
"version": "1.0", "browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}

  其中有几点需要注意,browser_action 这个指定了点击插件的时候,弹出的页面以及 插件的图标。Permission 就是指定了哪些URL对于这个插件是有用的,比如你可以输入特定的域名,那么只有在这个域名下,这个插件才有用。

  下面我们来新建一个popup.html页面,代码如下。

<!doctype html>
<html>
<head>
<title>GTmetrix Analyzer</title>
<script src="popup.js"></script>
</head>
<body>
<h1>GTmetrix Analyzer</h1>
<button id="checkPage">Check this page now!</button>
</body>
</html>

  大家可能注意到了我其实使用了一个popus.js的文件,这个其实是为了实现点击checkPage时候的效果所必须的脚本,下面我们新建一个popup.js的文件。

ocument.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function() { chrome.tabs.getSelected(null, function(tab) {
d = document; var f = d.createElement('form');
f.action = 'http://gtmetrix.com/analyze.html?bm';
f.method = 'post';
var i = d.createElement('input');
i.type = 'hidden';
i.name = 'url';
i.value = tab.url;
f.appendChild(i);
d.body.appendChild(f);
f.submit();
});
}, false);
}, false);

  细心的人不难发现,上面的代码就是向某个网站发一个post请求,checkPage其实是注册了click事件的,一旦按钮被点击了,我们就会获取到当前活动Tab并且执行一些js代码。

  那么怎么测试我们的插件呢?在Chrome地址栏输入chrome://extensions,打开开发者模式,然后点击加载已解压的扩展程序,选择相对应的目录就OK了,如果你的插件修改过,别忘了点一下重新加载(Ctrl+R)按钮。

  最终效果如下:

总结

  因为Chrome插件涉及的知识点很多,所以一次也讲不完,以后如果有时间,我会把我学到的东西和大家分享,另外这个插件也是我这2天学的,因为公司要做一个信息自动刷新的功能,所以才想到了Chrome插件,不过很可惜,竞赛完了,我并没得奖,也小小吐槽下吧。

动手做第一个Chrome插件的更多相关文章

  1. chrome 浏览器插件开发(一)—— 创建第一个chrome插件

    最近在开发一个chrome插件,在网上找到了一些的文章,虽说按照文章可以写出对应的例子,但若要进行实际开发,发现还是有不少文章中没有的坑.下面我将结合我在开发过程中遇到的几个方面,对这些坑做一下补充. ...

  2. 开发一个chrome插件:将百度搜索热点屏蔽掉!

    每次百度搜索,搜索结果的右边总是出现些乱七八糟的搜索热点(推的都是些什么玩意,高校替课和我有毛关系,几个悲伤的热点我用星号顶掉了). 强迫症想把它隐藏掉,我用的是chrome浏览器,受adblock( ...

  3. 我的项目:一个chrome插件的诞生记,名字叫jumper

    选课是个问题,为了选课,便有了以下的故事. 最开始,萌生想法于2013年7月. 接着网上了解了chrome的结构知识,却发现例子是假的. 幸好有之前师兄的一个同功能插件开源,但代码写得很乱,我喜欢逻辑 ...

  4. 为了少点击几次,自己写了一个Chrome插件

    缘由 chrome应用商店有三款二维码插件,自己一直使用的第一款.这三款插件有且只有一个功能就是生成当前页面的URL的二维码. 其实这个功能基本上满足了需要移动端开发在微信里打开页面进行调试的情况. ...

  5. 我的第一个Chrome插件:天气预报应用

    1.Chrome插件开发基础   开发Chrome插件很简单,只要会基本的前台技术HTML.CSS.JS就可以开发了. Chrome插件一般包括两个HTML页面background和popup.   ...

  6. 做了一个jquery插件,使表格的标题列可左右拉伸

    示例下载 插件名称命名为:jquery.tableresize.js,代码如下: /* Writen by mlcactus, 2014-11-24 这是我封装的一个jquery插件,能够使table ...

  7. js写一个chrome 插件

    访问网站的时候,最烦的就是一些弹窗和广告.于是,就想着能不能在访问特定网站的时候,执行一段js脚本,去除页面的广告.于是乎,好像 chrome 插件可以实现. 这里,以 百度 的网站为例 新建 sim ...

  8. 菜鸟写的第一个chrome插件

    一.新建一个文件夹,用来放插件的代码 二.首先新建配置文件manifest.json // 开发参考:http://open.chrome.360.cn/extension_dev/overview. ...

  9. 【Chrome】Octotree Chrome插件离线安装

    插件下载地址:http://www.cnplugins.com/devtool/octotree/download.html Octotree 是国外程序员Buu Nguyen 做的一个 Chrome ...

随机推荐

  1. [APUE]标准IO库(上)

    一.流和FILE对象 系统IO都是针对文件描述符,当打开一个文件时,即返回一个文件描述符,然后用该文件描述符来进行下面的操作,而对于标准IO库,它们的操作则是围绕流(stream)进行的. 当打开一个 ...

  2. 转:聊聊mavenCenter和JCenter

    Gradle支持从maven中央仓库和JCenter上获取构件,那这两者有什么区别呢? maven中央仓库(http://repo1.maven.org/maven2/)是由Sonatype公司提供的 ...

  3. Smarty的基本使用与总结

    含义: Smarty是PHP的一个引擎模板,可以更好的进行逻辑与显示的分离,即我们常说的MVC,这个引擎的作用就是将C分离出来. 环境需求:PHP5.2或者更高版本 我使用的环境是:PHP5.3,wi ...

  4. 小兔JS教程(三)-- 彻底攻略JS回调函数

    这一讲来谈谈回调函数. 其实一句话就能概括这个东西: 回调函数就是把一个函数当做参数,传入另一个函数中.传进去的目的仅仅是为了在某个时刻去执行它. 如果不执行,那么你传一个函数进去干嘛呢? 就比如说对 ...

  5. iOS 委托与文本输入(内容根据iOS编程编写)

    文本框(UITextField) 本章节继续编辑 JXHypnoNerd .文件地址 . 首先我们继续编辑  JXHypnosisViewController.m 修改  loadView 方法,向  ...

  6. HTML5实现文件断点续传

    HTML5的FILE api,有一个slice方法,可以将BLOB对象进行分割.前端通过FileList对象获取到相应的文件,按照指定的分割方式将大文件分段,然后一段一段地传给后端,后端再按顺序一段段 ...

  7. SharePoint 2013管理中心里【管理服务器上的服务】不见了

    打开管理中心,准备配置Managed Metadata Service,发现"管理服务器上的服务"不见了 那我自己拼url直接访问:http://xxxx/_admin/Serve ...

  8. ReactiveCocoa代码实践之-UI组件的RAC信号操作

    上一节是自己对网络层的一些重构,本节是自己一些代码小实践做出的一些demo程序,基本涵盖大多数UI控件操作. 一.用UISlider实现调色板 假设我们现在做一个demo,上面有一个View用来展示颜 ...

  9. 转:MSSQL还原单mdf文件报1813错误

    原文地址:http://www.cnblogs.com/clownkings/p/4950865.html 解决办法: 1.首先要备份好mdf文件,如果他没了经理非吃了你不可.都不吐骨头的. 2.在数 ...

  10. 自定义Angular插件 - 网站用户引导

    最近由于项目进行了较大的改版,为了让用户能够适应这次新的改版,因此在系统中引入了“用户引导”功能,对于初次进入系统的用户一些简单的使用培训training.对于大多数网站来说,这是一个很常见的功能.所 ...