手抓手带你实现一个chrome插件

241 阅读4分钟

概要

本文主要是手抓手的带大家实现一个简单且没用chrome插件,以实战为主,我们先看下实现之后的效果。

image.png 浏览器左上角有个图标,点击图标会展示一些丑陋的按钮 :)

分别点击更大老年人模,效果如下

image.png 点击大

image.png 点击更大

image.png 点击老年人模式 可以看到字体变大了:)

然后我们再点击开启健康上网,这时候它会帮你屏蔽掉一些不健康的网站:) 比如当我们搜澳门赌场会直接引流到我们工作站 image.png image.png

第一步:如何在我们的插件列表里看到我们自己的插件?

image.png

  1. 新建文件夹
  2. 新建manifest.json,输入以下配置
{
  "name": "Hello World",  //插件名
  "version": "1.0.0",     //插件版本
  "manifest_version": 2   //manifest.json的版本,这里固定是2
}

这时候在扩展的页面加载这个文件夹就可以看到这个插件了 image.png

什么是manifest.json?

manifest.json是插件的配置清单文件,我们这个插件的描述,要用什么功能,申请什么权限都要在这里去申明。

现在我们已经可以看到我们自己的插件了,但是没有logo,要设置logo需要在manifest内加入如下配置

"icons": {
  "16": "imgs/icon.png",  // 16 * 16像素的图片,后面跟图片的路径,图片格式最好是png
  "48": "imgs/icon.png",
  "128": "imgs/icon.png"
}

第二步:如何点击右上角出现丑陋的按钮?

manifest加入以下配置

"browser_action": {
  "default_icon": "imgs/icon.png",     //浏览器右上角图标
  "default_popup": "popup/popup.html"  //浏览器右上角弹窗
}

default_popup就是配置弹窗的字段,可以看到弹窗完全就是个html,所以我们可以为所欲为:) 加几个丑陋的按钮更是简单,但是要注意的是html内不可以使用内联js。

第三步:如何让字体变大?

最简单的办法就是遍历DOM,改变每个元素的font-size,那么在插件内怎么能够访问到页面的DOM元素呢?这时候就需要用到内容脚本content_script,它的意思就是将js脚本注入到页面。 manifest加入如下配置

"content_scripts": [
  {
    "matches": ["http://*/*", "https://*/*"], // js要注入到的页面
    "js": ["content-script.js"], //要注入的js
    "run_at": "document_start"  //js的执行时机,
    														//document_start:DOM开始加载时执行;
                                //document_end: documentContentLoad之后执行
    														//document_idle: window.onload左右执行
  }
]

然后我们新建content-script.js,在js内就可以为所欲为的操作DOM了,但是它的作用域是隔离的,也就是说不能访问页面其它脚本的变量。

第四步:如何在点击按钮时让字体变大?

现在我们遇到的问题是如何在点击按钮时通知给页面内的脚本,这就属于popup与内容脚本(content_script)的通信。此时我们要用到chrome提供的api。

popup.js内:

chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
  chrome.tabs.sendMessage(tabs[0].id, msg, function(response) {
    console.log(respone)
  });
});

首先使用chrome.tabs.query获取到当前窗口的当前tab栏,所谓当前窗口是指我们可能会打开多个chrome浏览器,每个浏览器就是指一个窗口,当前tab栏同理,我们会有多个标签栏。 然后我们通过chrome.tabs.sendMessage方法向某个标签页的内容脚本发送信息。

content_script内:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  sendResponse('nothing')
})

content_script内我们可以通过chrome.runtime.onMessage来接受信息。

chrome.tabs.query API详解: ****占位符

chrome.tabs.``sendMessage API详解: ****占位符

chrome.tabs.``onMessage API详解: ****占位符

第五步:如何实现屏蔽不健康的网站:)

要想屏蔽掉某些特类网站就需要拦截所有浏览器请求,拦截浏览器请求我们可以通过chrome.webRequestApi,但是现在的问题是把这个api放在哪个脚本里,如果放在content_script内,它是无权访问chrome.webRequest的,并且它最多只能捕获当前页面发出的请求,没办法捕获整个浏览器的请求,如果放到popup内,它的生命周期是有限的,它只有在弹出层弹出的时候才会执行,所以现在以上方法都没办法实现。这时就需要background脚本了,它是后台脚本,在后台执行,生命周期跟浏览器一样,即浏览器打开时它就会执行,浏览器关闭时它才结束。

manifest.json内:

"background": {
  "scripts": ["background.js"] //后台脚本配置
},

"permissions": [  //使用webRequest所要申请的权限
  "webRequest",
  "https://*/*",
  "http://*/*",
  "webRequestBlocking"
]

background.js

const forbidden = [
  encodeURIComponent('澳门赌场'),
  encodeURIComponent('美女荷官'),
  encodeURIComponent('在线发牌')
];

let isHealthInternet = false;
chrome.webRequest.onBeforeRequest.addListener(
  details => {
    if (!isHealthInternet) {
      return
    }

    let isForbid = false;
    forbidden.forEach(item => {
      if (details.url.indexOf(item) > -1) {
        isForbid = true;
      }
    })
    console.log(details.url)
    if (isForbid) {
      return { redirectUrl: 'https://d.guahao.cn' }
    }
  },
  { urls: ['<all_urls>'] },
  ['blocking']
);

function openHealthInternet() {
  isHealthInternet = true
}

function closeHealthInternet() {
  isHealthInternet = false
}