Bug 1081353 - Eliminate PPluginIdentifier (r=bsmedberg)

This commit is contained in:
Bill McCloskey 2014-10-20 09:47:25 -07:00
Родитель 273f76d366
Коммит 1809fa7212
18 изменённых файлов: 440 добавлений и 818 удалений

Просмотреть файл

@ -126,7 +126,7 @@ IntToNPIdentifier(int i)
JSContext* GetJSContext(NPP npp);
inline bool
NPStringIdentifierIsPermanent(NPP npp, NPIdentifier id)
NPStringIdentifierIsPermanent(NPIdentifier id)
{
AutoSafeJSContext cx;
return JS_StringHasBeenInterned(cx, NPIdentifierToString(id));

Просмотреть файл

@ -1,30 +0,0 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* 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 PPluginModule;
namespace mozilla {
namespace plugins {
/**
* Represents an NPIdentifier that wraps either a string or an integer.
*/
async protocol PPluginIdentifier
{
manager PPluginModule;
parent:
/**
* If this is a temporary identifier, inform the parent that the plugin
* has made the identifier permanent by calling NPN_GetStringIdentifier.
*/
async Retain();
child:
async __delete__();
};
} // namespace plugins
} // namespace mozilla

Просмотреть файл

@ -3,12 +3,10 @@
* 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 PPluginIdentifier;
include protocol PPluginInstance;
include protocol PPluginScriptableObject;
include protocol PCrashReporter;
using NPError from "npapi.h";
using NPNVariable from "npapi.h";
using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
@ -21,25 +19,9 @@ namespace plugins {
intr protocol PPluginModule
{
manages PPluginInstance;
manages PPluginIdentifier;
manages PCrashReporter;
both:
/**
* Sending a void string to this constructor creates an int identifier whereas
* sending a non-void string will create a string identifier. This constructor
* may be called by either child or parent. If a race occurs by calling the
* constructor with the same string or int argument then we create two actors
* and detect the second instance in the child. We prevent the parent's actor
* from leaking out to plugin code and only allow the child's to be used.
*
* When calling into the plugin, the parent may create a "temporary"
* identifier which is only valid for the lifetime of the current inerrupt frame.
*/
async PPluginIdentifier(nsCString aString,
int32_t aInt,
bool temporary);
// Window-specific message which instructs the interrupt mechanism to enter
// a nested event loop for the current interrupt call.
async ProcessNativeEventsInInterruptCall();

Просмотреть файл

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PPluginInstance;
include protocol PPluginIdentifier;
include PluginTypes;
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
@ -39,10 +39,10 @@ child:
both:
// NPClass methods
intr HasMethod(PPluginIdentifier aId)
intr HasMethod(PluginIdentifier aId)
returns (bool aHasMethod);
intr Invoke(PPluginIdentifier aId,
intr Invoke(PluginIdentifier aId,
Variant[] aArgs)
returns (Variant aResult,
bool aSuccess);
@ -51,18 +51,18 @@ both:
returns (Variant aResult,
bool aSuccess);
intr HasProperty(PPluginIdentifier aId)
intr HasProperty(PluginIdentifier aId)
returns (bool aHasProperty);
intr SetProperty(PPluginIdentifier aId,
intr SetProperty(PluginIdentifier aId,
Variant aValue)
returns (bool aSuccess);
intr RemoveProperty(PPluginIdentifier aId)
intr RemoveProperty(PluginIdentifier aId)
returns (bool aSuccess);
intr Enumerate()
returns (PPluginIdentifier[] aProperties,
returns (PluginIdentifier[] aProperties,
bool aSuccess);
intr Construct(Variant[] aArgs)
@ -86,12 +86,12 @@ both:
* several checks at once and return all the results simultaneously.
*/
parent:
intr GetParentProperty(PPluginIdentifier aId)
intr GetParentProperty(PluginIdentifier aId)
returns (Variant aResult,
bool aSuccess);
child:
intr GetChildProperty(PPluginIdentifier aId)
intr GetChildProperty(PluginIdentifier aId)
returns (bool aHasProperty,
bool aHasMethod,
Variant aResult,

Просмотреть файл

@ -1,141 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et :
* 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 "PluginIdentifierChild.h"
#include "PluginModuleChild.h"
namespace mozilla {
namespace plugins {
void
PluginIdentifierChild::MakePermanent()
{
if (mCanonicalIdentifier) {
NS_ASSERTION(mCanonicalIdentifier->mHashed && mCanonicalIdentifier->mTemporaryRefs == 0,
"Canonical identifiers should always be permanent.");
return; // nothing to do
}
if (!mHashed) {
NS_ASSERTION(mTemporaryRefs == 0, "Not hashed, but temporary refs?");
PluginIdentifierChild* c = GetCanonical();
if (c) {
NS_ASSERTION(c != this, "How did I get in the hash?");
mCanonicalIdentifier = c;
NS_ASSERTION(mCanonicalIdentifier->mHashed && mCanonicalIdentifier->mTemporaryRefs == 0,
"Canonical identifiers should always be permanent.");
return;
}
Hash();
mHashed = true;
return;
}
if (mTemporaryRefs) {
SendRetain();
mTemporaryRefs = 0;
}
}
void
PluginIdentifierChild::StartTemporary()
{
if (mCanonicalIdentifier) {
NS_ASSERTION(mCanonicalIdentifier->mHashed && mCanonicalIdentifier->mTemporaryRefs == 0,
"Canonical identifiers should always be permanent.");
return; // nothing to do
}
if (!mHashed) {
NS_ASSERTION(mTemporaryRefs == 0, "Not hashed, but temporary refs?");
PluginIdentifierChild* c = GetCanonical();
if (c) {
NS_ASSERTION(c != this, "How did I get in the hash?");
mCanonicalIdentifier = c;
NS_ASSERTION(mCanonicalIdentifier->mHashed && mCanonicalIdentifier->mTemporaryRefs == 0,
"Canonical identifiers should always be permanent.");
return;
}
Hash();
mHashed = true;
mTemporaryRefs = 1;
return;
}
if (mTemporaryRefs)
++mTemporaryRefs;
}
void
PluginIdentifierChild::FinishTemporary()
{
if (mCanonicalIdentifier)
return;
NS_ASSERTION(mHashed, "Finishing unhashed identifier?");
if (!mTemporaryRefs)
return;
--mTemporaryRefs;
if (mTemporaryRefs)
return;
Unhash();
mHashed = false;
}
PluginIdentifierChild*
PluginIdentifierChildString::GetCanonical()
{
PluginModuleChild* module = static_cast<PluginModuleChild*>(Manager());
return module->mStringIdentifiers.Get(mString);
}
void
PluginIdentifierChildString::Hash()
{
PluginModuleChild* module = static_cast<PluginModuleChild*>(Manager());
NS_ASSERTION(module->mStringIdentifiers.Get(mString) == nullptr, "Replacing Hash?");
module->mStringIdentifiers.Put(mString, this);
}
void
PluginIdentifierChildString::Unhash()
{
PluginModuleChild* module = static_cast<PluginModuleChild*>(Manager());
NS_ASSERTION(module->mStringIdentifiers.Get(mString) == this, "Incorrect identifier hash?");
module->mStringIdentifiers.Remove(mString);
}
PluginIdentifierChild*
PluginIdentifierChildInt::GetCanonical()
{
PluginModuleChild* module = static_cast<PluginModuleChild*>(Manager());
return module->mIntIdentifiers.Get(mInt);
}
void
PluginIdentifierChildInt::Hash()
{
PluginModuleChild* module = static_cast<PluginModuleChild*>(Manager());
NS_ASSERTION(module->mIntIdentifiers.Get(mInt) == nullptr, "Replacing Hash?");
module->mIntIdentifiers.Put(mInt, this);
}
void
PluginIdentifierChildInt::Unhash()
{
PluginModuleChild* module = static_cast<PluginModuleChild*>(Manager());
NS_ASSERTION(module->mIntIdentifiers.Get(mInt) == this, "Incorrect identifier hash?");
module->mIntIdentifiers.Remove(mInt);
}
} // namespace mozilla::plugins
} // namespace mozilla

Просмотреть файл

@ -1,164 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et :
* 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 dom_plugins_PluginIdentifierChild_h
#define dom_plugins_PluginIdentifierChild_h
#include "mozilla/plugins/PPluginIdentifierChild.h"
#include "npapi.h"
#include "npruntime.h"
#include "nsString.h"
namespace mozilla {
namespace plugins {
class PluginModuleChild;
/**
* Plugin identifiers may be "temporary", see the comment on the
* PPluginIdentifier constructor for details. This means that any IPDL method
* which receives a PPluginIdentifierChild* parameter must use StackIdentifier
* to track it.
*/
class PluginIdentifierChild : public PPluginIdentifierChild
{
friend class PluginModuleChild;
public:
bool IsString()
{
return mIsString;
}
NPIdentifier ToNPIdentifier()
{
if (mCanonicalIdentifier) {
return mCanonicalIdentifier;
}
NS_ASSERTION(mHashed, "Handing out an unhashed identifier?");
return this;
}
void MakePermanent();
class MOZ_STACK_CLASS StackIdentifier
{
public:
explicit StackIdentifier(PPluginIdentifierChild* actor)
: mIdentifier(static_cast<PluginIdentifierChild*>(actor))
{
if (mIdentifier)
mIdentifier->StartTemporary();
}
~StackIdentifier() {
if (mIdentifier)
mIdentifier->FinishTemporary();
}
PluginIdentifierChild* operator->() { return mIdentifier; }
private:
PluginIdentifierChild* mIdentifier;
};
protected:
explicit PluginIdentifierChild(bool aIsString)
: mCanonicalIdentifier(nullptr)
, mHashed(false)
, mTemporaryRefs(0)
, mIsString(aIsString)
{
MOZ_COUNT_CTOR(PluginIdentifierChild);
}
virtual ~PluginIdentifierChild()
{
MOZ_COUNT_DTOR(PluginIdentifierChild);
}
// The following functions are implemented by the subclasses for their
// identifier maps.
virtual PluginIdentifierChild* GetCanonical() = 0;
virtual void Hash() = 0;
virtual void Unhash() = 0;
private:
void StartTemporary();
void FinishTemporary();
// There's a possibility that we already have an actor that wraps the same
// string or int because we do all this identifier construction
// asynchronously. In this case we need to hand out the canonical version
// created by the child side.
//
// In order to deal with temporary identifiers which appear on the stack,
// identifiers use the following state invariants:
//
// * mCanonicalIdentifier is non-nullptr: this is a duplicate identifier, no
// further information is necessary.
// * mHashed is false: this identifier is a newborn, non-permanent identifier
// * mHashed is true, mTemporaryRefs is 0: this identifier is permanent
// * mHashed is true, mTemporaryRefs is non-0: this identifier is temporary;
// if NPN_GetFooIdentifier is called for it, we need to retain it. If
// all stack references are lost, unhash it because it will soon be
// deleted.
PluginIdentifierChild* mCanonicalIdentifier;
bool mHashed;
unsigned int mTemporaryRefs;
bool mIsString;
};
class PluginIdentifierChildString : public PluginIdentifierChild
{
friend class PluginModuleChild;
public:
NPUTF8* ToString()
{
return ToNewCString(mString);
}
protected:
explicit PluginIdentifierChildString(const nsCString& aString)
: PluginIdentifierChild(true),
mString(aString)
{ }
virtual PluginIdentifierChild* GetCanonical();
virtual void Hash();
virtual void Unhash();
nsCString mString;
};
class PluginIdentifierChildInt : public PluginIdentifierChild
{
friend class PluginModuleChild;
public:
int32_t ToInt()
{
return mInt;
}
protected:
explicit PluginIdentifierChildInt(int32_t aInt)
: PluginIdentifierChild(false),
mInt(aInt)
{ }
virtual PluginIdentifierChild* GetCanonical();
virtual void Hash();
virtual void Unhash();
int32_t mInt;
};
} // namespace plugins
} // namespace mozilla
#endif // dom_plugins_PluginIdentifierChild_h

Просмотреть файл

@ -1,80 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et :
* 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 "PluginIdentifierParent.h"
#include "nsNPAPIPlugin.h"
#include "nsServiceManagerUtils.h"
#include "PluginScriptableObjectUtils.h"
#include "mozilla/unused.h"
using namespace mozilla::plugins::parent;
namespace mozilla {
namespace plugins {
void
PluginIdentifierParent::ActorDestroy(ActorDestroyReason aWhy)
{
// Implement me! Bug 1005161
}
bool
PluginIdentifierParent::RecvRetain()
{
mTemporaryRefs = 0;
// Intern the jsid if necessary.
AutoSafeJSContext cx;
JS::Rooted<jsid> id(cx, NPIdentifierToJSId(mIdentifier));
if (!JSID_IS_STRING(id)) {
return true;
}
// The following is what nsNPAPIPlugin.cpp does. Gross, but the API doesn't
// give you a NPP to play with.
JS::Rooted<JSString*> str(cx, JSID_TO_STRING(id));
JSString* str2 = JS_InternJSString(cx, str);
if (!str2) {
return false;
}
NS_ASSERTION(str == str2, "Interning a string in a JSID should always return the same string.");
return true;
}
PluginIdentifierParent::StackIdentifier::StackIdentifier
(PluginInstanceParent* inst, NPIdentifier aIdentifier)
: mIdentifier(inst->Module()->GetIdentifierForNPIdentifier(inst->GetNPP(), aIdentifier))
{
}
PluginIdentifierParent::StackIdentifier::StackIdentifier
(NPObject* aObject, NPIdentifier aIdentifier)
: mIdentifier(nullptr)
{
PluginInstanceParent* inst = GetInstance(aObject);
mIdentifier = inst->Module()->GetIdentifierForNPIdentifier(inst->GetNPP(), aIdentifier);
}
PluginIdentifierParent::StackIdentifier::~StackIdentifier()
{
if (!mIdentifier) {
return;
}
if (!mIdentifier->IsTemporary()) {
return;
}
if (mIdentifier->RemoveTemporaryRef()) {
unused << PPluginIdentifierParent::Send__delete__(mIdentifier);
}
}
} // namespace mozilla::plugins
} // namespace mozilla

Просмотреть файл

@ -1,91 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et :
* 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 dom_plugins_PluginIdentifierParent_h
#define dom_plugins_PluginIdentifierParent_h
#include "mozilla/plugins/PPluginIdentifierParent.h"
#include "npapi.h"
#include "npruntime.h"
namespace mozilla {
namespace plugins {
class PluginInstanceParent;
class PluginIdentifierParent : public PPluginIdentifierParent
{
friend class PluginModuleParent;
public:
NPIdentifier ToNPIdentifier()
{
return mIdentifier;
}
bool IsTemporary() {
return !!mTemporaryRefs;
}
/**
* Holds a perhaps-temporary identifier for the current stack frame.
*/
class MOZ_STACK_CLASS StackIdentifier
{
public:
StackIdentifier(PluginInstanceParent* inst, NPIdentifier aIdentifier);
StackIdentifier(NPObject* aObject, NPIdentifier aIdentifier);
~StackIdentifier();
operator PluginIdentifierParent*() {
return mIdentifier;
}
private:
DISALLOW_COPY_AND_ASSIGN(StackIdentifier);
PluginIdentifierParent* mIdentifier;
};
protected:
PluginIdentifierParent(NPIdentifier aIdentifier, bool aTemporary)
: mIdentifier(aIdentifier)
, mTemporaryRefs(aTemporary ? 1 : 0)
{
MOZ_COUNT_CTOR(PluginIdentifierParent);
}
virtual ~PluginIdentifierParent()
{
MOZ_COUNT_DTOR(PluginIdentifierParent);
}
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool RecvRetain() MOZ_OVERRIDE;
void AddTemporaryRef() {
mTemporaryRefs++;
}
/**
* @returns true if the last temporary reference was removed.
*/
bool RemoveTemporaryRef() {
--mTemporaryRefs;
return !mTemporaryRefs;
}
private:
NPIdentifier mIdentifier;
unsigned int mTemporaryRefs;
};
} // namespace plugins
} // namespace mozilla
#endif // dom_plugins_PluginIdentifierParent_h

Просмотреть файл

@ -37,7 +37,6 @@
#include "mozilla/plugins/StreamNotifyChild.h"
#include "mozilla/plugins/BrowserStreamChild.h"
#include "mozilla/plugins/PluginStreamChild.h"
#include "PluginIdentifierChild.h"
#include "mozilla/dom/CrashReporterChild.h"
#include "nsNPAPIPlugin.h"
@ -121,6 +120,7 @@ PluginModuleChild::~PluginModuleChild()
// other similar hooks.
DeinitGraphics();
PluginScriptableObjectChild::ClearIdentifiers();
gInstance = nullptr;
}
@ -1844,38 +1844,6 @@ PluginModuleChild::AnswerNP_Initialize(NPError* _retval)
#endif
}
PPluginIdentifierChild*
PluginModuleChild::AllocPPluginIdentifierChild(const nsCString& aString,
const int32_t& aInt,
const bool& aTemporary)
{
// We cannot call SetPermanent within this function because Manager() isn't
// set up yet.
if (aString.IsVoid()) {
return new PluginIdentifierChildInt(aInt);
}
return new PluginIdentifierChildString(aString);
}
bool
PluginModuleChild::RecvPPluginIdentifierConstructor(PPluginIdentifierChild* actor,
const nsCString& aString,
const int32_t& aInt,
const bool& aTemporary)
{
if (!aTemporary) {
static_cast<PluginIdentifierChild*>(actor)->MakePermanent();
}
return true;
}
bool
PluginModuleChild::DeallocPPluginIdentifierChild(PPluginIdentifierChild* aActor)
{
delete aActor;
return true;
}
#if defined(XP_WIN)
BOOL WINAPI
PMCGetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
@ -2180,18 +2148,11 @@ PluginModuleChild::NPN_GetStringIdentifier(const NPUTF8* aName)
if (!aName)
return 0;
PluginModuleChild* self = PluginModuleChild::current();
nsDependentCString name(aName);
PluginIdentifierChildString* ident = self->mStringIdentifiers.Get(name);
if (!ident) {
nsCString nameCopy(name);
ident = new PluginIdentifierChildString(nameCopy);
self->SendPPluginIdentifierConstructor(ident, nameCopy, -1, false);
}
ident->MakePermanent();
return ident;
PluginIdentifier ident(name);
PluginScriptableObjectChild::StackIdentifier stackID(ident);
stackID.MakePermanent();
return stackID.ToNPIdentifier();
}
void
@ -2206,23 +2167,16 @@ PluginModuleChild::NPN_GetStringIdentifiers(const NPUTF8** aNames,
NS_RUNTIMEABORT("Bad input! Headed for a crash!");
}
PluginModuleChild* self = PluginModuleChild::current();
for (int32_t index = 0; index < aNameCount; ++index) {
if (!aNames[index]) {
aIdentifiers[index] = 0;
continue;
}
nsDependentCString name(aNames[index]);
PluginIdentifierChildString* ident = self->mStringIdentifiers.Get(name);
if (!ident) {
nsCString nameCopy(name);
ident = new PluginIdentifierChildString(nameCopy);
self->SendPPluginIdentifierConstructor(ident, nameCopy, -1, false);
}
ident->MakePermanent();
aIdentifiers[index] = ident;
PluginIdentifier ident(name);
PluginScriptableObjectChild::StackIdentifier stackID(ident);
stackID.MakePermanent();
aIdentifiers[index] = stackID.ToNPIdentifier();
}
}
@ -2231,9 +2185,8 @@ PluginModuleChild::NPN_IdentifierIsString(NPIdentifier aIdentifier)
{
PLUGIN_LOG_DEBUG_FUNCTION;
PluginIdentifierChild* ident =
static_cast<PluginIdentifierChild*>(aIdentifier);
return ident->IsString();
PluginScriptableObjectChild::StackIdentifier stack(aIdentifier);
return stack.IsString();
}
NPIdentifier
@ -2242,18 +2195,10 @@ PluginModuleChild::NPN_GetIntIdentifier(int32_t aIntId)
PLUGIN_LOG_DEBUG_FUNCTION;
AssertPluginThread();
PluginModuleChild* self = PluginModuleChild::current();
PluginIdentifierChildInt* ident = self->mIntIdentifiers.Get(aIntId);
if (!ident) {
nsCString voidString;
voidString.SetIsVoid(true);
ident = new PluginIdentifierChildInt(aIntId);
self->SendPPluginIdentifierConstructor(ident, voidString, aIntId, false);
}
ident->MakePermanent();
return ident;
PluginIdentifier ident(aIntId);
PluginScriptableObjectChild::StackIdentifier stackID(ident);
stackID.MakePermanent();
return stackID.ToNPIdentifier();
}
NPUTF8*
@ -2261,8 +2206,9 @@ PluginModuleChild::NPN_UTF8FromIdentifier(NPIdentifier aIdentifier)
{
PLUGIN_LOG_DEBUG_FUNCTION;
if (static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
return static_cast<PluginIdentifierChildString*>(aIdentifier)->ToString();
PluginScriptableObjectChild::StackIdentifier stackID(aIdentifier);
if (stackID.IsString()) {
return ToNewCString(stackID.GetString());
}
return nullptr;
}
@ -2272,8 +2218,9 @@ PluginModuleChild::NPN_IntFromIdentifier(NPIdentifier aIdentifier)
{
PLUGIN_LOG_DEBUG_FUNCTION;
if (!static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
return static_cast<PluginIdentifierChildInt*>(aIdentifier)->ToInt();
PluginScriptableObjectChild::StackIdentifier stackID(aIdentifier);
if (!stackID.IsString()) {
return stackID.GetInt();
}
return INT32_MIN;
}

Просмотреть файл

@ -30,7 +30,6 @@
#include "mozilla/plugins/PPluginModuleChild.h"
#include "mozilla/plugins/PluginInstanceChild.h"
#include "mozilla/plugins/PluginIdentifierChild.h"
#include "mozilla/plugins/PluginMessageUtils.h"
// NOTE: stolen from nsNPAPIPlugin.h
@ -77,20 +76,6 @@ protected:
virtual bool AnswerNP_GetEntryPoints(NPError* rv) MOZ_OVERRIDE;
virtual bool AnswerNP_Initialize(NPError* rv) MOZ_OVERRIDE;
virtual PPluginIdentifierChild*
AllocPPluginIdentifierChild(const nsCString& aString,
const int32_t& aInt,
const bool& aTemporary) MOZ_OVERRIDE;
virtual bool
RecvPPluginIdentifierConstructor(PPluginIdentifierChild* actor,
const nsCString& aString,
const int32_t& aInt,
const bool& aTemporary) MOZ_OVERRIDE;
virtual bool
DeallocPPluginIdentifierChild(PPluginIdentifierChild* aActor) MOZ_OVERRIDE;
virtual PPluginInstanceChild*
AllocPPluginInstanceChild(const nsCString& aMimeType,
const uint16_t& aMode,
@ -388,12 +373,6 @@ private:
*/
nsTHashtable<NPObjectData> mObjectMap;
friend class PluginIdentifierChild;
friend class PluginIdentifierChildString;
friend class PluginIdentifierChildInt;
nsDataHashtable<nsCStringHashKey, PluginIdentifierChildString*> mStringIdentifiers;
nsDataHashtable<nsUint32HashKey, PluginIdentifierChildInt*> mIntIdentifiers;
public: // called by PluginInstanceChild
/**
* Dealloc an NPObject after last-release or when the associated instance

Просмотреть файл

@ -28,7 +28,6 @@
#include "nsIObserverService.h"
#include "nsNPAPIPlugin.h"
#include "nsPrintfCString.h"
#include "PluginIdentifierParent.h"
#include "prsystem.h"
#include "GeckoProfiler.h"
@ -779,37 +778,6 @@ PluginModuleParent::NotifyPluginCrashed()
mPlugin->PluginCrashed(mPluginDumpID, mBrowserDumpID);
}
PPluginIdentifierParent*
PluginModuleParent::AllocPPluginIdentifierParent(const nsCString& aString,
const int32_t& aInt,
const bool& aTemporary)
{
if (aTemporary) {
NS_ERROR("Plugins don't create temporary identifiers.");
return nullptr; // should abort the plugin
}
NPIdentifier npident = aString.IsVoid() ?
mozilla::plugins::parent::_getintidentifier(aInt) :
mozilla::plugins::parent::_getstringidentifier(aString.get());
if (!npident) {
NS_WARNING("Failed to get identifier!");
return nullptr;
}
PluginIdentifierParent* ident = new PluginIdentifierParent(npident, false);
mIdentifiers.Put(npident, ident);
return ident;
}
bool
PluginModuleParent::DeallocPPluginIdentifierParent(PPluginIdentifierParent* aActor)
{
delete aActor;
return true;
}
PPluginInstanceParent*
PluginModuleParent::AllocPPluginInstanceParent(const nsCString& aMimeType,
const uint16_t& aMode,
@ -1051,44 +1019,6 @@ PluginModuleParent::AnswerNPN_UserAgent(nsCString* userAgent)
return true;
}
PluginIdentifierParent*
PluginModuleParent::GetIdentifierForNPIdentifier(NPP npp, NPIdentifier aIdentifier)
{
PluginIdentifierParent* ident;
if (mIdentifiers.Get(aIdentifier, &ident)) {
if (ident->IsTemporary()) {
ident->AddTemporaryRef();
}
return ident;
}
nsCString string;
int32_t intval = -1;
bool temporary = false;
if (mozilla::plugins::parent::_identifierisstring(aIdentifier)) {
NPUTF8* chars =
mozilla::plugins::parent::_utf8fromidentifier(aIdentifier);
if (!chars) {
return nullptr;
}
string.Adopt(chars);
temporary = !NPStringIdentifierIsPermanent(npp, aIdentifier);
}
else {
intval = mozilla::plugins::parent::_intfromidentifier(aIdentifier);
string.SetIsVoid(true);
}
ident = new PluginIdentifierParent(aIdentifier, temporary);
if (!SendPPluginIdentifierConstructor(ident, string, intval, temporary))
return nullptr;
if (!temporary) {
mIdentifiers.Put(aIdentifier, ident);
}
return ident;
}
PluginInstanceParent*
PluginModuleParent::InstCast(NPP instance)
{

Просмотреть файл

@ -14,6 +14,7 @@
#include "mozilla/plugins/PluginProcessParent.h"
#include "mozilla/plugins/PPluginModuleParent.h"
#include "mozilla/plugins/PluginMessageUtils.h"
#include "mozilla/plugins/PluginTypes.h"
#include "npapi.h"
#include "npfunctions.h"
#include "nsAutoPtr.h"
@ -35,7 +36,6 @@ namespace plugins {
//-----------------------------------------------------------------------------
class BrowserStreamParent;
class PluginIdentifierParent;
class PluginInstanceParent;
#ifdef XP_WIN
@ -67,14 +67,6 @@ private:
protected:
virtual PPluginIdentifierParent*
AllocPPluginIdentifierParent(const nsCString& aString,
const int32_t& aInt,
const bool& aTemporary) MOZ_OVERRIDE;
virtual bool
DeallocPPluginIdentifierParent(PPluginIdentifierParent* aActor) MOZ_OVERRIDE;
PPluginInstanceParent*
AllocPPluginInstanceParent(const nsCString& aMimeType,
const uint16_t& aMode,
@ -116,15 +108,6 @@ public:
return !IsOnCxxStack();
}
/**
* Get an identifier actor for this NPIdentifier. If this is a temporary
* identifier, the temporary refcount is increased by one. This method
* is intended only for use by StackIdentifier and the scriptable
* Enumerate hook.
*/
PluginIdentifierParent*
GetIdentifierForNPIdentifier(NPP npp, NPIdentifier aIdentifier);
void ProcessRemoteNativeEventsInInterruptCall();
void TerminateChildProcess(MessageLoop* aMsgLoop);
@ -298,7 +281,6 @@ private:
bool mClearSiteDataSupported;
bool mGetSitesWithDataSupported;
const NPNetscapeFuncs* mNPNIface;
nsDataHashtable<nsPtrHashKey<void>, PluginIdentifierParent*> mIdentifiers;
nsNPAPIPlugin* mPlugin;
ScopedMethodFactory<PluginModuleParent> mTaskFactory;
nsString mPluginDumpID;

Просмотреть файл

@ -6,10 +6,125 @@
#include "PluginScriptableObjectChild.h"
#include "PluginScriptableObjectUtils.h"
#include "PluginIdentifierChild.h"
#include "mozilla/plugins/PluginTypes.h"
using namespace mozilla::plugins;
/**
* NPIdentifiers in the plugin process use a tagged representation. The low bit
* stores the tag. If it's zero, the identifier is a string, and the value is a
* pointer to a StoredIdentifier. If the tag bit is 1, then the rest of the
* NPIdentifier value is the integer itself. Like the JSAPI, we require that all
* integers stored in NPIdentifier be non-negative.
*
* String identifiers are stored in the sIdentifiers hashtable to ensure
* uniqueness. The lifetime of these identifiers is only as long as the incoming
* IPC call from the chrome process. If the plugin wants to retain an
* identifier, it needs to call NPN_GetStringIdentifier, which causes the
* mPermanent flag to be set on the identifier. When this flag is set, the
* identifier is saved until the plugin process exits.
*
* The StackIdentifier RAII class is used to manage ownership of
* identifiers. Any identifier obtained from this class should not be used
* outside its scope, except when the MakePermanent() method has been called on
* it.
*
* The lifetime of an NPIdentifier in the plugin process is totally divorced
* from the lifetime of an NPIdentifier in the chrome process (where an
* NPIdentifier is stored as a jsid). The JS GC in the chrome process is able to
* trace through the entire heap, unlike in the plugin process, so there is no
* reason to retain identifiers there.
*/
PluginScriptableObjectChild::IdentifierTable PluginScriptableObjectChild::sIdentifiers;
/* static */ PluginScriptableObjectChild::StoredIdentifier*
PluginScriptableObjectChild::HashIdentifier(const nsCString& aIdentifier)
{
StoredIdentifier* stored = sIdentifiers.Get(aIdentifier);
if (stored) {
return stored;
}
stored = new StoredIdentifier(aIdentifier);
sIdentifiers.Put(aIdentifier, stored);
return stored;
}
/* static */ void
PluginScriptableObjectChild::UnhashIdentifier(StoredIdentifier* aStored)
{
MOZ_ASSERT(sIdentifiers.Get(aStored->mIdentifier));
sIdentifiers.Remove(aStored->mIdentifier);
}
/* static */ void
PluginScriptableObjectChild::ClearIdentifiers()
{
sIdentifiers.Clear();
}
PluginScriptableObjectChild::StackIdentifier::StackIdentifier(const PluginIdentifier& aIdentifier)
: mIdentifier(aIdentifier),
mStored(nullptr)
{
if (aIdentifier.type() == PluginIdentifier::TnsCString) {
mStored = PluginScriptableObjectChild::HashIdentifier(mIdentifier.get_nsCString());
}
}
PluginScriptableObjectChild::StackIdentifier::StackIdentifier(NPIdentifier aIdentifier)
: mStored(nullptr)
{
uintptr_t bits = reinterpret_cast<uintptr_t>(aIdentifier);
if (bits & 1) {
int32_t num = int32_t(bits >> 1);
mIdentifier = PluginIdentifier(num);
} else {
mStored = static_cast<StoredIdentifier*>(aIdentifier);
mIdentifier = mStored->mIdentifier;
}
}
PluginScriptableObjectChild::StackIdentifier::~StackIdentifier()
{
if (!mStored) {
return;
}
// Each StackIdentifier owns one reference to its StoredIdentifier. In
// addition, the sIdentifiers table owns a reference. If mPermanent is false
// and sIdentifiers has the last reference, then we want to remove the
// StoredIdentifier from the table (and destroy it).
StoredIdentifier *stored = mStored;
mStored = nullptr;
if (stored->mRefCnt == 1 && !stored->mPermanent) {
PluginScriptableObjectChild::UnhashIdentifier(stored);
}
}
NPIdentifier
PluginScriptableObjectChild::StackIdentifier::ToNPIdentifier() const
{
if (mStored) {
MOZ_ASSERT(mIdentifier.type() == PluginIdentifier::TnsCString);
MOZ_ASSERT((reinterpret_cast<uintptr_t>(mStored.get()) & 1) == 0);
return mStored;
}
int32_t num = mIdentifier.get_int32_t();
// The JS engine imposes this condition on int32s in jsids, so we assume it.
MOZ_ASSERT(num >= 0);
return reinterpret_cast<NPIdentifier>((num << 1) | 1);
}
static PluginIdentifier
FromNPIdentifier(NPIdentifier aIdentifier)
{
PluginScriptableObjectChild::StackIdentifier stack(aIdentifier);
return stack.GetIdentifier();
}
// static
NPObject*
PluginScriptableObjectChild::ScriptableAllocate(NPP aInstance,
@ -85,7 +200,7 @@ PluginScriptableObjectChild::ScriptableHasMethod(NPObject* aObject,
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
bool result;
actor->CallHasMethod(static_cast<PPluginIdentifierChild*>(aName), &result);
actor->CallHasMethod(FromNPIdentifier(aName), &result);
return result;
}
@ -122,7 +237,7 @@ PluginScriptableObjectChild::ScriptableInvoke(NPObject* aObject,
Variant remoteResult;
bool success;
actor->CallInvoke(static_cast<PPluginIdentifierChild*>(aName), args,
actor->CallInvoke(FromNPIdentifier(aName), args,
&remoteResult, &success);
if (!success) {
@ -196,7 +311,7 @@ PluginScriptableObjectChild::ScriptableHasProperty(NPObject* aObject,
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
bool result;
actor->CallHasProperty(static_cast<PPluginIdentifierChild*>(aName), &result);
actor->CallHasProperty(FromNPIdentifier(aName), &result);
return result;
}
@ -225,7 +340,7 @@ PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject,
Variant result;
bool success;
actor->CallGetParentProperty(static_cast<PPluginIdentifierChild*>(aName),
actor->CallGetParentProperty(FromNPIdentifier(aName),
&result, &success);
if (!success) {
@ -265,7 +380,7 @@ PluginScriptableObjectChild::ScriptableSetProperty(NPObject* aObject,
}
bool success;
actor->CallSetProperty(static_cast<PPluginIdentifierChild*>(aName), value,
actor->CallSetProperty(FromNPIdentifier(aName), value,
&success);
return success;
@ -293,7 +408,7 @@ PluginScriptableObjectChild::ScriptableRemoveProperty(NPObject* aObject,
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
bool success;
actor->CallRemoveProperty(static_cast<PPluginIdentifierChild*>(aName),
actor->CallRemoveProperty(FromNPIdentifier(aName),
&success);
return success;
@ -321,7 +436,7 @@ PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject,
NS_ASSERTION(actor, "This shouldn't ever be null!");
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
AutoInfallibleTArray<PPluginIdentifierChild*, 10> identifiers;
AutoInfallibleTArray<PluginIdentifier, 10> identifiers;
bool success;
actor->CallEnumerate(&identifiers, &success);
@ -343,8 +458,10 @@ PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject,
}
for (uint32_t index = 0; index < *aCount; index++) {
(*aIdentifiers)[index] =
static_cast<PPluginIdentifierChild*>(identifiers[index]);
StackIdentifier id(identifiers[index]);
// Make the id permanent in case the plugin retains it.
id.MakePermanent();
(*aIdentifiers)[index] = id.ToNPIdentifier();
}
return true;
}
@ -610,7 +727,7 @@ PluginScriptableObjectChild::AnswerInvalidate()
}
bool
PluginScriptableObjectChild::AnswerHasMethod(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerHasMethod(const PluginIdentifier& aId,
bool* aHasMethod)
{
AssertPluginThread();
@ -629,13 +746,13 @@ PluginScriptableObjectChild::AnswerHasMethod(PPluginIdentifierChild* aId,
return true;
}
PluginIdentifierChild::StackIdentifier id(aId);
*aHasMethod = mObject->_class->hasMethod(mObject, id->ToNPIdentifier());
StackIdentifier id(aId);
*aHasMethod = mObject->_class->hasMethod(mObject, id.ToNPIdentifier());
return true;
}
bool
PluginScriptableObjectChild::AnswerInvoke(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerInvoke(const PluginIdentifier& aId,
const InfallibleTArray<Variant>& aArgs,
Variant* aResult,
bool* aSuccess)
@ -673,8 +790,8 @@ PluginScriptableObjectChild::AnswerInvoke(PPluginIdentifierChild* aId,
NPVariant result;
VOID_TO_NPVARIANT(result);
PluginIdentifierChild::StackIdentifier id(aId);
bool success = mObject->_class->invoke(mObject, id->ToNPIdentifier(),
StackIdentifier id(aId);
bool success = mObject->_class->invoke(mObject, id.ToNPIdentifier(),
convertedArgs.Elements(), argCount,
&result);
@ -775,7 +892,7 @@ PluginScriptableObjectChild::AnswerInvokeDefault(const InfallibleTArray<Variant>
}
bool
PluginScriptableObjectChild::AnswerHasProperty(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerHasProperty(const PluginIdentifier& aId,
bool* aHasProperty)
{
AssertPluginThread();
@ -794,13 +911,13 @@ PluginScriptableObjectChild::AnswerHasProperty(PPluginIdentifierChild* aId,
return true;
}
PluginIdentifierChild::StackIdentifier id(aId);
*aHasProperty = mObject->_class->hasProperty(mObject, id->ToNPIdentifier());
StackIdentifier id(aId);
*aHasProperty = mObject->_class->hasProperty(mObject, id.ToNPIdentifier());
return true;
}
bool
PluginScriptableObjectChild::AnswerGetChildProperty(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerGetChildProperty(const PluginIdentifier& aId,
bool* aHasProperty,
bool* aHasMethod,
Variant* aResult,
@ -824,8 +941,8 @@ PluginScriptableObjectChild::AnswerGetChildProperty(PPluginIdentifierChild* aId,
return true;
}
PluginIdentifierChild::StackIdentifier stackID(aId);
NPIdentifier id = stackID->ToNPIdentifier();
StackIdentifier stackID(aId);
NPIdentifier id = stackID.ToNPIdentifier();
*aHasProperty = mObject->_class->hasProperty(mObject, id);
*aHasMethod = mObject->_class->hasMethod(mObject, id);
@ -850,7 +967,7 @@ PluginScriptableObjectChild::AnswerGetChildProperty(PPluginIdentifierChild* aId,
}
bool
PluginScriptableObjectChild::AnswerSetProperty(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerSetProperty(const PluginIdentifier& aId,
const Variant& aValue,
bool* aSuccess)
{
@ -871,8 +988,8 @@ PluginScriptableObjectChild::AnswerSetProperty(PPluginIdentifierChild* aId,
return true;
}
PluginIdentifierChild::StackIdentifier stackID(aId);
NPIdentifier id = stackID->ToNPIdentifier();
StackIdentifier stackID(aId);
NPIdentifier id = stackID.ToNPIdentifier();
if (!mObject->_class->hasProperty(mObject, id)) {
*aSuccess = false;
@ -889,7 +1006,7 @@ PluginScriptableObjectChild::AnswerSetProperty(PPluginIdentifierChild* aId,
}
bool
PluginScriptableObjectChild::AnswerRemoveProperty(PPluginIdentifierChild* aId,
PluginScriptableObjectChild::AnswerRemoveProperty(const PluginIdentifier& aId,
bool* aSuccess)
{
AssertPluginThread();
@ -909,8 +1026,8 @@ PluginScriptableObjectChild::AnswerRemoveProperty(PPluginIdentifierChild* aId,
return true;
}
PluginIdentifierChild::StackIdentifier stackID(aId);
NPIdentifier id = stackID->ToNPIdentifier();
StackIdentifier stackID(aId);
NPIdentifier id = stackID.ToNPIdentifier();
*aSuccess = mObject->_class->hasProperty(mObject, id) ?
mObject->_class->removeProperty(mObject, id) :
true;
@ -919,7 +1036,7 @@ PluginScriptableObjectChild::AnswerRemoveProperty(PPluginIdentifierChild* aId,
}
bool
PluginScriptableObjectChild::AnswerEnumerate(InfallibleTArray<PPluginIdentifierChild*>* aProperties,
PluginScriptableObjectChild::AnswerEnumerate(InfallibleTArray<PluginIdentifier>* aProperties,
bool* aSuccess)
{
AssertPluginThread();
@ -948,8 +1065,7 @@ PluginScriptableObjectChild::AnswerEnumerate(InfallibleTArray<PPluginIdentifierC
aProperties->SetCapacity(idCount);
for (uint32_t index = 0; index < idCount; index++) {
PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(ids[index]);
aProperties->AppendElement(id);
aProperties->AppendElement(FromNPIdentifier(ids[index]));
}
PluginModuleChild::sBrowserFuncs.memfree(ids);

Просмотреть файл

@ -9,15 +9,16 @@
#include "mozilla/plugins/PPluginScriptableObjectChild.h"
#include "mozilla/plugins/PluginMessageUtils.h"
#include "mozilla/plugins/PluginTypes.h"
#include "npruntime.h"
#include "nsDataHashtable.h"
namespace mozilla {
namespace plugins {
class PluginInstanceChild;
class PluginScriptableObjectChild;
class PPluginIdentifierChild;
struct ChildNPObject : NPObject
{
@ -57,11 +58,11 @@ public:
AnswerInvalidate() MOZ_OVERRIDE;
virtual bool
AnswerHasMethod(PPluginIdentifierChild* aId,
AnswerHasMethod(const PluginIdentifier& aId,
bool* aHasMethod) MOZ_OVERRIDE;
virtual bool
AnswerInvoke(PPluginIdentifierChild* aId,
AnswerInvoke(const PluginIdentifier& aId,
const InfallibleTArray<Variant>& aArgs,
Variant* aResult,
bool* aSuccess) MOZ_OVERRIDE;
@ -72,27 +73,27 @@ public:
bool* aSuccess) MOZ_OVERRIDE;
virtual bool
AnswerHasProperty(PPluginIdentifierChild* aId,
AnswerHasProperty(const PluginIdentifier& aId,
bool* aHasProperty) MOZ_OVERRIDE;
virtual bool
AnswerGetChildProperty(PPluginIdentifierChild* aId,
AnswerGetChildProperty(const PluginIdentifier& aId,
bool* aHasProperty,
bool* aHasMethod,
Variant* aResult,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool
AnswerSetProperty(PPluginIdentifierChild* aId,
AnswerSetProperty(const PluginIdentifier& aId,
const Variant& aValue,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool
AnswerRemoveProperty(PPluginIdentifierChild* aId,
AnswerRemoveProperty(const PluginIdentifier& aId,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool
AnswerEnumerate(InfallibleTArray<PPluginIdentifierChild*>* aProperties,
AnswerEnumerate(InfallibleTArray<PluginIdentifier>* aProperties,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool
@ -156,6 +157,66 @@ public:
return mType;
}
private:
struct StoredIdentifier
{
nsCString mIdentifier;
nsAutoRefCnt mRefCnt;
bool mPermanent;
nsrefcnt AddRef() {
++mRefCnt;
return mRefCnt;
}
nsrefcnt Release() {
--mRefCnt;
if (mRefCnt == 0) {
delete this;
return 0;
}
return mRefCnt;
}
explicit StoredIdentifier(const nsCString& aIdentifier)
: mIdentifier(aIdentifier), mRefCnt(), mPermanent(false)
{ MOZ_COUNT_CTOR(StoredIdentifier); }
~StoredIdentifier() { MOZ_COUNT_DTOR(StoredIdentifier); }
};
public:
class MOZ_STACK_CLASS StackIdentifier
{
public:
StackIdentifier(const PluginIdentifier& aIdentifier);
StackIdentifier(NPIdentifier aIdentifier);
~StackIdentifier();
void MakePermanent()
{
if (mStored) {
mStored->mPermanent = true;
}
}
NPIdentifier ToNPIdentifier() const;
bool IsString() const { return mIdentifier.type() == PluginIdentifier::TnsCString; }
const nsCString& GetString() const { return mIdentifier.get_nsCString(); }
int32_t GetInt() const { return mIdentifier.get_int32_t(); }
PluginIdentifier GetIdentifier() const { return mIdentifier; }
private:
DISALLOW_COPY_AND_ASSIGN(StackIdentifier);
PluginIdentifier mIdentifier;
nsRefPtr<StoredIdentifier> mStored;
};
static void ClearIdentifiers();
private:
static NPObject*
ScriptableAllocate(NPP aInstance,
@ -230,6 +291,12 @@ private:
ScriptableObjectType mType;
static const NPClass sNPClass;
static StoredIdentifier* HashIdentifier(const nsCString& aIdentifier);
static void UnhashIdentifier(StoredIdentifier* aIdentifier);
typedef nsDataHashtable<nsCStringHashKey, nsRefPtr<StoredIdentifier>> IdentifierTable;
static IdentifierTable sIdentifiers;
};
} /* namespace plugins */

Просмотреть файл

@ -6,15 +6,103 @@
#include "PluginScriptableObjectParent.h"
#include "jsapi.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/plugins/PluginIdentifierParent.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/plugins/PluginTypes.h"
#include "mozilla/unused.h"
#include "nsNPAPIPlugin.h"
#include "PluginScriptableObjectUtils.h"
using namespace mozilla;
using namespace mozilla::plugins;
using namespace mozilla::plugins::parent;
/**
* NPIdentifiers in the chrome process are stored as jsids. The difficulty is in
* ensuring that string identifiers are rooted without interning them all. We
* assume that all NPIdentifiers passed into nsJSNPRuntime will not be used
* outside the scope of the NPAPI call (i.e., they won't be stored in the
* heap). Rooting is done using the StackIdentifier class, which roots the
* identifier via RootedId.
*
* This system does not allow jsids to be moved, as would be needed for
* generational or compacting GC. When Firefox implements a moving GC for
* strings, we will need to ensure that no movement happens while NPAPI code is
* on the stack: although StackIdentifier roots all identifiers used, the GC has
* no way to no that a jsid cast to an NPIdentifier needs to be fixed up if it
* is moved.
*/
class MOZ_STACK_CLASS StackIdentifier
{
public:
StackIdentifier(const PluginIdentifier& aIdentifier, bool aIntern = false);
bool Failed() const { return mFailed; }
NPIdentifier ToNPIdentifier() const { return mIdentifier; }
private:
bool mFailed;
NPIdentifier mIdentifier;
AutoSafeJSContext mCx;
JS::RootedId mId;
};
StackIdentifier::StackIdentifier(const PluginIdentifier& aIdentifier, bool aIntern)
: mFailed(false),
mId(mCx)
{
if (aIdentifier.type() == PluginIdentifier::TnsCString) {
// We don't call _getstringidentifier because we may not want to intern the string.
NS_ConvertUTF8toUTF16 utf16name(aIdentifier.get_nsCString());
JS::RootedString str(mCx, JS_NewUCStringCopyN(mCx, utf16name.get(), utf16name.Length()));
if (!str) {
NS_ERROR("Id can't be allocated");
mFailed = true;
return;
}
if (aIntern) {
str = JS_InternJSString(mCx, str);
if (!str) {
NS_ERROR("Id can't be allocated");
mFailed = true;
return;
}
}
if (!JS_StringToId(mCx, str, &mId)) {
NS_ERROR("Id can't be allocated");
mFailed = true;
return;
}
mIdentifier = JSIdToNPIdentifier(mId);
return;
}
mIdentifier = mozilla::plugins::parent::_getintidentifier(aIdentifier.get_int32_t());
}
static bool
FromNPIdentifier(NPIdentifier aIdentifier, PluginIdentifier* aResult)
{
if (mozilla::plugins::parent::_identifierisstring(aIdentifier)) {
nsCString string;
NPUTF8* chars =
mozilla::plugins::parent::_utf8fromidentifier(aIdentifier);
if (!chars) {
return false;
}
string.Adopt(chars);
*aResult = PluginIdentifier(string);
return true;
}
else {
int32_t intval = mozilla::plugins::parent::_intfromidentifier(aIdentifier);
*aResult = PluginIdentifier(intval);
return true;
}
}
namespace {
inline void
@ -105,8 +193,8 @@ PluginScriptableObjectParent::ScriptableHasMethod(NPObject* aObject,
return false;
}
PluginIdentifierParent::StackIdentifier identifier(aObject, aName);
if (!identifier) {
PluginIdentifier identifier;
if (!FromNPIdentifier(aName, &identifier)) {
return false;
}
@ -145,8 +233,8 @@ PluginScriptableObjectParent::ScriptableInvoke(NPObject* aObject,
return false;
}
PluginIdentifierParent::StackIdentifier identifier(aObject, aName);
if (!identifier) {
PluginIdentifier identifier;
if (!FromNPIdentifier(aName, &identifier)) {
return false;
}
@ -247,8 +335,8 @@ PluginScriptableObjectParent::ScriptableHasProperty(NPObject* aObject,
return false;
}
PluginIdentifierParent::StackIdentifier identifier(aObject, aName);
if (!identifier) {
PluginIdentifier identifier;
if (!FromNPIdentifier(aName, &identifier)) {
return false;
}
@ -296,8 +384,8 @@ PluginScriptableObjectParent::ScriptableSetProperty(NPObject* aObject,
return false;
}
PluginIdentifierParent::StackIdentifier identifier(aObject, aName);
if (!identifier) {
PluginIdentifier identifier;
if (!FromNPIdentifier(aName, &identifier)) {
return false;
}
@ -339,8 +427,8 @@ PluginScriptableObjectParent::ScriptableRemoveProperty(NPObject* aObject,
return false;
}
PluginIdentifierParent::StackIdentifier identifier(aObject, aName);
if (!identifier) {
PluginIdentifier identifier;
if (!FromNPIdentifier(aName, &identifier)) {
return false;
}
@ -385,7 +473,7 @@ PluginScriptableObjectParent::ScriptableEnumerate(NPObject* aObject,
return false;
}
AutoInfallibleTArray<PPluginIdentifierParent*, 10> identifiers;
AutoInfallibleTArray<PluginIdentifier, 10> identifiers;
bool success;
if (!actor->CallEnumerate(&identifiers, &success)) {
NS_WARNING("Failed to send message!");
@ -409,9 +497,13 @@ PluginScriptableObjectParent::ScriptableEnumerate(NPObject* aObject,
}
for (uint32_t index = 0; index < *aCount; index++) {
PluginIdentifierParent* id =
static_cast<PluginIdentifierParent*>(identifiers[index]);
(*aIdentifiers)[index] = id->ToNPIdentifier();
// We intern the ID to avoid a GC hazard here. This could probably be fixed
// if the interface with nsJSNPRuntime were smarter.
StackIdentifier stackID(identifiers[index], true /* aIntern */);
if (stackID.Failed()) {
return false;
}
(*aIdentifiers)[index] = stackID.ToNPIdentifier();
}
return true;
}
@ -649,7 +741,7 @@ PluginScriptableObjectParent::ActorDestroy(ActorDestroyReason aWhy)
}
bool
PluginScriptableObjectParent::AnswerHasMethod(PPluginIdentifierParent* aId,
PluginScriptableObjectParent::AnswerHasMethod(const PluginIdentifier& aId,
bool* aHasMethod)
{
if (!mObject) {
@ -675,13 +767,17 @@ PluginScriptableObjectParent::AnswerHasMethod(PPluginIdentifierParent* aId,
return true;
}
PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
*aHasMethod = npn->hasmethod(instance->GetNPP(), mObject, id->ToNPIdentifier());
StackIdentifier stackID(aId);
if (stackID.Failed()) {
*aHasMethod = false;
return true;
}
*aHasMethod = npn->hasmethod(instance->GetNPP(), mObject, stackID.ToNPIdentifier());
return true;
}
bool
PluginScriptableObjectParent::AnswerInvoke(PPluginIdentifierParent* aId,
PluginScriptableObjectParent::AnswerInvoke(const PluginIdentifier& aId,
const InfallibleTArray<Variant>& aArgs,
Variant* aResult,
bool* aSuccess)
@ -712,6 +808,13 @@ PluginScriptableObjectParent::AnswerInvoke(PPluginIdentifierParent* aId,
return true;
}
StackIdentifier stackID(aId);
if (stackID.Failed()) {
*aResult = void_t();
*aSuccess = false;
return true;
}
AutoFallibleTArray<NPVariant, 10> convertedArgs;
uint32_t argCount = aArgs.Length();
@ -733,9 +836,8 @@ PluginScriptableObjectParent::AnswerInvoke(PPluginIdentifierParent* aId,
}
}
PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
NPVariant result;
bool success = npn->invoke(instance->GetNPP(), mObject, id->ToNPIdentifier(),
bool success = npn->invoke(instance->GetNPP(), mObject, stackID.ToNPIdentifier(),
convertedArgs.Elements(), argCount, &result);
for (uint32_t index = 0; index < argCount; index++) {
@ -848,7 +950,7 @@ PluginScriptableObjectParent::AnswerInvokeDefault(const InfallibleTArray<Variant
}
bool
PluginScriptableObjectParent::AnswerHasProperty(PPluginIdentifierParent* aId,
PluginScriptableObjectParent::AnswerHasProperty(const PluginIdentifier& aId,
bool* aHasProperty)
{
if (!mObject) {
@ -874,15 +976,20 @@ PluginScriptableObjectParent::AnswerHasProperty(PPluginIdentifierParent* aId,
return true;
}
PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
StackIdentifier stackID(aId);
if (stackID.Failed()) {
*aHasProperty = false;
return true;
}
*aHasProperty = npn->hasproperty(instance->GetNPP(), mObject,
id->ToNPIdentifier());
stackID.ToNPIdentifier());
return true;
}
bool
PluginScriptableObjectParent::AnswerGetParentProperty(
PPluginIdentifierParent* aId,
const PluginIdentifier& aId,
Variant* aResult,
bool* aSuccess)
{
@ -912,9 +1019,15 @@ PluginScriptableObjectParent::AnswerGetParentProperty(
return true;
}
PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
StackIdentifier stackID(aId);
if (stackID.Failed()) {
*aResult = void_t();
*aSuccess = false;
return true;
}
NPVariant result;
if (!npn->getproperty(instance->GetNPP(), mObject, id->ToNPIdentifier(),
if (!npn->getproperty(instance->GetNPP(), mObject, stackID.ToNPIdentifier(),
&result)) {
*aResult = void_t();
*aSuccess = false;
@ -934,7 +1047,7 @@ PluginScriptableObjectParent::AnswerGetParentProperty(
}
bool
PluginScriptableObjectParent::AnswerSetProperty(PPluginIdentifierParent* aId,
PluginScriptableObjectParent::AnswerSetProperty(const PluginIdentifier& aId,
const Variant& aValue,
bool* aSuccess)
{
@ -967,16 +1080,21 @@ PluginScriptableObjectParent::AnswerSetProperty(PPluginIdentifierParent* aId,
return true;
}
PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
StackIdentifier stackID(aId);
if (stackID.Failed()) {
*aSuccess = false;
return true;
}
if ((*aSuccess = npn->setproperty(instance->GetNPP(), mObject,
id->ToNPIdentifier(), &converted))) {
stackID.ToNPIdentifier(), &converted))) {
ReleaseVariant(converted, instance);
}
return true;
}
bool
PluginScriptableObjectParent::AnswerRemoveProperty(PPluginIdentifierParent* aId,
PluginScriptableObjectParent::AnswerRemoveProperty(const PluginIdentifier& aId,
bool* aSuccess)
{
if (!mObject) {
@ -1002,14 +1120,19 @@ PluginScriptableObjectParent::AnswerRemoveProperty(PPluginIdentifierParent* aId,
return true;
}
PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
StackIdentifier stackID(aId);
if (stackID.Failed()) {
*aSuccess = false;
return true;
}
*aSuccess = npn->removeproperty(instance->GetNPP(), mObject,
id->ToNPIdentifier());
stackID.ToNPIdentifier());
return true;
}
bool
PluginScriptableObjectParent::AnswerEnumerate(InfallibleTArray<PPluginIdentifierParent*>* aProperties,
PluginScriptableObjectParent::AnswerEnumerate(InfallibleTArray<PluginIdentifier>* aProperties,
bool* aSuccess)
{
if (!mObject) {
@ -1044,21 +1167,12 @@ PluginScriptableObjectParent::AnswerEnumerate(InfallibleTArray<PPluginIdentifier
aProperties->SetCapacity(idCount);
mozilla::AutoSafeJSContext cx;
for (uint32_t index = 0; index < idCount; index++) {
// Because of GC hazards, all identifiers returned from enumerate
// must be made permanent.
if (_identifierisstring(ids[index])) {
JS::Rooted<JSString*> str(cx, NPIdentifierToString(ids[index]));
if (!JS_StringHasBeenInterned(cx, str)) {
DebugOnly<JSString*> str2 = JS_InternJSString(cx, str);
NS_ASSERTION(str2 == str, "Interning a JS string which is currently an ID should return itself.");
}
PluginIdentifier id;
if (!FromNPIdentifier(ids[index], &id)) {
return false;
}
PluginIdentifierParent* id =
instance->Module()->GetIdentifierForNPIdentifier(instance->GetNPP(), ids[index]);
aProperties->AppendElement(id);
NS_ASSERTION(!id->IsTemporary(), "Should only have permanent identifiers!");
}
npn->memfree(ids);
@ -1229,8 +1343,8 @@ PluginScriptableObjectParent::GetPropertyHelper(NPIdentifier aName,
return false;
}
PluginIdentifierParent::StackIdentifier identifier(GetInstance(), aName);
if (!identifier) {
PluginIdentifier identifier;
if (!FromNPIdentifier(aName, &identifier)) {
return false;
}

Просмотреть файл

@ -18,7 +18,6 @@ namespace plugins {
class PluginInstanceParent;
class PluginScriptableObjectParent;
class PPluginIdentifierParent;
struct ParentNPObject : NPObject
{
@ -49,11 +48,11 @@ public:
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool
AnswerHasMethod(PPluginIdentifierParent* aId,
AnswerHasMethod(const PluginIdentifier& aId,
bool* aHasMethod) MOZ_OVERRIDE;
virtual bool
AnswerInvoke(PPluginIdentifierParent* aId,
AnswerInvoke(const PluginIdentifier& aId,
const InfallibleTArray<Variant>& aArgs,
Variant* aResult,
bool* aSuccess) MOZ_OVERRIDE;
@ -64,25 +63,25 @@ public:
bool* aSuccess) MOZ_OVERRIDE;
virtual bool
AnswerHasProperty(PPluginIdentifierParent* aId,
AnswerHasProperty(const PluginIdentifier& aId,
bool* aHasProperty) MOZ_OVERRIDE;
virtual bool
AnswerGetParentProperty(PPluginIdentifierParent* aId,
AnswerGetParentProperty(const PluginIdentifier& aId,
Variant* aResult,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool
AnswerSetProperty(PPluginIdentifierParent* aId,
AnswerSetProperty(const PluginIdentifier& aId,
const Variant& aValue,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool
AnswerRemoveProperty(PPluginIdentifierParent* aId,
AnswerRemoveProperty(const PluginIdentifier& aId,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool
AnswerEnumerate(InfallibleTArray<PPluginIdentifierParent*>* aProperties,
AnswerEnumerate(InfallibleTArray<PluginIdentifier>* aProperties,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool

Просмотреть файл

@ -0,0 +1,16 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* 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/. */
namespace mozilla {
namespace plugins {
union PluginIdentifier
{
nsCString;
int32_t;
};
} // namespace plugins
} // namespace mozilla

Просмотреть файл

@ -21,8 +21,6 @@ EXPORTS.mozilla.plugins += [
'NPEventOSX.h',
'NPEventUnix.h',
'NPEventWindows.h',
'PluginIdentifierChild.h',
'PluginIdentifierParent.h',
'PluginInstanceChild.h',
'PluginInstanceParent.h',
'PluginMessageUtils.h',
@ -79,8 +77,6 @@ UNIFIED_SOURCES += [
'ChildAsyncCall.cpp',
'ChildTimer.cpp',
'PluginBackgroundDestroyer.cpp',
'PluginIdentifierChild.cpp',
'PluginIdentifierParent.cpp',
'PluginInstanceParent.cpp',
'PluginMessageUtils.cpp',
'PluginModuleParent.cpp',
@ -105,8 +101,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
IPDL_SOURCES += [
'PBrowserStream.ipdl',
'PluginTypes.ipdlh',
'PPluginBackgroundDestroyer.ipdl',
'PPluginIdentifier.ipdl',
'PPluginInstance.ipdl',
'PPluginModule.ipdl',
'PPluginScriptableObject.ipdl',