summaryrefslogtreecommitdiffstats
path: root/gpu/gpu_plugin
diff options
context:
space:
mode:
authorapatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-24 19:34:24 +0000
committerapatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-24 19:34:24 +0000
commit97632e2039e3ec0b9342f5e7c074bf631c738a9f (patch)
tree71e51bad650961671a0aa96b433403fc5a8ff544 /gpu/gpu_plugin
parentd4edbe5e406c5773d66d65214b963ed474b34cf4 (diff)
downloadchromium_src-97632e2039e3ec0b9342f5e7c074bf631c738a9f.zip
chromium_src-97632e2039e3ec0b9342f5e7c074bf631c738a9f.tar.gz
chromium_src-97632e2039e3ec0b9342f5e7c074bf631c738a9f.tar.bz2
Branched gpu process and command buffer code into Chrome tree. Fixed up paths and other minor changes to make it work in the Chrome tree. Will remove copy from O3D tree shortly. Only works in Windows currently.
TEST=none BUG=none Review URL: http://codereview.chromium.org/436017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32952 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/gpu_plugin')
-rw-r--r--gpu/gpu_plugin/gpu_plugin.cc135
-rw-r--r--gpu/gpu_plugin/gpu_plugin.h30
-rw-r--r--gpu/gpu_plugin/gpu_plugin_object.cc123
-rw-r--r--gpu/gpu_plugin/gpu_plugin_object.h133
-rw-r--r--gpu/gpu_plugin/gpu_plugin_object_factory.cc27
-rw-r--r--gpu/gpu_plugin/gpu_plugin_object_factory.h27
-rw-r--r--gpu/gpu_plugin/gpu_plugin_object_factory_unittest.cc41
-rw-r--r--gpu/gpu_plugin/gpu_plugin_object_unittest.cc319
-rw-r--r--gpu/gpu_plugin/gpu_plugin_object_win.cc62
-rw-r--r--gpu/gpu_plugin/gpu_plugin_unittest.cc302
10 files changed, 1199 insertions, 0 deletions
diff --git a/gpu/gpu_plugin/gpu_plugin.cc b/gpu/gpu_plugin/gpu_plugin.cc
new file mode 100644
index 0000000..35771fd
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin.cc
@@ -0,0 +1,135 @@
+// 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.h"
+#include "gpu/gpu_plugin/gpu_plugin_object_factory.h"
+#include "gpu/np_utils/np_browser.h"
+#include "gpu/np_utils/np_plugin_object.h"
+#include "gpu/np_utils/np_plugin_object_factory.h"
+#include "webkit/glue/plugins/nphostapi.h"
+
+using np_utils::NPBrowser;
+using np_utils::NPPluginObjectFactory;
+using np_utils::PluginObject;
+
+namespace gpu_plugin {
+
+// Definitions of NPAPI plugin entry points.
+
+namespace {
+NPBrowser* g_browser;
+GPUPluginObjectFactory g_plugin_object_factory;
+
+NPError NPP_New(NPMIMEType plugin_type, NPP instance,
+ uint16 mode, int16 argc, char* argn[],
+ char* argv[], NPSavedData* saved) {
+ if (!instance)
+ return NPERR_INVALID_INSTANCE_ERROR;
+
+ PluginObject* plugin_object =
+ NPPluginObjectFactory::get()->CreatePluginObject(instance, plugin_type);
+ if (!plugin_object)
+ return NPERR_GENERIC_ERROR;
+
+ instance->pdata = plugin_object;
+
+ NPError error = plugin_object->New(plugin_type, argc, argn, argv, saved);
+ if (error != NPERR_NO_ERROR) {
+ plugin_object->Release();
+ }
+
+ return error;
+}
+
+NPError NPP_Destroy(NPP instance, NPSavedData** saved) {
+ if (!instance)
+ return NPERR_INVALID_INSTANCE_ERROR;
+
+ PluginObject* plugin_object = static_cast<PluginObject*>(instance->pdata);
+ NPError error = plugin_object->Destroy(saved);
+
+ if (error == NPERR_NO_ERROR) {
+ plugin_object->Release();
+ }
+
+ return error;
+}
+
+NPError NPP_SetWindow(NPP instance, NPWindow* window) {
+ if (!instance)
+ return NPERR_INVALID_INSTANCE_ERROR;
+
+ PluginObject* plugin_object = static_cast<PluginObject*>(instance->pdata);
+ return plugin_object->SetWindow(window);
+}
+
+int16 NPP_HandleEvent(NPP instance, void* event) {
+ if (!instance)
+ return 0;
+
+ PluginObject* plugin_object = static_cast<PluginObject*>(instance->pdata);
+ return plugin_object->HandleEvent(static_cast<NPEvent*>(event));
+}
+
+NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
+ if (!instance)
+ return NPERR_INVALID_INSTANCE_ERROR;
+
+ PluginObject* plugin_object = static_cast<PluginObject*>(instance->pdata);
+ switch (variable) {
+ case NPPVpluginScriptableNPObject:
+ *reinterpret_cast<NPObject**>(value) =
+ plugin_object->GetScriptableNPObject();
+ return NPERR_NO_ERROR;
+ default:
+ return NPERR_GENERIC_ERROR;
+ }
+}
+
+NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
+ return NPERR_NO_ERROR;
+}
+}
+
+NPError NP_GetEntryPoints(NPPluginFuncs* funcs) {
+ funcs->newp = NPP_New;
+ funcs->destroy = NPP_Destroy;
+ funcs->setwindow = NPP_SetWindow;
+ funcs->event = NPP_HandleEvent;
+ funcs->getvalue = NPP_GetValue;
+ funcs->setvalue = NPP_SetValue;
+ return NPERR_NO_ERROR;
+}
+
+#if defined(OS_LINUX)
+NPError API_CALL NP_Initialize(NPNetscapeFuncs *browser_funcs,
+ NPPluginFuncs* plugin_funcs) {
+#else
+NPError NP_Initialize(NPNetscapeFuncs *browser_funcs) {
+#endif
+ if (!browser_funcs)
+ return NPERR_INVALID_FUNCTABLE_ERROR;
+
+ if (g_browser)
+ return NPERR_GENERIC_ERROR;
+
+#if defined(OS_LINUX)
+ NP_GetEntryPoints(plugin_funcs);
+#endif
+
+ g_browser = new NPBrowser(browser_funcs);
+
+ return NPERR_NO_ERROR;
+}
+
+NPError NP_Shutdown() {
+ if (!g_browser)
+ return NPERR_GENERIC_ERROR;
+
+ delete g_browser;
+ g_browser = NULL;
+
+ return NPERR_NO_ERROR;
+}
+} // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin.h b/gpu/gpu_plugin/gpu_plugin.h
new file mode 100644
index 0000000..0f90f77
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin.h
@@ -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.
+
+#ifndef GPU_GPU_PLUGIN_GPU_PLUGIN_H_
+#define GPU_GPU_PLUGIN_GPU_PLUGIN_H_
+
+#include "gpu/np_utils/np_headers.h"
+
+typedef struct _NPPluginFuncs NPPluginFuncs;
+typedef struct _NPNetscapeFuncs NPNetscapeFuncs;
+
+namespace gpu_plugin {
+
+// Declarations of NPAPI plugin entry points.
+
+NPError NP_GetEntryPoints(NPPluginFuncs* funcs);
+
+#if defined(OS_LINUX)
+NPError NP_Initialize(NPNetscapeFuncs *browser_funcs,
+ NPPluginFuncs* plugin_funcs);
+#else
+NPError NP_Initialize(NPNetscapeFuncs* browser_funcs);
+#endif
+
+NPError NP_Shutdown();
+
+} // namespace gpu_plugin
+
+#endif // GPU_GPU_PLUGIN_GPU_PLUGIN_H_
diff --git a/gpu/gpu_plugin/gpu_plugin_object.cc b/gpu/gpu_plugin/gpu_plugin_object.cc
new file mode 100644
index 0000000..d4ea9150
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object.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 <stdlib.h>
+
+#include "base/logging.h"
+#include "gpu/command_buffer/service/command_buffer_service.h"
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/np_utils/np_utils.h"
+#include "gpu/gpu_plugin/gpu_plugin_object.h"
+
+using ::base::SharedMemory;
+using command_buffer::CommandBuffer;
+using command_buffer::CommandBufferService;
+using command_buffer::GPUProcessor;
+using np_utils::NPBrowser;
+using np_utils::NPObjectPointer;
+
+namespace gpu_plugin {
+
+const NPUTF8 GPUPluginObject::kPluginType[] =
+ "application/vnd.google.chrome.gpu-plugin";
+
+GPUPluginObject::GPUPluginObject(NPP npp)
+ : npp_(npp),
+ status_(kWaitingForNew),
+ command_buffer_(new CommandBufferService),
+ processor_(new GPUProcessor(npp, command_buffer_.get())) {
+ memset(&window_, 0, sizeof(window_));
+}
+
+NPError GPUPluginObject::New(NPMIMEType plugin_type,
+ int16 argc,
+ char* argn[],
+ char* argv[],
+ NPSavedData* saved) {
+ if (status_ != kWaitingForNew)
+ return NPERR_GENERIC_ERROR;
+
+ status_ = kWaitingForSetWindow;
+
+ return NPERR_NO_ERROR;
+}
+
+NPError GPUPluginObject::SetWindow(NPWindow* new_window) {
+ if (status_ == kWaitingForNew || status_ == kDestroyed)
+ return NPERR_GENERIC_ERROR;
+
+ // PlatformSpecificSetWindow advances the status depending on what happens.
+ NPError error = PlatformSpecificSetWindow(new_window);
+ if (error == NPERR_NO_ERROR) {
+ window_ = *new_window;
+
+ if (event_sync_.Get()) {
+ NPInvokeVoid(npp_,
+ event_sync_,
+ "resize",
+ static_cast<int32>(window_.width),
+ static_cast<int32>(window_.height));
+ }
+ } else {
+ memset(&window_, 0, sizeof(window_));
+ }
+
+ return error;
+}
+
+int16 GPUPluginObject::HandleEvent(NPEvent* event) {
+ return 0;
+}
+
+NPError GPUPluginObject::Destroy(NPSavedData** saved) {
+ if (status_ == kWaitingForNew || status_ == kDestroyed)
+ return NPERR_GENERIC_ERROR;
+
+ if (command_buffer_.get()) {
+ command_buffer_->SetPutOffsetChangeCallback(NULL);
+ }
+
+ status_ = kDestroyed;
+
+ return NPERR_NO_ERROR;
+}
+
+void GPUPluginObject::Release() {
+ DCHECK(status_ == kWaitingForNew || status_ == kDestroyed);
+ NPBrowser::get()->ReleaseObject(this);
+}
+
+NPObject*GPUPluginObject::GetScriptableNPObject() {
+ NPBrowser::get()->RetainObject(this);
+ return this;
+}
+
+CommandBuffer* GPUPluginObject::OpenCommandBuffer() {
+ if (status_ == kInitializationSuccessful)
+ return command_buffer_.get();
+
+ // SetWindow must have been called before OpenCommandBuffer.
+ // PlatformSpecificSetWindow advances the status to
+ // kWaitingForOpenCommandBuffer.
+ if (status_ != kWaitingForOpenCommandBuffer)
+ return NULL;
+
+ scoped_ptr<SharedMemory> ring_buffer(new SharedMemory);
+ if (!ring_buffer->Create(std::wstring(), false, false, kCommandBufferSize))
+ return NULL;
+
+ if (command_buffer_->Initialize(ring_buffer.release())) {
+ if (processor_->Initialize(static_cast<HWND>(window_.window))) {
+ command_buffer_->SetPutOffsetChangeCallback(
+ NewCallback(processor_.get(),
+ &GPUProcessor::ProcessCommands));
+ status_ = kInitializationSuccessful;
+ return command_buffer_.get();
+ }
+ }
+
+ return NULL;
+}
+
+} // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin_object.h b/gpu/gpu_plugin/gpu_plugin_object.h
new file mode 100644
index 0000000..0602aa9
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object.h
@@ -0,0 +1,133 @@
+// 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_GPU_PLUGIN_GPU_PLUGIN_OBJECT_H_
+#define GPU_GPU_PLUGIN_GPU_PLUGIN_OBJECT_H_
+
+#include <string>
+
+#include "base/ref_counted.h"
+#include "base/thread.h"
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/np_utils/default_np_object.h"
+#include "gpu/np_utils/np_dispatcher.h"
+#include "gpu/np_utils/np_headers.h"
+#include "gpu/np_utils/np_plugin_object.h"
+#include "gpu/np_utils/np_utils.h"
+
+namespace gpu_plugin {
+
+// The scriptable object for the GPU plugin.
+class GPUPluginObject : public np_utils::DefaultNPObject<NPObject>,
+ public np_utils::PluginObject {
+ public:
+ static const int32 kCommandBufferSize = 1024 * 1024;
+
+ enum Status {
+ // In the state of waiting for the named function to be called to continue
+ // the initialization sequence.
+ kWaitingForNew,
+ kWaitingForSetWindow,
+ kWaitingForOpenCommandBuffer,
+
+ // Initialization either succeeded or failed.
+ kInitializationSuccessful,
+ kInitializationFailed,
+
+ // Destroy has now been called and the plugin object cannot be used.
+ kDestroyed,
+ };
+
+ static const NPUTF8 kPluginType[];
+
+ explicit GPUPluginObject(NPP npp);
+
+ virtual NPError New(NPMIMEType plugin_type,
+ int16 argc,
+ char* argn[],
+ char* argv[],
+ NPSavedData* saved);
+
+ virtual NPError SetWindow(NPWindow* new_window);
+ const NPWindow& GetWindow() { return window_; }
+
+ virtual int16 HandleEvent(NPEvent* event);
+
+ virtual NPError Destroy(NPSavedData** saved);
+
+ virtual void Release();
+
+ virtual NPObject* GetScriptableNPObject();
+
+ // Returns the current initialization status. See Status enum.
+ int32 GetStatus() {
+ return status_;
+ }
+
+ // Get the width of the plugin window.
+ int32 GetWidth() {
+ return window_.width;
+ }
+
+ // Get the height of the plugin window.
+ int32 GetHeight() {
+ return window_.height;
+ }
+
+ // Set the object that receives notifications of GPU plugin object events
+ // such as resize and keyboard and mouse input.
+ void SetEventSync(np_utils::NPObjectPointer<NPObject> event_sync) {
+ event_sync_ = event_sync;
+ }
+
+ np_utils::NPObjectPointer<NPObject> GetEventSync() {
+ return event_sync_;
+ }
+
+ // Initializes and returns the command buffer object. Returns NULL if the
+ // command buffer cannot be initialized, for example if the plugin does not
+ // yet have a window handle.
+ command_buffer::CommandBuffer* OpenCommandBuffer();
+
+ // Set the status for testing.
+ void set_status(Status status) {
+ status_ = status;
+ }
+
+ // Replace the default command buffer for testing. Takes ownership.
+ void set_command_buffer(command_buffer::CommandBuffer*
+ command_buffer) {
+ command_buffer_.reset(command_buffer);
+ }
+
+ // Replace the default GPU processor for testing.
+ void set_gpu_processor(
+ const scoped_refptr<command_buffer::GPUProcessor>& processor) {
+ processor_ = processor;
+ }
+
+ NP_UTILS_BEGIN_DISPATCHER_CHAIN(GPUPluginObject, DefaultNPObject<NPObject>)
+ NP_UTILS_DISPATCHER(GetStatus, int32())
+ NP_UTILS_DISPATCHER(GetWidth, int32())
+ NP_UTILS_DISPATCHER(GetHeight, int32())
+ NP_UTILS_DISPATCHER(SetEventSync,
+ void(np_utils::NPObjectPointer<NPObject> sync))
+ NP_UTILS_DISPATCHER(GetEventSync, np_utils::NPObjectPointer<NPObject>())
+ NP_UTILS_END_DISPATCHER_CHAIN
+
+ private:
+ NPError PlatformSpecificSetWindow(NPWindow* new_window);
+
+ NPP npp_;
+ Status status_;
+ NPWindow window_;
+ scoped_ptr<command_buffer::CommandBuffer> command_buffer_;
+ scoped_refptr<command_buffer::GPUProcessor> processor_;
+ np_utils::NPObjectPointer<NPObject> event_sync_;
+};
+
+} // namespace gpu_plugin
+
+#endif // GPU_GPU_PLUGIN_GPU_PLUGIN_OBJECT_H_
diff --git a/gpu/gpu_plugin/gpu_plugin_object_factory.cc b/gpu/gpu_plugin/gpu_plugin_object_factory.cc
new file mode 100644
index 0000000..da9e17a
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object_factory.cc
@@ -0,0 +1,27 @@
+// 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.h"
+#include "gpu/gpu_plugin/gpu_plugin_object_factory.h"
+#include "gpu/np_utils/np_utils.h"
+
+namespace gpu_plugin {
+
+GPUPluginObjectFactory::GPUPluginObjectFactory() {
+}
+
+GPUPluginObjectFactory::~GPUPluginObjectFactory() {
+}
+
+np_utils::PluginObject* GPUPluginObjectFactory::CreatePluginObject(
+ NPP npp,
+ NPMIMEType plugin_type) {
+ if (strcmp(plugin_type, GPUPluginObject::kPluginType) == 0) {
+ return np_utils::NPCreateObject<GPUPluginObject>(npp).ToReturned();
+ }
+
+ return NULL;
+}
+
+} // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin_object_factory.h b/gpu/gpu_plugin/gpu_plugin_object_factory.h
new file mode 100644
index 0000000..0d1d80e
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object_factory.h
@@ -0,0 +1,27 @@
+// 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_GPU_PLUGIN_GPU_PLUGIN_OBJECT_FACTORY_H_
+#define GPU_GPU_PLUGIN_GPU_PLUGIN_OBJECT_FACTORY_H_
+
+#include "gpu/np_utils/np_plugin_object_factory.h"
+
+namespace gpu_plugin {
+
+// Plugin object factory for creating the GPUPluginObject.
+class GPUPluginObjectFactory : public np_utils::NPPluginObjectFactory {
+ public:
+ GPUPluginObjectFactory();
+ virtual ~GPUPluginObjectFactory();
+
+ virtual np_utils::PluginObject* CreatePluginObject(NPP npp,
+ NPMIMEType plugin_type);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GPUPluginObjectFactory);
+};
+
+} // namespace gpu_plugin
+
+#endif // GPU_GPU_PLUGIN_GPU_PLUGIN_OBJECT_FACTORY_H_
diff --git a/gpu/gpu_plugin/gpu_plugin_object_factory_unittest.cc b/gpu/gpu_plugin/gpu_plugin_object_factory_unittest.cc
new file mode 100644
index 0000000..298a8c5
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object_factory_unittest.cc
@@ -0,0 +1,41 @@
+// 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.h"
+#include "gpu/gpu_plugin/gpu_plugin_object_factory.h"
+#include "gpu/np_utils/np_browser_stub.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using np_utils::PluginObject;
+
+namespace gpu_plugin {
+
+class PluginObjectFactoryTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ factory_ = new GPUPluginObjectFactory;
+ }
+
+ virtual void TearDown() {
+ delete factory_;
+ }
+
+ np_utils::StubNPBrowser stub_browser_;
+ GPUPluginObjectFactory* factory_;
+};
+
+TEST_F(PluginObjectFactoryTest, ReturnsNullForUnknownMimeType) {
+ PluginObject* plugin_object = factory_->CreatePluginObject(
+ NULL, "application/unknown");
+ EXPECT_TRUE(NULL == plugin_object);
+}
+
+TEST_F(PluginObjectFactoryTest, CreatesGPUPlugin) {
+ PluginObject* plugin_object = factory_->CreatePluginObject(
+ NULL, const_cast<NPMIMEType>(GPUPluginObject::kPluginType));
+ EXPECT_TRUE(NULL != plugin_object);
+}
+
+} // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin_object_unittest.cc b/gpu/gpu_plugin/gpu_plugin_object_unittest.cc
new file mode 100644
index 0000000..b032aa0
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object_unittest.cc
@@ -0,0 +1,319 @@
+// 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/command_buffer/common/command_buffer_mock.h"
+#include "gpu/gpu_plugin/gpu_plugin_object.h"
+#include "gpu/command_buffer/service/gpu_processor_mock.h"
+#include "gpu/np_utils/np_browser_mock.h"
+#include "gpu/np_utils/dynamic_np_object.h"
+#include "gpu/np_utils/np_object_mock.h"
+#include "gpu/np_utils/np_object_pointer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "webkit/glue/plugins/nphostapi.h"
+
+using ::base::SharedMemory;
+using command_buffer::GPUProcessor;
+using command_buffer::MockCommandBuffer;
+using command_buffer::MockGPUProcessor;
+using np_utils::MockNPBrowser;
+using np_utils::NPBrowser;
+using np_utils::NPObjectPointer;
+using testing::_;
+using testing::DoAll;
+using testing::Invoke;
+using testing::NotNull;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+namespace gpu_plugin {
+
+class GPUPluginObjectTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ plugin_object_ = np_utils::NPCreateObject<GPUPluginObject>(NULL);
+
+ command_buffer_ = new MockCommandBuffer;
+
+ // Takes ownership.
+ plugin_object_->set_command_buffer(command_buffer_);
+
+ processor_ = new MockGPUProcessor(command_buffer_);
+ plugin_object_->set_gpu_processor(processor_.get());
+ }
+
+ MockNPBrowser mock_browser_;
+ NPObjectPointer<GPUPluginObject> plugin_object_;
+ MockCommandBuffer* command_buffer_;
+ scoped_refptr<MockGPUProcessor> processor_;
+};
+
+namespace {
+template <typename T>
+void DeleteObject(T* object) {
+ delete object;
+}
+} // namespace anonymous
+
+
+TEST_F(GPUPluginObjectTest, CanInstantiateAndDestroyPluginObject) {
+ EXPECT_EQ(GPUPluginObject::kWaitingForNew, plugin_object_->GetStatus());
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ EXPECT_EQ(GPUPluginObject::kWaitingForSetWindow, plugin_object_->GetStatus());
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+
+ EXPECT_EQ(GPUPluginObject::kDestroyed, plugin_object_->GetStatus());
+}
+
+TEST_F(GPUPluginObjectTest, DestroyFailsIfNotInitialized) {
+ EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_object_->Destroy(NULL));
+}
+
+TEST_F(GPUPluginObjectTest, NewFailsIfAlreadyInitialized) {
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ EXPECT_EQ(GPUPluginObject::kWaitingForSetWindow, plugin_object_->GetStatus());
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+
+ EXPECT_EQ(GPUPluginObject::kDestroyed, plugin_object_->GetStatus());
+}
+
+TEST_F(GPUPluginObjectTest, NewFailsIfObjectHasPreviouslyBeenDestroyed) {
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+
+ EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ EXPECT_EQ(GPUPluginObject::kDestroyed, plugin_object_->GetStatus());
+}
+
+TEST_F(GPUPluginObjectTest, WindowIsNullBeforeSetWindowCalled) {
+ NPWindow window = plugin_object_->GetWindow();
+ EXPECT_EQ(NULL, window.window);
+}
+
+TEST_F(GPUPluginObjectTest, CanSetWindow) {
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ NPWindow window = {0};
+ window.window = &window;
+ window.x = 7;
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->SetWindow(&window));
+ EXPECT_EQ(0, memcmp(&window, &plugin_object_->GetWindow(), sizeof(window)));
+ EXPECT_EQ(GPUPluginObject::kWaitingForOpenCommandBuffer,
+ plugin_object_->GetStatus());
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+TEST_F(GPUPluginObjectTest, CanGetWindowSize) {
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ NPWindow window = {0};
+ window.window = &window;
+ window.x = 10;
+ window.y = 10;
+ window.width = 100;
+ window.height = 200;
+
+ EXPECT_EQ(0, plugin_object_->GetWidth());
+ EXPECT_EQ(0, plugin_object_->GetHeight());
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->SetWindow(&window));
+ EXPECT_EQ(100, plugin_object_->GetWidth());
+ EXPECT_EQ(200, plugin_object_->GetHeight());
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+TEST_F(GPUPluginObjectTest, SetWindowFailsIfNotInitialized) {
+ NPWindow window = {0};
+ EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_object_->SetWindow(&window));
+ EXPECT_EQ(GPUPluginObject::kWaitingForNew, plugin_object_->GetStatus());
+}
+
+TEST_F(GPUPluginObjectTest, CanGetScriptableNPObject) {
+ NPObject* scriptable_object = plugin_object_->GetScriptableNPObject();
+ EXPECT_EQ(plugin_object_.Get(), scriptable_object);
+ NPBrowser::get()->ReleaseObject(scriptable_object);
+}
+
+TEST_F(GPUPluginObjectTest, OpenCommandBufferReturnsInitializedCommandBuffer) {
+ EXPECT_CALL(*command_buffer_, Initialize(NotNull()))
+ .WillOnce(DoAll(Invoke(DeleteObject<SharedMemory>),
+ Return(true)));
+
+ EXPECT_CALL(*processor_.get(), Initialize(NULL))
+ .WillOnce(Return(true));
+
+ EXPECT_CALL(*command_buffer_, SetPutOffsetChangeCallback(NotNull()))
+ .WillOnce(Invoke(DeleteObject<Callback0::Type>));
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ // Set status as though SetWindow has been called. Avoids having to create a
+ // valid window handle to pass to SetWindow in tests.
+ plugin_object_->set_status(GPUPluginObject::kWaitingForOpenCommandBuffer);
+
+ EXPECT_EQ(command_buffer_, plugin_object_->OpenCommandBuffer());
+
+ // Calling OpenCommandBuffer again just returns the existing command buffer.
+ EXPECT_EQ(command_buffer_, plugin_object_->OpenCommandBuffer());
+
+ EXPECT_EQ(GPUPluginObject::kInitializationSuccessful,
+ plugin_object_->GetStatus());
+
+ EXPECT_CALL(*command_buffer_, SetPutOffsetChangeCallback(NULL));
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+TEST_F(GPUPluginObjectTest, OpenCommandBufferReturnsNullIfWindowNotReady) {
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ // Set status as though SetWindow has not been called.
+ plugin_object_->set_status(GPUPluginObject::kWaitingForSetWindow);
+
+ EXPECT_TRUE(NULL == plugin_object_->OpenCommandBuffer());
+
+ EXPECT_EQ(GPUPluginObject::kWaitingForSetWindow, plugin_object_->GetStatus());
+}
+
+
+TEST_F(GPUPluginObjectTest,
+ OpenCommandBufferReturnsNullIfCommandBufferCannotInitialize) {
+ EXPECT_CALL(*command_buffer_, Initialize(NotNull()))
+ .WillOnce(DoAll(Invoke(DeleteObject<SharedMemory>),
+ Return(false)));
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ // Set status as though SetWindow has been called. Avoids having to create a
+ // valid window handle to pass to SetWindow in tests.
+ plugin_object_->set_status(GPUPluginObject::kWaitingForOpenCommandBuffer);
+
+ EXPECT_TRUE(NULL == plugin_object_->OpenCommandBuffer());
+
+ EXPECT_EQ(GPUPluginObject::kWaitingForOpenCommandBuffer,
+ plugin_object_->GetStatus());
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+TEST_F(GPUPluginObjectTest,
+ OpenCommandBufferReturnsNullIGPUProcessorCannotInitialize) {
+ EXPECT_CALL(*command_buffer_, Initialize(NotNull()))
+ .WillOnce(DoAll(Invoke(DeleteObject<SharedMemory>),
+ Return(true)));
+
+ EXPECT_CALL(*processor_.get(), Initialize(NULL))
+ .WillOnce(Return(false));
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ // Set status as though SetWindow has been called. Avoids having to create a
+ // valid window handle to pass to SetWindow in tests.
+ plugin_object_->set_status(GPUPluginObject::kWaitingForOpenCommandBuffer);
+
+ EXPECT_TRUE(NULL == plugin_object_->OpenCommandBuffer());
+
+ EXPECT_EQ(GPUPluginObject::kWaitingForOpenCommandBuffer,
+ plugin_object_->GetStatus());
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+class MockEventSync : public np_utils::DefaultNPObject<NPObject> {
+ public:
+ explicit MockEventSync(NPP npp) {
+ }
+
+ MOCK_METHOD2(Resize, void(int32 width, int32 height));
+
+ NP_UTILS_BEGIN_DISPATCHER_CHAIN(MockEventSync, DefaultNPObject<NPObject>)
+ NP_UTILS_DISPATCHER(Resize, void(int32 width, int32 height))
+ NP_UTILS_END_DISPATCHER_CHAIN
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockEventSync);
+};
+
+TEST_F(GPUPluginObjectTest, SendsResizeEventOnSetWindow) {
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->New("application/foo",
+ 0,
+ NULL,
+ NULL,
+ NULL));
+
+ NPObjectPointer<MockEventSync> event_sync =
+ np_utils::NPCreateObject<MockEventSync>(NULL);
+ plugin_object_->SetEventSync(event_sync);
+
+ EXPECT_CALL(*event_sync.Get(), Resize(100, 200));
+
+ NPWindow window = {0};
+ window.window = &window;
+ window.x = 10;
+ window.y = 10;
+ window.width = 100;
+ window.height = 200;
+
+ plugin_object_->SetWindow(&window);
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_object_->Destroy(NULL));
+}
+
+} // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin_object_win.cc b/gpu/gpu_plugin/gpu_plugin_object_win.cc
new file mode 100644
index 0000000..31c6393
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_object_win.cc
@@ -0,0 +1,62 @@
+// 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 <windows.h>
+
+#include "gpu/command_buffer/service/gpu_processor.h"
+#include "gpu/gpu_plugin/gpu_plugin_object.h"
+
+namespace gpu_plugin {
+
+namespace {
+const LPCTSTR kPluginObjectProperty = TEXT("GPUPluginObject");
+const LPCTSTR kOriginalWindowProc = TEXT("GPUPluginObjectOriginalWindowProc");
+
+LRESULT CALLBACK WindowProc(HWND handle,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ return ::DefWindowProc(handle, message, w_param, l_param);
+}
+} // namespace anonymous
+
+NPError GPUPluginObject::PlatformSpecificSetWindow(NPWindow* new_window) {
+ // Detach properties from old window and restore the original window proc.
+ if (window_.window) {
+ HWND handle = reinterpret_cast<HWND>(window_.window);
+ ::RemoveProp(handle, kPluginObjectProperty);
+
+ LONG original_window_proc = reinterpret_cast<LONG>(
+ ::GetProp(handle, kOriginalWindowProc));
+ ::SetWindowLong(handle, GWL_WNDPROC,
+ original_window_proc);
+ ::RemoveProp(handle, kOriginalWindowProc);
+ }
+
+ // Attach properties to new window and set a new window proc.
+ if (new_window->window) {
+ HWND handle = reinterpret_cast<HWND>(new_window->window);
+ ::SetProp(handle,
+ kPluginObjectProperty,
+ reinterpret_cast<HANDLE>(this));
+
+ LONG original_window_proc = ::GetWindowLong(handle, GWL_WNDPROC);
+ ::SetProp(handle,
+ kOriginalWindowProc,
+ reinterpret_cast<HANDLE>(original_window_proc));
+ ::SetWindowLong(handle, GWL_WNDPROC,
+ reinterpret_cast<LONG>(WindowProc));
+
+ status_ = kWaitingForOpenCommandBuffer;
+ } else {
+ status_ = kWaitingForSetWindow;
+ if (processor_) {
+ processor_->Destroy();
+ }
+ }
+
+ return NPERR_NO_ERROR;
+}
+
+} // namespace gpu_plugin
diff --git a/gpu/gpu_plugin/gpu_plugin_unittest.cc b/gpu/gpu_plugin/gpu_plugin_unittest.cc
new file mode 100644
index 0000000..ea1bb5f
--- /dev/null
+++ b/gpu/gpu_plugin/gpu_plugin_unittest.cc
@@ -0,0 +1,302 @@
+// 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.h"
+#include "gpu/gpu_plugin/gpu_plugin_object.h"
+#include "gpu/np_utils/np_object_mock.h"
+#include "gpu/np_utils/np_plugin_object_factory_mock.h"
+#include "gpu/np_utils/np_plugin_object_mock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/glue/plugins/nphostapi.h"
+
+#if defined(OS_LINUX)
+#define INITIALIZE_PLUGIN_FUNCS , &plugin_funcs_
+#else
+#define INITIALIZE_PLUGIN_FUNCS
+#endif
+
+using np_utils::MockPluginObject;
+using np_utils::PluginObject;
+using testing::_;
+using testing::DoAll;
+using testing::NiceMock;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+
+namespace gpu_plugin {
+
+class GPUPluginTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ memset(&npp_, 0, sizeof(npp_));
+ memset(&browser_funcs_, 0, sizeof(browser_funcs_));
+ memset(&plugin_funcs_, 0, sizeof(plugin_funcs_));
+
+ plugin_object_factory_ = new StrictMock<np_utils::MockPluginObjectFactory>;
+
+ np_class_ = np_utils::NPGetClass<StrictMock<np_utils::MockNPObject> >();
+ }
+
+ virtual void TearDown() {
+ delete plugin_object_factory_;
+ }
+
+ NPP_t npp_;
+ NPNetscapeFuncs browser_funcs_;
+ NPPluginFuncs plugin_funcs_;
+ np_utils::MockPluginObjectFactory* plugin_object_factory_;
+ const NPClass* np_class_;
+};
+
+TEST_F(GPUPluginTest, GetEntryPointsSetsNeededFunctionPointers) {
+#if defined(OS_LINUX)
+ NPError error = gpu_plugin::NP_Initialize(&browser_funcs_,
+ &plugin_funcs_);
+ gpu_plugin::NP_Shutdown();
+#else
+ NPError error = gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+#endif
+
+ EXPECT_EQ(NPERR_NO_ERROR, error);
+ EXPECT_TRUE(NULL != plugin_funcs_.newp);
+ EXPECT_TRUE(NULL != plugin_funcs_.destroy);
+ EXPECT_TRUE(NULL != plugin_funcs_.setwindow);
+ EXPECT_TRUE(NULL != plugin_funcs_.event);
+ EXPECT_TRUE(NULL != plugin_funcs_.getvalue);
+ EXPECT_TRUE(NULL != plugin_funcs_.setvalue);
+}
+
+TEST_F(GPUPluginTest, CanInitializeAndShutdownPlugin) {
+ EXPECT_EQ(NPERR_NO_ERROR,
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS));
+ EXPECT_EQ(NPERR_NO_ERROR, gpu_plugin::NP_Shutdown());
+}
+
+TEST_F(GPUPluginTest, InitializeFailsIfBrowserFuncsIsNull) {
+ EXPECT_EQ(NPERR_INVALID_FUNCTABLE_ERROR,
+ gpu_plugin::NP_Initialize(NULL INITIALIZE_PLUGIN_FUNCS));
+}
+
+TEST_F(GPUPluginTest, InitializeFailsIfAlreadyInitialized) {
+ EXPECT_EQ(NPERR_NO_ERROR,
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS));
+ EXPECT_EQ(NPERR_GENERIC_ERROR,
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS));
+ EXPECT_EQ(NPERR_NO_ERROR, gpu_plugin::NP_Shutdown());
+}
+
+TEST_F(GPUPluginTest, ShutdownFailsIfNotInitialized) {
+ EXPECT_EQ(NPERR_GENERIC_ERROR, gpu_plugin::NP_Shutdown());
+}
+
+TEST_F(GPUPluginTest, NewReturnsErrorForInvalidInstance) {
+ gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+ EXPECT_EQ(NPERR_INVALID_INSTANCE_ERROR, plugin_funcs_.newp(
+ const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+ NULL, 0, 0, NULL, NULL, NULL));
+
+ gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, GetValueReturnsErrorForInvalidInstance) {
+ gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+ int* result = NULL;
+ EXPECT_EQ(NPERR_INVALID_INSTANCE_ERROR, plugin_funcs_.getvalue(
+ NULL, NPPVjavaClass, &result));
+
+ gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, DestroyReturnsErrorForInvalidInstance) {
+ gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+ EXPECT_EQ(NPERR_INVALID_INSTANCE_ERROR, plugin_funcs_.destroy(NULL, NULL));
+
+ gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, SetWindowReturnsErrorForInvalidInstance) {
+ gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+ EXPECT_EQ(NPERR_INVALID_INSTANCE_ERROR, plugin_funcs_.setwindow(NULL, NULL));
+
+ gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, HandleEventReturnsFalseForInvalidInstance) {
+ gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+ EXPECT_EQ(0, plugin_funcs_.event(NULL, NULL));
+
+ gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, NewCreatesAPluginObjectAndInitializesIt) {
+ StrictMock<np_utils::MockPluginObject> plugin_object;
+
+ EXPECT_CALL(*plugin_object_factory_, CreatePluginObject(
+ &npp_, const_cast<NPMIMEType>(GPUPluginObject::kPluginType)))
+ .WillOnce(Return(&plugin_object));
+
+ NPObject scriptable_object;
+
+ EXPECT_CALL(plugin_object, New(
+ const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+ 0, NULL, NULL, NULL))
+ .WillOnce(Return(NPERR_NO_ERROR));
+
+ EXPECT_CALL(plugin_object, GetScriptableNPObject())
+ .WillOnce(Return(&scriptable_object));
+
+ EXPECT_CALL(plugin_object, Destroy(static_cast<NPSavedData**>(NULL)))
+ .WillOnce(Return(NPERR_NO_ERROR));
+
+ EXPECT_CALL(plugin_object, Release());
+
+ gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.newp(
+ const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+ &npp_, 0, 0, NULL, NULL, NULL));
+
+ NPObject* result;
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.getvalue(
+ &npp_, NPPVpluginScriptableNPObject, &result));
+ EXPECT_EQ(&scriptable_object, result);
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.destroy(&npp_, NULL));
+
+ gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, NewFailsIfPluginObjectFactoryFails) {
+ EXPECT_CALL(*plugin_object_factory_, CreatePluginObject(
+ &npp_, const_cast<NPMIMEType>(GPUPluginObject::kPluginType)))
+ .WillOnce(Return(static_cast<PluginObject*>(NULL)));
+
+ gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+ EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_funcs_.newp(
+ const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+ &npp_, 0, 0, NULL, NULL, NULL));
+
+ gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, SetWindowForwardsToPluginObject) {
+ StrictMock<MockPluginObject> plugin_object;
+
+ EXPECT_CALL(*plugin_object_factory_, CreatePluginObject(
+ &npp_, const_cast<NPMIMEType>(GPUPluginObject::kPluginType)))
+ .WillOnce(Return(&plugin_object));
+
+ EXPECT_CALL(plugin_object, New(
+ const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+ 0, NULL, NULL, NULL))
+ .WillOnce(Return(NPERR_NO_ERROR));
+
+ NPWindow window = {0};
+
+ EXPECT_CALL(plugin_object, SetWindow(&window))
+ .WillOnce(Return(NPERR_NO_ERROR));
+
+ EXPECT_CALL(plugin_object, Destroy(static_cast<NPSavedData**>(NULL)))
+ .WillOnce(Return(NPERR_NO_ERROR));
+
+ EXPECT_CALL(plugin_object, Release());
+
+ gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.newp(
+ const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+ &npp_, 0, 0, NULL, NULL, NULL));
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.setwindow(&npp_, &window));
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.destroy(&npp_, NULL));
+
+ gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, HandleEventForwardsToPluginObject) {
+ StrictMock<MockPluginObject> plugin_object;
+
+ EXPECT_CALL(*plugin_object_factory_, CreatePluginObject(
+ &npp_, const_cast<NPMIMEType>(GPUPluginObject::kPluginType)))
+ .WillOnce(Return(&plugin_object));
+
+ EXPECT_CALL(plugin_object, New(
+ const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+ 0, NULL, NULL, NULL))
+ .WillOnce(Return(NPERR_NO_ERROR));
+
+ NPEvent event = {0};
+
+ EXPECT_CALL(plugin_object, HandleEvent(&event))
+ .WillOnce(Return(7));
+
+ EXPECT_CALL(plugin_object, Destroy(static_cast<NPSavedData**>(NULL)))
+ .WillOnce(Return(NPERR_NO_ERROR));
+
+ EXPECT_CALL(plugin_object, Release());
+
+ gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.newp(
+ const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+ &npp_, 0, 0, NULL, NULL, NULL));
+
+ EXPECT_EQ(7, plugin_funcs_.event(&npp_, &event));
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.destroy(&npp_, NULL));
+
+ gpu_plugin::NP_Shutdown();
+}
+
+TEST_F(GPUPluginTest, GetValueReturnsErrorForUnknownVariable) {
+ StrictMock<MockPluginObject> plugin_object;
+
+ EXPECT_CALL(*plugin_object_factory_, CreatePluginObject(
+ &npp_, const_cast<NPMIMEType>(GPUPluginObject::kPluginType)))
+ .WillOnce(Return(&plugin_object));
+
+ EXPECT_CALL(plugin_object, New(
+ const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+ 0, NULL, NULL, NULL))
+ .WillOnce(Return(NPERR_NO_ERROR));
+
+ EXPECT_CALL(plugin_object, Destroy(static_cast<NPSavedData**>(NULL)))
+ .WillOnce(Return(NPERR_NO_ERROR));
+
+ EXPECT_CALL(plugin_object, Release());
+
+ gpu_plugin::NP_GetEntryPoints(&plugin_funcs_);
+ gpu_plugin::NP_Initialize(&browser_funcs_ INITIALIZE_PLUGIN_FUNCS);
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.newp(
+ const_cast<NPMIMEType>(GPUPluginObject::kPluginType),
+ &npp_, 0, 0, NULL, NULL, NULL));
+
+ int* result = NULL;
+ EXPECT_EQ(NPERR_GENERIC_ERROR, plugin_funcs_.getvalue(
+ &npp_, NPPVjavaClass, &result));
+
+ EXPECT_EQ(NPERR_NO_ERROR, plugin_funcs_.destroy(&npp_, NULL));
+
+ gpu_plugin::NP_Shutdown();
+}
+
+} // namespace gpu_plugin