Bug 1397426 - When short-circuiting a TabParent::RenderLayers call, still fire the layer tree event if we've been preserving layers. r=billm
MozReview-Commit-ID: 7UT036vUY85
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -169,16 +169,17 @@ TabParent::TabParent(nsIContentParent* a
, mTabSetsCursor(false)
, mHasContentOpener(false)
#ifdef DEBUG
, mActiveSupressDisplayportCount(0)
#endif
, mLayerTreeEpoch(0)
, mPreserveLayers(false)
, mRenderLayers(false)
+ , mHasLayers(false)
, mHasPresented(false)
, mHasBeforeUnload(false)
, mIsMouseEnterIntoWidgetEventSuppressed(false)
{
MOZ_ASSERT(aManager);
// When the input event queue is disabled, we don't need to handle the case
// that some input events are dispatched before PBrowserConstructor.
mIsReadyToHandleInputEvents = !ContentParent::IsInputEventQueueSupported();
@@ -2946,16 +2947,31 @@ TabParent::GetIsPrerendered(bool* aIsPre
*aIsPrerendered = mIsPrerendered;
return NS_OK;
}
NS_IMETHODIMP
TabParent::RenderLayers(bool aEnabled)
{
if (aEnabled == mRenderLayers) {
+ if (aEnabled && mHasLayers && mPreserveLayers) {
+ // RenderLayers might be called when we've been preserving layers,
+ // and already had layers uploaded. In that case, the MozLayerTreeReady
+ // event will not naturally arrive, which can confuse the front-end
+ // layer. So we fire the event here.
+ RefPtr<TabParent> self = this;
+ uint64_t epoch = mLayerTreeEpoch;
+ NS_DispatchToMainThread(NS_NewRunnableFunction(
+ "dom::TabParent::RenderLayers",
+ [self, epoch] () {
+ MOZ_ASSERT(NS_IsMainThread());
+ self->LayerTreeUpdate(epoch, true);
+ }));
+ }
+
return NS_OK;
}
// Preserve layers means that attempts to stop rendering layers
// will be ignored.
if (!aEnabled && mPreserveLayers) {
return NS_OK;
}
@@ -3060,61 +3076,34 @@ TabParent::TransmitPermissionsForPrincip
NS_IMETHODIMP
TabParent::GetHasBeforeUnload(bool* aResult)
{
*aResult = mHasBeforeUnload;
return NS_OK;
}
-class LayerTreeUpdateRunnable final
- : public mozilla::Runnable
-{
- uint64_t mLayersId;
- uint64_t mEpoch;
- bool mActive;
-
-public:
- explicit LayerTreeUpdateRunnable(uint64_t aLayersId,
- uint64_t aEpoch,
- bool aActive)
- : Runnable("dom::LayerTreeUpdateRunnable")
- , mLayersId(aLayersId)
- , mEpoch(aEpoch)
- , mActive(aActive)
- {
- MOZ_ASSERT(!NS_IsMainThread());
- }
-
-private:
- NS_IMETHOD Run() override {
- MOZ_ASSERT(NS_IsMainThread());
- if (RefPtr<TabParent> tabParent = TabParent::GetTabParentFromLayersId(mLayersId)) {
- tabParent->LayerTreeUpdate(mEpoch, mActive);
- }
- return NS_OK;
- }
-};
-
void
TabParent::LayerTreeUpdate(uint64_t aEpoch, bool aActive)
{
// Ignore updates from old epochs. They might tell us that layers are
// available when we've already sent a message to clear them. We can't trust
// the update in that case since layers could disappear anytime after that.
if (aEpoch != mLayerTreeEpoch || mIsDestroyed) {
return;
}
nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement);
if (!target) {
NS_WARNING("Could not locate target for layer tree message.");
return;
}
+ mHasLayers = aActive;
+
RefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr);
if (aActive) {
mHasPresented = true;
event->InitEvent(NS_LITERAL_STRING("MozLayerTreeReady"), true, false);
} else {
event->InitEvent(NS_LITERAL_STRING("MozLayerTreeCleared"), true, false);
}
event->SetTrusted(true);
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -777,19 +777,25 @@ private:
static void RemoveTabParentFromTable(uint64_t aLayersId);
uint64_t mLayerTreeEpoch;
// If this flag is set, then the tab's layers will be preserved even when
// the tab's docshell is inactive.
bool mPreserveLayers;
- // Holds the most recent value passed to the RenderLayers function.
+ // Holds the most recent value passed to the RenderLayers function. This
+ // does not necessarily mean that the layers have finished rendering
+ // and have uploaded - for that, use mHasLayers.
bool mRenderLayers;
+ // True if the compositor has reported that the TabChild has uploaded
+ // layers.
+ bool mHasLayers;
+
// True if this TabParent has had its layer tree sent to the compositor
// at least once.
bool mHasPresented;
// True if at least one window hosted in the TabChild has added a
// beforeunload event listener.
bool mHasBeforeUnload;