如何编写一个Chrome扩展程序?
最近迫切地感受到做事情不能拖,后果比如水果不吃放到坏,等到想起要交作业时发现已经过了DDL,放在to do list里的事情很久没做直到失效或错过了机会而后悔。
编写和发布扩展程序其实已经是好多天以前的事情了,想一想不能再拖了,于是有了这篇文章。
起因
淘宝的登录策略变成了默认使用扫码登录,想要切换成密码登录就需要多点击一下,这是很恼人的一件事。可能一些人觉得扫码登录可能会更快,但实际上对于我们这些习惯于保存密码的用户来说,登录是只需要点击一下的事情,无需输入密码。所以,本来点击一下就登录的事情,变成了要点两下,点击的位置还不一样,这就让我很烦。
因此,我想用写脚本的方式来解决这一问题。
思路
首先想到的是使用Tampermonkey这个扩展程序来加载用户脚本。Tampermonkey允许用户编写js代码,来操作网页上的元素,我只需要写好代码,让它加载即可。
事实上我也用它实现了功能(代码编写细节在下面会讲),但如果想把它推荐给其他人,操作未免有些麻烦。又考虑到Tampermonkey对资源占用也比较多,因此我决定将我的脚本改成一个扩展程序。
因此,现在的任务主要有两个,一是分析login.taobao.com页面,写出js代码;二是了解Chrome扩展程序的编写方法。
分析页面
观察淘宝的登录页面,我们很容易知道,显示的登录策略是由一个id为J_LoginBox
的div的class控制的。module-quick
表示二维码登录,module-static
表示账号密码登录,而在二维码加载完成之前,它的值为loading
。
进一步观察,发现有一个script定义了window.loginConfig
变量,里面有个shownQRCode
的布尔类型,表示“是否自动显示二维码登录”。
因此,我们的任务就是把shownQRCode
设置为false,并把class中相应的值设置成module-static
。
于是,我们很容易写出这样的代码。
function fucktaobao()
{
var tbclass=document.getElementById("J_LoginBox").className;
if (tbclass.search(/module-quick/)!=-1)
{
document.getElementById("J_LoginBox").className=tbclass.replace(/module-quick/, "module-static");
}
else
{
setTimeout(fucktaobao, 100);
}
}
var regexp = /login\.taobao\.com\//;
var match = regexp.exec(location.href);
if (match !== null)
{
//window.loginConfig.enableQRCode=false;
window.loginConfig.shownQRCode=false;
document.getElementById("J_LoginBox").className=document.getElementById("J_LoginBox").className.replace(/loading/, "module-static");
fucktaobao();
}
编写扩展
想学习扩展程序编写,应该怎么办?
首先想到的是看官方文档,如果你觉得太花时间,还可以看360翻译的中文文档(还挺良心的)。但是仔细想一想,我只是要跑一段js,为什么要看这么多东西呢?
于是我想到找一个扩展程序的代码,照着改一改,应该就可以了。
于是我找了一个最简单的扩展程序:这篇文章中提到的Back to Backspace,用于恢复使用退格键作为返回功能的快捷键。下载crx文件后进行zip解压就可以得到代码,而这个扩展也在GitHub上开源了代码,所以直接下载即可。
由于Chrome扩展程序所有的设置项都在manifest.json
文件中,因此我们主要需要修改这个文件,它描述了扩展信息以及需要用到的js文件等等信息。而现在我们要做的,就是在这个文件中指定要执行的js文件。
照葫芦画瓢发现需要加载的代码文件名以及匹配的网页地址都在content_scripts
字段中,修改它就好了。
接着在chrome://extensions/中,勾选“开发者模式”,点击“加载已解压的扩展程序”,选中扩展程序所在文件夹即可加载我们的扩展程序。
一个严重的问题
当我一切都做完后,程序并不能正常工作,打印log之后发现,程序找不到window.loginConfig
变量。这就奇了怪了。在stackoverflow上一查才知道,是因为Chrome为了安全,让扩展程序无法访问window变量。但是可以通过js注入的方法变相实现访问window变量。具体的做法是,在manifest.json
文件中将js文件列入web_accessible_resources
,并在content_scripts
中指定的js文件中,获取需注入的js文件地址,之后创建一个script标签指定src为那个地址。
而这一切做完后,扩展程序就能正常工作了。
如果你没有看懂,可以访问文末给的链接,看看代码就会懂了。
发布扩展
进入谷歌开发者信息中心进行发布即可。不过要想发布扩展程序,需要先给谷歌交5美元才行。
现在问题来了,想交这5刀,可不是那么容易,因为它并不支持支付宝、微信甚至银联、PayPal。还好我有以前在全球付办的一张虚拟信用卡,在付款时选择地区为香港,随便填个香港的地址即可。
付款时谷歌会先扣1刀测试账户是否可用(因为开通了Google Wallet),之后会扣除成为开发者所需的5刀,再之后会将之前扣除的1刀进行冲正。
虽然5刀并不是很多(确实不多了),但是还是很不爽,这5刀就被谷歌私吞了。而Steam Greenlight Submission Fee就明确说了这100刀(国区250块)将会用于慈善。
不完善的地方
我用Tampermonkey时,在里面添加用户脚本,运行起来不会有任何问题。但是我做成扩展程序之后,页面打开之后过几秒登录框就会闪一下二维码登录再变回来。虽然对于保存密码的用户来说,这个问题几乎不会有任何影响,但是遗留一个问题总是让人不太爽。
仔细思考之后,感觉应该是js脚本注入位置不同导致执行时间不同,从而影响执行结果。但是我试了好多js注入位置,都不能实现理想的效果,只好作罢。等以后有机会更多地了解浏览器原理之后再来做吧!