看到亚马逊的Chrome插件亚马逊购物助手上线了,打开京东出现了,亚马逊相关商品的推荐广告。想想他们两家的竞争也是够猛的,在请求的资源中发现了requirejs
和underscore
等等,于是便想看看里面的代码。先从一些简单的地方慢慢开始:
简单地先来说一下基本的顺序:
下面是插件中的main.html
<html>
<head>
</head>
<body>
<script type="text/javascript" src="lib/bit/update-event-interceptor.js"></script>
<script type="text/javascript" src="lib/requirejs/require.js"></script>
<script type="text/javascript" src="lib/requirejs/requirejs-config.js"></script>
</body>
</html>
update-event-interceptor.js
看上去是给Chrome用的,这里就先忽略之
chrome.runtime.onInstalled.addListener(window.UpdateEventInterceptor.onInstalled);
接着便请求requirejs-config
,
require.config({
baseUrl: "native-src",
shim: {
underscore: {
exports: "_"
},
md5: {
exports: "md5"
}
}
});
require(["bit/ext/chromelike/main"], function() {});
里面引用了underscore
和md5
,然后请求了
native-src/bit/ext/chromelike/main
这是一个很长很长的文件。。
看了看的main.js确实是很长很长,也发现了几点:
说说第二点,发现了
var SIX_HOURS = 21600000;
和
var cc_suffix_map = {
'us' : '20',
'ca' : '20',
'uk' : '21',
'gb' : '21',
'fr' : '21',
'de' : '21',
'es' : '21',
'it' : '21',
'jp' : '22',
'cn' : '23'
};
是没有被用到的。
首先迎面而来的是很长的一个HelperKlass
,定义了那样的一个函数
var HelperKlass = function() {
this.initialize.apply(this, arguments);
}
接着用underscore
扩展了原型。。。
_.extend(HelperKlass.prototype, {})
里面定义了这样一堆方法
这个多达500行的类居然不是在一个单独的文件里。。。其中各种用到了Promise
模式。
其中还有一个叫MessageHandler
的类来处理不同的Message,于是还有相对应的一个start
函数。而实际上我们需要关心的是chrome.extension.onConnect
事件监听器
Chrome的文档上有对于这个的解释
chrome.extension.onConnect.addListener(function(Port port) {...});
接收到本扩展进程的页面或content script发来的连接时触发。
对应的在Amazon中有下面的代码:
chrome.extension.onConnect.addListener(function(port) {
if (!port){
return;
}
Logger.log(port.name);
if (port.name === 'UBPAppsChromePanel') {
panelPort = port;
panelPort.onDisconnect.addListener(function() {
panelPort = false;
});
}
port.onMessage.addListener(function(message) {
Logger.log('Extension got message');
Logger.log(message);
MessageHandler.handleMessage(message, port);
});
});
在MessageHandler
中有这样的一个逻辑
case "Options_acceptTermsOfUse":
applicationState.setCurrentState("termsOfUsageAccepted");
storage.set({'options.acceptedTermsOfUse': true});
start();
break;
而start()
做的便是诸如termsOfUsageAccepted
这一类的事情。
最后函数的执行被绑定在
(function() {
...
var oneButtonApp = new OneButtonApp({
platformServiceBootstrapper: platformServiceBootstrapper,
sandboxDelegate: sandboxDelegate,
localeDelegate: Helper,
transportStyle: "postMessage",
transportStrategyOptions: {},
productCompassManager: productCompassManager,
platformCode: "chrome",
featureConfigs: featureConfigs,
tokenVendor: tokenVendor,
simpleStorageDelegate: $simpleStorage,
pinger: pinger,
guidManager: guidManager
});
oneButtonApp.start(function() {
Logger.log("All started");
});
window.oneButtonApp = oneButtonApp;
}());
这样的匿名函数里?
在OneButtonApp里用了Promise来说明了这个过程:
start: function(cb) {
return Promise.bind(this)
.then(function() {
return this._bootstrapPlatformService();
})
.then(function() {
return this._startPlatformService();
})
.then(function() {
return this._bootstrapProcessManager();
})
.then(function() {
return this._startProcessManager();
})
.then(function() {
return this._startInitialProcesses();
})
.then(function() {
return this._registerProductCompassSystemHandler();
})
.then(function() {
// In the interest of keeping things "simple",
// ProductCompassManager is managed independently
// for now. The intent is to convert it to
// a "process" at some point.
return this._wireProductCompassManager();
})
.then(function() {
return this._productCompassManager.cycle();
})
.catch(function (err) {
console.log(err);
})
.nodeify(cb);
},
可以让我们知道这个是怎么运作起来的。
围观我的Github Idea墙, 也许,你会遇到心仪的项目