Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Accessing @mozilla.org/xmlextras/xmlhttprequest;1 from content

80 views
Skip to first unread message

Matthew Gertner

unread,
Feb 22, 2013, 10:02:40 AM2/22/13
to dev-pl...@lists.mozilla.org
I have an extension that loads an HTML file into a hidden <browser> and runs script in the context of the hidden browser window. That script needs to be able to make crossdomain XHR requests to chrome:// and resource:// URLs that are apparently now blocked in Firefox 19 (they weren't blocked in Firefox 18).

I'm trying to solve this by injecting my own XMLHttpRequest symbol into the window that wraps @mozilla.org/xmlextras/xmlhttprequest;1. This means that the content can instantiate an XHR with chrome privileges and no crossdomain restrictions. The properties of the XHR object weren't visible in content when I first tried this, but I solved this using __exposedProps__.

Now I get "Permission denied to access property 'documentElement'" when accessing using the responseXML property. I tried setting __exposedProps__ = { documentElement: "r" } but this doesn't appear to make a difference (presumably because setting __exposedProps__ on a native wrapper doesn't work).

Is there a better way to let content do crossdomain XHR? Or is there a good way to provide a usable XML DOM from chrome to content? I can always reparse responseText to create my own DOM if there's a way to create a content-friendly DOM.

Cheers,
Matt

Kyle Huey

unread,
Feb 22, 2013, 10:28:08 AM2/22/13
to Matthew Gertner, dev-pl...@lists.mozilla.org
On Fri, Feb 22, 2013 at 7:02 AM, Matthew Gertner <mat...@salsitasoft.com>wrote:

> Is there a better way to let content do crossdomain XHR? Or is there a
> good way to provide a usable XML DOM from chrome to content? I can always
> reparse responseText to create my own DOM if there's a way to create a
> content-friendly DOM.
>

You should look at SpecialPowersAPI.createSystemXHR. It's what we use in
our test suite to do this.

There's also a systemXHR facility built into Gecko for allowing certain
sites to do cross-origin XHRs without CORS that's being used for b2g, but I
don't think it works to chrome or resource protocols.

- Kyle

Brian Smith

unread,
Feb 22, 2013, 6:19:47 PM2/22/13
to Matthew Gertner, dev-pl...@lists.mozilla.org
----- Original Message -----
> From: "Matthew Gertner" <mat...@salsitasoft.com>
> To: dev-pl...@lists.mozilla.org
> Sent: Friday, February 22, 2013 7:02:40 AM
> Subject: Accessing @mozilla.org/xmlextras/xmlhttprequest;1 from content
>
> I have an extension that loads an HTML file into a hidden <browser>
> and runs script in the context of the hidden browser window. That
> script needs to be able to make crossdomain XHR requests to
> chrome:// and resource:// URLs that are apparently now blocked in
> Firefox 19 (they weren't blocked in Firefox 18).

I believe that the Addon SDK (a.k.a. JetPack) has special provisions for this; See [1], section "Content Scripts." In particular, I think that if you inject a "content script" into the <browser> then the "content script" will be able to make cross-origin requests like you propose. At least, I know that the Addon SDK required an extension to the nsIPrincipal interface to support multi-origin principals for this case.

I am particularly interested if this strategy would work for you and other addon developers.

Cheers,
Brian

[1] https://addons.mozilla.org/en-US/developers/docs/sdk/1.12/dev-guide/guides/xul-migration.html

mat...@salsitasoft.com

unread,
Feb 23, 2013, 1:08:52 PM2/23/13
to Matthew Gertner, dev-pl...@lists.mozilla.org
On Friday, February 22, 2013 4:28:08 PM UTC+1, Kyle Huey wrote:
> You should look at SpecialPowersAPI.createSystemXHR. It's what we use in
> our test suite to do this.

Hi Kyle,

Thanks for this. I need to replace the XMLHttpRequest constructor with my own constructor, so I can't call createSystemXHR directly. I'll see if I can figure out from the code how to do this.

Currently I have to admit that I don't understand how the code addresses the issue of giving content access to the responseXML DOM returned by the Cc['@mozilla.org/xmlextras/xmlhttprequest;1'].

To reiterate my problem: I am replacing the default implementation of XMLHttpRequest with my own wrapper than delegates to Cc['@mozilla.org/xmlextras/xmlhttprequest;1']. Everything works fine except that the DOM returned by the responseXML property returns an error (Permission denied to access property 'documentElement') when I try to retrieve its properties. Clearly there is a wrapper in play but exactly what kind of wrapper and how to penetrate it is not yet clear to me.

I guess the reason I'm suddenly having this problem is https://bugzilla.mozilla.org/show_bug.cgi?id=809652 but I can't be sure since I don't have access to it.

mat...@salsitasoft.com

unread,
Feb 23, 2013, 1:08:52 PM2/23/13
to mozilla.de...@googlegroups.com, Matthew Gertner, dev-pl...@lists.mozilla.org
On Friday, February 22, 2013 4:28:08 PM UTC+1, Kyle Huey wrote:
> You should look at SpecialPowersAPI.createSystemXHR. It's what we use in
> our test suite to do this.

mat...@salsitasoft.com

unread,
Feb 23, 2013, 1:10:51 PM2/23/13
to Matthew Gertner, dev-pl...@lists.mozilla.org
On Saturday, February 23, 2013 12:19:47 AM UTC+1, Brian Smith wrote:
> I believe that the Addon SDK (a.k.a. JetPack) has special provisions for this; See [1], section "Content Scripts." In particular, I think that if you inject a "content script" into the <browser> then the "content script" will be able to make cross-origin requests like you propose. At least, I know that the Addon SDK required an extension to the nsIPrincipal interface to support multi-origin principals for this case.

Hi Brian,

Thanks for the pointer. It looks to me like the Addon SDK is solving the problem by running its content scripts in a sandbox instantiated with the system principal. I do something similar with my content scripts. In this case, the problem is in a background script that is loaded directly into the background window of my framework using a <script> tag, so I think a different solution will be necessary.

Cheers,
Matt

Brian Smith

unread,
Feb 23, 2013, 10:27:16 PM2/23/13
to mat...@salsitasoft.com, dev-pl...@lists.mozilla.org, mozilla dev platform
mat...@salsitasoft.com wrote:
> Thanks for the pointer. It looks to me like the Addon SDK is solving
> the problem by running its content scripts in a sandbox instantiated
> with the system principal. I do something similar with my content
> scripts. In this case, the problem is in a background script that is
> loaded directly into the background window of my framework using a
> <script> tag, so I think a different solution will be necessary.

Right. The Addon SDK approach, AFAICT, requires you to replace your direct chrome:// and resource:// references in your content in the <browser> element with postMessage() to your chrome-context code, which would then fetch the chrome:// and resource:// references and send them back to the content.

I notice that your company has developed a cross-browser framework for building extensions. That means you are probably familiar with Chromium's requirements here. I believe that Chromium requires you to do things the same way as the Firefox Addon SDK recommends. (I'm not sure if that helps explain my suggestion or not.)

Cheers,
Brian

mat...@salsitasoft.com

unread,
Feb 24, 2013, 12:44:03 PM2/24/13
to mat...@salsitasoft.com, dev-pl...@lists.mozilla.org
On Sunday, February 24, 2013 4:27:16 AM UTC+1, Brian Smith wrote:
> I notice that your company has developed a cross-browser framework for building extensions. That means you are probably familiar with Chromium's requirements here. I believe that Chromium requires you to do things the same way as the Firefox Addon SDK recommends. (I'm not sure if that helps explain my suggestion or not.)

Exactly, we need to emulate Chrome's behavior in the background window (see http://developer.chrome.com/extensions/xhr.html). Specifically we need to be able to make cross-domain requests in the background window and requests to chrome:// and resource:// URLs. I've implemented the background window as a hidden XUL window with a <browser> embedded.

Looking over my code before the switch from FF18 to FF19, I wasn't actually doing anything at all except setting the type attribute of the <browser> to chrome (i.e. the default). Unfortunately I'm relying on DOMWindowCreated to inject my symbols into the window, and this is no longer fired in FF19 with the type set to chrome. I guess I'll file a bug about this.

I was naively looking for a quick fix by injecting my own XHR implementation but it looks like that's problematic as I described in my OP. I'll see if I can use the content-document-global-created notification or something.
Message has been deleted

Boris Zbarsky

unread,
Feb 24, 2013, 10:20:40 PM2/24/13
to
On 2/24/13 12:44 PM, mat...@salsitasoft.com wrote:
> Unfortunately I'm relying on DOMWindowCreated to inject my symbols into the window, and this is no longer fired in FF19 with the type set to chrome.

Uh.... code inspection and basic testing over here suggest it fires just
fine, for what it's worth.

-Boris

Boris Zbarsky

unread,
Feb 24, 2013, 10:27:24 PM2/24/13
to
On 2/23/13 1:08 PM, mat...@salsitasoft.com wrote:
> Currently I have to admit that I don't understand how the code addresses the issue of giving content access to the responseXML DOM returned by the Cc['@mozilla.org/xmlextras/xmlhttprequest;1'].

The DOM returned by responseXML is associated with the origin the XHR
was initialized with.

As far as how you set this origin, it used to be that you could do this
directly from a component, but now it looks like we always use the
principal of the associated window, if any.

Unfortunately, we also use that window to determine whether this is a
system XHR or not, as far as I can tell...

> Clearly there is a wrapper in play but exactly what kind of wrapper and how to penetrate it is not yet clear to me.

You really want to just give that DOM the origin of the page you want to
expose it to.

> I guess the reason I'm suddenly having this problem is https://bugzilla.mozilla.org/show_bug.cgi?id=809652

Seems pretty unlikely.

Can you pin down which nightly build the behavior change you observe
happened in? See http://harthur.github.com/mozregression/

-Boris

mat...@salsitasoft.com

unread,
Feb 25, 2013, 3:45:35 AM2/25/13
to
On Monday, February 25, 2013 4:27:24 AM UTC+1, Boris Zbarsky wrote:
> > I guess the reason I'm suddenly having this problem is https://bugzilla.mozilla.org/show_bug.cgi?id=809652
>
> Seems pretty unlikely.

Yes, I misanalyzed this. It appears that the root cause of the problem was that my content scripts (which run in a sandbox) stopped being able to request chrome:// URLs in FF19. I therefore changed to resource:// URLs. Apparently DOMWindowCreated doesn't fire for a resource:// URL in a browser with type == "chrome", so this is indeed not a FF19 change. This led me to use type == "content" (in retrospect a bad idea) and inject my own XHR implementation.

Changing back to chrome:// URLs solves all of this (including eliminating the need to muck with the XHR implementation in the background page) except the original problem of accessing them via XHR in the sandbox. But using the system principal in the sandbox appears to fix this (thanks Brian!).

Hopefully I'm all good now with respect to FF19. Thanks for the help.

Matt

mat...@salsitasoft.com

unread,
Feb 25, 2013, 5:39:41 AM2/25/13
to
On Monday, February 25, 2013 4:27:24 AM UTC+1, Boris Zbarsky wrote:
> The DOM returned by responseXML is associated with the origin the XHR
> was initialized with.
>
> As far as how you set this origin, it used to be that you could do this
> directly from a component, but now it looks like we always use the
> principal of the associated window, if any.
>
> Unfortunately, we also use that window to determine whether this is a
> system XHR or not, as far as I can tell...

I'm not going to need to deal with this for this rev (hopefully) but very useful info nonetheless. Thanks!

Matt

mat...@salsitasoft.com

unread,
Feb 27, 2013, 10:02:40 AM2/27/13
to
On Monday, February 25, 2013 9:45:35 AM UTC+1, mat...@salsitasoft.com wrote:
> Changing back to chrome:// URLs solves all of this (including eliminating the need to muck with the XHR implementation in the background page) except the original problem of accessing them via XHR in the sandbox. But using the system principal in the sandbox appears to fix this (thanks Brian!).

BTW: Using the system principal for my sandbox lets me use the privileged XHR implementation in FF19+. However, this seems to break the code in FF<=18 (where I used a chrome window as the principal for the sandbox). I'd like to preserve backwards compatibility at least for a version or two. For now I'll use nsIXULAppInfo to check the version, but if there's a way to check the capability directly I'd prefer that. Can anyone point me to the bug where this behavior was changed?
0 new messages