Bug 1342297 - Add support for <iframe useContentEventHandling=true>. r=smaug draft
authorTim Nguyen <ntim.bugs@gmail.com>
Sat, 25 Feb 2017 13:12:34 +0000
changeset 489661 94e9bdb6ee05875eaea715d64a237cbfce501abc
parent 488960 8d35b6c817c2e53e954755cdd1584c2911a33209
child 489662 31fcecf320f528a0f56f1c05b18afede7780cd73
push id46875
push userbmo:ntim.bugs@gmail.com
push dateSat, 25 Feb 2017 13:15:07 +0000
reviewerssmaug
bugs1342297
milestone54.0a1
Bug 1342297 - Add support for <iframe useContentEventHandling=true>. r=smaug MozReview-Commit-ID: APNwd2v17PG
dom/base/nsFrameLoader.cpp
dom/base/nsGkAtomList.h
dom/base/nsGlobalWindow.cpp
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -1705,16 +1705,23 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   nsCOMPtr<nsPIDOMWindowOuter> ourWindow = ourDocshell->GetWindow();
   nsCOMPtr<nsPIDOMWindowOuter> otherWindow = otherDocshell->GetWindow();
 
   nsCOMPtr<Element> ourFrameElement =
     ourWindow->GetFrameElementInternal();
   nsCOMPtr<Element> otherFrameElement =
     otherWindow->GetFrameElementInternal();
 
+  NS_ENSURE_STATE(ourFrameElement->AttrValueIs(kNameSpaceID_None,
+                                               nsGkAtoms::useContentEventHandling,
+                                               nsGkAtoms::_true, eCaseMatters) ==
+                  otherFrameElement->AttrValueIs(kNameSpaceID_None,
+                                               nsGkAtoms::useContentEventHandling,
+                                               nsGkAtoms::_true, eCaseMatters));
+
   nsCOMPtr<EventTarget> ourChromeEventHandler =
     do_QueryInterface(ourWindow->GetChromeEventHandler());
   nsCOMPtr<EventTarget> otherChromeEventHandler =
     do_QueryInterface(otherWindow->GetChromeEventHandler());
 
   nsCOMPtr<EventTarget> ourEventTarget = ourWindow->GetParentTarget();
   nsCOMPtr<EventTarget> otherEventTarget = otherWindow->GetParentTarget();
 
@@ -1823,20 +1830,25 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   ourParentItem->AddChild(otherDocshell);
   otherParentItem->AddChild(ourDocshell);
 
   // Restore the correct chrome event handlers.
   ourDocshell->SetChromeEventHandler(otherChromeEventHandler);
   otherDocshell->SetChromeEventHandler(ourChromeEventHandler);
   // Restore the correct treeowners
   // (and also chrome event handlers for content frames only).
+  bool wantsContentEventHandling =
+    ourType == nsIDocShellTreeItem::typeContent ||
+    !ourFrameElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::useContentEventHandling,
+                                  nsGkAtoms::_true, eCaseMatters);
+
   SetTreeOwnerAndChromeEventHandlerOnDocshellTree(ourDocshell, otherOwner,
-    ourType == nsIDocShellTreeItem::typeContent ? otherChromeEventHandler.get() : nullptr);
+    wantsContentEventHandling ? otherChromeEventHandler.get() : nullptr);
   SetTreeOwnerAndChromeEventHandlerOnDocshellTree(otherDocshell, ourOwner,
-    ourType == nsIDocShellTreeItem::typeContent ? ourChromeEventHandler.get() : nullptr);
+    wantsContentEventHandling ? ourChromeEventHandler.get() : nullptr);
 
   // Switch the owner content before we start calling AddTreeItemToTreeOwner.
   // Note that we rely on this to deal with setting mObservingOwnerContent to
   // false and calling RemoveMutationObserver as needed.
   SetOwnerContent(otherContent);
   aOther->SetOwnerContent(ourContent);
 
   AddTreeItemToTreeOwner(ourDocshell, otherOwner, otherParentType, nullptr);
@@ -2341,17 +2353,19 @@ nsFrameLoader::MaybeCreateDocShell()
   NS_ENSURE_STATE(parentTreeOwner);
   mIsTopLevelContent =
     AddTreeItemToTreeOwner(mDocShell, parentTreeOwner, parentType, docShell);
 
   // Make sure all shells have links back to the content element
   // in the nearest enclosing chrome shell.
   nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
 
-  if (parentType == nsIDocShellTreeItem::typeChrome) {
+  if (parentType == nsIDocShellTreeItem::typeChrome &&
+      !mOwnerContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::useContentEventHandling,
+                                  nsGkAtoms::_true, eCaseMatters)) {
     // Our parent shell is a chrome shell. It is therefore our nearest
     // enclosing chrome shell.
 
     chromeEventHandler = do_QueryInterface(mOwnerContent);
     NS_ASSERTION(chromeEventHandler,
                  "This mContent should implement this.");
   } else {
     // Our parent shell is a content shell. Get the chrome event
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -1285,16 +1285,17 @@ GK_ATOM(ul, "ul")
 GK_ATOM(underflow, "underflow")
 GK_ATOM(undetermined, "undetermined")
 GK_ATOM(unload, "unload")
 GK_ATOM(unparsedEntityUri, "unparsed-entity-uri")
 GK_ATOM(upperFirst, "upper-first")
 GK_ATOM(uri, "uri")
 GK_ATOM(use, "use")
 GK_ATOM(useAttributeSets, "use-attribute-sets")
+GK_ATOM(useContentEventHandling, "useContentEventHandling")
 GK_ATOM(usemap, "usemap")
 GK_ATOM(user_scalable, "user-scalable")
 GK_ATOM(userInput, "userInput")
 GK_ATOM(validate, "validate")
 GK_ATOM(valign, "valign")
 GK_ATOM(value, "value")
 GK_ATOM(values, "values")
 GK_ATOM(valueOf, "value-of")
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -3770,18 +3770,20 @@ nsGlobalWindow::PostHandleEvent(EventCha
     // This is page load event since load events don't propagate to |window|.
     // @see nsDocument::GetEventTargetParent.
     mIsDocumentLoaded = true;
 
     mTimeoutManager->OnDocumentLoaded();
 
     nsCOMPtr<Element> element = GetOuterWindow()->GetFrameElementInternal();
     nsIDocShell* docShell = GetDocShell();
-    if (element && GetParentInternal() &&
-        docShell && docShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
+    if (element && GetParentInternal() && docShell &&
+        (docShell->ItemType() != nsIDocShellTreeItem::typeChrome ||
+         element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::useContentEventHandling,
+                                nsGkAtoms::_true, eCaseMatters))) {
       // If we're not in chrome, or at a chrome boundary, fire the
       // onload event for the frame element.
 
       nsEventStatus status = nsEventStatus_eIgnore;
       WidgetEvent event(aVisitor.mEvent->IsTrusted(), eLoad);
       event.mFlags.mBubbles = false;
       event.mFlags.mCancelable = false;