Bug 1516482 - part1 : save user gesture activation flag in top level browsing context r=nika

This patch moves the user gesture activation flag from saving in document to saving in browsing context. The flag would be saved in the top level browsing context and then every time we need to check for that flag, we will request it from top level browsing context.

Differential Revision: https://phabricator.services.mozilla.com/D15435

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Alastor Wu 2019-01-14 23:09:42 +00:00
Родитель 869afb0d73
Коммит 71c03664cd
4 изменённых файлов: 78 добавлений и 30 удалений

Просмотреть файл

@ -29,6 +29,11 @@
namespace mozilla {
namespace dom {
extern mozilla::LazyLogModule gUserInteractionPRLog;
#define USER_ACTIVATION_LOG(msg, ...) \
MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
static LazyLogModule gBrowsingContextLog("BrowsingContext");
static StaticAutoPtr<BrowsingContext::Children> sRootBrowsingContexts;
@ -64,6 +69,14 @@ static void Sync(BrowsingContext* aBrowsingContext) {
aBrowsingContext->Name());
}
BrowsingContext* BrowsingContext::TopLevelBrowsingContext() {
BrowsingContext* bc = this;
while (bc->mParent) {
bc = bc->mParent;
}
return bc;
}
/* static */ void BrowsingContext::Init() {
if (!sRootBrowsingContexts) {
sRootBrowsingContexts = new BrowsingContext::Children();
@ -156,7 +169,8 @@ BrowsingContext::BrowsingContext(BrowsingContext* aParent,
mParent(aParent),
mOpener(aOpener),
mName(aName),
mClosed(false) {
mClosed(false),
mIsActivatedByUserGesture(false) {
if (mParent) {
mBrowsingContextGroup = mParent->mBrowsingContextGroup;
} else if (mOpener) {
@ -308,6 +322,27 @@ JSObject* BrowsingContext::WrapObject(JSContext* aCx,
return BrowsingContext_Binding::Wrap(aCx, this, aGivenProto);
}
void BrowsingContext::NotifyUserGestureActivation() {
// We would set the user gesture activation flag on the top level browsing
// context, which would automatically be sync to other top level browsing
// contexts which are in the different process.
RefPtr<BrowsingContext> topLevelBC = TopLevelBrowsingContext();
topLevelBC->SetUserGestureActivation();
// TODO(alwu) : sync the value to ChromeBrowsingContext.
}
void BrowsingContext::SetUserGestureActivation() {
MOZ_ASSERT(!mParent, "Set user activation flag on non top-level context!");
USER_ACTIVATION_LOG(
"Set user gesture activation for browsing context 0x%08" PRIx64, Id());
mIsActivatedByUserGesture = true;
}
bool BrowsingContext::GetUserGestureActivation() {
RefPtr<BrowsingContext> topLevelBC = TopLevelBrowsingContext();
return topLevelBC->mIsActivatedByUserGesture;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(BrowsingContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContext)

Просмотреть файл

@ -140,6 +140,18 @@ class BrowsingContext : public nsWrapperCache,
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
// This function would be called when its corresponding document is activated
// by user gesture, and we would set the flag in the top level browsing
// context.
void NotifyUserGestureActivation();
// This function would only be called in the top level browsing context. It
// would set the user gesture activation flag.
void SetUserGestureActivation();
// Return true if it corresponding document is activated by user gesture.
bool GetUserGestureActivation();
// Return the window proxy object that corresponds to this browsing context.
inline JSObject* GetWindowProxy() const { return mWindowProxy; }
// Set the window proxy object that corresponds to this browsing context.
@ -204,6 +216,8 @@ class BrowsingContext : public nsWrapperCache,
// reach its browsing context anymore.
void ClearWindowProxy() { mWindowProxy = nullptr; }
BrowsingContext* TopLevelBrowsingContext();
// Type of BrowsingContent
const Type mType;
@ -222,6 +236,10 @@ class BrowsingContext : public nsWrapperCache,
// objectMoved hook and clear it from its finalize hook.
JS::Heap<JSObject*> mWindowProxy;
bool mClosed;
// This flag is only valid in the top level browsing context, it indicates
// whether the corresponding document has been activated by user gesture.
bool mIsActivatedByUserGesture;
};
/**

Просмотреть файл

@ -311,7 +311,7 @@ typedef nsTArray<Link*> LinkArray;
static LazyLogModule gDocumentLeakPRLog("DocumentLeak");
static LazyLogModule gCspPRLog("CSP");
static LazyLogModule gUserInteractionPRLog("UserInteraction");
LazyLogModule gUserInteractionPRLog("UserInteraction");
static nsresult GetHttpChannelHelper(nsIChannel* aChannel,
nsIHttpChannel** aHttpChannel) {
@ -11666,16 +11666,29 @@ void Document::SetUserHasInteracted() {
MaybeAllowStorageForOpenerAfterUserInteraction();
}
BrowsingContext* Document::GetBrowsingContext() const {
nsPIDOMWindowOuter* outer = GetWindow();
return outer ? outer->GetBrowsingContext() : nullptr;
}
void Document::NotifyUserGestureActivation() {
// Activate this document and all documents up to the top level
// content document.
Document* doc = this;
while (doc && !doc->mUserGestureActivated) {
MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug,
("Document %p has been activated by user.", this));
doc->mUserGestureActivated = true;
doc = doc->GetSameTypeParentDocument();
if (HasBeenUserGestureActivated()) {
return;
}
RefPtr<BrowsingContext> bc = GetBrowsingContext();
if (!bc) {
return;
}
bc->NotifyUserGestureActivation();
}
bool Document::HasBeenUserGestureActivated() {
RefPtr<BrowsingContext> bc = GetBrowsingContext();
if (!bc) {
return false;
}
return bc->GetUserGestureActivation();
}
void Document::MaybeNotifyAutoplayBlocked() {
@ -11943,26 +11956,6 @@ void Document::ResetUserInteractionTimer() {
mHasUserInteractionTimerScheduled = false;
}
bool Document::HasBeenUserGestureActivated() {
if (mUserGestureActivated) {
return true;
}
// If any ancestor document is activated, so are we.
Document* doc = GetSameTypeParentDocument();
while (doc) {
if (doc->mUserGestureActivated) {
// An ancestor is also activated. Record activation on the unactivated
// sub-branch to speed up future queries.
NotifyUserGestureActivation();
break;
}
doc = doc->GetSameTypeParentDocument();
}
return mUserGestureActivated;
}
bool Document::IsExtensionPage() const {
return Preferences::GetBool("media.autoplay.allow-extension-background-pages",
true) &&

Просмотреть файл

@ -3302,6 +3302,8 @@ class Document : public nsINode,
// document in the document tree.
bool HasBeenUserGestureActivated();
BrowsingContext* GetBrowsingContext() const;
// This document is a WebExtension page, it might be a background page, a
// popup, a visible tab, a visible iframe ...e.t.c.
bool IsExtensionPage() const;