XUL контейнерная функция js, и я хочу вызвать одну из функций js из внешнего iframe на странице - PullRequest
3 голосов
/ 22 ноября 2011

Я создаю шаблон xul и добавляю js внутри xul.

главная страница содержит тег iframe.Я хочу вызвать определенную функцию js (внутри xul) со страницы загруженного iframe.

например:

это файл 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>

Это файл General 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>

есть ли способ сделать это?

1 Ответ

0 голосов
/ 01 февраля 2014

Контент (ненадежный) документ (включая любые 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. Он устанавливает функцию в ненадежное окно domWindow, которое предоставляет ожидаемый API конечному пользователю, который при вызове упаковывает аргументы (включая функцию обратного вызова) и вызывает искусственное событие. Он организует это как фабрику методов, так что конечный пользователь может иметь любую форму 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);
    }
  };
})();

Теперь, когда мы нашли способ вырваться из песочницы, нам нужно убедиться, что мы только добавляем эту возможность на наши «доверенные» веб-страницы. (т.е. URL, на котором вы разместили свой PHP).

Я делал это в Firefox, поэтому я имею дело с одним или несколькими TabBrowser элементами XUL в пользовательском интерфейсе. Поскольку вы используете XulRunner, это может быть не так.

Чтобы найти нашу «доверенную» страницу, нам нужно просмотреть все текущие (и будущие) chromeWindows и установить на них обработчик «загрузки».

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);

, где WindowListener определяется как:

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) { }
};

, где my_load_handler определяется как:

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);
  }
}
...