// 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 "chrome/default_plugin/plugin_main.h" #include "base/logging.h" #include "base/string_util.h" #include "chrome/default_plugin/plugin_impl.h" #include "webkit/glue/webkit_glue.h" namespace default_plugin { #if defined(OS_WIN) // // Forward declare the linker-provided pseudo variable for the // current module handle. // extern "C" IMAGE_DOS_HEADER __ImageBase; // get the handle to the currently executing module inline HMODULE GetCurrentModuleHandle() { return reinterpret_cast(&__ImageBase); } #endif // Initialized in NP_Initialize. NPNetscapeFuncs* g_browser = NULL; NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* funcs) { // Be explicit about the namespace, because all internal plugins have // functions with these names and some might accidentally put them into the // global namespace. In that case, the linker might prefer the global one. funcs->version = 11; funcs->size = sizeof(*funcs); funcs->newp = default_plugin::NPP_New; funcs->destroy = default_plugin::NPP_Destroy; funcs->setwindow = default_plugin::NPP_SetWindow; funcs->newstream = default_plugin::NPP_NewStream; funcs->destroystream = default_plugin::NPP_DestroyStream; funcs->writeready = default_plugin::NPP_WriteReady; funcs->write = default_plugin::NPP_Write; funcs->asfile = NULL; funcs->print = NULL; funcs->event = default_plugin::NPP_HandleEvent; funcs->urlnotify = default_plugin::NPP_URLNotify; #if defined(OS_POSIX) && !defined(OS_MACOSX) funcs->getvalue = default_plugin::NPP_GetValue; #else funcs->getvalue = NULL; #endif funcs->setvalue = NULL; return NPERR_NO_ERROR; } NPError API_CALL NP_Initialize(NPNetscapeFuncs* funcs) { g_browser = funcs; return 0; } #if defined(OS_POSIX) && !defined(OS_MACOSX) NPError API_CALL NP_Initialize(NPNetscapeFuncs* funcs, NPPluginFuncs* p_funcs) { NPError err = NP_Initialize(funcs); if (err != NPERR_NO_ERROR) return err; return NP_GetEntryPoints(p_funcs); } #endif NPError API_CALL NP_Shutdown(void) { g_browser = NULL; return NPERR_NO_ERROR; } namespace { // This function is only invoked when the default plugin is invoked // with a special mime type application/chromium-test-default-plugin void SignalTestResult(NPP instance) { NPObject *window_obj = NULL; g_browser->getvalue(instance, NPNVWindowNPObject, &window_obj); if (!window_obj) { NOTREACHED(); return; } std::string script = "javascript:onSuccess()"; NPString script_string; script_string.UTF8Characters = script.c_str(); script_string.UTF8Length = static_cast(script.length()); NPVariant result_var; g_browser->evaluate(instance, window_obj, &script_string, &result_var); g_browser->releaseobject(window_obj); } } // namespace CHROMIUM_DefaultPluginTest bool NegotiateModels(NPP instance) { #if defined(OS_MACOSX) NPError err; // Set drawing model to core graphics NPBool supportsCoreGraphics = false; err = g_browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics); if (err != NPERR_NO_ERROR || !supportsCoreGraphics) { NOTREACHED(); return false; } err = g_browser->setvalue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelCoreGraphics); if (err != NPERR_NO_ERROR) { NOTREACHED(); return false; } // Set event model to cocoa NPBool supportsCocoaEvents = false; err = g_browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoaEvents); if (err != NPERR_NO_ERROR || !supportsCocoaEvents) { NOTREACHED(); return false; } err = g_browser->setvalue(instance, NPPVpluginEventModel, (void*)NPEventModelCocoa); if (err != NPERR_NO_ERROR) { NOTREACHED(); return false; } #elif defined(OS_POSIX) NPError err; // Check that chrome still supports xembed. NPBool supportsXEmbed = false; err = g_browser->getvalue(instance, NPNVSupportsXEmbedBool, &supportsXEmbed); if (err != NPERR_NO_ERROR || !supportsXEmbed) { NOTREACHED(); return false; } // Check that the toolkit is still gtk2. NPNToolkitType toolkit; err = g_browser->getvalue(instance, NPNVToolkit, &toolkit); if (err != NPERR_NO_ERROR || toolkit != NPNVGtk2) { NOTREACHED(); return false; } #endif return true; } NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved) { if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; // We don't want the null plugin to work in the following cases:- // 1. Test-shell // 2. The plugin is running in the renderer process. if (webkit_glue::IsPluginRunningInRendererProcess()) { return NPERR_GENERIC_ERROR; } if (!NegotiateModels(instance)) return NPERR_INCOMPATIBLE_VERSION_ERROR; PluginInstallerImpl* plugin_impl = new PluginInstallerImpl(mode); plugin_impl->Initialize( #if defined(OS_WIN) GetCurrentModuleHandle(), #else NULL, #endif instance, plugin_type, argc, argn, argv); instance->pdata = reinterpret_cast(plugin_impl); if (!base::strcasecmp(plugin_type, "application/chromium-test-default-plugin")) { SignalTestResult(instance); } return NPERR_NO_ERROR; } NPError NPP_Destroy(NPP instance, NPSavedData** save) { PluginInstallerImpl* plugin_impl = reinterpret_cast(instance->pdata); if (plugin_impl) { plugin_impl->Shutdown(); delete plugin_impl; } return NPERR_NO_ERROR; } NPError NPP_SetWindow(NPP instance, NPWindow* window_info) { if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; if (window_info == NULL) { NOTREACHED(); return NPERR_GENERIC_ERROR; } PluginInstallerImpl* plugin_impl = reinterpret_cast(instance->pdata); if (plugin_impl == NULL) { NOTREACHED(); return NPERR_GENERIC_ERROR; } if (!plugin_impl->NPP_SetWindow(window_info)) { delete plugin_impl; return NPERR_GENERIC_ERROR; } return NPERR_NO_ERROR; } NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype) { if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; PluginInstallerImpl* plugin_impl = reinterpret_cast(instance->pdata); if (!plugin_impl) { NOTREACHED(); return NPERR_INVALID_INSTANCE_ERROR; } plugin_impl->NewStream(stream); return NPERR_NO_ERROR; } NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) { if (instance == NULL) return NPERR_INVALID_INSTANCE_ERROR; PluginInstallerImpl* plugin_impl = reinterpret_cast(instance->pdata); if (!plugin_impl) { NOTREACHED(); return NPERR_INVALID_INSTANCE_ERROR; } plugin_impl->DestroyStream(stream, reason); return NPERR_NO_ERROR; } int32_t NPP_WriteReady(NPP instance, NPStream* stream) { if (instance == NULL) return 0; PluginInstallerImpl* plugin_impl = reinterpret_cast(instance->pdata); if (!plugin_impl) { NOTREACHED(); return 0; } if (plugin_impl->WriteReady(stream)) return 0x7FFFFFFF; return 0; } int32_t NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer) { if (instance == NULL) return 0; PluginInstallerImpl* plugin_impl = reinterpret_cast(instance->pdata); if (!plugin_impl) { NOTREACHED(); return 0; } return plugin_impl->Write(stream, offset, len, buffer); } void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) { if (instance != NULL) { PluginInstallerImpl* plugin_impl = reinterpret_cast(instance->pdata); if (!plugin_impl) { NOTREACHED(); return; } plugin_impl->URLNotify(url, reason); } } #if defined(OS_POSIX) && !defined(OS_MACOSX) NPError NPP_GetValue(NPP instance, NPPVariable variable, void* value) { switch (variable) { case NPPVpluginNeedsXEmbed: *static_cast(value) = true; return NPERR_NO_ERROR; default: return NPERR_INVALID_PARAM; } } #endif int16_t NPP_HandleEvent(NPP instance, void* event) { if (instance == NULL) return 0; PluginInstallerImpl* plugin_impl = reinterpret_cast(instance->pdata); return plugin_impl->NPP_HandleEvent(event); } } // default_plugin