Bug 1359017 - onmessageerror for WindowEventHandlers in case StructuredClone algorithm fails when deserializing, r=masayuki, r=smaug
☠☠ backed out by 220ec1526e2f ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 12 Sep 2017 11:57:26 +0200
changeset 429773 e28d6869f6a0f6b6199c1fe404cf246986c3a929
parent 429772 65146cc073d492b94432e9ea1fd4b89e35bbf484
child 429774 cfa7187f70e26d9cc083a20ccafcfa5fee87d7a7
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [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(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(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(nsGlobalWindow* aTargetWindow,
+                                mozilla::dom::EventTarget* aEventTarget)
+{
+  MessageEventInit init;
+  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(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)