Bug 1516482 - part3 : reset user gesture activation flag when top level document changes. r=nika

As the user gesture activation flag is a flag which is used to reflect whether the corresponding document of browsing context has been activated by user or not, we should reset the flag when the top level window changes its document.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Alastor Wu 2019-01-14 23:21:05 +00:00
Родитель 0b67992fb9
Коммит 9ac741bd4b
7 изменённых файлов: 65 добавлений и 15 удалений

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

@ -339,6 +339,23 @@ void BrowsingContext::NotifyUserGestureActivation() {
cc->SendSetUserGestureActivation(BrowsingContextId(topLevelBC->Id()), true);
}
void BrowsingContext::NotifyResetUserGestureActivation() {
// We would reset 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();
USER_ACTIVATION_LOG("Get top level browsing context 0x%08" PRIx64,
topLevelBC->Id());
topLevelBC->ResetUserGestureActivation();
if (!XRE_IsContentProcess()) {
return;
}
auto cc = ContentChild::GetSingleton();
MOZ_ASSERT(cc);
cc->SendSetUserGestureActivation(BrowsingContextId(topLevelBC->Id()), false);
}
void BrowsingContext::SetUserGestureActivation() {
MOZ_ASSERT(!mParent, "Set user activation flag on non top-level context!");
USER_ACTIVATION_LOG(
@ -351,6 +368,13 @@ bool BrowsingContext::GetUserGestureActivation() {
return topLevelBC->mIsActivatedByUserGesture;
}
void BrowsingContext::ResetUserGestureActivation() {
MOZ_ASSERT(!mParent, "Clear user activation flag on non top-level context!");
USER_ACTIVATION_LOG(
"Reset user gesture activation for browsing context 0x%08" PRIx64, Id());
mIsActivatedByUserGesture = false;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(BrowsingContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContext)

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

@ -145,9 +145,14 @@ class BrowsingContext : public nsWrapperCache,
// context.
void NotifyUserGestureActivation();
// This function would only be called in the top level browsing context. It
// would set the user gesture activation flag.
// This function would be called when we want to reset the user gesture
// activation flag of the top level browsing context.
void NotifyResetUserGestureActivation();
// These functions would only be called in the top level browsing context.
// They would set/reset the user gesture activation flag.
void SetUserGestureActivation();
void ResetUserGestureActivation();
// Return true if it corresponding document is activated by user gesture.
bool GetUserGestureActivation();

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

@ -100,15 +100,21 @@ JSObject* ChromeBrowsingContext::WrapObject(JSContext* aCx,
return ChromeBrowsingContext_Binding::Wrap(aCx, this, aGivenProto);
}
void ChromeBrowsingContext::NotifyUserGestureActivationFromIPC() {
void ChromeBrowsingContext::NotifySetUserGestureActivationFromIPC(
bool aIsUserGestureActivation) {
if (!mCurrentWindowGlobal) {
return;
}
SetUserGestureActivation();
if (aIsUserGestureActivation) {
SetUserGestureActivation();
} else {
ResetUserGestureActivation();
}
USER_ACTIVATION_LOG("Chrome browsing context 0x%08" PRIx64
" would notify other browsing contexts for setting "
"user gesture activation.",
" would notify other browsing contexts for updating "
"user gesture activation flag.",
Id());
// XXX(alwu) : we need to sync the flag to other browsing contexts which are
// not in the same child process where the flag was set. Will implement that

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

@ -51,11 +51,13 @@ class ChromeBrowsingContext final : public BrowsingContext {
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
// This function would set its user gesture activation flag and then notify
// other browsing contexts which are not the one related with the current
// window global to set the flag. (the corresponding browsing context of the
// current global window has been set before calling this function)
void NotifyUserGestureActivationFromIPC();
// This functions would set/reset its user gesture activation flag and then
// notify other browsing contexts which are not the one related with the
// current window global to set/reset the flag. (the corresponding browsing
// context of the current global window has been set/reset before calling this
// function)
void NotifySetUserGestureActivationFromIPC(bool aIsUserGestureActivation);
protected:
void Traverse(nsCycleCollectionTraversalCallback& cb);
void Unlink();

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

@ -1599,6 +1599,14 @@ void nsGlobalWindowInner::TraceGlobalJSObject(JSTracer* aTrc) {
TraceWrapper(aTrc, "active window global");
}
bool nsGlobalWindowInner::ShouldResetBrowsingContextUserGestureActivation() {
// Reset user gesture activation flag only when the top level document changes
// and its corresponding browsing context has been activated by user gesture.
return mWindowGlobalChild && GetOuterWindowInternal() &&
GetOuterWindowInternal()->IsTopLevelWindow() && Window() &&
Window()->GetUserGestureActivation();
}
nsresult nsGlobalWindowInner::SetNewDocument(Document* aDocument,
nsISupports* aState,
bool aForceReuseInnerWindow) {
@ -1652,6 +1660,10 @@ void nsGlobalWindowInner::InnerSetNewDocument(JSContext* aCx,
mWindowGlobalChild = WindowGlobalChild::Create(this);
}
if (ShouldResetBrowsingContextUserGestureActivation()) {
Window()->NotifyResetUserGestureActivation();
}
#ifdef DEBUG
mLastOpenedURI = aDocument->GetDocumentURI();
#endif

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

@ -1255,6 +1255,10 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
void CallDocumentFlushedResolvers();
void CancelDocumentFlushedResolvers();
// Return true if we need to notify browsing context to reset its user gesture
// activation flag.
bool ShouldResetBrowsingContextUserGestureActivation();
public:
// Dispatch a runnable related to the global.
virtual nsresult Dispatch(mozilla::TaskCategory aCategory,

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

@ -5732,10 +5732,7 @@ mozilla::ipc::IPCResult ContentParent::RecvSetUserGestureActivation(
return IPC_OK();
}
if (aNewValue) {
context->NotifyUserGestureActivationFromIPC();
}
context->NotifySetUserGestureActivationFromIPC(aNewValue);
return IPC_OK();
}