写点什么

浏览器插件:那些你需会的操作

用户头像
梁龙先森
关注
发布于: 2020 年 11 月 15 日
浏览器插件:那些你需会的操作

Chrome 扩展程序序列文章:

  1. 浏览器插件:那些你需会的操作

  2. 热更新方案设计:1.原理分析及构建部署实现

  3. 热更新方案设计:2.基于双缓存更新功能模块

1、 配置文件(manifest.json)详解
{  "manifest_version": 2, // manifest文件版本号。Chrome18开始必须为2  "page_action": {}, // 地址栏右侧图标管理。包含图标及页面设置等  "theme": {}, // 用于更改整改浏览器的主题  "app": {}, // 指定扩展需要跳转到的URL  "background":{}, // 指定扩展进程的background运行环境  "chrome_url_overrides":{ // 替换页面,将原定显示的页面替换为自定义页面    "pageToOverride":"", // 页面    "bookmarks":"", // 书签    "history":"", // 历史    "newtab":"" // 新标签页  },   "content_scripts":[{ // 指定向web页面注入的脚本/css。    "matches":[], // 匹配的url    "css":[],  // 注入的css资源路径    "js":[],   // 注入的js资源路径    "run_at":""  // 注入的时机。 document_start|end|idle    "all_frames":1, // 是否运行在所有frame中    ...  }],   "content_security_policy": "",  // 安全策略  "homepage_url": "http://xxx", // 扩展的官方主页  "options_page": "", // 选项页。用于在扩展管理页面跳转到选项设置  "permissions":[   // 权限     "bookmarks",   // 启用书签权限     "contextMenus", // 启用右键菜单权限     "cookies",     // 启用cookie权限     "experimental", // 启用chrome的实验性功能API     "history",     // 启用history权限     "notifications",  // 启用桌面通知权限     "tabs",         // 启用标签权限     "activeTab",    // 启用活动标签权限     ...  ],    "requirements": {}, // 指定所需要的特殊技术。目前只支持"3D"  "update_url": "",   // 自动升级  "plugins":[],  // 扩展。 可调用第三方扩展  "web_accessible_resources": [] // 指定资源路径,为String数组  ...}
复制代码
2、如何优雅处理前后通信

问题:传统处理通信,当请求众多,background.js 中监听的请求处理逻辑大,手动引入注册监听费事。

// CS页面发起请求chrome.extension.sendRequest({  ...},function(res){
})
// background.js监听请求chrome.extension.onRequest.addListener( function(request,sender,sendResponse){ switch(...){ case ...: // 通过request匹配出请求标识 ...; // 引入或编写对应的业务逻辑 break; } })
复制代码

解决方案:工程化,通过 webpack 的能力,自动注册监听

  1. 设计目录结构

requestModule/  index.js    // 获取所有的请求监听模块  requestModule1.js  // 请求监听模块  requestModule2.jsregesiterRequest.js  // 注册监听
复制代码
  1. 代码实现

// requestModule/index.js
// 注册所有的导出的请求监听函数let requestProvider = {}
//获取一系列完整的依赖关系 参数解释:(目录,是否包含子目录,匹配文件)const request = require.context('./', false, /^((?!index).)*\.js$/)request.keys().forEach(path => { const module = request(path).default || request(path) Object.keys(module).forEach(key => { if (module[key] && requestProvider[key]) { throw new Error(`${key}该函数名已被占用,请更换函数名`) } requestProvider[key] = module[key] })})export default requestProvider
复制代码


// regesiterRequest.js
import isFunction from 'lodash/isFunction'import requestProvider from './requestModule/index'// 注册所有的请求监听chrome.extension.onRequest.addListener( function(request, sender, sendResponse) { if (!request.name) { throw 'request的name值,是必传参数!' } if (filterFn.indexOf(request.name) > -1) { return } if (!isFunction(requestProvider[request.name])) { console.warn(`requestProvider中不存在 ${request.name} 这个方法!`) return } if(typeof requestProvider[request.name] === 'function'){ requestProvider[request.name](request, sendResponse) } });
复制代码
3、拦截 HTTP 请求

a、声明权限(manifest.json)

{  "permissions":{    "webRequest"  }}
复制代码

b、介绍 onBeforeSendHeaders 的使用:允许添加/修改/删除 request headers

// 例子:删除所有的request中User-Agent的Headerchrome.webRequest.onBeforeSendHeaders.addListener(  function(details) {    for (var i = 0; i < details.requestHeaders.length; ++i) {      if (details.requestHeaders[i].name === 'User-Agent') {        details.requestHeaders.splice(i, 1);        break;      }    }    return {requestHeaders: details.requestHeaders};  },  {urls: ["<all_urls>"]},  ["blocking", "requestHeaders"]);
复制代码

c、介绍 onBeforeRequest 的使用:在 TCP 连接建立之后和 HTTP 数据发送之前被调用的事件

// 例子:阻止发往百度的requestchrome.webRequest.onBeforeRequest.addListener(  function(details) {    return {cancel: details.url.indexOf("://www.baidu.com/") != -1};  },  {urls: ["<all_urls>"]},  ["blocking"]);
复制代码

d、API 文档

// onBeforeSendHeaders的callback的参数details结构details = {    tabId: integer, //如果没有和tab关联则返回-1    parentFrameId: integer,    url: string,    timeStamp: double,    //0表示request是在main frame里发生的    frameId: integer,    requestId: string,    requestHeaders: HttpHeaders, // optional    type: enumerated_string, //value in:  ["main_frame", "sub_frame", "stylesheet", "script", "image", "object", "xmlhttprequest", "other"]    method: string //标准HTTP方法};
RequestFilter = { tabId: interger, //optional //URL的数组,或者是匹配URL的pattern urls: array_of_string, //可选的值有:"main_frame", "sub_frame", "stylesheet", "script", "image", "object", "xmlhttprequest", "other" types: array_of_enumerated_string, //optional windowId: integer //optional};
// 设置了blocking关键字的就用这个object来作为block的规则了BolockingResponse = { //为true的话request被cancel,在onBeforeRequest里面用哦 cancel: boolean, //optional //只在onBeforeRequest事件中使用,用来掉包的关键属性!!! redirectUrl: string, //option //只用在onHeadersReceived事件里,在浏览器返给server时把header给掉包 responseHeaders: HttpHeaders //optional //只在onBeforeSendHeaders事件中使用。是另一个用来掉包的关键属性!!! requestHeaders: HttpHeaders //optional //只在onAuthRequred事件中使用,当然也是用来掉包的 authCredentials: object //optional};
复制代码
4、 域绝缘下,操作 PageScript 页的 JS 对象

往页面注册脚本,操作对象。常用于对编辑器的功能增强需求。

const originInject = function(jsPath, id, cb) {  if(id && document.getElementById(id)){	  typeof cb==="function" && cb()	  return;  }
jsPath = jsPath || '' var temp = document.createElement('script') temp.setAttribute('type', 'text/javascript') // 获得的地址类似:chrome-extension://****/js/inject.js temp.src = chrome.extension.getURL(jsPath) if(id){ temp.id = id } temp.onload = function() { typeof cb=="function" && cb() }; document.head.appendChild(temp)}
复制代码
5、开发支持热更新

webpack-chrome-extension-reloader:扩展程序热更新插件

// webpack.config.js{  ...  plugins:initPlugins.concat([new ChromeReloadPlugin({  port: config.port,  reloadPage: true,  entries: {    // 背景页       background: 'background',    // 配置ContentScripts的路径    contentScript: Object.keys(entries).filter(function (item) {       return item.indexOf('content-scripts') > -1    })  }})])}
复制代码


--END--


作者:梁龙先森 WX:newBlob


原创作品,抄袭必究!


发布于: 2020 年 11 月 15 日阅读数: 90
用户头像

梁龙先森

关注

脚踏V8引擎的无情写作机器 2018.03.17 加入

还未添加个人简介

评论

发布
暂无评论
浏览器插件:那些你需会的操作