зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
57367d9eb4
Коммит
503713f913
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче