Bug 1359017 - onmessageerror for WindowEventHandlers in case StructuredClone algorithm fails when deserializing, r=masayuki, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 13 Sep 2017 05:59:06 +0200
changeset 380681 065b12d3c1f3
parent 380680 31af77b6355f
child 380682 39c093e6dda9
push id32492
push userarchaeopteryx@coole-files.de
push date2017-09-13 21:59 +0000
treeherdermozilla-central@8645a74bbbd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki, smaug
bugs1359017
milestone57.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 1359017 - onmessageerror for WindowEventHandlers in case StructuredClone algorithm fails when deserializing, r=masayuki, r=smaug
dom/base/PostMessageEvent.cpp
dom/base/PostMessageEvent.h
dom/events/EventNameList.h
dom/webidl/EventHandler.webidl
widget/EventMessageList.h
--- a/dom/base/PostMessageEvent.cpp
+++ b/dom/base/PostMessageEvent.cpp
@@ -138,60 +138,86 @@ PostMessageEvent::Run()
         nsContentUtils::eDOM_PROPERTIES,
         "TargetPrincipalDoesNotMatch",
         params, ArrayLength(params));
 
       return NS_OK;
     }
   }
 
-  ErrorResult rv;
+  IgnoredErrorResult rv;
   JS::Rooted<JS::Value> messageData(cx);
-  nsCOMPtr<nsPIDOMWindowInner> window = targetWindow->AsInner();
+  nsCOMPtr<mozilla::dom::EventTarget> eventTarget = do_QueryObject(targetWindow);
 
-  Read(window, cx, &messageData, rv);
+  Read(targetWindow->AsInner(), cx, &messageData, rv);
   if (NS_WARN_IF(rv.Failed())) {
-    return rv.StealNSResult();
+    DispatchError(cx, targetWindow, eventTarget);
+    return NS_OK;
   }
 
   // Create the event
-  nsCOMPtr<mozilla::dom::EventTarget> eventTarget = do_QueryObject(targetWindow);
-  RefPtr<MessageEvent> event =
-    new MessageEvent(eventTarget, nullptr, nullptr);
+  RefPtr<MessageEvent> event = new MessageEvent(eventTarget, nullptr, nullptr);
 
 
   Nullable<WindowProxyOrMessagePortOrServiceWorker> source;
   source.SetValue().SetAsWindowProxy() = mSource ? mSource->AsOuter() : nullptr;
 
   Sequence<OwningNonNull<MessagePort>> ports;
   if (!TakeTransferredPortsAsSequence(ports)) {
-    return NS_ERROR_OUT_OF_MEMORY;
+    DispatchError(cx, targetWindow, eventTarget);
+    return NS_OK;
   }
 
   event->InitMessageEvent(nullptr, NS_LITERAL_STRING("message"),
                           false /*non-bubbling */, false /*cancelable */,
                           messageData, mCallerOrigin,
                           EmptyString(), source, ports);
 
+  Dispatch(targetWindow, event);
+  return NS_OK;
+}
+
+void
+PostMessageEvent::DispatchError(JSContext* aCx, nsGlobalWindow* aTargetWindow,
+                                mozilla::dom::EventTarget* aEventTarget)
+{
+  RootedDictionary<MessageEventInit> init(aCx);
+  init.mBubbles = false;
+  init.mCancelable = false;
+  init.mOrigin = mCallerOrigin;
+
+  if (mSource) {
+    init.mSource.SetValue().SetAsWindowProxy() = mSource->AsOuter();
+  }
+
+  RefPtr<Event> event =
+    MessageEvent::Constructor(aEventTarget, NS_LITERAL_STRING("messageerror"),
+                              init);
+  Dispatch(aTargetWindow, event);
+}
+
+void
+PostMessageEvent::Dispatch(nsGlobalWindow* aTargetWindow, Event* aEvent)
+{
   // We can't simply call dispatchEvent on the window because doing so ends
   // up flipping the trusted bit on the event, and we don't want that to
   // happen because then untrusted content can call postMessage on a chrome
   // window if it can get a reference to it.
 
-  nsIPresShell *shell = targetWindow->GetExtantDoc()->GetShell();
+  nsIPresShell *shell = aTargetWindow->GetExtantDoc()->GetShell();
   RefPtr<nsPresContext> presContext;
-  if (shell)
+  if (shell) {
     presContext = shell->GetPresContext();
+  }
 
-  event->SetTrusted(mTrustedCaller);
-  WidgetEvent* internalEvent = event->WidgetEventPtr();
+  aEvent->SetTrusted(mTrustedCaller);
+  WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
 
   nsEventStatus status = nsEventStatus_eIgnore;
-  EventDispatcher::Dispatch(window,
+  EventDispatcher::Dispatch(aTargetWindow->AsInner(),
                             presContext,
                             internalEvent,
-                            static_cast<dom::Event*>(event.get()),
+                            aEvent,
                             &status);
-  return NS_OK;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/PostMessageEvent.h
+++ b/dom/base/PostMessageEvent.h
@@ -35,16 +35,23 @@ public:
                    nsGlobalWindow* aTargetWindow,
                    nsIPrincipal* aProvidedPrincipal,
                    nsIDocument* aSourceDocument,
                    bool aTrustedCaller);
 
 private:
   ~PostMessageEvent();
 
+  void
+  Dispatch(nsGlobalWindow* aTargetWindow, Event* aEvent);
+
+  void
+  DispatchError(JSContext* aCx, nsGlobalWindow* aTargetWindow,
+                mozilla::dom::EventTarget* aEventTarget);
+
   RefPtr<nsGlobalWindow> mSource;
   nsString mCallerOrigin;
   RefPtr<nsGlobalWindow> mTargetWindow;
   nsCOMPtr<nsIPrincipal> mProvidedPrincipal;
   nsCOMPtr<nsIDocument> mSourceDocument;
   bool mTrustedCaller;
 };
 
--- a/dom/events/EventNameList.h
+++ b/dom/events/EventNameList.h
@@ -546,16 +546,20 @@ WINDOW_EVENT(languagechange,
              eBasicEventClass)
 // XXXbz Should the onmessage attribute on <body> really not work?  If so, do we
 // need a different macro to flag things like that (IDL, but not content
 // attributes on body/frameset), or is just using EventNameType_None enough?
 WINDOW_EVENT(message,
              eMessage,
              EventNameType_None,
              eBasicEventClass)
+WINDOW_EVENT(messageerror,
+             eMessageError,
+             EventNameType_HTMLBodyOrFramesetOnly,
+             eBasicEventClass)
 WINDOW_EVENT(offline,
              eOffline,
              EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly,
              eBasicEventClass)
 WINDOW_EVENT(online,
              eOnline,
              EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly,
              eBasicEventClass)
--- a/dom/webidl/EventHandler.webidl
+++ b/dom/webidl/EventHandler.webidl
@@ -142,16 +142,17 @@ interface GlobalEventHandlers {
 [NoInterfaceObject]
 interface WindowEventHandlers {
            attribute EventHandler onafterprint;
            attribute EventHandler onbeforeprint;
            attribute OnBeforeUnloadEventHandler onbeforeunload;
            attribute EventHandler onhashchange;
            attribute EventHandler onlanguagechange;
            attribute EventHandler onmessage;
+           attribute EventHandler onmessageerror;
            attribute EventHandler onoffline;
            attribute EventHandler ononline;
            attribute EventHandler onpagehide;
            attribute EventHandler onpageshow;
            attribute EventHandler onpopstate;
            attribute EventHandler onstorage;
            attribute EventHandler onunload;
 };
--- a/widget/EventMessageList.h
+++ b/widget/EventMessageList.h
@@ -369,16 +369,17 @@ NS_EVENT_MESSAGE(eAudioComplete)
 // script notification events
 NS_EVENT_MESSAGE(eBeforeScriptExecute)
 NS_EVENT_MESSAGE(eAfterScriptExecute)
 
 NS_EVENT_MESSAGE(eBeforePrint)
 NS_EVENT_MESSAGE(eAfterPrint)
 
 NS_EVENT_MESSAGE(eMessage)
+NS_EVENT_MESSAGE(eMessageError)
 
 // Menu open event
 NS_EVENT_MESSAGE(eOpen)
 
 // Device motion and orientation
 NS_EVENT_MESSAGE(eDeviceOrientation)
 NS_EVENT_MESSAGE(eAbsoluteDeviceOrientation)
 NS_EVENT_MESSAGE(eDeviceMotion)