Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chrome插件开发简介(一)——开发入门 #25

Open
Froguard opened this issue Mar 31, 2017 · 6 comments
Open

chrome插件开发简介(一)——开发入门 #25

Froguard opened this issue Mar 31, 2017 · 6 comments

Comments

@Froguard
Copy link
Member

Froguard commented Mar 31, 2017

chrome插件开发简介(一)——开发入门

chrome作为目前最流行的浏览器,备受前端推崇,原因除了其对于前端标准的支持这一大核心原因之外,还有就是其强大的扩展性,
基于其开发规范实现的插件如今已经非常庞大,在国内也是欣欣向荣,
如天猫开发了大量的扩展,用于检测页面质量以及页面性能,淘宝开发了许多的扩展以供运营工具的优化等等。其强大性不言而喻。

这里我们来讲一下其插件开发

基础概念

  1. 与chrome应用类似,chrome扩展主要是用于扩充chrome浏览器的功能。他体现为一些文件的集合,包括前端文件(html/css/js),配置文件manifest.json。
    主要采用JavaScript语言进行编写。

个别扩展可能会用到DLL和so动态库,不过出于安全以及职责分离的考虑,在后续的标准中,将会被舍弃,这里不再赘述

  1. chrome扩展能做的事情:
  • 基于浏览器本身窗口的交互界面
  • 操作用户页面:操作用户页面里的dom
  • 管理浏览器:书签,cookie,历史,扩展和应用本身的管理,其中甚至修改chrome的一些默认页面,地址栏关键字等,包括浏览器外观主题都是可以更改的

这里需要着重提一下,前端开发者喜欢的DevTools工具,在这里也能进行自定义

  • 网络通信:http,socket,UDP/TCP等
  • 跨域请求不受限制:
  • 常驻后台运行
  • 数据存储:采用3种方式(localStorage,Web SQL DB,chrome提供的存储API(文件系统))
  • 扩展页面间可进行通信:提供runtime相关接口
  • 其他功能:下载,代理,系统信息,媒体库,硬件相关(如usb设备操作,串口通信等),国际化
  1. chrome扩展的限制:
  • 环境限制:基本上功能性操作都需要通过chrome提供的API来完成,这跟实际的页面js又有一些差异,看上去并没有那么的完全自由。
    如chrome扩展的页面脚本,可以获取并操作页面dom,但是,出于安全性的考虑,页面脚本的域是独立区分开来的,即js成员变量不共享。
    即:插入到用户页面的js脚本可执行,但是与原始脚本不同执行域,互相不会影响。
    content_script不能使用除了chrome.extension之外的chrome.* 的接口,不能访问它所在扩展中定义的函数和变量,不能访问web页面或其它content script中定义的函数和变量,不能做cross-site XMLHttpRequests

  • chrome扩展,其功能受限于chrome的API,比如说文件系统,必须通过chrome的fileSystem接口,而这些接口仅仅只是对html5已有的文件系统接口的扩展,
    它允许Chrome应用读写硬盘中用户选择的任意位置,而HTML5本身提供的文件系统接口则只能在沙箱中读写文件,并不能获取用户磁盘中真正的目录。

  • 其他,一些潜在的会引起漏洞的操作,或者说不建议的操作,会被禁止掉。
    比如,想要通过用js代码主动唤起打开devtools面板,这个是不允许的。
    https://bugs.chromium.org/p/chromium/issues/detail?id=112277

可以看到回复:

We only allow explicit devtools opening.

举个栗子:apple:

下面以一个简单的例子来简述一下我们开发扩展过程中会遇到哪些问题

这个栗子主要用于去自定义用户页面的样式(比如此处为改滚动条样式),插入一个自定义的脚本到用户页面中执行(此处为输出一些简单信息)

1.编辑扩展程序所需要的主要文件夹

文件结构说明

 ./
 ├─ manifest.json //扩展的配置项
 ├─ Custom.js     //自定义js脚本
 ├─ Custom.css    //自定义css样式
 ├─ icon.png      //扩展程序的icon
 └─ popup.html    //扩展的展示弹窗
  • 自定义js脚本:浏览器中执行,但并非真正意义上的“插入”,与原来页面的js域隔离开

例如,custom.js中的window跟页面js中的window不是同一个对象,变量也无法共享。

console.log('执行init');
console.log(document.title);
console.log(document.getElementById("abc"));
// 实例函数,可以供popup.html中调用
function helloWorld(name){
    console.log(`${name} say 'hello world!'`);
    alert(`${name} say 'hello world!'`);
}
//...

这样的脚本路径将以 chrome://extensions/扩展的id串码/path/to/you/js/xxx.js出现在控制台调试时候。

image

  • 自定义样式:同样,css也不是真正的插入到页面的document中,而是浏览器的样式生效策略中会加入这些样式规则

image

/* 重置滚动条 */
::-webkit-scrollbar {width:4px!important;height:7px;}
::-webkit-scrollbar-button {display:none;}
::-webkit-scrollbar-thumb {border-radius:3px;background: #45A5DB;}
::-webkit-scrollbar-track {width:4px;height:7px;background:transparent;}
::-webkit-scrollbar-track-piece {background:transparent;}

/* ... */
  • 小窗口popup.html:这里面是一个按钮,点击后去调用custom.js里面的helloWorld函数
<!doctype html>
<html>
  <head>
    <title>hello world</title>
  </head>
  <body>
    <h2>hello world</h2>
	<p><button onclick="dealClick('王小明')">按钮</button></p>
    <script>
        function dealClick(name){
            //这里值得注意,大部分功能性操作,比如执行脚本,执行函数,都是不可以直接执行,而需要通过chrome.*这样方式进行
            chrome.tabs.executeScript(
                null,
                {
                    code: `helloWorld('${name}')` // 这里调用的是上面的custom.js重定义好的function
                }
            );
        }
    </script>
  </body>
</html>
  • 核心配置文件manifest.json
{
  "name": "扩展名称",
  "version": "1.0.0",
  "manifest_version": 2,
  "description": "扩展描述",
  "icons" : {           // 扩展的icon
    "16" : "icon.png",
    "48" : "icon.png",
    "128" : "icon.png"
  },
  "browser_action": {   // browser_action表示程序图标会出现在地址栏右侧,若要出现在地址栏,则写成page_action
    "default_title": "日报工具",
    "default_icon": "icon.png",
    "default_popup": "popup.html"
  },
  "content_scripts": [  //content_scripts是在Web页面内运行的javascript脚本。
                        //通过使用标准的DOM,它们可以获取浏览器所访问页面的详细信息,并可以修改这些信息。
    {                   //这里的值是数组,可以针对多个站点进行不同的操作配置
      "matches": [
        "http://www.google.com/*"
      ],
      "css": [
        "custom.css"
      ],
      "js": [
        "custom.js"
      ],
      "all_frames": true,
      "run_at": "document_idle"
    }
  ],
  "permissions": [   //一些权限的配置,
    "cookies",       //比如cookie权限,比如系统通知权限,类似于notify这样的东西,在window系统上未右下角的小气泡
    "notifications"
  ]
}

page_action,browser_action类型的扩展对应位置

image

2.打包生成插件包

浏览器打开 chrome://extensions/(或者‘更过工具->扩展程序’),左上角有一个 打包扩展程序 按钮

image

然后,将生成的*.crx文件拖到浏览器即可完成安装。

到这步插件其实已经差不多了,当然,这里的功能都比较简单,你可以自己尝试一些更高级的功能

由于自己DIY的扩展是没有发布到web app store的,所以下次打开浏览器时会被禁掉,解决方法见第二篇文章《chrome插件开发简介(二)——如何添“加浏览器扩展白名单”》

@TerryZwei
Copy link

感谢分享这么详细的教程,但是文章中例子需要修改几个地方才能正常运行。

  • popup.html里面的行内js代码需要通过外部引用js文件的方式写入,还有按钮的事件绑定也要写在外部的js里面;
  • 配置文件manifest.json里面的permissions缺少tabs和当前的页面的权限配置;

@Froguard
Copy link
Member Author

Froguard commented Sep 25, 2017

@TerryZwei 恩,为了示例好看,代码部分确实删减过一些。多谢指正.

@Benjamin-UnderWood
Copy link

请问怎么能使用chrome.runtime 这类的API? 官网的例子没实现出来。。

@huhuang03
Copy link

希望能加上icon的下载地址。方便大家!!

@kyao777
Copy link

kyao777 commented Jul 27, 2018

请问一下,如果在chrome扩展中实现以一定的时间间隔刷新页面,我通过setTimeout() 和setInternal()都只是点击那一刻可以刷新,能帮忙指点一下是否需要什么特殊的权限配置。

@ilaipi
Copy link

ilaipi commented Nov 25, 2018

能讲一下怎么开发调试么?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants