chrome扩展程序开发

  前几天某懒产品经理提出了一个懒需求,大概是这样的:想从我们公司的cms后台点击进入另一个第三方后台的同时,将cms后台的一些数据自动填充到那个第三方后台的一些表单中。也就是说,以前他们需要把数据、文字一个一个拷贝粘贴到第三方后台,现在他们不干了,想让我帮他们实现这个自动“搬迁”数据的过程。这该怎么办呢?那个第三方后台也不是我能控制的了的啊,这时就要使用chrome扩展程序这个神器了,它可以实现浏览器上多个页面之间的数据传递呢!

  关于chrome扩展程序的开发,网上有一个比较完整的中文翻译的开发文档——http://open.chrome.360.cn/extension_dev/overview.html,有兴趣可以翻阅一下。chrome扩展程序能做的事情还是挺多挺好玩的,不过这篇博文我只是想以一个很简单的例子来讲解一下它的基本开发过程,从代码编写到加载运行,最后再说明一下整个扩展程序的运行原理以及调试。这个简单例子是这样的:将一些QQ邮箱的账号密码写在文件中,然后进入QQ邮箱登陆界面的时候带入一个id参数,chrome扩展程序根据这个id去读取QQ账号密码自动填充到登录表单中,无需我们手动输入,然后这个扩展程序还要能记录邮箱的登录情况。废话不多说,这就开始了!

  首先创建一个空文件夹qqmail用于存放这个扩展程序所有的代码文件,然后写一个配置文件manifest.json,配置文件各个参数配置和意义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "name": "QQ Mail Extention",//扩展程序名称
    "version": "1.0",//版本
    "manifest_version": 2,//一定要为2,否则会报错
    "description": "This Extention can help you manifest_versionto login QQ Mail faster!",//扩展程序描述
    "browser_action": {
        "default_icon": "logo.png",//默认图标
        "default_popup": "popup.html"//点击图标时弹出的页面
    },
    "background": {
        "persistent": true,
        "scripts": ["background.js"]//扩展程序背景页脚本
    },
    "content_scripts": [{
        "all_frames": true,//是否运行在页面所有frame中,设置为true时扩展程序在iframe中也能起作用
        "matches": ["*://*/*"],//定义那些页面需要注入content script脚本
        "js": ["jq.1.8.2_dev.js","content_scripts.js"]//需要向页面注入的content script脚本
    }],
    "permissions": [//扩展程序权限
        "tabs", "webNavigation"
    ]
}  

说明(browser_action和page_action只能选其中一个):

browser_action:扩展程序图标在chrome地址栏之外,chrome主工具栏右侧。定义处理事件适用于所有页面。
page_action:扩展程序图标在chrome地址栏之内右侧。定义需要处理的页面的事件,并不是适用于所有页面的。
扩展程序背景页脚本:在以上配置中为background.js,是一个独立于所有页面的脚本,常用于管理一些任务或状态,可作为不同页面之间传递数据的桥梁。它会在扩展程序的整个生命周期都存在,同时,在同一时间只有一个实例处于活动状态。

  接下来,编写扩展程序弹窗页面popup.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html>
    <head>
        <title>QQ邮箱快捷登录插件</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
            table{border-collapse:collapse}
            table td{padding:5px}
        </style>
    </head>
    <body style="height:150px;width:200px">
        <h3>当前QQ邮箱信息</h3>
        <div id="info"></div>
    </body>
    <script src="jq.1.8.2_dev.js"></script>
    <script src="popup.js"></script>
</html>

  popup.html中引入了两个js文件,一个是jQuery文件,另一个则是用于刷新弹窗内容的popup.js,不过,这里要先介绍一下扩展程序背景页脚本background.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
var qqmail = new function() {
    var I = this, info = {'hasInfo': 0},//当前邮箱信息
    accounts = {//所有QQ邮箱账号配置
        1: {
            'username': '2******04@qq.com',//账号
            'password': '1242444',//密码
            'password2': '341222'//独立密码
        },
        2: {
            'username': '8834839@sina.com',
            'password': '1234245',
            'password2': '2141211'
        },
        3: {
            'username': '8110110109@qq.com',
            'password': '111111',
            'password2': '222222'
        }
    };
     
    I.setInfo = function(id) {//设置当前邮箱信息
        if(accounts[id]) {
            info = accounts[id];
            info.hasInfo = 1;
            I.setStatus(0);
        }
    };
     
    I.setStatus = function(i) {//设置当前邮箱状态
        var status = {
            0: '未登录',
            1: '还需输入独立密码',
            2: '已登录',
            3: '已退出登录'
        };
        if(status[i]) info.status = status[i];
    };
     
    I.getInfo = function() {//获取当前邮箱信息
        return info;
    };
};
 
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {//监听来自content_scripts.js的消息并作出响应
    var f = qqmail[request.cmd];
    if(typeof f === 'function') {
        var ret = f(request.par);
        if(typeof sendResponse == 'function') {
            sendResponse(ret);
        }
    }
});

这个文件主要记录了一些QQ邮箱的账号、密码和独立密码,并维护当前登录邮箱的登录状态,使用chrome.runtime.onMessage.addListener()监听来自content script脚本的请求。

  好了,现在回过头来看看popup.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(function() {
    var fn = function() {
        var info = chrome.extension.getBackgroundPage().qqmail.getInfo(), s = '';
        if(info.hasInfo) {
            var cfg = {
                'username': '邮箱',
                'password': '密码',
                'password2': '独立密码',
                'status': '登录状态'
            };
            s = '<table border="1">';
            $.each(info, function(k, v) {
                if(cfg[k]) s += '<tr><td>' + cfg[k] + '</td><td>' + v + '</td></tr>';
            });
            s += '</table>';
        } else {
            s = '尚无任何QQ邮箱信息......';
        }
        $('#info').html(s);
    };
    fn();
})();

这个js文件主要是通过chrome.extension.getBackgroundPage()与扩展程序背景页脚本background.js取得联系,并调用其中的qqmail.getInfo()取得当前登录邮箱的信息,刷新弹窗页面popup.html的内容。

  最后就是content script文件content_scripts.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
(function() {
    var init = function() {
        if(location.href.indexOf('https://mail.qq.com/?id=') >= 0) {//QQ邮箱登录主页面
            var id = location.href.split('=')[1];
            send('setInfo', id);//初始化当前邮箱信息
        } else if(location.href.indexOf('https://xui.ptlogin2.qq.com/cgi-bin/xlogin') >= 0) {//QQ邮箱登录表单iframe
            send('getInfo', function(ret) {//获取当前邮箱信息填充登录表单
                getObj('[name="u"]', function(o) {
                    o.val(ret.username);
                    $('[name="p"]').val(ret.password);
                });
            });
        } else if(location.href.indexOf('https://mail.qq.com/cgi-bin/loginpage?autologin') >= 0) {//填写QQ邮箱独立密码
            send('setStatus', 1);//设置邮箱状态
            send('getInfo', function(ret) {//获取当前邮箱信息填充登录表单
                getObj('[name="pp"]', function(o) {
                    o.val(ret.password2);
                });
            });
        } else if(location.href.indexOf('https://mail.qq.com/cgi-bin/frame_html') >= 0) {//QQ邮箱成功登录
            send('setStatus', 2);//设置邮箱状态
        } else if(location.href.indexOf('https://mail.qq.com/cgi-bin/loginpage?t=wx_logout') >= 0) {//QQ邮箱退出登录
            send('setStatus', 3);//设置邮箱状态
        }
    },
    getObj = function(s, fn, tm, tmout) {//控件加载完成才获取,防止控件尚未加载完成而导致获取不到对象
        tm = tm || 100;
        var t = setInterval(function() {
            var o = $(s);
            if(o[0]) {
                clearInterval(t);
                if(tmout && tmout > 0) {
                    setTimeout(function() {
                        fn(o);
                    }, tmout);
                } else {
                    fn(o);
                }
            }
        }, tm);
    };
    send = function(cmd, par, cb){//给background.js发消息
        if(typeof par == 'function'){
            cb = par;
            par = '';
        }
        chrome.runtime.sendMessage({cmd:cmd, par:par}, cb);
    };
    $(init);
})();  

这个脚本是运行在chrome每一个页面的,主要工作就是判断当前页面是哪个页面并作出相应动作,使用chrome.runtime.sendMessage()从背景页脚本请求数据、发送邮箱登陆状态给背景页。

  好了,到这里这个简单的chrome扩展程序便开发完成了,目录的所有文件如下:

代码编写完毕之后便可以开始加载这个扩展程序来运行了,在chrome上的操作示意图如下:

点击“加载已解压的扩展文件”选中刚刚的目录qqmail,加载之后信息如下:

 

至此,这个简单的chrome扩展程序已经开始运行,接下来操作一下邮箱登录过程,并逐步说明这个扩展程序的运行过程与原理。

  加载之后点击扩展程序图标,弹窗页面脚本popup.js便会请求背景页脚本background.js,获取邮箱信息,刷新弹窗页面内容,由于此时还没有进入QQ邮箱登录页面并传id参数,所以background.js中还没有当前登录邮箱的任何信息,所以弹窗页面是这样的:

接下来打开QQ邮箱登录页面并传id,比如这样:https://mail.qq.com/?id=1,进入这个页面之后content script脚本content_scripts.js通过url匹配找到要执行的动作,即:取得参数id的值,并调用背景页脚本background.js的qqmail.setInfo()函数,取得当前要登录邮箱的信息并保存在info对象中。这时,由于QQ邮箱登录表单位于登录页面中的iframe中,扩展程序的content script脚本content_scripts.js也运行其中,通过脚本中第二个url匹配,发送消息给背景页脚本background.js,调用其中的qqmail.getInfo()函数取得info对象中的账号和密码,自动填充到登录表单中,这样就无需我们手动输入了。此时再去点击扩展程序图标,弹窗脚本popup.js再次请求背景页脚本background.js中的qqmail.getInfo()函数获取当前登录QQ邮箱信息,刷新弹窗页面,效果是这样的:

接下来,点击登录,进入独立密码填写页面,content script脚本content_scripts.js通过与背景页脚本background.js通信,做两个动作:首先调用qqmail.setStatus()函数设置邮箱登录状态,然后调用qqmail.getInfo()函数取得独立密码并自动填充表单。此时再点击扩展程序图标,popup.js重新请求背景页脚本刷新弹窗页面如下:

 

同样的,登录成功、退出登录时,content script脚本content_scripts.js也都会发消息给背景页脚本background.js去修改当前登录邮箱的登录状态,即更新info对象的值,点击扩展图标时弹窗页面脚本popup.js也会请求背景页脚本background.js获取当前登录邮箱状态,刷新弹窗页面。

  好了,现在大概了解chrome扩展程序大概的运作原理了吧。整个扩展程序主要涉及三个js脚本文件:

1. 弹窗页面脚本:每点击一次扩展程序图标则运行一次,主要负责通过与背景页脚本通信,请求数据,刷新弹窗内容。

2. content script脚本:运行于chrome中每个打开的页面,可与背景页脚本通信,可操作当前页面。

3. 背景页脚本:独立于chrome任何页面,存在于扩展程序整个生命周期,一般用于保存一些数据状态,充当不同页面之间数据交流的桥梁。

  最后,简单说一下chrome扩展程序开发过程中的调试方法。弹窗页面脚本的调试方法:右键扩展图标,点击“审查弹出内容”即可弹出调试窗口,对弹窗页面进行抓包。content script脚本的调试方法则与一般调试相同,直接按“F12”按钮即可。而背景页脚本,由于没有具体页面,故无法直接调试,可通过弹窗页面脚本和 content script脚本使用一定方法间接调试,因为这两个脚本都可获取到背景页脚本中的数据啊。修改了扩展程序代码之后,保存,然后直接在chrome扩展程序管理页面点击“重新加载”即可生效!

  其实chrome扩展程序能做的事情还真挺多的,本文只是提供了一个很简单的例子来说明它的开发过程与运行过程而已。一般来说,我们可以通过在某个第三方网页的url末尾加上我们自定义的参数,由我们的chrome扩展程序的content script脚本根据这个参数去请求我们自己的接口,获取数据来填充这个网页的表单,或是做一些其他的操作来达到我们的目的,也可以在content script脚本中定义某个页面的某个按钮的点击事件,在事件响应函数中就可以做我们想做的事情就是了,当然了,操作页面上的内容之前,首先要先研究一下这个页面的html代码,不然你怎么知道去操作哪些控件呢是吧。

  本文到此结束,所述内容如有不妥,敬请谅解,欢迎指教,哈哈!

 

posted @   疯一样的狼人  阅读(4530)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示