Bug 1428722 - part2 : move all user-activation implementation details to nsDocument.
In order to write tests, I would like to create an method that allows chorome js can directly set the user-activation flag.
Therefore, I need to move all these details into nsDocument, then we could easily simulate the user activation.
MozReview-Commit-ID: 5JrCoQc0vF7
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -13271,33 +13271,46 @@ 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)
+nsIDocument::NotifyUserActivation()
+{
+ ActivateByUserGesture();
+ // Activate parent document which has same principle on the parent chain.
+ nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
+ nsCOMPtr<nsIDocument> parent = GetSameTypeParentDocument();
+ while (parent) {
+ parent->MaybeActivateByUserGesture(principal);
+ parent = parent->GetSameTypeParentDocument();
+ }
+}
+
+void
+nsIDocument::MaybeActivateByUserGesture(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()
+ ActivateByUserGesture();
+ }
+}
+
+void
+nsIDocument::ActivateByUserGesture()
{
if (mUserHasActivatedInteraction) {
return;
}
MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug,
("Document %p has been activated by user.", this));
mUserHasActivatedInteraction = true;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -3066,31 +3066,23 @@ public:
}
void SetUserHasInteracted(bool aUserHasInteracted);
bool UserHasInteracted()
{
return mUserHasInteracted;
}
- // This would be called when document get activated by specific user gestures.
+ // This would be called when document get activated by specific user gestures
+ // and propagate the user activation flag to its parent.
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();
void ReportHasScrollLinkedEffect();
bool HasScrollLinkedEffect() const
{
return mHasScrollLinkedEffect;
@@ -3271,16 +3263,27 @@ 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();
+
+ // Return the first parent document with same pricipal, return nullptr if we
+ // can't find it.
+ nsIDocument* GetFirstParentDocumentWithSamePrincipal(nsIPrincipal* aPrincipal);
+
+ // Activate the flag 'mUserHasActivatedInteraction' by specific user gestures.
+ void ActivateByUserGesture();
+ void MaybeActivateByUserGesture(nsIPrincipal* aPrincipal);
+
// 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
@@ -917,24 +917,16 @@ EventStateManager::NotifyTargetUserActiv
if (!doc || doc->HasBeenUserActivated()) {
return;
}
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->GetSameTypeParentDocument();
- while (parent) {
- parent->MaybeNotifyUserActivation(principal);
- parent = parent->GetSameTypeParentDocument();
- }
}
void
EventStateManager::HandleQueryContentEvent(WidgetQueryContentEvent* aEvent)
{
switch (aEvent->mMessage) {
case eQuerySelectedText:
case eQueryTextContent:
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -440,16 +440,23 @@ partial interface Document {
};
// Extension to give chrome JS the ability to determine whether
// the user has interacted with the document or not.
partial interface Document {
[ChromeOnly] readonly attribute boolean userHasInteracted;
};
+// Extension to give chrome JS the ability to simulate activate the docuement
+// by user gesture.
+partial interface Document {
+ [ChromeOnly]
+ void notifyUserActivation();
+};
+
// Extension to give chrome and XBL JS the ability to determine whether
// the document is sandboxed without permission to run scripts
// and whether inline scripts are blocked by the document's CSP.
partial interface Document {
[Func="IsChromeOrXBL"] readonly attribute boolean hasScriptsBlockedBySandbox;
[Func="IsChromeOrXBL"] readonly attribute boolean inlineScriptAllowedByCSP;
};