When a new site is visited, the WebExtension creates a new ContentScript in that page's context, which can be seen at app/scripts/contentscript.js. This script represents a per-page setup process, which creates the per-page web3api, connects it to the background script via the Port API (wrapped in a stream abstraction), and injected into the DOM before anything loads.

当访问一个新站点时,WebExtension会在该页面的上下文中创建一个新的ContentScript,可以在app/scripts/ ContentScript .js中看到其的代码。这个脚本表示每个页面的设置过程,它创建每个页面的web3api,通过端口API(封装在流抽象中)将其连接到后台脚本,并在加载之前注入DOM。

它其实就是在页面与metamask之间进行交互前先通过contentscript来对页面的内容进行查看并判断是否提供web3给页面

metamask-extension/app/scripts/contentscript.js

它的作用就是将inpage.js这个脚本写到浏览器<script>上,使得浏览器能够调用这个脚本处理json rpc

const fs = require('fs')
const path = require('path')
const pump = require('pump')
const LocalMessageDuplexStream = require('post-message-stream')
const PongStream = require('ping-pong-stream/pong')
const ObjectMultiplex = require('obj-multiplex')
const extension = require('extensionizer')
const PortStream = require('./lib/port-stream.js') const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString()
const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('inpage.js') + '\n'
const inpageBundle = inpageContent + inpageSuffix // Eventually this streaming injection could be replaced with:
// https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction
//
// But for now that is only Firefox
// If we create a FireFox-only code path using that API,
// MetaMask will be much faster loading and performant on Firefox. if (shouldInjectWeb3()) {//判断传过来的访问页面如果判断满足能够InjectWeb3就将web3 inject并且建立从contentscript到inpage的双向流
setupInjection() //然后这样传给inpage后,其web3才能使用,然后再传给页面使用
setupStreams()
} /**
* Creates a script tag that injects inpage.js
*/
function setupInjection () {//将inpage.js脚本嵌入页面<script>中
try {
// inject in-page script
var scriptTag = document.createElement('script')
scriptTag.textContent = inpageBundle
scriptTag.onload = function () { this.parentNode.removeChild(this) }
var container = document.head || document.documentElement
// append as first child
container.insertBefore(scriptTag, container.children[])
} catch (e) {
console.error('Metamask injection failed.', e)
}
} /**
* Sets up two-way communication streams between the
* browser extension and local per-page browser context
*/
function setupStreams () { //建立contentscript到inpage的双向流,inpage.js是创建inpage到contentscript的双向流
// setup communication to page and plugin
const pageStream = new LocalMessageDuplexStream({
name: 'contentscript',
target: 'inpage',
})
const pluginPort = extension.runtime.connect({ name: 'contentscript' })
const pluginStream = new PortStream(pluginPort) // forward communication plugin->inpage
pump(
pageStream,
pluginStream,
pageStream,
(err) => logStreamDisconnectWarning('MetaMask Contentscript Forwarding', err)
) // setup local multistream channels
const mux = new ObjectMultiplex()
mux.setMaxListeners() pump(
mux,
pageStream,
mux,
(err) => logStreamDisconnectWarning('MetaMask Inpage', err)
)
pump(
mux,
pluginStream,
mux,
(err) => logStreamDisconnectWarning('MetaMask Background', err)
) // connect ping stream
const pongStream = new PongStream({ objectMode: true })
pump(
mux,
pongStream,
mux,
(err) => logStreamDisconnectWarning('MetaMask PingPongStream', err)
) // connect phishing warning stream
const phishingStream = mux.createStream('phishing')
phishingStream.once('data', redirectToPhishingWarning) // ignore unused channels (handled by background, inpage)
mux.ignoreStream('provider')
mux.ignoreStream('publicConfig')
} /**
* Error handler for page to plugin stream disconnections
*
* @param {string} remoteLabel Remote stream name
* @param {Error} err Stream connection error
*/
function logStreamDisconnectWarning (remoteLabel, err) {
let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}`
if (err) warningMsg += '\n' + err.stack
console.warn(warningMsg)
} /**
* Determines if Web3 should be injected
*
* @returns {boolean} {@code true} if Web3 should be injected
*/
function shouldInjectWeb3 () {决定是否应该插入web3
return doctypeCheck() && suffixCheck() &&
documentElementCheck() && !blacklistedDomainCheck() //
} /**
* Checks the doctype of the current document if it exists
*
* @returns {boolean} {@code true} if the doctype is html or if none exists
*/
function doctypeCheck () {//查看页面的类型
const doctype = window.document.doctype //指定文档类型节点是否为html或不存在
if (doctype) {
return doctype.name === 'html'
} else {
return true
}
} /**
* Checks the current document extension
*
* @returns {boolean} {@code true} if the current extension is not prohibited
*/
function suffixCheck () {//检查当前文档扩展名(不为'xml', 'pdf')
var prohibitedTypes = ['xml', 'pdf']
var currentUrl = window.location.href
var currentRegex
for (let i = ; i < prohibitedTypes.length; i++) {
currentRegex = new RegExp(`\\.${prohibitedTypes[i]}$`)
if (currentRegex.test(currentUrl)) {
return false
}
}
return true
} /**
* Checks the documentElement of the current document
*
* @returns {boolean} {@code true} if the documentElement is an html node or if none exists
*/
function documentElementCheck () {
var documentElement = document.documentElement.nodeName //返回文档的根节点是否为html或不存在
if (documentElement) {
return documentElement.toLowerCase() === 'html'
}
return true
} /**
* Checks if the current domain is blacklisted
*
* @returns {boolean} {@code true} if the current domain is blacklisted
*/
function blacklistedDomainCheck () {//黑名单
var blacklistedDomains = [
'uscourts.gov',
'dropbox.com',
'webbyawards.com',
'cdn.shopify.com/s/javascripts/tricorder/xtld-read-only-frame.html',
'adyen.com',
'gravityforms.com',
'harbourair.com',
'ani.gamer.com.tw',
'blueskybooking.com',
]
var currentUrl = window.location.href
var currentRegex
for (let i = ; i < blacklistedDomains.length; i++) {
const blacklistedDomain = blacklistedDomains[i].replace('.', '\\.')
currentRegex = new RegExp(`(?:https?:\\/\\/)(?:(?!${blacklistedDomain}).)*$`)
if (!currentRegex.test(currentUrl)) {
return true
}
}
return false
} /**
* Redirects the current page to a phishing information page
*/
function redirectToPhishingWarning () {
console.log('MetaMask - routing to Phishing Warning component')
const extensionURL = extension.runtime.getURL('phishing.html')
window.location.href = extensionURL
}

metamask源码学习-contentscript.js的更多相关文章

  1. metamask源码学习-inpage.js

    The most confusing part about porting MetaMask to a new platform is the way we provide the Web3 API ...

  2. metamask源码学习-background.js

    这个就是浏览器后台所进行操作的地方了,它就是页面也区块链进行交互的中间部分. metamask-background描述了为web扩展单例的文件app/scripts/background.js.该上 ...

  3. metamask源码学习-ui/index.js

    The UI-即上图左下角metamask-ui部分,即其图形化界面 The MetaMask UI is essentially just a website that can be configu ...

  4. metamask源码学习导论

    ()MetaMask Browser Extension https://github.com/MetaMask/metamask-extension 这就是整个metamask的源码所在之处,好好看 ...

  5. metamask源码学习-controller-transaction

    ()metamask-extension/app/scripts/controllers/transactions Transaction Controller is an aggregate of ...

  6. metamask源码学习-metamask-controller.js

    The MetaMask Controller——The central metamask controller. Aggregates other controllers and exports a ...

  7. metamask源码学习-controllers-network

    https://github.com/MetaMask/metamask-extension/tree/master/app/scripts/controllers/network metamask- ...

  8. 【 js 基础 】【 源码学习 】源码设计 (持续更新)

    学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析第二部分:undersc ...

  9. Underscore.js 源码学习笔记(下)

    上接 Underscore.js 源码学习笔记(上) === 756 行开始 函数部分. var executeBound = function(sourceFunc, boundFunc, cont ...

随机推荐

  1. MVC架构介绍-事件机制

    实例产品基于asp.net mvc 5.0框架,源码下载地址:http://www.jinhusns.com/Products/Download 在.net框架中,事件是将事件发送者(触发事件的对象) ...

  2. 秒懂AOP

    AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓存.对象池管理等.AOP 实现的关键就在于 ...

  3. Java 10新特性

    ref:http://www.cocoachina.com/industry/20180309/22520.html https://www.oschina.net/news/94402/java-1 ...

  4. css3火焰文字样式代码

    css样式: <style type="text/css"> body{background:#000;} *{margin:0;padding:0;transitio ...

  5. 1788:Pell数列

    1788:Pell数列 查看 提交 统计 提问 总时间限制:  3000ms 内存限制:  65536kB 描述 Pell数列a1, a2, a3, ...的定义是这样的,a1 = 1, a2 = 2 ...

  6. nativefier(一行代码将任意网页转化为桌面应用)

    刚刚在看前端九部的手册的时候,发现一个之前没有用过的骚东西,看上去还挺好用,我这个好奇心瞬间就窜的老高了,赶紧试一试,看看这个东西有没有必要收入我的胯下 结果实验完了之后, 必须必须要强行安利给你们 ...

  7. Salesforce的报表和仪表板

    报表是现代企业中最常用到的功能之一.Salesforce中提供了强大的报表和仪表板功能. 报表和仪表板简介 报表是一组数据展示,用户可以自定义规则,只有符合相应规则的数据才会显示出来. Salesfo ...

  8. 安卓开发_浅谈TimePicker(时间选择器)

    TimePicker也继承自FrameLayout类.时间选择控件向用户显示一天中的时间(可以为24小时,也可以为AM/PM制),并允许用户进行选择.如果要捕获用户修改时间数据的事件,便需要为Time ...

  9. 《Inside C#》笔记(六) 属性、数组、索引器

    一 属性 a) 属性可用于隐藏类的内部成员,对外提供可控的存取接口.属性相当于有些语言的getter.setter方法,只是使用起来更加方便一点,而且查看对应的IL码可以看到,属性的本质也确实是方法. ...

  10. [软件逆向]实战Mac系统下的软件分析+Mac QQ和微信的防撤回

      0x00  一点废话 最近因为Mac软件收费的比较多,所以买了几款正版软件,但是有的软件卖的有点贵,买了感觉不值,不买吧,又觉得不方便,用别人的吧,又怕不安全.于是我就买了正版的Hopper Di ...