diff options
Diffstat (limited to 'gpu/np_utils')
28 files changed, 3338 insertions, 0 deletions
diff --git a/gpu/np_utils/default_np_object.h b/gpu/np_utils/default_np_object.h new file mode 100644 index 0000000..b3b5fc0 --- /dev/null +++ b/gpu/np_utils/default_np_object.h @@ -0,0 +1,84 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_DEFAULT_NP_OBJECT_H_ +#define GPU_NP_UTILS_DEFAULT_NP_OBJECT_H_ + +#include "base/basictypes.h" +#include "gpu/np_utils/np_headers.h" + +namespace np_utils { + +class BaseNPDispatcher; + +// This class implements each of the functions in the NPClass interface. They +// all return error by default. Note that these are not virtual functions and +// this is not an interface. This class can be used as a mixin so that an +// NPObject class does not need to implement every NPClass function but rather +// inherits a default from DefaultNPObject. +template <typename RootClass> +class DefaultNPObject : public RootClass { + public: + void Invalidate() {} + + bool HasMethod(NPIdentifier name) { + return false; + } + + bool Invoke(NPIdentifier name, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + return false; + } + + bool InvokeDefault(const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + return false; + } + + bool HasProperty(NPIdentifier name) { + return false; + } + + bool GetProperty(NPIdentifier name, NPVariant* result) { + return false; + } + + bool SetProperty(NPIdentifier name, const NPVariant* value) { + return false; + } + + bool RemoveProperty(NPIdentifier name) { + return false; + } + + bool Enumerate(NPIdentifier** names, + uint32_t* count) { + *names = NULL; + *count = 0; + return true; + } + + bool Construct(const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + return false; + } + + static BaseNPDispatcher* GetDispatcherChain() { + return NULL; + } + + protected: + DefaultNPObject() {} + virtual ~DefaultNPObject() {} + + private: + DISALLOW_COPY_AND_ASSIGN(DefaultNPObject); +}; +} // namespace np_utils + +#endif // GPU_NP_UTILS_DEFAULT_NP_OBJECT_H_ diff --git a/gpu/np_utils/dispatched_np_object_unittest.cc b/gpu/np_utils/dispatched_np_object_unittest.cc new file mode 100644 index 0000000..19d5a2b --- /dev/null +++ b/gpu/np_utils/dispatched_np_object_unittest.cc @@ -0,0 +1,403 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "gpu/np_utils/default_np_object.h" +#include "gpu/np_utils/np_browser_stub.h" +#include "gpu/np_utils/np_dispatcher.h" +#include "gpu/np_utils/np_object_mock.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Return; +using testing::StrictMock; + +namespace np_utils { + +// This mock class has a dispatcher chain with an entry for each mocked +// function. The tests that follow that invoking an NPAPI method calls the +// corresponding mocked member function. +class MockDispatchedNPObject : public DefaultNPObject<NPObject> { + public: + explicit MockDispatchedNPObject(NPP npp) { + } + + MOCK_METHOD0(VoidReturnNoParams, void()); + MOCK_METHOD1(VoidReturnBoolParam, void(bool)); + MOCK_METHOD1(VoidReturnIntParam, void(int)); + MOCK_METHOD1(VoidReturnFloatParam, void(float)); + MOCK_METHOD1(VoidReturnDoubleParam, void(double)); + MOCK_METHOD1(VoidReturnStringParam, void(std::string)); + MOCK_METHOD1(VoidReturnObjectParam, void(NPObjectPointer<NPObject>)); + MOCK_METHOD2(VoidReturnTwoParams, void(bool, int)); + MOCK_METHOD0(Overloaded, void()); + MOCK_METHOD1(Overloaded, void(bool)); + MOCK_METHOD1(Overloaded, void(std::string)); + MOCK_METHOD0(BoolReturn, bool()); + MOCK_METHOD0(IntReturn, int()); + MOCK_METHOD0(FloatReturn, float()); + MOCK_METHOD0(DoubleReturn, double()); + MOCK_METHOD0(StringReturn, std::string()); + MOCK_METHOD0(ObjectReturn, NPObjectPointer<NPObject>()); + + NP_UTILS_BEGIN_DISPATCHER_CHAIN(MockDispatchedNPObject, DefaultNPObject<NPObject>) + NP_UTILS_DISPATCHER(VoidReturnNoParams, void()) + NP_UTILS_DISPATCHER(VoidReturnBoolParam, void(bool)) + NP_UTILS_DISPATCHER(VoidReturnIntParam, void(int)) + NP_UTILS_DISPATCHER(VoidReturnFloatParam, void(float)) + NP_UTILS_DISPATCHER(VoidReturnDoubleParam, void(double)) + NP_UTILS_DISPATCHER(VoidReturnStringParam, void(std::string)) + NP_UTILS_DISPATCHER(VoidReturnObjectParam, void(NPObjectPointer<NPObject>)) + NP_UTILS_DISPATCHER(VoidReturnTwoParams, void(bool, int)) + NP_UTILS_DISPATCHER(Overloaded, void()) + NP_UTILS_DISPATCHER(Overloaded, void(bool)) + NP_UTILS_DISPATCHER(Overloaded, void(std::string)) + NP_UTILS_DISPATCHER(BoolReturn, bool()) + NP_UTILS_DISPATCHER(IntReturn, int()) + NP_UTILS_DISPATCHER(FloatReturn, float()) + NP_UTILS_DISPATCHER(DoubleReturn, double()) + NP_UTILS_DISPATCHER(StringReturn, std::string()) + NP_UTILS_DISPATCHER(ObjectReturn, NPObjectPointer<NPObject>()); + NP_UTILS_END_DISPATCHER_CHAIN +}; + +class DispatchedNPObjectTest : public testing::Test { + protected: + virtual void SetUp() { + object_ = NPCreateObject<StrictMock<MockDispatchedNPObject> >(NULL); + passed_object_ = NPCreateObject<MockNPObject>(NULL); + + for (int i = 0; i != arraysize(args_); ++i) { + NULL_TO_NPVARIANT(args_[i]); + } + NULL_TO_NPVARIANT(result_); + } + + StubNPBrowser stub_browser_; + NPVariant args_[3]; + NPVariant result_; + NPObjectPointer<MockDispatchedNPObject> object_; + NPObjectPointer<NPObject> passed_object_; +}; + +TEST_F(DispatchedNPObjectTest, CannotInvokeMissingFunction) { + EXPECT_FALSE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("missing"), + NULL, + 0, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnNoParams) { + EXPECT_CALL(*object_, VoidReturnNoParams()); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnNoParams"), + NULL, + 0, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, + CannotInvokeVoidReturnNoParamsWithTooManyParams) { + EXPECT_FALSE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnNoParams"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnIntParam) { + EXPECT_CALL(*object_, VoidReturnIntParam(7)); + + INT32_TO_NPVARIANT(7, args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnIntParam"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnBoolParam) { + EXPECT_CALL(*object_, VoidReturnBoolParam(true)); + + BOOLEAN_TO_NPVARIANT(true, args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnBoolParam"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnFloatParamWithDoubleParam) { + EXPECT_CALL(*object_, VoidReturnFloatParam(7.0f)); + + DOUBLE_TO_NPVARIANT(7.0, args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnFloatParam"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnFloatParamWithIntParam) { + EXPECT_CALL(*object_, VoidReturnFloatParam(7.0f)); + + INT32_TO_NPVARIANT(7, args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnFloatParam"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnDoubleParamWithDoubleParam) { + EXPECT_CALL(*object_, VoidReturnDoubleParam(7.0)); + + DOUBLE_TO_NPVARIANT(7.0, args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnDoubleParam"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnDoubleParamWithIntParam) { + EXPECT_CALL(*object_, VoidReturnDoubleParam(7.0f)); + + INT32_TO_NPVARIANT(7, args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnDoubleParam"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnStringParam) { + EXPECT_CALL(*object_, VoidReturnStringParam(std::string("hello"))); + + STRINGZ_TO_NPVARIANT("hello", args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnStringParam"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnObjectParamWithObject) { + EXPECT_CALL(*object_, VoidReturnObjectParam(passed_object_)); + + OBJECT_TO_NPVARIANT(passed_object_.Get(), args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnObjectParam"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnObjectParamWithNull) { + EXPECT_CALL( + *object_, + VoidReturnObjectParam(NPObjectPointer<NPObject>())); + + NULL_TO_NPVARIANT(args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnObjectParam"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeVoidReturnTwoParams) { + EXPECT_CALL(*object_, VoidReturnTwoParams(false, 7)); + + BOOLEAN_TO_NPVARIANT(false, args_[0]); + INT32_TO_NPVARIANT(7, args_[1]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("voidReturnTwoParams"), + args_, + 2, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeOverloadedWithNoParams) { + EXPECT_CALL(*object_, Overloaded()); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("overloaded"), + NULL, + 0, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeOverloadedWithOneStringParam) { + EXPECT_CALL(*object_, Overloaded(std::string("hello"))); + + STRINGZ_TO_NPVARIANT("hello", args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("overloaded"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeOverloadedWithOneBoolParam) { + EXPECT_CALL(*object_, Overloaded(true)); + + BOOLEAN_TO_NPVARIANT(true, args_[0]); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("overloaded"), + args_, + 1, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_VOID(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeBoolReturn) { + EXPECT_CALL(*object_, BoolReturn()).WillOnce(Return(true)); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("boolReturn"), + NULL, + 0, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_BOOLEAN(result_)); + EXPECT_TRUE(NPVARIANT_TO_BOOLEAN(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeIntReturn) { + EXPECT_CALL(*object_, IntReturn()).WillOnce(Return(7)); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("intReturn"), + NULL, + 0, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_INT32(result_)); + EXPECT_EQ(7, NPVARIANT_TO_INT32(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeFloatReturn) { + EXPECT_CALL(*object_, FloatReturn()).WillOnce(Return(7.0f)); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("floatReturn"), + NULL, + 0, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_DOUBLE(result_)); + EXPECT_EQ(7.0, NPVARIANT_TO_DOUBLE(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeDoubleReturn) { + EXPECT_CALL(*object_, DoubleReturn()).WillOnce(Return(7.0)); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("doubleReturn"), + NULL, + 0, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_DOUBLE(result_)); + EXPECT_EQ(7.0, NPVARIANT_TO_DOUBLE(result_)); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeStringReturn) { + EXPECT_CALL(*object_, StringReturn()).WillOnce(Return(std::string("hello"))); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("stringReturn"), + NULL, + 0, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_STRING(result_)); + + NPString& str = NPVARIANT_TO_STRING(result_); + EXPECT_EQ(std::string("hello"), + std::string(str.UTF8Characters, str.UTF8Length)); + + // Callee is responsible for releasing string. + NPBrowser::get()->ReleaseVariantValue(&result_); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeObjectReturnWithObject) { + EXPECT_CALL(*object_, ObjectReturn()).WillOnce(Return(passed_object_)); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("objectReturn"), + NULL, + 0, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_OBJECT(result_)); + EXPECT_EQ(passed_object_.Get(), NPVARIANT_TO_OBJECT(result_)); + + NPBrowser::get()->ReleaseVariantValue(&result_); +} + +TEST_F(DispatchedNPObjectTest, CanInvokeObjectReturnWithNull) { + EXPECT_CALL(*object_, ObjectReturn()) + .WillOnce(Return(NPObjectPointer<NPObject>())); + + EXPECT_TRUE(object_->Invoke( + NPBrowser::get()->GetStringIdentifier("objectReturn"), + NULL, + 0, + &result_)); + EXPECT_TRUE(NPVARIANT_IS_NULL(result_)); +} + +TEST_F(DispatchedNPObjectTest, HasMethodReturnsTrueIfMatchingMemberVariable) { + EXPECT_TRUE(object_->HasMethod( + NPBrowser::get()->GetStringIdentifier("objectReturn"))); +} + +TEST_F(DispatchedNPObjectTest, HasMethodReturnsTrueIfNoMatchingMemberVariable) { + EXPECT_FALSE(object_->HasMethod( + NPBrowser::get()->GetStringIdentifier("missing"))); +} + +TEST_F(DispatchedNPObjectTest, EnumeratesAllAvailableMethods) { + NPIdentifier* names; + uint32_t num_names; + ASSERT_TRUE(object_->Enumerate(&names, &num_names)); + + // Don't compare all of them; this test would need to change every time new + // dispatchers were added to the test NPObject class. Just compare the first + // registered (last in the dispatcher chain) and that more than one is + // returned. + EXPECT_GT(num_names, 1u); + EXPECT_EQ(NPBrowser::get()->GetStringIdentifier("voidReturnNoParams"), + names[num_names - 1]); + + NPBrowser::get()->MemFree(names); +} + +} // namespace np_utils diff --git a/gpu/np_utils/dynamic_np_object.cc b/gpu/np_utils/dynamic_np_object.cc new file mode 100644 index 0000000..e037fdc --- /dev/null +++ b/gpu/np_utils/dynamic_np_object.cc @@ -0,0 +1,59 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/np_utils/dynamic_np_object.h" + +namespace np_utils { + +DynamicNPObject::DynamicNPObject(NPP npp) { +} + +void DynamicNPObject::Invalidate() { + for (PropertyMap::iterator it = properties_.begin(); + it != properties_.end(); + ++it) { + it->second.Invalidate(); + } +} + +bool DynamicNPObject::HasProperty(NPIdentifier name) { + PropertyMap::iterator it = properties_.find(name); + return it != properties_.end(); +} + +bool DynamicNPObject::GetProperty(NPIdentifier name, NPVariant* result) { + PropertyMap::iterator it = properties_.find(name); + if (it == properties_.end()) + return false; + + it->second.CopyTo(result); + return true; +} + +bool DynamicNPObject::SetProperty(NPIdentifier name, const NPVariant* value) { + properties_[name] = *value; + return true; +} + +bool DynamicNPObject::RemoveProperty(NPIdentifier name) { + properties_.erase(name); + return false; +} + +bool DynamicNPObject::Enumerate(NPIdentifier** names, uint32_t* count) { + *names = static_cast<NPIdentifier*>( + NPBrowser::get()->MemAlloc(properties_.size() * sizeof(*names))); + *count = properties_.size(); + + int i = 0; + for (PropertyMap::iterator it = properties_.begin(); + it != properties_.end(); + ++it) { + (*names)[i] = it->first; + ++i; + } + + return true; +} +} // namespace np_utils diff --git a/gpu/np_utils/dynamic_np_object.h b/gpu/np_utils/dynamic_np_object.h new file mode 100644 index 0000000..2b63e78 --- /dev/null +++ b/gpu/np_utils/dynamic_np_object.h @@ -0,0 +1,35 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_DYNAMIC_NP_OBJECT_H_ +#define GPU_NP_UTILS_DYNAMIC_NP_OBJECT_H_ + +#include <map> + +#include "gpu/np_utils/default_np_object.h" +#include "gpu/np_utils/np_utils.h" + +namespace np_utils { + +// NPObjects of this type have a dictionary of property name / variant pairs +// that can be changed at runtime through NPAPI. +class DynamicNPObject : public DefaultNPObject<NPObject> { + public: + explicit DynamicNPObject(NPP npp); + + void Invalidate(); + bool HasProperty(NPIdentifier name); + bool GetProperty(NPIdentifier name, NPVariant* result); + bool SetProperty(NPIdentifier name, const NPVariant* value); + bool RemoveProperty(NPIdentifier name); + bool Enumerate(NPIdentifier** names, uint32_t* count); + + private: + typedef std::map<NPIdentifier, SmartNPVariant> PropertyMap; + PropertyMap properties_; + DISALLOW_COPY_AND_ASSIGN(DynamicNPObject); +}; +} // namespace np_utils + +#endif // GPU_NP_UTILS_DYNAMIC_NP_OBJECT_H_ diff --git a/gpu/np_utils/dynamic_np_object_unittest.cc b/gpu/np_utils/dynamic_np_object_unittest.cc new file mode 100644 index 0000000..d58e963 --- /dev/null +++ b/gpu/np_utils/dynamic_np_object_unittest.cc @@ -0,0 +1,83 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "gpu/np_utils/dynamic_np_object.h" +#include "gpu/np_utils/np_browser_stub.h" +#include "gpu/np_utils/np_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Return; +using testing::StrictMock; + +namespace np_utils { + +class NPDynamicNPObjectTest : public testing::Test { + protected: + virtual void SetUp() { + object_ = NPCreateObject<DynamicNPObject>(NULL); + } + + StubNPBrowser stub_browser_; + NPObjectPointer<DynamicNPObject> object_; +}; + +TEST_F(NPDynamicNPObjectTest, HasPropertyReturnsFalseForMissingProperty) { + EXPECT_FALSE(NPHasProperty(NULL, object_, "missing")); +} + +TEST_F(NPDynamicNPObjectTest, GetPropertyReturnsFalseForMissingProperty) { + int32 r; + EXPECT_FALSE(NPGetProperty(NULL, object_, "missing", &r)); +} + +TEST_F(NPDynamicNPObjectTest, CanSetProperty) { + EXPECT_TRUE(NPSetProperty(NULL, object_, "foo", 7)); + int32 r; + EXPECT_TRUE(NPHasProperty(NULL, object_, "foo")); + EXPECT_TRUE(NPGetProperty(NULL, object_, "foo", &r)); + EXPECT_EQ(7, r); +} + +TEST_F(NPDynamicNPObjectTest, CanRemoveProperty) { + EXPECT_TRUE(NPSetProperty(NULL, object_, "foo", 7)); + EXPECT_TRUE(NPHasProperty(NULL, object_, "foo")); + EXPECT_FALSE(NPRemoveProperty(NULL, object_, "foo")); + EXPECT_FALSE(NPHasProperty(NULL, object_, "foo")); + int32 r; + EXPECT_FALSE(NPGetProperty(NULL, object_, "foo", &r)); +} + +TEST_F(NPDynamicNPObjectTest, CanEnumerateProperties) { + EXPECT_TRUE(NPSetProperty(NULL, object_, "foo", 7)); + + NPIdentifier* names; + uint32 num_names; + EXPECT_TRUE(object_->_class->enumerate(object_.Get(), &names, &num_names)); + + EXPECT_EQ(1, num_names); + EXPECT_EQ(NPBrowser::get()->GetStringIdentifier("foo"), names[0]); + + NPBrowser::get()->MemFree(names); +} + +// Properties should not be +TEST_F(NPDynamicNPObjectTest, InvalidateNullsObjectProperties) { + EXPECT_EQ(1, object_->referenceCount); + { + EXPECT_TRUE(NPSetProperty(NULL, object_, "foo", object_)); + EXPECT_TRUE(NPHasProperty(NULL, object_, "foo")); + object_->_class->invalidate(object_.Get()); + EXPECT_TRUE(NPHasProperty(NULL, object_, "foo")); + NPObjectPointer<DynamicNPObject> r; + EXPECT_TRUE(NPGetProperty(NULL, object_, "foo", &r)); + EXPECT_TRUE(NULL == r.Get()); + } + // Invalidate did not release object + EXPECT_EQ(2, object_->referenceCount); + NPBrowser::get()->ReleaseObject(object_.Get()); +} +} // namespace np_utils diff --git a/gpu/np_utils/np_browser.cc b/gpu/np_utils/np_browser.cc new file mode 100644 index 0000000..d0d703c --- /dev/null +++ b/gpu/np_utils/np_browser.cc @@ -0,0 +1,123 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/np_utils/np_browser.h" +#include "base/logging.h" +#include "webkit/glue/plugins/nphostapi.h" + +namespace np_utils { + +NPBrowser* NPBrowser::browser_; + +NPBrowser::NPBrowser(NPNetscapeFuncs* funcs) + : netscape_funcs_(funcs) { + // Make this the first browser in the linked list. + previous_browser_ = browser_; + browser_ = this; +} + +NPBrowser::~NPBrowser() { + // Remove this browser from the linked list. + DCHECK(browser_ == this); + browser_ = previous_browser_; +} + +NPIdentifier NPBrowser::GetStringIdentifier(const NPUTF8* name) { + return netscape_funcs_->getstringidentifier(name); +} + +void* NPBrowser::MemAlloc(size_t size) { + return netscape_funcs_->memalloc(size); +} + +void NPBrowser::MemFree(void* p) { + netscape_funcs_->memfree(p); +} + +NPObject* NPBrowser::CreateObject(NPP npp, const NPClass* cl) { + return netscape_funcs_->createobject(npp, const_cast<NPClass*>(cl)); +} + +NPObject* NPBrowser::RetainObject(NPObject* object) { + return netscape_funcs_->retainobject(object); +} + +void NPBrowser::ReleaseObject(NPObject* object) { + netscape_funcs_->releaseobject(object); +} + +void NPBrowser::ReleaseVariantValue(NPVariant* variant) { + netscape_funcs_->releasevariantvalue(variant); +} + +bool NPBrowser::HasProperty(NPP npp, + NPObject* object, + NPIdentifier name) { + return netscape_funcs_->hasproperty(npp, object, name); +} + +bool NPBrowser::GetProperty(NPP npp, + NPObject* object, + NPIdentifier name, + NPVariant* result) { + return netscape_funcs_->getproperty(npp, object, name, result); +} + +bool NPBrowser::SetProperty(NPP npp, + NPObject* object, + NPIdentifier name, + const NPVariant* result) { + return netscape_funcs_->setproperty(npp, object, name, result); +} + +bool NPBrowser::RemoveProperty(NPP npp, + NPObject* object, + NPIdentifier name) { + return netscape_funcs_->removeproperty(npp, object, name); +} + +bool NPBrowser::HasMethod(NPP npp, + NPObject* object, + NPIdentifier name) { + return netscape_funcs_->hasmethod(npp, object, name); +} + +bool NPBrowser::Invoke(NPP npp, + NPObject* object, + NPIdentifier name, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + return netscape_funcs_->invoke(npp, object, name, args, num_args, result); +} + +NPObject* NPBrowser::GetWindowNPObject(NPP npp) { + NPObject* window; + if (NPERR_NO_ERROR == netscape_funcs_->getvalue(npp, + NPNVWindowNPObject, + &window)) { + return window; + } else { + return NULL; + } +} + +void NPBrowser::PluginThreadAsyncCall(NPP npp, + PluginThreadAsyncCallProc callback, + void* data) { + netscape_funcs_->pluginthreadasynccall(npp, callback, data); +} + +uint32 NPBrowser::ScheduleTimer(NPP npp, + uint32 interval, + bool repeat, + TimerProc callback) { + return netscape_funcs_->scheduletimer(npp, interval, repeat, callback); +} + +void NPBrowser::UnscheduleTimer(NPP npp, uint32 timer_id) { + netscape_funcs_->unscheduletimer(npp, timer_id); +} + +} // namespace np_utils diff --git a/gpu/np_utils/np_browser.h b/gpu/np_utils/np_browser.h new file mode 100644 index 0000000..e46bf38 --- /dev/null +++ b/gpu/np_utils/np_browser.h @@ -0,0 +1,95 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_BROWSER_H_ +#define GPU_NP_UTILS_NP_BROWSER_H_ + +#include "base/basictypes.h" +#include "gpu/np_utils/np_headers.h" + +typedef struct _NPNetscapeFuncs NPNetscapeFuncs; + +namespace np_utils { + +// This class exposes the functions provided by the browser to a plugin (the +// ones prefixed NPN_). +class NPBrowser { + public: + explicit NPBrowser(NPNetscapeFuncs* funcs); + virtual ~NPBrowser(); + + static NPBrowser* get() { + return browser_; + } + + // Standard functions from NPNetscapeFuncs. + + virtual NPIdentifier GetStringIdentifier(const NPUTF8* name); + + virtual void* MemAlloc(size_t size); + + virtual void MemFree(void* p); + + virtual NPObject* CreateObject(NPP npp, const NPClass* cl); + + virtual NPObject* RetainObject(NPObject* object); + + virtual void ReleaseObject(NPObject* object); + + virtual void ReleaseVariantValue(NPVariant* variant); + + virtual bool HasProperty(NPP npp, + NPObject* object, + NPIdentifier name); + + virtual bool GetProperty(NPP npp, + NPObject* object, + NPIdentifier name, + NPVariant* result); + + virtual bool SetProperty(NPP npp, + NPObject* object, + NPIdentifier name, + const NPVariant* result); + + virtual bool RemoveProperty(NPP npp, + NPObject* object, + NPIdentifier name); + + virtual bool HasMethod(NPP npp, + NPObject* object, + NPIdentifier name); + + virtual bool Invoke(NPP npp, + NPObject* object, + NPIdentifier name, + const NPVariant* args, + uint32_t num_args, + NPVariant* result); + + virtual NPObject* GetWindowNPObject(NPP npp); + + typedef void (*PluginThreadAsyncCallProc)(void* data); + virtual void PluginThreadAsyncCall(NPP npp, + PluginThreadAsyncCallProc callback, + void* data); + + typedef void (*TimerProc)(NPP npp, uint32 timer_id); + virtual uint32 ScheduleTimer(NPP npp, + uint32 interval, + bool repeat, + TimerProc callback); + + virtual void UnscheduleTimer(NPP npp, uint32 timer_id); + + private: + static NPBrowser* browser_; + NPBrowser* previous_browser_; + NPNetscapeFuncs* netscape_funcs_; + DISALLOW_COPY_AND_ASSIGN(NPBrowser); +}; + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_BROWSER_H_ diff --git a/gpu/np_utils/np_browser_mock.h b/gpu/np_utils/np_browser_mock.h new file mode 100644 index 0000000..c5361c7 --- /dev/null +++ b/gpu/np_utils/np_browser_mock.h @@ -0,0 +1,50 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_BROWSER_MOCK_H_ +#define GPU_NP_UTILS_NP_BROWSER_MOCK_H_ + +#include "gpu/np_utils/np_browser_stub.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace np_utils { + +// This mocks certain member functions of the stub browser. Those relating +// to identifiers, memory management, reference counting and forwarding to +// NPObjects are deliberately not mocked so the mock browser can be used as +// normal for these calls. +class MockNPBrowser : public StubNPBrowser { + public: + NPObject* ConcreteCreateObject(NPP npp, const NPClass* cl) { + return StubNPBrowser::CreateObject(npp, cl); + } + + MockNPBrowser() { + // Do not mock CreateObject by default but allow it to be mocked so object + // creation can be intercepted. + ON_CALL(*this, CreateObject(testing::_, testing::_)) + .WillByDefault(testing::Invoke(this, + &MockNPBrowser::ConcreteCreateObject)); + } + + void ConcretePluginThreadAsyncCall(NPP npp, + PluginThreadAsyncCallProc callback, + void* data) { + return StubNPBrowser::PluginThreadAsyncCall(npp, callback, data); + } + + MOCK_METHOD2(CreateObject, NPObject*(NPP npp, const NPClass* cl)); + MOCK_METHOD1(GetWindowNPObject, NPObject*(NPP cpp)); + MOCK_METHOD3(PluginThreadAsyncCall, + void(NPP npp, PluginThreadAsyncCallProc callback, void* data)); + MOCK_METHOD4(ScheduleTimer, uint32(NPP npp, + uint32 interval, + bool repeat, + TimerProc callback)); + MOCK_METHOD2(UnscheduleTimer, void(NPP npp, uint32 timer_id)); +}; + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_BROWSER_MOCK_H_ diff --git a/gpu/np_utils/np_browser_stub.cc b/gpu/np_utils/np_browser_stub.cc new file mode 100644 index 0000000..2e1c757 --- /dev/null +++ b/gpu/np_utils/np_browser_stub.cc @@ -0,0 +1,125 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/np_utils/np_browser_stub.h" +#include "base/logging.h" +#include "base/message_loop.h" + +namespace np_utils { + +StubNPBrowser::StubNPBrowser() : NPBrowser(NULL) { +} + +StubNPBrowser::~StubNPBrowser() { +} + +NPIdentifier StubNPBrowser::GetStringIdentifier(const NPUTF8* name) { + static std::set<std::string> names; + std::set<std::string>::iterator it = names.find(name); + if (it == names.end()) { + it = names.insert(name).first; + } + return const_cast<NPUTF8*>((*it).c_str()); +} + +void* StubNPBrowser::MemAlloc(size_t size) { + return malloc(size); +} + +void StubNPBrowser::MemFree(void* p) { + free(p); +} + +NPObject* StubNPBrowser::CreateObject(NPP npp, const NPClass* cl) { + NPObject* object = cl->allocate(npp, const_cast<NPClass*>(cl)); + object->referenceCount = 1; + object->_class = const_cast<NPClass*>(cl); + return object; +} + +NPObject* StubNPBrowser::RetainObject(NPObject* object) { + ++object->referenceCount; + return object; +} + +void StubNPBrowser::ReleaseObject(NPObject* object) { + DCHECK_GE(object->referenceCount, 0u); + --object->referenceCount; + if (object->referenceCount == 0) { + object->_class->deallocate(object); + } +} + +void StubNPBrowser::ReleaseVariantValue(NPVariant* variant) { + if (NPVARIANT_IS_STRING(*variant)) { + MemFree(const_cast<NPUTF8*>(variant->value.stringValue.UTF8Characters)); + } else if (NPVARIANT_IS_OBJECT(*variant)) { + ReleaseObject(NPVARIANT_TO_OBJECT(*variant)); + } +} + +bool StubNPBrowser::HasProperty(NPP npp, + NPObject* object, + NPIdentifier name) { + return object->_class->hasProperty(object, name); +} + +bool StubNPBrowser::GetProperty(NPP npp, + NPObject* object, + NPIdentifier name, + NPVariant* result) { + return object->_class->getProperty(object, name, result); +} + +bool StubNPBrowser::SetProperty(NPP npp, + NPObject* object, + NPIdentifier name, + const NPVariant* result) { + return object->_class->setProperty(object, name, result); +} + +bool StubNPBrowser::RemoveProperty(NPP npp, + NPObject* object, + NPIdentifier name) { + return object->_class->removeProperty(object, name); +} + +bool StubNPBrowser::HasMethod(NPP npp, + NPObject* object, + NPIdentifier name) { + return object->_class->hasMethod(object, name); +} + +bool StubNPBrowser::Invoke(NPP npp, + NPObject* object, + NPIdentifier name, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + return object->_class->invoke(object, name, args, num_args, result); +} + +NPObject* StubNPBrowser::GetWindowNPObject(NPP npp) { + return NULL; +} + +void StubNPBrowser::PluginThreadAsyncCall( + NPP npp, + PluginThreadAsyncCallProc callback, + void* data) { + MessageLoop::current()->PostTask(FROM_HERE, + NewRunnableFunction(callback, data)); +} + +uint32 StubNPBrowser::ScheduleTimer(NPP npp, + uint32 interval, + bool repeat, + TimerProc callback) { + return 0; +} + +void StubNPBrowser::UnscheduleTimer(NPP npp, uint32 timer_id) { +} + +} // namespace np_utils diff --git a/gpu/np_utils/np_browser_stub.h b/gpu/np_utils/np_browser_stub.h new file mode 100644 index 0000000..f208b7b --- /dev/null +++ b/gpu/np_utils/np_browser_stub.h @@ -0,0 +1,84 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_BROWSER_STUB_H_ +#define GPU_NP_UTILS_NP_BROWSER_STUB_H_ + +#include <set> +#include <string> + +#include "gpu/np_utils/np_browser.h" + +namespace np_utils { + +// Simple implementation of subset of the NPN functions for testing. +class StubNPBrowser : public NPBrowser { + public: + StubNPBrowser(); + virtual ~StubNPBrowser(); + + // Standard functions from NPNetscapeFuncs. + + virtual NPIdentifier GetStringIdentifier(const NPUTF8* name); + + virtual void* MemAlloc(size_t size); + + virtual void MemFree(void* p); + + virtual NPObject* CreateObject(NPP npp, const NPClass* cl); + + virtual NPObject* RetainObject(NPObject* object); + + virtual void ReleaseObject(NPObject* object); + + virtual void ReleaseVariantValue(NPVariant* variant); + + virtual bool HasProperty(NPP npp, + NPObject* object, + NPIdentifier name); + + virtual bool GetProperty(NPP npp, + NPObject* object, + NPIdentifier name, + NPVariant* result); + + virtual bool SetProperty(NPP npp, + NPObject* object, + NPIdentifier name, + const NPVariant* result); + + virtual bool RemoveProperty(NPP npp, + NPObject* object, + NPIdentifier name); + + virtual bool HasMethod(NPP npp, + NPObject* object, + NPIdentifier name); + virtual bool Invoke(NPP npp, + NPObject* object, + NPIdentifier name, + const NPVariant* args, + uint32_t num_args, + NPVariant* result); + + virtual NPObject* GetWindowNPObject(NPP npp); + + virtual void PluginThreadAsyncCall(NPP npp, + PluginThreadAsyncCallProc callback, + void* data); + + virtual uint32 ScheduleTimer(NPP npp, + uint32 interval, + bool repeat, + TimerProc callback); + + virtual void UnscheduleTimer(NPP npp, uint32 timer_id); + + private: + DISALLOW_COPY_AND_ASSIGN(StubNPBrowser); +}; + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_BROWSER_STUB_H_ diff --git a/gpu/np_utils/np_class.h b/gpu/np_utils/np_class.h new file mode 100644 index 0000000..21d1d4b --- /dev/null +++ b/gpu/np_utils/np_class.h @@ -0,0 +1,125 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_CLASS_H_ +#define GPU_NP_UTILS_NP_CLASS_H_ + +#include "gpu/np_utils/np_object_pointer.h" +#include "gpu/np_utils/np_headers.h" + +// This file implements NPGetClass<T>. This function returns an NPClass +// that can be used to instantiate an NPObject subclass T. The NPClass +// function pointers will invoke the most derived corresponding member +// functions in T. + +namespace np_utils { + +namespace np_class_impl { + // This template version of the NPClass allocate function creates a subclass + // of BaseNPObject. + template <typename NPObjectType> + static NPObject* Allocate(NPP npp, NPClass*) { + return new NPObjectType(npp); + } + + // These implementations of the NPClass functions forward to the virtual + // functions in DefaultNPObject. + template <typename NPObjectType> + static void Deallocate(NPObject* object) { + delete static_cast<NPObjectType*>(object); + } + + template <typename NPObjectType> + static void Invalidate(NPObject* object) { + return static_cast<NPObjectType*>(object)->Invalidate(); + } + + template <typename NPObjectType> + static bool HasMethod(NPObject* object, NPIdentifier name) { + return static_cast<NPObjectType*>(object)->HasMethod(name); + } + + template <typename NPObjectType> + static bool Invoke(NPObject* object, + NPIdentifier name, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + return static_cast<NPObjectType*>(object)->Invoke( + name, args, num_args, result); + } + + template <typename NPObjectType> + static bool InvokeDefault(NPObject* object, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + return static_cast<NPObjectType*>(object)->InvokeDefault( + args, num_args, result); + } + + template <typename NPObjectType> + static bool HasProperty(NPObject* object, NPIdentifier name) { + return static_cast<NPObjectType*>(object)->HasProperty(name); + } + + template <typename NPObjectType> + static bool GetProperty(NPObject* object, + NPIdentifier name, + NPVariant* result) { + return static_cast<NPObjectType*>(object)->GetProperty(name, result); + } + + template <typename NPObjectType> + static bool SetProperty(NPObject* object, + NPIdentifier name, + const NPVariant* value) { + return static_cast<NPObjectType*>(object)->SetProperty(name, value); + } + + template <typename NPObjectType> + static bool RemoveProperty(NPObject* object, NPIdentifier name) { + return static_cast<NPObjectType*>(object)->RemoveProperty(name); + } + + template <typename NPObjectType> + static bool Enumerate(NPObject* object, + NPIdentifier** names, + uint32_t* count) { + return static_cast<NPObjectType*>(object)->Enumerate(names, count); + }; + + template <typename NPObjectType> + static bool Construct(NPObject* object, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + return static_cast<NPObjectType*>(object)->Construct( + args, num_args, result); + } +} // namespace np_class_impl; + +template <typename NPObjectType> +const NPClass* NPGetClass() { + static const NPClass np_class = { + NP_CLASS_STRUCT_VERSION, + np_class_impl::Allocate<NPObjectType>, + np_class_impl::Deallocate<NPObjectType>, + np_class_impl::Invalidate<NPObjectType>, + np_class_impl::HasMethod<NPObjectType>, + np_class_impl::Invoke<NPObjectType>, + np_class_impl::InvokeDefault<NPObjectType>, + np_class_impl::HasProperty<NPObjectType>, + np_class_impl::GetProperty<NPObjectType>, + np_class_impl::SetProperty<NPObjectType>, + np_class_impl::RemoveProperty<NPObjectType>, + np_class_impl::Enumerate<NPObjectType>, + np_class_impl::Construct<NPObjectType>, + }; + return &np_class; +}; + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_CLASS_H_ diff --git a/gpu/np_utils/np_class_unittest.cc b/gpu/np_utils/np_class_unittest.cc new file mode 100644 index 0000000..0e7807f --- /dev/null +++ b/gpu/np_utils/np_class_unittest.cc @@ -0,0 +1,143 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/np_utils/np_class.h" +#include "gpu/np_utils/np_object_mock.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::StrictMock; + +namespace np_utils { + +class NPClassTest : public testing::Test { + protected: + virtual void SetUp() { + np_class = NPGetClass<StrictMock<MockNPObject> >(); + + // Dummy identifier is never used with real NPAPI so it can point to + // anything. + identifier = this; + } + + virtual void TearDown() { + } + + NPP_t npp_; + const NPClass* np_class; + NPIdentifier identifier; + NPVariant args[3]; + NPVariant result; +}; + +TEST_F(NPClassTest, AllocateAndDeallocateObject) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + EXPECT_TRUE(NULL != object); + + np_class->deallocate(object); +} + +TEST_F(NPClassTest, InvalidateForwards) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + + EXPECT_CALL(*object, Invalidate()); + np_class->invalidate(object); + + np_class->deallocate(object); +} + +TEST_F(NPClassTest, HasMethodForwards) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + + EXPECT_CALL(*object, HasMethod(identifier)); + np_class->hasMethod(object, identifier); + + np_class->deallocate(object); +} + +TEST_F(NPClassTest, InvokeForwards) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + + EXPECT_CALL(*object, Invoke(identifier, args, 3, &result)); + np_class->invoke(object, identifier, args, 3, &result); + + np_class->deallocate(object); +} + +TEST_F(NPClassTest, InvokeDefaultForwards) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + + EXPECT_CALL(*object, InvokeDefault(args, 3, &result)); + np_class->invokeDefault(object, args, 3, &result); + + np_class->deallocate(object); +} + +TEST_F(NPClassTest, HasPropertyForwards) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + + EXPECT_CALL(*object, HasProperty(identifier)); + np_class->hasProperty(object, identifier); + + np_class->deallocate(object); +} + +TEST_F(NPClassTest, GetPropertyForwards) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + + EXPECT_CALL(*object, GetProperty(identifier, &result)); + np_class->getProperty(object, identifier, &result); + + np_class->deallocate(object); +} + +TEST_F(NPClassTest, SetPropertyForwards) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + + EXPECT_CALL(*object, SetProperty(identifier, &result)); + np_class->setProperty(object, identifier, &result); + + np_class->deallocate(object); +} + +TEST_F(NPClassTest, RemovePropertyForwards) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + + EXPECT_CALL(*object, RemoveProperty(identifier)); + np_class->removeProperty(object, identifier); + + np_class->deallocate(object); +} + +TEST_F(NPClassTest, EnumerateForwards) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + + NPIdentifier* identifier = NULL; + uint32_t count; + EXPECT_CALL(*object, Enumerate(&identifier, &count)); + np_class->enumerate(object, &identifier, &count); + + np_class->deallocate(object); +} + +TEST_F(NPClassTest, ConstructForwards) { + MockNPObject* object = static_cast<MockNPObject*>( + np_class->allocate(&npp_, const_cast<NPClass*>(np_class))); + + EXPECT_CALL(*object, Construct(args, 3, &result)); + np_class->construct(object, args, 3, &result); + + np_class->deallocate(object); +} +} // namespace np_utils diff --git a/gpu/np_utils/np_dispatcher.cc b/gpu/np_utils/np_dispatcher.cc new file mode 100644 index 0000000..63293c0 --- /dev/null +++ b/gpu/np_utils/np_dispatcher.cc @@ -0,0 +1,86 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/np_utils/np_dispatcher.h" + +namespace np_utils { + +bool DispatcherHasMethodHelper(BaseNPDispatcher* chain, + NPObject* object, + NPIdentifier name) { + for (BaseNPDispatcher* dispatcher = chain; + dispatcher; + dispatcher = dispatcher->next()) { + if (dispatcher->name() == name) { + return true; + } + } + + return false; +} + +bool DispatcherInvokeHelper(BaseNPDispatcher* chain, + NPObject* object, + NPIdentifier name, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + VOID_TO_NPVARIANT(*result); + + for (BaseNPDispatcher* dispatcher = chain; + dispatcher; + dispatcher = dispatcher->next()) { + if (dispatcher->name() == name && + dispatcher->num_args() == static_cast<int>(num_args)) { + if (dispatcher->Invoke(object, args, num_args, result)) + return true; + } + } + + return false; +} + +bool DispatcherEnumerateHelper(BaseNPDispatcher* chain, + NPObject* object, + NPIdentifier** names, + uint32_t* num_names) { + // Count the number of names. + *num_names = 0; + for (BaseNPDispatcher* dispatcher = chain; + dispatcher; + dispatcher = dispatcher->next()) { + ++(*num_names); + } + + // Copy names into the array. + *names = static_cast<NPIdentifier*>( + NPBrowser::get()->MemAlloc((*num_names) * sizeof(**names))); + int i = 0; + for (BaseNPDispatcher* dispatcher = chain; + dispatcher; + dispatcher = dispatcher->next()) { + (*names)[i] = dispatcher->name(); + ++i; + } + + return true; +} + +BaseNPDispatcher::BaseNPDispatcher(BaseNPDispatcher* next, const NPUTF8* name) + : next_(next) { + // Convert first character to lower case if it is the ASCII range. + // TODO(apatrick): do this correctly for non-ASCII characters. + std::string java_script_style_name(name); + if (isupper(java_script_style_name[0])) { + java_script_style_name[0] = tolower(java_script_style_name[0]); + } + + name_ = NPBrowser::get()->GetStringIdentifier( + java_script_style_name.c_str()); +} + +BaseNPDispatcher::~BaseNPDispatcher() { +} + +} // namespace np_utils diff --git a/gpu/np_utils/np_dispatcher.h b/gpu/np_utils/np_dispatcher.h new file mode 100644 index 0000000..ff6bed5 --- /dev/null +++ b/gpu/np_utils/np_dispatcher.h @@ -0,0 +1,224 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_DISPATCHER_H_ +#define GPU_NP_UTILS_NP_DISPATCHER_H_ + +#include <string> + +#include "gpu/np_utils/np_utils.h" +#include "gpu/np_utils/np_headers.h" + +// Dispatchers make regular member functions available as NPObject methods. +// Usage: +// +// class MyNPObject : public DefaultNPObject<NPObject> { +// public: +// int MyMethod(bool a, float b); +// NP_UTILS_BEGIN_DISPATCHER_CHAIN(MyNPObject, DispatchedNPObject) +// NP_UTILS_DISPATCHER(MyMethod, int(bool, float)) +// NP_UTILS_END_DISPATCHER_CHAIN +// }; +// +// Multiple member functions may be listed in the dispatcher chain. Inheritance +// is supported. The following types are supported as return types and parameter +// types: +// * bool +// * int +// * float +// * double +// * std::string +// * NPObject* +// + +// These macros are used to make dispatcher chains. +#define NP_UTILS_NP_UTILS_DISPATCHER_JOIN2(a, b) a ## b +#define NP_UTILS_DISPATCHER_JOIN(a, b) NP_UTILS_NP_UTILS_DISPATCHER_JOIN2(a, b) +#define NP_UTILS_DISPATCHER_UNIQUE \ + NP_UTILS_DISPATCHER_JOIN(dispatcher, __LINE__) + +#define NP_UTILS_BEGIN_DISPATCHER_CHAIN(Class, BaseClass) \ + static ::np_utils::BaseNPDispatcher* GetDispatcherChain() { \ + typedef Class ThisClass; \ + ::np_utils::BaseNPDispatcher* top_dispatcher = \ + BaseClass::GetDispatcherChain(); \ + +#define NP_UTILS_DISPATCHER(name, Signature) \ + static ::np_utils::NPDispatcher<ThisClass, Signature> \ + NP_UTILS_DISPATCHER_UNIQUE( \ + top_dispatcher, \ + #name, \ + &ThisClass::name); \ + top_dispatcher = &NP_UTILS_DISPATCHER_UNIQUE; \ + +#define NP_UTILS_END_DISPATCHER_CHAIN \ + return top_dispatcher; \ + } \ + bool HasMethod(NPIdentifier name) { \ + return ::np_utils::DispatcherHasMethodHelper( \ + GetDispatcherChain(), this, name); \ + } \ + bool Invoke(NPIdentifier name, \ + const NPVariant* args, \ + uint32_t num_args, \ + NPVariant* result) { \ + return ::np_utils::DispatcherInvokeHelper(GetDispatcherChain(), \ + this, \ + name, \ + args, \ + num_args, \ + result); \ + } \ + bool Enumerate(NPIdentifier** names, uint32_t* num_names) { \ + return ::np_utils::DispatcherEnumerateHelper(GetDispatcherChain(), \ + this, \ + names, \ + num_names); \ + } \ + +namespace np_utils { + +class BaseNPDispatcher { + public: + BaseNPDispatcher(BaseNPDispatcher* next, const NPUTF8* name); + + virtual ~BaseNPDispatcher(); + + BaseNPDispatcher* next() const { + return next_; + } + + NPIdentifier name() const { + return name_; + } + + virtual int num_args() const = 0; + + virtual bool Invoke(NPObject* object, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) = 0; + + private: + BaseNPDispatcher* next_; + NPIdentifier name_; + DISALLOW_COPY_AND_ASSIGN(BaseNPDispatcher); +}; + +bool DispatcherHasMethodHelper(BaseNPDispatcher* chain, + NPObject* object, + NPIdentifier name); + +bool DispatcherInvokeHelper(BaseNPDispatcher* chain, + NPObject* object, + NPIdentifier name, + const NPVariant* args, + uint32_t num_args, + NPVariant* result); + +bool DispatcherEnumerateHelper(BaseNPDispatcher* chain, + NPObject* object, + NPIdentifier** names, + uint32_t* num_names); + +// This class should never be instantiated. It is always specialized. Attempting +// to instantiate it results in a compilation error. This might mean an +// attempt to instantiate a dispatcher with more parameters than have been +// specialized for. See the specialization code below. +template <typename NPObjectType, typename FunctionType> +struct NPDispatcher { +}; + +#define TO_NPVARIANT(index) \ + T##index n##index; \ + if (!NPVariantToValue(&n##index, args[index])) \ + return false; \ + +#define NUM_PARAMS 0 +#define PARAM_TYPENAMES +#define PARAM_TYPES +#define PARAM_NAMES +#define PARAM_DECLS // NOLINT + +#define PARAM_TO_NVPARIANT_CONVERSIONS \ + +#include "gpu/np_utils/np_dispatcher_specializations.h" // NOLINT + + +#define NUM_PARAMS 1 +#define PARAM_TYPENAMES , typename T0 +#define PARAM_TYPES T0 +#define PARAM_NAMES n0 +#define PARAM_DECLS T0 n0; // NOLINT + +#define PARAM_TO_NVPARIANT_CONVERSIONS \ + TO_NPVARIANT(0); \ + +#include "gpu/np_utils/np_dispatcher_specializations.h" // NOLINT + + +#define NUM_PARAMS 2 +#define PARAM_TYPENAMES , typename T0, typename T1 +#define PARAM_TYPES T0, T1 +#define PARAM_NAMES n0, n1 +#define PARAM_DECLS T0 n0; T1 n1; // NOLINT + +#define PARAM_TO_NVPARIANT_CONVERSIONS \ + TO_NPVARIANT(0); \ + TO_NPVARIANT(1); \ + +#include "gpu/np_utils/np_dispatcher_specializations.h" // NOLINT + + +#define NUM_PARAMS 3 +#define PARAM_TYPENAMES , typename T0, typename T1, typename T2 +#define PARAM_TYPES T0, T1, T2 +#define PARAM_NAMES n0, n1, n2 +#define PARAM_DECLS T0 n0; T1 n1; T2 n2; // NOLINT + +#define PARAM_TO_NVPARIANT_CONVERSIONS \ + TO_NPVARIANT(0); \ + TO_NPVARIANT(1); \ + TO_NPVARIANT(2); \ + +#include "gpu/np_utils/np_dispatcher_specializations.h" // NOLINT + + +#define NUM_PARAMS 4 +#define PARAM_TYPENAMES , typename T0, typename T1, typename T2, typename T3 +#define PARAM_TYPES T0, T1, T2, T3 +#define PARAM_NAMES n0, n1, n2, n3 +#define PARAM_DECLS T0 n0; T1 n1; T2 n2; T3 n3; // NOLINT + +#define PARAM_TO_NVPARIANT_CONVERSIONS \ + TO_NPVARIANT(0); \ + TO_NPVARIANT(1); \ + TO_NPVARIANT(2); \ + TO_NPVARIANT(3); \ + +#include "gpu/np_utils/np_dispatcher_specializations.h" // NOLINT + + +#define NUM_PARAMS 5 +#define PARAM_TYPENAMES , typename T0, typename T1, typename T2, typename T3, \ + typename T4 +#define PARAM_TYPES T0, T1, T2, T3, T4 +#define PARAM_NAMES n0, n1, n2, n3, n4 +#define PARAM_DECLS T0 n0; T1 n1; T2 n2; T3 n3; T4 n4; // NOLINT + +#define PARAM_TO_NVPARIANT_CONVERSIONS \ + TO_NPVARIANT(0); \ + TO_NPVARIANT(1); \ + TO_NPVARIANT(2); \ + TO_NPVARIANT(3); \ + TO_NPVARIANT(4); \ + +#include "gpu/np_utils/np_dispatcher_specializations.h" // NOLINT + + +#undef TO_NPVARIANT + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_DISPATCHER_H_ diff --git a/gpu/np_utils/np_dispatcher_specializations.h b/gpu/np_utils/np_dispatcher_specializations.h new file mode 100644 index 0000000..62fb8c4 --- /dev/null +++ b/gpu/np_utils/np_dispatcher_specializations.h @@ -0,0 +1,85 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// There is deliberately no header guard here. This file is included multiple +// times, once for each dispatcher specialiation arity. Do not include this +// file directly. Include np_dispatcher.h instead. + +template <typename NPObjectType PARAM_TYPENAMES> +class NPDispatcher<NPObjectType, void(PARAM_TYPES)> + : public BaseNPDispatcher { + typedef void (NPObjectType::*FunctionType)(PARAM_TYPES); + public: + NPDispatcher(BaseNPDispatcher* next, + const NPUTF8* name, + FunctionType function) + : BaseNPDispatcher(next, name), + function_(function) { + } + + virtual bool Invoke(NPObject* object, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + VOID_TO_NPVARIANT(*result); + + if (num_args != NUM_PARAMS) + return false; + + PARAM_TO_NVPARIANT_CONVERSIONS + + (static_cast<NPObjectType*>(object)->*function_)(PARAM_NAMES); + return true; + } + + virtual int num_args() const { + return NUM_PARAMS; + } + + private: + FunctionType function_; +}; + +template <typename NPObjectType, typename R PARAM_TYPENAMES> +class NPDispatcher<NPObjectType, R(PARAM_TYPES)> + : public BaseNPDispatcher { + typedef R (NPObjectType::*FunctionType)(PARAM_TYPES); + public: + NPDispatcher(BaseNPDispatcher* next, + const NPUTF8* name, + FunctionType function) + : BaseNPDispatcher(next, name), + function_(function) { + } + + virtual bool Invoke(NPObject* object, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + VOID_TO_NPVARIANT(*result); + + if (num_args != NUM_PARAMS) + return false; + + PARAM_TO_NVPARIANT_CONVERSIONS + + ValueToNPVariant( + (static_cast<NPObjectType*>(object)->*function_)(PARAM_NAMES), result); + return true; + } + + virtual int num_args() const { + return NUM_PARAMS; + } + + private: + FunctionType function_; +}; + +#undef NUM_PARAMS +#undef PARAM_TYPENAMES +#undef PARAM_TYPES +#undef PARAM_NAMES +#undef PARAM_DECLS +#undef PARAM_TO_NVPARIANT_CONVERSIONS diff --git a/gpu/np_utils/np_headers.h b/gpu/np_utils/np_headers.h new file mode 100644 index 0000000..cd4d8f9 --- /dev/null +++ b/gpu/np_utils/np_headers.h @@ -0,0 +1,11 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_HEADERS_H_ +#define GPU_NP_UTILS_NP_HEADERS_H_ + +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/npruntime.h" + +#endif // GPU_NP_UTILS_NP_HEADERS_H_ diff --git a/gpu/np_utils/np_object_mock.h b/gpu/np_utils/np_object_mock.h new file mode 100644 index 0000000..99d1ff6 --- /dev/null +++ b/gpu/np_utils/np_object_mock.h @@ -0,0 +1,36 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_OBJECT_MOCK_H_ +#define GPU_NP_UTILS_NP_OBJECT_MOCK_H_ + +#include "gpu/np_utils/np_browser.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace np_utils { + +class MockNPObject : public NPObject { + public: + explicit MockNPObject(NPP npp) { + } + + MOCK_METHOD0(Invalidate, void()); + MOCK_METHOD1(HasMethod, bool(NPIdentifier)); + MOCK_METHOD4(Invoke, + bool(NPIdentifier, const NPVariant*, uint32_t, NPVariant*)); + MOCK_METHOD3(InvokeDefault, bool(const NPVariant*, uint32_t, NPVariant*)); + MOCK_METHOD1(HasProperty, bool(NPIdentifier)); + MOCK_METHOD2(GetProperty, bool(NPIdentifier, NPVariant*)); + MOCK_METHOD2(SetProperty, bool(NPIdentifier, const NPVariant*)); + MOCK_METHOD1(RemoveProperty, bool(NPIdentifier)); + MOCK_METHOD2(Enumerate, bool(NPIdentifier**, uint32_t*)); + MOCK_METHOD3(Construct, bool(const NPVariant*, uint32_t, NPVariant*)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockNPObject); +}; + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_OBJECT_MOCK_H_ diff --git a/gpu/np_utils/np_object_pointer.h b/gpu/np_utils/np_object_pointer.h new file mode 100644 index 0000000..44286a7 --- /dev/null +++ b/gpu/np_utils/np_object_pointer.h @@ -0,0 +1,119 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_OBJECT_POINTER_H_ +#define GPU_NP_UTILS_NP_OBJECT_POINTER_H_ + +#include "base/logging.h" +#include "gpu/np_utils/np_browser.h" +#include "gpu/np_utils/np_headers.h" + +namespace np_utils { + +// Smart pointer for NPObjects that automatically handles reference counting. +template <typename NPObjectType> +class NPObjectPointer { + public: + NPObjectPointer() : object_(NULL) {} + + NPObjectPointer(const NPObjectPointer& rhs) : object_(rhs.object_) { + Retain(); + } + + explicit NPObjectPointer(NPObjectType* p) : object_(p) { + Retain(); + } + + template <typename RHS> + NPObjectPointer(const NPObjectPointer<RHS>& rhs) : object_(rhs.Get()) { + Retain(); + } + + ~NPObjectPointer() { + Release(); + } + + NPObjectPointer& operator=(const NPObjectPointer& rhs) { + if (object_ == rhs.Get()) + return *this; + + Release(); + object_ = rhs.object_; + Retain(); + return *this; + } + + template <typename RHS> + NPObjectPointer& operator=(const NPObjectPointer<RHS>& rhs) { + if (object_ == rhs.Get()) + return *this; + + Release(); + object_ = rhs.Get(); + Retain(); + return *this; + } + + template <class RHS> + bool operator==(const NPObjectPointer<RHS>& rhs) const { + return object_ == rhs.Get(); + } + + template <class RHS> + bool operator!=(const NPObjectPointer<RHS>& rhs) const { + return object_ != rhs.Get(); + } + + // The NPObject convention for returning an NPObject pointer from a function + // is that the caller is responsible for releasing the reference count. + static NPObjectPointer FromReturned(NPObjectType* p) { + NPObjectPointer pointer(p); + pointer.Release(); + return pointer; + } + + // The NPObject convention for returning an NPObject pointer from a function + // is that the caller is responsible for releasing the reference count. + NPObjectType* ToReturned() const { + Retain(); + return object_; + } + + NPObjectType* Get() const { + return object_; + } + + NPObjectType* operator->() const { + return object_; + } + + NPObjectType& operator*() const { + return *object_; + } + + private: + void Retain() const { + if (object_) { + NPBrowser::get()->RetainObject(object_); + } + } + + void Release() const { + if (object_) { + NPBrowser::get()->ReleaseObject(object_); + } + } + + NPObjectType* object_; +}; + +// For test diagnostics. +template <typename NPObjectType> +std::ostream& operator<<(std::ostream& stream, + const NPObjectPointer<NPObjectType>& pointer) { + return stream << pointer.Get(); +} +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_OBJECT_POINTER_H_ diff --git a/gpu/np_utils/np_object_pointer_unittest.cc b/gpu/np_utils/np_object_pointer_unittest.cc new file mode 100644 index 0000000..1e48453 --- /dev/null +++ b/gpu/np_utils/np_object_pointer_unittest.cc @@ -0,0 +1,220 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/np_utils/np_class.h" +#include "gpu/np_utils/np_object_mock.h" +#include "gpu/np_utils/np_browser_stub.h" +#include "gpu/np_utils/np_object_pointer.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Return; +using testing::StrictMock; + +namespace np_utils { + +class DerivedNPObject : public MockNPObject { + public: + explicit DerivedNPObject(NPP npp) : MockNPObject(npp) { + } +}; + +class NPObjectPointerTest : public testing::Test { + protected: + virtual void SetUp() { + np_class_ = NPGetClass<StrictMock<MockNPObject> >(); + + raw_pointer_ = static_cast<MockNPObject*>( + NPBrowser::get()->CreateObject(NULL, np_class_)); + + raw_derived_pointer_ = static_cast<DerivedNPObject*>( + NPBrowser::get()->CreateObject(NULL, np_class_)); + } + + virtual void TearDown() { + NPBrowser::get()->ReleaseObject(raw_pointer_); + NPBrowser::get()->ReleaseObject(raw_derived_pointer_); + } + + StubNPBrowser stub_browser_; + const NPClass* np_class_; + MockNPObject* raw_pointer_; + DerivedNPObject* raw_derived_pointer_; +}; + +TEST_F(NPObjectPointerTest, PointerIsNullByDefault) { + NPObjectPointer<MockNPObject> p; + ASSERT_TRUE(NULL == p.Get()); +} + +TEST_F(NPObjectPointerTest, PointerCanBeExplicitlyConstructedFromRawPointer) { + EXPECT_EQ(1, raw_pointer_->referenceCount); + { + NPObjectPointer<MockNPObject> p(raw_pointer_); + ASSERT_TRUE(raw_pointer_ == p.Get()); + EXPECT_EQ(2, raw_pointer_->referenceCount); + } + EXPECT_EQ(1, raw_pointer_->referenceCount); +} + +TEST_F(NPObjectPointerTest, + PointerCanBeExplicitlyConstructedFromNullRawPointer) { + NPObjectPointer<MockNPObject> p(NULL); + ASSERT_TRUE(NULL == p.Get()); +} + +TEST_F(NPObjectPointerTest, PointerCanBeCopyConstructed) { + NPObjectPointer<MockNPObject> p1(raw_pointer_); + EXPECT_EQ(2, raw_pointer_->referenceCount); + { + NPObjectPointer<MockNPObject> p2(p1); + ASSERT_TRUE(raw_pointer_ == p2.Get()); + EXPECT_EQ(3, raw_pointer_->referenceCount); + } + EXPECT_EQ(2, raw_pointer_->referenceCount); +} + +TEST_F(NPObjectPointerTest, PointerCanBeConstructedFromDerived) { + NPObjectPointer<DerivedNPObject> p1(raw_derived_pointer_); + EXPECT_EQ(2, raw_derived_pointer_->referenceCount); + { + NPObjectPointer<MockNPObject> p2(p1); + ASSERT_TRUE(raw_derived_pointer_ == p2.Get()); + EXPECT_EQ(3, raw_derived_pointer_->referenceCount); + } + EXPECT_EQ(2, raw_derived_pointer_->referenceCount); +} + +TEST_F(NPObjectPointerTest, + PointerCanBeCopyConstructedFromNull) { + NPObjectPointer<MockNPObject> p(NULL); + ASSERT_TRUE(NULL == p.Get()); +} + +TEST_F(NPObjectPointerTest, PointerCanBeAssigned) { + NPObjectPointer<MockNPObject> p1(raw_pointer_); + EXPECT_EQ(2, raw_pointer_->referenceCount); + { + NPObjectPointer<MockNPObject> p2; + p2 = p1; + ASSERT_TRUE(raw_pointer_ == p2.Get()); + EXPECT_EQ(3, raw_pointer_->referenceCount); + + p2 = NPObjectPointer<MockNPObject>(); + ASSERT_TRUE(NULL == p2.Get()); + EXPECT_EQ(2, raw_pointer_->referenceCount); + + p2 = p1; + ASSERT_TRUE(raw_pointer_ == p2.Get()); + EXPECT_EQ(3, raw_pointer_->referenceCount); + } + EXPECT_EQ(2, raw_pointer_->referenceCount); +} + +TEST_F(NPObjectPointerTest, PointerCanBeAssignedToSelf) { + NPObjectPointer<MockNPObject> p(raw_pointer_); + NPBrowser::get()->ReleaseObject(raw_pointer_); + EXPECT_EQ(1, raw_pointer_->referenceCount); + p = p; + EXPECT_EQ(1, raw_pointer_->referenceCount); + NPBrowser::get()->RetainObject(raw_pointer_); +} + +TEST_F(NPObjectPointerTest, PointerCanBeAssignedDerived) { + NPObjectPointer<DerivedNPObject> p1(raw_derived_pointer_); + EXPECT_EQ(2, raw_derived_pointer_->referenceCount); + { + NPObjectPointer<MockNPObject> p2; + p2 = p1; + ASSERT_TRUE(raw_derived_pointer_ == p2.Get()); + EXPECT_EQ(3, raw_derived_pointer_->referenceCount); + + p2 = NPObjectPointer<MockNPObject>(); + ASSERT_TRUE(NULL == p2.Get()); + EXPECT_EQ(2, raw_derived_pointer_->referenceCount); + + p2 = p1; + ASSERT_TRUE(raw_derived_pointer_ == p2.Get()); + EXPECT_EQ(3, raw_derived_pointer_->referenceCount); + } + EXPECT_EQ(2, raw_derived_pointer_->referenceCount); +} + +TEST_F(NPObjectPointerTest, DerivedPointerCanBeAssignedToSelf) { + NPObjectPointer<MockNPObject> p1(raw_derived_pointer_); + NPObjectPointer<DerivedNPObject> p2(raw_derived_pointer_); + NPBrowser::get()->ReleaseObject(raw_derived_pointer_); + NPBrowser::get()->ReleaseObject(raw_derived_pointer_); + EXPECT_EQ(1, raw_derived_pointer_->referenceCount); + p1 = p2; + EXPECT_EQ(1, raw_derived_pointer_->referenceCount); + NPBrowser::get()->RetainObject(raw_derived_pointer_); + NPBrowser::get()->RetainObject(raw_derived_pointer_); +} + +TEST_F(NPObjectPointerTest, CanComparePointersForEqual) { + NPObjectPointer<MockNPObject> p1(raw_pointer_); + NPObjectPointer<DerivedNPObject> p2(raw_derived_pointer_); + EXPECT_TRUE(p1 == p1); + EXPECT_FALSE(p1 == p2); + EXPECT_FALSE(p2 == p1); + EXPECT_FALSE(p1 == NPObjectPointer<MockNPObject>()); +} + +TEST_F(NPObjectPointerTest, CanComparePointersForNotEqual) { + NPObjectPointer<MockNPObject> p1(raw_pointer_); + NPObjectPointer<DerivedNPObject> p2(raw_derived_pointer_); + EXPECT_FALSE(p1 != p1); + EXPECT_TRUE(p1 != p2); + EXPECT_TRUE(p2 != p1); + EXPECT_TRUE(p1 != NPObjectPointer<MockNPObject>()); +} + +TEST_F(NPObjectPointerTest, ArrowOperatorCanBeUsedToAccessNPObjectMembers) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("hello"); + + EXPECT_CALL(*raw_pointer_, HasProperty(name)).WillOnce(Return(true)); + + NPObjectPointer<MockNPObject> p(raw_pointer_); + EXPECT_TRUE(p->HasProperty(name)); +} + +TEST_F(NPObjectPointerTest, StarOperatorReturnsNPObjectReference) { + NPObjectPointer<MockNPObject> p(raw_pointer_); + EXPECT_EQ(raw_pointer_, &*p); +} + +TEST_F(NPObjectPointerTest, PointerCanBeConstructedFromReturnedNPObject) { + NPBrowser::get()->RetainObject(raw_pointer_); + EXPECT_EQ(2, raw_pointer_->referenceCount); + { + NPObjectPointer<MockNPObject> p( + NPObjectPointer<MockNPObject>::FromReturned(raw_pointer_)); + EXPECT_EQ(2, raw_pointer_->referenceCount); + } + EXPECT_EQ(1, raw_pointer_->referenceCount); +} + +TEST_F(NPObjectPointerTest, PointerCanBeConstructedFromReturnedNullNPObject) { + NPObjectPointer<MockNPObject> p( + NPObjectPointer<MockNPObject>::FromReturned(NULL)); + EXPECT_TRUE(NULL == p.Get()); +} + +TEST_F(NPObjectPointerTest, PointerCanBeReturnedAsARawNPObject) { + NPObjectPointer<MockNPObject> p(raw_pointer_); + EXPECT_EQ(raw_pointer_, p.ToReturned()); + + // Check reference count is incremented before return for caller. + EXPECT_EQ(3, raw_pointer_->referenceCount); + + NPBrowser::get()->ReleaseObject(raw_pointer_); +} + +TEST_F(NPObjectPointerTest, NULLPointerCanBeReturnedAsARawNPObject) { + NPObjectPointer<MockNPObject> p; + EXPECT_TRUE(NULL == p.ToReturned()); +} + +} // namespace np_utils diff --git a/gpu/np_utils/np_plugin_object.h b/gpu/np_utils/np_plugin_object.h new file mode 100644 index 0000000..ad578e4 --- /dev/null +++ b/gpu/np_utils/np_plugin_object.h @@ -0,0 +1,50 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_PLUGIN_OBJECT_H_ +#define GPU_NP_UTILS_NP_PLUGIN_OBJECT_H_ + +#include "gpu/np_utils/np_object_pointer.h" +#include "gpu/np_utils/np_headers.h" + +namespace np_utils { + +// Interface for a plugin instance. The NPP plugin calls forwards to an instance +// of this interface. +class PluginObject { + public: + // Initialize this object. + virtual NPError New(NPMIMEType plugin_type, + int16 argc, + char* argn[], + char* argv[], + NPSavedData* saved) = 0; + + virtual NPError SetWindow(NPWindow* new_window) = 0; + + virtual int16 HandleEvent(NPEvent* event) = 0; + + // Uninitialize but do not deallocate the object. Release will be called to + // deallocate if Destroy succeeds. + virtual NPError Destroy(NPSavedData** saved) = 0; + + // Deallocate this object. This object is invalid after this returns. + virtual void Release() = 0; + + virtual NPObject* GetScriptableNPObject() = 0; + + protected: + PluginObject() { + } + + virtual ~PluginObject() { + } + + private: + DISALLOW_COPY_AND_ASSIGN(PluginObject); +}; + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_PLUGIN_OBJECT_H_ diff --git a/gpu/np_utils/np_plugin_object_factory.cc b/gpu/np_utils/np_plugin_object_factory.cc new file mode 100644 index 0000000..7eedcc8 --- /dev/null +++ b/gpu/np_utils/np_plugin_object_factory.cc @@ -0,0 +1,30 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/gpu_plugin/gpu_plugin_object_factory.h" +#include "base/logging.h" + +namespace np_utils { + +NPPluginObjectFactory* NPPluginObjectFactory::factory_; + +PluginObject* NPPluginObjectFactory::CreatePluginObject( + NPP npp, + NPMIMEType plugin_type) { + return NULL; +} + +NPPluginObjectFactory::NPPluginObjectFactory() { + // Make this the first factory in the linked list. + previous_factory_ = factory_; + factory_ = this; +} + +NPPluginObjectFactory::~NPPluginObjectFactory() { + // Remove this factory from the linked list. + DCHECK(factory_ == this); + factory_ = previous_factory_; +} + +} // namespace np_utils diff --git a/gpu/np_utils/np_plugin_object_factory.h b/gpu/np_utils/np_plugin_object_factory.h new file mode 100644 index 0000000..969f5a3 --- /dev/null +++ b/gpu/np_utils/np_plugin_object_factory.h @@ -0,0 +1,37 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_H_ +#define GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_H_ + +#include "base/basictypes.h" +#include "gpu/np_utils/np_headers.h" + +namespace np_utils { + +class PluginObject; + +// Mockable factory base class used to create instances of PluginObject based on +// plugin mime type. +class NPPluginObjectFactory { + public: + virtual PluginObject* CreatePluginObject(NPP npp, NPMIMEType plugin_type); + + static NPPluginObjectFactory* get() { + return factory_; + } + + protected: + NPPluginObjectFactory(); + virtual ~NPPluginObjectFactory(); + + private: + static NPPluginObjectFactory* factory_; + NPPluginObjectFactory* previous_factory_; + DISALLOW_COPY_AND_ASSIGN(NPPluginObjectFactory); +}; + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_H_ diff --git a/gpu/np_utils/np_plugin_object_factory_mock.h b/gpu/np_utils/np_plugin_object_factory_mock.h new file mode 100644 index 0000000..a09205c --- /dev/null +++ b/gpu/np_utils/np_plugin_object_factory_mock.h @@ -0,0 +1,23 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_MOCK_H_ +#define GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_MOCK_H_ + +#include "gpu/np_utils/np_plugin_object_factory.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace np_utils { + +// Mockable factory used to create instances of PluginObject based on plugin +// mime type. +class MockPluginObjectFactory : public NPPluginObjectFactory { + public: + MOCK_METHOD2(CreatePluginObject, PluginObject*(NPP, NPMIMEType)); +}; + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_PLUGIN_OBJECT_FACTORY_MOCK_H_ diff --git a/gpu/np_utils/np_plugin_object_mock.h b/gpu/np_utils/np_plugin_object_mock.h new file mode 100644 index 0000000..342b22c --- /dev/null +++ b/gpu/np_utils/np_plugin_object_mock.h @@ -0,0 +1,26 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_PLUGIN_OBJECT_MOCK_H_ +#define GPU_NP_UTILS_NP_PLUGIN_OBJECT_MOCK_H_ + +#include "gpu/np_utils/np_plugin_object.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace np_utils { + +class MockPluginObject : public PluginObject { + public: + MOCK_METHOD5(New, NPError(NPMIMEType, int16, char*[], char*[], NPSavedData*)); + MOCK_METHOD1(SetWindow, NPError(NPWindow*)); + MOCK_METHOD1(HandleEvent, int16(NPEvent*)); + MOCK_METHOD1(Destroy, NPError(NPSavedData**)); + MOCK_METHOD0(Release, void()); + MOCK_METHOD0(GetScriptableNPObject, NPObject*()); +}; + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_PLUGIN_OBJECT_MOCK_H_ diff --git a/gpu/np_utils/np_utils.cc b/gpu/np_utils/np_utils.cc new file mode 100644 index 0000000..d6a15a4 --- /dev/null +++ b/gpu/np_utils/np_utils.cc @@ -0,0 +1,170 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/np_utils/np_utils.h" + +namespace np_utils { + +bool NPVariantToValue(bool* value, const NPVariant& variant) { + if (NPVARIANT_IS_BOOLEAN(variant)) { + *value = NPVARIANT_TO_BOOLEAN(variant); + return true; + } + + return false; +} + +bool NPVariantToValue(int32* value, const NPVariant& variant) { + if (NPVARIANT_IS_INT32(variant)) { + *value = NPVARIANT_TO_INT32(variant); + return true; + } + + return false; +} + +bool NPVariantToValue(float* value, const NPVariant& variant) { + if (NPVARIANT_IS_DOUBLE(variant)) { + *value = static_cast<float>(NPVARIANT_TO_DOUBLE(variant)); + return true; + } else if (NPVARIANT_IS_INT32(variant)) { + *value = static_cast<float>(NPVARIANT_TO_INT32(variant)); + return true; + } + + return false; +} + +bool NPVariantToValue(double* value, const NPVariant& variant) { + if (NPVARIANT_IS_DOUBLE(variant)) { + *value = NPVARIANT_TO_DOUBLE(variant); + return true; + } else if (NPVARIANT_IS_INT32(variant)) { + *value = NPVARIANT_TO_INT32(variant); + return true; + } + + return false; +} + +bool NPVariantToValue(std::string* value, const NPVariant& variant) { + if (NPVARIANT_IS_STRING(variant)) { + const NPString& str = NPVARIANT_TO_STRING(variant); + *value = std::string(str.UTF8Characters, str.UTF8Length); + return true; + } + + return false; +} + +void ValueToNPVariant(bool value, NPVariant* variant) { + BOOLEAN_TO_NPVARIANT(value, *variant); +} + +void ValueToNPVariant(int32 value, NPVariant* variant) { + INT32_TO_NPVARIANT(value, *variant); +} + +void ValueToNPVariant(float value, NPVariant* variant) { + DOUBLE_TO_NPVARIANT(value, *variant); +} + +void ValueToNPVariant(double value, NPVariant* variant) { + DOUBLE_TO_NPVARIANT(value, *variant); +} + +void ValueToNPVariant(const std::string& value, NPVariant* variant) { + NPUTF8* p = static_cast<NPUTF8*>(NPBrowser::get()->MemAlloc(value.length())); + memcpy(p, value.c_str(), value.length()); + STRINGN_TO_NPVARIANT(p, value.length(), *variant); +} + +SmartNPVariant::SmartNPVariant() { + VOID_TO_NPVARIANT(*this); +} + +SmartNPVariant::SmartNPVariant(const SmartNPVariant& rhs) { + rhs.CopyTo(this); +} + +SmartNPVariant::SmartNPVariant(const NPVariant& rhs) { + static_cast<const SmartNPVariant&>(rhs).CopyTo(this); +} + +SmartNPVariant::~SmartNPVariant() { + Release(); +} + +SmartNPVariant& SmartNPVariant::operator=(const SmartNPVariant& rhs) { + Release(); + rhs.CopyTo(this); + return *this; +} + +SmartNPVariant& SmartNPVariant::operator=(const NPVariant& rhs) { + Release(); + static_cast<const SmartNPVariant&>(rhs).CopyTo(this); + return *this; +} + +bool SmartNPVariant::IsVoid() const { + return NPVARIANT_IS_VOID(*this); +} + +void SmartNPVariant::Release() { + NPBrowser::get()->ReleaseVariantValue(this); + VOID_TO_NPVARIANT(*this); +} + +void SmartNPVariant::Invalidate() { + if (NPVARIANT_IS_OBJECT(*this)) { + NULL_TO_NPVARIANT(*this); + } +} + +void SmartNPVariant::CopyTo(NPVariant* rhs) const { + if (NPVARIANT_IS_OBJECT(*this)) { + NPObject* object = NPVARIANT_TO_OBJECT(*this); + OBJECT_TO_NPVARIANT(object, *rhs); + NPBrowser::get()->RetainObject(object); + } else if (NPVARIANT_IS_STRING(*this)) { + NPUTF8* copy = static_cast<NPUTF8*>(NPBrowser::get()->MemAlloc( + value.stringValue.UTF8Length)); + memcpy(copy, + value.stringValue.UTF8Characters, + value.stringValue.UTF8Length); + STRINGN_TO_NPVARIANT(copy, value.stringValue.UTF8Length, *rhs); + } else { + memcpy(rhs, this, sizeof(*rhs)); + } +} + +bool NPHasMethod(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name) { + return NPBrowser::get()->HasMethod( + npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name)); +} + +bool NPHasProperty(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name) { + return NPBrowser::get()->HasProperty( + npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name)); +} + +bool NPRemoveProperty(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name) { + return NPBrowser::get()->RemoveProperty( + npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name)); +} + +} // namespace np_utils diff --git a/gpu/np_utils/np_utils.h b/gpu/np_utils/np_utils.h new file mode 100644 index 0000000..5c7e3b7 --- /dev/null +++ b/gpu/np_utils/np_utils.h @@ -0,0 +1,271 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_NP_UTILS_H_ +#define GPU_NP_UTILS_NP_UTILS_H_ + +#include <string> + +#include "gpu/np_utils/np_browser.h" +#include "gpu/np_utils/np_class.h" +#include "gpu/np_utils/np_object_pointer.h" +#include "gpu/np_utils/np_headers.h" + +namespace np_utils { + +// Convert NPVariant to C++ type. Returns whether the conversion was successful. +bool NPVariantToValue(bool* value, const NPVariant& variant); +bool NPVariantToValue(int32* value, const NPVariant& variant); +bool NPVariantToValue(float* value, const NPVariant& variant); +bool NPVariantToValue(double* value, const NPVariant& variant); +bool NPVariantToValue(std::string* value, const NPVariant& variant); + +template <typename T> +bool NPVariantToValue(NPObjectPointer<T>* value, + const NPVariant& variant) { + if (NPVARIANT_IS_NULL(variant)) { + *value = NPObjectPointer<T>(); + return true; + } else if (NPVARIANT_IS_OBJECT(variant)) { + NPObject* object = NPVARIANT_TO_OBJECT(variant); + if (object->_class == NPGetClass<T>()) { + *value = NPObjectPointer<T>(static_cast<T*>( + NPVARIANT_TO_OBJECT(variant))); + return true; + } + } + + return false; +} + +// Specialization for NPObject does not check for mismatched NPClass. +template <> +inline bool NPVariantToValue(NPObjectPointer<NPObject>* value, + const NPVariant& variant) { + if (NPVARIANT_IS_NULL(variant)) { + *value = NPObjectPointer<NPObject>(); + return true; + } else if (NPVARIANT_IS_OBJECT(variant)) { + *value = NPObjectPointer<NPObject>(NPVARIANT_TO_OBJECT(variant)); + return true; + } + + return false; +} + +// Convert C++ type to NPVariant. +void ValueToNPVariant(bool value, NPVariant* variant); +void ValueToNPVariant(int32 value, NPVariant* variant); +void ValueToNPVariant(float value, NPVariant* variant); +void ValueToNPVariant(double value, NPVariant* variant); +void ValueToNPVariant(const std::string& value, NPVariant* variant); + +template <typename T> +void ValueToNPVariant(const NPObjectPointer<T>& value, + NPVariant* variant) { + if (value.Get()) { + NPBrowser::get()->RetainObject(value.Get()); + OBJECT_TO_NPVARIANT(value.Get(), *variant); + } else { + NULL_TO_NPVARIANT(*variant); + } +} + +// NPVariant that automatically manages lifetime of string and object variants. +class SmartNPVariant : public NPVariant { + public: + SmartNPVariant(); + SmartNPVariant(const SmartNPVariant& rhs); + explicit SmartNPVariant(const NPVariant& rhs); + + template <typename T> + explicit SmartNPVariant(const T& v) { + ValueToNPVariant(v, this); + } + + ~SmartNPVariant(); + + SmartNPVariant& operator=(const SmartNPVariant& rhs); + SmartNPVariant& operator=(const NPVariant& rhs); + + template <typename T> + bool GetValue(T* v) const { + return NPVariantToValue(v, *this); + } + + bool IsVoid() const; + + template <typename T> + void SetValue(const T& v) { + Release(); + ValueToNPVariant(v, this); + } + + void CopyTo(NPVariant* target) const; + + // Sets the variant to void. + void Release(); + + // Called when an NPObject is invalidated to clear any references to other + // NPObjects. Does not release the object as it might no longer be valid. + void Invalidate(); +}; + +// These allow a method to be invoked with automatic conversion of C++ +// types to variants for arguments and return values. + +bool NPHasMethod(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name); + +inline bool NPInvokeVoid(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name) { + SmartNPVariant result; + return NPBrowser::get()->Invoke( + npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name), + NULL, 0, + &result); +} + +template<typename R> +bool NPInvoke(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name, + R* r) { + SmartNPVariant result; + if (NPBrowser::get()->Invoke( + npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name), + NULL, 0, + &result)) { + return result.GetValue(r); + } + return false; +} + +template<typename P0> +bool NPInvokeVoid(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name, + P0 p0) { + SmartNPVariant args[1]; + args[0].SetValue(p0); + SmartNPVariant result; + return NPBrowser::get()->Invoke( + npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name), + &args[0], 1, + &result); +} + +template<typename R, typename P0> +bool NPInvoke(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name, + P0 p0, + R* r) { + SmartNPVariant args[1]; + args[0].SetValue(p0); + SmartNPVariant result; + if (NPBrowser::get()->Invoke( + npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name), + &args[0], 1, + &result)) { + return result.GetValue(r); + } + return false; +} + +template<typename P0, typename P1> +bool NPInvokeVoid(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name, + P0 p0, P1 p1) { + SmartNPVariant args[2]; + args[0].SetValue(p0); + args[1].SetValue(p1); + SmartNPVariant result; + return NPBrowser::get()->Invoke( + npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name), + &args[0], 2, + &result); +} + +template<typename R, typename P0, typename P1> +bool NPInvoke(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name, + P0 p0, P1 p1, + R* r) { + SmartNPVariant args[2]; + args[0].SetValue(p0); + args[1].SetValue(p1); + SmartNPVariant result; + if (NPBrowser::get()->Invoke( + npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name), + &args[0], 2, + &result)) { + return result.GetValue(r); + } + return false; +} + +bool NPHasProperty(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name); + +template <typename T> +bool NPGetProperty(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name, + T* value) { + SmartNPVariant result; + if (NPBrowser::get()->GetProperty(npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name), + &result)) { + return result.GetValue(value); + } + return false; +} + +template <typename T> +bool NPSetProperty(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name, + const T& value) { + SmartNPVariant variant(value); + return NPBrowser::get()->SetProperty( + npp, + object.Get(), + NPBrowser::get()->GetStringIdentifier(name), + &variant); +} + +bool NPRemoveProperty(NPP npp, + const NPObjectPointer<NPObject>& object, + const NPUTF8* name); + +template <typename NPObjectType> +NPObjectPointer<NPObjectType> NPCreateObject(NPP npp) { + const NPClass* np_class = NPGetClass<NPObjectType>(); + NPObjectType* object = static_cast<NPObjectType*>( + NPBrowser::get()->CreateObject(npp, np_class)); + return NPObjectPointer<NPObjectType>::FromReturned(object); +} + +} // namespace np_utils + +#endif // GPU_NP_UTILS_NP_UTILS_H_ diff --git a/gpu/np_utils/np_utils_unittest.cc b/gpu/np_utils/np_utils_unittest.cc new file mode 100644 index 0000000..ceb87ad --- /dev/null +++ b/gpu/np_utils/np_utils_unittest.cc @@ -0,0 +1,424 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/np_utils/np_object_mock.h" +#include "gpu/np_utils/np_browser_stub.h" +#include "gpu/np_utils/np_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::DoAll; +using testing::MakeMatcher; +using testing::Matcher; +using testing::Pointee; +using testing::Return; +using testing::SetArgumentPointee; +using testing::StrictMock; + +namespace np_utils { + +class NPUtilsTest : public testing::Test { + protected: + StubNPBrowser stub_browser_; + NPP_t npp_; + NPVariant variant_; +}; + +TEST_F(NPUtilsTest, TestBoolNPVariantToValue) { + bool v; + + BOOLEAN_TO_NPVARIANT(false, variant_); + EXPECT_TRUE(NPVariantToValue(&v, variant_)); + EXPECT_FALSE(v); + + BOOLEAN_TO_NPVARIANT(true, variant_); + EXPECT_TRUE(NPVariantToValue(&v, variant_)); + EXPECT_TRUE(v); + + INT32_TO_NPVARIANT(7, variant_); + EXPECT_FALSE(NPVariantToValue(&v, variant_)); +} + +TEST_F(NPUtilsTest, TestIntNPVariantToValue) { + INT32_TO_NPVARIANT(7, variant_); + + int v1; + EXPECT_TRUE(NPVariantToValue(&v1, variant_)); + EXPECT_EQ(7, v1); + + float v2; + EXPECT_TRUE(NPVariantToValue(&v2, variant_)); + EXPECT_EQ(7.0f, v2); + + double v3; + EXPECT_TRUE(NPVariantToValue(&v3, variant_)); + EXPECT_EQ(7.0, v3); + + BOOLEAN_TO_NPVARIANT(false, variant_); + EXPECT_FALSE(NPVariantToValue(&v1, variant_)); +} + +TEST_F(NPUtilsTest, TestFloatNPVariantToValue) { + float v; + + DOUBLE_TO_NPVARIANT(7.0, variant_); + EXPECT_TRUE(NPVariantToValue(&v, variant_)); + EXPECT_EQ(7.0f, v); + + BOOLEAN_TO_NPVARIANT(false, variant_); + EXPECT_FALSE(NPVariantToValue(&v, variant_)); +} + +TEST_F(NPUtilsTest, TestDoubleNPVariantToValue) { + double v; + + DOUBLE_TO_NPVARIANT(7.0, variant_); + EXPECT_TRUE(NPVariantToValue(&v, variant_)); + EXPECT_EQ(7.0, v); + + BOOLEAN_TO_NPVARIANT(false, variant_); + EXPECT_FALSE(NPVariantToValue(&v, variant_)); +} + +TEST_F(NPUtilsTest, TestStringNPVariantToValue) { + std::string v; + + STRINGZ_TO_NPVARIANT("hello", variant_); + EXPECT_TRUE(NPVariantToValue(&v, variant_)); + EXPECT_EQ(std::string("hello"), v); + + BOOLEAN_TO_NPVARIANT(false, variant_); + EXPECT_FALSE(NPVariantToValue(&v, variant_)); +} + +TEST_F(NPUtilsTest, TestObjectNPVariantToValue) { + NPObjectPointer<NPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + NPObjectPointer<NPObject> v; + + OBJECT_TO_NPVARIANT(object.Get(), variant_); + EXPECT_TRUE(NPVariantToValue(&v, variant_)); + EXPECT_EQ(object, v); + + BOOLEAN_TO_NPVARIANT(false, variant_); + EXPECT_FALSE(NPVariantToValue(&v, variant_)); +} + +TEST_F(NPUtilsTest, TestNullNPVariantToValue) { + NPObjectPointer<NPObject> v; + + NULL_TO_NPVARIANT(variant_); + EXPECT_TRUE(NPVariantToValue(&v, variant_)); + EXPECT_TRUE(NPObjectPointer<NPObject>() == v); + + BOOLEAN_TO_NPVARIANT(false, variant_); + EXPECT_FALSE(NPVariantToValue(&v, variant_)); +} + +TEST_F(NPUtilsTest, TestDerivedObjectNPVariantToValue) { + NPObjectPointer<NPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + NPObjectPointer<StrictMock<MockNPObject> > v; + + OBJECT_TO_NPVARIANT(object.Get(), variant_); + EXPECT_TRUE(NPVariantToValue(&v, variant_)); + EXPECT_EQ(object, v); +} + +TEST_F(NPUtilsTest, + TestDerivedObjectNPVariantToValueFailsIfValueHasDifferentType) { + NPObjectPointer<NPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + NPObjectPointer<MockNPObject> v; + + OBJECT_TO_NPVARIANT(object.Get(), variant_); + EXPECT_FALSE(NPVariantToValue(&v, variant_)); +} + +TEST_F(NPUtilsTest, TestBoolValueToNPVariant) { + ValueToNPVariant(true, &variant_); + EXPECT_TRUE(NPVARIANT_IS_BOOLEAN(variant_)); + EXPECT_TRUE(NPVARIANT_TO_BOOLEAN(variant_)); + + ValueToNPVariant(false, &variant_); + EXPECT_TRUE(NPVARIANT_IS_BOOLEAN(variant_)); + EXPECT_FALSE(NPVARIANT_TO_BOOLEAN(variant_)); +} + +TEST_F(NPUtilsTest, TestIntValueToNPVariant) { + ValueToNPVariant(7, &variant_); + EXPECT_TRUE(NPVARIANT_IS_INT32(variant_)); + EXPECT_EQ(7, NPVARIANT_TO_INT32(variant_)); +} + +TEST_F(NPUtilsTest, TestFloatValueToNPVariant) { + ValueToNPVariant(7.0f, &variant_); + EXPECT_TRUE(NPVARIANT_IS_DOUBLE(variant_)); + EXPECT_EQ(7.0, NPVARIANT_TO_DOUBLE(variant_)); +} + +TEST_F(NPUtilsTest, TestDoubleValueToNPVariant) { + ValueToNPVariant(7.0, &variant_); + EXPECT_TRUE(NPVARIANT_IS_DOUBLE(variant_)); + EXPECT_EQ(7.0, NPVARIANT_TO_DOUBLE(variant_)); +} + +TEST_F(NPUtilsTest, TestStringValueToNPVariant) { + ValueToNPVariant(std::string("hello"), &variant_); + EXPECT_TRUE(NPVARIANT_IS_STRING(variant_)); + EXPECT_EQ(std::string("hello"), + std::string(variant_.value.stringValue.UTF8Characters, + variant_.value.stringValue.UTF8Length)); +} + +TEST_F(NPUtilsTest, TestObjectValueToNPVariant) { + NPObjectPointer<NPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + ValueToNPVariant(object, &variant_); + EXPECT_TRUE(NPVARIANT_IS_OBJECT(variant_)); + EXPECT_EQ(object.Get(), NPVARIANT_TO_OBJECT(variant_)); + + NPBrowser::get()->ReleaseVariantValue(&variant_); +} + +TEST_F(NPUtilsTest, TestNullValueToNPVariant) { + ValueToNPVariant(NPObjectPointer<NPObject>(), &variant_); + EXPECT_TRUE(NPVARIANT_IS_NULL(variant_)); +} + +TEST_F(NPUtilsTest, CanCopyObjectSmartVariant) { + NPObjectPointer<NPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + EXPECT_EQ(1, object->referenceCount); + { + SmartNPVariant v1(object); + EXPECT_EQ(2, object->referenceCount); + { + SmartNPVariant v2(v1); + EXPECT_EQ(3, object->referenceCount); + } + EXPECT_EQ(2, object->referenceCount); + } + EXPECT_EQ(1, object->referenceCount); +} + +TEST_F(NPUtilsTest, CanCopyStringSmartVariant) { + SmartNPVariant v1(std::string("hello")); + SmartNPVariant v2(v1); + std::string r; + EXPECT_TRUE(NPVariantToValue(&r, v2)); + EXPECT_EQ(std::string("hello"), r); + EXPECT_NE(v1.value.stringValue.UTF8Characters, + v2.value.stringValue.UTF8Characters); +} + +TEST_F(NPUtilsTest, CanReleaseSmartVariant) { + SmartNPVariant variant(std::string("hello")); + EXPECT_FALSE(variant.IsVoid()); + variant.Release(); + EXPECT_TRUE(variant.IsVoid()); +} + +template <typename T> +class VariantMatcher : public testing::MatcherInterface<const NPVariant&> { + public: + explicit VariantMatcher(const T& value) : value_(value) { + } + + virtual bool Matches(const NPVariant& variant) const { + T other_value; + return NPVariantToValue(&other_value, variant) && other_value == value_; + } + + virtual void DescribeTo(::std::ostream* os) const { + *os << "equals " << value_; + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "does not equal " << value_; + } + + private: + T value_; +}; + +template <typename T> +Matcher<const NPVariant&> VariantMatches(const T& value) { + return MakeMatcher(new VariantMatcher<T>(value)); +} + +TEST_F(NPUtilsTest, CanDetermineIfObjectHasMethod) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + EXPECT_CALL(*object, HasMethod(name)) + .WillOnce(Return(true)); + + EXPECT_TRUE(NPHasMethod(NULL, object, "foo")); +} + +TEST_F(NPUtilsTest, CanInvokeVoidMethodWithNativeTypes) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + VOID_TO_NPVARIANT(variant_); + + EXPECT_CALL(*object, Invoke(name, Pointee(VariantMatches<int32>(7)), 1, _)) + .WillOnce(DoAll(SetArgumentPointee<3>(variant_), + Return(true))); + + EXPECT_TRUE(NPInvokeVoid(NULL, object, "foo", 7)); +} + +TEST_F(NPUtilsTest, InvokeVoidMethodCanFail) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + VOID_TO_NPVARIANT(variant_); + + EXPECT_CALL(*object, Invoke(name, Pointee(VariantMatches<int32>(7)), 1, _)) + .WillOnce(DoAll(SetArgumentPointee<3>(variant_), + Return(false))); + + EXPECT_FALSE(NPInvokeVoid(NULL, object, "foo", 7)); +} + +TEST_F(NPUtilsTest, CanInvokeNonVoidMethodWithNativeTypes) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + DOUBLE_TO_NPVARIANT(1.5, variant_); + + EXPECT_CALL(*object, Invoke(name, Pointee(VariantMatches<int32>(7)), 1, _)) + .WillOnce(DoAll(SetArgumentPointee<3>(variant_), + Return(true))); + + double r; + EXPECT_TRUE(NPInvoke(NULL, object, "foo", 7, &r)); + EXPECT_EQ(1.5, r); +} + +TEST_F(NPUtilsTest, InvokeNonVoidMethodCanFail) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + DOUBLE_TO_NPVARIANT(1.5, variant_); + + EXPECT_CALL(*object, Invoke(name, Pointee(VariantMatches<int32>(7)), 1, _)) + .WillOnce(DoAll(SetArgumentPointee<3>(variant_), + Return(false))); + + double r; + EXPECT_FALSE(NPInvoke(NULL, object, "foo", 7, &r)); +} + +TEST_F(NPUtilsTest, InvokeNonVoidMethodFailsIfResultIsIncompatible) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + DOUBLE_TO_NPVARIANT(1.5, variant_); + + EXPECT_CALL(*object, Invoke(name, Pointee(VariantMatches<int32>(7)), 1, _)) + .WillOnce(DoAll(SetArgumentPointee<3>(variant_), + Return(true))); + + int r; + EXPECT_FALSE(NPInvoke(NULL, object, "foo", 7, &r)); +} + +TEST_F(NPUtilsTest, CanDetermineIfObjectHasProperty) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + EXPECT_CALL(*object, HasProperty(name)) + .WillOnce(Return(true)); + + EXPECT_TRUE(NPHasProperty(NULL, object, "foo")); +} + +TEST_F(NPUtilsTest, CanGetPropertyValue) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + DOUBLE_TO_NPVARIANT(1.5, variant_); + + EXPECT_CALL(*object, GetProperty(name, _)) + .WillOnce(DoAll(SetArgumentPointee<1>(variant_), + Return(true))); + + double r; + EXPECT_TRUE(NPGetProperty(NULL, object, "foo", &r)); +} + +TEST_F(NPUtilsTest, NPGetPropertyReportsFailureIfResultTypeIsDifferent) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + DOUBLE_TO_NPVARIANT(1.5, variant_); + + EXPECT_CALL(*object, GetProperty(name, _)) + .WillOnce(DoAll(SetArgumentPointee<1>(variant_), + Return(true))); + + bool r; + EXPECT_FALSE(NPGetProperty(NULL, object, "foo", &r)); +} + +TEST_F(NPUtilsTest, NPGetPropertyReportsFailureFromGetProperty) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + EXPECT_CALL(*object, GetProperty(name, _)) + .WillOnce(Return(false)); + + double r; + EXPECT_FALSE(NPGetProperty(NULL, object, "foo", &r)); +} + +TEST_F(NPUtilsTest, CanSetPropertyValue) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + EXPECT_CALL(*object, SetProperty(name, Pointee(VariantMatches(1.5)))) + .WillOnce(Return(true)); + + EXPECT_TRUE(NPSetProperty(NULL, object, "foo", 1.5)); +} + +TEST_F(NPUtilsTest, NPSetPropertyReportsFailureFromSetProperty) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + EXPECT_CALL(*object, SetProperty(name, Pointee(VariantMatches(1.5)))) + .WillOnce(Return(false)); + + EXPECT_FALSE(NPSetProperty(NULL, object, "foo", 1.5)); +} + +TEST_F(NPUtilsTest, CanRemovePropertyValue) { + NPIdentifier name = NPBrowser::get()->GetStringIdentifier("foo"); + NPObjectPointer<MockNPObject> object = + NPCreateObject<StrictMock<MockNPObject> >(NULL); + + EXPECT_CALL(*object, RemoveProperty(name)) + .WillOnce(Return(true)); + + EXPECT_TRUE(NPRemoveProperty(NULL, object, "foo")); +} + +} // namespace np_utils diff --git a/gpu/np_utils/webkit_browser.h b/gpu/np_utils/webkit_browser.h new file mode 100644 index 0000000..6b57d05 --- /dev/null +++ b/gpu/np_utils/webkit_browser.h @@ -0,0 +1,117 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_NP_UTILS_WEBKIT_BROWSER_H_ +#define GPU_NP_UTILS_WEBKIT_BROWSER_H_ + +// TODO(apatrick): This does not belong in np_utils. np_utils should not be +// dependent on WebKit (and it isn't - that's why the member functions are +// inline). + +#include <stdlib.h> + +#include "gpu/np_utils/np_browser.h" +#include "WebKit/api/public/WebBindings.h" + +typedef struct _NPNetscapeFuncs NPNetscapeFuncs; +typedef struct _NPChromiumFuncs NPChromiumFuncs; + +namespace np_utils { + +// This class implements NPBrowser for the WebKit WebBindings. +class WebKitBrowser : public NPBrowser { + public: + WebKitBrowser(): NPBrowser(NULL) { + } + + // Standard functions from NPNetscapeFuncs. + + virtual NPIdentifier GetStringIdentifier(const NPUTF8* name) { + return WebKit::WebBindings::getStringIdentifier(name); + } + + virtual void* MemAlloc(size_t size) { + return malloc(size); + } + + virtual void MemFree(void* p) { + free(p); + } + + virtual NPObject* CreateObject(NPP npp, const NPClass* cl) { + return WebKit::WebBindings::createObject(npp, const_cast<NPClass*>(cl)); + } + + virtual NPObject* RetainObject(NPObject* object) { + return WebKit::WebBindings::retainObject(object); + } + + virtual void ReleaseObject(NPObject* object) { + WebKit::WebBindings::releaseObject(object); + } + + virtual void ReleaseVariantValue(NPVariant* variant) { + WebKit::WebBindings::releaseVariantValue(variant); + } + + virtual bool HasProperty(NPP npp, + NPObject* object, + NPIdentifier name) { + return WebKit::WebBindings::hasProperty(npp, object, name); + } + + virtual bool GetProperty(NPP npp, + NPObject* object, + NPIdentifier name, + NPVariant* result) { + return WebKit::WebBindings::getProperty(npp, object, name, result); + } + + virtual bool SetProperty(NPP npp, + NPObject* object, + NPIdentifier name, + const NPVariant* result) { + return WebKit::WebBindings::setProperty(npp, object, name, result); + } + + virtual bool RemoveProperty(NPP npp, + NPObject* object, + NPIdentifier name) { + return WebKit::WebBindings::removeProperty(npp, object, name); + } + + virtual bool HasMethod(NPP npp, + NPObject* object, + NPIdentifier name) { + return WebKit::WebBindings::hasMethod(npp, object, name); + } + + virtual bool Invoke(NPP npp, + NPObject* object, + NPIdentifier name, + const NPVariant* args, + uint32_t num_args, + NPVariant* result) { + return WebKit::WebBindings::invoke(npp, object, name, args, num_args, + result); + } + + virtual NPObject* GetWindowNPObject(NPP npp) { + NPObject* window; + if (NPERR_NO_ERROR == NPN_GetValue(npp, + NPNVWindowNPObject, + &window)) { + return window; + } else { + return NULL; + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(WebKitBrowser); +}; + +} // namespace np_utils + +#endif // GPU_NP_UTILS_WEBKIT_BROWSER_H_ |