mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-28 21:28:55 +00:00
Bug 787131. Move management of primary content state stuff from the nsSubDocumentFrame into the nsFrameLoader, so it works on display:none elements. r=jlebar
This commit is contained in:
parent
d7c07b26b1
commit
25a4faafba
@ -91,6 +91,10 @@
|
||||
|
||||
#include "mozilla/dom/StructuredCloneUtils.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPopupManager.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::layers;
|
||||
@ -306,6 +310,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
|
||||
, mClipSubdocument(true)
|
||||
, mClampScrollPosition(true)
|
||||
, mRemoteBrowserInitialized(false)
|
||||
, mObservingOwnerContent(false)
|
||||
, mCurrentRemoteFrame(nullptr)
|
||||
, mRemoteBrowser(nullptr)
|
||||
, mRenderMode(RENDER_MODE_DEFAULT)
|
||||
@ -657,29 +662,24 @@ SetTreeOwnerAndChromeEventHandlerOnDocshellTree(nsIDocShellTreeItem* aItem,
|
||||
/**
|
||||
* Set the type of the treeitem and hook it up to the treeowner.
|
||||
* @param aItem the treeitem we're working with
|
||||
* @param aOwningContent the content node that owns aItem
|
||||
* @param aTreeOwner the relevant treeowner; might be null
|
||||
* @param aParentType the nsIDocShellTreeItem::GetType of our parent docshell
|
||||
* @param aParentNode if non-null, the docshell we should be added as a child to
|
||||
*
|
||||
* @return whether aItem is top-level content
|
||||
*/
|
||||
static bool
|
||||
AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, nsIContent* aOwningContent,
|
||||
nsIDocShellTreeOwner* aOwner, int32_t aParentType,
|
||||
nsIDocShellTreeNode* aParentNode)
|
||||
bool
|
||||
nsFrameLoader::AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeOwner* aOwner,
|
||||
int32_t aParentType,
|
||||
nsIDocShellTreeNode* aParentNode)
|
||||
{
|
||||
NS_PRECONDITION(aItem, "Must have docshell treeitem");
|
||||
NS_PRECONDITION(aOwningContent, "Must have owning content");
|
||||
NS_PRECONDITION(mOwnerContent, "Must have owning content");
|
||||
|
||||
nsAutoString value;
|
||||
bool isContent = false;
|
||||
|
||||
if (aOwningContent->IsXUL()) {
|
||||
aOwningContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
|
||||
} else {
|
||||
aOwningContent->GetAttr(kNameSpaceID_None, nsGkAtoms::mozframetype, value);
|
||||
}
|
||||
mOwnerContent->GetAttr(kNameSpaceID_None, TypeAttrName(), value);
|
||||
|
||||
// we accept "content" and "content-xxx" values.
|
||||
// at time of writing, we expect "xxx" to be "primary" or "targetable", but
|
||||
@ -692,7 +692,7 @@ AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, nsIContent* aOwningContent,
|
||||
// Force mozbrowser frames to always be typeContent, even if the
|
||||
// mozbrowser interfaces are disabled.
|
||||
nsCOMPtr<nsIDOMMozBrowserFrame> mozbrowser =
|
||||
do_QueryInterface(aOwningContent);
|
||||
do_QueryInterface(mOwnerContent);
|
||||
if (mozbrowser) {
|
||||
bool isMozbrowser = false;
|
||||
mozbrowser->GetMozbrowser(&isMozbrowser);
|
||||
@ -725,6 +725,8 @@ AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem, nsIContent* aOwningContent,
|
||||
if (aOwner) {
|
||||
bool is_targetable = is_primary ||
|
||||
value.LowerCaseEqualsLiteral("content-targetable");
|
||||
mOwnerContent->AddMutationObserver(this);
|
||||
mObservingOwnerContent = true;
|
||||
aOwner->ContentShellAdded(aItem, is_primary, is_targetable, value);
|
||||
}
|
||||
}
|
||||
@ -1205,10 +1207,15 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(otherTreeItem, ourOwner,
|
||||
ourChromeEventHandler);
|
||||
|
||||
AddTreeItemToTreeOwner(ourTreeItem, otherContent, otherOwner,
|
||||
otherParentType, nullptr);
|
||||
AddTreeItemToTreeOwner(otherTreeItem, ourContent, ourOwner, ourParentType,
|
||||
nullptr);
|
||||
// Switch the owner content before we start calling AddTreeItemToTreeOwner.
|
||||
// Note that we rely on this to deal with setting mObservingOwnerContent to
|
||||
// false and calling RemoveMutationObserver as needed.
|
||||
SetOwnerContent(otherContent);
|
||||
aOther->SetOwnerContent(ourContent);
|
||||
|
||||
AddTreeItemToTreeOwner(ourTreeItem, otherOwner, otherParentType, nullptr);
|
||||
aOther->AddTreeItemToTreeOwner(otherTreeItem, ourOwner, ourParentType,
|
||||
nullptr);
|
||||
|
||||
// SetSubDocumentFor nulls out parent documents on the old child doc if a
|
||||
// new non-null document is passed in, so just go ahead and remove both
|
||||
@ -1222,9 +1229,6 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
||||
ourWindow->SetFrameElementInternal(otherFrameElement);
|
||||
otherWindow->SetFrameElementInternal(ourFrameElement);
|
||||
|
||||
SetOwnerContent(otherContent);
|
||||
aOther->SetOwnerContent(ourContent);
|
||||
|
||||
nsRefPtr<nsFrameMessageManager> ourMessageManager = mMessageManager;
|
||||
nsRefPtr<nsFrameMessageManager> otherMessageManager = aOther->mMessageManager;
|
||||
// Swap pointers in child message managers.
|
||||
@ -1383,6 +1387,10 @@ nsFrameLoader::GetDepthTooGreat(bool* aDepthTooGreat)
|
||||
void
|
||||
nsFrameLoader::SetOwnerContent(Element* aContent)
|
||||
{
|
||||
if (mObservingOwnerContent) {
|
||||
mObservingOwnerContent = false;
|
||||
mOwnerContent->RemoveMutationObserver(this);
|
||||
}
|
||||
mOwnerContent = aContent;
|
||||
if (RenderFrameParent* rfp = GetCurrentRemoteFrame()) {
|
||||
rfp->OwnerContentChanged(aContent);
|
||||
@ -1559,8 +1567,8 @@ nsFrameLoader::MaybeCreateDocShell()
|
||||
parentAsItem->GetTreeOwner(getter_AddRefs(parentTreeOwner));
|
||||
NS_ENSURE_STATE(parentTreeOwner);
|
||||
mIsTopLevelContent =
|
||||
AddTreeItemToTreeOwner(docShellAsItem, mOwnerContent, parentTreeOwner,
|
||||
parentType, parentAsNode);
|
||||
AddTreeItemToTreeOwner(docShellAsItem, parentTreeOwner, parentType,
|
||||
parentAsNode);
|
||||
|
||||
// Make sure all shells have links back to the content element
|
||||
// in the nearest enclosing chrome shell.
|
||||
@ -2404,3 +2412,78 @@ nsFrameLoader::GetDetachedSubdocView(nsIDocument** aContainerDoc) const
|
||||
return mDetachedSubdocViews;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsFrameLoader::AttributeChanged(nsIDocument* aDocument,
|
||||
mozilla::dom::Element* aElement,
|
||||
int32_t aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
int32_t aModType)
|
||||
{
|
||||
MOZ_ASSERT(mObservingOwnerContent);
|
||||
// TODO: Implement ContentShellAdded for remote browsers (bug 658304)
|
||||
MOZ_ASSERT(!mRemoteBrowser);
|
||||
|
||||
if (aNameSpaceID != kNameSpaceID_None || aAttribute != TypeAttrName()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aElement != mOwnerContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: This logic duplicates a lot of logic in
|
||||
// MaybeCreateDocshell. We should fix that.
|
||||
|
||||
// Notify our enclosing chrome that our type has changed. We only do this
|
||||
// if our parent is chrome, since in all other cases we're random content
|
||||
// subframes and the treeowner shouldn't worry about us.
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
|
||||
if (!docShellAsItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
docShellAsItem->GetParent(getter_AddRefs(parentItem));
|
||||
if (!parentItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t parentType;
|
||||
parentItem->GetItemType(&parentType);
|
||||
|
||||
if (parentType != nsIDocShellTreeItem::typeChrome) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
|
||||
parentItem->GetTreeOwner(getter_AddRefs(parentTreeOwner));
|
||||
if (!parentTreeOwner) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString value;
|
||||
aElement->GetAttr(kNameSpaceID_None, TypeAttrName(), value);
|
||||
|
||||
bool is_primary = value.LowerCaseEqualsLiteral("content-primary");
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
// when a content panel is no longer primary, hide any open popups it may have
|
||||
if (!is_primary) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm)
|
||||
pm->HidePopupsInDocShell(docShellAsItem);
|
||||
}
|
||||
#endif
|
||||
|
||||
parentTreeOwner->ContentShellRemoved(docShellAsItem);
|
||||
if (value.LowerCaseEqualsLiteral("content") ||
|
||||
StringBeginsWith(value, NS_LITERAL_STRING("content-"),
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
bool is_targetable = is_primary ||
|
||||
value.LowerCaseEqualsLiteral("content-targetable");
|
||||
|
||||
parentTreeOwner->ContentShellAdded(docShellAsItem, is_primary,
|
||||
is_targetable, value);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "FrameMetrics.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
|
||||
class nsIURI;
|
||||
class nsSubDocumentFrame;
|
||||
@ -29,6 +30,9 @@ class nsIView;
|
||||
class nsIInProcessContentFrameMessageManager;
|
||||
class AutoResetInShow;
|
||||
class nsITabParent;
|
||||
class nsIDocShellTreeItem;
|
||||
class nsIDocShellTreeOwner;
|
||||
class nsIDocShellTreeNode;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -135,7 +139,8 @@ private:
|
||||
|
||||
|
||||
class nsFrameLoader MOZ_FINAL : public nsIFrameLoader,
|
||||
public nsIContentViewManager
|
||||
public nsIContentViewManager,
|
||||
public nsStubMutationObserver
|
||||
{
|
||||
friend class AutoResetInShow;
|
||||
typedef mozilla::dom::PBrowserParent PBrowserParent;
|
||||
@ -166,6 +171,7 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameLoader, nsIFrameLoader)
|
||||
NS_DECL_NSIFRAMELOADER
|
||||
NS_DECL_NSICONTENTVIEWMANAGER
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||
NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI);
|
||||
nsresult ReallyStartLoading();
|
||||
void Finalize();
|
||||
@ -337,9 +343,19 @@ private:
|
||||
// Tell the remote browser that it's now "virtually visible"
|
||||
bool ShowRemoteFrame(const nsIntSize& size);
|
||||
|
||||
bool AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeOwner* aOwner,
|
||||
int32_t aParentType,
|
||||
nsIDocShellTreeNode* aParentNode);
|
||||
|
||||
nsIAtom* TypeAttrName() const {
|
||||
return mOwnerContent->IsXUL() ? nsGkAtoms::type : nsGkAtoms::mozframetype;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
nsCOMPtr<nsIURI> mURIToLoad;
|
||||
mozilla::dom::Element* mOwnerContent; // WEAK
|
||||
|
||||
public:
|
||||
// public because a callback needs these.
|
||||
nsRefPtr<nsFrameMessageManager> mMessageManager;
|
||||
@ -373,6 +389,7 @@ private:
|
||||
bool mClipSubdocument : 1;
|
||||
bool mClampScrollPosition : 1;
|
||||
bool mRemoteBrowserInitialized : 1;
|
||||
bool mObservingOwnerContent : 1;
|
||||
|
||||
// XXX leaking
|
||||
nsCOMPtr<nsIObserver> mChildHost;
|
||||
|
@ -54,10 +54,6 @@
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPopupManager.h"
|
||||
#endif
|
||||
|
||||
// For Accessibility
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "nsAccessibilityService.h"
|
||||
@ -703,76 +699,6 @@ nsSubDocumentFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
if (frameloader)
|
||||
frameloader->MarginsChanged(margins.width, margins.height);
|
||||
}
|
||||
else if (aAttribute == nsGkAtoms::type) {
|
||||
if (!mFrameLoader)
|
||||
return NS_OK;
|
||||
|
||||
if (!mContent->IsXUL()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mFrameLoader->GetRemoteBrowser()) {
|
||||
// TODO: Implement ContentShellAdded for remote browsers (bug 658304)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Note: This logic duplicates a lot of logic in
|
||||
// nsFrameLoader::EnsureDocShell. We should fix that.
|
||||
|
||||
// Notify our enclosing chrome that our type has changed. We only do this
|
||||
// if our parent is chrome, since in all other cases we're random content
|
||||
// subframes and the treeowner shouldn't worry about us.
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell;
|
||||
mFrameLoader->GetDocShell(getter_AddRefs(docShell));
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(docShell));
|
||||
if (!docShellAsItem) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
docShellAsItem->GetParent(getter_AddRefs(parentItem));
|
||||
if (!parentItem) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t parentType;
|
||||
parentItem->GetItemType(&parentType);
|
||||
|
||||
if (parentType != nsIDocShellTreeItem::typeChrome) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
|
||||
parentItem->GetTreeOwner(getter_AddRefs(parentTreeOwner));
|
||||
if (parentTreeOwner) {
|
||||
nsAutoString value;
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
|
||||
|
||||
bool is_primary = value.LowerCaseEqualsLiteral("content-primary");
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
// when a content panel is no longer primary, hide any open popups it may have
|
||||
if (!is_primary) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm)
|
||||
pm->HidePopupsInDocShell(docShellAsItem);
|
||||
}
|
||||
#endif
|
||||
|
||||
parentTreeOwner->ContentShellRemoved(docShellAsItem);
|
||||
|
||||
if (value.LowerCaseEqualsLiteral("content") ||
|
||||
StringBeginsWith(value, NS_LITERAL_STRING("content-"),
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
bool is_targetable = is_primary ||
|
||||
value.LowerCaseEqualsLiteral("content-targetable");
|
||||
|
||||
parentTreeOwner->ContentShellAdded(docShellAsItem, is_primary,
|
||||
is_targetable, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user