0

Convert chromoting to pepperv2 API.

Currently disables use of PepperView, and HostConnection->Connect().  This is mainly an attempt to get the build working. Will re-enable functionality later.

BUG=none
TEST=none

Review URL: http://codereview.chromium.org/2857011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50502 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
ajwong@chromium.org
2010-06-22 19:28:18 +00:00
parent 2515815230
commit edd588048c
11 changed files with 96 additions and 961 deletions

@ -1,157 +0,0 @@
// 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();
}

@ -1,61 +0,0 @@
// 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_

@ -1,373 +0,0 @@
// 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;
}

@ -1,22 +0,0 @@
/*
* 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

@ -1,106 +0,0 @@
// 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_

@ -1,24 +0,0 @@
// 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/plugin/chromoting_plugin.h"
// Initialize general plugin info like name and description.
// This information needs to live outside of the PepperPlugin since it can
// be requested by the browser before the PepperPlugin has been instantiated.
void InitializePluginInfo(pepper::PepperPlugin::Info* plugin_info) {
plugin_info->mime_description = remoting::ChromotingPlugin::kMimeType;
plugin_info->plugin_name = "Chromoting";
plugin_info->plugin_description = "Remote access for Chrome";
}
// Create the Pepper plugin instance.
//
// This is called in response to the NPP_New call.
// This instantiates a PepperPlugin subclass that implements the plugin
// specific functionality.
pepper::PepperPlugin* CreatePlugin(NPNetscapeFuncs* browser_funcs,
NPP instance) {
return new remoting::ChromotingPlugin(browser_funcs, instance);
}

@ -14,6 +14,9 @@
#include "remoting/client/jingle_host_connection.h"
#include "remoting/client/plugin/pepper_view.h"
#include "remoting/jingle_glue/jingle_thread.h"
#include "third_party/ppapi/c/pp_event.h"
#include "third_party/ppapi/c/pp_rect.h"
#include "third_party/ppapi/cpp/image_data.h"
using std::string;
using std::vector;
@ -23,30 +26,33 @@ namespace remoting {
const char* ChromotingPlugin::kMimeType =
"pepper-application/x-chromoting-plugin::Chromoting";
ChromotingPlugin::ChromotingPlugin(NPNetscapeFuncs* browser_funcs,
NPP instance)
: PepperPlugin(browser_funcs, instance), width_(0), height_(0),
device_(NULL) {
ChromotingPlugin::ChromotingPlugin(PP_Instance instance)
: pp::Instance(instance),
width_(0),
height_(0) {
}
ChromotingPlugin::~ChromotingPlugin() {
if (host_connection_.get())
host_connection_->Disconnect();
// TODO(ajwong): We need to ensure all objects have actually stopped posting
// to the message loop before this point. Right now, we don't have a well
// defined stop for the plugin process, and the thread shutdown is likely a
// race condition.
if (network_thread_.get())
network_thread_->Stop();
if (main_thread_.get())
main_thread_->Stop();
}
NPError ChromotingPlugin::New(NPMIMEType pluginType,
int16 argc, char* argn[], char* argv[]) {
LOG(INFO) << "Started ChromotingPlugin::New";
// Verify the mime type and subtype
std::string mime(kMimeType);
std::string::size_type type_end = mime.find("/");
std::string::size_type subtype_end = mime.find(":", type_end);
if (strncmp(pluginType, kMimeType, subtype_end)) {
return NPERR_GENERIC_ERROR;
}
bool ChromotingPlugin::Init(uint32_t argc, const char* argn[], const char* argv[]) {
LOG(INFO) << "Started ChromotingPlugin::Init";
// Extract the URL from the arguments.
char* url = NULL;
for (int i = 0; i < argc; ++i) {
const char* url = NULL;
for (uint32_t i = 0; i < argc; ++i) {
if (strcmp(argn[i], "src") == 0) {
url = argv[i];
break;
@ -54,7 +60,7 @@ NPError ChromotingPlugin::New(NPMIMEType pluginType,
}
if (!url) {
return NPERR_GENERIC_ERROR;
return false;
}
string user_id;
@ -62,100 +68,94 @@ NPError ChromotingPlugin::New(NPMIMEType pluginType,
string host_jid;
if (!ParseUrl(url, &user_id, &auth_token, &host_jid)) {
LOG(WARNING) << "Could not parse URL: " << url;
return NPERR_GENERIC_ERROR;
return false;
}
// Setup pepper context.
device_ = extensions()->acquireDevice(instance(), NPPepper2DDevice);
// Start the threads.
main_thread_.reset(new base::Thread("ChromoClientMain"));
if (!main_thread_->Start()) {
LOG(ERROR) << "Main thread failed to start.";
return NPERR_GENERIC_ERROR;
return false;
}
network_thread_.reset(new JingleThread());
network_thread_->Start();
// Create the chromting objects.
host_connection_.reset(new JingleHostConnection(network_thread_.get()));
/*
view_.reset(new PepperView(main_thread_->message_loop(), device_,
instance()));
client_.reset(new ChromotingClient(main_thread_->message_loop(),
host_connection_.get(), view_.get()));
*/
//client_.reset(new ChromotingClient(main_thread_->message_loop(),
// host_connection_.get(), view_.get()));
// Kick off the connection.
host_connection_->Connect(user_id, auth_token, host_jid, client_.get());
//host_connection_->Connect(user_id, auth_token, host_jid, client_.get());
return NPERR_NO_ERROR;
return true;
}
NPError ChromotingPlugin::Destroy(NPSavedData** save) {
host_connection_->Disconnect();
void ChromotingPlugin::ViewChanged(const PP_Rect& position,
const PP_Rect& clip) {
// TODO(ajwong): This is going to be a race condition when the view changes
// and we're in the middle of a Paint().
LOG(INFO) << "ViewChanged "
<< position.point.x << ","
<< position.point.y << ","
<< position.size.width << ","
<< position.size.height;
// TODO(ajwong): We need to ensure all objects have actually stopped posting
// to the message loop before this point. Right now, we don't have a well
// defined stop for the plugin process, and the thread shutdown is likely a
// race condition.
network_thread_->Stop();
main_thread_->Stop();
// TODO(ajwong): Do we care about the position? Probably not...
if (position.size.width == width_ || position.size.height == height_)
return;
main_thread_.reset();
network_thread_.reset();
return NPERR_NO_ERROR;
width_ = position.size.width;
height_ = position.size.height;
device_context_ = pp::DeviceContext2D(width_, height_, false);
if (!BindGraphicsDeviceContext(device_context_)) {
LOG(ERROR) << "Couldn't bind the device context.";
return;
}
pp::ImageData image(PP_IMAGEDATAFORMAT_BGRA_PREMUL, width_, height_, false);
if (!image.is_null()) {
for (int y = 0; y < image.height(); y++) {
for (int x = 0; x < image.width(); x++) {
*image.GetAddr32(x, y) = 0xccff00cc;
}
}
device_context_.ReplaceContents(&image);
device_context_.Flush(NULL, this);
} else {
LOG(ERROR) << "Unable to allocate image.";
}
//client_->SetViewport(0, 0, width_, height_);
//client_->Repaint();
}
NPError ChromotingPlugin::SetWindow(NPWindow* window) {
width_ = window->width;
height_ = window->height;
client_->SetViewport(0, 0, window->width, window->height);
client_->Repaint();
return NPERR_NO_ERROR;
}
int16 ChromotingPlugin::HandleEvent(void* event) {
NPPepperEvent* npevent = static_cast<NPPepperEvent*>(event);
switch (npevent->type) {
case NPEventType_MouseDown:
// Fall through
case NPEventType_MouseUp:
// Fall through
case NPEventType_MouseMove:
// Fall through
case NPEventType_MouseEnter:
// Fall through
case NPEventType_MouseLeave:
bool ChromotingPlugin::HandleEvent(const PP_Event& event) {
switch (event.type) {
case PP_Event_Type_MouseDown:
case PP_Event_Type_MouseUp:
case PP_Event_Type_MouseMove:
case PP_Event_Type_MouseEnter:
case PP_Event_Type_MouseLeave:
//client_->handle_mouse_event(npevent);
break;
case NPEventType_MouseWheel:
case NPEventType_RawKeyDown:
break;
case NPEventType_KeyDown:
case NPEventType_KeyUp:
break;
case NPEventType_Char:
case PP_Event_Type_Char:
//client_->handle_char_event(npevent);
break;
case NPEventType_Minimize:
case NPEventType_Focus:
case NPEventType_Device:
default:
break;
}
return false;
}
NPError ChromotingPlugin::GetValue(NPPVariable variable, void* value) {
return NPERR_NO_ERROR;
}
NPError ChromotingPlugin::SetValue(NPNVariable variable, void* value) {
return NPERR_NO_ERROR;
}
bool ChromotingPlugin::ParseUrl(const std::string& url,
string* user_id,
string* auth_token,

@ -10,8 +10,9 @@
#include "base/at_exit.h"
#include "base/scoped_ptr.h"
#include "remoting/client/host_connection.h"
#include "remoting/client/pepper/pepper_plugin.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
#include "third_party/ppapi/cpp/device_context_2d.h"
#include "third_party/ppapi/cpp/instance.h"
namespace base {
class Thread;
@ -26,7 +27,7 @@ class PepperView;
class ChromotingClient;
class ChromotingPlugin : public pepper::PepperPlugin {
class ChromotingPlugin : public pp::Instance {
public:
// The mimetype for which this plugin is registered.
//
@ -34,46 +35,27 @@ class ChromotingPlugin : public pepper::PepperPlugin {
// point. I think we should handle a special protocol (eg., chromotocol://)
static const char *kMimeType;
ChromotingPlugin(NPNetscapeFuncs* browser_funcs, NPP instance);
ChromotingPlugin(PP_Instance instance);
virtual ~ChromotingPlugin();
// PepperPlugin implementation.
virtual NPError New(NPMIMEType pluginType, int16 argc, char* argn[],
char* argv[]);
virtual NPError Destroy(NPSavedData** save);
virtual NPError SetWindow(NPWindow* window);
virtual int16 HandleEvent(void* event);
virtual NPError GetValue(NPPVariable variable, void* value);
virtual NPError SetValue(NPNVariable variable, void* value);
virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
virtual bool HandleEvent(const PP_Event& event);
virtual void ViewChanged(const PP_Rect& position, const PP_Rect& clip);
private:
FRIEND_TEST(ChromotingPluginTest, ParseUrl);
FRIEND_TEST(ChromotingPluginTest, TestCaseSetup);
NPDevice* device() { return device_; }
static bool ParseUrl(const std::string& url,
std::string* user_id,
std::string* auth_token,
std::string* host_jid);
// Size of the plugin window.
int width_, height_;
int width_;
int height_;
// Rendering device provided by browser.
NPDevice* device_;
// Since the ChromotingPlugin's lifetime is conceptually the lifetime of the
// object, use it to control running of atexit() calls.
//
// TODO(ajwong): Should this be moved into PepperPlugin? Or maybe even
// higher?
//
// TODO(ajwong): This causes unittests to fail so commenting out for now. We
// need to understand process instantiation better. This may also be a
// non-issue when we are no longer being loaded as a DSO.
//
// base::AtExitManager at_exit_manager_;
pp::DeviceContext2D device_context_;
scoped_ptr<base::Thread> main_thread_;
scoped_ptr<JingleThread> network_thread_;

@ -5,86 +5,18 @@
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "remoting/client/plugin/chromoting_plugin.h"
#include "remoting/client/pepper/fake_browser.h"
#include "testing/gtest/include/gtest/gtest.h"
// Routine to create the PepperPlugin subclass that implements all of the
// plugin-specific functionality.
pepper::PepperPlugin* CreatePlugin(NPNetscapeFuncs* browser_funcs,
NPP instance);
namespace remoting {
// TODO(ajwong): Once ChromotingPlugin stablizes a little more, come up with
// sane unittests.
class ChromotingPluginTest : public testing::Test {
protected:
virtual void SetUp() {
// Set up the fake browser callback routines.
fake_browser_ = Singleton<FakeBrowser>::get();
NPNetscapeFuncs* browser_funcs_ = fake_browser_->GetBrowserFuncs();
instance_.reset(new NPP_t());
// Create the ChromotingPlugin for testing.
pepper::PepperPlugin* pepper_plugin =
CreatePlugin(browser_funcs_, instance_.get());
plugin_.reset(
static_cast<ChromotingPlugin*>(pepper_plugin));
}
virtual void TearDown() {
}
FakeBrowser* fake_browser_;
scoped_ptr<NPP_t> instance_;
scoped_ptr<ChromotingPlugin> plugin_;
};
TEST_F(ChromotingPluginTest, TestCaseSetup) {
ASSERT_TRUE(plugin_->browser() != NULL);
ASSERT_TRUE(plugin_->extensions() != NULL);
ASSERT_TRUE(plugin_->instance() != NULL);
// Device is not set until New() is called.
ASSERT_TRUE(plugin_->device() == NULL);
}
#if 0
TODO(ajwong): reenable once we have the threading sorted out.
TEST_F(ChromotingPluginTest, TestNew) {
NPMIMEType mimetype =
const_cast<NPMIMEType>("pepper-application/x-chromoting-plugin");
int16 argc;
char* argn[4];
char* argv[4];
// Test 0 arguments.
argc = 0;
ASSERT_EQ(NPERR_GENERIC_ERROR, plugin_->New(mimetype, argc, argn, argv));
// Test 1 argument (missing "src").
argc = 1;
argn[0] = const_cast<char*>("noturl");
argv[0] = const_cast<char*>("random.value");
ASSERT_EQ(NPERR_GENERIC_ERROR, plugin_->New(mimetype, argc, argn, argv));
// Test "src" argument.
argc = 1;
argn[0] = const_cast<char*>("src");
argv[0] = const_cast<char*>("chromotocol://name?user=u&auth=a&jid=j");
ASSERT_EQ(NPERR_NO_ERROR, plugin_->New(mimetype, argc, argn, argv));
ASSERT_EQ(NPERR_NO_ERROR, plugin_->Destroy(NULL));
}
TEST_F(ChromotingPluginTest, TestSetWindow) {
NPWindow* window = fake_browser_->GetWindow();
NPError result;
result = plugin_->SetWindow(window);
ASSERT_EQ(NPERR_NO_ERROR, result);
}
#endif
TEST_F(ChromotingPluginTest, ParseUrl) {
const char url[] = "chromotocol://hostid?user=auser&auth=someauth&jid=ajid";
std::string user_id;

@ -8,7 +8,8 @@
#include "base/scoped_ptr.h"
#include "base/task.h"
#include "remoting/client/chromoting_view.h"
#include "remoting/client/pepper/pepper_plugin.h"
#include "third_party/npapi/bindings/npapi.h"
#include "third_party/npapi/bindings/npapi_extensions.h"
class MessageLoop;

@ -20,7 +20,7 @@
['OS=="linux" or OS=="mac"', {
'targets': [
{
'target_name': 'chromoting_client_plugin_lib',
'target_name': 'chromoting_client_plugin',
'type': 'static_library',
'defines': [
'HAVE_STDINT_H', # Required by on2_integer.h
@ -29,16 +29,14 @@
'chromoting_base',
'chromoting_client',
'chromoting_jingle_glue',
'../third_party/ppapi/ppapi.gyp:ppapi_cpp',
'../third_party/zlib/zlib.gyp:zlib',
],
'sources': [
'client/plugin/chromoting_main.cc',
'client/plugin/chromoting_plugin.cc',
'client/plugin/chromoting_plugin.h',
'client/plugin/pepper_view.cc',
'client/plugin/pepper_view.h',
'client/pepper/pepper_plugin.cc',
'client/pepper/pepper_plugin.h',
'../media/base/yuv_convert.cc',
'../media/base/yuv_convert.h',
'../media/base/yuv_row.h',
@ -56,31 +54,7 @@
'cflags': ['-fPIC'],
}],
], # end of 'conditions'
}, # end of target 'chromoting_client_plugin_lib'
# TODO(ajwong): reenable once we figure out the -fPIC issues.
# Client plugin: libchromoting_plugin.so.
# {
# 'target_name': 'chromoting_client_plugin',
# 'type': 'shared_library',
# 'product_name': 'chromoting_plugin',
# 'dependencies': [
# 'chromoting_client_plugin_lib',
# ],
# 'sources': [
# # Required here (rather than in lib) so that functions are
# # exported properly.
# 'client/pepper/pepper_main.cc',
# ],
# 'conditions': [
# ['OS=="linux" and target_arch=="x64" and linux_fpic!=1', {
# # Shared libraries need -fPIC on x86-64
# 'cflags': [
# '-fPIC'
# ],
# }],
# ], # end of 'conditions'
# }, # end of target 'chromoting_client_plugin'
}, # end of target 'chromoting_client_plugin'
# Simple webserver for testing chromoting client plugin.
{
@ -379,17 +353,6 @@
'host/capturer_mac_unittest.cc',
],
}],
['OS=="linux" or OS=="mac"', {
'dependencies': [
'chromoting_client_plugin_lib',
],
'sources': [
'client/plugin/chromoting_plugin_unittest.cc',
'client/pepper/pepper_main.cc',
'client/pepper/fake_browser.cc',
'client/pepper/fake_browser.h',
],
}],
], # end of 'conditions'
}, # end of target 'chromoting_unittests'
], # end of targets