• 初试Chrome扩展开发


      前阵子没事的时候尝试做了个chrome扩展,主要功能就是用来检测那个微软的邮箱outlook web access的基础版的新邮件的。因为公司现在用的这个邮箱可是这个破邮箱竟然即使有个客户端也不给邮箱提醒功能,估计是硬要别人买个高级版的。

      一直刷页面看新邮件麻烦啊,所以起初只是想着找个chrome扩展来刷页面,很容易google到一个刷新工具用着感觉不错,但是用了会发现即使刷新了我也要切到那个tab页才能看到新邮件啊,还是很麻烦那,最终决定还是自己diy下吧。

      废话到此开始讲内容吧,chrome扩展的基本开发方式什么的,在 google的 扩展程序开发人员必读 上都有  这边主要就写下我的扩展程序的制作过程吧。

      首先建立manifest.json文件,感觉就等于这个扩展的配置文件

    {
        "name": "OuterLook Checker",                    //名称
        "version": "1.4",                               //版本            
        "icons": { "16": "icons/new.png",
                   "32": "icons/no_new.png",
                   "48": "icons/checkIng.png" },        //图标
        "description": "OuterLook Checker by Leif",     //描述      
        "background_page": "background.html",           //后台运行页面
        "browser_action": {
            "default_title": "OuterLook Checker",       //标题
            "popup": "popup.html",                      //点击打开的页面
            "default_icon": "icons/no_new.png"          //默认图标
        },
        "options_page": "options.html",                 //选项页面
        "permissions": [
            "http://red001.mail.microsoftonline.com/*",
            "https://red001.mail.microsoftonline.com/*",
            "tabs"
        ],                                              //页面过滤这边我只要在邮箱页面运行后台的js
        "content_scripts": [
    		{
    			"matches": [https://red001.mail.microsoftonline.com/*], 
                             //js脚本添加页面过滤 
    			"js": ["content.js"],      //页面添加的js脚本 
    			"run_at":"document_start"  //js脚本启动时间
     		}
    	]
    }
    
    

      然后就是设置页面 options.html ,这边现在只是用来设置下用户名密码而已。

    <html>
    <head>
      <title>Options for the OuterLook Checker extension</title>
    </head>
    <body>
    <table width="500px;" style="border: thin solid #6699FF; margin: auto; padding:10px;" cellspacing="0" cellpadding="0">
    <tr>
      <td colspan="2">
        <h2>User Set</h2>
      </td>
    </tr>
    <tr>
      <td>
         User Name:
      </td>
      <td>
        <input type="text" id="txtName" maxlength="50" />
      </td>
    </tr>
    <tr>
      <td>
        Password:
      </td>
      <td>
        <input type="password" id="txtPassword" maxlength="50" />
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <input type="button" id="btnSave" value="Save" onclick="saveUser();" />
      </td>
    </tr>
    </table>
    <script type="text/javascript">
           function saveUser() {  //用localStorage保存用户名密码并重置下 
            localStorage["OWAusername"] = txtName.value;
            localStorage["OWAPsssward"] = txtPassword.value;
            localStorage["looptime"] = 0;
            window.close();
        }
            window.onload = function() { //读取保存的用户名密码 
            var name = localStorage["OWAusername"]
            var password = localStorage["OWAPsssward"] 
            if (name != null) {
                txtName.value = name;
            }
            
            if (password != null) {
                txtPassword.value = password;
            }
            
            
        };
    </script>
    </body>
    </html>

      接着是单击显示页面,这个页面实际上大部分代码是chrome扩展 ChromeReload

    <body onload="restoreOptions()" style="background-color:white;">
    <div style="10pc;color:black;font-family:sans-serif;font-size:small">
        Check mail every:
        <form name="reload_options">
        	<!-- Poor man's menu emulation.  TODO: highlight when mouse is over -->
        	<!-- XXX Replace the hard-coded indices -->
        	<div style="color:black" width="100%" onclick="document.reload_options.reloadOption[0].checked = true;rentun false; ">
        	    <input type="radio" name="reloadOption" value="0" checked="checked">Never</input>
        	</div>
            <div style="color:black" width="100%" onclick="document.reload_options.reloadOption[1].checked = true;rentun false;">
        	    <input type="radio" name="reloadOption" value="5000">5 seconds</input>
        	</div>
            <div style="color:black" width="100%" onclick="document.reload_options.reloadOption[2].checked = true;rentun false;">
        	    <input type="radio" name="reloadOption" value="15000">15 seconds</input>
        	</div>
            <div style="color:black" width="100%" onclick="document.reload_options.reloadOption[3].checked = true;rentun false;">
        	    <input type="radio" name="reloadOption" value="30000">30 seconds</input>
        	</div>
            <div style="color:black" width="100%" onclick="document.reload_options.reloadOption[4].checked = true;rentun false;">
        	    <input type="radio" name="reloadOption" value="60000">1 minute</input>
        	</div>
            <div style="color:black" width="100%" onclick="document.reload_options.reloadOption[5].checked = true; rentun false;">
        	    <input type="radio" name="reloadOption" value="120000">2 minutes</input>
        	</div>
            <div style="color:black" width="100%" onclick="document.reload_options.reloadOption[6].checked = true; rentun false;">
        	    <input type="radio" name="reloadOption" value="300000">5 minutes</input> 
        	</div>
            <div style="color:black" width="100%" onclick="document.reload_options.reloadOption[7].checked = true; rentun false;">
        	    <input type="radio" name="reloadOption" value="900000">15 minutes</input> 
        	</div>
            <div style="color:black" width="100%" onclick="document.reload_options.reloadOption[8].checked = true; rentun false;">
        	    <input type="radio" name="reloadOption" value="1800000">30 minutes</input>
        	</div>
        	<div style="color:black" width="100%" onclick="document.reload_options.reloadOption[8].checked = true; rentun false;">
        	    <input type="radio" name="reloadOption" value="3600000">1 hour</input>
        	</div>
        	<div style="color:black" width="100%" onclick="document.reload_options.reloadOption[8].checked = true; rentun false;">
        	    <input type="radio" name="reloadOption" value="7200000">2 hours</input>
        	</div>
            
            <input type="submit" value="Set" onclick="setReloader();"/>
            <input type="submit" value="DefaultTime Set" onclick="setAsDefault(); return false;"/>
        </form>
    </div>
    <script>
        function restoreOptions() {
            var hasOpened = false;
            var needOpened = true;
           //判断如果未打开邮箱页面即自己打开一个(这边传用户名密码没加密,还没有发现一个好的方法来实现这边的加密)
            chrome.windows.getCurrent(function(wnd) {
                chrome.tabs.getAllInWindow(wnd.id, function(tabs) {
                    for (var i = 0; i < tabs.length; i++) {
                        hasOpened = tabs[i].url.indexOf("red001.mail.microsoftonline.com") > -1;
                        if (hasOpened) {
                            needOpened = false;
                        }
                    }
                    if (needOpened) {
                        var name = localStorage["OWAusername"];
    
                        var password = localStorage["OWAPsssward"];
                        chrome.tabs.create({ 'url': 'https://red001.mail.microsoftonline.com/owa/auth/logon.aspx?url=https://red001.mail.microsoftonline.com/owa/&reason=0&name=' + name + '&password=' + password });
                        window.close();
                    }
                });
            });
    
            var port = chrome.extension.connect({ name: "findReloadTime" });
            port.onMessage.addListener(recvData);
            port.postMessage({ msg: 'getReloadTime' });
        }
    
        function recvData(data){
            if (data.is_random) {
                document.reload_options.reloadOption[9].checked = true;        
            } else {
                var reloadTime = data.ms_between_load;
                for( i = 0; i < document.reload_options.reloadOption.length; i++ ) {
                    if(document.reload_options.reloadOption[i].value == reloadTime) {
                        document.reload_options.reloadOption[i].checked = true;
                        return;
                    }
                }
             }
        }
    
    
        function setReloader() {
            var option = 0;
            var isRandom = false;
            // Walk thru the radios
            for( i = 0; i < document.reload_options.reloadOption.length; i++ ) {
                if( document.reload_options.reloadOption[i].checked == true ) {
                    if ('rand' == document.reload_options.reloadOption[i].value) {
                        option = Math.floor(Math.random()*1800000);
                        isRandom = true;
                    } else {
                        option = document.reload_options.reloadOption[i].value;                
                    } 
                    break;
                }
            }       
            
            var views = chrome.extension.getViews();
            for (var i in views) {
                if (views[i].doReloader) {                
                    views[i].doReloader(option, isRandom);
                }
            }
            window.close();
            return true;  // We use this function in onSubmit; probably not necessary
        }
    
        function setAsDefault() {
            var option = 0;
            var isRandom = false;
            // Walk thru the radios
            for (i = 0; i < document.reload_options.reloadOption.length; i++) {
                if (document.reload_options.reloadOption[i].checked == true) {
                    if ('rand' == document.reload_options.reloadOption[i].value) {
                        option = Math.floor(Math.random() * 1800000);
                        isRandom = true;
                    } else {
                        option = document.reload_options.reloadOption[i].value;
                    }
                    break;
                }
            }
    
            localStorage["DefualtTime"] = option;
            var views = chrome.extension.getViews();
            for (var i in views) {
                if (views[i].doReloader) {
                    views[i].doReloader(option, isRandom);
                }
            }
            window.close();
            return true;
        }
    </script>
    </body>

      content.js这段脚本会嵌入指定的页面中即在manifest.json中指定的,所以对于安全性会差点,这里用来自动登录和新邮件提醒的。

    window.addEventListener("load", function() {
        var usernameView = document.getElementById("username");  
        if (usernameView) {  //判断是否需登录
            var PasswordView = document.getElementById("password");
    
            var name = getArgs("name");
            if (name != null) {
                usernameView.value = name;
                var password = getArgs("password");
                if (password != null) {
                    PasswordView.value = password;
                    document.cookie = "logondata= 1 &" + name + "; expires=1000000000";
                    document.forms[0].submit(); //logonForm
                }
            }    
        }
        else {
            var result = "0";
            var classElements = [], allElements = document.getElementsByTagName("td");
            for (var i = 0; i < allElements.length; i++) {         //在用户在收件箱状态时 判断是否有新邮件(避免草稿箱的误报 )        if ((allElements[i].className == "fld sl bld" || allElements[i].className == "fld bld") && (allElements[i].childNodes[0].title == "收件箱" || allElements[i].childNodes[0].title == "Inbox")) {
                    result = "1";
                }
            }
            chrome.extension.sendRequest({
                emails: result
            });
        }
    });
    
    function getArgs(strParame) {
        var args = new Object();
        var query = location.search.substring(1); // Get query string
        var pairs = query.split("&"); // Break at ampersand
        for (var i = 0; i < pairs.length; i++) {
            var pos = pairs[i].indexOf('='); // Look for "name=value"
            if (pos == -1) continue; // If not found, skip
            var argname = pairs[i].substring(0, pos); // Extract the name
            var value = pairs[i].substring(pos + 1); // Extract the value
            value = decodeURIComponent(value); // Decode it, if needed
            args[argname] = value; // Store as a property
        }
        return args[strParame]; // Return the object
    }
    

      最后就是background.html啦,主要用来接收和响应事件,自动刷新页面部分是ChromeReload的代码啦。

    <html>
    <head>
    
        <script type="text/javascript">
    
            var tabs = new Array();
            localStorage["looptime"] = "0";
            
            chrome.extension.onConnect.addListener(function(port) {
                if (port.name === 'findReloadTime') {
                    port.onMessage.addListener(function(data) {
                        if (data.msg === 'getReloadTime') {
                            chrome.tabs.getSelected(null, function(tab) {
                                var tabIsReloaderActive = tabs[tab.id] || false;
                                if (tabIsReloaderActive) {
                                    port.postMessage({ ms_between_load: tabs[tab.id].ms_between_load, is_random: tabs[tab.id].is_random });
                                }
                            });
                        }
                    });
                }            
            });
            chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {  //接收邮箱发来的信息处理 
                if (request["emails"] == 1) {
                    chrome.browserAction.setBadgeText({ text: "New" });
                    chrome.browserAction.setIcon({ path: "icons/new.png" });
                    
                    if (localStorage["emails"] != "checked") {
                        alert("New Email Received!");
                        localStorage["emails"] = "checked";                   
                        
                        if (localStorage["looptime"] != "0") {
                            doReloader("0", false);
    
                        }
                    }
                }
                else {              
                    if (localStorage["looptime"] == undefined || localStorage["looptime"] == "0") {
                        if (localStorage["DefualtTime"] != undefined) {
                            localStorage["looptime"] = localStorage["DefualtTime"];
                        }
                        else {
                            localStorage["looptime"] = "1800000";
                        }
    
                        chrome.browserAction.setBadgeText({ text: "" });
                        localStorage["emails"] = "";
                        chrome.browserAction.setIcon({ path: "icons/no_new.png" });
                        
                        doReloader(localStorage["looptime"], false);
                    }
                }
            });
    
            function doReloader(time, isRandom) {
                if (time > 0) {
                    chrome.tabs.getSelected(null, function(tab) {
    
                        if (tabs[tab.id] || false) {
                            // if there is already a reloader setup for this tab, cancel it
                            cancelReload(tab.id);
                        }
                        
                        if (tab.title == "收件箱 - Outlook Web Access 基本客户端" || tab.title == "Inbox - Outlook Web Access Light" || tab.title == "收件箱 - Outlook Web Access Light") {
                            tabs[tab.id] = new Array();
                            tabs[tab.id]['action_url'] = tab.url;
                            tabs[tab.id]['ms_between_load'] = time;
                            tabs[tab.id]['seconds_to_next_reload'] = time / 1000;
                            tabs[tab.id]['is_random'] = isRandom;
    
                            chrome.tabs.onUpdated.addListener(onUpdateListener);
    
                            chrome.browserAction.setIcon({ path: "icons/checkIng.png", tabId: tab.id });
                            localStorage["looptime"] = time;
                            // reload the page
                            // timers are set for the next reload (and a display timer) in the page load listener
                            doReload(tab.id);
                        }
                    });
    
                } else {
                    chrome.tabs.getSelected(null, function(tab) {
                        cancelReload(tab.id);
                    });
                }
            }
    
            function onUpdateListener(tabId, changeInfo) {
                // Hide the badge text
                chrome.browserAction.setBadgeText({ text: '', tabId: tabId });
    
                var tabIsReloaderActive = (tabs[tabId] || false) && (tabs[tabId].ms_between_load > 0 || false);
                if (tabIsReloaderActive) {
                    // can only get the URL infomation when the page is loading, not when it is complete
                    if (changeInfo['status'] === 'loading') {
                        // we want to cancel the reloader if they navigate away
                        var urlChanged = changeInfo['url'] || false;
                        if (urlChanged) {
                            // the URL has changed - presumably by navigation
                            // cancel the reloads
                            cancelReload(tabId);
                        } else {
                            // reset the icon (it is cleared when reloaded)
                        chrome.browserAction.setIcon({ path: "icons/checkIng.png", tabId: tabId }); // the icon is reset when the page is reloaded
    
    
                            // Cancel the timer display while the tab is reloading
                            cancelDisplayTimer(tabId);
    
                            // Cancel the reload time (in case the user manually reloaded the page)
                            if (tabs[tabId].reloadTimer || false) {
                                clearTimeout(tabs[tabId].reloadTimer);
                                tabs[tabId].reloadTimer = null;
                            }
                        }
                    } else if (changeInfo['status'] === 'complete') {
                        // page has just completed loading
    
                        // reset the icon (it is cleared when reloaded)
                    chrome.browserAction.setIcon({ path: "icons/checkIng.png", tabId: tabId }); // the icon is reset when the page is reloaded
    
                        // if we are using random timouts then we need to reset the time related variables here
                        if (tabs[tabId]['is_random']) {
                            var time = Math.floor(Math.random() * 1800000);
                            tabs[tabId].ms_between_load = time;
    
                        }
    
                        // reset the timer for the countdown
                        tabs[tabId].seconds_to_next_reload = tabs[tabId].ms_between_load / 1000;
    
    
    
                        // and set the correct countdown text
                        setBadgeText(tabId);
    
                        // set a timeout for the next reload
                        setupReloadTimer(tabId);
    
                        // make really sure this timeout is cancelled before we add a new one
                        cancelDisplayTimer(tabId);
    
                        // setup the reload countdown
                        tabs[tabId].displayTimer = window.setInterval(function(tab_id) {
                            tabs[tab_id].seconds_to_next_reload--;
                            setBadgeText(tab_id);
                        }, 1000, tabId);
                    }
                }
            }
    
            function setupReloadTimer(tabId) {
                // be sure to remove any reload timer before we add a new one
                if (tabs[tabId].reloadTimer || false) {
                    clearTimeout(tabs[tabId].reloadTimer);
                    tabs[tabId].reloadTimer = null;
                }
    
                // set the reload to occur in ms_between_load milliseconds time
                tabs[tabId].reloadTimer = window.setTimeout(function(tab_id) {
                    doReload(tab_id);
                }, tabs[tabId].ms_between_load, tabId);
            }
    
            function cancelDisplayTimer(tabId) {
                if (tabs[tabId].displayTimer || false) {
                    clearTimeout(tabs[tabId].displayTimer);
                    tabs[tabId].displayTimer = null;
                }
            }
    
            function setBadgeText(tab_id) {
                //chrome.browserAction.setBadgeText({text:'p1', tabId:tab_id});
    
                if (tabs[tab_id].seconds_to_next_reload < 0) {
                    // something is wrong! Don't display any text
                    chrome.browserAction.setBadgeText({ text: String(), tabId: tab_id });
                    // cancel the time which is calling this. It will get recreated if the page is auto-reloaded
                    cancelDisplayTimer(tab_id);
                } else {
                    var badgeText = String(tabs[tab_id].seconds_to_next_reload);
    
                    //var mins = Math.floor(tabs[tab_id].seconds_to_next_reload/60);
                    var secs = tabs[tab_id].seconds_to_next_reload % 60;
                    //if (secs < 10) {
                    //    secs = '0' + String(secs);
                    //}            
                    //badgeText= String(mins) + ':' + String(secs);
    
                    var mins = Math.floor((tabs[tab_id].seconds_to_next_reload / 60) % 60);
                    var hours = Math.floor((tabs[tab_id].seconds_to_next_reload / (60 * 60)) % 24);
                    var days = Math.floor((tabs[tab_id].seconds_to_next_reload / (60 * 60 * 24)));
    
                    // Format
                    // The banner fits about 4.5 characters (depending on the character's width)
                    if (days > 999) {
                        badgeText = 'long'; // it will take long...
                    } else if (days > 9) {
                        badgeText = String(days) + 'd';
                    } else if (days > 0) {
                        // The 'h' will not entirely fit on the banner all the time.  Live with it.
                        badgeText = String(days) + 'd' + String(hours) + 'h';
                    } else if (hours > 0) {
                        if (mins < 10) {
                            mins = '0' + String(mins);
                        }
                        // Blinking ':'
                        // Note: The banner uses a variable-width font; both strings have to have the same width
                        if (secs % 2) {
                            var blinker = ':';
                        } else {
                            var blinker = ' ';
                        }
                        badgeText = String(hours) + blinker + String(mins);
                    } else {
                        if (secs < 10) {
                            secs = '0' + String(secs);
                        }
                        badgeText = String(mins) + ':' + String(secs);
                    }
    
                    chrome.browserAction.setBadgeText({ text: badgeText, tabId: tab_id });
                }
            }
    
            function cancelReload(tab_id) {
                if (tabs[tab_id].reloadTimer || false) {
                    clearTimeout(tabs[tab_id].reloadTimer);
                    tabs[tab_id].reloadTimer = null;
                }
                if (tabs[tab_id].displayTimer || false) {
                    clearTimeout(tabs[tab_id].displayTimer);
                    tabs[tab_id].displayTimer = null;
                }
                tabs[tab_id].ms_between_load = 0;
                tabs[tab_id].seconds_to_next_reload = 0;
                chrome.browserAction.setIcon({ path: "icons/no_new.png", tabId: tab_id });
                chrome.browserAction.setBadgeText({ text: String(), tabId: tab_id });
                localStorage["looptime"] = "0";
    
            }
    
            function doReload(tab_id) {
    
                chrome.browserAction.setIcon({ path: "icons/checkIng.png", tabId: tab_id });
                chrome.browserAction.setBadgeText({ text: '', tabId: tab_id });
    
                // need to work out a way to make POST'ed pages reload
                chrome.tabs.update(tab_id, { url: tabs[tab_id].action_url });
    
                chrome.tabs.executeScript(tab_id, {code: 'window.location.reload()'});
    
            }        
    
        </script>
    
    </head>
    </html>
    

            基本上一个简单chrome的扩展也就上面几个文件而已,而且用chrome调试js还是很方便的,所以做过扩展还是很方便的,但是感觉中文的文档还是比较缺的,开始学的时候感觉资源不多啊,在网上找了几个开源的看了下才大概知道了怎么搞。实际上后来我发现要看别人扩展源码很简单啊,直接把那个控制程序下来来解压下就全有了….

           哎,第一次写个博客,加上一会东一个事情一会西一个事情,结果整整写了一上午啊,呵呵。我有空还得继续加强下我的扩展啊,下一步目标是学gmail check的邮件提醒方式。

  • 相关阅读:
    定点数的表示
    [收集]XMPP使用tls 和sasl登录
    socket函数
    [收集] SendMessage、PostMessage原理
    DLL中用malloc分配了一块内存,但是在exe程序中释放引发的错误:其原因可能是堆被损坏,这也说明 **.exe 中或它所加载的任何 DLL 中有 bug。
    关于在IWebBrowser中无法响应Ctrl+C等快捷键的解决方法
    Enum 操作
    程序员面对分歧和难题应当具备的态度【转】
    NDIS学习笔记一
    NDIS学习笔记二——(模拟丢包)
  • 原文地址:https://www.cnblogs.com/leif/p/1814461.html
Copyright © 2020-2023  润新知