Bug 1428722 - part1 : always activate the top level frame. draft
authorAlastor Wu <alwu@mozilla.com>
Mon, 08 Jan 2018 16:44:28 +0800
changeset 720212 45addc47ae092f06863cfcfc6e6da411ec02c84e
parent 720211 368f35aad8863aaa108063feeadd7787d222eabd
child 720213 088dfff9856d86b4ec4d41269f21736b3b6cec35
push id95482
push userbmo:alwu@mozilla.com
push dateMon, 15 Jan 2018 03:52:14 +0000
bugs1428722
milestone59.0a1
Bug 1428722 - part1 : always activate the top level frame. For top level frame, it should also be activated when user activate its child frame. eg. A (youtube.com) -> B (ad.com), when user activate B frame, the A frame would also be activated. MozReview-Commit-ID: BP7eGKiqYJe
dom/base/nsDocument.cpp
dom/base/nsIDocument.h
dom/events/EventStateManager.cpp
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -13271,16 +13271,32 @@ void
 nsIDocument::SetUserHasInteracted(bool aUserHasInteracted)
 {
   MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug,
           ("Document %p has been interacted by user.", this));
   mUserHasInteracted = aUserHasInteracted;
 }
 
 void
+nsIDocument::MaybeNotifyUserActivation(nsIPrincipal* aPrincipal)
+{
+  bool isEqual = false;
+  nsresult rv = aPrincipal->Equals(NodePrincipal(), &isEqual);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return;
+  }
+
+  // If a child frame is actived, it would always activate the top frame and its
+  // parent frames which has same priciple.
+  if (isEqual || IsTopLevelContentDocument()) {
+    NotifyUserActivation();
+  }
+}
+
+void
 nsIDocument::NotifyUserActivation()
 {
   if (mUserHasActivatedInteraction) {
     return;
   }
 
   MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug,
           ("Document %p has been activated by user.", this));
@@ -13302,38 +13318,37 @@ nsIDocument::HasBeenUserActivated()
 
   return mUserHasActivatedInteraction;
 }
 
 nsIDocument*
 nsIDocument::GetFirstParentDocumentWithSamePrincipal(nsIPrincipal* aPrincipal)
 {
   MOZ_ASSERT(aPrincipal);
-  nsIDocument* parent = GetSameTypeParentDocument(this);
+  nsIDocument* parent = GetSameTypeParentDocument();
   while (parent) {
     bool isEqual = false;
     nsresult rv = aPrincipal->Equals(parent->NodePrincipal(), &isEqual);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return nullptr;
     }
 
     if (isEqual) {
       return parent;
     }
-    parent = GetSameTypeParentDocument(parent);
+    parent = parent->GetSameTypeParentDocument();
   }
   MOZ_ASSERT(!parent);
   return nullptr;
 }
 
 nsIDocument*
-nsIDocument::GetSameTypeParentDocument(const nsIDocument* aDoc)
-{
-  MOZ_ASSERT(aDoc);
-  nsCOMPtr<nsIDocShellTreeItem> current = aDoc->GetDocShell();
+nsIDocument::GetSameTypeParentDocument()
+{
+  nsCOMPtr<nsIDocShellTreeItem> current = GetDocShell();
   if (!current) {
     return nullptr;
   }
 
   nsCOMPtr<nsIDocShellTreeItem> parent;
   current->GetSameTypeParent(getter_AddRefs(parent));
   if (!parent) {
     return nullptr;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -3072,16 +3072,21 @@ public:
   }
 
   // This would be called when document get activated by specific user gestures.
   void NotifyUserActivation();
 
   // Return true if document has interacted by specific user gestures.
   bool HasBeenUserActivated();
 
+  void MaybeNotifyUserActivation(nsIPrincipal* aPrincipal);
+
+  // Return the same type parent docuement if exists, or return null.
+  nsIDocument* GetSameTypeParentDocument();
+
   // Return the first parent document with same pricipal, return nullptr if we
   // can't find it.
   nsIDocument* GetFirstParentDocumentWithSamePrincipal(nsIPrincipal* aPrincipal);
 
   bool HasScriptsBlockedBySandbox();
 
   bool InlineScriptAllowedByCSP();
 
@@ -3266,19 +3271,16 @@ protected:
   // mFrameRequestCallbacksScheduled.  aOldShell should only be passed when
   // mPresShell is becoming null; in that case it will be used to get hold of
   // the relevant refresh driver.
   void UpdateFrameRequestCallbackSchedulingState(nsIPresShell* aOldShell = nullptr);
 
   // Helper for GetScrollingElement/IsScrollingElement.
   bool IsPotentiallyScrollable(mozilla::dom::HTMLBodyElement* aBody);
 
-  // Return the same type parent docuement if exists, or return null.
-  nsIDocument* GetSameTypeParentDocument(const nsIDocument* aDoc);
-
   // Helpers for GetElementsByName.
   static bool MatchNameAttribute(mozilla::dom::Element* aElement,
                                  int32_t aNamespaceID,
                                  nsAtom* aAtom, void* aData);
   static void* UseExistingNameString(nsINode* aRootNode, const nsString* aName);
 
   nsCString mReferrer;
   nsString mLastModified;
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -920,21 +920,20 @@ EventStateManager::NotifyTargetUserActiv
 
   MOZ_ASSERT(aEvent->mMessage == eKeyUp   ||
              aEvent->mMessage == eMouseUp ||
              aEvent->mMessage == eTouchEnd);
   doc->NotifyUserActivation();
 
   // Activate parent document which has same principle on the parent chain.
   nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
-  nsCOMPtr<nsIDocument> parent =
-    doc->GetFirstParentDocumentWithSamePrincipal(principal);
+  nsCOMPtr<nsIDocument> parent = doc->GetSameTypeParentDocument();
   while (parent) {
-    parent->NotifyUserActivation();
-    parent = parent->GetFirstParentDocumentWithSamePrincipal(principal);
+    parent->MaybeNotifyUserActivation(principal);
+    parent = parent->GetSameTypeParentDocument();
   }
 }
 
 void
 EventStateManager::HandleQueryContentEvent(WidgetQueryContentEvent* aEvent)
 {
   switch (aEvent->mMessage) {
     case eQuerySelectedText: