2014-06-11 09:44:03 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2015-05-03 22:32:37 +03:00
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2014-06-11 09:44:03 +04:00
|
|
|
/* 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 "nsIContentParent.h"
|
|
|
|
|
|
|
|
#include "mozilla/AppProcessChecker.h"
|
|
|
|
#include "mozilla/Preferences.h"
|
2014-10-08 20:15:23 +04:00
|
|
|
#include "mozilla/dom/File.h"
|
2014-06-11 09:44:03 +04:00
|
|
|
#include "mozilla/dom/ContentParent.h"
|
2015-08-31 08:53:00 +03:00
|
|
|
#include "mozilla/dom/ContentBridgeParent.h"
|
2014-06-11 09:44:03 +04:00
|
|
|
#include "mozilla/dom/PTabContext.h"
|
|
|
|
#include "mozilla/dom/PermissionMessageUtils.h"
|
|
|
|
#include "mozilla/dom/TabParent.h"
|
2014-09-27 03:21:57 +04:00
|
|
|
#include "mozilla/dom/ipc/BlobParent.h"
|
2015-09-10 23:50:58 +03:00
|
|
|
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
2015-01-27 00:32:18 +03:00
|
|
|
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
2014-06-11 09:44:03 +04:00
|
|
|
#include "mozilla/unused.h"
|
|
|
|
|
|
|
|
#include "nsFrameMessageManager.h"
|
|
|
|
#include "nsPrintfCString.h"
|
2015-06-27 04:44:14 +03:00
|
|
|
#include "xpcpublic.h"
|
2014-06-11 09:44:03 +04:00
|
|
|
|
|
|
|
using namespace mozilla::jsipc;
|
|
|
|
|
2014-10-29 21:11:00 +03:00
|
|
|
// XXX need another bug to move this to a common header.
|
|
|
|
#ifdef DISABLE_ASSERTS_FOR_FUZZING
|
2015-02-07 02:05:08 +03:00
|
|
|
#define ASSERT_UNLESS_FUZZING(...) do { } while (0)
|
2014-10-29 21:11:00 +03:00
|
|
|
#else
|
2015-02-07 02:05:08 +03:00
|
|
|
#define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
|
2014-10-29 21:11:00 +03:00
|
|
|
#endif
|
|
|
|
|
2014-06-11 09:44:03 +04:00
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
|
|
|
|
|
|
nsIContentParent::nsIContentParent()
|
|
|
|
{
|
2015-03-06 04:03:25 +03:00
|
|
|
mMessageManager = nsFrameMessageManager::NewProcessMessageManager(true);
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
ContentParent*
|
|
|
|
nsIContentParent::AsContentParent()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsContentParent());
|
|
|
|
return static_cast<ContentParent*>(this);
|
|
|
|
}
|
|
|
|
|
2015-08-31 08:53:00 +03:00
|
|
|
ContentBridgeParent*
|
|
|
|
nsIContentParent::AsContentBridgeParent()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsContentBridgeParent());
|
|
|
|
return static_cast<ContentBridgeParent*>(this);
|
|
|
|
}
|
|
|
|
|
2014-06-11 09:44:03 +04:00
|
|
|
PJavaScriptParent*
|
|
|
|
nsIContentParent::AllocPJavaScriptParent()
|
|
|
|
{
|
2015-06-27 04:44:14 +03:00
|
|
|
return NewJavaScriptParent(xpc::GetJSRuntime());
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsIContentParent::DeallocPJavaScriptParent(PJavaScriptParent* aParent)
|
|
|
|
{
|
2015-01-27 00:32:18 +03:00
|
|
|
ReleaseJavaScriptParent(aParent);
|
2014-06-11 09:44:03 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-06-11 09:44:13 +04:00
|
|
|
bool
|
|
|
|
nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext)
|
2014-06-11 09:44:03 +04:00
|
|
|
{
|
2015-10-07 06:47:46 +03:00
|
|
|
const IPCTabContextUnion& contextUnion = aContext.contextUnion();
|
2014-06-11 09:44:03 +04:00
|
|
|
|
|
|
|
// We don't trust the IPCTabContext we receive from the child, so we'll bail
|
|
|
|
// if we receive an IPCTabContext that's not a PopupIPCTabContext.
|
|
|
|
// (PopupIPCTabContext lets the child process prove that it has access to
|
|
|
|
// the app it's trying to open.)
|
2015-10-07 06:47:46 +03:00
|
|
|
if (contextUnion.type() != IPCTabContextUnion::TPopupIPCTabContext) {
|
2015-02-07 02:05:08 +03:00
|
|
|
ASSERT_UNLESS_FUZZING("Unexpected IPCTabContext type. Aborting AllocPBrowserParent.");
|
2014-06-11 09:44:13 +04:00
|
|
|
return false;
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
|
2015-10-07 06:47:46 +03:00
|
|
|
const PopupIPCTabContext& popupContext = contextUnion.get_PopupIPCTabContext();
|
2014-10-29 21:11:00 +03:00
|
|
|
if (popupContext.opener().type() != PBrowserOrId::TPBrowserParent) {
|
2015-02-07 02:05:08 +03:00
|
|
|
ASSERT_UNLESS_FUZZING("Unexpected PopupIPCTabContext type. Aborting AllocPBrowserParent.");
|
2014-10-29 21:11:00 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-02-06 00:47:32 +03:00
|
|
|
auto opener = TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
|
2014-06-11 09:44:03 +04:00
|
|
|
if (!opener) {
|
2015-02-07 02:05:08 +03:00
|
|
|
ASSERT_UNLESS_FUZZING("Got null opener from child; aborting AllocPBrowserParent.");
|
2014-06-11 09:44:13 +04:00
|
|
|
return false;
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Popup windows of isBrowser frames must be isBrowser if the parent
|
|
|
|
// isBrowser. Allocating a !isBrowser frame with same app ID would allow
|
|
|
|
// the content to access data it's not supposed to.
|
|
|
|
if (!popupContext.isBrowserElement() && opener->IsBrowserElement()) {
|
2015-02-07 02:05:08 +03:00
|
|
|
ASSERT_UNLESS_FUZZING("Child trying to escalate privileges! Aborting AllocPBrowserParent.");
|
2014-06-11 09:44:13 +04:00
|
|
|
return false;
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
MaybeInvalidTabContext tc(aContext);
|
|
|
|
if (!tc.IsValid()) {
|
|
|
|
NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext. (%s) "
|
|
|
|
"Aborting AllocPBrowserParent.",
|
|
|
|
tc.GetInvalidReason()).get());
|
2014-06-11 09:44:13 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
PBrowserParent*
|
2014-10-29 21:11:00 +03:00
|
|
|
nsIContentParent::AllocPBrowserParent(const TabId& aTabId,
|
|
|
|
const IPCTabContext& aContext,
|
2014-06-11 09:44:13 +04:00
|
|
|
const uint32_t& aChromeFlags,
|
2014-10-24 04:28:00 +04:00
|
|
|
const ContentParentId& aCpId,
|
2014-06-11 09:44:13 +04:00
|
|
|
const bool& aIsForApp,
|
|
|
|
const bool& aIsForBrowser)
|
|
|
|
{
|
2014-10-24 04:28:00 +04:00
|
|
|
unused << aCpId;
|
2014-06-11 09:44:13 +04:00
|
|
|
unused << aIsForApp;
|
|
|
|
unused << aIsForBrowser;
|
|
|
|
|
|
|
|
if (!CanOpenBrowser(aContext)) {
|
2014-06-11 09:44:03 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-10-07 06:47:46 +03:00
|
|
|
const IPCTabContextUnion& contextUnion = aContext.contextUnion();
|
|
|
|
const PopupIPCTabContext& popupContext = contextUnion.get_PopupIPCTabContext();
|
2015-09-17 22:15:33 +03:00
|
|
|
|
|
|
|
uint32_t chromeFlags = aChromeFlags;
|
|
|
|
|
|
|
|
// CanOpenBrowser has ensured that the IPCTabContext is of
|
|
|
|
// type PopupIPCTabContext, and that the opener TabParent is
|
|
|
|
// reachable.
|
|
|
|
auto opener = TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
|
|
|
|
// We must ensure that the private browsing and remoteness flags
|
|
|
|
// match those of the opener.
|
|
|
|
nsCOMPtr<nsILoadContext> loadContext = opener->GetLoadContext();
|
|
|
|
if (!loadContext) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isPrivate;
|
|
|
|
loadContext->GetUsePrivateBrowsing(&isPrivate);
|
|
|
|
if (isPrivate) {
|
|
|
|
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
|
|
|
|
}
|
|
|
|
|
|
|
|
// And because we're allocating a remote browser, of course the
|
|
|
|
// window is remote.
|
|
|
|
chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
|
|
|
|
|
2014-06-11 09:44:13 +04:00
|
|
|
MaybeInvalidTabContext tc(aContext);
|
|
|
|
MOZ_ASSERT(tc.IsValid());
|
2015-09-17 22:15:33 +03:00
|
|
|
TabParent* parent = new TabParent(this, aTabId, tc.GetTabContext(), chromeFlags);
|
2014-06-11 09:44:03 +04:00
|
|
|
|
|
|
|
// We release this ref in DeallocPBrowserParent()
|
|
|
|
NS_ADDREF(parent);
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsIContentParent::DeallocPBrowserParent(PBrowserParent* aFrame)
|
|
|
|
{
|
2015-02-06 00:47:32 +03:00
|
|
|
TabParent* parent = TabParent::GetFrom(aFrame);
|
2014-06-11 09:44:03 +04:00
|
|
|
NS_RELEASE(parent);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
PBlobParent*
|
|
|
|
nsIContentParent::AllocPBlobParent(const BlobConstructorParams& aParams)
|
|
|
|
{
|
|
|
|
return BlobParent::Create(this, aParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsIContentParent::DeallocPBlobParent(PBlobParent* aActor)
|
|
|
|
{
|
2014-09-27 03:21:57 +04:00
|
|
|
BlobParent::Destroy(aActor);
|
2014-06-11 09:44:03 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlobParent*
|
2015-05-12 15:09:51 +03:00
|
|
|
nsIContentParent::GetOrCreateActorForBlob(Blob* aBlob)
|
2014-06-11 09:44:03 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(aBlob);
|
|
|
|
|
2015-05-12 15:11:03 +03:00
|
|
|
nsRefPtr<BlobImpl> blobImpl = aBlob->Impl();
|
2014-09-27 03:21:57 +04:00
|
|
|
MOZ_ASSERT(blobImpl);
|
2014-06-11 09:44:03 +04:00
|
|
|
|
2015-05-12 15:11:03 +03:00
|
|
|
return GetOrCreateActorForBlobImpl(blobImpl);
|
2015-05-12 15:09:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
BlobParent*
|
2015-05-12 15:11:03 +03:00
|
|
|
nsIContentParent::GetOrCreateActorForBlobImpl(BlobImpl* aImpl)
|
2015-05-12 15:09:51 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(aImpl);
|
|
|
|
|
|
|
|
BlobParent* actor = BlobParent::GetOrCreate(this, aImpl);
|
2014-06-11 09:44:03 +04:00
|
|
|
NS_ENSURE_TRUE(actor, nullptr);
|
|
|
|
|
2014-09-27 03:21:57 +04:00
|
|
|
return actor;
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsIContentParent::RecvSyncMessage(const nsString& aMsg,
|
|
|
|
const ClonedMessageData& aData,
|
2015-01-16 22:58:52 +03:00
|
|
|
InfallibleTArray<CpowEntry>&& aCpows,
|
2014-06-11 09:44:03 +04:00
|
|
|
const IPC::Principal& aPrincipal,
|
2015-09-10 23:50:58 +03:00
|
|
|
nsTArray<ipc::StructuredCloneData>* aRetvals)
|
2014-06-11 09:44:03 +04:00
|
|
|
{
|
|
|
|
// FIXME Permission check in Content process
|
|
|
|
nsIPrincipal* principal = aPrincipal;
|
2014-06-14 11:32:24 +04:00
|
|
|
if (IsContentParent()) {
|
|
|
|
ContentParent* parent = AsContentParent();
|
|
|
|
if (!ContentParent::IgnoreIPCPrincipal() &&
|
|
|
|
parent && principal && !AssertAppPrincipal(parent, principal)) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
|
|
|
|
if (ppm) {
|
2015-09-10 23:50:58 +03:00
|
|
|
ipc::StructuredCloneData data;
|
|
|
|
ipc::UnpackClonedMessageDataForParent(aData, data);
|
2015-09-02 19:20:30 +03:00
|
|
|
|
2015-01-27 00:32:31 +03:00
|
|
|
CrossProcessCpowHolder cpows(this, aCpows);
|
2015-04-16 18:17:54 +03:00
|
|
|
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr,
|
2015-09-10 23:50:58 +03:00
|
|
|
aMsg, true, &data, &cpows, aPrincipal, aRetvals);
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-10-08 08:32:45 +04:00
|
|
|
nsIContentParent::RecvRpcMessage(const nsString& aMsg,
|
|
|
|
const ClonedMessageData& aData,
|
2015-01-16 22:58:52 +03:00
|
|
|
InfallibleTArray<CpowEntry>&& aCpows,
|
2014-10-08 08:32:45 +04:00
|
|
|
const IPC::Principal& aPrincipal,
|
2015-09-10 23:50:58 +03:00
|
|
|
nsTArray<ipc::StructuredCloneData>* aRetvals)
|
2014-06-11 09:44:03 +04:00
|
|
|
{
|
|
|
|
// FIXME Permission check in Content process
|
|
|
|
nsIPrincipal* principal = aPrincipal;
|
2014-06-14 11:32:24 +04:00
|
|
|
if (IsContentParent()) {
|
|
|
|
ContentParent* parent = AsContentParent();
|
|
|
|
if (!ContentParent::IgnoreIPCPrincipal() &&
|
|
|
|
parent && principal && !AssertAppPrincipal(parent, principal)) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
|
|
|
|
if (ppm) {
|
2015-09-10 23:50:58 +03:00
|
|
|
ipc::StructuredCloneData data;
|
|
|
|
ipc::UnpackClonedMessageDataForParent(aData, data);
|
2015-09-02 19:20:30 +03:00
|
|
|
|
2015-01-27 00:32:31 +03:00
|
|
|
CrossProcessCpowHolder cpows(this, aCpows);
|
2015-04-16 18:17:54 +03:00
|
|
|
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr,
|
2015-09-10 23:50:58 +03:00
|
|
|
aMsg, true, &data, &cpows, aPrincipal, aRetvals);
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsIContentParent::RecvAsyncMessage(const nsString& aMsg,
|
|
|
|
const ClonedMessageData& aData,
|
2015-01-16 22:58:52 +03:00
|
|
|
InfallibleTArray<CpowEntry>&& aCpows,
|
2014-06-11 09:44:03 +04:00
|
|
|
const IPC::Principal& aPrincipal)
|
|
|
|
{
|
|
|
|
// FIXME Permission check in Content process
|
|
|
|
nsIPrincipal* principal = aPrincipal;
|
2014-06-14 11:32:24 +04:00
|
|
|
if (IsContentParent()) {
|
|
|
|
ContentParent* parent = AsContentParent();
|
|
|
|
if (!ContentParent::IgnoreIPCPrincipal() &&
|
|
|
|
parent && principal && !AssertAppPrincipal(parent, principal)) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
|
|
|
|
if (ppm) {
|
2015-09-10 23:50:58 +03:00
|
|
|
ipc::StructuredCloneData data;
|
|
|
|
ipc::UnpackClonedMessageDataForParent(aData, data);
|
2015-09-02 19:20:30 +03:00
|
|
|
|
2015-01-27 00:32:31 +03:00
|
|
|
CrossProcessCpowHolder cpows(this, aCpows);
|
2015-04-16 18:17:54 +03:00
|
|
|
ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr,
|
2015-09-10 23:50:58 +03:00
|
|
|
aMsg, false, &data, &cpows, aPrincipal, nullptr);
|
2014-06-11 09:44:03 +04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|