Bug 641706: Make SpecialPowers able to create a XHR object with full system powers. r=smaug

This commit is contained in:
Jonas Sicking 2011-03-17 09:19:13 -07:00
Родитель ef31f6cfa2
Коммит 9a77da1530
5 изменённых файлов: 38 добавлений и 47 удалений

Просмотреть файл

@ -126,19 +126,16 @@
#define XML_HTTP_REQUEST_ABORTED (1 << 7) // Internal #define XML_HTTP_REQUEST_ABORTED (1 << 7) // Internal
#define XML_HTTP_REQUEST_ASYNC (1 << 8) // Internal #define XML_HTTP_REQUEST_ASYNC (1 << 8) // Internal
#define XML_HTTP_REQUEST_PARSEBODY (1 << 9) // Internal #define XML_HTTP_REQUEST_PARSEBODY (1 << 9) // Internal
#define XML_HTTP_REQUEST_XSITEENABLED (1 << 10) // Internal, Is any cross-site request allowed? #define XML_HTTP_REQUEST_SYNCLOOPING (1 << 10) // Internal
// Even if this is false the #define XML_HTTP_REQUEST_MULTIPART (1 << 11) // Internal
// access-control spec is supported #define XML_HTTP_REQUEST_GOT_FINAL_STOP (1 << 12) // Internal
#define XML_HTTP_REQUEST_SYNCLOOPING (1 << 11) // Internal #define XML_HTTP_REQUEST_BACKGROUND (1 << 13) // Internal
#define XML_HTTP_REQUEST_MULTIPART (1 << 12) // Internal
#define XML_HTTP_REQUEST_GOT_FINAL_STOP (1 << 13) // Internal
#define XML_HTTP_REQUEST_BACKGROUND (1 << 14) // Internal
// This is set when we've got the headers for a multipart XMLHttpRequest, // This is set when we've got the headers for a multipart XMLHttpRequest,
// but haven't yet started to process the first part. // but haven't yet started to process the first part.
#define XML_HTTP_REQUEST_MPART_HEADERS (1 << 15) // Internal #define XML_HTTP_REQUEST_MPART_HEADERS (1 << 14) // Internal
#define XML_HTTP_REQUEST_USE_XSITE_AC (1 << 16) // Internal #define XML_HTTP_REQUEST_USE_XSITE_AC (1 << 15) // Internal
#define XML_HTTP_REQUEST_NEED_AC_PREFLIGHT (1 << 17) // Internal #define XML_HTTP_REQUEST_NEED_AC_PREFLIGHT (1 << 16) // Internal
#define XML_HTTP_REQUEST_AC_WITH_CREDENTIALS (1 << 18) // Internal #define XML_HTTP_REQUEST_AC_WITH_CREDENTIALS (1 << 17) // Internal
#define XML_HTTP_REQUEST_LOADSTATES \ #define XML_HTTP_REQUEST_LOADSTATES \
(XML_HTTP_REQUEST_UNINITIALIZED | \ (XML_HTTP_REQUEST_UNINITIALIZED | \
@ -1639,14 +1636,12 @@ nsXMLHttpRequest::GetCurrentHttpChannel()
nsresult nsresult
nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel) nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel)
{ {
// First check if cross-site requests are enabled // First check if cross-site requests are enabled...
if ((mState & XML_HTTP_REQUEST_XSITEENABLED)) { if (IsSystemXHR()) {
return NS_OK; return NS_OK;
} }
// or if this is a same-origin request. // ...or if this is a same-origin request.
NS_ASSERTION(!nsContentUtils::IsSystemPrincipal(mPrincipal),
"Shouldn't get here!");
if (nsContentUtils::CheckMayLoad(mPrincipal, aChannel)) { if (nsContentUtils::CheckMayLoad(mPrincipal, aChannel)) {
return NS_OK; return NS_OK;
} }
@ -1797,12 +1792,6 @@ nsXMLHttpRequest::OpenRequest(const nsACString& method,
channelPolicy); channelPolicy);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
// Check if we're doing a cross-origin request.
if (nsContentUtils::IsSystemPrincipal(mPrincipal)) {
// Chrome callers are always allowed to read from different origins.
mState |= XML_HTTP_REQUEST_XSITEENABLED;
}
mState &= ~(XML_HTTP_REQUEST_USE_XSITE_AC | mState &= ~(XML_HTTP_REQUEST_USE_XSITE_AC |
XML_HTTP_REQUEST_NEED_AC_PREFLIGHT); XML_HTTP_REQUEST_NEED_AC_PREFLIGHT);
@ -1823,17 +1812,6 @@ nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
PRBool async, const nsAString& user, PRBool async, const nsAString& user,
const nsAString& password, PRUint8 optional_argc) const nsAString& password, PRUint8 optional_argc)
{ {
if (nsContentUtils::GetCurrentJSContext()) {
// We're (likely) called from JS
// Find out if UniversalBrowserRead privileges are enabled
if (nsContentUtils::IsCallerTrustedForRead()) {
mState |= XML_HTTP_REQUEST_XSITEENABLED;
} else {
mState &= ~XML_HTTP_REQUEST_XSITEENABLED;
}
}
if (!optional_argc) { if (!optional_argc) {
// No optional arguments were passed in. Default async to true. // No optional arguments were passed in. Default async to true.
async = PR_TRUE; async = PR_TRUE;
@ -1954,8 +1932,8 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
nsCOMPtr<nsIChannel> channel(do_QueryInterface(request)); nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
NS_ENSURE_TRUE(channel, NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(channel, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIPrincipal> documentPrincipal = mPrincipal; nsCOMPtr<nsIPrincipal> documentPrincipal;
if (nsContentUtils::IsSystemPrincipal(documentPrincipal)) { if (IsSystemXHR()) {
// Don't give this document the system principal. We need to keep track of // Don't give this document the system principal. We need to keep track of
// mPrincipal being system because we use it for various security checks // mPrincipal being system because we use it for various security checks
// that should be passing, but the document data shouldn't get a system // that should be passing, but the document data shouldn't get a system
@ -1963,6 +1941,8 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
nsresult rv; nsresult rv;
documentPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv); documentPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} else {
documentPrincipal = mPrincipal;
} }
channel->SetOwner(documentPrincipal); channel->SetOwner(documentPrincipal);
@ -2040,7 +2020,7 @@ nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
nsCOMPtr<nsIDocument> responseDoc = do_QueryInterface(mResponseXML); nsCOMPtr<nsIDocument> responseDoc = do_QueryInterface(mResponseXML);
responseDoc->SetPrincipal(documentPrincipal); responseDoc->SetPrincipal(documentPrincipal);
if (nsContentUtils::IsSystemPrincipal(mPrincipal)) { if (IsSystemXHR()) {
responseDoc->ForceEnableXULXBL(); responseDoc->ForceEnableXULXBL();
} }
@ -2420,7 +2400,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
if (httpChannel) { if (httpChannel) {
httpChannel->GetRequestMethod(method); // If GET, method name will be uppercase httpChannel->GetRequestMethod(method); // If GET, method name will be uppercase
if (!nsContentUtils::IsSystemPrincipal(mPrincipal)) { if (!IsSystemXHR()) {
// Get the referrer for the request. // Get the referrer for the request.
// //
// If it weren't for history.push/replaceState, we could just use the // If it weren't for history.push/replaceState, we could just use the
@ -2656,7 +2636,7 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
} }
} }
if (!(mState & XML_HTTP_REQUEST_XSITEENABLED)) { if (!IsSystemXHR()) {
// Always create a nsCrossSiteListenerProxy here even if it's // Always create a nsCrossSiteListenerProxy here even if it's
// a same-origin request right now, since it could be redirected. // a same-origin request right now, since it could be redirected.
listener = new nsCrossSiteListenerProxy(listener, mPrincipal, mChannel, listener = new nsCrossSiteListenerProxy(listener, mPrincipal, mChannel,
@ -2853,7 +2833,7 @@ nsXMLHttpRequest::SetRequestHeader(const nsACString& header,
} }
// Check for dangerous cross-site headers // Check for dangerous cross-site headers
PRBool safeHeader = !!(mState & XML_HTTP_REQUEST_XSITEENABLED); bool safeHeader = IsSystemXHR();
if (!safeHeader) { if (!safeHeader) {
// Content-Type isn't always safe, but we'll deal with it in Send() // Content-Type isn't always safe, but we'll deal with it in Send()
const char *kCrossOriginSafeHeaders[] = { const char *kCrossOriginSafeHeaders[] = {
@ -2862,7 +2842,7 @@ nsXMLHttpRequest::SetRequestHeader(const nsACString& header,
}; };
for (i = 0; i < NS_ARRAY_LENGTH(kCrossOriginSafeHeaders); ++i) { for (i = 0; i < NS_ARRAY_LENGTH(kCrossOriginSafeHeaders); ++i) {
if (header.LowerCaseEqualsASCII(kCrossOriginSafeHeaders[i])) { if (header.LowerCaseEqualsASCII(kCrossOriginSafeHeaders[i])) {
safeHeader = PR_TRUE; safeHeader = true;
break; break;
} }
} }

Просмотреть файл

@ -69,6 +69,7 @@
#include "nsIPrivateDOMEvent.h" #include "nsIPrivateDOMEvent.h"
#include "nsDOMProgressEvent.h" #include "nsDOMProgressEvent.h"
#include "nsDOMEventTargetWrapperCache.h" #include "nsDOMEventTargetWrapperCache.h"
#include "nsContentUtils.h"
class nsILoadGroup; class nsILoadGroup;
class AsyncVerifyRedirectCallbackForwarder; class AsyncVerifyRedirectCallbackForwarder;
@ -333,6 +334,10 @@ protected:
already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel(); already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
bool IsSystemXHR() {
return !!nsContentUtils::IsSystemPrincipal(mPrincipal);
}
/** /**
* Check if aChannel is ok for a cross-site request by making sure no * Check if aChannel is ok for a cross-site request by making sure no
* inappropriate headers are set, and no username/password is set. * inappropriate headers are set, and no username/password is set.

Просмотреть файл

@ -22,9 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=426308
const SJS_URL = "http://example.org:80/tests/content/base/test/bug426308-redirect.sjs"; const SJS_URL = "http://example.org:80/tests/content/base/test/bug426308-redirect.sjs";
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); var req = SpecialPowers.createSystemXHR();
var req = new XMLHttpRequest();
req.open("GET", SJS_URL + "?" + window.location.href, false); req.open("GET", SJS_URL + "?" + window.location.href, false);
req.send(null); req.send(null);

Просмотреть файл

@ -52,8 +52,7 @@ function createDoc() {
function xhrDoc(idx) { function xhrDoc(idx) {
return function() { return function() {
// Defy same-origin restrictions! // Defy same-origin restrictions!
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var xhr = SpecialPowers.createSystemXHR();
var xhr = new XMLHttpRequest();
xhr.open("GET", docSources[idx], false); xhr.open("GET", docSources[idx], false);
xhr.send(); xhr.send();
return xhr.responseXML; return xhr.responseXML;

Просмотреть файл

@ -37,13 +37,18 @@
/* This code is loaded in every child process that is started by mochitest in /* This code is loaded in every child process that is started by mochitest in
* order to be used as a replacement for UniversalXPConnect * order to be used as a replacement for UniversalXPConnect
*/ */
var Ci = Components.interfaces;
var Cc = Components.classes;
function SpecialPowers(window) { function SpecialPowers(window) {
this.window = window; this.window = window;
bindDOMWindowUtils(this, window); bindDOMWindowUtils(this, window);
} }
function bindDOMWindowUtils(sp, window) { function bindDOMWindowUtils(sp, window) {
var util = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils); var util = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
// This bit of magic brought to you by the letters // This bit of magic brought to you by the letters
// B Z, and E, S and the number 5. // B Z, and E, S and the number 5.
// //
@ -135,7 +140,6 @@ SpecialPowers.prototype = {
//XXX: these APIs really ought to be removed, they're not e10s-safe. //XXX: these APIs really ought to be removed, they're not e10s-safe.
// (also they're pretty Firefox-specific) // (also they're pretty Firefox-specific)
_getTopChromeWindow: function(window) { _getTopChromeWindow: function(window) {
var Ci = Components.interfaces;
return window.QueryInterface(Ci.nsIInterfaceRequestor) return window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation) .getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem) .QueryInterface(Ci.nsIDocShellTreeItem)
@ -169,6 +173,11 @@ SpecialPowers.prototype = {
}, },
removeChromeEventListener: function(type, listener, capture) { removeChromeEventListener: function(type, listener, capture) {
removeEventListener(type, listener, capture); removeEventListener(type, listener, capture);
},
createSystemXHR: function() {
return Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
} }
}; };