Bug 1638373 - remove js/ipc now that CPOWs are dead, r=mccr8

Depends on D76597

Differential Revision: https://phabricator.services.mozilla.com/D76598
This commit is contained in:
Gijs Kruitbosch 2020-05-24 18:47:04 +00:00
parent 2f983e6cfa
commit 38b061ef45
41 changed files with 6 additions and 4645 deletions

View file

@ -135,7 +135,6 @@ intl/l10n/
# Exclude everything but self-hosted JS
js/ductwork/
js/examples/
js/ipc/
js/public/
js/xpconnect/
js/src/devtools/

View file

@ -68,7 +68,6 @@
#include "mozilla/dom/WorkerScope.h"
#include "mozilla/dom/XrayExpandoClass.h"
#include "mozilla/dom/WindowProxyHolder.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "ipc/ErrorIPCUtils.h"
#include "mozilla/UseCounter.h"
#include "mozilla/dom/DocGroup.h"
@ -2387,16 +2386,6 @@ bool InterfaceHasInstance(JSContext* cx, unsigned argc, JS::Value* vp) {
return true;
}
if (jsipc::IsWrappedCPOW(instance)) {
bool boolp = false;
if (!jsipc::DOMInstanceOf(cx, js::UncheckedUnwrap(instance),
clasp->mPrototypeID, clasp->mDepth, &boolp)) {
return false;
}
args.rval().setBoolean(boolp);
return true;
}
if (IsRemoteObjectProxy(instance, clasp->mPrototypeID)) {
args.rval().setBoolean(true);
return true;

View file

@ -1,26 +0,0 @@
/* -*- 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/. */
#ifndef mozilla_dom_CPOWManagerGetter_h
#define mozilla_dom_CPOWManagerGetter_h
namespace mozilla {
namespace jsipc {
class CPOWManager;
} /* namespace jsipc */
namespace dom {
class CPOWManagerGetter {
public:
virtual mozilla::jsipc::CPOWManager* GetCPOWManager() = 0;
};
} /* namespace dom */
} /* namespace mozilla */
#endif /* mozilla_dom_CPOWManagerGetter_h */

View file

@ -81,8 +81,6 @@
#include "mozilla/ipc/PParentToChildStreamChild.h"
#include "mozilla/intl/LocaleService.h"
#include "mozilla/ipc/TestShellChild.h"
// Needed for NewJavaScriptChild and ReleaseJavaScriptChild
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/layers/APZChild.h"
#include "mozilla/layers/CompositorManagerChild.h"
#include "mozilla/layers/ContentProcessController.h"
@ -1301,9 +1299,6 @@ void ContentChild::InitXPCOM(
RecvBidiKeyboardNotify(aXPCOMInit.isLangRTL(),
aXPCOMInit.haveBidiKeyboards());
// Create the CPOW manager as soon as possible.
SendPJavaScriptConstructor();
if (aXPCOMInit.domainPolicy().active()) {
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
MOZ_ASSERT(ssm);
@ -1691,17 +1686,6 @@ static void FirstIdle(void) {
ContentChild::GetSingleton()->SendFirstIdle();
}
mozilla::jsipc::PJavaScriptChild* ContentChild::AllocPJavaScriptChild() {
MOZ_ASSERT(ManagedPJavaScriptChild().IsEmpty());
return jsipc::NewJavaScriptChild();
}
bool ContentChild::DeallocPJavaScriptChild(PJavaScriptChild* aChild) {
jsipc::ReleaseJavaScriptChild(aChild);
return true;
}
mozilla::ipc::IPCResult ContentChild::RecvConstructBrowser(
ManagedEndpoint<PBrowserChild>&& aBrowserEp,
ManagedEndpoint<PWindowGlobalChild>&& aWindowEp, const TabId& aTabId,
@ -3509,7 +3493,6 @@ mozilla::ipc::IPCResult ContentChild::RecvSessionStorageData(
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvOnAllowAccessFor(
const MaybeDiscarded<BrowsingContext>& aContext,
const nsCString& aTrackingOrigin, uint32_t aCookieBehavior,

View file

@ -289,10 +289,6 @@ class ContentChild final : public PContentChild,
mozilla::ipc::IPCResult RecvClearImageCache(const bool& privateLoader,
const bool& chrome);
mozilla::jsipc::PJavaScriptChild* AllocPJavaScriptChild();
bool DeallocPJavaScriptChild(mozilla::jsipc::PJavaScriptChild*);
PRemoteSpellcheckEngineChild* AllocPRemoteSpellcheckEngineChild();
bool DeallocPRemoteSpellcheckEngineChild(PRemoteSpellcheckEngineChild*);
@ -794,7 +790,7 @@ class ContentChild final : public PContentChild,
mozilla::ipc::IPCResult RecvHistoryCommitLength(
const MaybeDiscarded<BrowsingContext>& aContext, uint32_t aLength);
private:
private:
#ifdef NIGHTLY_BUILD
virtual PContentChild::Result OnMessageReceived(const Message& aMsg) override;
#else

View file

@ -137,8 +137,6 @@
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/PChildToParentStreamParent.h"
#include "mozilla/ipc/TestShellParent.h"
// Needed for NewJavaScriptChild and ReleaseJavaScriptChild
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageBridgeParent.h"
#include "mozilla/layers/LayerTreeOwnerTracker.h"
@ -3127,16 +3125,6 @@ mozilla::ipc::IPCResult ContentParent::RecvInitBackground(
return IPC_OK();
}
mozilla::jsipc::PJavaScriptParent* ContentParent::AllocPJavaScriptParent() {
MOZ_ASSERT(ManagedPJavaScriptParent().IsEmpty());
return jsipc::NewJavaScriptParent();
}
bool ContentParent::DeallocPJavaScriptParent(PJavaScriptParent* parent) {
jsipc::ReleaseJavaScriptParent(parent);
return true;
}
bool ContentParent::CanOpenBrowser(const IPCTabContext& aContext) {
// (PopupIPCTabContext lets the child process prove that it has access to
// the app it's trying to open.)
@ -6380,7 +6368,7 @@ mozilla::ipc::IPCResult ContentParent::RecvHistoryGo(
HistoryGoResolver&& aResolveRequestedIndex) {
if (!aContext.IsDiscarded()) {
nsSHistory* shistory =
static_cast<nsSHistory*>(aContext.get_canonical()->GetSessionHistory());
static_cast<nsSHistory*>(aContext.get_canonical()->GetSessionHistory());
nsTArray<nsSHistory::LoadEntryResult> loadResults;
nsresult rv = shistory->GotoIndex(aOffset, loadResults);
if (NS_FAILED(rv)) {

View file

@ -101,10 +101,6 @@ class ProtocolFuzzerHelper;
class SharedPreferenceSerializer;
} // namespace ipc
namespace jsipc {
class PJavaScriptParent;
} // namespace jsipc
namespace layers {
struct TextureFactoryIdentifier;
} // namespace layers
@ -461,13 +457,6 @@ class ContentParent final
PHeapSnapshotTempFileHelperParent* AllocPHeapSnapshotTempFileHelperParent();
PJavaScriptParent* AllocPJavaScriptParent();
virtual mozilla::ipc::IPCResult RecvPJavaScriptConstructor(
PJavaScriptParent* aActor) override {
return PContentParent::RecvPJavaScriptConstructor(aActor);
}
PRemoteSpellcheckEngineParent* AllocPRemoteSpellcheckEngineParent();
mozilla::ipc::IPCResult RecvRecordingDeviceEvents(
@ -875,8 +864,6 @@ class ContentParent final
mozilla::ipc::IPCResult RecvAddPerformanceMetrics(
const nsID& aID, nsTArray<PerformanceInfo>&& aMetrics);
bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*);
bool DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*);
mozilla::ipc::IPCResult RecvConstructPopupBrowser(

View file

@ -24,7 +24,6 @@ include protocol PBrowserBridge;
include DOMTypes;
include IPCBlob;
include IPCStream;
include JavaScriptTypes;
include URIParams;
include PPrintingTypes;
include PTabContext;

View file

@ -33,7 +33,6 @@ include protocol POfflineCacheUpdate;
include protocol PSpeechSynthesis;
#endif
include protocol PTestShell;
include protocol PJavaScript;
include protocol PRemoteSpellcheckEngine;
include protocol PWebBrowserPersistDocument;
include protocol PWebrtcGlobal;
@ -48,7 +47,6 @@ include protocol PScriptCache;
include protocol PSessionStorageObserver;
include protocol PBenchmarkStorage;
include DOMTypes;
include JavaScriptTypes;
include IPCBlob;
include IPCStream;
include PTabContext;
@ -392,7 +390,6 @@ nested(upto inside_cpow) sync protocol PContent
manages PSpeechSynthesis;
#endif
manages PTestShell;
manages PJavaScript;
manages PRemoteSpellcheckEngine;
manages PWebBrowserPersistDocument;
manages PWebrtcGlobal;
@ -923,8 +920,6 @@ parent:
sync LaunchRDDProcess()
returns (nsresult rv, Endpoint<PRemoteDecoderManagerChild> aEndpoint);
async PJavaScript();
async PRemoteSpellcheckEngine();
async InitCrashReporter(NativeThreadId tid);

View file

@ -50,7 +50,6 @@ EXPORTS.mozilla.dom += [
'ContentParent.h',
'ContentProcess.h',
'ContentProcessManager.h',
'CPOWManagerGetter.h',
'CSPMessageUtils.h',
'DocShellMessageUtils.h',
'EffectsInfo.h',

View file

@ -438,8 +438,6 @@ DIRECT_CALL_OVERRIDES = {
# set() of (Protocol, side)
VIRTUAL_CALL_CLASSES = set([
# Defined as a strange template
("PJavaScript", "child"),
("PJavaScript", "parent"),
("PMedia", "parent"),
("PTexture", "parent"),

View file

@ -614,48 +614,6 @@ platform = win
description = Legacy a11y IPC
platform = win
# CPOWs
[PJavaScript::PreventExtensions]
description = CPOW Implementation
[PJavaScript::GetOwnPropertyDescriptor]
description = CPOW Implementation
[PJavaScript::DefineProperty]
description = CPOW Implementation
[PJavaScript::Delete]
description = CPOW Implementation
[PJavaScript::Has]
description = CPOW Implementation
[PJavaScript::HasOwn]
description = CPOW Implementation
[PJavaScript::Get]
description = CPOW Implementation
[PJavaScript::Set]
description = CPOW Implementation
[PJavaScript::IsExtensible]
description = CPOW Implementation
[PJavaScript::CallOrConstruct]
description = CPOW Implementation
[PJavaScript::HasInstance]
description = CPOW Implementation
[PJavaScript::GetBuiltinClass]
description = CPOW Implementation
[PJavaScript::IsArray]
description = CPOW Implementation
[PJavaScript::ClassName]
description = CPOW Implementation
[PJavaScript::GetPrototype]
description = CPOW Implementation
[PJavaScript::GetPrototypeIfOrdinary]
description = CPOW Implementation
[PJavaScript::RegExpToShared]
description = CPOW Implementation
[PJavaScript::GetPropertyKeys]
description = CPOW Implementation
[PJavaScript::InstanceOf]
description = CPOW Implementation
[PJavaScript::DOMInstanceOf]
description = CPOW Implementation
# Plugins
[PPluginWidget::Create]
description = Legacy NPAPI IPC

View file

@ -1,24 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sw=2 et 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/. */
#ifndef mozilla_jsipc_CpowHolder_h__
#define mozilla_jsipc_CpowHolder_h__
#include "js/TypeDecls.h"
namespace mozilla {
namespace jsipc {
class CpowHolder {
public:
virtual bool ToObject(JSContext* cx, JS::MutableHandle<JSObject*> objp) = 0;
};
} // namespace jsipc
} // namespace mozilla
#endif // mozilla_jsipc_CpowHolder_h__

View file

@ -1,84 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sw=2 et 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/. */
#ifndef mozilla_jsipc_CrossProcessObjectWrappers_h__
#define mozilla_jsipc_CrossProcessObjectWrappers_h__
#include "js/TypeDecls.h"
#include "mozilla/jsipc/CpowHolder.h"
#include "mozilla/jsipc/JavaScriptTypes.h"
#include "nsID.h"
#include "nsString.h"
#include "nsTArray.h"
#ifdef XP_WIN
# undef GetClassName
# undef GetClassInfo
#endif
namespace mozilla {
namespace dom {
class CPOWManagerGetter;
} // namespace dom
namespace jsipc {
class PJavaScriptParent;
class PJavaScriptChild;
class CPOWManager {
public:
virtual bool Unwrap(JSContext* cx, const nsTArray<CpowEntry>& aCpows,
JS::MutableHandleObject objp) = 0;
virtual bool Wrap(JSContext* cx, JS::HandleObject aObj,
nsTArray<CpowEntry>* outCpows) = 0;
};
class CrossProcessCpowHolder : public CpowHolder {
public:
CrossProcessCpowHolder(dom::CPOWManagerGetter* managerGetter,
const nsTArray<CpowEntry>& cpows);
~CrossProcessCpowHolder();
bool ToObject(JSContext* cx, JS::MutableHandleObject objp) override;
private:
CPOWManager* js_;
const nsTArray<CpowEntry>& cpows_;
bool unwrapped_;
};
CPOWManager* CPOWManagerFor(PJavaScriptParent* aParent);
CPOWManager* CPOWManagerFor(PJavaScriptChild* aChild);
bool IsCPOW(JSObject* obj);
bool IsWrappedCPOW(JSObject* obj);
nsresult InstanceOf(JSObject* obj, const nsID* id, bool* bp);
bool DOMInstanceOf(JSContext* cx, JSObject* obj, int prototypeID, int depth,
bool* bp);
PJavaScriptParent* NewJavaScriptParent();
void ReleaseJavaScriptParent(PJavaScriptParent* parent);
PJavaScriptChild* NewJavaScriptChild();
void ReleaseJavaScriptChild(PJavaScriptChild* child);
void AfterProcessTask();
} // namespace jsipc
} // namespace mozilla
#endif // mozilla_jsipc_CrossProcessObjectWrappers_h__

View file

@ -1,353 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sw=2 et 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/. */
#ifndef mozilla_jsipc_JavaScriptBase_h__
#define mozilla_jsipc_JavaScriptBase_h__
#include "WrapperAnswer.h"
#include "WrapperOwner.h"
#include "mozilla/dom/DOMTypes.h"
#include "mozilla/jsipc/PJavaScript.h"
namespace mozilla {
namespace jsipc {
template <class Base>
class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base {
using Answer = WrapperAnswer;
public:
virtual ~JavaScriptBase() = default;
virtual void ActorDestroy(WrapperOwner::ActorDestroyReason why) override {
WrapperOwner::ActorDestroy(why);
}
/*** IPC handlers ***/
mozilla::ipc::IPCResult RecvPreventExtensions(const uint64_t& objId,
ReturnStatus* rs) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvPreventExtensions(obj.value(), rs)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvGetOwnPropertyDescriptor(
const uint64_t& objId, const JSIDVariant& id, ReturnStatus* rs,
PPropertyDescriptor* out) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() ||
!Answer::RecvGetOwnPropertyDescriptor(obj.value(), id, rs, out)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvDefineProperty(const uint64_t& objId,
const JSIDVariant& id,
const PPropertyDescriptor& flags,
ReturnStatus* rs) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() ||
!Answer::RecvDefineProperty(obj.value(), id, flags, rs)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvDelete(const uint64_t& objId,
const JSIDVariant& id,
ReturnStatus* rs) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvDelete(obj.value(), id, rs)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvHas(const uint64_t& objId, const JSIDVariant& id,
ReturnStatus* rs, bool* bp) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvHas(obj.value(), id, rs, bp)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvHasOwn(const uint64_t& objId,
const JSIDVariant& id, ReturnStatus* rs,
bool* bp) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvHasOwn(obj.value(), id, rs, bp)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvGet(const uint64_t& objId,
const JSVariant& receiverVar,
const JSIDVariant& id, ReturnStatus* rs,
JSVariant* result) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() ||
!Answer::RecvGet(obj.value(), receiverVar, id, rs, result)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvSet(const uint64_t& objId, const JSIDVariant& id,
const JSVariant& value,
const JSVariant& receiverVar,
ReturnStatus* rs) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() ||
!Answer::RecvSet(obj.value(), id, value, receiverVar, rs)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvIsExtensible(const uint64_t& objId,
ReturnStatus* rs,
bool* result) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvIsExtensible(obj.value(), rs, result)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvCallOrConstruct(
const uint64_t& objId, nsTArray<JSParam>&& argv, const bool& construct,
ReturnStatus* rs, JSVariant* result,
nsTArray<JSParam>* outparams) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() ||
!Answer::RecvCallOrConstruct(obj.value(), std::move(argv), construct,
rs, result, outparams)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvHasInstance(const uint64_t& objId,
const JSVariant& v, ReturnStatus* rs,
bool* bp) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvHasInstance(obj.value(), v, rs, bp)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvGetBuiltinClass(const uint64_t& objId,
ReturnStatus* rs,
uint32_t* classValue) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() ||
!Answer::RecvGetBuiltinClass(obj.value(), rs, classValue)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvIsArray(const uint64_t& objId, ReturnStatus* rs,
uint32_t* answer) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvIsArray(obj.value(), rs, answer)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvClassName(const uint64_t& objId,
nsCString* result) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvClassName(obj.value(), result)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvGetPrototype(
const uint64_t& objId, ReturnStatus* rs,
ObjectOrNullVariant* result) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvGetPrototype(obj.value(), rs, result)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvGetPrototypeIfOrdinary(
const uint64_t& objId, ReturnStatus* rs, bool* isOrdinary,
ObjectOrNullVariant* result) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvGetPrototypeIfOrdinary(
obj.value(), rs, isOrdinary, result)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvRegExpToShared(const uint64_t& objId,
ReturnStatus* rs, nsString* source,
uint32_t* flags) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() ||
!Answer::RecvRegExpToShared(obj.value(), rs, source, flags)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvGetPropertyKeys(
const uint64_t& objId, const uint32_t& flags, ReturnStatus* rs,
nsTArray<JSIDVariant>* ids) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() ||
!Answer::RecvGetPropertyKeys(obj.value(), flags, rs, ids)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvInstanceOf(const uint64_t& objId,
const JSIID& iid, ReturnStatus* rs,
bool* instanceof) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() ||
!Answer::RecvInstanceOf(obj.value(), iid, rs, instanceof)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvDOMInstanceOf(const uint64_t& objId,
const int& prototypeID,
const int& depth, ReturnStatus* rs,
bool* instanceof) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() ||
!Answer::RecvDOMInstanceOf(obj.value(), prototypeID, depth, rs,
instanceof)) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
mozilla::ipc::IPCResult RecvDropObject(const uint64_t& objId) override {
Maybe<ObjectId> obj(ObjectId::deserialize(objId));
if (obj.isNothing() || !Answer::RecvDropObject(obj.value())) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
/*** Dummy call handlers ***/
bool SendDropObject(const ObjectId& objId) override {
return Base::SendDropObject(objId.serialize());
}
bool SendPreventExtensions(const ObjectId& objId, ReturnStatus* rs) override {
return Base::SendPreventExtensions(objId.serialize(), rs);
}
bool SendGetOwnPropertyDescriptor(const ObjectId& objId,
const JSIDVariant& id, ReturnStatus* rs,
PPropertyDescriptor* out) override {
return Base::SendGetOwnPropertyDescriptor(objId.serialize(), id, rs, out);
}
bool SendDefineProperty(const ObjectId& objId, const JSIDVariant& id,
const PPropertyDescriptor& flags,
ReturnStatus* rs) override {
return Base::SendDefineProperty(objId.serialize(), id, flags, rs);
}
bool SendDelete(const ObjectId& objId, const JSIDVariant& id,
ReturnStatus* rs) override {
return Base::SendDelete(objId.serialize(), id, rs);
}
bool SendHas(const ObjectId& objId, const JSIDVariant& id, ReturnStatus* rs,
bool* bp) override {
return Base::SendHas(objId.serialize(), id, rs, bp);
}
bool SendHasOwn(const ObjectId& objId, const JSIDVariant& id,
ReturnStatus* rs, bool* bp) override {
return Base::SendHasOwn(objId.serialize(), id, rs, bp);
}
bool SendGet(const ObjectId& objId, const JSVariant& receiverVar,
const JSIDVariant& id, ReturnStatus* rs,
JSVariant* result) override {
return Base::SendGet(objId.serialize(), receiverVar, id, rs, result);
}
bool SendSet(const ObjectId& objId, const JSIDVariant& id,
const JSVariant& value, const JSVariant& receiverVar,
ReturnStatus* rs) override {
return Base::SendSet(objId.serialize(), id, value, receiverVar, rs);
}
bool SendIsExtensible(const ObjectId& objId, ReturnStatus* rs,
bool* result) override {
return Base::SendIsExtensible(objId.serialize(), rs, result);
}
bool SendCallOrConstruct(const ObjectId& objId, const nsTArray<JSParam>& argv,
const bool& construct, ReturnStatus* rs,
JSVariant* result,
nsTArray<JSParam>* outparams) override {
return Base::SendCallOrConstruct(objId.serialize(), argv, construct, rs,
result, outparams);
}
bool SendHasInstance(const ObjectId& objId, const JSVariant& v,
ReturnStatus* rs, bool* bp) override {
return Base::SendHasInstance(objId.serialize(), v, rs, bp);
}
bool SendGetBuiltinClass(const ObjectId& objId, ReturnStatus* rs,
uint32_t* classValue) override {
return Base::SendGetBuiltinClass(objId.serialize(), rs, classValue);
}
bool SendIsArray(const ObjectId& objId, ReturnStatus* rs,
uint32_t* answer) override {
return Base::SendIsArray(objId.serialize(), rs, answer);
}
bool SendClassName(const ObjectId& objId, nsCString* result) override {
return Base::SendClassName(objId.serialize(), result);
}
bool SendGetPrototype(const ObjectId& objId, ReturnStatus* rs,
ObjectOrNullVariant* result) override {
return Base::SendGetPrototype(objId.serialize(), rs, result);
}
bool SendGetPrototypeIfOrdinary(const ObjectId& objId, ReturnStatus* rs,
bool* isOrdinary,
ObjectOrNullVariant* result) override {
return Base::SendGetPrototypeIfOrdinary(objId.serialize(), rs, isOrdinary,
result);
}
bool SendRegExpToShared(const ObjectId& objId, ReturnStatus* rs,
nsString* source, uint32_t* flags) override {
return Base::SendRegExpToShared(objId.serialize(), rs, source, flags);
}
bool SendGetPropertyKeys(const ObjectId& objId, const uint32_t& flags,
ReturnStatus* rs,
nsTArray<JSIDVariant>* ids) override {
return Base::SendGetPropertyKeys(objId.serialize(), flags, rs, ids);
}
bool SendInstanceOf(const ObjectId& objId, const JSIID& iid, ReturnStatus* rs,
bool* instanceof) override {
return Base::SendInstanceOf(objId.serialize(), iid, rs, instanceof);
}
bool SendDOMInstanceOf(const ObjectId& objId, const int& prototypeID,
const int& depth, ReturnStatus* rs,
bool* instanceof) override {
return Base::SendDOMInstanceOf(objId.serialize(), prototypeID, depth, rs,
instanceof);
}
/* The following code is needed to suppress a bogus MSVC warning (C4250). */
virtual bool toObjectVariant(JSContext* cx, JSObject* obj,
ObjectVariant* objVarp) override {
return WrapperOwner::toObjectVariant(cx, obj, objVarp);
}
virtual JSObject* fromObjectVariant(JSContext* cx,
const ObjectVariant& objVar) override {
return WrapperOwner::fromObjectVariant(cx, objVar);
}
};
} // namespace jsipc
} // namespace mozilla
#endif

View file

@ -1,79 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=4 sw=2 et 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 "JavaScriptChild.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/ipc/MessageChannel.h"
#include "nsContentUtils.h"
#include "xpcprivate.h"
#include "jsfriendapi.h"
#include "AccessCheck.h"
using namespace JS;
using namespace mozilla;
using namespace mozilla::jsipc;
using mozilla::AutoSafeJSContext;
static void UpdateChildWeakPointersBeforeSweepingZoneGroup(JSContext* cx,
void* data) {
static_cast<JavaScriptChild*>(data)->updateWeakPointers();
}
static void TraceChild(JSTracer* trc, void* data) {
static_cast<JavaScriptChild*>(data)->trace(trc);
}
JavaScriptChild::~JavaScriptChild() {
JSContext* cx = dom::danger::GetJSContext();
JS_RemoveWeakPointerZonesCallback(
cx, UpdateChildWeakPointersBeforeSweepingZoneGroup);
JS_RemoveExtraGCRootsTracer(cx, TraceChild, this);
}
bool JavaScriptChild::init() {
JSContext* cx = dom::danger::GetJSContext();
JS_AddWeakPointerZonesCallback(
cx, UpdateChildWeakPointersBeforeSweepingZoneGroup, this);
JS_AddExtraGCRootsTracer(cx, TraceChild, this);
return true;
}
void JavaScriptChild::trace(JSTracer* trc) {
objects_.trace(trc, strongReferenceObjIdMinimum_);
}
void JavaScriptChild::updateWeakPointers() {
objects_.sweep();
unwaivedObjectIds_.sweep();
waivedObjectIds_.sweep();
}
JSObject* JavaScriptChild::scopeForTargetObjects() {
// CPOWs from the parent need to point into the child's privileged junk
// scope so that they can benefit from XrayWrappers in the child.
return xpc::PrivilegedJunkScope();
}
mozilla::ipc::IPCResult JavaScriptChild::RecvDropTemporaryStrongReferences(
const uint64_t& upToObjId) {
strongReferenceObjIdMinimum_ = upToObjId + 1;
return IPC_OK();
}
PJavaScriptChild* mozilla::jsipc::NewJavaScriptChild() {
JavaScriptChild* child = new JavaScriptChild();
if (!child->init()) {
delete child;
return nullptr;
}
return child;
}
void mozilla::jsipc::ReleaseJavaScriptChild(PJavaScriptChild* child) {
static_cast<JavaScriptChild*>(child)->decref();
}

View file

@ -1,50 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=4 sw=2 et 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/. */
#ifndef mozilla_jsipc_JavaScriptChild_h_
#define mozilla_jsipc_JavaScriptChild_h_
#include "JavaScriptBase.h"
#include "mozilla/jsipc/PJavaScriptChild.h"
namespace mozilla {
namespace jsipc {
class JavaScriptChild : public JavaScriptBase<PJavaScriptChild> {
public:
JavaScriptChild() : strongReferenceObjIdMinimum_(0) {}
virtual ~JavaScriptChild();
bool init();
void trace(JSTracer* trc);
void updateWeakPointers();
void drop(JSObject* obj);
bool allowMessage(JSContext* cx) override { return true; }
protected:
virtual bool isParent() override { return false; }
virtual JSObject* scopeForTargetObjects() override;
mozilla::ipc::IPCResult RecvDropTemporaryStrongReferences(
const uint64_t& upToObjId) override;
private:
bool fail(JSContext* cx, ReturnStatus* rs);
bool ok(ReturnStatus* rs);
// JavaScriptChild will keep strong references to JS objects that are
// referenced by the parent only if their ID is >=
// strongReferenceObjIdMinimum_.
uint64_t strongReferenceObjIdMinimum_;
};
} // namespace jsipc
} // namespace mozilla
#endif

View file

@ -1,230 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sw=2 et 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/. */
#ifndef mozilla_jsipc_JavaScriptLogging__
#define mozilla_jsipc_JavaScriptLogging__
#include "nsString.h"
#include "nsPrintfCString.h"
#include "jsfriendapi.h"
#include "js/Wrapper.h"
namespace mozilla {
namespace jsipc {
#define LOG(...) \
PR_BEGIN_MACRO \
if (LoggingEnabled()) { \
Logging log(this, cx); \
log.print(__VA_ARGS__); \
} \
PR_END_MACRO
#define LOG_STACK() \
PR_BEGIN_MACRO \
if (StackLoggingEnabled()) { \
js::DumpBacktrace(cx); \
} \
PR_END_MACRO
struct ReceiverObj {
ObjectId id;
explicit ReceiverObj(ObjectId id) : id(id) {}
};
struct InVariant {
JSVariant variant;
explicit InVariant(const JSVariant& variant) : variant(variant) {}
};
struct OutVariant {
JSVariant variant;
explicit OutVariant(const JSVariant& variant) : variant(variant) {}
};
struct Identifier {
JSIDVariant variant;
explicit Identifier(const JSIDVariant& variant) : variant(variant) {}
};
class Logging {
public:
Logging(JavaScriptShared* shared, JSContext* cx) : shared(shared), cx(cx) {}
void print(const nsCString& str) {
const char* side = shared->isParent() ? "from child" : "from parent";
printf("CPOW %s: %s\n", side, str.get());
}
void print(const char* str) { print(nsCString(str)); }
template <typename T1>
void print(const char* fmt, const T1& a1) {
nsAutoCString tmp1;
format(a1, tmp1);
print(nsPrintfCString(fmt, tmp1.get()));
}
template <typename T1, typename T2>
void print(const char* fmt, const T1& a1, const T2& a2) {
nsAutoCString tmp1;
nsAutoCString tmp2;
format(a1, tmp1);
format(a2, tmp2);
print(nsPrintfCString(fmt, tmp1.get(), tmp2.get()));
}
template <typename T1, typename T2, typename T3>
void print(const char* fmt, const T1& a1, const T2& a2, const T3& a3) {
nsAutoCString tmp1;
nsAutoCString tmp2;
nsAutoCString tmp3;
format(a1, tmp1);
format(a2, tmp2);
format(a3, tmp3);
print(nsPrintfCString(fmt, tmp1.get(), tmp2.get(), tmp3.get()));
}
void format(const nsString& str, nsCString& out) {
out = NS_ConvertUTF16toUTF8(str);
}
void formatObject(bool incoming, bool local, ObjectId id, nsCString& out) {
const char* side;
const char* objDesc;
void* ptr;
if (local == incoming) {
JS::RootedObject obj(cx);
obj = shared->objects_.find(id);
obj = js::UncheckedUnwrap(obj, true);
JSAutoRealm ar(cx, obj);
objDesc = js::ObjectClassName(cx, obj);
side = shared->isParent() ? "parent" : "child";
ptr = obj;
} else {
objDesc = "<cpow>";
side = shared->isParent() ? "child" : "parent";
ptr = nullptr;
}
out = nsPrintfCString("<%s %s:%" PRIu64 ":%p>", side, objDesc,
id.serialNumber(), ptr);
}
void format(const ReceiverObj& obj, nsCString& out) {
formatObject(true, true, obj.id, out);
}
void format(const nsTArray<JSParam>& values, nsCString& out) {
nsAutoCString tmp;
out.Truncate();
for (size_t i = 0; i < values.Length(); i++) {
if (i) {
out.AppendLiteral(", ");
}
if (values[i].type() == JSParam::Tvoid_t) {
out.AppendLiteral("<void>");
} else {
format(InVariant(values[i].get_JSVariant()), tmp);
out += tmp;
}
}
}
void format(const InVariant& value, nsCString& out) {
format(true, value.variant, out);
}
void format(const OutVariant& value, nsCString& out) {
format(false, value.variant, out);
}
void format(bool incoming, const JSVariant& value, nsCString& out) {
switch (value.type()) {
case JSVariant::TUndefinedVariant: {
out = "undefined";
break;
}
case JSVariant::TNullVariant: {
out = "null";
break;
}
case JSVariant::TnsString: {
nsAutoCString tmp;
format(value.get_nsString(), tmp);
out = nsPrintfCString("\"%s\"", tmp.get());
break;
}
case JSVariant::TObjectVariant: {
const ObjectVariant& ovar = value.get_ObjectVariant();
if (ovar.type() == ObjectVariant::TLocalObject) {
Maybe<ObjectId> objId(
ObjectId::deserialize(ovar.get_LocalObject().serializedId()));
MOZ_RELEASE_ASSERT(objId.isSome());
formatObject(incoming, true, objId.value(), out);
} else {
Maybe<ObjectId> objId(
ObjectId::deserialize(ovar.get_RemoteObject().serializedId()));
MOZ_RELEASE_ASSERT(objId.isSome());
formatObject(incoming, false, objId.value(), out);
}
break;
}
case JSVariant::TSymbolVariant: {
out = "<Symbol>";
break;
}
case JSVariant::Tdouble: {
out = nsPrintfCString("%.0f", value.get_double());
break;
}
case JSVariant::Tbool: {
out = value.get_bool() ? "true" : "false";
break;
}
case JSVariant::TJSIID: {
out = "<JSIID>";
break;
}
default: {
out = "<JSIID>";
break;
}
}
}
void format(const Identifier& id, nsCString& out) {
switch (id.variant.type()) {
case JSIDVariant::TSymbolVariant: {
out = "<Symbol>";
break;
}
case JSIDVariant::TnsString: {
nsAutoCString tmp;
format(id.variant.get_nsString(), tmp);
out = nsPrintfCString("\"%s\"", tmp.get());
break;
}
case JSIDVariant::Tint32_t: {
out = nsPrintfCString("%d", id.variant.get_int32_t());
break;
}
default: {
out = "Unknown";
break;
}
}
}
private:
JavaScriptShared* shared;
JSContext* cx;
};
} // namespace jsipc
} // namespace mozilla
#endif

View file

@ -1,144 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=4 sw=2 et 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 "JavaScriptParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsJSUtils.h"
#include "nsIConsoleService.h"
#include "nsIScriptError.h"
#include "jsfriendapi.h"
#include "js/Proxy.h"
#include "js/HeapAPI.h"
#include "js/Wrapper.h"
#include "xpcprivate.h"
#include "mozilla/Casting.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/Telemetry.h"
using namespace js;
using namespace JS;
using namespace mozilla;
using namespace mozilla::jsipc;
using namespace mozilla::dom;
static void TraceParent(JSTracer* trc, void* data) {
static_cast<JavaScriptParent*>(data)->trace(trc);
}
JavaScriptParent::JavaScriptParent() : savedNextCPOWNumber_(1) {
JS_AddExtraGCRootsTracer(danger::GetJSContext(), TraceParent, this);
}
JavaScriptParent::~JavaScriptParent() {
JS_RemoveExtraGCRootsTracer(danger::GetJSContext(), TraceParent, this);
}
static bool ForbidUnsafeBrowserCPOWs() {
return StaticPrefs::dom_ipc_cpows_forbid_unsafe_from_browser();
}
bool JavaScriptParent::allowMessage(JSContext* cx) {
MOZ_ASSERT(cx);
// If we're running browser code while running tests (in automation),
// then we allow all safe CPOWs and forbid unsafe CPOWs
// based on a pref (which defaults to forbidden).
// A normal (release) browser build will never allow CPOWs,
// except as a token to pass round.
if (!xpc::IsInAutomation()) {
JS_ReportErrorASCII(cx, "CPOW usage forbidden");
return false;
}
MessageChannel* channel = GetIPCChannel();
bool isSafe = channel->IsInTransaction();
if (isSafe) {
return true;
}
nsIGlobalObject* global = dom::GetIncumbentGlobal();
JS::Rooted<JSObject*> jsGlobal(
cx, global ? global->GetGlobalJSObject() : nullptr);
if (jsGlobal) {
JSAutoRealm ar(cx, jsGlobal);
if (ForbidUnsafeBrowserCPOWs()) {
JS_ReportErrorASCII(cx, "unsafe CPOW usage forbidden");
return false;
}
}
static bool disableUnsafeCPOWWarnings =
PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");
if (!disableUnsafeCPOWWarnings) {
nsCOMPtr<nsIConsoleService> console(
do_GetService(NS_CONSOLESERVICE_CONTRACTID));
if (console) {
nsAutoString filename;
uint32_t lineno = 0, column = 0;
nsJSUtils::GetCallingLocation(cx, filename, &lineno, &column);
nsCOMPtr<nsIScriptError> error(
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
error->Init(NS_LITERAL_STRING("unsafe/forbidden CPOW usage"), filename,
EmptyString(), lineno, column, nsIScriptError::warningFlag,
"chrome javascript", false /* from private window */,
true /* from chrome context */);
console->LogMessage(error);
} else {
NS_WARNING("Unsafe synchronous IPC message");
}
}
return true;
}
void JavaScriptParent::trace(JSTracer* trc) {
objects_.trace(trc);
unwaivedObjectIds_.trace(trc);
waivedObjectIds_.trace(trc);
}
JSObject* JavaScriptParent::scopeForTargetObjects() {
// CPOWs from the child need to point into the parent's unprivileged junk
// scope so that a compromised child cannot compromise the parent. In
// practice, this means that a child process can only (a) hold parent
// objects alive and (b) invoke them if they are callable.
return xpc::UnprivilegedJunkScope();
}
void JavaScriptParent::afterProcessTask() {
if (savedNextCPOWNumber_ == nextCPOWNumber_) {
return;
}
savedNextCPOWNumber_ = nextCPOWNumber_;
MOZ_ASSERT(nextCPOWNumber_ > 0);
if (active()) {
Unused << SendDropTemporaryStrongReferences(nextCPOWNumber_ - 1);
}
}
PJavaScriptParent* mozilla::jsipc::NewJavaScriptParent() {
return new JavaScriptParent();
}
void mozilla::jsipc::ReleaseJavaScriptParent(PJavaScriptParent* parent) {
static_cast<JavaScriptParent*>(parent)->decref();
}
void mozilla::jsipc::AfterProcessTask() {
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
if (PJavaScriptParent* p =
LoneManagedOrNullAsserts(cp->ManagedPJavaScriptParent())) {
static_cast<JavaScriptParent*>(p)->afterProcessTask();
}
}
}

View file

@ -1,40 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=4 sw=2 et 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/. */
#ifndef mozilla_jsipc_JavaScriptParent__
#define mozilla_jsipc_JavaScriptParent__
#include "JavaScriptBase.h"
#include "mozilla/jsipc/PJavaScriptParent.h"
namespace mozilla {
namespace jsipc {
class JavaScriptParent : public JavaScriptBase<PJavaScriptParent> {
public:
JavaScriptParent();
virtual ~JavaScriptParent();
void trace(JSTracer* trc);
void drop(JSObject* obj);
bool allowMessage(JSContext* cx) override;
void afterProcessTask();
protected:
virtual bool isParent() override { return true; }
virtual JSObject* scopeForTargetObjects() override;
private:
uint64_t savedNextCPOWNumber_;
};
} // namespace jsipc
} // namespace mozilla
#endif // mozilla_jsipc_JavaScriptWrapper_h__

View file

@ -1,697 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=4 sw=2 et 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 "JavaScriptShared.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/CPOWManagerGetter.h"
#include "mozilla/dom/BrowserChild.h"
#include "jsfriendapi.h"
#include "js/Symbol.h"
#include "xpcprivate.h"
#include "WrapperFactory.h"
#include "mozilla/Preferences.h"
using namespace js;
using namespace JS;
using namespace mozilla;
using namespace mozilla::jsipc;
IdToObjectMap::IdToObjectMap() : table_(SystemAllocPolicy(), 32) {}
void IdToObjectMap::trace(JSTracer* trc, uint64_t minimumId) {
for (Table::Range r(table_.all()); !r.empty(); r.popFront()) {
if (r.front().key().serialNumber() >= minimumId) {
JS::TraceEdge(trc, &r.front().value(), "ipc-object");
}
}
}
void IdToObjectMap::sweep() {
for (Table::Enum e(table_); !e.empty(); e.popFront()) {
JS::Heap<JSObject*>* objp = &e.front().value();
JS_UpdateWeakPointerAfterGC(objp);
if (!*objp) {
e.removeFront();
}
}
}
JSObject* IdToObjectMap::find(ObjectId id) {
Table::Ptr p = table_.lookup(id);
if (!p) {
return nullptr;
}
return p->value();
}
JSObject* IdToObjectMap::findPreserveColor(ObjectId id) {
Table::Ptr p = table_.lookup(id);
if (!p) {
return nullptr;
}
return p->value().unbarrieredGet();
}
bool IdToObjectMap::add(ObjectId id, JSObject* obj) {
return table_.put(id, obj);
}
void IdToObjectMap::remove(ObjectId id) { table_.remove(id); }
void IdToObjectMap::clear() { table_.clear(); }
bool IdToObjectMap::empty() const { return table_.empty(); }
#ifdef DEBUG
bool IdToObjectMap::has(const ObjectId& id, const JSObject* obj) const {
auto p = table_.lookup(id);
if (!p) {
return false;
}
return p->value() == obj;
}
#endif
ObjectToIdMap::ObjectToIdMap() : table_(SystemAllocPolicy(), 32) {}
void ObjectToIdMap::trace(JSTracer* trc) { table_.trace(trc); }
void ObjectToIdMap::sweep() { table_.sweep(); }
ObjectId ObjectToIdMap::find(JSObject* obj) {
Table::Ptr p = table_.lookup(obj);
if (!p) {
return ObjectId::nullId();
}
return p->value();
}
bool ObjectToIdMap::add(JSContext* cx, JSObject* obj, ObjectId id) {
return table_.put(obj, id);
}
void ObjectToIdMap::remove(JSObject* obj) { table_.remove(obj); }
void ObjectToIdMap::clear() { table_.clear(); }
bool JavaScriptShared::sLoggingInitialized;
bool JavaScriptShared::sLoggingEnabledByEnvVar;
bool JavaScriptShared::sStackLoggingEnabledByEnvVar;
JavaScriptShared::JavaScriptShared()
: refcount_(1), nextSerialNumber_(1), nextCPOWNumber_(1) {
if (!sLoggingInitialized) {
sLoggingInitialized = true;
if (PR_GetEnv("MOZ_CPOW_LOG")) {
sLoggingEnabledByEnvVar = true;
sStackLoggingEnabledByEnvVar =
!!strstr(PR_GetEnv("MOZ_CPOW_LOG"), "stacks");
}
}
}
JavaScriptShared::~JavaScriptShared() { MOZ_RELEASE_ASSERT(cpows_.empty()); }
void JavaScriptShared::decref() {
refcount_--;
if (!refcount_) {
delete this;
}
}
void JavaScriptShared::incref() { refcount_++; }
bool JavaScriptShared::convertIdToGeckoString(JSContext* cx, JS::HandleId id,
nsString* to) {
RootedValue idval(cx);
if (!JS_IdToValue(cx, id, &idval)) {
return false;
}
RootedString str(cx, ToString(cx, idval));
if (!str) {
return false;
}
return AssignJSString(cx, *to, str);
}
bool JavaScriptShared::convertGeckoStringToId(JSContext* cx,
const nsString& from,
JS::MutableHandleId to) {
RootedString str(cx,
JS_NewUCStringCopyN(cx, from.BeginReading(), from.Length()));
if (!str) {
return false;
}
return JS_StringToId(cx, str, to);
}
bool JavaScriptShared::toVariant(JSContext* cx, JS::HandleValue from,
JSVariant* to) {
switch (JS_TypeOfValue(cx, from)) {
case JSTYPE_UNDEFINED:
*to = UndefinedVariant();
return true;
case JSTYPE_OBJECT:
case JSTYPE_FUNCTION: {
RootedObject obj(cx, from.toObjectOrNull());
if (!obj) {
MOZ_ASSERT(from.isNull());
*to = NullVariant();
return true;
}
Maybe<nsID> id = xpc::JSValue2ID(cx, from);
if (id) {
JSIID iid;
ConvertID(*id, &iid);
*to = iid;
return true;
}
ObjectVariant objVar;
if (!toObjectVariant(cx, obj, &objVar)) {
return false;
}
*to = objVar;
return true;
}
case JSTYPE_SYMBOL: {
RootedSymbol sym(cx, from.toSymbol());
SymbolVariant symVar;
if (!toSymbolVariant(cx, sym, &symVar)) {
return false;
}
*to = symVar;
return true;
}
case JSTYPE_STRING: {
nsAutoJSString autoStr;
if (!autoStr.init(cx, from)) {
return false;
}
*to = autoStr;
return true;
}
case JSTYPE_NUMBER:
if (from.isInt32()) {
*to = double(from.toInt32());
} else {
*to = from.toDouble();
}
return true;
case JSTYPE_BOOLEAN:
*to = from.toBoolean();
return true;
default:
MOZ_ASSERT(false);
return false;
}
}
bool JavaScriptShared::fromVariant(JSContext* cx, const JSVariant& from,
MutableHandleValue to) {
switch (from.type()) {
case JSVariant::TUndefinedVariant:
to.set(UndefinedValue());
return true;
case JSVariant::TNullVariant:
to.set(NullValue());
return true;
case JSVariant::TObjectVariant: {
JSObject* obj = fromObjectVariant(cx, from.get_ObjectVariant());
if (!obj) {
return false;
}
to.set(ObjectValue(*obj));
return true;
}
case JSVariant::TSymbolVariant: {
Symbol* sym = fromSymbolVariant(cx, from.get_SymbolVariant());
if (!sym) {
return false;
}
to.setSymbol(sym);
return true;
}
case JSVariant::Tdouble:
to.set(JS_NumberValue(from.get_double()));
return true;
case JSVariant::Tbool:
to.setBoolean(from.get_bool());
return true;
case JSVariant::TnsString: {
const nsString& old = from.get_nsString();
JSString* str = JS_NewUCStringCopyN(cx, old.BeginReading(), old.Length());
if (!str) {
return false;
}
to.set(StringValue(str));
return true;
}
case JSVariant::TJSIID: {
nsID iid;
const JSIID& id = from.get_JSIID();
ConvertID(id, &iid);
return xpc::ID2JSValue(cx, iid, to);
}
default:
MOZ_CRASH("NYI");
return false;
}
}
bool JavaScriptShared::toJSIDVariant(JSContext* cx, HandleId from,
JSIDVariant* to) {
if (JSID_IS_STRING(from)) {
nsAutoJSString autoStr;
if (!autoStr.init(cx, JSID_TO_STRING(from))) {
return false;
}
*to = autoStr;
return true;
}
if (JSID_IS_INT(from)) {
*to = JSID_TO_INT(from);
return true;
}
if (JSID_IS_SYMBOL(from)) {
SymbolVariant symVar;
if (!toSymbolVariant(cx, JSID_TO_SYMBOL(from), &symVar)) {
return false;
}
*to = symVar;
return true;
}
MOZ_ASSERT(false);
return false;
}
bool JavaScriptShared::fromJSIDVariant(JSContext* cx, const JSIDVariant& from,
MutableHandleId to) {
switch (from.type()) {
case JSIDVariant::TSymbolVariant: {
Symbol* sym = fromSymbolVariant(cx, from.get_SymbolVariant());
if (!sym) {
return false;
}
to.set(SYMBOL_TO_JSID(sym));
return true;
}
case JSIDVariant::TnsString:
return convertGeckoStringToId(cx, from.get_nsString(), to);
case JSIDVariant::Tint32_t:
to.set(INT_TO_JSID(from.get_int32_t()));
return true;
default:
return false;
}
}
bool JavaScriptShared::toSymbolVariant(JSContext* cx, JS::Symbol* symArg,
SymbolVariant* symVarp) {
RootedSymbol sym(cx, symArg);
MOZ_ASSERT(sym);
SymbolCode code = GetSymbolCode(sym);
if (static_cast<uint32_t>(code) < WellKnownSymbolLimit) {
*symVarp = WellKnownSymbol(static_cast<uint32_t>(code));
return true;
}
if (code == SymbolCode::InSymbolRegistry) {
nsAutoJSString autoStr;
if (!autoStr.init(cx, GetSymbolDescription(sym))) {
return false;
}
*symVarp = RegisteredSymbol(autoStr);
return true;
}
JS_ReportErrorASCII(cx, "unique symbol can't be used with CPOW");
return false;
}
JS::Symbol* JavaScriptShared::fromSymbolVariant(JSContext* cx,
const SymbolVariant& symVar) {
switch (symVar.type()) {
case SymbolVariant::TWellKnownSymbol: {
uint32_t which = symVar.get_WellKnownSymbol().which();
if (which < WellKnownSymbolLimit) {
return GetWellKnownSymbol(cx, static_cast<SymbolCode>(which));
}
MOZ_ASSERT(false, "bad child data");
return nullptr;
}
case SymbolVariant::TRegisteredSymbol: {
nsString key = symVar.get_RegisteredSymbol().key();
RootedString str(cx, JS_NewUCStringCopyN(cx, key.get(), key.Length()));
if (!str) {
return nullptr;
}
return GetSymbolFor(cx, str);
}
default:
return nullptr;
}
}
/* static */
void JavaScriptShared::ConvertID(const nsID& from, JSIID* to) {
to->m0() = from.m0;
to->m1() = from.m1;
to->m2() = from.m2;
to->m3_0() = from.m3[0];
to->m3_1() = from.m3[1];
to->m3_2() = from.m3[2];
to->m3_3() = from.m3[3];
to->m3_4() = from.m3[4];
to->m3_5() = from.m3[5];
to->m3_6() = from.m3[6];
to->m3_7() = from.m3[7];
}
/* static */
void JavaScriptShared::ConvertID(const JSIID& from, nsID* to) {
to->m0 = from.m0();
to->m1 = from.m1();
to->m2 = from.m2();
to->m3[0] = from.m3_0();
to->m3[1] = from.m3_1();
to->m3[2] = from.m3_2();
to->m3[3] = from.m3_3();
to->m3[4] = from.m3_4();
to->m3[5] = from.m3_5();
to->m3[6] = from.m3_6();
to->m3[7] = from.m3_7();
}
JSObject* JavaScriptShared::findCPOWById(const ObjectId& objId) {
JSObject* obj = findCPOWByIdPreserveColor(objId);
if (obj) {
JS::ExposeObjectToActiveJS(obj);
}
return obj;
}
JSObject* JavaScriptShared::findCPOWByIdPreserveColor(const ObjectId& objId) {
JSObject* obj = cpows_.findPreserveColor(objId);
if (!obj) {
return nullptr;
}
if (js::gc::EdgeNeedsSweepUnbarriered(&obj)) {
cpows_.remove(objId);
return nullptr;
}
return obj;
}
JSObject* JavaScriptShared::findObjectById(JSContext* cx,
const ObjectId& objId) {
RootedObject obj(cx, objects_.find(objId));
if (!obj) {
JS_ReportErrorASCII(cx, "operation not possible on dead CPOW");
return nullptr;
}
// Each process has a dedicated compartment for CPOW targets. All CPOWs
// from the other process point to objects in this scope. From there, they
// can access objects in other compartments using cross-compartment
// wrappers.
JSAutoRealm ar(cx, scopeForTargetObjects());
if (objId.hasXrayWaiver()) {
obj = js::ToWindowProxyIfWindow(obj);
MOZ_ASSERT(obj);
if (!xpc::WrapperFactory::WaiveXrayAndWrap(cx, &obj)) {
return nullptr;
}
} else {
if (!JS_WrapObject(cx, &obj)) {
return nullptr;
}
}
return obj;
}
static const uint64_t UnknownPropertyOp = 1;
bool JavaScriptShared::fromDescriptor(JSContext* cx,
Handle<PropertyDescriptor> desc,
PPropertyDescriptor* out) {
out->attrs() = desc.attributes();
if (!toVariant(cx, desc.value(), &out->value())) {
return false;
}
if (!toObjectOrNullVariant(cx, desc.object(), &out->obj())) {
return false;
}
if (!desc.getter()) {
out->getter() = 0;
} else if (desc.hasGetterObject()) {
JSObject* getter = desc.getterObject();
ObjectVariant objVar;
if (!toObjectVariant(cx, getter, &objVar)) {
return false;
}
out->getter() = objVar;
} else {
out->getter() = UnknownPropertyOp;
}
if (!desc.setter()) {
out->setter() = 0;
} else if (desc.hasSetterObject()) {
JSObject* setter = desc.setterObject();
ObjectVariant objVar;
if (!toObjectVariant(cx, setter, &objVar)) {
return false;
}
out->setter() = objVar;
} else {
out->setter() = UnknownPropertyOp;
}
return true;
}
bool UnknownPropertyStub(JSContext* cx, HandleObject obj, HandleId id,
MutableHandleValue vp) {
JS_ReportErrorASCII(cx, "getter could not be wrapped via CPOWs");
return false;
}
bool UnknownStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id,
HandleValue v, ObjectOpResult& result) {
JS_ReportErrorASCII(cx, "setter could not be wrapped via CPOWs");
return false;
}
bool JavaScriptShared::toDescriptor(JSContext* cx,
const PPropertyDescriptor& in,
MutableHandle<PropertyDescriptor> out) {
out.setAttributes(in.attrs());
if (!fromVariant(cx, in.value(), out.value())) {
return false;
}
out.object().set(fromObjectOrNullVariant(cx, in.obj()));
if (in.getter().type() == GetterSetter::Tuint64_t &&
!in.getter().get_uint64_t()) {
out.setGetter(nullptr);
} else if (in.attrs() & JSPROP_GETTER) {
Rooted<JSObject*> getter(cx);
getter = fromObjectVariant(cx, in.getter().get_ObjectVariant());
if (!getter) {
return false;
}
out.setGetter(JS_DATA_TO_FUNC_PTR(JSGetterOp, getter.get()));
} else {
out.setGetter(UnknownPropertyStub);
}
if (in.setter().type() == GetterSetter::Tuint64_t &&
!in.setter().get_uint64_t()) {
out.setSetter(nullptr);
} else if (in.attrs() & JSPROP_SETTER) {
Rooted<JSObject*> setter(cx);
setter = fromObjectVariant(cx, in.setter().get_ObjectVariant());
if (!setter) {
return false;
}
out.setSetter(JS_DATA_TO_FUNC_PTR(JSSetterOp, setter.get()));
} else {
out.setSetter(UnknownStrictPropertyStub);
}
return true;
}
bool JavaScriptShared::toObjectOrNullVariant(JSContext* cx, JSObject* obj,
ObjectOrNullVariant* objVarp) {
if (!obj) {
*objVarp = NullVariant();
return true;
}
ObjectVariant objVar;
if (!toObjectVariant(cx, obj, &objVar)) {
return false;
}
*objVarp = objVar;
return true;
}
JSObject* JavaScriptShared::fromObjectOrNullVariant(
JSContext* cx, const ObjectOrNullVariant& objVar) {
if (objVar.type() == ObjectOrNullVariant::TNullVariant) {
return nullptr;
}
return fromObjectVariant(cx, objVar.get_ObjectVariant());
}
CrossProcessCpowHolder::CrossProcessCpowHolder(
dom::CPOWManagerGetter* managerGetter, const nsTArray<CpowEntry>& cpows)
: js_(nullptr), cpows_(cpows), unwrapped_(false) {
// Only instantiate the CPOW manager if we might need it later.
if (cpows.Length()) {
js_ = managerGetter->GetCPOWManager();
}
}
CrossProcessCpowHolder::~CrossProcessCpowHolder() {
if (cpows_.Length() && !unwrapped_) {
// This should only happen if a message manager message
// containing CPOWs gets ignored for some reason. We need to
// unwrap every incoming CPOW in this process to ensure that
// the corresponding part of the CPOW in the other process
// will eventually be collected. The scope for this object
// doesn't really matter, because it immediately becomes
// garbage.
AutoJSAPI jsapi;
if (!jsapi.Init(xpc::PrivilegedJunkScope())) {
return;
}
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> cpows(cx);
js_->Unwrap(cx, cpows_, &cpows);
}
}
bool CrossProcessCpowHolder::ToObject(JSContext* cx,
JS::MutableHandleObject objp) {
unwrapped_ = true;
if (!cpows_.Length()) {
return true;
}
return js_->Unwrap(cx, cpows_, objp);
}
bool JavaScriptShared::Unwrap(JSContext* cx, const nsTArray<CpowEntry>& aCpows,
JS::MutableHandleObject objp) {
objp.set(nullptr);
if (!aCpows.Length()) {
return true;
}
RootedObject obj(cx, JS_NewPlainObject(cx));
if (!obj) {
return false;
}
RootedValue v(cx);
RootedString str(cx);
for (size_t i = 0; i < aCpows.Length(); i++) {
const nsString& name = aCpows[i].name();
if (!fromVariant(cx, aCpows[i].value(), &v)) {
return false;
}
if (!JS_DefineUCProperty(cx, obj, name.BeginReading(), name.Length(), v,
JSPROP_ENUMERATE)) {
return false;
}
}
objp.set(obj);
return true;
}
bool JavaScriptShared::Wrap(JSContext* cx, HandleObject aObj,
nsTArray<CpowEntry>* outCpows) {
if (!aObj) {
return true;
}
Rooted<IdVector> ids(cx, IdVector(cx));
if (!JS_Enumerate(cx, aObj, &ids)) {
return false;
}
RootedId id(cx);
RootedValue v(cx);
for (size_t i = 0; i < ids.length(); i++) {
id = ids[i];
nsString str;
if (!convertIdToGeckoString(cx, id, &str)) {
return false;
}
if (!JS_GetPropertyById(cx, aObj, id, &v)) {
return false;
}
JSVariant var;
if (!toVariant(cx, v, &var)) {
return false;
}
outCpows->AppendElement(CpowEntry(str, var));
}
return true;
}
CPOWManager* mozilla::jsipc::CPOWManagerFor(PJavaScriptParent* aParent) {
return static_cast<JavaScriptParent*>(aParent);
}
CPOWManager* mozilla::jsipc::CPOWManagerFor(PJavaScriptChild* aChild) {
return static_cast<JavaScriptChild*>(aChild);
}

View file

@ -1,255 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sw=2 et 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/. */
#ifndef mozilla_jsipc_JavaScriptShared_h__
#define mozilla_jsipc_JavaScriptShared_h__
#include "mozilla/HashFunctions.h"
#include "mozilla/dom/DOMTypes.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/jsipc/PJavaScript.h"
#include "mozilla/StaticPrefs_dom.h"
#include "js/GCHashTable.h"
#include "nsJSUtils.h"
namespace mozilla {
namespace jsipc {
class ObjectId {
public:
// Use 47 bits at most, to be safe, since jsval privates are encoded as
// doubles. See bug 1065811 comment 12 for an explanation.
static const size_t SERIAL_NUMBER_BITS = 47;
static const size_t FLAG_BITS = 1;
static const uint64_t SERIAL_NUMBER_MAX =
(uint64_t(1) << SERIAL_NUMBER_BITS) - 1;
explicit ObjectId(uint64_t serialNumber, bool hasXrayWaiver)
: serialNumber_(serialNumber), hasXrayWaiver_(hasXrayWaiver) {
if (isInvalidSerialNumber(serialNumber)) {
MOZ_CRASH("Bad CPOW Id");
}
}
bool operator==(const ObjectId& other) const {
bool equal = serialNumber() == other.serialNumber();
MOZ_ASSERT_IF(equal, hasXrayWaiver() == other.hasXrayWaiver());
return equal;
}
bool isNull() { return !serialNumber_; }
uint64_t serialNumber() const { return serialNumber_; }
bool hasXrayWaiver() const { return hasXrayWaiver_; }
uint64_t serialize() const {
MOZ_ASSERT(serialNumber(), "Don't send a null ObjectId over IPC");
return uint64_t((serialNumber() << FLAG_BITS) |
((hasXrayWaiver() ? 1 : 0) << 0));
}
static ObjectId nullId() { return ObjectId(); }
static Maybe<ObjectId> deserialize(uint64_t data) {
if (isInvalidSerialNumber(data >> FLAG_BITS)) {
return Nothing();
}
return Some(ObjectId(data >> FLAG_BITS, data & 1));
}
// For use with StructGCPolicy.
void trace(JSTracer*) const {}
bool needsSweep() const { return false; }
private:
ObjectId() : serialNumber_(0), hasXrayWaiver_(false) {}
static bool isInvalidSerialNumber(uint64_t aSerialNumber) {
return aSerialNumber == 0 || aSerialNumber > SERIAL_NUMBER_MAX;
}
uint64_t serialNumber_ : SERIAL_NUMBER_BITS;
bool hasXrayWaiver_ : 1;
};
class JavaScriptShared;
// DefaultHasher<T> requires that T coerce to an integral type. We could make
// ObjectId do that, but doing so would weaken our type invariants, so we just
// reimplement it manually.
struct ObjectIdHasher {
using Lookup = ObjectId;
static js::HashNumber hash(const Lookup& l) {
return mozilla::HashGeneric(l.serialize());
}
static bool match(const ObjectId& k, const ObjectId& l) { return k == l; }
static void rekey(ObjectId& k, const ObjectId& newKey) { k = newKey; }
};
// Map ids -> JSObjects
class IdToObjectMap {
typedef js::HashMap<ObjectId, JS::Heap<JSObject*>, ObjectIdHasher,
js::SystemAllocPolicy>
Table;
public:
IdToObjectMap();
void trace(JSTracer* trc, uint64_t minimumId = 0);
void sweep();
bool add(ObjectId id, JSObject* obj);
JSObject* find(ObjectId id);
JSObject* findPreserveColor(ObjectId id);
void remove(ObjectId id);
void clear();
bool empty() const;
#ifdef DEBUG
bool has(const ObjectId& id, const JSObject* obj) const;
#endif
private:
Table table_;
};
// Map JSObjects -> ids
class ObjectToIdMap {
using Hasher = js::MovableCellHasher<JS::Heap<JSObject*>>;
using Table = JS::GCHashMap<JS::Heap<JSObject*>, ObjectId, Hasher,
js::SystemAllocPolicy>;
public:
ObjectToIdMap();
void trace(JSTracer* trc);
void sweep();
bool add(JSContext* cx, JSObject* obj, ObjectId id);
ObjectId find(JSObject* obj);
void remove(JSObject* obj);
void clear();
private:
Table table_;
};
class Logging;
class JavaScriptShared : public CPOWManager {
public:
JavaScriptShared();
virtual ~JavaScriptShared();
void decref();
void incref();
bool Unwrap(JSContext* cx, const nsTArray<CpowEntry>& aCpows,
JS::MutableHandleObject objp) override;
bool Wrap(JSContext* cx, JS::HandleObject aObj,
nsTArray<CpowEntry>* outCpows) override;
protected:
bool toVariant(JSContext* cx, JS::HandleValue from, JSVariant* to);
bool fromVariant(JSContext* cx, const JSVariant& from,
JS::MutableHandleValue to);
bool toJSIDVariant(JSContext* cx, JS::HandleId from, JSIDVariant* to);
bool fromJSIDVariant(JSContext* cx, const JSIDVariant& from,
JS::MutableHandleId to);
bool toSymbolVariant(JSContext* cx, JS::Symbol* sym, SymbolVariant* symVarp);
JS::Symbol* fromSymbolVariant(JSContext* cx, const SymbolVariant& symVar);
bool fromDescriptor(JSContext* cx, JS::Handle<JS::PropertyDescriptor> desc,
PPropertyDescriptor* out);
bool toDescriptor(JSContext* cx, const PPropertyDescriptor& in,
JS::MutableHandle<JS::PropertyDescriptor> out);
bool toObjectOrNullVariant(JSContext* cx, JSObject* obj,
ObjectOrNullVariant* objVarp);
JSObject* fromObjectOrNullVariant(JSContext* cx,
const ObjectOrNullVariant& objVar);
bool convertIdToGeckoString(JSContext* cx, JS::HandleId id, nsString* to);
bool convertGeckoStringToId(JSContext* cx, const nsString& from,
JS::MutableHandleId id);
virtual bool toObjectVariant(JSContext* cx, JSObject* obj,
ObjectVariant* objVarp) = 0;
virtual JSObject* fromObjectVariant(JSContext* cx,
const ObjectVariant& objVar) = 0;
static void ConvertID(const nsID& from, JSIID* to);
static void ConvertID(const JSIID& from, nsID* to);
JSObject* findCPOWById(const ObjectId& objId);
JSObject* findCPOWByIdPreserveColor(const ObjectId& objId);
JSObject* findObjectById(JSContext* cx, const ObjectId& objId);
#ifdef DEBUG
bool hasCPOW(const ObjectId& objId, const JSObject* obj) {
MOZ_ASSERT(obj);
return findCPOWByIdPreserveColor(objId) == obj;
}
#endif
static bool LoggingEnabled() {
return sLoggingEnabledByEnvVar || StaticPrefs::dom_ipc_cpows_log_enabled();
}
static bool StackLoggingEnabled() {
return sStackLoggingEnabledByEnvVar ||
StaticPrefs::dom_ipc_cpows_log_stack();
}
friend class Logging;
virtual bool isParent() = 0;
virtual JSObject* scopeForTargetObjects() = 0;
protected:
uintptr_t refcount_;
IdToObjectMap objects_;
IdToObjectMap cpows_;
uint64_t nextSerialNumber_;
// nextCPOWNumber_ should be the value of nextSerialNumber_ in the other
// process. The next new CPOW we get should have this serial number.
uint64_t nextCPOWNumber_;
// CPOW references can be weak, and any object we store in a map may be
// GCed (at which point the CPOW will report itself "dead" to the owner).
// This means that we don't want to store any js::Wrappers in the CPOW map,
// because CPOW will die if the wrapper is GCed, even if the underlying
// object is still alive.
//
// This presents a tricky situation for Xray waivers, since they're normally
// represented as a special same-compartment wrapper. We have to strip them
// off before putting them in the id-to-object and object-to-id maps, so we
// need a way of distinguishing them at lookup-time.
//
// For the id-to-object map, we encode waiver-or-not information into the id
// itself, which lets us do the right thing when accessing the object.
//
// For the object-to-id map, we just keep two maps, one for each type.
ObjectToIdMap unwaivedObjectIds_;
ObjectToIdMap waivedObjectIds_;
ObjectToIdMap& objectIdMap(bool waiver) {
return waiver ? waivedObjectIds_ : unwaivedObjectIds_;
}
static bool sLoggingInitialized;
static bool sLoggingEnabledByEnvVar;
static bool sStackLoggingEnabledByEnvVar;
};
} // namespace jsipc
} // namespace mozilla
#endif

View file

@ -1,155 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et 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 DOMTypes;
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
namespace mozilla {
namespace jsipc {
struct JSIID
{
uint32_t m0;
uint16_t m1;
uint16_t m2;
uint8_t m3_0;
uint8_t m3_1;
uint8_t m3_2;
uint8_t m3_3;
uint8_t m3_4;
uint8_t m3_5;
uint8_t m3_6;
uint8_t m3_7;
};
struct LocalObject
{
uint64_t serializedId;
};
struct RemoteObject
{
uint64_t serializedId;
bool isCallable;
bool isConstructor;
bool isDOMObject;
};
union ObjectVariant
{
LocalObject;
RemoteObject;
};
struct WellKnownSymbol
{
uint32_t which;
};
struct RegisteredSymbol
{
nsString key;
};
union SymbolVariant
{
WellKnownSymbol;
RegisteredSymbol;
};
struct UndefinedVariant {};
struct NullVariant {};
union ObjectOrNullVariant
{
ObjectVariant;
NullVariant;
};
union JSVariant
{
UndefinedVariant;
NullVariant;
ObjectVariant;
SymbolVariant;
nsString; /* StringValue(x) */
double; /* NumberValue(x) */
bool; /* BooleanValue(x) */
JSIID; /* XPC nsIID */
};
union JSIDVariant
{
SymbolVariant;
nsString;
int32_t;
};
struct ReturnSuccess
{
};
struct ReturnDeadCPOW
{
};
struct ReturnException
{
JSVariant exn;
};
struct ReturnObjectOpResult
{
uint32_t code;
};
union ReturnStatus
{
ReturnSuccess;
ReturnDeadCPOW;
ReturnException;
ReturnObjectOpResult;
};
union JSParam
{
void_t; /* value is strictly an xpc out param */
JSVariant; /* actual value to pass through */
};
union GetterSetter
{
uint64_t;
ObjectVariant;
};
struct PPropertyDescriptor
{
ObjectOrNullVariant obj;
uint32_t attrs;
JSVariant value;
// How to interpret these values depends on whether JSPROP_GETTER/SETTER
// are set. If set, the corresponding value is a CPOW or 0 for NULL.
// Otherwise, the following table is used:
//
// 0 - NULL
// 1 - Default getter or setter.
// 2 - Unknown
GetterSetter getter;
GetterSetter setter;
};
struct CpowEntry
{
nsString name;
JSVariant value;
};
}
}

View file

@ -1,58 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et 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 protocol PContent;
include DOMTypes;
include JavaScriptTypes;
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
namespace mozilla {
namespace jsipc {
nested(upto inside_sync) sync protocol PJavaScript
{
manager PContent;
both:
// Sent when a CPOW has been finalized and table entries can be freed up.
async DropObject(uint64_t objId);
// These roughly map to the ProxyHandler hooks that CPOWs need.
nested(inside_sync) sync PreventExtensions(uint64_t objId) returns (ReturnStatus rs);
nested(inside_sync) sync GetOwnPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
nested(inside_sync) sync DefineProperty(uint64_t objId, JSIDVariant id, PPropertyDescriptor descriptor) returns (ReturnStatus rs);
nested(inside_sync) sync Delete(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs);
nested(inside_sync) sync Has(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
nested(inside_sync) sync HasOwn(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
nested(inside_sync) sync Get(uint64_t objId, JSVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
nested(inside_sync) sync Set(uint64_t objId, JSIDVariant id, JSVariant value, JSVariant receiver) returns (ReturnStatus rs);
nested(inside_sync) sync IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
nested(inside_sync) sync CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
nested(inside_sync) sync HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
nested(inside_sync) sync GetBuiltinClass(uint64_t objId) returns (ReturnStatus rs, uint32_t classValue);
nested(inside_sync) sync IsArray(uint64_t objId) returns (ReturnStatus rs, uint32_t ans);
nested(inside_sync) sync ClassName(uint64_t objId) returns (nsCString name);
nested(inside_sync) sync GetPrototype(uint64_t objId) returns (ReturnStatus rs, ObjectOrNullVariant result);
nested(inside_sync) sync GetPrototypeIfOrdinary(uint64_t objId) returns (ReturnStatus rs, bool isOrdinary, ObjectOrNullVariant result);
nested(inside_sync) sync RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
nested(inside_sync) sync GetPropertyKeys(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, JSIDVariant[] ids);
nested(inside_sync) sync InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
nested(inside_sync) sync DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof);
parent:
async __delete__();
child:
async DropTemporaryStrongReferences(uint64_t upToObjId);
};
}
}

View file

@ -1,892 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=4 sw=2 et 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 "WrapperAnswer.h"
#include "JavaScriptLogging.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ScriptSettings.h"
#include "xpcprivate.h"
#include "js/Class.h"
#include "js/RegExp.h"
#include "jsfriendapi.h"
using namespace JS;
using namespace mozilla;
using namespace mozilla::jsipc;
// Note - Using AutoJSAPI (rather than AutoEntryScript) for a trap means
// that we don't expect it to run script. For most of these traps that will only
// happen if the target is a scripted proxy, which is probably something that we
// don't want to support over CPOWs. When enough code is fixed up, the long-term
// plan is to have the JS engine throw if it encounters script when it isn't
// expecting it.
using mozilla::dom::AutoEntryScript;
using mozilla::dom::AutoJSAPI;
using xpc::IsInAutomation;
static void MaybeForceDebugGC() {
static bool sEnvVarInitialized = false;
static bool sDebugGCs = false;
if (!sEnvVarInitialized) {
sDebugGCs = !!PR_GetEnv("MOZ_DEBUG_DEAD_CPOWS");
}
if (sDebugGCs) {
JSContext* cx = XPCJSContext::Get()->Context();
PrepareForFullGC(cx);
NonIncrementalGC(cx, GC_NORMAL, GCReason::COMPONENT_UTILS);
}
}
bool WrapperAnswer::fail(AutoJSAPI& jsapi, ReturnStatus* rs) {
// By default, we set |undefined| unless we can get a more meaningful
// exception.
*rs = ReturnStatus(ReturnException(JSVariant(UndefinedVariant())));
// Note we always return true from this function, since this propagates
// to the IPC code, and we don't want a JS failure to cause the death
// of the child process.
JSContext* cx = jsapi.cx();
RootedValue exn(cx);
if (!jsapi.HasException()) {
return true;
}
if (!jsapi.StealException(&exn)) {
return true;
}
// If this fails, we still don't want to exit. Just return an invalid
// exception.
(void)toVariant(cx, exn, &rs->get_ReturnException().exn());
return true;
}
bool WrapperAnswer::ok(ReturnStatus* rs) {
*rs = ReturnStatus(ReturnSuccess());
return true;
}
bool WrapperAnswer::ok(ReturnStatus* rs, const JS::ObjectOpResult& result) {
*rs = result ? ReturnStatus(ReturnSuccess())
: ReturnStatus(ReturnObjectOpResult(result.failureCode()));
return true;
}
bool WrapperAnswer::deadCPOW(AutoJSAPI& jsapi, ReturnStatus* rs) {
JSContext* cx = jsapi.cx();
JS_ClearPendingException(cx);
*rs = ReturnStatus(ReturnDeadCPOW());
return true;
}
bool WrapperAnswer::RecvPreventExtensions(const ObjectId& objId,
ReturnStatus* rs) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
ObjectOpResult success;
if (!JS_PreventExtensions(cx, obj, success)) {
return fail(jsapi, rs);
}
LOG("%s.preventExtensions()", ReceiverObj(objId));
return ok(rs, success);
}
static void EmptyDesc(PPropertyDescriptor* desc) {
desc->obj() = LocalObject(0);
desc->attrs() = 0;
desc->value() = UndefinedVariant();
desc->getter() = 0;
desc->setter() = 0;
}
bool WrapperAnswer::RecvGetOwnPropertyDescriptor(const ObjectId& objId,
const JSIDVariant& idVar,
ReturnStatus* rs,
PPropertyDescriptor* out) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
EmptyDesc(out);
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("%s.getOwnPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar));
RootedId id(cx);
if (!fromJSIDVariant(cx, idVar, &id)) {
return fail(jsapi, rs);
}
Rooted<PropertyDescriptor> desc(cx);
if (!JS_GetOwnPropertyDescriptorById(cx, obj, id, &desc)) {
return fail(jsapi, rs);
}
if (!fromDescriptor(cx, desc, out)) {
return fail(jsapi, rs);
}
return ok(rs);
}
bool WrapperAnswer::RecvDefineProperty(const ObjectId& objId,
const JSIDVariant& idVar,
const PPropertyDescriptor& descriptor,
ReturnStatus* rs) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("define %s[%s]", ReceiverObj(objId), Identifier(idVar));
RootedId id(cx);
if (!fromJSIDVariant(cx, idVar, &id)) {
return fail(jsapi, rs);
}
Rooted<PropertyDescriptor> desc(cx);
if (!toDescriptor(cx, descriptor, &desc)) {
return fail(jsapi, rs);
}
ObjectOpResult success;
if (!JS_DefinePropertyById(cx, obj, id, desc, success)) {
return fail(jsapi, rs);
}
return ok(rs, success);
}
bool WrapperAnswer::RecvDelete(const ObjectId& objId, const JSIDVariant& idVar,
ReturnStatus* rs) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("delete %s[%s]", ReceiverObj(objId), Identifier(idVar));
RootedId id(cx);
if (!fromJSIDVariant(cx, idVar, &id)) {
return fail(jsapi, rs);
}
ObjectOpResult success;
if (!JS_DeletePropertyById(cx, obj, id, success)) {
return fail(jsapi, rs);
}
return ok(rs, success);
}
bool WrapperAnswer::RecvHas(const ObjectId& objId, const JSIDVariant& idVar,
ReturnStatus* rs, bool* foundp) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
*foundp = false;
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("%s.has(%s)", ReceiverObj(objId), Identifier(idVar));
RootedId id(cx);
if (!fromJSIDVariant(cx, idVar, &id)) {
return fail(jsapi, rs);
}
if (!JS_HasPropertyById(cx, obj, id, foundp)) {
return fail(jsapi, rs);
}
return ok(rs);
}
bool WrapperAnswer::RecvHasOwn(const ObjectId& objId, const JSIDVariant& idVar,
ReturnStatus* rs, bool* foundp) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
*foundp = false;
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("%s.hasOwn(%s)", ReceiverObj(objId), Identifier(idVar));
RootedId id(cx);
if (!fromJSIDVariant(cx, idVar, &id)) {
return fail(jsapi, rs);
}
if (!JS_HasOwnPropertyById(cx, obj, id, foundp)) {
return fail(jsapi, rs);
}
return ok(rs);
}
bool WrapperAnswer::RecvGet(const ObjectId& objId, const JSVariant& receiverVar,
const JSIDVariant& idVar, ReturnStatus* rs,
JSVariant* result) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
// We may run scripted getters.
AutoEntryScript aes(scopeForTargetObjects(),
"Cross-Process Object Wrapper 'get'");
JSContext* cx = aes.cx();
// The outparam will be written to the buffer, so it must be set even if
// the parent won't read it.
*result = UndefinedVariant();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(aes, rs);
}
RootedValue receiver(cx);
if (!fromVariant(cx, receiverVar, &receiver)) {
return fail(aes, rs);
}
RootedId id(cx);
if (!fromJSIDVariant(cx, idVar, &id)) {
return fail(aes, rs);
}
JS::RootedValue val(cx);
if (!JS_ForwardGetPropertyTo(cx, obj, id, receiver, &val)) {
return fail(aes, rs);
}
if (!toVariant(cx, val, result)) {
return fail(aes, rs);
}
LOG("get %s.%s = %s", ReceiverObj(objId), Identifier(idVar),
OutVariant(*result));
return ok(rs);
}
bool WrapperAnswer::RecvSet(const ObjectId& objId, const JSIDVariant& idVar,
const JSVariant& value,
const JSVariant& receiverVar, ReturnStatus* rs) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
// We may run scripted setters.
AutoEntryScript aes(scopeForTargetObjects(),
"Cross-Process Object Wrapper 'set'");
JSContext* cx = aes.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(aes, rs);
}
LOG("set %s[%s] = %s", ReceiverObj(objId), Identifier(idVar),
InVariant(value));
RootedId id(cx);
if (!fromJSIDVariant(cx, idVar, &id)) {
return fail(aes, rs);
}
RootedValue val(cx);
if (!fromVariant(cx, value, &val)) {
return fail(aes, rs);
}
RootedValue receiver(cx);
if (!fromVariant(cx, receiverVar, &receiver)) {
return fail(aes, rs);
}
ObjectOpResult result;
if (!JS_ForwardSetPropertyTo(cx, obj, id, val, receiver, result)) {
return fail(aes, rs);
}
return ok(rs, result);
}
bool WrapperAnswer::RecvIsExtensible(const ObjectId& objId, ReturnStatus* rs,
bool* result) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
*result = false;
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("%s.isExtensible()", ReceiverObj(objId));
bool extensible;
if (!JS_IsExtensible(cx, obj, &extensible)) {
return fail(jsapi, rs);
}
*result = !!extensible;
return ok(rs);
}
bool WrapperAnswer::RecvCallOrConstruct(const ObjectId& objId,
nsTArray<JSParam>&& argv,
const bool& construct, ReturnStatus* rs,
JSVariant* result,
nsTArray<JSParam>* outparams) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoEntryScript aes(scopeForTargetObjects(),
"Cross-Process Object Wrapper call/construct");
JSContext* cx = aes.cx();
// The outparam will be written to the buffer, so it must be set even if
// the parent won't read it.
*result = UndefinedVariant();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(aes, rs);
}
MOZ_ASSERT(argv.Length() >= 2);
RootedValue objv(cx);
if (!fromVariant(cx, argv[0], &objv)) {
return fail(aes, rs);
}
*result = JSVariant(UndefinedVariant());
RootedValueVector vals(cx);
RootedValueVector outobjects(cx);
for (size_t i = 0; i < argv.Length(); i++) {
if (argv[i].type() == JSParam::Tvoid_t) {
// This is an outparam.
RootedObject obj(cx, xpc::NewOutObject(cx));
if (!obj) {
return fail(aes, rs);
}
if (!outobjects.append(ObjectValue(*obj))) {
return fail(aes, rs);
}
if (!vals.append(ObjectValue(*obj))) {
return fail(aes, rs);
}
} else {
RootedValue v(cx);
if (!fromVariant(cx, argv[i].get_JSVariant(), &v)) {
return fail(aes, rs);
}
if (!vals.append(v)) {
return fail(aes, rs);
}
}
}
RootedValue rval(cx);
{
HandleValueArray args =
HandleValueArray::subarray(vals, 2, vals.length() - 2);
if (construct) {
RootedObject obj(cx);
if (!JS::Construct(cx, vals[0], args, &obj)) {
return fail(aes, rs);
}
rval.setObject(*obj);
} else {
if (!JS::Call(cx, vals[1], vals[0], args, &rval)) return fail(aes, rs);
}
}
if (!toVariant(cx, rval, result)) {
return fail(aes, rs);
}
// Prefill everything with a dummy jsval.
for (size_t i = 0; i < outobjects.length(); i++) {
outparams->AppendElement(JSParam(void_t()));
}
// Go through each argument that was an outparam, retrieve the "value"
// field, and add it to a temporary list. We need to do this separately
// because the outparams vector is not rooted.
vals.clear();
for (size_t i = 0; i < outobjects.length(); i++) {
RootedObject obj(cx, &outobjects[i].toObject());
RootedValue v(cx);
bool found;
if (JS_HasProperty(cx, obj, "value", &found)) {
if (!JS_GetProperty(cx, obj, "value", &v)) {
return fail(aes, rs);
}
} else {
v = UndefinedValue();
}
if (!vals.append(v)) {
return fail(aes, rs);
}
}
// Copy the outparams. If any outparam is already set to a void_t, we
// treat this as the outparam never having been set.
for (size_t i = 0; i < vals.length(); i++) {
JSVariant variant;
if (!toVariant(cx, vals[i], &variant)) {
return fail(aes, rs);
}
outparams->ReplaceElementAt(i, JSParam(variant));
}
LOG("%s.call(%s) = %s", ReceiverObj(objId), argv, OutVariant(*result));
return ok(rs);
}
bool WrapperAnswer::RecvHasInstance(const ObjectId& objId,
const JSVariant& vVar, ReturnStatus* rs,
bool* bp) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("%s.hasInstance(%s)", ReceiverObj(objId), InVariant(vVar));
RootedValue val(cx);
if (!fromVariant(cx, vVar, &val)) {
return fail(jsapi, rs);
}
if (!JS_HasInstance(cx, obj, val, bp)) {
return fail(jsapi, rs);
}
return ok(rs);
}
bool WrapperAnswer::RecvGetBuiltinClass(const ObjectId& objId, ReturnStatus* rs,
uint32_t* classValue) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
*classValue = uint32_t(js::ESClass::Other);
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("%s.getBuiltinClass()", ReceiverObj(objId));
js::ESClass cls;
if (!js::GetBuiltinClass(cx, obj, &cls)) {
return fail(jsapi, rs);
}
*classValue = uint32_t(cls);
return ok(rs);
}
bool WrapperAnswer::RecvIsArray(const ObjectId& objId, ReturnStatus* rs,
uint32_t* ans) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
*ans = uint32_t(IsArrayAnswer::NotArray);
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("%s.isArray()", ReceiverObj(objId));
IsArrayAnswer answer;
if (!JS::IsArray(cx, obj, &answer)) {
return fail(jsapi, rs);
}
*ans = uint32_t(answer);
return ok(rs);
}
bool WrapperAnswer::RecvClassName(const ObjectId& objId, nsCString* name) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
// This is very unfortunate, but we have no choice.
*name = "<dead CPOW>";
return true;
}
LOG("%s.className()", ReceiverObj(objId));
*name = js::ObjectClassName(cx, obj);
return true;
}
bool WrapperAnswer::RecvGetPrototype(const ObjectId& objId, ReturnStatus* rs,
ObjectOrNullVariant* result) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
*result = NullVariant();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
JS::RootedObject proto(cx);
if (!JS_GetPrototype(cx, obj, &proto)) {
return fail(jsapi, rs);
}
if (!toObjectOrNullVariant(cx, proto, result)) {
return fail(jsapi, rs);
}
LOG("getPrototype(%s)", ReceiverObj(objId));
return ok(rs);
}
bool WrapperAnswer::RecvGetPrototypeIfOrdinary(const ObjectId& objId,
ReturnStatus* rs,
bool* isOrdinary,
ObjectOrNullVariant* result) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
*result = NullVariant();
*isOrdinary = false;
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
JS::RootedObject proto(cx);
if (!JS_GetPrototypeIfOrdinary(cx, obj, isOrdinary, &proto)) {
return fail(jsapi, rs);
}
if (!toObjectOrNullVariant(cx, proto, result)) {
return fail(jsapi, rs);
}
LOG("getPrototypeIfOrdinary(%s)", ReceiverObj(objId));
return ok(rs);
}
bool WrapperAnswer::RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs,
nsString* source, uint32_t* flags) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
RootedString sourceJSStr(cx, JS::GetRegExpSource(cx, obj));
if (!sourceJSStr) {
return fail(jsapi, rs);
}
nsAutoJSString sourceStr;
if (!sourceStr.init(cx, sourceJSStr)) {
return fail(jsapi, rs);
}
source->Assign(sourceStr);
*flags = JS::GetRegExpFlags(cx, obj).value();
return ok(rs);
}
bool WrapperAnswer::RecvGetPropertyKeys(const ObjectId& objId,
const uint32_t& flags, ReturnStatus* rs,
nsTArray<JSIDVariant>* ids) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("%s.getPropertyKeys()", ReceiverObj(objId));
RootedIdVector props(cx);
if (!js::GetPropertyKeys(cx, obj, flags, &props)) {
return fail(jsapi, rs);
}
for (size_t i = 0; i < props.length(); i++) {
JSIDVariant id;
if (!toJSIDVariant(cx, props[i], &id)) {
return fail(jsapi, rs);
}
ids->AppendElement(id);
}
return ok(rs);
}
bool WrapperAnswer::RecvInstanceOf(const ObjectId& objId, const JSIID& iid,
ReturnStatus* rs, bool* instanceof) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
* instanceof = false;
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("%s.instanceOf()", ReceiverObj(objId));
nsID nsiid;
ConvertID(iid, &nsiid);
nsresult rv = xpc::HasInstance(cx, obj, &nsiid, instanceof);
if (rv != NS_OK) {
return fail(jsapi, rs);
}
return ok(rs);
}
bool WrapperAnswer::RecvDOMInstanceOf(const ObjectId& objId,
const int& prototypeID, const int& depth,
ReturnStatus* rs, bool* instanceof) {
if (!IsInAutomation()) {
return false;
}
MaybeForceDebugGC();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) {
return false;
}
JSContext* cx = jsapi.cx();
* instanceof = false;
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj) {
return deadCPOW(jsapi, rs);
}
LOG("%s.domInstanceOf()", ReceiverObj(objId));
bool tmp;
if (!mozilla::dom::InterfaceHasInstance(cx, prototypeID, depth, obj, &tmp)) {
return fail(jsapi, rs);
}
* instanceof = tmp;
return ok(rs);
}
bool WrapperAnswer::RecvDropObject(const ObjectId& objId) {
JSObject* obj = objects_.findPreserveColor(objId);
if (obj) {
objectIdMap(objId.hasXrayWaiver()).remove(obj);
objects_.remove(objId);
}
return true;
}

View file

@ -1,79 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=4 sw=2 et 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/. */
#ifndef mozilla_jsipc_WrapperAnswer_h_
#define mozilla_jsipc_WrapperAnswer_h_
#include "JavaScriptShared.h"
namespace mozilla {
namespace dom {
class AutoJSAPI;
} // namespace dom
namespace jsipc {
class WrapperAnswer : public virtual JavaScriptShared {
public:
bool RecvPreventExtensions(const ObjectId& objId, ReturnStatus* rs);
bool RecvGetOwnPropertyDescriptor(const ObjectId& objId,
const JSIDVariant& id, ReturnStatus* rs,
PPropertyDescriptor* out);
bool RecvDefineProperty(const ObjectId& objId, const JSIDVariant& id,
const PPropertyDescriptor& flags, ReturnStatus* rs);
bool RecvDelete(const ObjectId& objId, const JSIDVariant& id,
ReturnStatus* rs);
bool RecvHas(const ObjectId& objId, const JSIDVariant& id, ReturnStatus* rs,
bool* foundp);
bool RecvHasOwn(const ObjectId& objId, const JSIDVariant& id,
ReturnStatus* rs, bool* foundp);
bool RecvGet(const ObjectId& objId, const JSVariant& receiverVar,
const JSIDVariant& id, ReturnStatus* rs, JSVariant* result);
bool RecvSet(const ObjectId& objId, const JSIDVariant& id,
const JSVariant& value, const JSVariant& receiverVar,
ReturnStatus* rs);
bool RecvIsExtensible(const ObjectId& objId, ReturnStatus* rs, bool* result);
bool RecvCallOrConstruct(const ObjectId& objId, nsTArray<JSParam>&& argv,
const bool& construct, ReturnStatus* rs,
JSVariant* result, nsTArray<JSParam>* outparams);
bool RecvHasInstance(const ObjectId& objId, const JSVariant& v,
ReturnStatus* rs, bool* bp);
bool RecvGetBuiltinClass(const ObjectId& objId, ReturnStatus* rs,
uint32_t* classValue);
bool RecvIsArray(const ObjectId& objId, ReturnStatus* rs, uint32_t* ans);
bool RecvClassName(const ObjectId& objId, nsCString* result);
bool RecvGetPrototype(const ObjectId& objId, ReturnStatus* rs,
ObjectOrNullVariant* result);
bool RecvGetPrototypeIfOrdinary(const ObjectId& objId, ReturnStatus* rs,
bool* isOrdinary,
ObjectOrNullVariant* result);
bool RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs,
nsString* source, uint32_t* flags);
bool RecvGetPropertyKeys(const ObjectId& objId, const uint32_t& flags,
ReturnStatus* rs, nsTArray<JSIDVariant>* ids);
bool RecvInstanceOf(const ObjectId& objId, const JSIID& iid, ReturnStatus* rs,
bool* instanceof);
bool RecvDOMInstanceOf(const ObjectId& objId, const int& prototypeID,
const int& depth, ReturnStatus* rs, bool* instanceof);
bool RecvDropObject(const ObjectId& objId);
private:
bool fail(dom::AutoJSAPI& jsapi, ReturnStatus* rs);
bool ok(ReturnStatus* rs);
bool ok(ReturnStatus* rs, const JS::ObjectOpResult& result);
bool deadCPOW(dom::AutoJSAPI& jsapi, ReturnStatus* rs);
};
} // namespace jsipc
} // namespace mozilla
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,177 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sw=2 et 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/. */
#ifndef mozilla_jsipc_WrapperOwner_h__
#define mozilla_jsipc_WrapperOwner_h__
#include "JavaScriptShared.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "js/Class.h"
#include "js/Proxy.h"
namespace mozilla {
namespace jsipc {
class WrapperOwner : public virtual JavaScriptShared {
public:
using ActorDestroyReason = mozilla::ipc::IProtocol::ActorDestroyReason;
WrapperOwner();
// Standard internal methods.
// (The traps should be in the same order like js/Proxy.h)
bool getOwnPropertyDescriptor(JSContext* cx, JS::HandleObject proxy,
JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc);
bool defineProperty(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
JS::Handle<JS::PropertyDescriptor> desc,
JS::ObjectOpResult& result);
bool ownPropertyKeys(JSContext* cx, JS::HandleObject proxy,
JS::MutableHandleIdVector props);
bool delete_(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
JS::ObjectOpResult& result);
bool preventExtensions(JSContext* cx, JS::HandleObject proxy,
JS::ObjectOpResult& result);
bool isExtensible(JSContext* cx, JS::HandleObject proxy, bool* extensible);
bool has(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, bool* bp);
bool get(JSContext* cx, JS::HandleObject proxy, JS::HandleValue receiver,
JS::HandleId id, JS::MutableHandleValue vp);
bool set(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
JS::HandleValue v, JS::HandleValue receiver,
JS::ObjectOpResult& result);
bool callOrConstruct(JSContext* cx, JS::HandleObject proxy,
const JS::CallArgs& args, bool construct);
// SpiderMonkey extensions.
bool hasOwn(JSContext* cx, JS::HandleObject proxy, JS::HandleId id, bool* bp);
bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::HandleObject proxy,
JS::MutableHandleIdVector props);
bool hasInstance(JSContext* cx, JS::HandleObject proxy,
JS::MutableHandleValue v, bool* bp);
bool getBuiltinClass(JSContext* cx, JS::HandleObject proxy, js::ESClass* cls);
bool isArray(JSContext* cx, JS::HandleObject proxy,
JS::IsArrayAnswer* answer);
const char* className(JSContext* cx, JS::HandleObject proxy);
bool getPrototype(JSContext* cx, JS::HandleObject proxy,
JS::MutableHandleObject protop);
bool getPrototypeIfOrdinary(JSContext* cx, JS::HandleObject proxy,
bool* isOrdinary, JS::MutableHandleObject protop);
js::RegExpShared* regexp_toShared(JSContext* cx, JS::HandleObject proxy);
nsresult instanceOf(JSObject* obj, const nsID* id, bool* bp);
bool toString(JSContext* cx, JS::HandleObject callee, JS::CallArgs& args);
/*
* Check that |obj| is a DOM wrapper whose prototype chain contains
* |prototypeID| at depth |depth|.
*/
bool domInstanceOf(JSContext* cx, JSObject* obj, int prototypeID, int depth,
bool* bp);
bool active() { return !inactive_; }
virtual bool allowMessage(JSContext* cx) = 0;
void drop(JSObject* obj);
void updatePointer(JSObject* obj, const JSObject* old);
virtual void ActorDestroy(ActorDestroyReason why);
virtual bool toObjectVariant(JSContext* cx, JSObject* obj,
ObjectVariant* objVarp) override;
virtual JSObject* fromObjectVariant(JSContext* cx,
const ObjectVariant& objVar) override;
JSObject* fromRemoteObjectVariant(JSContext* cx, const RemoteObject& objVar);
JSObject* fromLocalObjectVariant(JSContext* cx, const LocalObject& objVar);
protected:
ObjectId idOf(JSObject* obj);
private:
ObjectId idOfUnchecked(JSObject* obj);
bool getPropertyKeys(JSContext* cx, JS::HandleObject proxy, uint32_t flags,
JS::MutableHandleIdVector props);
// Catastrophic IPC failure.
bool ipcfail(JSContext* cx);
// Check whether a return status is okay, and if not, propagate its error.
//
// If 'status' might be a ReturnObjectOpResult, which is only possible for
// a subset of the operations below, 'result' must be passed.
bool ok(JSContext* cx, const ReturnStatus& status,
JS::ObjectOpResult& result);
bool ok(JSContext* cx, const ReturnStatus& status);
bool inactive_;
/*** Dummy call handlers ***/
public:
virtual bool SendDropObject(const ObjectId& objId) = 0;
virtual bool SendPreventExtensions(const ObjectId& objId,
ReturnStatus* rs) = 0;
virtual bool SendGetOwnPropertyDescriptor(const ObjectId& objId,
const JSIDVariant& id,
ReturnStatus* rs,
PPropertyDescriptor* out) = 0;
virtual bool SendDefineProperty(const ObjectId& objId, const JSIDVariant& id,
const PPropertyDescriptor& flags,
ReturnStatus* rs) = 0;
virtual bool SendDelete(const ObjectId& objId, const JSIDVariant& id,
ReturnStatus* rs) = 0;
virtual bool SendHas(const ObjectId& objId, const JSIDVariant& id,
ReturnStatus* rs, bool* bp) = 0;
virtual bool SendHasOwn(const ObjectId& objId, const JSIDVariant& id,
ReturnStatus* rs, bool* bp) = 0;
virtual bool SendGet(const ObjectId& objId, const JSVariant& receiverVar,
const JSIDVariant& id, ReturnStatus* rs,
JSVariant* result) = 0;
virtual bool SendSet(const ObjectId& objId, const JSIDVariant& id,
const JSVariant& value, const JSVariant& receiverVar,
ReturnStatus* rs) = 0;
virtual bool SendIsExtensible(const ObjectId& objId, ReturnStatus* rs,
bool* result) = 0;
virtual bool SendCallOrConstruct(const ObjectId& objId,
const nsTArray<JSParam>& argv,
const bool& construct, ReturnStatus* rs,
JSVariant* result,
nsTArray<JSParam>* outparams) = 0;
virtual bool SendHasInstance(const ObjectId& objId, const JSVariant& v,
ReturnStatus* rs, bool* bp) = 0;
virtual bool SendGetBuiltinClass(const ObjectId& objId, ReturnStatus* rs,
uint32_t* classValue) = 0;
virtual bool SendIsArray(const ObjectId& objId, ReturnStatus* rs,
uint32_t* answer) = 0;
virtual bool SendClassName(const ObjectId& objId, nsCString* result) = 0;
virtual bool SendGetPrototype(const ObjectId& objId, ReturnStatus* rs,
ObjectOrNullVariant* result) = 0;
virtual bool SendGetPrototypeIfOrdinary(const ObjectId& objId,
ReturnStatus* rs, bool* isOrdinary,
ObjectOrNullVariant* result) = 0;
virtual bool SendRegExpToShared(const ObjectId& objId, ReturnStatus* rs,
nsString* source, uint32_t* flags) = 0;
virtual bool SendGetPropertyKeys(const ObjectId& objId, const uint32_t& flags,
ReturnStatus* rs,
nsTArray<JSIDVariant>* ids) = 0;
virtual bool SendInstanceOf(const ObjectId& objId, const JSIID& iid,
ReturnStatus* rs, bool* instanceof) = 0;
virtual bool SendDOMInstanceOf(const ObjectId& objId, const int& prototypeID,
const int& depth, ReturnStatus* rs,
bool* instanceof) = 0;
};
} // namespace jsipc
} // namespace mozilla
#endif // mozilla_jsipc_WrapperOwner_h__

View file

@ -1,40 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
UNIFIED_SOURCES += [
'JavaScriptChild.cpp',
'JavaScriptParent.cpp',
'JavaScriptShared.cpp',
'WrapperAnswer.cpp',
'WrapperOwner.cpp',
]
IPDL_SOURCES += [
'JavaScriptTypes.ipdlh',
'PJavaScript.ipdl',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
DEFINES['BIN_SUFFIX'] = '"%s"' % CONFIG['BIN_SUFFIX']
EXPORTS.mozilla.jsipc = [
'CpowHolder.h',
'CrossProcessObjectWrappers.h',
]
LOCAL_INCLUDES += [
'/dom/base',
'/js/ipc',
'/js/src',
'/js/xpconnect/src',
'/js/xpconnect/wrappers',
]
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-shadow']

View file

@ -58,9 +58,6 @@ class JS_FRIEND_API Wrapper;
* - DOM objects with special property behavior, like named getters
* (dom/bindings/Codegen.py generates these proxies from WebIDL)
*
* - semi-transparent use of objects that live in other processes
* (CPOWs, implemented in js/ipc)
*
* ### Proxies and internal methods
*
* ES2019 specifies 13 internal methods. The runtime semantics of just about

View file

@ -9,7 +9,7 @@ set -e
cd $SOURCE
./mach configure
./mach build export
./mach build -X nsprpub mfbt memory memory/mozalloc modules/zlib mozglue js/src xpcom/glue js/ductwork/debugger js/ipc js/xpconnect/loader js/xpconnect/wrappers js/xpconnect/src
./mach build -X nsprpub mfbt memory memory/mozalloc modules/zlib mozglue js/src xpcom/glue js/ductwork/debugger js/xpconnect/loader js/xpconnect/wrappers js/xpconnect/src
status=$?
echo "[[[[ build.js complete, exit code $status ]]]]"
exit $status

View file

@ -30,7 +30,6 @@
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/PrimitiveConversions.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
using namespace xpc;
using namespace mozilla;
@ -46,22 +45,6 @@ using namespace JS;
#define ILLEGAL_CHAR_RANGE(c) (0 != ((c)&0x80))
/***********************************************************/
static JSObject* UnwrapNativeCPOW(nsISupports* wrapper) {
nsCOMPtr<nsIXPConnectWrappedJS> underware = do_QueryInterface(wrapper);
if (underware) {
// The analysis falsely believes that ~nsCOMPtr can GC because it could
// drop the refcount to zero, but that can't happen here.
JS::AutoSuppressGCAnalysis nogc;
JSObject* mainObj = underware->GetJSObject();
if (mainObj && mozilla::jsipc::IsWrappedCPOW(mainObj)) {
return mainObj;
}
}
return nullptr;
}
/***************************************************************************/
// static
@ -956,19 +939,6 @@ bool XPCConvert::NativeInterface2JSObject(JSContext* cx, MutableHandleValue d,
}
}
// Don't double wrap CPOWs. This is a temporary measure for compatibility
// with objects that don't provide necessary QIs (such as objects under
// the new DOM bindings). We expect the other side of the CPOW to have
// the appropriate wrappers in place.
RootedObject cpow(cx, UnwrapNativeCPOW(aHelper.Object()));
if (cpow) {
if (!JS_WrapObject(cx, &cpow)) {
return false;
}
d.setObject(*cpow);
return true;
}
// Go ahead and create an XPCWrappedNative for this object.
RefPtr<XPCNativeInterface> iface = XPCNativeInterface::GetNewOrUsed(cx, iid);
if (!iface) {

View file

@ -44,7 +44,6 @@
#include "mozilla/dom/ScriptLoader.h"
#include "mozilla/dom/WindowBinding.h"
#include "mozilla/extensions/WebExtensionPolicy.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/ProcessHangMonitor.h"
@ -1341,7 +1340,6 @@ void XPCJSContext::AfterProcessTask(uint32_t aNewRecursionDepth) {
MOZ_ASSERT(NS_IsMainThread());
nsJSContext::MaybePokeCC();
CycleCollectedJSContext::AfterProcessTask(aNewRecursionDepth);
mozilla::jsipc::AfterProcessTask();
// This exception might have been set if we called an XPCWrappedJS that threw,
// but now we're returning to the event loop, so nothing is going to look at

View file

@ -9,7 +9,6 @@
#include "xpcprivate.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "js/Symbol.h"
using namespace mozilla::dom;
@ -370,7 +369,6 @@ static bool ID_Equals(JSContext* aCx, unsigned aArgc, Value* aVp) {
*/
static nsresult FindObjectForHasInstance(JSContext* cx, HandleObject objArg,
MutableHandleObject target) {
using namespace mozilla::jsipc;
RootedObject obj(cx, objArg), proto(cx);
while (true) {
// Try the object, or the wrappee if allowed. We want CheckedUnwrapDynamic
@ -378,7 +376,7 @@ static nsresult FindObjectForHasInstance(JSContext* cx, HandleObject objArg,
// our current global.
JSObject* o =
js::IsWrapper(obj) ? js::CheckedUnwrapDynamic(obj, cx, false) : obj;
if (o && (IS_WN_REFLECTOR(o) || IsDOMObject(o) || IsCPOW(o))) {
if (o && (IS_WN_REFLECTOR(o) || IsDOMObject(o))) {
target.set(o);
return NS_OK;
}
@ -410,10 +408,6 @@ nsresult HasInstance(JSContext* cx, HandleObject objArg, const nsID* iid,
return NS_OK;
}
if (mozilla::jsipc::IsCPOW(obj)) {
return mozilla::jsipc::InstanceOf(obj, iid, bp);
}
// Need to unwrap Window correctly here, so use ReflectorToISupportsDynamic.
nsCOMPtr<nsISupports> identity = ReflectorToISupportsDynamic(obj, cx);
if (!identity) {

View file

@ -57,7 +57,6 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/WindowBinding.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/ProcessHangMonitor.h"

View file

@ -9,7 +9,6 @@
#include "xpcprivate.h"
#include "mozilla/DeferredFinalize.h"
#include "mozilla/Sprintf.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "nsCCUncollectableMarker.h"
#include "nsContentUtils.h"
#include "nsThreadUtils.h"

View file

@ -20,7 +20,6 @@
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/DOMExceptionBinding.h"
#include "mozilla/dom/MozQueryInterface.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "jsapi.h"
#include "jsfriendapi.h"

View file

@ -7,7 +7,6 @@
/* Wrapper object for reflecting native xpcom objects into JavaScript. */
#include "xpcprivate.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "nsWrapperCacheInlines.h"
#include "XPCLog.h"
#include "js/Array.h" // JS::GetArrayLength, JS::IsArrayObject
@ -1537,19 +1536,6 @@ bool CallMethodHelper::ConvertIndependentParam(uint8_t i) {
param_iid = inner.GetInterface()->IID();
}
// Don't allow CPOWs to be passed to native code (in case they try to cast
// to a concrete type).
if (src.isObject() && jsipc::IsWrappedCPOW(&src.toObject()) &&
type.Tag() == nsXPTType::T_INTERFACE &&
!param_iid.Equals(NS_GET_IID(nsISupports))) {
// Allow passing CPOWs to XPCWrappedJS.
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS(do_QueryInterface(mCallee));
if (!wrappedJS) {
ThrowBadParam(NS_ERROR_XPC_CANT_PASS_CPOW_TO_NATIVE, i, mCallContext);
return false;
}
}
nsresult err;
if (!XPCConvert::JSData2Native(mCallContext, &dp->val, src, type, &param_iid,
0, &err)) {

View file

@ -19,7 +19,6 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/LocationBinding.h"
#include "mozilla/dom/WindowBinding.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "nsJSUtils.h"
#include "xpcprivate.h"
@ -100,16 +99,6 @@ bool AccessCheck::checkPassToPrivilegedCode(JSContext* cx, HandleObject wrapper,
return true;
}
// CPOWs use COWs (in the unprivileged junk scope) for all child->parent
// references. Without this test, the child process wouldn't be able to
// pass any objects at all to CPOWs.
if (mozilla::jsipc::IsWrappedCPOW(obj) &&
js::GetObjectCompartment(wrapper) ==
js::GetObjectCompartment(xpc::UnprivilegedJunkScope()) &&
XRE_IsParentProcess()) {
return true;
}
// Same-origin wrappers are fine.
if (AccessCheck::wrapperSubsumes(obj)) {
return true;

View file

@ -16,7 +16,6 @@
#include "XPCMaps.h"
#include "mozilla/dom/BindingUtils.h"
#include "jsfriendapi.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/Likely.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/MaybeCrossOriginObject.h"
@ -543,11 +542,8 @@ JSObject* WrapperFactory::Rewrap(JSContext* cx, HandleObject existing,
// Special handling for chrome objects being exposed to content.
else if (originIsChrome && !targetIsChrome) {
// If this is a chrome function being exposed to content, we need to allow
// call (but nothing else). We allow CPOWs that purport to be function's
// here, but only in the content process.
if ((IdentifyStandardInstance(obj) == JSProto_Function ||
(jsipc::IsCPOW(obj) && JS::IsCallable(obj) &&
XRE_IsContentProcess()))) {
// call (but nothing else).
if ((IdentifyStandardInstance(obj) == JSProto_Function)) {
wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper,
OpaqueWithCall>::singleton;
}

View file

@ -74,7 +74,6 @@ if CONFIG['MOZ_UPDATER'] and CONFIG['OS_TARGET'] != 'Android':
DIRS += [
'/ipc',
'/js/ipc',
'/hal',
'/js/xpconnect',
'/modules/libjar',