forked from mirrors/gecko-dev
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:
parent
2f983e6cfa
commit
38b061ef45
41 changed files with 6 additions and 4645 deletions
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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*);
|
||||
|
|
|
|||
|
|
@ -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.)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ include protocol PBrowserBridge;
|
|||
include DOMTypes;
|
||||
include IPCBlob;
|
||||
include IPCStream;
|
||||
include JavaScriptTypes;
|
||||
include URIParams;
|
||||
include PPrintingTypes;
|
||||
include PTabContext;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ EXPORTS.mozilla.dom += [
|
|||
'ContentParent.h',
|
||||
'ContentProcess.h',
|
||||
'ContentProcessManager.h',
|
||||
'CPOWManagerGetter.h',
|
||||
'CSPMessageUtils.h',
|
||||
'DocShellMessageUtils.h',
|
||||
'EffectsInfo.h',
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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__
|
||||
|
|
@ -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__
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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__
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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__
|
||||
|
|
@ -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']
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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, ¶m_iid,
|
||||
0, &err)) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ if CONFIG['MOZ_UPDATER'] and CONFIG['OS_TARGET'] != 'Android':
|
|||
|
||||
DIRS += [
|
||||
'/ipc',
|
||||
'/js/ipc',
|
||||
'/hal',
|
||||
'/js/xpconnect',
|
||||
'/modules/libjar',
|
||||
|
|
|
|||
Loading…
Reference in a new issue