Bug 1353060: Use the correct layer manager for frameloaders in <popup>s. r=kats,mattwoodrow

Currently, we only correctly support remote layer trees for frameloaders that
use the same layer manager as their document. Since we need to be able to host
remote <browser> content in popup widgets for remote WebExtensions, we need to
tie the frameloaders to the layer manager of their host element, rather than
the root layer manager for the document.

MozReview-Commit-ID: 4RCsamFBiQw
This commit is contained in:
Kris Maglione 2017-04-17 21:41:18 -07:00
Родитель 57367d9eb4
Коммит 503713f913
6 изменённых файлов: 90 добавлений и 13 удалений

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

@ -6883,6 +6883,34 @@ nsContentUtils::WidgetForDocument(const nsIDocument* aDoc)
return nullptr;
}
nsIWidget*
nsContentUtils::WidgetForContent(const nsIContent* aContent)
{
nsIFrame* frame = aContent->GetPrimaryFrame();
if (frame) {
frame = nsLayoutUtils::GetDisplayRootFrame(frame);
nsView* view = frame->GetView();
if (view) {
return view->GetWidget();
}
}
return nullptr;
}
already_AddRefed<LayerManager>
nsContentUtils::LayerManagerForContent(const nsIContent *aContent)
{
nsIWidget* widget = nsContentUtils::WidgetForContent(aContent);
if (widget) {
RefPtr<LayerManager> manager = widget->GetLayerManager();
return manager.forget();
}
return nullptr;
}
static already_AddRefed<LayerManager>
LayerManagerForDocumentInternal(const nsIDocument *aDoc, bool aRequirePersistent)
{

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

@ -2037,15 +2037,29 @@ public:
* Returns the widget for this document if there is one. Looks at all ancestor
* documents to try to find a widget, so for example this can still find a
* widget for documents in display:none frames that have no presentation.
*
* You should probably use WidgetForContent() instead of this, unless you have
* a good reason to do otherwise.
*/
static nsIWidget* WidgetForDocument(const nsIDocument* aDoc);
/**
* Returns the appropriate widget for this element, if there is one. Unlike
* WidgetForDocument(), this returns the correct widget for content in popups.
*
* You should probably use this instead of WidgetForDocument().
*/
static nsIWidget* WidgetForContent(const nsIContent* aContent);
/**
* Returns a layer manager to use for the given document. Basically we
* look up the document hierarchy for the first document which has
* a presentation with an associated widget, and use that widget's
* layer manager.
*
* You should probably use LayerManagerForContent() instead of this, unless
* you have a good reason to do otherwise.
*
* @param aDoc the document for which to return a layer manager.
* @param aAllowRetaining an outparam that states whether the returned
* layer manager should be used for retained layers
@ -2053,6 +2067,16 @@ public:
static already_AddRefed<mozilla::layers::LayerManager>
LayerManagerForDocument(const nsIDocument *aDoc);
/**
* Returns a layer manager to use for the given content. Unlike
* LayerManagerForDocument(), this returns the correct layer manager for
* content in popups.
*
* You should probably use this instead of LayerManagerForDocument().
*/
static already_AddRefed<mozilla::layers::LayerManager>
LayerManagerForContent(const nsIContent *aContent);
/**
* Returns a layer manager to use for the given document. Basically we
* look up the document hierarchy for the first document which has

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

@ -1259,9 +1259,12 @@ nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
return false;
}
RefPtr<layers::LayerManager> layerManager =
nsContentUtils::LayerManagerForDocument(mOwnerContent->GetComposedDoc());
if (!layerManager) {
RenderFrameParent* rfp = GetCurrentRenderFrame();
if (!rfp) {
return false;
}
if (!rfp->AttachLayerManager()) {
// This is just not going to work.
return false;
}

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

@ -2293,7 +2293,7 @@ TabParent::RecvGetDPI(float* aValue)
{
TryCacheDPIAndScale();
MOZ_ASSERT(mDPI > 0,
MOZ_ASSERT(mDPI > 0 || mFrameElement,
"Must not ask for DPI before OwnerElement is received!");
*aValue = mDPI;
return IPC_OK();
@ -2304,7 +2304,7 @@ TabParent::RecvGetDefaultScale(double* aValue)
{
TryCacheDPIAndScale();
MOZ_ASSERT(mDefaultScale.scale > 0,
MOZ_ASSERT(mDefaultScale.scale > 0 || mFrameElement,
"Must not ask for scale before OwnerElement is received!");
*aValue = mDefaultScale.scale;
return IPC_OK();
@ -2315,7 +2315,7 @@ TabParent::RecvGetWidgetRounding(int32_t* aValue)
{
TryCacheDPIAndScale();
MOZ_ASSERT(mRounding > 0,
MOZ_ASSERT(mRounding > 0 || mFrameElement,
"Must not ask for rounding before OwnerElement is received!");
*aValue = mRounding;
return IPC_OK();
@ -2581,7 +2581,7 @@ TabParent::GetWidget() const
if (!mFrameElement) {
return nullptr;
}
nsCOMPtr<nsIWidget> widget = nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc());
nsCOMPtr<nsIWidget> widget = nsContentUtils::WidgetForContent(mFrameElement);
return widget.forget();
}

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

@ -146,6 +146,7 @@ void
RenderFrameParent::Destroy()
{
mFrameLoaderDestroyed = true;
mLayerManager = nullptr;
}
already_AddRefed<Layer>
@ -206,18 +207,35 @@ RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
return layer.forget();
}
LayerManager*
RenderFrameParent::AttachLayerManager()
{
RefPtr<LayerManager> lm;
if (mFrameLoader) {
nsIContent* content = mFrameLoader->GetOwnerContent();
if (content) {
lm = nsContentUtils::LayerManagerForContent(content);
}
}
// Perhaps the document containing this frame currently has no presentation?
if (lm && lm->GetCompositorBridgeChild() && lm != mLayerManager) {
mLayersConnected = lm->GetCompositorBridgeChild()->SendAdoptChild(mLayersId);
FrameLayerBuilder::InvalidateAllLayers(lm);
}
mLayerManager = lm.forget();
return mLayerManager;
}
void
RenderFrameParent::OwnerContentChanged(nsIContent* aContent)
{
MOZ_ASSERT(!mFrameLoader || mFrameLoader->GetOwnerContent() == aContent,
"Don't build new map if owner is same!");
RefPtr<LayerManager> lm = mFrameLoader ? GetFrom(mFrameLoader) : nullptr;
// Perhaps the document containing this frame currently has no presentation?
if (lm && lm->GetCompositorBridgeChild()) {
mLayersConnected = lm->GetCompositorBridgeChild()->SendAdoptChild(mLayersId);
FrameLayerBuilder::InvalidateAllLayers(lm);
}
Unused << AttachLayerManager();
}
void
@ -232,6 +250,7 @@ RenderFrameParent::ActorDestroy(ActorDestroyReason why)
}
mFrameLoader = nullptr;
mLayerManager = nullptr;
}
mozilla::ipc::IPCResult

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

@ -90,6 +90,8 @@ public:
void EnsureLayersConnected(CompositorOptions* aCompositorOptions);
LayerManager* AttachLayerManager();
protected:
void ActorDestroy(ActorDestroyReason why) override;
@ -114,6 +116,7 @@ private:
RefPtr<nsFrameLoader> mFrameLoader;
RefPtr<ContainerLayer> mContainer;
RefPtr<LayerManager> mLayerManager;
// True after Destroy() has been called, which is triggered
// originally by nsFrameLoader::Destroy(). After this point, we can