title: Firefox 45 XUL/XPCOM - accessing webpage JS objects and functions from browser context
body: <p>I am currently developing an app using Firefox 45 as a framework, which will access and control a surveillance camera. The camera has a built-in webserver and can be accessed on the local network using the IP address. I wanted to provide extended features not currently available in the camera's UI.</p>
  <p>I chose FF 45 as it was the oldest version available which supports the code the camera code uses. I was trying to go for the most primitive version of FF as I could as the older versions are much less bloated, and it is also easier to manipulate the browser's native code on those older versions.  Ultimately I will modify Firefox to turn it into a stand-alone app for the camera.</p>
  <p>Perhaps some of you folks who have dealt with XUL Firefox in the past either developing addons or even contributing to native code might remember enough to help me out.  I have written XUL addons in the past but none which were trying to access webpage JS.  It appears MDN has now removed all of its XUL documentation (for a while they were hosting it as &quot;obsolete content&quot;, but it appears like it is no longer available.)</p>
  <p>Herein lies my issue. I am finding that I cannot directly access JS objects/functions on the camera page from the browser context, at least not how I have attempted. I have been trying to feel my way around using Scratchpad in browser context. Here is an example:</p>
  <p>In scratchpad within the webpage content context, I can run:</p>
  <pre><code>// Code run in Scratchpad in camera webpage content context.
  // ViewImage is a function within the camera webpage's code.
  
  dump(window.ViewImage + &quot;\n&quot;);
  </code></pre>
  <p>And I get output indicating ViewImage is accessible.</p>
  <p>However, in Browser context:</p>
  <pre><code>// Code run in Scratchpad in browser context:
  // Webpage is loaded in gBrowser.browsers[0].
  
  function XXXXRun() {
    let win = gBrowser.browsers[0].docShell.DOMWindow.window;
    dump(win.ViewImage + &quot;\n&quot;);
  }
  
  XXXXRun();
  </code></pre>
  <p>Output indicates &quot;undefined&quot;. However, I can access DOM objects eg,</p>
  <pre><code>// Code run in Scratchpad in browser context:
  // Webpage is loaded in gBrowser.browsers[0].
  
  function XXXXRun() {
    let win = gBrowser.browsers[0].docShell.DOMWindow.window;
    dump(win.document.getElementById(&quot;some_id_unique_to_the_camera_page&quot;) + &quot;\n&quot;);
  }
  
  XXXXRun();
  </code></pre>
  <p>Indicates the presence of an element with that ID.</p>
  <p>It would seem to me that <code>gBrowser.browsers[0].docShell.DOMWindow.window</code> is equivalent to <code>window</code> of the page residing in <code>gBrowser.browsers[0]</code>, but perhaps there is more to it than that.  It seems I can get a reference to the webpage's window object in some capacity (eg, able to get references to DOM objects through win.document) but am restricted to a degree.  I have even tried <code>gBrowser.browsers[0].docShell.DOMWindow.window.document.defaultView</code> to get a reference of the webpage's window object.</p>
  <p>Here is an example of the code in the JS file downloaded from the camera:</p>
  <pre><code>function ViewImage() {
    throw { &quot;msg&quot;: &quot;Don't NEW a singleton.&quot; };
  }
  
  EventListener.apply(ViewImage);
  
  (function() {
    ViewImage.refreshView = function() {
    ...
    }
    ...
  })();
  </code></pre>
  <p>I ultimately intend to modify the browser code rather than running an addon inside of it. I have successfully made modifications to the code already to add features to the camera UI which involve DOM manipulation. Eventually the UI will be radically altered where it will not appear like a browser at all. If someone has ever written a Firefox XUL addon which accomplishes accessing a webpage's objects, information on that would be a good start I'm sure. Or if someone knows how I can access the page's objects using Scratchpad in browser context, that would be better, as I could use the code directly.</p>
  <p>UPDATE:</p>
  <p>I tried implementing <code>wrappedJSObject</code> in my code, eg: <code>let win = gBrowser.browsers[0].docShell.DOMWindow.window.wrappedJSObject;</code>:</p>
  <pre><code>// Code run in Scratchpad in browser context:
  // Webpage is loaded in gBrowser.browsers[0].
  
  function XXXXRun() {
    // Now using wrappedJSObject property:
    let win = gBrowser.browsers[0].docShell.DOMWindow.window.wrappedJSObject;
    
    // Now output indicates ViewImage is being accessed...
    dump(win.ViewImage + &quot;\n&quot;);
  
    // ...also shows function ViewImage.sendCommand is present...
    dump(win.ViewImage.sendCommand + &quot;\n&quot;);
  
    // ...however, running this function appears to do nothing:
    win.ViewImage.sendCommand('SetImage', { &quot;Image&quot;: {&quot;bright&quot;:80}})
  
    // ...yet running the same function from the webpage context in Scratchpad gives the expected behavior.
  }
  
  XXXXRun();
  </code></pre>
  <p>This seems to show I am accessing the object (prints out the function code in the console,) however, when running a function which is a property of the object from this context, the function runs, but does not pass parameters correctly :-/.  If I run the same function from the webpage context, I get the expected results.  I felt like I was just about there, but disappointed when the function didn't work properly :-/</p>