Chrome擴展與應用(一)

Chrome擴展與應用(一)

一、創建並加載一個應用

1.創建一個文本文件,命名爲manifest.json

{
    "name": "我的第一個擴展",
    "version": "1.0",
    "description": "這是一個小的示例.",
    "browser_action": {
        "default_icon": "img/icon.png",
        "default_popup": "popup.html"
    },
    "manifest_version": 2
}

2.圖標放到img目錄中

3.編寫html

<!doctype html>
<html>

    <head>
        <title>彈出擴展</title>
    </head>
    <body>
        <img src="img/snow.png"/>
    </body>
</html>

4.加載應用(擴展)

image

二、manifest.json屬性

1、browser_action

2、page_action

3、background

4、content_scripts

  Manifest的content_scripts屬性值爲數組類型,數組的每個元素可以包含matches、exclude_matches、css、js、run_at、all_frames、include_globs和exclude_globs等屬性。其中matches屬性定義了哪些頁面會被注入腳本,exclude_matches則定義了哪些頁面不會被注入腳本,css和js對應要注入的樣式表和JavaScript,run_at定義了何時進行注入,all_frames定義腳本是否會注入到嵌入式框架中,include_globs和exclude_globs則是全局URL匹配,最終腳本是否會被注入由matches、exclude_matches、include_globs和exclude_globs的值共同決定。簡單的說,如果URL匹配mathces值的同時也匹配include_globs的值,會被注入;如果URL匹配exclude_matches的值或者匹配exclude_globs的值,則不會被注入。
  content_scripts中的腳本只是共享頁面的DOM1,而並不共享頁面內嵌JavaScript的命名空間。也就是說,如果當前頁面中的JavaScript有一個全局變量a,content_scripts中注入的腳本也可以有一個全局變量a,兩者不會相互干擾。當然你也無法通過content_scripts訪問到頁面本身內嵌JavaScript的變量和函數。

5、permissions

6、web_accessible_resources

7、options_page

三、跨域請求

  跨域指的是JavaScript通過XMLHttpRequest請求數據時,調用JavaScript的頁面所在的域和被請求頁面的域不一致。對於網站來說,瀏覽器出於安全考慮是不允許跨域。另外,對於域相同,但端口或協議不同時,瀏覽器也是禁止的。
{

“permissions”: [
://.xtwy.com/*”
]
}

示例:
manifest.json

{
    "name": "我的第一個擴展",
    "version": "1.0",
    "description": "這是一個小的示例.",
    "browser_action": {
        "default_icon": "img/icon.png",
        "default_popup": "popup.html"
    },"permissions": [
        "http://127.0.0.1:8020/*"
    ],
    "manifest_version": 2
}

popup.html

<!doctype html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>數據交互</title>
    </head>
    <body>
        <img src="img/snow.png" />
        <p id="txt"></p>
        <input type="button" id="btn" value="測試" />
        <script src="js/GetContext.js" type="text/javascript" charset="utf-8"></script>
    </body>
</html>

GetContext.js

function httpRequest(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.onreadystatechange = function() {
        if(xhr.readyState == 4) {
            callback(xhr.responseText);
        }
    }
    xhr.send();
}

document.querySelector("#btn").onclick = function() {
    console.log("調用前");
    httpRequest('http://127.0.0.1:8020/page/a.txt', function(txt) {
        alert(txt+"test");
        document.getElementById('txt').innerText = txt;
    });
    console.log("調用後"); 
};

四、常駐後臺

  有時我們希望擴展不僅在用戶主動發起時(如開啓特定頁面或點擊擴展圖標等)才運行,而是希望擴展自動運行並常駐後臺來實現一些特定的功能,比如實時提示未讀郵件數量、後臺播放音樂等等。
  Chrome允許擴展應用在後臺常駐一個頁面以實現這樣的功能。在一些典型的擴展中,UI頁面,如popup頁面或者options頁面,在需要更新一些狀態時,會向後臺頁面請求數據,而當後臺頁面檢測到狀態發生改變時,也會通知UI界面刷新。
  在Manifest中指定background域可以使擴展常駐後臺。background可以包含三種屬性,分別是scripts、page和persistent。如果指定了scripts屬性,則Chrome會在擴展啓動時自動創建一個包含所有指定腳本的頁面;如果指定了page屬性,則Chrome會將指定的HTML文件作爲後臺頁面運行。通常我們只需要使用scripts屬性即可,除非在後臺頁面中需要構建特殊的HTML——但一般情況下後臺頁面的HTML我們是看不到的。persistent屬性定義了常駐後臺的方式——當其值爲true時,表示擴展將一直在後臺運行,無論其是否正在工作;當其值爲false時,表示擴展在後臺按需運行,這就是Chrome後來提出的Event Page。Event Page可以有效減小擴展對內存的消耗,如非必要,請將persistent設置爲false。persistent的默認值爲true。

五、帶選項頁面的擴展

指定options_page屬性後,擴展圖標上的右鍵菜單會包含“選項”鏈接。
通過聲明unlimitedStorage權限,Chrome擴展和應用可以突破這一限制。
有很多網站提供天氣預報的API,比如OpenWeatherMap的API。

1.擴展代碼:

manifest.json

{
    "manifest_version": 2,
    "name": "天氣預報",
    "version": "1.0",
    "description": "查看未來兩週的天氣情況",
    "icons": {
        "16": "img/icon16.png",
        "48": "img/icon48.png",
        "128": "img/icon128.png"
    },
    "browser_action": {
        "default_icon": {
            "19": "img/icon19.png",
            "38": "img/icon38.png"
        },
        "default_title": "天氣預報",
        "default_popup": "popup.html"
    },
    "options_page": "options.html",
    "permissions": [
        "http://api.openweathermap.org/data/2.5/forecast?q=*"
    ]
}

weather.js

/**
 * ajax請求
 * @param {Object} url
 * @param {Object} callback
 */
function httpRequest(url, callback){
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            callback(xhr.responseText);
        }
    }
    xhr.send();
}
/**
 * 顯示天氣
 * @param {Object} result
 */
function showWeather(result){
    result = JSON.parse(result);
    var list = result.list;
    var table = '<table><tr><th>日期</th><th>天氣</th><th>最低溫度</th><th>最高溫度</th></tr>';
    for(var i in list){
        var d = new Date(list[i].dt*1000);
        table += '<tr>';
        table += '<td>'+d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate()+'</td>';
        table += '<td>'+list[i].weather[0].description+'</td>';
        table += '<td>'+Math.round(list[i].temp.min-273.15)+' °C</td>';
        table += '<td>'+Math.round(list[i].temp.max-273.15)+' °C</td>';
        table += '</tr>';
    }
    table += '</table>';
    document.getElementById('weather').innerHTML = table;
}
/**
 * 讀取本地存儲
 */
var city = localStorage.city;
city = city?city:'beijing';
var url = 'http://api.openweathermap.org/data/2.5/forecast/daily?q='+city+',china&lang=zh_cn';
//ajax請求調用
httpRequest(url, showWeather);

popup.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            body {
                width: 520px;
                height: 270px;
            }

            table {
                font-family: "Lucida Sans Unicode", "Lucida Grande", Sans-Serif;
                font-size: 12px;
                width: 480px;
                text-align: left;
                border-collapse: collapse;
                border: 1px solid #69c;
                margin: 20px;
                cursor: default;
            }

            table th {
                font-weight: normal;
                font-size: 14px;
                color: #039;
                border-bottom: 1px dashed #69c;
                padding: 12px 17px;
                white-space: nowrap;
            }

            table td {
                color: #669;
                padding: 7px 17px;
                white-space: nowrap;
            }

            table tbody tr:hover td {
                color: #339;
                background: #d0dafd;
            }
        </style>
    </head>
    <body>
        <div id="weather">載入中……</div>
        <script src="js/weather.js"></script>
    </body>
</html>

2.網頁代碼

options.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>設定城市</title>
    </head>
    <body>
        <input type="text" id="city" />
        <input type="button" id="save" value="保存" />
        <script src="js/options.js"></script>
    </body>
</html>

options.js

//存儲本地數據
var city = localStorage.city;
city = city?city:'beijing';
document.getElementById('city').value = city;
document.getElementById('save').onclick = function(){
    localStorage.city = document.getElementById('city').value;
    alert('保存成功。');
}

六、window.postMessage實現跨域通信

以下必須在web服務器中設置:
X-Frame-Options是什麼?
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM http://xtwy.com/
第一個例子告訴瀏覽器不要(DENY)把這個網頁放在iFrame內,通常的目的就是要幫助用戶對抗點擊劫持。
第二個例子告訴瀏覽器只有當架設iFrame的網站與發出X-Frame-Options的網站相同,才能顯示發出X-Frame-Options網頁的內容。
第三個例子告訴瀏覽器這個網頁只能放在http://xtwy.com//網頁架設的iFrame內。

1.發送消息的”postMessage”方法

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<title>數據發送端</title>
<!--實現跨域通信-->
<iframe id="proxy" src="http://127.0.0.1:8020/postMessage/index.html"  style="display: none"></iframe>
<script type="text/javascript">
    var iframe = document.getElementById('proxy');
    var win = iframe.contentWindow;
    //週期性的發送消息
    setInterval(function(){
        var message = '現在的時間是: ' + (new Date().getTime());
        console.log('發送消息:  ' + message);
        win.postMessage(message,'http://127.0.0.1:8020/');
    },6000);

    //監聽消息反饋
    window.addEventListener('message',function(event) {
        if(event.origin !== 'http://127.0.0.1:8020') return;
        console.log('接受響應:  ',event.data);
    },false);
</script>
</body>
</html>

向外界窗口發送消息:
otherWindow.postMessage(message, targetOrigin);
otherWindow: 指目標窗口,也就是給哪個window發消息,是 window.frames 屬性的成員或者由 window.open 方法創建的窗口
參數說明:
message: 是要發送的消息,類型爲 String、Object (IE8、9 不支持)
targetOrigin: 是限定消息接收範圍,不限制請使用 ‘*’

2.接受信息的”message”事件

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>數據接收端</title>
    </head>
    <body>
        數據接收端。
        <script>
            window.addEventListener("message", receiveMessage, false);

            function receiveMessage(event) {
                //data.msg 將是從另一個域發送來的
                if(event.origin !== "http://localhost:63342")
                    return;
                //輸出內容
                console.log('接受消息:' + event.data,event);
                //回發
                event.source.postMessage('消息返回!',event.origin);
            }
        </script>
    </body>
</html>

結果:
image

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章