Bug 1423208 - Queue pending RenderLayers calls when there are DocShell creation blockers. r?mystor
MozReview-Commit-ID: H4MqkWnfCkF
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -432,16 +432,19 @@ TabChild::TabChild(nsIContentChild* aMan
#if defined(XP_WIN) && defined(ACCESSIBILITY)
, mNativeWindowHandle(0)
#endif
#if defined(ACCESSIBILITY)
, mTopLevelDocAccessibleChild(nullptr)
#endif
, mPendingDocShellIsActive(false)
, mPendingDocShellReceivedMessage(false)
+ , mPendingRenderLayers(false)
+ , mPendingRenderLayersReceivedMessage(false)
+ , mPendingLayerObserverEpoch(0)
, mPendingDocShellBlockers(0)
, mWidgetNativeData(0)
{
mozilla::HoldJSObjects(this);
nsWeakPtr weakPtrThis(do_GetWeakReference(static_cast<nsITabChild*>(this))); // for capture by the lambda
mSetAllowedTouchBehaviorCallback = [weakPtrThis](uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aFlags)
@@ -2658,16 +2661,20 @@ TabChild::AddPendingDocShellBlocker()
void
TabChild::RemovePendingDocShellBlocker()
{
mPendingDocShellBlockers--;
if (!mPendingDocShellBlockers && mPendingDocShellReceivedMessage) {
mPendingDocShellReceivedMessage = false;
InternalSetDocShellIsActive(mPendingDocShellIsActive);
}
+ if (!mPendingDocShellBlockers && mPendingRenderLayersReceivedMessage) {
+ mPendingRenderLayersReceivedMessage = false;
+ RecvRenderLayers(mPendingRenderLayers, mPendingLayerObserverEpoch);
+ }
}
void
TabChild::InternalSetDocShellIsActive(bool aIsActive)
{
// docshell is consider prerendered only if not active yet
mIsPrerendered &= !aIsActive;
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
@@ -2691,16 +2698,23 @@ TabChild::RecvSetDocShellIsActive(const
InternalSetDocShellIsActive(aIsActive);
return IPC_OK();
}
mozilla::ipc::IPCResult
TabChild::RecvRenderLayers(const bool& aEnabled, const uint64_t& aLayerObserverEpoch)
{
+ if (mPendingDocShellBlockers > 0) {
+ mPendingRenderLayersReceivedMessage = true;
+ mPendingRenderLayers = aEnabled;
+ mPendingLayerObserverEpoch = aLayerObserverEpoch;
+ return IPC_OK();
+ }
+
// Since requests to change the rendering state come in from both the hang
// monitor channel and the PContent channel, we have an ordering problem. This
// code ensures that we respect the order in which the requests were made and
// ignore stale requests.
if (mLayerObserverEpoch >= aLayerObserverEpoch) {
return IPC_OK();
}
mLayerObserverEpoch = aLayerObserverEpoch;
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -978,18 +978,30 @@ private:
uintptr_t mNativeWindowHandle;
#endif // defined(XP_WIN)
#if defined(ACCESSIBILITY)
PDocAccessibleChild* mTopLevelDocAccessibleChild;
#endif
bool mCoalesceMouseMoveEvents;
+ // In some circumstances, a DocShell might be in a state where it is
+ // "blocked", and we should not attempt to change its active state or
+ // the underlying PresShell state until the DocShell becomes unblocked.
+ // It is possible, however, for the parent process to send commands to
+ // change those states while the DocShell is blocked. We store those
+ // states temporarily as "pending", and only apply them once the DocShell
+ // is no longer blocked.
bool mPendingDocShellIsActive;
bool mPendingDocShellReceivedMessage;
+ bool mPendingRenderLayers;
+ bool mPendingRenderLayersReceivedMessage;
+ uint64_t mPendingLayerObserverEpoch;
+ // When mPendingDocShellBlockers is greater than 0, the DocShell is blocked,
+ // and once it reaches 0, it is no longer blocked.
uint32_t mPendingDocShellBlockers;
WindowsHandle mWidgetNativeData;
// This state is used to keep track of the current visible tabs (the ones rendering
// layers). There may be more than one if there are multiple browser windows open, or
// tabs are being warmed up. There may be none if this process does not host any
// visible or warming tabs.