Bug 1006102 - Save originAttributes in the Error object. draft
authorLuca Greco <lgreco@mozilla.com>
Mon, 06 Jun 2016 16:32:54 +0200
changeset 375739 ac94a30c4c58ee8abbf7c92ec5bcfeea3405c202
parent 374989 0c48702e8ff4cf427e443ed91630465c39f6c4ee
child 375740 b67dee7e2d3f1d049b3524ebecf899b435ec1d55
push id20366
push userluca.greco@alcacoop.it
push dateMon, 06 Jun 2016 15:45:16 +0000
bugs1006102
milestone49.0a1
Bug 1006102 - Save originAttributes in the Error object. MozReview-Commit-ID: 5x3M9fj4cRR
dom/base/ScriptSettings.cpp
js/xpconnect/idl/nsIScriptError.idl
js/xpconnect/src/nsScriptError.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/src/xpcpublic.h
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -590,16 +590,27 @@ AutoJSAPI::ReportException()
         // We run addons in a separate privileged compartment, but they still
         // expect to trigger the onerror handler of their associated DOM Window.
         win = xpc::AddonWindowOrNull(errorGlobal);
       }
       nsPIDOMWindowInner* inner = win ? win->AsInner() : nullptr;
       xpcReport->Init(jsReport.report(), jsReport.message(),
                       nsContentUtils::IsCallerChrome(),
                       inner ? inner->WindowID() : 0);
+
+      if (win) {
+        // If an error reported from AutoJSAPI has an associated window,
+        // retrieve the originAttributes and save it in the error report.
+        nsIPrincipal* winPrincipal = win->GetPrincipal();
+        if (winPrincipal) {
+          PrincipalOriginAttributes poa = BasePrincipal::Cast(winPrincipal)->OriginAttributesRef();
+          xpcReport->mOriginAttributes = poa;
+        }
+      }
+
       if (inner && jsReport.report()->errorNumber != JSMSG_OUT_OF_MEMORY) {
         DispatchScriptErrorEvent(inner, JS_GetRuntime(cx()), xpcReport, exn);
       } else {
         JS::Rooted<JSObject*> stack(cx(),
           xpc::FindExceptionStackForConsoleReport(inner, exn));
         xpcReport->LogToConsoleWithStack(stack);
       }
     } else {
--- a/js/xpconnect/idl/nsIScriptError.idl
+++ b/js/xpconnect/idl/nsIScriptError.idl
@@ -8,18 +8,21 @@
  */
 
 
 #include "nsISupports.idl"
 #include "nsIConsoleMessage.idl"
 
 %{C++
 #include "nsStringGlue.h" // for nsDependentCString
+#include "mozilla/BasePrincipal.h" // for OriginAttributesDictionary
 %}
 
+[ref] native const_OriginAttributesDictionary(const mozilla::dom::OriginAttributesDictionary);
+
 [scriptable, uuid(361be358-76f0-47aa-b37b-6ad833599e8d)]
 interface nsIScriptError : nsIConsoleMessage
 {
     /** pseudo-flag for default case */
     const unsigned long errorFlag = 0x0;
 
     /** message is warning */
     const unsigned long warningFlag = 0x1;
@@ -63,16 +66,21 @@ interface nsIScriptError : nsIConsoleMes
     /* Get the inner window id this was initialized with.  Zero will be
        returned if init() was used instead of initWithWindowID(). */
     readonly attribute unsigned long long innerWindowID;
 
     readonly attribute boolean isFromPrivateWindow;
 
     attribute jsval stack;
 
+    /** Saved originAttributes from the document principal. */
+    readonly attribute jsval originAttributes;
+    [noscript, nostdcall, binaryname(SetOriginAttributes)]
+    void binarySetOriginAttributes(in const_OriginAttributesDictionary aOriginAttributes);
+
     /**
      * The name of a template string, as found in js.msg, associated with the
      * error message.
      */
     attribute AString errorMessageName;
 
 
     void init(in AString message,
--- a/js/xpconnect/src/nsScriptError.cpp
+++ b/js/xpconnect/src/nsScriptError.cpp
@@ -48,25 +48,31 @@ nsScriptErrorBase::InitializeOnMainThrea
         nsGlobalWindow* window =
           nsGlobalWindow::GetInnerWindowWithId(mInnerWindowID);
         if (window) {
             nsPIDOMWindowOuter* outer = window->GetOuterWindow();
             if (outer)
                 mOuterWindowID = outer->WindowID();
 
             nsIDocShell* docShell = window->GetDocShell();
+            nsIPrincipal* winPrincipal = window->GetPrincipal();
             nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
 
             if (loadContext) {
                 // Never mark exceptions from chrome windows as having come from
                 // private windows, since we always want them to be reported.
-                nsIPrincipal* winPrincipal = window->GetPrincipal();
                 mIsFromPrivateWindow = loadContext->UsePrivateBrowsing() &&
                                        !nsContentUtils::IsSystemPrincipal(winPrincipal);
             }
+
+            // Save the originAttributes associated to the window selected by the innerWindowID.
+            if (winPrincipal) {
+                PrincipalOriginAttributes poa = BasePrincipal::Cast(winPrincipal)->OriginAttributesRef();
+                mOriginAttributes = poa;
+            }
         }
     }
 
     mInitializedOnMainThread = true;
 }
 
 // nsIConsoleMessage methods
 NS_IMETHODIMP
@@ -161,16 +167,33 @@ nsScriptErrorBase::GetErrorMessageName(n
 
 NS_IMETHODIMP
 nsScriptErrorBase::SetErrorMessageName(const nsAString& aErrorMessageName) {
     mMessageName = aErrorMessageName;
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsScriptErrorBase::GetOriginAttributes(JS::MutableHandleValue aOriginAttributes) {
+    dom::AutoJSAPI jsapi;
+    jsapi.Init();
+    JSContext* cx = jsapi.cx();
+    JSAutoCompartment ac(cx, xpc::UnprivilegedJunkScope());
+
+    mOriginAttributes.ToObjectInternal(cx, aOriginAttributes);
+
+    return NS_OK;
+}
+
+nsresult nsScriptErrorBase::SetOriginAttributes(const mozilla::dom::OriginAttributesDictionary & aOriginAttributes) {
+    mOriginAttributes = aOriginAttributes;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsScriptErrorBase::Init(const nsAString& message,
                         const nsAString& sourceName,
                         const nsAString& sourceLine,
                         uint32_t lineNumber,
                         uint32_t columnNumber,
                         uint32_t flags,
                         const char* category)
 {
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -274,18 +274,22 @@ xpc::ErrorReport::LogToConsoleWithStack(
     }
     errorObject->SetErrorMessageName(mErrorMsgName);
     NS_ENSURE_TRUE_VOID(consoleService && errorObject);
 
     nsresult rv = errorObject->InitWithWindowID(mErrorMsg, mFileName, mSourceLine,
                                                 mLineNumber, mColumn, mFlags,
                                                 mCategory, mWindowID);
     NS_ENSURE_SUCCESS_VOID(rv);
+
+    // Propagate the saved originAttributes from the error report to the script error
+    // object.
+    errorObject->SetOriginAttributes(mOriginAttributes);
+
     consoleService->LogMessage(errorObject);
-
 }
 
 /* static */
 void
 xpc::ErrorReport::ErrorReportToMessageString(JSErrorReport* aReport,
                                              nsAString& aString)
 {
     aString.Truncate();
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -149,16 +149,17 @@
 #include "nsDeque.h"
 
 #include "nsIScriptSecurityManager.h"
 
 #include "nsIPrincipal.h"
 #include "nsJSPrincipals.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "xpcObjectHelper.h"
+#include "mozilla/BasePrincipal.h"
 
 #include "SandboxPrivate.h"
 #include "BackstagePass.h"
 #include "nsAXPCNativeCallContext.h"
 
 #ifdef XP_WIN
 // Nasty MS defines
 #ifdef GetClassInfo
@@ -2910,16 +2911,18 @@ protected:
     nsString mSourceLine;
     uint32_t mColumnNumber;
     uint32_t mFlags;
     nsCString mCategory;
     // mOuterWindowID is set on the main thread from InitializeOnMainThread().
     uint64_t mOuterWindowID;
     uint64_t mInnerWindowID;
     int64_t mTimeStamp;
+    // Saved originAttributes from the principal origin attributes where the error happened.
+    mozilla::dom::OriginAttributesDictionary mOriginAttributes;
     // mInitializedOnMainThread and mIsFromPrivateWindow are set on the main
     // thread from InitializeOnMainThread().
     mozilla::Atomic<bool> mInitializedOnMainThread;
     bool mIsFromPrivateWindow;
 };
 
 class nsScriptError final : public nsScriptErrorBase {
 public:
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -20,16 +20,17 @@
 #include "nsWrapperCache.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "mozilla/dom/JSSlots.h"
 #include "mozilla/fallible.h"
 #include "nsMathUtils.h"
 #include "nsStringBuffer.h"
 #include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/BasePrincipal.h"
 
 class nsGlobalWindow;
 class nsIPrincipal;
 class nsScriptNameSpaceManager;
 class nsIMemoryReporterCallback;
 
 namespace mozilla {
 namespace dom {
@@ -541,16 +542,17 @@ class ErrorReport {
     nsString mErrorMsg;
     nsString mFileName;
     nsString mSourceLine;
     uint64_t mWindowID;
     uint32_t mLineNumber;
     uint32_t mColumn;
     uint32_t mFlags;
     bool mIsMuted;
+    mozilla::dom::OriginAttributesDictionary mOriginAttributes;
 
   private:
     ~ErrorReport() {}
 };
 
 void
 DispatchScriptErrorEvent(nsPIDOMWindowInner* win, JSRuntime* rt, xpc::ErrorReport* xpcReport,
                          JS::Handle<JS::Value> exception);