2013-04-15 31 views
1

設置:跨幀跨站點腳本 - 創建網頁reloader /看門狗

有遠程測量站,有集中收集/處理/呈現服務器(帶有一個網絡服務器),並有觀測站這是爲客戶顯示收集的數據。

這些觀測站包括裸露的骨頭簡單嵌入式計算機配備有web瀏覽器在kiosk模式工作顯示從每個中央服務器的一個特定網頁的。此網頁使用顯示給定測量站的最新測量結果的AJAX進行更新。連接到固定的監視器上,這些站點幾乎可以免費維護多年。

現在,我們已經制定了大部分的扭結,但有此事:如果Web服務器出現故障? 瀏覽器將加載「無法訪問」,「404」,「權限被拒絕」,「500」或服務器在此時發生的任何故障模式,並保留在那裏,直到有人手動重新啓動觀察站。

我想出的通用解決方案是將瀏覽器的主頁設置爲不是觀察頁面,而是設置爲始終可用的本地HTML文件,如果遠程頁面已加載並正確更新,它將執行定期檢查,然後重新加載它是否因任何原因無法執行。

問題:

問題出在跨框架腳本。我猜目標網頁將不得不加載爲框架,iframe,文本/ HTML類型的對象,或以其他方式顯示,而無需移除/禁用本地「容器」文件。幾年前,我寫了一個跨框架腳本頁面,規避安全對策並不容易。自那時以來,安全必須收緊。

所以,從遠程服務器加載的頁面包含一塊定期推出(setInterval的部分),如果一切順利的話,還是不一樣,如果東西壞了的JavaScript。這個信號週期性地到達容器框架使其重置其超時並且不採取任何其他動作。

在情況下,信號沒有到達,作爲超時期滿時,容器開始週期性刷新所加載的網頁,直到服務器的固定和適當的內容被加載,信令至裝載機。

如何獲取遠程頁面信號「活着」(比如設置變量)從文件加載的地方(容器)頁面://每次URL特定的功能被觸發?

回答

0

跨幀,跨站通信使用的postMessage的方法。

所包含的框架,每個正確的執行應該執行:

window.top.postMessage('tyrp', '*'); 

容器文檔應該包含:

window.onmessage = function(e) 
{ 
    if (e.data == 'tyrp') { 
     //reset timeout here 
    } 
}; 
2

有一個叫porthole庫,基本上做什麼SF的答案。以更正式的形式描述。我剛寫了一個網頁來切換顯示兩個iframe中的一個。在頂級網頁我有

var windowProxy; 
windowProxy = new Porthole.WindowProxy(baseURL + '/porthole/proxy.html', frameId); 
windowProxy.addEventListener(onMessage); 
... 
function onMessage(messageEvent) { 
    if (messageEvent.origin !== baseURL) { 
     $log.error(logPrefix + ': onMessage: invalid origin'); 
     console.dir(messageEvent); 
     return; 
    } 
    if (messageEvent.data.pong) { 
     pongReceived(); 
     return; 
    } 
    $log.log(logPrefix + ': onMessage: unknown message'); 
    console.dir(messageEvent); 
} 
... 
var sendPing = function() { 
    $log.log(logPrefix + ': ping to ' + baseURL); 
    ... 
    windowProxy.post({ 'ping': true }); 
}; 

加上一些額外的控制邏輯。在孩子的網頁下面就是一切我不得不添加(加上從控制器到portholeService.init()通話):

// This service takes care of porthole (https://github.com/ternarylabs/porthole) 
// communication if this is invoked from a parent frame having this web page 
// as a child iframe. Usage of porthole is completely optional, and should 
// have no impact on anything outside this service. The purpose of this 
// service is to enable some failover service to be build on top of this 
// using two iframes to switch between. 
services.factory('portholeService', ['$rootScope', '$log', '$location', function ($rootScope, $log, $location) { 
    $log.log('Hello from portholeService'); 

    function betterOffWithFailover() { 
     ... 
    } 

    function onMessage(messageEvent) { 
     $rootScope.$apply(function() { 
      if (messageEvent.origin !== baseUrl) { 
       $log.error('onMessage: invalid origin'); 
       console.dir(messageEvent); 
       return; 
      } 

      if (!messageEvent.data.ping) { 
       $log.error('unknown message'); 
       console.dir(messageEvent.data); 
       return; 
      } 

      if (betterOffWithFailover()) { 
       $log.log('not sending pong'); 
       return; 
      } 

      windowProxy.post({ 'pong': true }); 
     }); 
    } 

    var windowProxy; 
    var baseUrl; 
    function init() { 
     baseUrl = $location.protocol() + '://' + $location.host() + ':' + $location.port(); 
     windowProxy = new Porthole.WindowProxy(baseUrl + '/porthole/proxy.html'); 
     windowProxy.addEventListener(onMessage); 
    } 

    return { 
     init: init 
    }; 
}]); 

僅供參考這些頁面的情況下,$rootScope.$apply等使用AngularJS被陌生吧。