// Copyright (c) 2012 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 "content/test/plugin/plugin_client.h"
#include "base/strings/string_util.h"
#include "content/test/plugin/plugin_execute_stream_javascript.h"
#include "content/test/plugin/plugin_test.h"
#include "content/test/plugin/plugin_test_factory.h"
namespace NPAPIClient {
NPNetscapeFuncs* PluginClient::host_functions_;
NPError PluginClient::GetEntryPoints(NPPluginFuncs* pFuncs) {
if (pFuncs == NULL)
return NPERR_INVALID_FUNCTABLE_ERROR;
if (pFuncs->size < sizeof(NPPluginFuncs))
return NPERR_INVALID_FUNCTABLE_ERROR;
pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
pFuncs->newp = NPP_New;
pFuncs->destroy = NPP_Destroy;
pFuncs->setwindow = NPP_SetWindow;
pFuncs->newstream = NPP_NewStream;
pFuncs->destroystream = NPP_DestroyStream;
pFuncs->asfile = NPP_StreamAsFile;
pFuncs->writeready = NPP_WriteReady;
pFuncs->write = NPP_Write;
pFuncs->print = NPP_Print;
pFuncs->event = NPP_HandleEvent;
pFuncs->urlnotify = NPP_URLNotify;
pFuncs->getvalue = NPP_GetValue;
pFuncs->setvalue = NPP_SetValue;
pFuncs->javaClass = NULL;
pFuncs->urlredirectnotify = NPP_URLRedirectNotify;
pFuncs->clearsitedata = NPP_ClearSiteData;
return NPERR_NO_ERROR;
}
NPError PluginClient::Initialize(NPNetscapeFuncs* pFuncs) {
if (pFuncs == NULL) {
return NPERR_INVALID_FUNCTABLE_ERROR;
}
if (static_cast<unsigned char>((pFuncs->version >> 8) & 0xff) >
NP_VERSION_MAJOR) {
return NPERR_INCOMPATIBLE_VERSION_ERROR;
}
#if defined(OS_WIN)
// Check if we should crash.
HANDLE crash_event = CreateEvent(NULL, TRUE, FALSE, L"TestPluginCrashOnInit");
if (WaitForSingleObject(crash_event, 0) == WAIT_OBJECT_0) {
int *zero = NULL;
*zero = 0;
}
CloseHandle(crash_event);
#endif
host_functions_ = pFuncs;
return NPERR_NO_ERROR;
}
NPError PluginClient::Shutdown() {
return NPERR_NO_ERROR;
}
} // namespace NPAPIClient
extern "C" {
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
int16 argc, char* argn[], char* argv[], NPSavedData* saved) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
NPAPIClient::PluginTest* new_test = NULL;
if (mode == NP_FULL) {
new_test = new::NPAPIClient::ExecuteStreamJavaScript(
instance, NPAPIClient::PluginClient::HostFunctions());
} else {
// We look at the test name requested via the plugin arguments. We match
// that against a given test and try to instantiate it.
// lookup the name parameter
std::string test_name;
for (int name_index = 0; name_index < argc; name_index++) {
if (base::strcasecmp(argn[name_index], "name") == 0) {
test_name = argv[name_index];
break;
}
}
if (test_name.empty())
return NPERR_GENERIC_ERROR; // no name found
new_test = NPAPIClient::CreatePluginTest(test_name,
instance, NPAPIClient::PluginClient::HostFunctions());
if (new_test == NULL) {
// If we don't have a test case for this, create a
// generic one which basically never fails.
LOG(WARNING) << "Unknown test name '" << test_name
<< "'; using default test.";
new_test = new NPAPIClient::PluginTest(instance,
NPAPIClient::PluginClient::HostFunctions());
}
}
#if defined(OS_MACOSX)
// Set modern drawing and event models.
NPError drawing_ret = NPAPIClient::PluginClient::HostFunctions()->setvalue(
instance, NPPVpluginDrawingModel, (void*)NPDrawingModelCoreGraphics);
NPError event_ret = NPAPIClient::PluginClient::HostFunctions()->setvalue(
instance, NPPVpluginEventModel, (void*)NPEventModelCocoa);
if (drawing_ret != NPERR_NO_ERROR || event_ret != NPERR_NO_ERROR)
return NPERR_INCOMPATIBLE_VERSION_ERROR;
#endif
NPError ret = new_test->New(mode, argc, (const char**)argn,
(const char**)argv, saved);
if ((ret == NPERR_NO_ERROR) && new_test->IsWindowless()) {
NPAPIClient::PluginClient::HostFunctions()->setvalue(
instance, NPPVpluginWindowBool, NULL);
}
return ret;
}
NPError NPP_Destroy(NPP instance, NPSavedData** save) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
NPAPIClient::PluginTest* plugin =
reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
NPError rv = plugin->Destroy();
delete plugin;
return rv;
}
NPError NPP_SetWindow(NPP instance, NPWindow* pNPWindow) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
NPAPIClient::PluginTest* plugin =
reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->SetWindow(pNPWindow);
}
NPError NPP_NewStream(NPP instance, NPMIMEType type,
NPStream* stream, NPBool seekable, uint16* stype) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
NPAPIClient::PluginTest* plugin =
reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->NewStream(type, stream, seekable, stype);
}
int32 NPP_WriteReady(NPP instance, NPStream *stream) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
NPAPIClient::PluginTest* plugin =
reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->WriteReady(stream);
}
int32 NPP_Write(NPP instance, NPStream *stream, int32 offset,
int32 len, void *buffer) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
NPAPIClient::PluginTest* plugin =
reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->Write(stream, offset, len, buffer);
}
NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
NPAPIClient::PluginTest* plugin =
reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->DestroyStream(stream, reason);
}
void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {
if (instance == NULL)
return;
NPAPIClient::PluginTest* plugin =
reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->StreamAsFile(stream, fname);
}
void NPP_Print(NPP instance, NPPrint* printInfo) {
if (instance == NULL)
return;
// XXXMB - do work here.
}
void NPP_URLNotify(NPP instance, const char* url, NPReason reason,
void* notifyData) {
if (instance == NULL)
return;
NPAPIClient::PluginTest* plugin =
reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->URLNotify(url, reason, notifyData);
}
NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
if (variable == NPPVpluginNeedsXEmbed) {
*static_cast<NPBool*>(value) = 1;
return NPERR_NO_ERROR;
}
// XXXMB - do work here.
return NPERR_GENERIC_ERROR;
}
NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
// XXXMB - do work here.
return NPERR_GENERIC_ERROR;
}
int16 NPP_HandleEvent(NPP instance, void* event) {
if (instance == NULL)
return 0;
NPAPIClient::PluginTest* plugin =
reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
return plugin->HandleEvent(event);
}
void NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status,
void* notify_data) {
if (instance) {
NPAPIClient::PluginTest* plugin =
reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata);
plugin->URLRedirectNotify(url, status, notify_data);
}
}
NPError NPP_ClearSiteData(const char* site,
uint64 flags,
uint64 max_age) {
VLOG(0) << "NPP_ClearSiteData called";
return NPERR_NO_ERROR;
}
} // extern "C"