зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1480198 - Construct nsDocShell objects inside BrowsingContext. r=peterv
Differential Revision: https://phabricator.services.mozilla.com/D7400 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
a35bbfce87
Коммит
89cb220346
|
@ -9,14 +9,15 @@
|
|||
#include "mozilla/dom/ChromeBrowsingContext.h"
|
||||
#include "mozilla/dom/BrowsingContextBinding.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
|
@ -35,6 +36,31 @@ static StaticAutoPtr<nsDataHashtable<nsUint64HashKey, BrowsingContext*>>
|
|||
static StaticAutoPtr<nsRefPtrHashtable<nsUint64HashKey, BrowsingContext>>
|
||||
sCachedBrowsingContexts;
|
||||
|
||||
static void
|
||||
Register(BrowsingContext* aBrowsingContext)
|
||||
{
|
||||
auto entry = sBrowsingContexts->LookupForAdd(aBrowsingContext->Id());
|
||||
MOZ_RELEASE_ASSERT(!entry, "Duplicate BrowsingContext ID");
|
||||
entry.OrInsert([&] { return aBrowsingContext; });
|
||||
}
|
||||
|
||||
static void
|
||||
Sync(BrowsingContext* aBrowsingContext)
|
||||
{
|
||||
if (!XRE_IsContentProcess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto cc = ContentChild::GetSingleton();
|
||||
MOZ_DIAGNOSTIC_ASSERT(cc);
|
||||
nsAutoString name;
|
||||
aBrowsingContext->GetName(name);
|
||||
RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent();
|
||||
cc->SendAttachBrowsingContext(BrowsingContextId(parent ? parent->Id() : 0),
|
||||
BrowsingContextId(aBrowsingContext->Id()),
|
||||
name);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
BrowsingContext::Init()
|
||||
{
|
||||
|
@ -70,38 +96,86 @@ BrowsingContext::Get(uint64_t aId)
|
|||
}
|
||||
|
||||
/* static */ already_AddRefed<BrowsingContext>
|
||||
BrowsingContext::Create(nsIDocShell* aDocShell)
|
||||
BrowsingContext::Create(BrowsingContext* aParent,
|
||||
const nsAString& aName,
|
||||
Type aType)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(!aParent || aParent->mType == aType);
|
||||
|
||||
uint64_t id = nsContentUtils::GenerateBrowsingContextId();
|
||||
|
||||
MOZ_LOG(GetLog(),
|
||||
LogLevel::Debug,
|
||||
("Creating 0x%08" PRIx64 " in %s",
|
||||
id,
|
||||
XRE_IsParentProcess() ? "Parent" : "Child"));
|
||||
|
||||
RefPtr<BrowsingContext> context;
|
||||
if (XRE_IsParentProcess()) {
|
||||
context = new ChromeBrowsingContext(aDocShell);
|
||||
context = new ChromeBrowsingContext(aParent, aName, id, /* aProcessId */ 0, aType);
|
||||
} else {
|
||||
// TODO(farre): will we ever create BrowsingContexts on processes
|
||||
// other than content and parent?
|
||||
MOZ_ASSERT(XRE_IsContentProcess());
|
||||
context = new BrowsingContext(aDocShell);
|
||||
context = new BrowsingContext(aParent, aName, id, aType);
|
||||
}
|
||||
|
||||
Register(context);
|
||||
|
||||
// Attach the browsing context to the tree.
|
||||
context->Attach();
|
||||
|
||||
return context.forget();
|
||||
}
|
||||
|
||||
BrowsingContext::BrowsingContext(nsIDocShell* aDocShell)
|
||||
: mBrowsingContextId(nsContentUtils::GenerateBrowsingContextId())
|
||||
, mDocShell(aDocShell)
|
||||
/* static */ already_AddRefed<BrowsingContext>
|
||||
BrowsingContext::CreateFromIPC(BrowsingContext* aParent, const nsAString& aName,
|
||||
uint64_t aId, ContentParent* aOriginProcess)
|
||||
{
|
||||
sBrowsingContexts->Put(mBrowsingContextId, this);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aOriginProcess || XRE_IsContentProcess(),
|
||||
"Parent Process IPC contexts need a Content Process.");
|
||||
MOZ_DIAGNOSTIC_ASSERT(!aParent || aParent->IsContent());
|
||||
|
||||
MOZ_LOG(GetLog(),
|
||||
LogLevel::Debug,
|
||||
("Creating 0x%08" PRIx64 " from IPC (origin=0x%08" PRIx64 ")",
|
||||
aId, aOriginProcess ? uint64_t(aOriginProcess->ChildID()) : 0));
|
||||
|
||||
RefPtr<BrowsingContext> context;
|
||||
if (XRE_IsParentProcess()) {
|
||||
context = new ChromeBrowsingContext(
|
||||
aParent, aName, aId, aOriginProcess->ChildID(), Type::Content);
|
||||
|
||||
} else {
|
||||
context = new BrowsingContext(aParent, aName, aId, Type::Content);
|
||||
}
|
||||
|
||||
Register(context);
|
||||
|
||||
context->Attach();
|
||||
|
||||
return context.forget();
|
||||
}
|
||||
|
||||
BrowsingContext::BrowsingContext(uint64_t aBrowsingContextId,
|
||||
const nsAString& aName)
|
||||
: mBrowsingContextId(aBrowsingContextId)
|
||||
BrowsingContext::BrowsingContext(BrowsingContext* aParent,
|
||||
const nsAString& aName,
|
||||
uint64_t aBrowsingContextId,
|
||||
Type aType)
|
||||
: mType(aType)
|
||||
, mBrowsingContextId(aBrowsingContextId)
|
||||
, mParent(aParent)
|
||||
, mName(aName)
|
||||
{
|
||||
sBrowsingContexts->Put(mBrowsingContextId, this);
|
||||
}
|
||||
|
||||
void
|
||||
BrowsingContext::Attach(BrowsingContext* aParent)
|
||||
BrowsingContext::SetDocShell(nsIDocShell* aDocShell)
|
||||
{
|
||||
// XXX(nika): We should communicate that we are now an active BrowsingContext
|
||||
// process to the parent & do other validation here.
|
||||
MOZ_RELEASE_ASSERT(nsDocShell::Cast(aDocShell)->GetBrowsingContext() == this);
|
||||
mDocShell = aDocShell;
|
||||
}
|
||||
|
||||
void
|
||||
BrowsingContext::Attach()
|
||||
{
|
||||
if (isInList()) {
|
||||
MOZ_LOG(GetLog(),
|
||||
|
@ -109,7 +183,7 @@ BrowsingContext::Attach(BrowsingContext* aParent)
|
|||
("%s: Connecting already existing 0x%08" PRIx64 " to 0x%08" PRIx64,
|
||||
XRE_IsParentProcess() ? "Parent" : "Child",
|
||||
Id(),
|
||||
aParent ? aParent->Id() : 0));
|
||||
mParent ? mParent->Id() : 0));
|
||||
MOZ_DIAGNOSTIC_ASSERT(sBrowsingContexts->Contains(Id()));
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsCached());
|
||||
return;
|
||||
|
@ -123,22 +197,12 @@ BrowsingContext::Attach(BrowsingContext* aParent)
|
|||
XRE_IsParentProcess() ? "Parent" : "Child",
|
||||
wasCached ? "Re-connecting" : "Connecting",
|
||||
Id(),
|
||||
aParent ? aParent->Id() : 0));
|
||||
mParent ? mParent->Id() : 0));
|
||||
|
||||
auto* children = aParent ? &aParent->mChildren : sRootBrowsingContexts.get();
|
||||
auto* children = mParent ? &mParent->mChildren : sRootBrowsingContexts.get();
|
||||
children->insertBack(this);
|
||||
mParent = aParent;
|
||||
|
||||
if (!XRE_IsContentProcess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto cc = ContentChild::GetSingleton();
|
||||
MOZ_DIAGNOSTIC_ASSERT(cc);
|
||||
cc->SendAttachBrowsingContext(
|
||||
BrowsingContextId(mParent ? mParent->Id() : 0),
|
||||
BrowsingContextId(Id()),
|
||||
mName);
|
||||
Sync(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -25,6 +25,8 @@ class LogModule;
|
|||
|
||||
namespace dom {
|
||||
|
||||
class ContentParent;
|
||||
|
||||
// BrowsingContext, in this context, is the cross process replicated
|
||||
// environment in which information about documents is stored. In
|
||||
// particular the tree structure of nested browsing contexts is
|
||||
|
@ -37,23 +39,51 @@ namespace dom {
|
|||
// to the parent process, making it possible to traverse the
|
||||
// BrowsingContext tree for a tab, in both the parent and the child
|
||||
// process.
|
||||
//
|
||||
// Trees of BrowsingContexts should only ever contain nodes of the
|
||||
// same BrowsingContext::Type. This is enforced by asserts in the
|
||||
// BrowsingContext::Create* methods.
|
||||
class BrowsingContext
|
||||
: public nsWrapperCache
|
||||
, public SupportsWeakPtr<BrowsingContext>
|
||||
, public LinkedListElement<RefPtr<BrowsingContext>>
|
||||
{
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
Chrome,
|
||||
Content
|
||||
};
|
||||
|
||||
static void Init();
|
||||
static LogModule* GetLog();
|
||||
static void CleanupContexts(uint64_t aProcessId);
|
||||
|
||||
// Look up a BrowsingContext in the current process by ID.
|
||||
static already_AddRefed<BrowsingContext> Get(uint64_t aId);
|
||||
static already_AddRefed<BrowsingContext> Create(nsIDocShell* aDocShell);
|
||||
|
||||
// Attach the current BrowsingContext to its parent, in both the
|
||||
// child and the parent process. If 'aParent' is null, 'this' is
|
||||
// taken to be a root BrowsingContext.
|
||||
void Attach(BrowsingContext* aParent);
|
||||
// Create a brand-new BrowsingContext object.
|
||||
static already_AddRefed<BrowsingContext> Create(BrowsingContext* aParent,
|
||||
const nsAString& aName,
|
||||
Type aType);
|
||||
|
||||
// Create a BrowsingContext object from over IPC.
|
||||
static already_AddRefed<BrowsingContext> CreateFromIPC(
|
||||
BrowsingContext* aParent,
|
||||
const nsAString& aName,
|
||||
uint64_t aId,
|
||||
ContentParent* aOriginProcess);
|
||||
|
||||
// Get the DocShell for this BrowsingContext if it is in-process, or
|
||||
// null if it's not.
|
||||
nsIDocShell* GetDocShell() { return mDocShell; }
|
||||
void SetDocShell(nsIDocShell* aDocShell);
|
||||
|
||||
// Attach the current BrowsingContext to its parent, in both the child and the
|
||||
// parent process. BrowsingContext objects are created attached by default, so
|
||||
// this method need only be called when restoring cached BrowsingContext
|
||||
// objects.
|
||||
void Attach();
|
||||
|
||||
// Detach the current BrowsingContext from its parent, in both the
|
||||
// child and the parent process.
|
||||
|
@ -63,27 +93,24 @@ public:
|
|||
// them to allow them to be attached again.
|
||||
void CacheChildren();
|
||||
|
||||
// Determine if the current BrowsingContext was 'cached' by the logic in
|
||||
// CacheChildren.
|
||||
bool IsCached();
|
||||
|
||||
// TODO(farre): We should sync changes from SetName to the parent
|
||||
// process. [Bug 1490303]
|
||||
void SetName(const nsAString& aName) { mName = aName; }
|
||||
void GetName(nsAString& aName) { aName = mName; }
|
||||
bool NameEquals(const nsAString& aName) { return mName.Equals(aName); }
|
||||
|
||||
uint64_t Id() const { return mBrowsingContextId; }
|
||||
uint64_t OwnerProcessId() const;
|
||||
bool IsContent() const { return mType == Type::Content; }
|
||||
|
||||
already_AddRefed<BrowsingContext> GetParent()
|
||||
{
|
||||
return do_AddRef(mParent.get());
|
||||
}
|
||||
uint64_t Id() const { return mBrowsingContextId; }
|
||||
|
||||
BrowsingContext* GetParent() { return mParent; }
|
||||
|
||||
void GetChildren(nsTArray<RefPtr<BrowsingContext>>& aChildren);
|
||||
|
||||
already_AddRefed<nsIDocShell> GetDocShell()
|
||||
{
|
||||
return do_AddRef(mDocShell.get());
|
||||
}
|
||||
|
||||
static void GetRootBrowsingContexts(
|
||||
nsTArray<RefPtr<BrowsingContext>>& aBrowsingContexts);
|
||||
|
||||
|
@ -99,16 +126,19 @@ public:
|
|||
|
||||
protected:
|
||||
virtual ~BrowsingContext();
|
||||
// Create a new BrowsingContext for 'aDocShell'. The id will be
|
||||
// generated so that it is unique across all content child processes
|
||||
// and the content parent process.
|
||||
explicit BrowsingContext(nsIDocShell* aDocShell);
|
||||
BrowsingContext(uint64_t aBrowsingContextId,
|
||||
const nsAString& aName);
|
||||
BrowsingContext(BrowsingContext* aParent,
|
||||
const nsAString& aName,
|
||||
uint64_t aBrowsingContextId,
|
||||
Type aType);
|
||||
|
||||
private:
|
||||
// Type of BrowsingContent
|
||||
const Type mType;
|
||||
|
||||
// Unique id identifying BrowsingContext
|
||||
const uint64_t mBrowsingContextId;
|
||||
|
||||
|
||||
WeakPtr<BrowsingContext> mParent;
|
||||
Children mChildren;
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
|
|
|
@ -6,13 +6,17 @@
|
|||
|
||||
#include "ChromeBrowsingContext.h"
|
||||
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
ChromeBrowsingContext::ChromeBrowsingContext(uint64_t aBrowsingContextId,
|
||||
ChromeBrowsingContext::ChromeBrowsingContext(BrowsingContext* aParent,
|
||||
const nsAString& aName,
|
||||
uint64_t aProcessId)
|
||||
: BrowsingContext(aBrowsingContextId, aName)
|
||||
uint64_t aBrowsingContextId,
|
||||
uint64_t aProcessId,
|
||||
BrowsingContext::Type aType)
|
||||
: BrowsingContext(aParent, aName, aBrowsingContextId, aType)
|
||||
, mProcessId(aProcessId)
|
||||
{
|
||||
// You are only ever allowed to create ChromeBrowsingContexts in the
|
||||
|
@ -20,15 +24,6 @@ ChromeBrowsingContext::ChromeBrowsingContext(uint64_t aBrowsingContextId,
|
|||
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
|
||||
}
|
||||
|
||||
ChromeBrowsingContext::ChromeBrowsingContext(nsIDocShell* aDocShell)
|
||||
: BrowsingContext(aDocShell)
|
||||
, mProcessId(0)
|
||||
{
|
||||
// You are only ever allowed to create ChromeBrowsingContexts in the
|
||||
// parent process.
|
||||
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
|
||||
}
|
||||
|
||||
// TODO(farre): ChromeBrowsingContext::CleanupContexts starts from the
|
||||
// list of root BrowsingContexts. This isn't enough when separate
|
||||
// BrowsingContext nodes of a BrowsingContext tree, not in a crashing
|
||||
|
@ -61,13 +56,11 @@ ChromeBrowsingContext::Cast(BrowsingContext* aContext)
|
|||
return static_cast<ChromeBrowsingContext*>(aContext);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<ChromeBrowsingContext>
|
||||
ChromeBrowsingContext::Create(
|
||||
uint64_t aBrowsingContextId,
|
||||
const nsAString& aName,
|
||||
uint64_t aProcessId)
|
||||
/* static */ const ChromeBrowsingContext*
|
||||
ChromeBrowsingContext::Cast(const BrowsingContext* aContext)
|
||||
{
|
||||
return do_AddRef(new ChromeBrowsingContext(aBrowsingContextId, aName, aProcessId));
|
||||
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
|
||||
return static_cast<const ChromeBrowsingContext*>(aContext);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -27,10 +27,7 @@ public:
|
|||
static void CleanupContexts(uint64_t aProcessId);
|
||||
static already_AddRefed<ChromeBrowsingContext> Get(uint64_t aId);
|
||||
static ChromeBrowsingContext* Cast(BrowsingContext* aContext);
|
||||
static already_AddRefed<ChromeBrowsingContext> Create(
|
||||
uint64_t aBrowsingContextId,
|
||||
const nsAString& aName,
|
||||
uint64_t aProcessId);
|
||||
static const ChromeBrowsingContext* Cast(const BrowsingContext* aContext);
|
||||
|
||||
bool IsOwnedByProcess(uint64_t aProcessId) const
|
||||
{
|
||||
|
@ -40,15 +37,18 @@ public:
|
|||
protected:
|
||||
void Traverse(nsCycleCollectionTraversalCallback& cb) {}
|
||||
void Unlink() {}
|
||||
ChromeBrowsingContext(uint64_t aBrowsingContextId,
|
||||
|
||||
using Type = BrowsingContext::Type;
|
||||
ChromeBrowsingContext(BrowsingContext* aParent,
|
||||
const nsAString& aName,
|
||||
uint64_t aProcessId);
|
||||
uint64_t aBrowsingContextId,
|
||||
uint64_t aProcessId,
|
||||
Type aType = Type::Chrome);
|
||||
|
||||
private:
|
||||
friend class BrowsingContext;
|
||||
|
||||
explicit ChromeBrowsingContext(nsIDocShell* aDocShell);
|
||||
|
||||
// XXX(farre): Store a ContentParent pointer here rather than mProcessId?
|
||||
// Indicates which process owns the docshell.
|
||||
uint64_t mProcessId;
|
||||
};
|
||||
|
|
|
@ -449,44 +449,70 @@ nsDocShell::~nsDocShell()
|
|||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::Init()
|
||||
/* static */ already_AddRefed<nsDocShell>
|
||||
nsDocShell::Create(BrowsingContext* aBrowsingContext)
|
||||
{
|
||||
MOZ_ASSERT(!mIsBeingDestroyed);
|
||||
MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!");
|
||||
|
||||
nsresult rv = nsDocLoader::Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv;
|
||||
RefPtr<nsDocShell> ds = new nsDocShell();
|
||||
ds->mBrowsingContext = aBrowsingContext;
|
||||
|
||||
NS_ASSERTION(mLoadGroup, "Something went wrong!");
|
||||
// Initialize the underlying nsDocLoader.
|
||||
rv = ds->nsDocLoader::Init();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mContentListener = new nsDSURIContentListener(this);
|
||||
rv = mContentListener->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Create our ContentListener
|
||||
ds->mContentListener = new nsDSURIContentListener(ds);
|
||||
rv = ds->mContentListener->Init();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If parent intercept is not enabled then we must forward to
|
||||
// the network controller from docshell. We also enable if we're
|
||||
// in the parent process in order to support non-e10s configurations.
|
||||
if (!ServiceWorkerParentInterceptEnabled() || XRE_IsParentProcess()) {
|
||||
mInterceptController = new ServiceWorkerInterceptController();
|
||||
ds->mInterceptController = new ServiceWorkerInterceptController();
|
||||
}
|
||||
|
||||
// We want to hold a strong ref to the loadgroup, so it better hold a weak
|
||||
// ref to us... use an InterfaceRequestorProxy to do this.
|
||||
nsCOMPtr<nsIInterfaceRequestor> proxy =
|
||||
new InterfaceRequestorProxy(static_cast<nsIInterfaceRequestor*>(this));
|
||||
mLoadGroup->SetNotificationCallbacks(proxy);
|
||||
nsCOMPtr<nsIInterfaceRequestor> proxy = new InterfaceRequestorProxy(ds);
|
||||
ds->mLoadGroup->SetNotificationCallbacks(proxy);
|
||||
|
||||
rv = nsDocLoader::AddDocLoaderAsChildOfRoot(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// XXX(nika): We have our BrowsingContext, so we might be able to skip this.
|
||||
// It could be nice to directly set up our DocLoader tree?
|
||||
rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mBrowsingContext = BrowsingContext::Create(this);
|
||||
// Add |ds| as a progress listener to itself. A little weird, but simpler
|
||||
// than reproducing all the listener-notification logic in overrides of the
|
||||
// various methods via which nsDocLoader can be notified. Note that this
|
||||
// holds an nsWeakPtr to |ds|, so it's ok.
|
||||
rv = ds->AddProgressListener(ds,
|
||||
nsIWebProgress::NOTIFY_STATE_DOCUMENT |
|
||||
nsIWebProgress::NOTIFY_STATE_NETWORK);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Add as |this| a progress listener to itself. A little weird, but
|
||||
// simpler than reproducing all the listener-notification logic in
|
||||
// overrides of the various methods via which nsDocLoader can be
|
||||
// notified. Note that this holds an nsWeakPtr to ourselves, so it's ok.
|
||||
return AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_DOCUMENT |
|
||||
nsIWebProgress::NOTIFY_STATE_NETWORK);
|
||||
// Set our DocShellTreeItem type based on our BrowsingContext
|
||||
ds->SetItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome);
|
||||
|
||||
// If our parent is present in this process, set up our parent now.
|
||||
RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent();
|
||||
if (parent && parent->GetDocShell()) {
|
||||
parent->GetDocShell()->AddChild(ds);
|
||||
}
|
||||
|
||||
// Make |ds| the primary DocShell for the given context.
|
||||
aBrowsingContext->SetDocShell(ds);
|
||||
return ds.forget();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3501,8 +3527,6 @@ nsDocShell::AddChild(nsIDocShellTreeItem* aChild)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
childAsDocShell->AttachBrowsingContext(this);
|
||||
|
||||
// charset, style-disabling, and zoom will be inherited in SetupNewViewer()
|
||||
|
||||
// Now take this document's charset and set the child's parentCharset field
|
||||
|
@ -3565,11 +3589,6 @@ nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild)
|
|||
nsresult rv = RemoveChildLoader(childAsDocLoader);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
|
||||
if (childAsDocShell) {
|
||||
childAsDocShell->DetachBrowsingContext();
|
||||
}
|
||||
|
||||
aChild->SetTreeOwner(nullptr);
|
||||
|
||||
return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
|
||||
|
@ -7784,6 +7803,14 @@ nsDocShell::BeginRestore(nsIContentViewer* aContentViewer, bool aTop)
|
|||
}
|
||||
}
|
||||
|
||||
// When re-attaching browsing context, a mozbrowser docshell will be
|
||||
// considered as top level, but its browsing context will have a
|
||||
// parent.
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
(aTop && !mBrowsingContext->GetParent()) ||
|
||||
((!aTop || GetIsMozBrowser()) && mBrowsingContext->GetParent()));
|
||||
mBrowsingContext->Attach();
|
||||
|
||||
if (!aTop) {
|
||||
// This point corresponds to us having gotten OnStartRequest or
|
||||
// STATE_START, so do the same thing that CreateContentViewer does at
|
||||
|
@ -14093,11 +14120,10 @@ nsDocShell::IsForceReloading()
|
|||
return IsForceReloadType(mLoadType);
|
||||
}
|
||||
|
||||
already_AddRefed<BrowsingContext>
|
||||
BrowsingContext*
|
||||
nsDocShell::GetBrowsingContext() const
|
||||
{
|
||||
RefPtr<BrowsingContext> browsingContext = mBrowsingContext;
|
||||
return browsingContext.forget();
|
||||
return mBrowsingContext;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -14106,24 +14132,3 @@ nsDocShell::GetBrowsingContext(BrowsingContext** aBrowsingContext)
|
|||
*aBrowsingContext = do_AddRef(mBrowsingContext).take();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocShell::AttachBrowsingContext(nsIDocShell* aParentDocShell)
|
||||
{
|
||||
RefPtr<BrowsingContext> childContext =
|
||||
nsDocShell::Cast(this)->GetBrowsingContext();
|
||||
RefPtr<BrowsingContext> parentContext;
|
||||
if (aParentDocShell) {
|
||||
parentContext =
|
||||
nsDocShell::Cast(aParentDocShell)->GetBrowsingContext();
|
||||
}
|
||||
childContext->Attach(parentContext);
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocShell::DetachBrowsingContext()
|
||||
{
|
||||
RefPtr<BrowsingContext> browsingContext =
|
||||
nsDocShell::Cast(this)->GetBrowsingContext();
|
||||
browsingContext->Detach();
|
||||
}
|
||||
|
|
|
@ -182,8 +182,9 @@ public:
|
|||
// nsIWebProgressListener has methods with identical names...
|
||||
NS_FORWARD_NSISECURITYEVENTSINK(nsDocLoader::)
|
||||
|
||||
nsDocShell();
|
||||
virtual nsresult Init() override;
|
||||
// Create a new nsDocShell object, initializing it.
|
||||
static already_AddRefed<nsDocShell>
|
||||
Create(mozilla::dom::BrowsingContext* aBrowsingContext);
|
||||
|
||||
NS_IMETHOD Stop() override
|
||||
{
|
||||
|
@ -380,13 +381,16 @@ public:
|
|||
// shift while triggering reload)
|
||||
bool IsForceReloading();
|
||||
|
||||
already_AddRefed<mozilla::dom::BrowsingContext>
|
||||
GetBrowsingContext() const;
|
||||
/**
|
||||
* Native getter for a DocShell's BrowsingContext.
|
||||
*/
|
||||
mozilla::dom::BrowsingContext* GetBrowsingContext() const;
|
||||
|
||||
private: // member functions
|
||||
friend class nsDSURIContentListener;
|
||||
friend class FramingChecker;
|
||||
friend class OnLinkClickEvent;
|
||||
friend class nsIDocShell;
|
||||
|
||||
// It is necessary to allow adding a timeline marker wherever a docshell
|
||||
// instance is available. This operation happens frequently and needs to
|
||||
|
@ -405,6 +409,8 @@ private: // member functions
|
|||
friend void mozilla::TimelineConsumers::PopMarkers(nsDocShell*,
|
||||
JSContext*, nsTArray<dom::ProfileTimelineMarker>&);
|
||||
|
||||
nsDocShell();
|
||||
|
||||
// Security checks to prevent frameset spoofing. See comments at
|
||||
// implementation sites.
|
||||
static bool CanAccessItem(nsIDocShellTreeItem* aTargetItem,
|
||||
|
|
|
@ -1232,9 +1232,6 @@ interface nsIDocShell : nsIDocShellTreeItem
|
|||
*/
|
||||
mozilla::HTMLEditor* GetHTMLEditor();
|
||||
nsresult SetHTMLEditor(mozilla::HTMLEditor* aHTMLEditor);
|
||||
|
||||
void AttachBrowsingContext(nsIDocShell* aParentDocShell);
|
||||
void DetachBrowsingContext();
|
||||
%}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,17 +14,6 @@
|
|||
*/
|
||||
#define NS_WEBNAVIGATION_INFO_CONTRACTID "@mozilla.org/webnavigation-info;1"
|
||||
|
||||
/**
|
||||
* Class and contract ID for the docshell. This is the container for a web
|
||||
* navigation context. It implements too many interfaces to count, and the
|
||||
* exact ones keep changing; if they stabilize somewhat that will get
|
||||
* documented.
|
||||
*/
|
||||
#define NS_DOCSHELL_CID \
|
||||
{ 0xf1eac762, 0x87e9, 0x11d3, \
|
||||
{ 0xaf, 0x80, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c } }
|
||||
#define NS_DOCSHELL_CONTRACTID "@mozilla.org/docshell/html;1"
|
||||
|
||||
/**
|
||||
* Contract ID to obtain the IHistory interface. This is a non-scriptable
|
||||
* interface used to interact with history in an asynchronous manner.
|
||||
|
|
|
@ -66,8 +66,6 @@ Shutdown()
|
|||
gInitialized = false;
|
||||
}
|
||||
|
||||
// docshell
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDocShell, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDefaultURIFixup)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWebNavigationInfo, Init)
|
||||
|
||||
|
@ -94,7 +92,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsOSPermissionRequest)
|
|||
// session history
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHEntry)
|
||||
|
||||
NS_DEFINE_NAMED_CID(NS_DOCSHELL_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_DEFAULTURIFIXUP_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_WEBNAVIGATION_INFO_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_ABOUT_REDIRECTOR_MODULE_CID);
|
||||
|
@ -117,7 +114,6 @@ NS_DEFINE_NAMED_CID(NS_CONTENTHANDLERSERVICE_CID);
|
|||
|
||||
const mozilla::Module::CIDEntry kDocShellCIDs[] = {
|
||||
// clang-format off
|
||||
{ &kNS_DOCSHELL_CID, false, nullptr, nsDocShellConstructor },
|
||||
{ &kNS_DEFAULTURIFIXUP_CID, false, nullptr, nsDefaultURIFixupConstructor },
|
||||
{ &kNS_WEBNAVIGATION_INFO_CID, false, nullptr, nsWebNavigationInfoConstructor },
|
||||
{ &kNS_ABOUT_REDIRECTOR_MODULE_CID, false, nullptr, nsAboutRedirector::Create },
|
||||
|
@ -144,7 +140,6 @@ const mozilla::Module::CIDEntry kDocShellCIDs[] = {
|
|||
|
||||
const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
|
||||
// clang-format off
|
||||
{ "@mozilla.org/docshell;1", &kNS_DOCSHELL_CID },
|
||||
{ NS_URIFIXUP_CONTRACTID, &kNS_DEFAULTURIFIXUP_CID },
|
||||
{ NS_WEBNAVIGATION_INFO_CONTRACTID, &kNS_WEBNAVIGATION_INFO_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "about", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
function destroy_transient_docshell() {
|
||||
var docshell = Cc["@mozilla.org/docshell;1"].createInstance(Ci.nsIDocShell);
|
||||
docshell.setOriginAttributes({privateBrowsingId : 1});
|
||||
let windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
|
||||
windowlessBrowser.docshell.setOriginAttributes({privateBrowsingId : 1});
|
||||
windowlessBrowser.close();
|
||||
do_test_pending();
|
||||
do_timeout(0, Cu.forceGC);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
var gNotifications = 0;
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var observer = {
|
||||
QueryInterface: function(iid) {
|
||||
if (Ci.nsIPrivacyTransitionObserver.equals(iid) ||
|
||||
|
@ -8,16 +10,17 @@ var observer = {
|
|||
return this;
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
|
||||
privateModeChanged: function(enabled) {
|
||||
gNotifications++;
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
var docshell = Cc["@mozilla.org/docshell;1"].createInstance(Ci.nsIDocShell);
|
||||
docshell.addWeakPrivacyTransitionObserver(observer);
|
||||
docshell.setOriginAttributes({ privateBrowsingId : 1 });
|
||||
docshell.setOriginAttributes({ privateBrowsingId : 0 });
|
||||
let windowlessBrowser = Services.appShell.createWindowlessBrowser(false);
|
||||
windowlessBrowser.docShell.addWeakPrivacyTransitionObserver(observer);
|
||||
windowlessBrowser.docShell.setOriginAttributes({privateBrowsingId : 1});
|
||||
windowlessBrowser.docShell.setOriginAttributes({privateBrowsingId : 0});
|
||||
windowlessBrowser.close();
|
||||
Assert.equal(gNotifications, 2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -562,61 +562,49 @@ SetTreeOwnerAndChromeEventHandlerOnDocshellTree(nsIDocShellTreeItem* aItem,
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckDocShellType(mozilla::dom::Element* aOwnerContent,
|
||||
nsIDocShellTreeItem* aDocShell,
|
||||
nsAtom* aAtom)
|
||||
{
|
||||
bool isContent = aOwnerContent->AttrValueIs(
|
||||
kNameSpaceID_None, aAtom, nsGkAtoms::content, eIgnoreCase);
|
||||
|
||||
if (!isContent) {
|
||||
nsCOMPtr<nsIMozBrowserFrame> mozbrowser = aOwnerContent->GetAsMozBrowserFrame();
|
||||
if (mozbrowser) {
|
||||
mozbrowser->GetMozbrowser(&isContent);
|
||||
}
|
||||
}
|
||||
|
||||
if (isContent) {
|
||||
return aDocShell->ItemType() == nsIDocShellTreeItem::typeContent;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> parent;
|
||||
aDocShell->GetParent(getter_AddRefs(parent));
|
||||
|
||||
return parent && parent->ItemType() == aDocShell->ItemType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of the treeitem and hook it up to the treeowner.
|
||||
* Hook up a given TreeItem to its tree owner. aItem's type must have already
|
||||
* been set, and it should already be part of the DocShellTree.
|
||||
* @param aItem the treeitem we're working with
|
||||
* @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
|
||||
*/
|
||||
bool
|
||||
void
|
||||
nsFrameLoader::AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeOwner* aOwner,
|
||||
int32_t aParentType,
|
||||
nsIDocShell* aParentNode)
|
||||
nsIDocShellTreeOwner* aOwner)
|
||||
{
|
||||
MOZ_ASSERT(aItem, "Must have docshell treeitem");
|
||||
MOZ_ASSERT(mOwnerContent, "Must have owning content");
|
||||
|
||||
nsAutoString value;
|
||||
bool isContent = mOwnerContent->AttrValueIs(
|
||||
kNameSpaceID_None, TypeAttrName(), nsGkAtoms::content, eIgnoreCase);
|
||||
|
||||
// Force mozbrowser frames to always be typeContent, even if the
|
||||
// mozbrowser interfaces are disabled.
|
||||
nsCOMPtr<nsIDOMMozBrowserFrame> mozbrowser =
|
||||
do_QueryInterface(mOwnerContent);
|
||||
if (mozbrowser) {
|
||||
bool isMozbrowser = false;
|
||||
mozbrowser->GetMozbrowser(&isMozbrowser);
|
||||
isContent |= isMozbrowser;
|
||||
}
|
||||
|
||||
if (isContent) {
|
||||
// The web shell's type is content.
|
||||
|
||||
aItem->SetItemType(nsIDocShellTreeItem::typeContent);
|
||||
} else {
|
||||
// Inherit our type from our parent docshell. If it is
|
||||
// chrome, we'll be chrome. If it is content, we'll be
|
||||
// content.
|
||||
|
||||
aItem->SetItemType(aParentType);
|
||||
}
|
||||
|
||||
// Now that we have our type set, add ourselves to the parent, as needed.
|
||||
if (aParentNode) {
|
||||
aParentNode->AddChild(aItem);
|
||||
} else if (nsCOMPtr<nsIDocShell> childAsDocShell = do_QueryInterface(aItem)) {
|
||||
childAsDocShell->AttachBrowsingContext(aParentNode);
|
||||
}
|
||||
|
||||
bool retval = false;
|
||||
if (aParentType == nsIDocShellTreeItem::typeChrome && isContent) {
|
||||
retval = true;
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
CheckDocShellType(mOwnerContent, aItem, TypeAttrName()),
|
||||
"Correct ItemType should be set when creating BrowsingContext");
|
||||
|
||||
if (mIsTopLevelContent) {
|
||||
bool is_primary =
|
||||
mOwnerContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::primary,
|
||||
nsGkAtoms::_true, eIgnoreCase);
|
||||
|
@ -626,8 +614,6 @@ nsFrameLoader::AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
|
|||
aOwner->ContentShellAdded(aItem, is_primary);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1499,9 +1485,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
|||
SetOwnerContent(otherContent);
|
||||
aOther->SetOwnerContent(ourContent);
|
||||
|
||||
AddTreeItemToTreeOwner(ourDocshell, otherOwner, otherParentType, nullptr);
|
||||
aOther->AddTreeItemToTreeOwner(otherDocshell, ourOwner, ourParentType,
|
||||
nullptr);
|
||||
AddTreeItemToTreeOwner(ourDocshell, otherOwner);
|
||||
aOther->AddTreeItemToTreeOwner(otherDocshell, ourOwner);
|
||||
|
||||
// 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
|
||||
|
@ -1904,6 +1889,23 @@ nsFrameLoader::IsRemoteFrame()
|
|||
return false;
|
||||
}
|
||||
|
||||
static already_AddRefed<BrowsingContext>
|
||||
CreateBrowsingContext(BrowsingContext* aParentContext,
|
||||
const nsAString& aName,
|
||||
bool aIsContent)
|
||||
{
|
||||
// If we're content but our parent isn't, we're going to want to start a new
|
||||
// browsing context tree.
|
||||
if (aIsContent && !aParentContext->IsContent()) {
|
||||
aParentContext = nullptr;
|
||||
}
|
||||
|
||||
BrowsingContext::Type type =
|
||||
aIsContent ? BrowsingContext::Type::Content : BrowsingContext::Type::Chrome;
|
||||
|
||||
return BrowsingContext::Create(aParentContext, aName, type);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameLoader::MaybeCreateDocShell()
|
||||
{
|
||||
|
@ -1936,22 +1938,16 @@ nsFrameLoader::MaybeCreateDocShell()
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> parentDocShell = doc->GetDocShell();
|
||||
nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(parentDocShell);
|
||||
NS_ENSURE_STATE(parentAsWebNav);
|
||||
|
||||
// Create the docshell...
|
||||
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
|
||||
if (!mNetworkCreated) {
|
||||
if (mDocShell) {
|
||||
mDocShell->SetCreatedDynamically(true);
|
||||
}
|
||||
// Determine our parent nsDocShell
|
||||
RefPtr<nsDocShell> parentDocShell = nsDocShell::Cast(doc->GetDocShell());
|
||||
if (NS_WARN_IF(!parentDocShell)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Get the frame name and tell the docshell about it.
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
RefPtr<BrowsingContext> parentBC = parentDocShell->GetBrowsingContext();
|
||||
MOZ_ASSERT(parentBC, "docShell must have BrowsingContext");
|
||||
|
||||
// Determine the frame name for the new browsing context.
|
||||
nsAutoString frameName;
|
||||
|
||||
int32_t namespaceID = mOwnerContent->GetNameSpaceID();
|
||||
|
@ -1966,45 +1962,55 @@ nsFrameLoader::MaybeCreateDocShell()
|
|||
}
|
||||
}
|
||||
|
||||
if (!frameName.IsEmpty()) {
|
||||
mDocShell->SetName(frameName);
|
||||
// Check if our new context is chrome or content
|
||||
bool isContent = parentBC->IsContent() ||
|
||||
mOwnerContent->AttrValueIs(kNameSpaceID_None, TypeAttrName(),
|
||||
nsGkAtoms::content, eIgnoreCase);
|
||||
|
||||
// Force mozbrowser frames to always be content, even if the mozbrowser
|
||||
// interfaces are disabled.
|
||||
nsCOMPtr<nsIMozBrowserFrame> mozbrowser =
|
||||
mOwnerContent->GetAsMozBrowserFrame();
|
||||
if (!isContent && mozbrowser) {
|
||||
mozbrowser->GetMozbrowser(&isContent);
|
||||
}
|
||||
|
||||
// Inform our docShell that it has a new child.
|
||||
// Note: This logic duplicates a lot of logic in
|
||||
// nsSubDocumentFrame::AttributeChanged. We should fix that.
|
||||
RefPtr<BrowsingContext> browsingContext = CreateBrowsingContext(parentBC, frameName, isContent);
|
||||
|
||||
const int32_t parentType = parentDocShell->ItemType();
|
||||
mDocShell = nsDocShell::Create(browsingContext);
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
|
||||
// XXXbz why is this in content code, exactly? We should handle
|
||||
// this some other way..... Not sure how yet.
|
||||
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
|
||||
parentDocShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
|
||||
NS_ENSURE_STATE(parentTreeOwner);
|
||||
mIsTopLevelContent =
|
||||
AddTreeItemToTreeOwner(mDocShell, parentTreeOwner, parentType,
|
||||
parentDocShell);
|
||||
mIsTopLevelContent = isContent && !parentBC->IsContent();
|
||||
if (!mNetworkCreated && !mIsTopLevelContent) {
|
||||
mDocShell->SetCreatedDynamically(true);
|
||||
}
|
||||
|
||||
if (mIsTopLevelContent) {
|
||||
mDocShell->SetCreatedDynamically(false);
|
||||
// Manually add ourselves to our parent's docshell, as BrowsingContext won't
|
||||
// have done this for us.
|
||||
//
|
||||
// XXX(nika): Consider removing the DocShellTree in the future, for
|
||||
// consistency between local and remote frames..
|
||||
parentDocShell->AddChild(mDocShell);
|
||||
}
|
||||
|
||||
// Make sure all shells have links back to the content element
|
||||
// in the nearest enclosing chrome shell.
|
||||
// Now that we are part of the DocShellTree, attach our DocShell to our
|
||||
// parent's TreeOwner.
|
||||
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
|
||||
parentDocShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
|
||||
AddTreeItemToTreeOwner(mDocShell, parentTreeOwner);
|
||||
|
||||
// Make sure all nsDocShells have links back to the content element in the
|
||||
// nearest enclosing chrome shell.
|
||||
RefPtr<EventTarget> chromeEventHandler;
|
||||
|
||||
if (parentType == nsIDocShellTreeItem::typeChrome) {
|
||||
// Our parent shell is a chrome shell. It is therefore our nearest
|
||||
// enclosing chrome shell.
|
||||
|
||||
chromeEventHandler = mOwnerContent;
|
||||
NS_ASSERTION(chromeEventHandler,
|
||||
"This mContent should implement this.");
|
||||
} else {
|
||||
// Our parent shell is a content shell. Get the chrome event
|
||||
// handler from it and use that for our shell as well.
|
||||
|
||||
if (parentBC->IsContent()) {
|
||||
// Our parent shell is a content shell. Get the chrome event handler from it
|
||||
// and use that for our shell as well.
|
||||
parentDocShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
|
||||
} else {
|
||||
// Our parent shell is a chrome shell. It is therefore our nearest enclosing
|
||||
// chrome shell.
|
||||
chromeEventHandler = mOwnerContent;
|
||||
}
|
||||
|
||||
mDocShell->SetChromeEventHandler(chromeEventHandler);
|
||||
|
@ -2015,32 +2021,34 @@ nsFrameLoader::MaybeCreateDocShell()
|
|||
// the right chrome event handler.
|
||||
|
||||
// Tell the window about the frame that hosts it.
|
||||
nsCOMPtr<Element> frame_element = mOwnerContent;
|
||||
NS_ASSERTION(frame_element, "frame loader owner element not a DOM element!");
|
||||
nsCOMPtr<nsPIDOMWindowOuter> newWindow = mDocShell->GetWindow();
|
||||
if (NS_WARN_IF(!newWindow)) {
|
||||
// Do not call Destroy() here. See bug 472312.
|
||||
NS_WARNING("Something wrong when creating the docshell for a frameloader!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win_private(mDocShell->GetWindow());
|
||||
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
|
||||
if (win_private) {
|
||||
win_private->SetFrameElementInternal(frame_element);
|
||||
newWindow->SetFrameElementInternal(mOwnerContent);
|
||||
|
||||
// Set the opener window if we have one provided here
|
||||
if (mOpener) {
|
||||
win_private->SetOpenerWindow(mOpener, true);
|
||||
mOpener = nullptr;
|
||||
}
|
||||
// Set the opener window if we have one provided here
|
||||
// XXX(nika): We should tell our BrowsingContext this as we create it.
|
||||
if (mOpener) {
|
||||
newWindow->SetOpenerWindow(mOpener, true);
|
||||
mOpener = nullptr;
|
||||
}
|
||||
|
||||
// Allow scripts to close the docshell if specified.
|
||||
if (win_private && mOwnerContent->IsXULElement(nsGkAtoms::browser) &&
|
||||
if (mOwnerContent->IsXULElement(nsGkAtoms::browser) &&
|
||||
mOwnerContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowscriptstoclose,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
nsGlobalWindowOuter::Cast(win_private)->AllowScriptsToClose();
|
||||
nsGlobalWindowOuter::Cast(newWindow)->AllowScriptsToClose();
|
||||
}
|
||||
|
||||
// This is kinda whacky, this call doesn't really create anything,
|
||||
// but it must be called to make sure things are properly
|
||||
// initialized.
|
||||
if (NS_FAILED(base_win->Create()) || !win_private) {
|
||||
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
|
||||
if (NS_FAILED(baseWin->Create())) {
|
||||
// Do not call Destroy() here. See bug 472312.
|
||||
NS_WARNING("Something wrong when creating the docshell for a frameloader!");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2060,7 +2068,7 @@ nsFrameLoader::MaybeCreateDocShell()
|
|||
|
||||
OriginAttributes attrs;
|
||||
if (parentDocShell->ItemType() == mDocShell->ItemType()) {
|
||||
attrs = nsDocShell::Cast(parentDocShell)->GetOriginAttributes();
|
||||
attrs = parentDocShell->GetOriginAttributes();
|
||||
}
|
||||
|
||||
// Inherit origin attributes from parent document if
|
||||
|
@ -2070,7 +2078,7 @@ nsFrameLoader::MaybeCreateDocShell()
|
|||
//
|
||||
// For example, firstPartyDomain is computed from top-level document, it
|
||||
// doesn't exist in the top-level docshell.
|
||||
if (parentType == nsIDocShellTreeItem::typeContent &&
|
||||
if (parentBC->IsContent() &&
|
||||
!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()) &&
|
||||
!OwnerIsMozBrowserFrame()) {
|
||||
OriginAttributes oa = doc->NodePrincipal()->OriginAttributesRef();
|
||||
|
@ -2116,10 +2124,7 @@ nsFrameLoader::MaybeCreateDocShell()
|
|||
}
|
||||
|
||||
bool isPrivate = false;
|
||||
nsCOMPtr<nsILoadContext> parentContext = do_QueryInterface(parentDocShell);
|
||||
NS_ENSURE_STATE(parentContext);
|
||||
|
||||
rv = parentContext->GetUsePrivateBrowsing(&isPrivate);
|
||||
rv = parentDocShell->GetUsePrivateBrowsing(&isPrivate);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -2158,7 +2163,7 @@ nsFrameLoader::MaybeCreateDocShell()
|
|||
// those cases.
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = doc->GetWindow();
|
||||
if (!mDocShell->GetIsMozBrowser() &&
|
||||
parentType == mDocShell->ItemType() &&
|
||||
parentDocShell->ItemType() == mDocShell->ItemType() &&
|
||||
!doc->IsStaticDocument() && win) {
|
||||
// Propagate through the ancestor principals.
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>> ancestorPrincipals;
|
||||
|
|
|
@ -423,10 +423,8 @@ private:
|
|||
bool ShowRemoteFrame(const mozilla::ScreenIntSize& size,
|
||||
nsSubDocumentFrame *aFrame = nullptr);
|
||||
|
||||
bool AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeOwner* aOwner,
|
||||
int32_t aParentType,
|
||||
nsIDocShell* aParentNode);
|
||||
void AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
|
||||
nsIDocShellTreeOwner* aOwner);
|
||||
|
||||
nsAtom* TypeAttrName() const {
|
||||
return mOwnerContent->IsXULElement()
|
||||
|
|
|
@ -6122,9 +6122,8 @@ ContentParent::RecvAttachBrowsingContext(
|
|||
}
|
||||
|
||||
if (!child) {
|
||||
child = ChromeBrowsingContext::Create(aChildId, aName, ChildID());
|
||||
child = BrowsingContext::CreateFromIPC(parent, aName, (uint64_t)aChildId, this);
|
||||
}
|
||||
child->Attach(parent);
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsDocShell.h"
|
||||
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
|
||||
//---------------------------------------------------
|
||||
//-- nsPrintObject Class Impl
|
||||
|
@ -56,11 +59,21 @@ nsPrintObject::Init(nsIDocShell* aDocShell, nsIDocument* aDoc,
|
|||
mDocShell = aDocShell;
|
||||
} else {
|
||||
mTreeOwner = do_GetInterface(aDocShell);
|
||||
|
||||
// Create a new BrowsingContext to create our DocShell in.
|
||||
RefPtr<BrowsingContext> bc = BrowsingContext::Create(
|
||||
nullptr,
|
||||
EmptyString(),
|
||||
aDocShell->ItemType() == nsIDocShellTreeItem::typeContent
|
||||
? BrowsingContext::Type::Content
|
||||
: BrowsingContext::Type::Chrome);
|
||||
|
||||
// Create a container docshell for printing.
|
||||
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
|
||||
mDocShell = nsDocShell::Create(bc);
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
mDidCreateDocShell = true;
|
||||
mDocShell->SetItemType(aDocShell->ItemType());
|
||||
MOZ_ASSERT(mDocShell->ItemType() == aDocShell->ItemType());
|
||||
mDocShell->SetTreeOwner(mTreeOwner);
|
||||
}
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
|
@ -104,4 +117,3 @@ nsPrintObject::DestroyPresentation()
|
|||
mPresContext = nullptr;
|
||||
mViewManager = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "nsDocShell.h"
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
|
||||
// for painting the background window
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
|
@ -979,10 +980,22 @@ nsWebBrowser::Create()
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(
|
||||
do_CreateInstance("@mozilla.org/docshell;1", &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsDocShell::Cast(docShell)->SetOriginAttributes(mOriginAttributes);
|
||||
// XXX(nika): Consider supporting creating nsWebBrowser for an existing
|
||||
// BrowsingContext (e.g. during a X-process load).
|
||||
// XXX(nika): Get window opener information into nsWebBrowser::Create.
|
||||
using BrowsingContext = mozilla::dom::BrowsingContext;
|
||||
RefPtr<mozilla::dom::BrowsingContext> browsingContext =
|
||||
BrowsingContext::Create(nullptr,
|
||||
mInitInfo->name,
|
||||
mContentType != typeChromeWrapper
|
||||
? BrowsingContext::Type::Content
|
||||
: BrowsingContext::Type::Chrome);
|
||||
|
||||
RefPtr<nsDocShell> docShell = nsDocShell::Create(browsingContext);
|
||||
if (NS_WARN_IF(!docShell)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
docShell->SetOriginAttributes(mOriginAttributes);
|
||||
rv = SetDocShell(docShell);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -1006,14 +1019,7 @@ nsWebBrowser::Create()
|
|||
mInitInfo->cx, mInitInfo->cy),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
mDocShell->SetName(mInitInfo->name);
|
||||
if (mContentType == typeChromeWrapper) {
|
||||
mDocShell->SetItemType(nsIDocShellTreeItem::typeChrome);
|
||||
} else {
|
||||
mDocShell->SetItemType(nsIDocShellTreeItem::typeContent);
|
||||
}
|
||||
mDocShell->SetTreeOwner(mDocShellTreeOwner);
|
||||
mDocShell->AttachBrowsingContext(nullptr);
|
||||
|
||||
// If the webbrowser is a content docshell item then we won't hear any
|
||||
// events from subframes. To solve that we install our own chrome event
|
||||
|
|
|
@ -56,12 +56,15 @@
|
|||
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsDocShell.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
|
||||
#include "nsPIWindowRoot.h"
|
||||
|
||||
#include "gfxPlatform.h"
|
||||
|
@ -179,9 +182,14 @@ nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
|
|||
mWindow->SetBackgroundColor(NS_RGB(255,255,255));
|
||||
|
||||
// Create web shell
|
||||
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
|
||||
RefPtr<BrowsingContext> browsingContext =
|
||||
BrowsingContext::Create(nullptr, EmptyString(), BrowsingContext::Type::Chrome);
|
||||
mDocShell = nsDocShell::Create(browsingContext);
|
||||
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
||||
|
||||
// XXX(nika): This is used to handle propagating opener across remote tab
|
||||
// creation. We should come up with a better system for doing this (probably
|
||||
// based on BrowsingContext).
|
||||
mDocShell->SetOpener(aOpeningTab);
|
||||
|
||||
// Make sure to set the item type on the docshell _before_ calling
|
||||
|
@ -191,9 +199,6 @@ nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
|
|||
NS_ENSURE_SUCCESS(EnsureChromeTreeOwner(), NS_ERROR_FAILURE);
|
||||
|
||||
docShellAsItem->SetTreeOwner(mChromeTreeOwner);
|
||||
docShellAsItem->SetItemType(nsIDocShellTreeItem::typeChrome);
|
||||
|
||||
mDocShell->AttachBrowsingContext(nullptr);
|
||||
|
||||
r.MoveTo(0, 0);
|
||||
nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
|
||||
|
|
Загрузка…
Ссылка в новой задаче