2011-11-22 11 views
3

xulテンプレートを作成し、xulの中にjsを追加しました。julのxulコンテナ関数です。ページの外部iframeからjs関数の1つを呼び出したい

メインページにはiframeタグが含まれています。 ロードされたiframeページから特定のjs関数(xulの内側)を呼び出したいとします。例えば

これはXULファイルです:

<?xml version="1.0"?> 

  <script type="application/x-javascript" 
     src="chrome://tuttoolbar/content/general.js" /> 

<toolbox id="navigator-toolbox"> 

    <toolbar id="TutTB-Toolbar" toolbarname="Tutorial Toolbar" accesskey="T" 
      class="chromeclass-toolbar" context="toolbar-context-menu" 
      hidden="false" persist="hidden"> 

     <toolbarbutton id="TutTB-MainMenu" type="menu" 
         tooltiptext="Tutorial Toolbar Main Menu"> 
      <menupopup> 
       <menuitem label="Google Home Page" accesskey="G" 
          tooltiptext="Navigate to Google" 
          oncommand="countChild('rso','li')" /> 

       <menuseparator /> 

       <menuitem label="Born Geek Website" accesskey="B" 
          tooltiptext="Navigate to Born Geek" 
          oncommand="te()" /> 
      </menupopup> 
     </toolbarbutton> 


    </toolbar> 



</toolbox> 

これは、一般的なJSファイルである(XULファイル内):

function box(){ 
alert("Box Work"); 
} 

test.phpを - これは、IFRAME内のロード元のページです:

 <html> 
    <head> 
    </head> 
    <body> 
    <div id="call" onclick="javascript:box();"> 
    </body> 
    </html> 

これはメインファイルである:

<html> 
    <head> 
    </head> 
    <body> 
    <iframe src="test.php" width="400" height="40"></iframe> 
    </body> 
    </html> 

それを行うにはどのような方法がありますか?

答えて

0

(信頼できない)ドキュメント(IFRAMEを含む)は、拡張機能やXulRunnerによって読み込まれた他の特権コードで定義された関数を直接実行することはできません。特権コードが信頼できないコンテンツウィンドウに関数を割り当てる場合でも、関数が特権を使用/呼び出ししようとするとセキュリティエラーが発生します。

ただし、信頼されていないコンテンツウィンドウにイベントリスナーを追加することができます。ちょっとした論争を経て、信頼できないコンテンツ、つまりセキュリティサンドボックスからの脱却といった「特権」機能を簡単にインストールするための体系を構築することができます。


ここで、信頼できないdomWindowが(特権)クロスドメインHTTP GET操作を実行することを可能にする例を示します

/* 
    Give the end-user this API: 
    xdomainGET(sURL, 
       function(
        iHTTPStatusCode, 
        sHTTPStatusText, 
        sHTTPResponseText 
       ) { ... })    
*/ 

function install_xdomainGET_on_my_special_page(chromeWindow, domWindow) { 

    install_privileged_method(
    /* this is the current browser chromeWindow (your XUL overlay is here!) */ 
    chromeWindow,  

    /* this is the unstrusted domWindow containing your IFRAME    */ 
    domWindow, 

    /* the name of the method we're adding to the untrusted domWindow  */ 
    'xdomainGET',  

    /* This is the methodFactory */ 
    function(priv) { 
     /* This is the method that will be installed onto the untrusted 
     domWindow. It takes two arguments, 'sURL' and 'cb'. 'sURL' is a 
     cross-domain HTTP URL which we want to be able to GET from the 
     untrusted domWindow. 'cb' is a callback function which returns 
     3 values to the caller...           */ 
     return function(sURL, cb) { 
     priv.call([sURL], function(rstatus, rdata, rerror){ 
      cb(rstatus ? rdata.statusCode : 0,  // iHTTPStatusCode 
      rstatus ? rdata.statusText : rerror, // sHTTPStatusText 
      rstatus ? rdata.responseText : null); // sHTTPResponseText 
     }); 
     }; 
    }, 

    /* This is the privileged 'handler code. It has access to the 
     chromeWindow, and all of the privileged APIs that are available 
     there. (e.g: nsI*, XPCom, js-ctypes, etc)       */ 
    function (chromeWindow, args, cb) { 
     var [url] = args; 
     var xhr = new chromeWindow.XMLHttpRequest(); 
     xhr.onload = function(){ 
     cb(1, { 
      statusCode: this.status, 
      statusText: this.statusText, 
      responseText: this.responseText 
     }, null); 
     }; 
     xhr.addEventListener('error', function(error_evt) { 
     cb(0, null, error_evt.error); 
     }, false); 
     xhr.open('get', url, true); 
     xhr.send(); 
    } 
); 
} 

をそして、ここではそれが可能に私のライブラリ関数です。

  1. これは、コールバック関数を含むパッケージまでの引数を(と呼ばれるエンドユーザーに期待されるAPIを提供unstrusted domWindowに機能をインストールします。基本的には、(特権コードから)2つのことを行います)、合成イベントを発生させる。これはメソッドファクトリーとして編成されており、コールバックを取る限り、エンドユーザーは任意のAPI形状を持つことができます。

  2. 信頼できないウィンドウにイベントハンドラをインストールします。信頼できないウィンドウがその合成イベントをディスパッチすると、イベントハンドラはそれをキャッチし、引数を展開して、提供された特権コードを実行します。次に、イベントの詳細内で提供される信頼できないコールバック関数を呼び出します。


const Cc = Components.classes; 
const Ci = Components.interfaces; 
let consoleService = Cc["@mozilla.org/consoleservice;1"] 
         .getService(Ci.nsIConsoleService); 
function LOG(msg) { 
    consoleService.logStringMessage("EXTENSION: "+msg); 
} 

// install a privileged method on the given (untrusted) 'target' window 
var install_privileged_method = (function(){ 
    var gensym = (function(){ 
    var __sym = 0; 
    return function() { return '__sym_'+(__sym++); } 
    })(); 

    return function (chromeWindow, target, slot, handler, methodFactory) { 
    try { 

     // initialise target window with ticket/callback-dict/namespace 
     target.__pmcache__ = target.hasOwnProperty('__pmcache__') 
     ? target.__pmcache__ 
     : { ticket_no: 0, callbacks: {}, namespace: gensym() }; 

     // install the user factory-generated dispatcher method on 
     // the 'target' untrusted content window. 
     target[slot] = methodFactory({ call: function(fargs, fcb) { 
     try { 
      var ticket_no = target.__pmcache__.ticket_no++; 
      target.__pmcache__.callbacks[ticket_no] = fcb; 
      var cevent = target.document.createEvent("CustomEvent"); 
      cevent.initCustomEvent(
      target.__pmcache__.namespace+'.'+slot, 
      true, true, { fargs: fargs, ticket_no: ticket_no } 
     ); 
      target.dispatchEvent(cevent); 
     } catch (ue) { 
      fcb(0, null, 'untrusted dispatcher error: '+ue); 
     } 
     }}); 
     LOG("installed untrusted dispatcher for method '"+slot+"'."); 

     // Add an event listener to (untrusted) target window which 
     // listens for custom event generated by above dispatcher method. 
     target.addEventListener(
     target.__pmcache__.namespace+'.'+slot, 
     function(cevent){ 
      var ticket_no = cevent.detail.ticket_no; 
      var fargs = cevent.detail.fargs; 
      var fcb = target.__pmcache__.callbacks[ticket_no]; 
      try { 
      handler(chromeWindow, fargs, fcb); 
      } catch (pe) { 
      fcb(0, null, 'privileged handler error: '+pe); 
      } 
     }, 
     false, 
     true 
    ); 
     LOG("installed privileged handler for method '"+slot+"'."); 

    } catch (ie) { 
     LOG("ERROR installing handler/factory for privileged "+ 
      "method '"+slot+"': "+ie); 
    } 
    }; 
})(); 

今、私たちはサンドボックスから抜け出すための方法を発見したことを、我々は唯一の私たちの「信頼のWebページにその可能性を追加することを確認する必要があります。 (つまり、あなたのPHPをホストしていたURL)。

私はFirefoxでこれをやっているので、私はユーザーインターフェイスで1つ以上のTabBrowser XUL要素を扱っています。 XulRunnerを使用しているので、そうではないかもしれません。

信頼できるページを見つけるには、現在の(および将来の)すべてのchromeWindowsを見て、それらに 'load'ハンドラをインストールする必要があります。

var my_load_handler = function (evt) { 
    try { 
    var browserEnumerator = wm.getEnumerator("navigator:browser"); 
    while (browserEnumerator.hasMoreElements()) { 
     var browserWin = browserEnumerator.getNext(); 
     var tabbrowser = browserWin.gBrowser; 
     var numTabs = tabbrowser.browsers.length; 
     for (var index = 0; index < numTabs; index++) { 
     var currentBrowser = tabbrowser.getBrowserAtIndex(index); 
     var domWindow = currentBrowser.contentWindow.wrappedJSObject; 

     // identify your target page... 
     if (domWindow.location.href == 'http://yourserver/yourpage') { 

      // install the privileged method (if it's not already there!) 
      if (!domWindow.hasOwnProperty('xdomainGET') { 
      install_xdomainGET_on_my_special_page(browserWin, domWindow); 
      } 
     } 

     } 
    } 
    } catch (e) { 
    LOG(e); 
    } 
} 
my_load_handlerのように定義される

var WindowListener = { 
    setupBrowserUI: function(window, xulWindow, othWindow) { 
    window.gBrowser.addEventListener('load', my_load_handler, true); 
    }, 
    tearDownBrowserUI: function(window) { 
    window.gBrowser.removeEventListener('load', my_load_handler, true); 
    }, 
    onOpenWindow: function(xulWindow) { 
    let domWindow = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor) 
         .getInterface(Ci.nsIDOMWindow); 
    domWindow.addEventListener("load", function listener() { 
     domWindow.removeEventListener("load", listener, false); 
     var domDocument = domWindow.document.documentElement; 
     var windowType = domDocument.getAttribute("windowtype"); 
     if (windowType == "navigator:browser") 
     WindowListener.setupBrowserUI(domWindow); 
    }, false); 
    }, 

    onCloseWindow: function(xulWindow) { }, 
    onWindowTitleChange: function(xulWindow, newTitle) { } 
}; 

WindowListenerのように定義される

let wm = Cc["@mozilla.org/appshell/window-mediator;1"] 
      .getService(Ci.nsIWindowMediator); 
let windows = wm.getEnumerator("navigator:browser"); 
while (windows.hasMoreElements()) { 
    let domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow); 
    WindowListener.setupBrowserUI(domWindow); 
} 
wm.addListener(WindowListener); 

関連する問題