Bug 1244340 - Part 2: add setOriginAttributes in nsIXMLHttpRequest. r=sicking
authorYoshi Huang <allstars.chh@mozilla.com>
Wed, 06 Jul 2016 12:06:25 +0800
changeset 311334 8627e28f153d281e534170932957092abdc7c0c8
parent 311333 4a18d3c8af3c1aadfecb373ac72818a2c35ba6b3
child 311335 bc99aaf0d06f42a97e540ea72afc2faabab95e62
push id81106
push useryhuang@mozilla.com
push dateFri, 26 Aug 2016 10:59:21 +0000
treeherdermozilla-inbound@bc99aaf0d06f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs1244340
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1244340 - Part 2: add setOriginAttributes in nsIXMLHttpRequest. r=sicking Add a ChromeOnly method called 'setOriginAttributes' on the XMLHttpRequest, so that we can override the origin attributes for those XHRs running by XUL (which will use System Principal).
caps/BasePrincipal.cpp
caps/BasePrincipal.h
dom/base/test/unit/test_xhr_origin_attributes.js
dom/base/test/unit/xpcshell.ini
dom/webidl/XMLHttpRequest.webidl
dom/xhr/XMLHttpRequest.h
dom/xhr/XMLHttpRequestMainThread.cpp
dom/xhr/XMLHttpRequestMainThread.h
dom/xhr/XMLHttpRequestWorker.h
dom/xhr/moz.build
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -293,16 +293,27 @@ OriginAttributes::PopulateFromOrigin(con
 }
 
 void
 OriginAttributes::SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing)
 {
   mPrivateBrowsingId = aInPrivateBrowsing ? 1 : 0;
 }
 
+void
+OriginAttributes::SetFromGenericAttributes(const GenericOriginAttributes& aAttrs)
+{
+  mAppId = aAttrs.mAppId;
+  mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
+  mAddonId = aAttrs.mAddonId;
+  mUserContextId = aAttrs.mUserContextId;
+  mSignedPkg = aAttrs.mSignedPkg;
+  mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
+}
+
 BasePrincipal::BasePrincipal()
 {}
 
 BasePrincipal::~BasePrincipal()
 {}
 
 NS_IMETHODIMP
 BasePrincipal::GetOrigin(nsACString& aOrigin)
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -18,16 +18,18 @@ class nsIContentSecurityPolicy;
 class nsIObjectOutputStream;
 class nsIObjectInputStream;
 class nsIURI;
 
 class nsExpandedPrincipal;
 
 namespace mozilla {
 
+class GenericOriginAttributes;
+
 // Base OriginAttributes class. This has several subclass flavors, and is not
 // directly constructable itself.
 class OriginAttributes : public dom::OriginAttributesDictionary
 {
 public:
   bool operator==(const OriginAttributes& aOther) const
   {
     return mAppId == aOther.mAppId &&
@@ -52,16 +54,18 @@ public:
   // |uri!key1=value1&key2=value2| and returns the uri without the suffix.
   MOZ_MUST_USE bool PopulateFromOrigin(const nsACString& aOrigin,
                           nsACString& aOriginNoSuffix);
 
   // Helper function to match mIsPrivateBrowsing to existing private browsing
   // flags. Once all other flags are removed, this can be removed too.
   void SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing);
 
+  void SetFromGenericAttributes(const GenericOriginAttributes& aAttrs);
+
 protected:
   OriginAttributes() {}
   explicit OriginAttributes(const OriginAttributesDictionary& aOther)
     : OriginAttributesDictionary(aOther) {}
 };
 
 class PrincipalOriginAttributes;
 class DocShellOriginAttributes;
new file mode 100644
--- /dev/null
+++ b/dom/base/test/unit/test_xhr_origin_attributes.js
@@ -0,0 +1,50 @@
+let Cc = Components.classes;
+let Ci = Components.interfaces;
+let Cu = Components.utils;
+
+Cu.import("resource://testing-common/httpd.js");
+
+let server = new HttpServer();
+server.start(-1);
+
+let body = "<!DOCTYPE HTML><html><head><meta charset='utf-8'></head><body></body></html>";
+
+function handler(request, response) {
+  response.setStatusLine(request.httpVersion, 200, "Ok");
+  response.setHeader("Content-Type", "text/html", false);
+
+  if (!request.hasHeader("Cookie")) {
+    response.setHeader("Set-Cookie", "test", false);
+    ok(true);
+  } else {
+    ok(false);
+  }
+
+  response.bodyOutputStream.write(body, body.length);
+}
+
+function run_test() {
+  do_test_pending();
+  server.registerPathHandler("/foo", handler);
+
+  let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1'].createInstance(Ci.nsIXMLHttpRequest);
+  xhr.open("GET", "http://localhost:" + server.identity.primaryPort + "/foo", true);
+  xhr.send(null);
+
+  xhr.onload = function() {
+    // We create another XHR to connect to the same site, but this time we
+    // specify with different origin attributes, which will make the XHR use a
+    // different cookie-jar than the previous one.
+    let xhr2 = Cc['@mozilla.org/xmlextras/xmlhttprequest;1'].createInstance(Ci.nsIXMLHttpRequest);
+    xhr2.open("GET", "http://localhost:" + server.identity.primaryPort + "/foo", true);
+    xhr2.setOriginAttributes({userContextId: 1});
+    xhr2.send(null);
+
+    let loadInfo = xhr2.channel.loadInfo;
+    Assert.equal(loadInfo.originAttributes.userContextId, 1);
+
+    xhr2.onload = function() {
+      server.stop(do_test_finished);
+    }
+  };
+}
--- a/dom/base/test/unit/xpcshell.ini
+++ b/dom/base/test/unit/xpcshell.ini
@@ -40,15 +40,16 @@ head = head_xml.js
 head = head_xml.js
 [test_range.js]
 head = head_xml.js
 [test_thirdpartyutil.js]
 [test_treewalker.js]
 head = head_xml.js
 [test_xhr_document.js]
 [test_xhr_standalone.js]
+[test_xhr_origin_attributes.js]
 [test_xml_parser.js]
 head = head_xml.js
 [test_xml_serializer.js]
 head = head_xml.js
 [test_xmlserializer.js]
 [test_cancelPrefetch.js]
 [test_chromeutils_base64.js]
--- a/dom/webidl/XMLHttpRequest.webidl
+++ b/dom/webidl/XMLHttpRequest.webidl
@@ -147,11 +147,14 @@ interface XMLHttpRequest : XMLHttpReques
   // A platform-specific identifer to represent the network interface 
   // which the HTTP request would occur on.
   [ChromeOnly, Exposed=Window]
   attribute ByteString? networkInterfaceId;
 
   [Throws, ChromeOnly, Exposed=Window]
   any getInterface(IID iid);
 
+  [ChromeOnly, Exposed=Window]
+  void setOriginAttributes(optional OriginAttributesDictionary originAttributes);
+
   readonly attribute boolean mozAnon;
   readonly attribute boolean mozSystem;
 };
--- a/dom/xhr/XMLHttpRequest.h
+++ b/dom/xhr/XMLHttpRequest.h
@@ -160,16 +160,19 @@ public:
   SetNetworkInterfaceId(const nsACString& aId) = 0;
 
   // We need a GetInterface callable from JS for chrome JS
   virtual void
   GetInterface(JSContext* aCx, nsIJSID* aIID,
                JS::MutableHandle<JS::Value> aRetval,
                ErrorResult& aRv) = 0;
 
+  virtual void
+  SetOriginAttributes(const mozilla::dom::OriginAttributesDictionary& aAttrs) = 0;
+
   virtual bool
   MozAnon() const = 0;
 
   virtual bool
   MozSystem() const = 0;
 
   virtual JSObject*
   WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -15,16 +15,17 @@
 #include "mozilla/dom/BlobSet.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FetchUtil.h"
 #include "mozilla/dom/FormData.h"
 #include "mozilla/dom/URLSearchParams.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/LoadInfo.h"
+#include "mozilla/LoadContext.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsIDOMDocument.h"
 #include "mozilla/dom/ProgressEvent.h"
 #include "nsIJARChannel.h"
 #include "nsIJARURI.h"
 #include "nsLayoutCID.h"
 #include "nsReadableUtils.h"
 
@@ -1539,16 +1540,30 @@ XMLHttpRequestMainThread::OpenInternal(c
     mState = State::opened;
     FireReadystatechangeEvent();
   }
 
   return NS_OK;
 }
 
 void
+XMLHttpRequestMainThread::SetOriginAttributes(const OriginAttributesDictionary& aAttrs)
+{
+  MOZ_ASSERT((mState == State::opened) && !mFlagSend);
+
+  GenericOriginAttributes attrs(aAttrs);
+  NeckoOriginAttributes neckoAttrs;
+  neckoAttrs.SetFromGenericAttributes(attrs);
+
+  nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
+  MOZ_ASSERT(loadInfo);
+  loadInfo->SetOriginAttributes(neckoAttrs);
+}
+
+void
 XMLHttpRequestMainThread::PopulateNetworkInterfaceId()
 {
   if (mNetworkInterfaceId.IsEmpty()) {
     return;
   }
   nsCOMPtr<nsIHttpChannelInternal> channel(do_QueryInterface(mChannel));
   if (!channel) {
     return;
--- a/dom/xhr/XMLHttpRequestMainThread.h
+++ b/dom/xhr/XMLHttpRequestMainThread.h
@@ -53,16 +53,17 @@ class nsIJSID;
 namespace mozilla {
 namespace dom {
 
 class Blob;
 class BlobSet;
 class FormData;
 class URLSearchParams;
 class XMLHttpRequestUpload;
+struct OriginAttributesDictionary;
 
 // A helper for building up an ArrayBuffer object's data
 // before creating the ArrayBuffer itself.  Will do doubling
 // based reallocation, up to an optional maximum growth given.
 //
 // When all the data has been appended, call getArrayBuffer,
 // passing in the JSContext* for which the ArrayBuffer object
 // is to be created.  This also implicitly resets the builder,
@@ -532,16 +533,20 @@ public:
   static void SetDontWarnAboutSyncXHR(bool aVal)
   {
     sDontWarnAboutSyncXHR = aVal;
   }
   static bool DontWarnAboutSyncXHR()
   {
     return sDontWarnAboutSyncXHR;
   }
+
+  virtual void
+  SetOriginAttributes(const mozilla::dom::OriginAttributesDictionary& aAttrs) override;
+
 protected:
   // XHR states are meant to mirror the XHR2 spec:
   //   https://xhr.spec.whatwg.org/#states
   enum class State : uint8_t {
     unsent,           // object has been constructed.
     opened,           // open() has been successfully invoked.
     headers_received, // redirects followed and response headers received.
     loading,          // response body is being received.
--- a/dom/xhr/XMLHttpRequestWorker.h
+++ b/dom/xhr/XMLHttpRequestWorker.h
@@ -243,16 +243,22 @@ public:
   virtual void
   GetInterface(JSContext* aCx, nsIJSID* aIID,
                JS::MutableHandle<JS::Value> aRetval,
                ErrorResult& aRv) override
   {
     aRv.Throw(NS_ERROR_FAILURE);
   }
 
+  virtual void
+  SetOriginAttributes(const mozilla::dom::OriginAttributesDictionary& aAttrs) override
+  {
+    MOZ_CRASH("This method cannot be called on workers.");
+  }
+
   XMLHttpRequestUpload*
   GetUploadObjectNoCreate() const
   {
     return mUpload;
   }
 
   void
   UpdateState(const StateData& aStateData, bool aUseCachedArrayBufferResponse);
--- a/dom/xhr/moz.build
+++ b/dom/xhr/moz.build
@@ -28,9 +28,11 @@ UNIFIED_SOURCES += [
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/workers',
     '/netwerk/base',
 ]
 
 MOCHITEST_MANIFESTS += [ 'tests/mochitest.ini' ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'