mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
eac76d9772
This patch removes support for mozapp iframes, leaving support for mozbrowser iframes intact. Some of the code has been rewritten in order to phrase things in terms of mozbrowser only, as opposed to mozbrowser or app. In some places, code that was only useful with apps has been completely removed, so that the APIs consumed can also be removed. In some places where the notion of appId was bleeding out of this API, now we use NO_APP_ID. Other notions of appId which were restricted to this API have been removed.
355 lines
11 KiB
C++
355 lines
11 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nsInProcessTabChildGlobal.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsIScriptSecurityManager.h"
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
#include "nsIComponentManager.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsComponentManagerUtils.h"
|
|
#include "nsScriptLoader.h"
|
|
#include "nsFrameLoader.h"
|
|
#include "xpcpublic.h"
|
|
#include "nsIMozBrowserFrame.h"
|
|
#include "nsDOMClassInfoID.h"
|
|
#include "mozilla/EventDispatcher.h"
|
|
#include "mozilla/dom/SameProcessMessageQueue.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::dom;
|
|
using namespace mozilla::dom::ipc;
|
|
|
|
bool
|
|
nsInProcessTabChildGlobal::DoSendBlockingMessage(JSContext* aCx,
|
|
const nsAString& aMessage,
|
|
StructuredCloneData& aData,
|
|
JS::Handle<JSObject *> aCpows,
|
|
nsIPrincipal* aPrincipal,
|
|
nsTArray<StructuredCloneData>* aRetVal,
|
|
bool aIsSync)
|
|
{
|
|
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
|
|
queue->Flush();
|
|
|
|
if (mChromeMessageManager) {
|
|
SameProcessCpowHolder cpows(JS::RootingContext::get(aCx), aCpows);
|
|
RefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
|
|
nsCOMPtr<nsIFrameLoader> fl = GetFrameLoader();
|
|
mm->ReceiveMessage(mOwner, fl, aMessage, true, &aData, &cpows, aPrincipal,
|
|
aRetVal);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
class nsAsyncMessageToParent : public nsSameProcessAsyncMessageBase,
|
|
public SameProcessMessageQueue::Runnable
|
|
{
|
|
public:
|
|
nsAsyncMessageToParent(JS::RootingContext* aRootingCx,
|
|
JS::Handle<JSObject*> aCpows,
|
|
nsInProcessTabChildGlobal* aTabChild)
|
|
: nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
|
|
, mTabChild(aTabChild)
|
|
{ }
|
|
|
|
virtual nsresult HandleMessage() override
|
|
{
|
|
nsCOMPtr<nsIFrameLoader> fl = mTabChild->GetFrameLoader();
|
|
ReceiveMessage(mTabChild->mOwner, fl, mTabChild->mChromeMessageManager);
|
|
return NS_OK;
|
|
}
|
|
RefPtr<nsInProcessTabChildGlobal> mTabChild;
|
|
};
|
|
|
|
nsresult
|
|
nsInProcessTabChildGlobal::DoSendAsyncMessage(JSContext* aCx,
|
|
const nsAString& aMessage,
|
|
StructuredCloneData& aData,
|
|
JS::Handle<JSObject *> aCpows,
|
|
nsIPrincipal* aPrincipal)
|
|
{
|
|
SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
|
|
JS::RootingContext* rcx = JS::RootingContext::get(aCx);
|
|
RefPtr<nsAsyncMessageToParent> ev =
|
|
new nsAsyncMessageToParent(rcx, aCpows, this);
|
|
|
|
nsresult rv = ev->Init(aMessage, aData, aPrincipal);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
queue->Push(ev);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
|
|
nsIContent* aOwner,
|
|
nsFrameMessageManager* aChrome)
|
|
: mDocShell(aShell), mInitialized(false), mLoadingScript(false),
|
|
mPreventEventsEscaping(false),
|
|
mOwner(aOwner), mChromeMessageManager(aChrome)
|
|
{
|
|
SetIsNotDOMBinding();
|
|
mozilla::HoldJSObjects(this);
|
|
|
|
// If owner corresponds to an <iframe mozbrowser>, we'll have to tweak our
|
|
// GetEventTargetParent implementation.
|
|
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
|
|
if (browserFrame) {
|
|
mIsBrowserFrame = browserFrame->GetReallyIsBrowser();
|
|
}
|
|
else {
|
|
mIsBrowserFrame = false;
|
|
}
|
|
}
|
|
|
|
nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
|
|
{
|
|
mAnonymousGlobalScopes.Clear();
|
|
mozilla::DropJSObjects(this);
|
|
}
|
|
|
|
// This method isn't automatically forwarded safely because it's notxpcom, so
|
|
// the IDL binding doesn't know what value to return.
|
|
NS_IMETHODIMP_(bool)
|
|
nsInProcessTabChildGlobal::MarkForCC()
|
|
{
|
|
MarkScopesForCC();
|
|
return mMessageManager ? mMessageManager->MarkForCC() : false;
|
|
}
|
|
|
|
nsresult
|
|
nsInProcessTabChildGlobal::Init()
|
|
{
|
|
#ifdef DEBUG
|
|
nsresult rv =
|
|
#endif
|
|
InitTabChildGlobal();
|
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
|
"Couldn't initialize nsInProcessTabChildGlobal");
|
|
mMessageManager = new nsFrameMessageManager(this,
|
|
nullptr,
|
|
dom::ipc::MM_CHILD);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsInProcessTabChildGlobal)
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
|
|
DOMEventTargetHelper)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
|
|
tmp->TraverseHostObjectURIs(cb);
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
|
|
DOMEventTargetHelper)
|
|
tmp->nsMessageManagerScriptExecutor::Trace(aCallbacks, aClosure);
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsInProcessTabChildGlobal,
|
|
DOMEventTargetHelper)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnonymousGlobalScopes)
|
|
tmp->UnlinkHostObjectURIs();
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal)
|
|
NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
|
|
NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
|
|
NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
|
|
NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
|
|
NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
|
|
NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
|
|
NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
|
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
|
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
|
|
|
NS_IMPL_ADDREF_INHERITED(nsInProcessTabChildGlobal, DOMEventTargetHelper)
|
|
NS_IMPL_RELEASE_INHERITED(nsInProcessTabChildGlobal, DOMEventTargetHelper)
|
|
|
|
void
|
|
nsInProcessTabChildGlobal::CacheFrameLoader(nsIFrameLoader* aFrameLoader)
|
|
{
|
|
mFrameLoader = aFrameLoader;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsInProcessTabChildGlobal::GetContent(mozIDOMWindowProxy** aContent)
|
|
{
|
|
*aContent = nullptr;
|
|
if (!mDocShell) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell->GetWindow();
|
|
window.forget(aContent);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
|
|
{
|
|
NS_IF_ADDREF(*aDocShell = mDocShell);
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsInProcessTabChildGlobal::FireUnloadEvent()
|
|
{
|
|
// We're called from nsDocument::MaybeInitializeFinalizeFrameLoaders, so it
|
|
// should be safe to run script.
|
|
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
|
|
|
|
// Don't let the unload event propagate to chrome event handlers.
|
|
mPreventEventsEscaping = true;
|
|
DOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
|
|
|
|
// Allow events fired during docshell destruction (pagehide, unload) to
|
|
// propagate to the <browser> element since chrome code depends on this.
|
|
mPreventEventsEscaping = false;
|
|
}
|
|
|
|
void
|
|
nsInProcessTabChildGlobal::DisconnectEventListeners()
|
|
{
|
|
if (mDocShell) {
|
|
if (nsCOMPtr<nsPIDOMWindowOuter> win = mDocShell->GetWindow()) {
|
|
MOZ_ASSERT(win->IsOuterWindow());
|
|
win->SetChromeEventHandler(win->GetChromeEventHandler());
|
|
}
|
|
}
|
|
if (mListenerManager) {
|
|
mListenerManager->Disconnect();
|
|
}
|
|
|
|
mDocShell = nullptr;
|
|
}
|
|
|
|
void
|
|
nsInProcessTabChildGlobal::Disconnect()
|
|
{
|
|
mChromeMessageManager = nullptr;
|
|
mOwner = nullptr;
|
|
if (mMessageManager) {
|
|
static_cast<nsFrameMessageManager*>(mMessageManager.get())->Disconnect();
|
|
mMessageManager = nullptr;
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP_(nsIContent *)
|
|
nsInProcessTabChildGlobal::GetOwnerContent()
|
|
{
|
|
return mOwner;
|
|
}
|
|
|
|
nsresult
|
|
nsInProcessTabChildGlobal::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
|
{
|
|
aVisitor.mForceContentDispatch = true;
|
|
aVisitor.mCanHandle = true;
|
|
|
|
#ifdef DEBUG
|
|
if (mOwner) {
|
|
nsCOMPtr<nsIFrameLoaderOwner> owner = do_QueryInterface(mOwner);
|
|
RefPtr<nsFrameLoader> fl = owner->GetFrameLoader();
|
|
if (fl) {
|
|
NS_ASSERTION(this == fl->GetTabChildGlobalAsEventTarget(),
|
|
"Wrong event target!");
|
|
NS_ASSERTION(fl->mMessageManager == mChromeMessageManager,
|
|
"Wrong message manager!");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (mPreventEventsEscaping) {
|
|
aVisitor.mParentTarget = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
if (mIsBrowserFrame &&
|
|
(!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) {
|
|
if (mOwner) {
|
|
if (nsPIDOMWindowInner* innerWindow = mOwner->OwnerDoc()->GetInnerWindow()) {
|
|
aVisitor.mParentTarget = innerWindow->GetParentTarget();
|
|
}
|
|
}
|
|
} else {
|
|
aVisitor.mParentTarget = mOwner;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsInProcessTabChildGlobal::InitTabChildGlobal()
|
|
{
|
|
// If you change this, please change GetCompartmentName() in XPCJSContext.cpp
|
|
// accordingly.
|
|
nsAutoCString id;
|
|
id.AssignLiteral("inProcessTabChildGlobal");
|
|
nsIURI* uri = mOwner->OwnerDoc()->GetDocumentURI();
|
|
if (uri) {
|
|
nsAutoCString u;
|
|
nsresult rv = uri->GetSpec(u);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
id.AppendLiteral("?ownedBy=");
|
|
id.Append(u);
|
|
}
|
|
nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, this);
|
|
NS_ENSURE_STATE(InitChildGlobalInternal(scopeSupports, id));
|
|
return NS_OK;
|
|
}
|
|
|
|
class nsAsyncScriptLoad : public Runnable
|
|
{
|
|
public:
|
|
nsAsyncScriptLoad(nsInProcessTabChildGlobal* aTabChild, const nsAString& aURL,
|
|
bool aRunInGlobalScope)
|
|
: mTabChild(aTabChild), mURL(aURL), mRunInGlobalScope(aRunInGlobalScope) {}
|
|
|
|
NS_IMETHOD Run() override
|
|
{
|
|
mTabChild->LoadFrameScript(mURL, mRunInGlobalScope);
|
|
return NS_OK;
|
|
}
|
|
RefPtr<nsInProcessTabChildGlobal> mTabChild;
|
|
nsString mURL;
|
|
bool mRunInGlobalScope;
|
|
};
|
|
|
|
void
|
|
nsInProcessTabChildGlobal::LoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope)
|
|
{
|
|
if (!nsContentUtils::IsSafeToRunScript()) {
|
|
nsContentUtils::AddScriptRunner(new nsAsyncScriptLoad(this, aURL, aRunInGlobalScope));
|
|
return;
|
|
}
|
|
if (!mInitialized) {
|
|
mInitialized = true;
|
|
Init();
|
|
}
|
|
bool tmp = mLoadingScript;
|
|
mLoadingScript = true;
|
|
LoadScriptInternal(aURL, aRunInGlobalScope);
|
|
mLoadingScript = tmp;
|
|
}
|
|
|
|
already_AddRefed<nsIFrameLoader>
|
|
nsInProcessTabChildGlobal::GetFrameLoader()
|
|
{
|
|
nsCOMPtr<nsIFrameLoaderOwner> owner = do_QueryInterface(mOwner);
|
|
nsCOMPtr<nsIFrameLoader> fl = owner ? owner->GetFrameLoader() : nullptr;
|
|
if (!fl) {
|
|
fl = mFrameLoader;
|
|
}
|
|
return fl.forget();
|
|
}
|