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 Extensions 插件扩展程序开发入门 #12

Open
diamont1001 opened this issue Oct 30, 2017 · 0 comments
Open

Chrome Extensions 插件扩展程序开发入门 #12

diamont1001 opened this issue Oct 30, 2017 · 0 comments

Comments

@diamont1001
Copy link
Owner

diamont1001 commented Oct 30, 2017

如果英文过关,直接看 官方文档 就好了,写的还是很清晰简单的,可以直接跳到看最后的 【章节:程序分享与发布】。

What are extensions?

Extensions are small software programs that can modify and enhance the functionality of the Chrome browser. You write them using web technologies such as HTML, JavaScript, and CSS.

Chrome Extensions,中文名叫 “Chrome浏览器扩展程序”。引用官方文档的描述,翻译一下就是 “可以修改和增强浏览器功能的 H5 小程序”。

它的入口在浏览器窗口的右上角,地址栏的最右边,如下图:
image

一般来说,还可以有弹窗界面,比如下面这个:
image

Getting Started

开发环境

时间关系,我已经准备好一个 DEMO 了。

  1. 下载 DEMO 源码
  2. Chrome 打开链接 chrome://extensions/
  3. 开启 “开发模式”

image

  1. 导入 DEMO

image

打开 DMEO 源码目录(包含 manifest.json 的那层),即可完成导入。

注意:目录不能包含 中文,不然会报错。

完成以上步骤,就完成项目的导入啦,现在可以看到 DEMO 的效果了,如下。

image

同时,浏览器插件扩展程序入口(右上角地址栏右边)也会出来 DEMO 的图标了,如下。
image

试下点击图标看看,弹出来的就是 popup 了。
image

OK,后面的事情,就根据文档也实现自己需要的功能就可以了。

manifest.json

manifest.json 是整个插件扩展程序中最重要的一个描述文件,这个 json 格式的文件包含了你整个扩展程序的一些重要描述,比如 “扩展程序名称”、“扩展程序图标”、“权限申请” 等。

下面给个官方的例子,加了点注释:

manifest.json 是 json 文件,是不允许有注释的,上面的 "//" 的注释是为了更方便的解释清楚每个字段的意义,大家在实际实现的时候记得把注释都删了才可以。

{
  // Required
  "manifest_version": 2, // manifest 版本号,这里都写 2 就好了,从 Google Chrome 18 开始,就开始升级到 2 版本了
  "name": "My Extension",
  "version": "1.0.0", // 扩展程序版本,这个是自定义的,建议参考 semver 规范(http://semver.org/)

  // Recommended
  "default_locale": "zh", // 默认语言,具体可以看 i18n 文档(https://developer.chrome.com/extensions/i18n)
  "description": "A plain text description", // 项目描述
  "icons": { // icon,不同的位置支持不同大小的 icon,具体看文档(https://developer.chrome.com/extensions/manifest/icons)
    "128": "icons/icon_128.png",
    "48": "icons/icon_48.png",
    "16": "icons/icon_16.png"
  },

  // Pick one (or none)
  "browser_action": { // 多数都是使用这个,插件扩展程序针对的是浏览器行为(图标是在地址栏外面)
    "default_icon": "icons/24.png", // 最佳大小为19*19,地址栏上的插件扩展程序的 icon(一般作为主入口)
    "default_popup": "popup.html", // 点击插件扩展程序 icon 后弹出来的窗口的主页面 html
    "default_title": "extentsions demo" // 当鼠标放到扩展程序图标上时显示的文字
  },
  "page_action": { // 插件扩展程序针对的是页面行为(图标是在地址栏里面的)
    ...
  },

  // Optional
  "author": ...,
  "automation": ...,
  "background": {
    // Recommended
    "persistent": false
  },
  "background": {
    "scripts": ["eventPage.js"],
    "persistent": false
  },
  "chrome_settings_overrides": {...},
  "chrome_ui_overrides": {
    "bookmarks_ui": {
      "remove_bookmark_shortcut": true,
      "remove_button": true
    }
  },
  "chrome_url_overrides": {...},
  "commands": {...},
  "content_capabilities": ...,
  "content_scripts": [{...}],
  "content_security_policy": "policyString",
  "converted_from_user_script": ...,
  "current_locale": ...,
  "declarative_net_request": ...,
  "devtools_page": "devtools.html",
  "event_rules": [{...}],
  "externally_connectable": {
    "matches": ["*://*.example.com/*"]
  },
  "file_browser_handlers": [...],
  "file_system_provider_capabilities": {
    "configurable": true,
    "multiple_mounts": true,
    "source": "network"
  },
  "homepage_url": "http://path/to/homepage",
  "import": [{"id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}],
  "incognito": "spanning, split, or not_allowed",
  "input_components": ...,
  "key": "publicKey",
  "minimum_chrome_version": "versionString",
  "nacl_modules": [...],
  "oauth2": ...,
  "offline_enabled": true,
  "omnibox": {
    "keyword": "aString"
  },
  "optional_permissions": ["tabs"],
  "options_page": "options.html",
  "options_ui": {
    "chrome_style": true,
    "page": "options.html"
  },
  "permissions": ["tabs"],
  "platforms": ...,
  "plugins": [...],
  "requirements": {...},
  "sandbox": [...],
  "short_name": "Short Name",
  "signature": ...,
  "spellcheck": ...,
  "storage": {
    "managed_schema": "schema.json"
  },
  "system_indicator": ...,
  "tts_engine": {...},
  "update_url": "http://path/to/updateInfo.xml",
  "version_name": "aString",
  "web_accessible_resources": [...]
}

常用 API

Chrome 给插件扩展程序提供了一系列的 API,但其实我们平时常用的也就那几个。

  • bookmarks: 书签管理接口,可以对浏览器的书签进行增删改查等管理
  • tabs: 标签管理接口,可以对浏览器的标签进行增删改查等管理
  • contextMenus: 右键菜单管理
  • cookies: 浏览器 cookie 的管理
  • notifications: 消息通知
  • desktopCapture: 可针对 “窗口” 或者 ”标签“ 的截图接口
  • i18n: 国际化(多语言支持)

程序分享与发布

当程序都开发完成了,想要发给小伙伴们体验下,可以怎么操作呢。

首先,要把程序打包

image

如图,点击 “打包扩展程序”。
image

第一个框需要定位到程序的根目录,也就是包含 manifest.json 文件的目录;
第二个框是填一个私钥文件的(同一个私钥打出来的插件扩展程序包的 ID 相同),第一次打包时因为没有所以不填。

image
如图,第一次打包完成后,会生成一个私钥文件(*.pem),可以保存好这个文件,下次升级打包的时候就可以使用了,不然打包出来的 ID 会变了,Chrome 就会把它当成一个新的程序了。

另外,*.crx 这个文件就是打包好的插件扩展程序了,这时你可以随意改名(别改后缀就行),然后发给其他人进行安装就可以试用你的这个程序了。

怎么安装?

拿到 *.crx 文件后,Chrome 打开链接 chrome://extensions/,然后把 *.crx 文件拖动到页面中间进行安装即可,如图。

image

image

安装完成后,点击右上角的�入口图标,弹出来的界面就是插件扩展程序的主页面(popup)。

”此扩展程序可能已损坏“ 问题修复

好像是 Chrome 53 版本起就会有这个问题,为了防止扩展程式被病毒木马或恶意软件修改,Chrome的扩展程序安全验证机制, 会比对本地扩展和Chrome商店中的扩展是否一致,如不匹配就会出现这个错误。

image

解决办法

我们平时在开发过程中,manifest.json 里不用写 "update_url": "https://clients2.google.com/service/update2/crx" 的,但是从商店下载下来的包会自动带上这个,所以如果我们是用商店下载下来的包去修改做开发的话,记得要把这句删掉,不然生成的 crx 文件别人是用不了的。

发布到 Chrome 商店

当一切准备就绪,就可以准备发布上线了,Chrome 有个官方的插件扩展程序市场,还自带了发布和更新等一体化管理的流程,非常方便,当然,需要先注册个 Chrome 账号。
传送门:【Chrome商店dashboard

注意,上传的是 zip 而不是上面生成的 crx 文件,具体参考:【https://developer.chrome.com/webstore/publish

实际例子(PP二维码扩展程序)

最后推广一个我很久之前刚学习前端的时候写的一个二维码扩展程序,还是挺好用的,有兴趣可以安装后直接查看代码(扩展程序都是开源的)。
image

常见问题

1. popup 页面在 Mac 上会有一个蓝框,如图:

image

这应该是一个 bug,经研究发现,它会自动给页面第一个 a 标签聚焦,从而产生蓝色的选择框,解决方法可以给页面最前面加上一个看不见的 a 标签。

<body>
<a href="#" style="width: 0; height:0;"></a>
...
</body>

2. ajax 网络请求跨域问题

这是一个很常见的问题,经常我们都会用到网络接口来请求数据,这时接口可能会有跨域同源限制,或者对 Origin 又或者对 Referer 来做防盗链。
另外,由于 CSP(contentSecurityPolicy) 问题,jsonp 也是用不了的。

解决方案:

Chrome 插件扩展程序 API 有提供了一个 webRequest 接口,可以通过它来修改发出去的网络请求的一些信息,比如 RefererOrigin 等。

首先,要在 mainfest.json 文件添加 webRequest 的权限:

"permissions": [
  "webRequest",
  "*://*.api.com/"
]

*://*.api.com/ 这里就是你请求的网络接口的域名

然后,添加代码来修改 referer 信息:

// popup.js

  chrome.webRequest.onBeforeSendHeaders.addListener(
    function(details){
        var newRef = "https://xxx.api.com/index.html";
        var gotRef = false;
        for(var n in details.requestHeaders){
          gotRef = details.requestHeaders[n].name.toLowerCase() === 'referer';

          if(gotRef){
            details.requestHeaders[n].value = newRef;
            break;
          }
        }
        if(!gotRef){
          details.requestHeaders.push({
            name: 'Referer',
            value: newRef
          });
        }

        return {requestHeaders: details.requestHeaders};
    },{
      urls:["*://xxx.api.com/*"]
    },[
      "requestHeaders",
      "blocking"
    ]
  );

最后,要说明一下的是,以上的代码只能修改使用 fetch 发起的网络请求,而对 xhr 的请求是没用的,所以,记得把请求库切换为 fetch,如:

fetch('http://xxx.api.com/getlist').then(response => {
  if (response.status === 200){
    return response.json();
  }
}).then(json => {
  console.log(json);
}).catch(err => {
  console.log(err);
});

完成以上步骤,再请求一下看看,会发现请求的 Referer 已经会被修改了,这样,就再也不怕什么跨域的问题了。

3. 引入外部 js 时报 Refused to load the script 的问题

在页面里引入一个 JS ,比如 jquery,在 Chrome 插件里会报错,比如:

<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>

会报以下错误:

image

分析原因,还是 CSP(contentSecurityPolicy) 的问题。

解决方案

修改 content_security_policy,把对应的域名加上去即可,比如以上的问题可以酱紫解决:

# manifest.json
{
    ...
    "content_security_policy": "script-src 'self' https://code.jquery.com; object-src 'self'"
    ...
}

以上表示允许 https://code.jquery.com 域名下的外部 js 的引入。

附1:扩展程序的安装目录

Chrome 插件扩展程序是开源的方式安装的,可以去安装目录通过扩展程序 ID 来找到源码。

正常情况下,Chrome 插件扩展程序的默认安装目录如下:

  • Windows XP:C:\Documents and Settings\用户名\Local Settings\Application Data\Google\Chrome\User Data\Default\Extensions
  • Windows7:C:\Users\用户名\AppData\Local\Google\Chrome\User Data\Default\Extensions
  • Mac:~/Library/Application Support/Google/Chrome/Default/Extensions
  • Ubuntu:~/.config/google-chrome/Default/Extensions

如果在这些不同操作系统中的默认安装位置没找到插件,那么还有一种方法可以查询到。

  1. 地址栏访问 chrome:version
  2. 找到 “个人资料路径”,该路径下的 extensions 文件夹就是 Chrome 插件扩展程序的安装路径了
  3. 安装路径下的插件扩展程序,是以 ID 为目录区分的
  4. 地址栏访问 chrome://extensions/,可以查看每个插件扩展程序的 ID,比如 “UC二维码插件” 的 ID 为 nhelohnehpahakjoklmodmogclacjgdj

附2:资料参考:

@diamont1001 diamont1001 changed the title Chrome Extensions 开发指南 Chrome Extensions 插件扩展程序开发指南 Oct 30, 2017
@diamont1001 diamont1001 changed the title Chrome Extensions 插件扩展程序开发指南 Chrome Extensions 插件扩展程序开发入门 Oct 30, 2017
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

1 participant