Bug 1154366 - Pass in a JSContext to StructuredCloneContainer::InitFromJSVal so it will throw its exceptions somewhere where people might see them. r=bholley, ba=sledru
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 16 Apr 2015 13:22:15 -0400
changeset 258543 72f1b4086067
parent 258542 5dc0d44c8dbd
child 258544 f3dd042acc18
push id4691
push userryanvm@gmail.com
push date2015-04-20 17:16 +0000
treeherdermozilla-beta@72f1b4086067 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1154366
milestone38.0
Bug 1154366 - Pass in a JSContext to StructuredCloneContainer::InitFromJSVal so it will throw its exceptions somewhere where people might see them. r=bholley, ba=sledru
docshell/base/nsDocShell.cpp
dom/base/crashtests/crashtests.list
dom/base/crashtests/structured_clone_container_throws.html
dom/base/nsStructuredCloneContainer.cpp
dom/interfaces/base/nsIStructuredCloneContainer.idl
dom/notification/Notification.cpp
testing/web-platform/meta/html/browsers/history/the-history-interface/001.html.ini
testing/web-platform/meta/html/browsers/history/the-history-interface/002.html.ini
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -11428,17 +11428,17 @@ nsDocShell::AddState(JS::Handle<JS::Valu
   {
     nsCOMPtr<nsIDocument> origDocument = GetDocument();
     if (!origDocument) {
       return NS_ERROR_DOM_SECURITY_ERR;
     }
     nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
 
     scContainer = new nsStructuredCloneContainer();
-    rv = scContainer->InitFromJSVal(aData);
+    rv = scContainer->InitFromJSVal(aData, aCx);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIDocument> newDocument = GetDocument();
     if (!newDocument) {
       return NS_ERROR_DOM_SECURITY_ERR;
     }
     nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
 
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -195,8 +195,9 @@ load 973401.html
 load 978646.html
 pref(dom.webcomponents.enabled,true) load 1027461-1.html
 pref(dom.webcomponents.enabled,true) load 1024428-1.html
 load 1026714.html
 pref(dom.webcomponents.enabled,true) load 1029710.html
 HTTP(..) load xhr_abortinprogress.html
 load xhr_empty_datauri.html
 load xhr_html_nullresponse.html
+load structured_clone_container_throws.html
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/structured_clone_container_throws.html
@@ -0,0 +1,9 @@
+<iframe></iframe>
+<script>
+try { frames[0].history.pushState({ dummy: function() {} }, ''); }
+catch (e) {}
+var doc = frames[0].document;
+var s = doc.createElement("script");
+s.textContent = "1";
+doc.body.appendChild(s);
+</script>
--- a/dom/base/nsStructuredCloneContainer.cpp
+++ b/dom/base/nsStructuredCloneContainer.cpp
@@ -37,38 +37,29 @@ nsStructuredCloneContainer::nsStructured
 }
 
 nsStructuredCloneContainer::~nsStructuredCloneContainer()
 {
   free(mData);
 }
 
 nsresult
-nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData)
+nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData,
+                                          JSContext* aCx)
 {
   NS_ENSURE_STATE(!mData);
 
   uint64_t* jsBytes = nullptr;
   bool success = false;
   if (aData.isPrimitive()) {
-    // |aData| is a primitive, so the structured clone algorithm won't run
-    // script and we can just use AutoJSAPI.
-    dom::AutoJSAPI jsapi;
-    jsapi.Init();
-    success = JS_WriteStructuredClone(jsapi.cx(), aData, &jsBytes, &mSize,
+    success = JS_WriteStructuredClone(aCx, aData, &jsBytes, &mSize,
                                       nullptr, nullptr,
                                       JS::UndefinedHandleValue);
   } else {
-    // |aData| is an object and the structured clone algorithm can run script as
-    // part of the "own" "deep clone" sub-steps, so we need an AutoEntryScript.
-    // http://www.whatwg.org/specs/web-apps/current-work/#internal-structured-cloning-algorithm
-    nsIGlobalObject* nativeGlobal =
-      xpc::NativeGlobal(js::GetGlobalForObjectCrossCompartment(&aData.toObject()));
-    dom::AutoEntryScript aes(nativeGlobal);
-    success = JS_WriteStructuredClone(aes.cx(), aData, &jsBytes, &mSize,
+    success = JS_WriteStructuredClone(aCx, aData, &jsBytes, &mSize,
                                       nullptr, nullptr,
                                       JS::UndefinedHandleValue);
   }
   NS_ENSURE_STATE(success);
   NS_ENSURE_STATE(jsBytes);
 
   // Copy jsBytes into our own buffer.
   mData = (uint64_t*) malloc(mSize);
--- a/dom/interfaces/base/nsIStructuredCloneContainer.idl
+++ b/dom/interfaces/base/nsIStructuredCloneContainer.idl
@@ -14,32 +14,32 @@ interface nsIDocument;
 #include "js/TypeDecls.h"
 %}
 
 /**
  * This interface acts as a container for an object serialized using the
  * structured clone algorithm.
  *
  * You can copy an object into an nsIStructuredCloneContainer using
- * initFromVariant or initFromBase64.  It's an error to initialize an
+ * initFromJSVal or initFromBase64.  It's an error to initialize an
  * nsIStructuredCloneContainer more than once.
  *
  * Once you've initialized the container, you can get a copy of the object it
  * stores by calling deserializeToVariant.  You can also get a base-64-encoded
  * string containing a copy of the container's serialized data, using
  * getDataAsBase64.
  */
-[scriptable, uuid(8144021a-7f8a-483a-a0f1-ca02b761403f)]
+[scriptable, uuid(63eeafec-63f5-42c3-aea9-5c04678784e7)]
 interface nsIStructuredCloneContainer : nsISupports
 {
   /**
    * Initialize this structured clone container so it contains a clone of the
    * given jsval.
    */
-  [noscript]
+  [noscript, implicit_jscontext]
   void initFromJSVal(in jsval aData);
 
   /**
    * Initialize this structured clone container from a base-64-encoded byte
    * stream, stored in aData.  aFormatVersion should be the version of the
    * structured clone algorithm which was used to generate aData.
    */
   [implicit_jscontext]
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -922,17 +922,17 @@ Notification::GetData(JSContext* aCx,
 void
 Notification::InitFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aData,
                             ErrorResult& aRv)
 {
   if (mDataObjectContainer || aData.isNull()) {
     return;
   }
   mDataObjectContainer = new nsStructuredCloneContainer();
-  aRv = mDataObjectContainer->InitFromJSVal(aData);
+  aRv = mDataObjectContainer->InitFromJSVal(aData, aCx);
 }
 
 void Notification::InitFromBase64(JSContext* aCx, const nsAString& aData,
                                   ErrorResult& aRv)
 {
   if (mDataObjectContainer || aData.IsEmpty()) {
     return;
   }
--- a/testing/web-platform/meta/html/browsers/history/the-history-interface/001.html.ini
+++ b/testing/web-platform/meta/html/browsers/history/the-history-interface/001.html.ini
@@ -15,12 +15,8 @@
   [pushState must not be allowed to create cross-origin URLs (data:URI)]
     expected: FAIL
 
   [pushState must remove any tasks queued by the history traversal task source]
     expected: FAIL
 
   [history.state should be a separate clone of the object, not a reference to the object passed to the event handler]
     expected: FAIL
-
-  [security errors are expected to be thrown in the context of the document that owns the history object (2)]
-    expected: FAIL
-
--- a/testing/web-platform/meta/html/browsers/history/the-history-interface/002.html.ini
+++ b/testing/web-platform/meta/html/browsers/history/the-history-interface/002.html.ini
@@ -18,12 +18,8 @@
   [replaceState must not remove any tasks queued by the history traversal task source]
     expected: FAIL
 
   [.go must queue a task with the history traversal task source (run asynchronously)]
     expected: FAIL
 
   [history.state should be a separate clone of the object, not a reference to the object passed to the event handler]
     expected: FAIL
-
-  [security errors are expected to be thrown in the context of the document that owns the history object (2)]
-    expected: FAIL
-