This source file includes following definitions.
- __divdi3
- __udivdi3
- scriptable_object_
- Init
- Save
- GetScriptableObject
- RunOnPluginThread
- SetWindow
- NPDelayedTaskSpringboard
- ScriptableFromObject
- Allocate
- Deallocate
- Invalidate
- HasMethod
- InvokeDefault
- Invoke
- HasProperty
- GetProperty
- SetProperty
- RemoveProperty
- Enumerate
- InitializePlugin
- ShutdownPlugin
- PluginFromInstance
- CreatePlugin
- DestroyPlugin
- GetValue
- HandleEvent
- SetWindow
- DllMain
- NP_GetEntryPoints
- NP_Initialize
- NP_Shutdown
- NP_GetMIMEDescription
- NP_GetValue
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include "base/at_exit.h"
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/stringize_macros.h"
#include "net/socket/ssl_server_socket.h"
#include "remoting/base/plugin_thread_task_runner.h"
#include "remoting/base/resources.h"
#include "remoting/base/string_resources.h"
#include "remoting/host/plugin/host_log_handler.h"
#include "remoting/host/plugin/host_plugin_utils.h"
#include "remoting/host/plugin/host_script_object.h"
#if defined(OS_WIN)
#include "ui/gfx/win/dpi.h"
#endif
#include "third_party/npapi/bindings/npapi.h"
#include "third_party/npapi/bindings/npfunctions.h"
#include "third_party/npapi/bindings/npruntime.h"
#include "ui/base/l10n/l10n_util.h"
#if defined (__GNUC__) && __GNUC__ >= 4
#define EXPORT __attribute__((visibility("default")))
#else
#define EXPORT
#endif
#if defined(OS_WIN)
extern "C" {
int64_t __cdecl __divdi3(int64_t a, int64_t b) {
return a / b;
}
uint64_t __cdecl __udivdi3(uint64_t a, uint64_t b) {
return a / b;
}
}
#endif
using remoting::g_npnetscape_funcs;
using remoting::HostLogHandler;
using remoting::HostNPScriptObject;
using remoting::StringFromNPIdentifier;
namespace {
bool g_initialized = false;
base::AtExitManager* g_at_exit_manager = NULL;
std::string* g_ui_name = NULL;
std::string* g_ui_description = NULL;
class HostNPPlugin : public remoting::PluginThreadTaskRunner::Delegate {
public:
HostNPPlugin(NPP instance, uint16 mode)
: instance_(instance),
scriptable_object_(NULL) {
plugin_task_runner_ = new remoting::PluginThreadTaskRunner(this);
plugin_auto_task_runner_ =
new remoting::AutoThreadTaskRunner(
plugin_task_runner_,
base::Bind(&remoting::PluginThreadTaskRunner::Quit,
plugin_task_runner_));
}
virtual ~HostNPPlugin() {
if (scriptable_object_) {
DCHECK_EQ(scriptable_object_->referenceCount, 1UL);
g_npnetscape_funcs->releaseobject(scriptable_object_);
scriptable_object_ = NULL;
}
plugin_auto_task_runner_ = NULL;
plugin_task_runner_->DetachAndRunShutdownLoop();
}
bool Init(int16 argc, char** argn, char** argv, NPSavedData* saved) {
#if defined(OS_MACOSX)
NPBool supports_core_graphics = false;
NPError err = g_npnetscape_funcs->getvalue(instance_,
NPNVsupportsCoreGraphicsBool,
&supports_core_graphics);
if (err == NPERR_NO_ERROR && supports_core_graphics) {
g_npnetscape_funcs->setvalue(instance_, NPPVpluginDrawingModel,
reinterpret_cast<void*>(NPDrawingModelCoreGraphics));
} else {
LOG(ERROR) << "No Core Graphics support";
return false;
}
NPBool supports_cocoa = false;
err = g_npnetscape_funcs->getvalue(instance_, NPNVsupportsCocoaBool,
&supports_cocoa);
if (err == NPERR_NO_ERROR && supports_cocoa) {
g_npnetscape_funcs->setvalue(instance_, NPPVpluginEventModel,
reinterpret_cast<void*>(NPEventModelCocoa));
} else {
LOG(ERROR) << "No Cocoa Event Model support";
return false;
}
#endif
net::EnableSSLServerSockets();
return true;
}
bool Save(NPSavedData** saved) {
return true;
}
NPObject* GetScriptableObject() {
if (!scriptable_object_) {
static NPClass npc_ref_object = {
NP_CLASS_STRUCT_VERSION,
&Allocate,
&Deallocate,
&Invalidate,
&HasMethod,
&Invoke,
&InvokeDefault,
&HasProperty,
&GetProperty,
&SetProperty,
&RemoveProperty,
&Enumerate,
NULL
};
scriptable_object_ = g_npnetscape_funcs->createobject(instance_,
&npc_ref_object);
}
return scriptable_object_;
}
virtual bool RunOnPluginThread(
base::TimeDelta delay, void(function)(void*), void* data) OVERRIDE {
if (delay == base::TimeDelta()) {
g_npnetscape_funcs->pluginthreadasynccall(instance_, function, data);
} else {
base::AutoLock auto_lock(timers_lock_);
uint32_t timer_id = g_npnetscape_funcs->scheduletimer(
instance_, delay.InMilliseconds(), false, &NPDelayedTaskSpringboard);
DelayedTask task = {function, data};
timers_[timer_id] = task;
}
return true;
}
void SetWindow(NPWindow* np_window) {
if (scriptable_object_) {
ScriptableFromObject(scriptable_object_)->SetWindow(np_window);
}
}
static void NPDelayedTaskSpringboard(NPP npp, uint32_t timer_id) {
HostNPPlugin* self = reinterpret_cast<HostNPPlugin*>(npp->pdata);
DelayedTask task;
{
base::AutoLock auto_lock(self->timers_lock_);
std::map<uint32_t, DelayedTask>::iterator it =
self->timers_.find(timer_id);
CHECK(it != self->timers_.end());
task = it->second;
self->timers_.erase(it);
}
task.function(task.data);
}
private:
struct ScriptableNPObject : public NPObject {
HostNPScriptObject* scriptable_object;
};
struct DelayedTask {
void (*function)(void*);
void* data;
};
static HostNPScriptObject* ScriptableFromObject(NPObject* obj) {
return reinterpret_cast<ScriptableNPObject*>(obj)->scriptable_object;
}
static NPObject* Allocate(NPP npp, NPClass* aClass) {
VLOG(2) << "static Allocate";
ScriptableNPObject* object =
reinterpret_cast<ScriptableNPObject*>(
g_npnetscape_funcs->memalloc(sizeof(ScriptableNPObject)));
HostNPPlugin* plugin = reinterpret_cast<HostNPPlugin*>(npp->pdata);
object->_class = aClass;
object->referenceCount = 1;
object->scriptable_object =
new HostNPScriptObject(npp, object, plugin->plugin_auto_task_runner_);
return object;
}
static void Deallocate(NPObject* npobj) {
VLOG(2) << "static Deallocate";
if (npobj) {
Invalidate(npobj);
g_npnetscape_funcs->memfree(npobj);
}
}
static void Invalidate(NPObject* npobj) {
if (npobj) {
ScriptableNPObject* object = reinterpret_cast<ScriptableNPObject*>(npobj);
if (object->scriptable_object) {
delete object->scriptable_object;
object->scriptable_object = NULL;
}
}
}
static bool HasMethod(NPObject* obj, NPIdentifier method_name) {
VLOG(2) << "static HasMethod";
HostNPScriptObject* scriptable = ScriptableFromObject(obj);
if (!scriptable) return false;
std::string method_name_string = StringFromNPIdentifier(method_name);
if (method_name_string.empty())
return false;
return scriptable->HasMethod(method_name_string);
}
static bool InvokeDefault(NPObject* obj,
const NPVariant* args,
uint32_t argCount,
NPVariant* result) {
VLOG(2) << "static InvokeDefault";
HostNPScriptObject* scriptable = ScriptableFromObject(obj);
if (!scriptable) return false;
return scriptable->InvokeDefault(args, argCount, result);
}
static bool Invoke(NPObject* obj,
NPIdentifier method_name,
const NPVariant* args,
uint32_t argCount,
NPVariant* result) {
VLOG(2) << "static Invoke";
HostNPScriptObject* scriptable = ScriptableFromObject(obj);
if (!scriptable)
return false;
std::string method_name_string = StringFromNPIdentifier(method_name);
if (method_name_string.empty())
return false;
return scriptable->Invoke(method_name_string, args, argCount, result);
}
static bool HasProperty(NPObject* obj, NPIdentifier property_name) {
VLOG(2) << "static HasProperty";
HostNPScriptObject* scriptable = ScriptableFromObject(obj);
if (!scriptable) return false;
std::string property_name_string = StringFromNPIdentifier(property_name);
if (property_name_string.empty())
return false;
return scriptable->HasProperty(property_name_string);
}
static bool GetProperty(NPObject* obj,
NPIdentifier property_name,
NPVariant* result) {
VLOG(2) << "static GetProperty";
HostNPScriptObject* scriptable = ScriptableFromObject(obj);
if (!scriptable) return false;
std::string property_name_string = StringFromNPIdentifier(property_name);
if (property_name_string.empty())
return false;
return scriptable->GetProperty(property_name_string, result);
}
static bool SetProperty(NPObject* obj,
NPIdentifier property_name,
const NPVariant* value) {
VLOG(2) << "static SetProperty";
HostNPScriptObject* scriptable = ScriptableFromObject(obj);
if (!scriptable) return false;
std::string property_name_string = StringFromNPIdentifier(property_name);
if (property_name_string.empty())
return false;
return scriptable->SetProperty(property_name_string, value);
}
static bool RemoveProperty(NPObject* obj, NPIdentifier property_name) {
VLOG(2) << "static RemoveProperty";
HostNPScriptObject* scriptable = ScriptableFromObject(obj);
if (!scriptable) return false;
std::string property_name_string = StringFromNPIdentifier(property_name);
if (property_name_string.empty())
return false;
return scriptable->RemoveProperty(property_name_string);
}
static bool Enumerate(NPObject* obj,
NPIdentifier** value,
uint32_t* count) {
VLOG(2) << "static Enumerate";
HostNPScriptObject* scriptable = ScriptableFromObject(obj);
if (!scriptable) return false;
std::vector<std::string> values;
bool is_good = scriptable->Enumerate(&values);
if (is_good) {
*count = values.size();
*value = reinterpret_cast<NPIdentifier*>(
g_npnetscape_funcs->memalloc(sizeof(NPIdentifier) * (*count)));
for (uint32_t i = 0; i < *count; ++i) {
(*value)[i] =
g_npnetscape_funcs->getstringidentifier(values[i].c_str());
}
}
return is_good;
}
NPP instance_;
NPObject* scriptable_object_;
scoped_refptr<remoting::PluginThreadTaskRunner> plugin_task_runner_;
scoped_refptr<remoting::AutoThreadTaskRunner> plugin_auto_task_runner_;
std::map<uint32_t, DelayedTask> timers_;
base::Lock timers_lock_;
};
void InitializePlugin() {
if (g_initialized)
return;
g_initialized = true;
g_at_exit_manager = new base::AtExitManager;
CommandLine::Init(0, NULL);
if (remoting::LoadResources("")) {
g_ui_name = new std::string(
l10n_util::GetStringUTF8(IDS_REMOTING_HOST_PLUGIN_NAME));
g_ui_description = new std::string(
l10n_util::GetStringUTF8(IDS_REMOTING_HOST_PLUGIN_DESCRIPTION));
} else {
g_ui_name = new std::string();
g_ui_description = new std::string();
}
}
void ShutdownPlugin() {
delete g_ui_name;
delete g_ui_description;
remoting::UnloadResources();
delete g_at_exit_manager;
}
HostNPPlugin* PluginFromInstance(NPP instance) {
return reinterpret_cast<HostNPPlugin*>(instance->pdata);
}
NPError CreatePlugin(NPMIMEType pluginType,
NPP instance,
uint16 mode,
int16 argc,
char** argn,
char** argv,
NPSavedData* saved) {
VLOG(2) << "CreatePlugin";
HostLogHandler::RegisterLogMessageHandler();
HostNPPlugin* plugin = new HostNPPlugin(instance, mode);
instance->pdata = plugin;
if (!plugin->Init(argc, argn, argv, saved)) {
delete plugin;
instance->pdata = NULL;
return NPERR_INVALID_PLUGIN_ERROR;
} else {
return NPERR_NO_ERROR;
}
}
NPError DestroyPlugin(NPP instance,
NPSavedData** save) {
VLOG(2) << "DestroyPlugin";
HostNPPlugin* plugin = PluginFromInstance(instance);
if (plugin) {
plugin->Save(save);
delete plugin;
instance->pdata = NULL;
return NPERR_NO_ERROR;
} else {
return NPERR_INVALID_PLUGIN_ERROR;
}
}
NPError GetValue(NPP instance, NPPVariable variable, void* value) {
InitializePlugin();
switch(variable) {
default:
VLOG(2) << "GetValue - default " << variable;
return NPERR_GENERIC_ERROR;
case NPPVpluginNameString:
VLOG(2) << "GetValue - name string";
*reinterpret_cast<const char**>(value) = g_ui_name->c_str();
break;
case NPPVpluginDescriptionString:
VLOG(2) << "GetValue - description string";
*reinterpret_cast<const char**>(value) = g_ui_description->c_str();
break;
case NPPVpluginNeedsXEmbed:
VLOG(2) << "GetValue - NeedsXEmbed";
*(static_cast<NPBool*>(value)) = true;
break;
case NPPVpluginScriptableNPObject:
VLOG(2) << "GetValue - scriptable object";
HostNPPlugin* plugin = PluginFromInstance(instance);
if (!plugin)
return NPERR_INVALID_PLUGIN_ERROR;
NPObject* scriptable_object = plugin->GetScriptableObject();
g_npnetscape_funcs->retainobject(scriptable_object);
*reinterpret_cast<NPObject**>(value) = scriptable_object;
break;
}
return NPERR_NO_ERROR;
}
NPError HandleEvent(NPP instance, void* ev) {
VLOG(2) << "HandleEvent";
return NPERR_NO_ERROR;
}
NPError SetWindow(NPP instance, NPWindow* pNPWindow) {
VLOG(2) << "SetWindow";
HostNPPlugin* plugin = PluginFromInstance(instance);
if (plugin) {
plugin->SetWindow(pNPWindow);
}
return NPERR_NO_ERROR;
}
}
#if defined(OS_WIN)
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
switch (dwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
#endif
extern "C" {
EXPORT NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* nppfuncs) {
VLOG(2) << "NP_GetEntryPoints";
nppfuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
nppfuncs->newp = &CreatePlugin;
nppfuncs->destroy = &DestroyPlugin;
nppfuncs->getvalue = &GetValue;
nppfuncs->event = &HandleEvent;
nppfuncs->setwindow = &SetWindow;
return NPERR_NO_ERROR;
}
EXPORT NPError API_CALL NP_Initialize(NPNetscapeFuncs* npnetscape_funcs
#if defined(OS_POSIX) && !defined(OS_MACOSX)
, NPPluginFuncs* nppfuncs
#endif
) {
VLOG(2) << "NP_Initialize";
InitializePlugin();
if(npnetscape_funcs == NULL)
return NPERR_INVALID_FUNCTABLE_ERROR;
if(((npnetscape_funcs->version & 0xff00) >> 8) > NP_VERSION_MAJOR)
return NPERR_INCOMPATIBLE_VERSION_ERROR;
g_npnetscape_funcs = npnetscape_funcs;
#if defined(OS_POSIX) && !defined(OS_MACOSX)
NP_GetEntryPoints(nppfuncs);
#endif
#if defined(OS_WIN)
gfx::EnableHighDPISupport();
#endif
return NPERR_NO_ERROR;
}
EXPORT NPError API_CALL NP_Shutdown() {
VLOG(2) << "NP_Shutdown";
ShutdownPlugin();
return NPERR_NO_ERROR;
}
#if defined(OS_POSIX) && !defined(OS_MACOSX)
EXPORT const char* API_CALL NP_GetMIMEDescription(void) {
VLOG(2) << "NP_GetMIMEDescription";
return STRINGIZE(HOST_PLUGIN_MIME_TYPE) "::";
}
EXPORT NPError API_CALL NP_GetValue(void* npp,
NPPVariable variable,
void* value) {
return GetValue((NPP)npp, variable, value);
}
#endif
}