diff options
Diffstat (limited to 'remoting/client/pepper')
-rw-r--r-- | remoting/client/pepper/fake_browser.cc | 157 | ||||
-rw-r--r-- | remoting/client/pepper/fake_browser.h | 61 | ||||
-rw-r--r-- | remoting/client/pepper/pepper_main.cc | 373 | ||||
-rw-r--r-- | remoting/client/pepper/pepper_plugin.cc | 22 | ||||
-rw-r--r-- | remoting/client/pepper/pepper_plugin.h | 106 |
5 files changed, 719 insertions, 0 deletions
diff --git a/remoting/client/pepper/fake_browser.cc b/remoting/client/pepper/fake_browser.cc new file mode 100644 index 0000000..a24668c --- /dev/null +++ b/remoting/client/pepper/fake_browser.cc @@ -0,0 +1,157 @@ +// Copyright (c) 2010 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 "remoting/client/pepper/fake_browser.h" + +// Constant value for browser window. +static const int kWindowWidth = 100; +static const int kWindowHeight = 100; + +// ---------------------------------------------------------------------------- +// Browser callback routines +// These are simple implementations of the routines that the browser provides +// to the plugin as callbacks. +// ---------------------------------------------------------------------------- + +// Handler for getvalue. +// Must be of type NPN_GetValueProcPtr. +NPError Browser_GetValue(NPP instance, NPNVariable variable, void *ret_value) { + if (variable == NPNVPepperExtensions) { + NPNExtensions** ret = static_cast<NPNExtensions**>(ret_value); + *ret = Singleton<FakeBrowser>()->GetExtensions(); + return NPERR_NO_ERROR; + } + return NPERR_GENERIC_ERROR; +} + +// Extension handler for acquireDevice. +// Must be of type NPAcquireDevicePtr. +NPDevice* Extension_AcquireDevice(NPP instance, NPDeviceID device) { + if (device == NPPepper2DDevice) { + return Singleton<FakeBrowser>()->GetDevice2d(); + } + // TODO(garykac): Add support for NPPepper3DDevice. + return NULL; +} + +// Initialize 2D device context. +NPError Device_InitializeContext2D(NPP instance, + NPDeviceContext2D* context, + int extra_bytes) { + FakeBrowser* browser = Singleton<FakeBrowser>::get(); + NPDeviceContext2D* context2d = static_cast<NPDeviceContext2D*>(context); + int width, height; + browser->GetWindowInfo(&width, &height); + int stride = (width * ARGB_PIXEL_SIZE) + extra_bytes; + context2d->region = browser->AllocPixelBuffer(stride); + context2d->stride = stride; + + return NPERR_NO_ERROR; +} + +// Device handler for initializeContext +// This initializes a 2D context where the stride == width. +// Must be of type NPDeviceInitializeContextPtr. +NPError Device_InitializeContext2D_NoExtraBytes(NPP instance, + const NPDeviceConfig* config, + NPDeviceContext* context) { + return Device_InitializeContext2D(instance, + static_cast<NPDeviceContext2D*>(context), + 0); +} + +// Device handler for initializeContext +// This initializes a 2D context where the stride > width. +// Must be of type NPDeviceInitializeContextPtr. +NPError Device_InitializeContext2D_ExtraBytes(NPP instance, + const NPDeviceConfig* config, + NPDeviceContext* context) { + return Device_InitializeContext2D(instance, + static_cast<NPDeviceContext2D*>(context), + 8 /* extra_bytes */); +} + +// Device handler for flushContext +// Must be of type NPDeviceFlushContextPtr. +NPError Device_FlushContext(NPP instance, NPDeviceContext* context, + NPDeviceFlushContextCallbackPtr callback, + void* userData) { + return NPERR_NO_ERROR; +} + +// ---------------------------------------------------------------------------- +// FakeBrowserFuncs +// Singleton class for creating/managing the NPNetscapeFuncs struct that we +// need to provide to the Pepper plugin. +// ---------------------------------------------------------------------------- + +FakeBrowser::FakeBrowser() { + // Setup fake versions of the browser funcs needed by the unit tests. + // There are dozens of browser funcs that can be set up, but we only worry + // about the ones needed for our unittests. + browser_funcs_.reset(new NPNetscapeFuncs()); + browser_funcs_->getvalue = &Browser_GetValue; + + // Setup fake extension funcs structure. + extensions_.reset(new NPNExtensions()); + extensions_->acquireDevice = &Extension_AcquireDevice; + + // Setup fake device funcs structure. + device2d_.reset(new NPDevice()); + device2d_->initializeContext = &Device_InitializeContext2D_NoExtraBytes; + device2d_->flushContext = &Device_FlushContext; + + // Fake browser window. + window_.reset(new NPWindow()); + window_->x = 0; + window_->y = 0; + window_->width = kWindowWidth; + window_->height = kWindowHeight; + + width_ = kWindowWidth; + height_ = kWindowHeight; + + stride_ = 0; + pixel_buffer_.reset(); +} + +FakeBrowser::~FakeBrowser() { + FreePixelBuffer(); +} + +// Normally in our tests, the stride (ie, the number of bytes between the +// start of a row and the start of the next row) is equal to the number of +// bytes used to store the pixels for the row. +// Passing true to this routine sets things up so that there are a few extra +// padding bytes to the end of each row so that the stride is not the same +// as the row width. +void FakeBrowser::ForceStrideInDeviceContext(bool extra_bytes) { + if (extra_bytes) { + device2d_->initializeContext = &Device_InitializeContext2D_ExtraBytes; + } else { + device2d_->initializeContext = &Device_InitializeContext2D_NoExtraBytes; + } +} + +// Allocate a pixel buffer for the plugin to use. +// The height and width of the buffer come from the window size. +// The stride value is used to force each row to be |stride| bytes in size. +// This is typically done to add extra padding bytes to the end of each row. +uint32* FakeBrowser::AllocPixelBuffer(int stride) { + // Don't allow the stride to be less than the window width. + if (stride < width_) { + stride = width_; + } + stride_ = stride; + pixel_buffer_.reset(new uint32[height_ * stride]); + + return pixel_buffer_.get(); +} + +void FakeBrowser::FreePixelBuffer() { + stride_ = 0; + pixel_buffer_.reset(); +} diff --git a/remoting/client/pepper/fake_browser.h b/remoting/client/pepper/fake_browser.h new file mode 100644 index 0000000..b9f2e15 --- /dev/null +++ b/remoting/client/pepper/fake_browser.h @@ -0,0 +1,61 @@ +// Copyright (c) 2010 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 REMOTING_CLIENT_PEPPER_FAKE_BROWSER_H_ +#define REMOTING_CLIENT_PEPPER_FAKE_BROWSER_H_ + +#include "base/scoped_ptr.h" +#include "base/singleton.h" +#include "third_party/npapi/bindings/nphostapi.h" +#include "third_party/npapi/bindings/npapi_extensions.h" + +// Each ARGB pixel is stored in a 4-byte uint32. +#define ARGB_PIXEL_SIZE 4 + +class FakeBrowser { + public: + NPNetscapeFuncs* GetBrowserFuncs() { return browser_funcs_.get(); } + NPNExtensions* GetExtensions() { return extensions_.get(); } + + NPDevice* GetDevice2d() { return device2d_.get(); } + void ForceStrideInDeviceContext(bool forceStride); + + NPWindow* GetWindow() { return window_.get(); } + void GetWindowInfo(int* width, int* height) { + *width = width_; + *height = height_; + } + + uint32* AllocPixelBuffer(int stride); + void FreePixelBuffer(); + + uint32* GetPixelBuffer() { return pixel_buffer_.get(); } + int GetPixelBufferStride() { return stride_; } + + private: + // Singleton private bits. + friend struct DefaultSingletonTraits<FakeBrowser>; + FakeBrowser(); + virtual ~FakeBrowser(); + + // Browser callback functions. + scoped_ptr<NPNetscapeFuncs> browser_funcs_; + + // Browser extension callbacks. + scoped_ptr<NPNExtensions> extensions_; + + // The rendering device (provided by the browser to the plugin). + scoped_ptr<NPDevice> device2d_; + + // Window (provided by the browser to the plugin). + scoped_ptr<NPWindow> window_; + + // Pixel buffer to store the device2d_ (and window_) pixels. + scoped_array<uint32> pixel_buffer_; + int width_, height_, stride_; + + DISALLOW_COPY_AND_ASSIGN(FakeBrowser); +}; + +#endif // REMOTING_CLIENT_PEPPER_FAKE_BROWSER_H_ diff --git a/remoting/client/pepper/pepper_main.cc b/remoting/client/pepper/pepper_main.cc new file mode 100644 index 0000000..013c90a --- /dev/null +++ b/remoting/client/pepper/pepper_main.cc @@ -0,0 +1,373 @@ +// Copyright (c) 2010 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 "remoting/client/pepper/pepper_plugin.h" +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/nphostapi.h" + +#if __GNUC__ >= 4 +# define EXPORT __attribute__ ((visibility("default"))) +# define PRIVATE __attribute__ ((visibility("hidden"))) +#else +# define EXPORT +# define PRIVATE +#endif + +// +// External Plugin Implementation +// + +// Plugin info. +// These routines are defined externally and provide the code that is specific +// to this particular plugin. + +// Initialize general plugin information. +extern void InitializePluginInfo(pepper::PepperPlugin::Info* plugin_info); + +// Routine to create the PepperPlugin subclass that implements all of the +// plugin-specific functionality. +extern pepper::PepperPlugin* CreatePlugin(NPNetscapeFuncs* browser_funcs, + NPP instance); + +namespace pepper { + +// +// Globals +// + +// Pointer to struct containing all the callbacks provided by the browser +// to the plugin. +NPNetscapeFuncs* g_browser_funcs = NULL; + +// General information (name/description) about this plugin. +PepperPlugin::Info g_plugin_info = { false, NULL, NULL, NULL }; + + +// +// Internal setup routines +// + +PRIVATE void Initialize(NPNetscapeFuncs* browser_funcs) { + g_browser_funcs = browser_funcs; + if (!g_plugin_info.initialized) { + InitializePluginInfo(&g_plugin_info); + } +} + +// Populate the NPPluginFuncs struct so that the browser knows how to find +// each entry point for the plugin. +PRIVATE void SetupEntryPoints(NPPluginFuncs* plugin_funcs) { + plugin_funcs->version = ((NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR); + plugin_funcs->size = sizeof(NPPluginFuncs); + plugin_funcs->newp = NPP_New; + plugin_funcs->destroy = NPP_Destroy; + plugin_funcs->setwindow = NPP_SetWindow; + plugin_funcs->newstream = NPP_NewStream; + plugin_funcs->destroystream = NPP_DestroyStream; + plugin_funcs->asfile = NPP_StreamAsFile; + plugin_funcs->writeready = NPP_WriteReady; + plugin_funcs->write = NPP_Write; + plugin_funcs->print = NPP_Print; + plugin_funcs->event = NPP_HandleEvent; + plugin_funcs->urlnotify = NPP_URLNotify; + plugin_funcs->javaClass = NULL; + plugin_funcs->getvalue = NPP_GetValue; + plugin_funcs->setvalue = NPP_SetValue; +} + +// Get the PepperPlugin from the private data storage in the instance. +PRIVATE PepperPlugin* GetPlugin(NPP instance) { + return static_cast<PepperPlugin*>(instance->pdata); +} + +} // namespace pepper + + +// +// Exported interfaces +// Routines to initialize/shutdown the plugin. +// + +extern "C" { + +#if defined(OS_POSIX) && !defined(OS_MACOSX) + +// Get the MIME-type associated with this plugin. +// Linux-only. Mac & Windows use a different mechanism for associating a +// MIME-type with the plugin. +// Note that this is called before NPP_Initialize(). +EXPORT const char* API_CALL NP_GetMIMEDescription() { + if (!pepper::g_plugin_info.initialized) { + InitializePluginInfo(&pepper::g_plugin_info); + } + return pepper::g_plugin_info.mime_description; +} + +// Old version of NPP_GetValue, required for Linux. +// Simply redirects to the NPP_GetValue. +EXPORT NPError API_CALL NP_GetValue(NPP instance, + NPPVariable variable, + void* value) { + return NPP_GetValue(instance, variable, value); +} + +// NP_Initialize for Linux. +// This is the equivalent of NP_Initialize and NP_GetEntryPoints for Mac/Win. +EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* browser_funcs, + NPPluginFuncs* plugin_funcs) { + pepper::Initialize(browser_funcs); + pepper::SetupEntryPoints(plugin_funcs); + return NPERR_NO_ERROR; +} + +#else + +// NP_Initialize for Mac/Windows. +EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* browser_funcs) { + pepper::Initialize(browser_funcs); + return NPERR_NO_ERROR; +} + +// NP_GetEntryPoints for Mac/Windows. +EXPORT NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* plugin_funcs) { + pepper::SetupEntryPoints(plugin_funcs); + return NPERR_NO_ERROR; +} + +#endif // defined(OS_POSIX) && !defined(OS_MACOSX) + +EXPORT NPError API_CALL NP_Shutdown() { + pepper::g_browser_funcs = NULL; + return NPERR_NO_ERROR; +} + +} // extern "C" + + +// +// Plugin Entrypoints +// Entry points that the plugin makes available to the browser. +// + +EXPORT NPError NPP_New(NPMIMEType pluginType, + NPP instance, + uint16 mode, + int16 argc, + char* argn[], + char* argv[], + NPSavedData* saved) { + if (!instance) { + return NPERR_INVALID_INSTANCE_ERROR; + } + + pepper::PepperPlugin* plugin + = CreatePlugin(pepper::g_browser_funcs, instance); + NPError result = plugin->New(pluginType, argc, argn, argv); + if (result != NPERR_NO_ERROR) { + delete plugin; + return result; + } + + instance->pdata = plugin; + return NPERR_NO_ERROR; +} + +EXPORT NPError NPP_Destroy(NPP instance, NPSavedData** save) { + if (!instance) { + return NPERR_INVALID_INSTANCE_ERROR; + } + + NPError result = NPERR_NO_ERROR; + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + result = plugin->Destroy(save); + if (result != NPERR_NO_ERROR) { + return result; + } + delete plugin; + instance->pdata = NULL; + } + return result; +} + +EXPORT NPError NPP_SetWindow(NPP instance, NPWindow* window) { + if (!instance) { + return NPERR_INVALID_INSTANCE_ERROR; + } + + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + return plugin->SetWindow(window); + } + + return NPERR_GENERIC_ERROR; +} + +EXPORT NPError NPP_NewStream(NPP instance, + NPMIMEType type, + NPStream* stream, + NPBool seekable, + uint16* stype) { + if (!instance) { + return NPERR_INVALID_INSTANCE_ERROR; + } + + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + return plugin->NewStream(type, stream, seekable, stype); + } + + return NPERR_GENERIC_ERROR; +} + +EXPORT NPError NPP_DestroyStream(NPP instance, + NPStream* stream, + NPReason reason) { + if (!instance) { + return NPERR_INVALID_INSTANCE_ERROR; + } + + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + return plugin->DestroyStream(stream, reason); + } + + return NPERR_GENERIC_ERROR; +} + +EXPORT void NPP_StreamAsFile(NPP instance, + NPStream* stream, + const char* fname) { + if (!instance) { + return; + } + + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + plugin->StreamAsFile(stream, fname); + } +} + +EXPORT int32 NPP_WriteReady(NPP instance, + NPStream* stream) { + if (!instance) { + return 0; + } + + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + return plugin->WriteReady(stream); + } + + return 0; +} + +EXPORT int32 NPP_Write(NPP instance, + NPStream* stream, + int32 offset, + int32 len, + void* buffer) { + if (!instance) { + return 0; + } + + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + return plugin->Write(stream, offset, len, buffer); + } + + return 0; +} + +EXPORT void NPP_Print(NPP instance, + NPPrint* platformPrint) { + if (!instance) { + return; + } + + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + plugin->Print(platformPrint); + } +} + +EXPORT int16 NPP_HandleEvent(NPP instance, + void* event) { + if (!instance) { + return false; + } + + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + return plugin->HandleEvent(event); + } + + return false; +} + +EXPORT void NPP_URLNotify(NPP instance, + const char* url, + NPReason reason, + void* notifyData) { + if (!instance) { + return; + } + + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + plugin->URLNotify(url, reason, notifyData); + } +} + +EXPORT NPError NPP_GetValue(NPP instance, + NPPVariable variable, + void* value) { +#if defined(OS_POSIX) && !defined(OS_MACOSX) + // Note that it is valid to call this routine before the plugin instance + // has been created. + // For example, the browser requests the name/description when plugin + // is loaded or when about:plugins is opened (whichever comes first). + // Thus, we can't check for a valid instance instance here and bail if + // it's not setup (like we do for the other routines). + + // If the name/description is being requested, then get that directly. + if (variable == NPPVpluginNameString) { + *((const char**)value) = pepper::g_plugin_info.plugin_name; + return NPERR_NO_ERROR; + } + if (variable == NPPVpluginDescriptionString) { + *((const char**)value) = pepper::g_plugin_info.plugin_description; + return NPERR_NO_ERROR; + } + if (variable == NPPVpluginNeedsXEmbed) { + *(static_cast<NPBool*>(value)) = true; + return NPERR_NO_ERROR; + } +#endif // defined(OS_POSIX) && !defined(OS_MACOSX) + + if (instance) { + // If we have an instance, then let the plugin handle the call. + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + return plugin->GetValue(variable, value); + } + } + + return NPERR_GENERIC_ERROR; +} + +EXPORT NPError NPP_SetValue(NPP instance, + NPNVariable variable, + void* value) { + if (!instance) { + return NPERR_INVALID_INSTANCE_ERROR; + } + + pepper::PepperPlugin* plugin = pepper::GetPlugin(instance); + if (plugin) { + return plugin->SetValue(variable, value); + } + + return NPERR_GENERIC_ERROR; +} diff --git a/remoting/client/pepper/pepper_plugin.cc b/remoting/client/pepper/pepper_plugin.cc new file mode 100644 index 0000000..4cb022f --- /dev/null +++ b/remoting/client/pepper/pepper_plugin.cc @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2010 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 "remoting/client/pepper/pepper_plugin.h" + +namespace pepper { + +PepperPlugin::PepperPlugin(NPNetscapeFuncs* browser_funcs, NPP instance) + : browser_funcs_(browser_funcs), + extensions_(NULL), + instance_(instance) { + browser_funcs_->getvalue(instance_, NPNVPepperExtensions, + static_cast<void*>(&extensions_)); +} + +PepperPlugin::~PepperPlugin() { +} + +} // namespace pepper diff --git a/remoting/client/pepper/pepper_plugin.h b/remoting/client/pepper/pepper_plugin.h new file mode 100644 index 0000000..723dc90 --- /dev/null +++ b/remoting/client/pepper/pepper_plugin.h @@ -0,0 +1,106 @@ +// Copyright (c) 2010 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 REMOTING_CLIENT_PEPPER_PEPPER_PLUGIN_H_ +#define REMOTING_CLIENT_PEPPER_PEPPER_PLUGIN_H_ + +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/npapi_extensions.h" +#include "third_party/npapi/bindings/nphostapi.h" + +namespace pepper { + +class PepperPlugin { + public: + // This class stores information about the plugin that cannot be instantiated + // as part of the PepperPlugin class because it is required before the + // PepperPlugin has been created. + class Info { + public: + // True if these fields have been initialized. + bool initialized; + + // MIME type and description. + const char* mime_description; + + // Name of plugin (shown in about:plugins). + const char* plugin_name; + + // Short description of plugin (shown in about:plugins). + const char* plugin_description; + }; + + PepperPlugin(NPNetscapeFuncs* browser_funcs, NPP instance); + virtual ~PepperPlugin(); + + NPNetscapeFuncs* browser() const { return browser_funcs_; } + NPNExtensions* extensions() const { return extensions_; } + NPP instance() const { return instance_; } + + // Virtual methods to be implemented by the plugin subclass. + + virtual NPError New(NPMIMEType pluginType, int16 argc, + char* argn[], char* argv[]) { + return NPERR_GENERIC_ERROR; + } + + virtual NPError Destroy(NPSavedData** save) { + return NPERR_GENERIC_ERROR; + } + + virtual NPError SetWindow(NPWindow* window) { + return NPERR_GENERIC_ERROR; + } + + virtual NPError NewStream(NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype) { + return NPERR_GENERIC_ERROR; + } + + virtual NPError DestroyStream(NPStream* stream, NPReason reason) { + return NPERR_GENERIC_ERROR; + } + + virtual void StreamAsFile(NPStream* stream, const char* fname) { + } + + virtual int32 WriteReady(NPStream* stream) { + return 0; + } + + virtual int32 Write(NPStream* stream, int32 offset, int32 len, void* buffer) { + return -1; + } + + virtual void Print(NPPrint* platformPrint) { + } + + virtual int16 HandleEvent(void* event) { + return false; + } + + virtual void URLNotify(const char* url, NPReason reason, void* nofifyData) { + } + + virtual NPError GetValue(NPPVariable variable, void* value) { + return NPERR_GENERIC_ERROR; + } + + virtual NPError SetValue(NPNVariable variable, void* value) { + return NPERR_GENERIC_ERROR; + } + + private: + // Browser callbacks. + NPNetscapeFuncs* browser_funcs_; + NPNExtensions* extensions_; + + NPP instance_; + + DISALLOW_COPY_AND_ASSIGN(PepperPlugin); +}; + +} // namespace pepper + +#endif // REMOTING_CLIENT_PEPPER_PEPPER_PLUGIN_H_ |