diff options
author | apatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-09 18:35:53 +0000 |
---|---|---|
committer | apatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-09 18:35:53 +0000 |
commit | 9bcc6daa3287203a358e782d2e63f53ac18102e1 (patch) | |
tree | b9fcca846890a50e387175def5c979dcc4c4bb4f /o3d | |
parent | 1279ace64f4bdd009ec06528cf6c94e11b48bf69 (diff) | |
download | chromium_src-9bcc6daa3287203a358e782d2e63f53ac18102e1.zip chromium_src-9bcc6daa3287203a358e782d2e63f53ac18102e1.tar.gz chromium_src-9bcc6daa3287203a358e782d2e63f53ac18102e1.tar.bz2 |
In preparation for becoming an internal plugin in chrome I did these things:
- Move declarations in the global namespace into the o3d namespace to avoid conflicts with Chrome.
- Ifdef out code that we do not want to run as an internal plugin (like breakpad, DllMain, etc)
- Prevent NP_Initialize, etc from being exported as an internal plugin.
Unfortunately I had to move functions around to group them by namespace so the diffs look like there is more change than there actually is.
Review URL: http://codereview.chromium.org/149130
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20285 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/plugin/cross/blacklist.cc | 3 | ||||
-rw-r--r-- | o3d/plugin/cross/config.h | 4 | ||||
-rw-r--r-- | o3d/plugin/cross/config_common.cc | 3 | ||||
-rw-r--r-- | o3d/plugin/cross/main.cc | 234 | ||||
-rw-r--r-- | o3d/plugin/cross/main.h | 125 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.cc | 18 | ||||
-rw-r--r-- | o3d/plugin/linux/main_linux.cc | 386 | ||||
-rw-r--r-- | o3d/plugin/mac/config_mac.mm | 3 | ||||
-rw-r--r-- | o3d/plugin/mac/graphics_utils_mac.h | 4 | ||||
-rw-r--r-- | o3d/plugin/mac/graphics_utils_mac.mm | 4 | ||||
-rw-r--r-- | o3d/plugin/mac/main_mac.mm | 1024 | ||||
-rw-r--r-- | o3d/plugin/mac/plugin_mac.h | 3 | ||||
-rw-r--r-- | o3d/plugin/mac/plugin_mac.mm | 43 | ||||
-rw-r--r-- | o3d/plugin/win/config.cc | 3 | ||||
-rw-r--r-- | o3d/plugin/win/main_win.cc | 634 | ||||
-rw-r--r-- | o3d/plugin/win/update_lock.cc | 4 | ||||
-rw-r--r-- | o3d/plugin/win/update_lock.h | 4 |
17 files changed, 1294 insertions, 1205 deletions
diff --git a/o3d/plugin/cross/blacklist.cc b/o3d/plugin/cross/blacklist.cc index 270c4df..9a0b33f 100644 --- a/o3d/plugin/cross/blacklist.cc +++ b/o3d/plugin/cross/blacklist.cc @@ -35,6 +35,8 @@ #include "plugin/cross/config.h" #include "base/logging.h" +namespace o3d { + // Checks the driver GUID against the blacklist file. Returns true if there's a // match [this driver is blacklisted] or if an IO error occurred. Check the // state of input_file to determine which it was. @@ -68,3 +70,4 @@ bool IsDriverBlacklisted(std::ifstream *input_file, unsigned int guid) { CHECK(input_file->eof()); return false; } +} // namespace o3d diff --git a/o3d/plugin/cross/config.h b/o3d/plugin/cross/config.h index 58ecc00..45fbaf5 100644 --- a/o3d/plugin/cross/config.h +++ b/o3d/plugin/cross/config.h @@ -40,6 +40,8 @@ #include <string> #include "plugin/cross/o3d_glue.h" +namespace o3d { + // Returns the user agent string. // Arguments: // npp: plugin instance. @@ -112,4 +114,6 @@ bool GetUserAgentMetrics(NPP npp); bool GetOpenGLMetrics(); +} // namespace o3d + #endif // O3D_PLUGIN_CROSS_CONFIG_H_ diff --git a/o3d/plugin/cross/config_common.cc b/o3d/plugin/cross/config_common.cc index 35d02f7..180443c 100644 --- a/o3d/plugin/cross/config_common.cc +++ b/o3d/plugin/cross/config_common.cc @@ -52,6 +52,8 @@ using glue::_o3d::GetServiceLocator; +namespace o3d { + // Gets the value of "navigator.userAgent" in the JavaScript context, which // contains the user agent string. std::string GetUserAgent(NPP npp) { @@ -213,3 +215,4 @@ bool CheckConfig(NPP npp) { if (!CheckUserAgent(npp, user_agent)) return false; return true; } +} // namespace o3d diff --git a/o3d/plugin/cross/main.cc b/o3d/plugin/cross/main.cc index 5f08407..23265e6 100644 --- a/o3d/plugin/cross/main.cc +++ b/o3d/plugin/cross/main.cc @@ -35,129 +35,141 @@ using glue::_o3d::PluginObject; using glue::StreamManager; +#if !defined(O3D_INTERNAL_PLUGIN) + int BreakpadEnabler::scope_count_ = 0; // Used for breakpad crash handling ExceptionManager *g_exception_manager = NULL; -extern "C" { - char *NP_GetMIMEDescription(void) { - return O3D_PLUGIN_MIME_TYPE "::O3D MIME"; - } - - NPError NP_GetValue(void *instance, NPPVariable variable, void *value) { - switch (variable) { - case NPPVpluginNameString: - *static_cast<char **>(value) = O3D_PLUGIN_NAME; - break; - case NPPVpluginDescriptionString: - *static_cast<char **>(value) = O3D_PLUGIN_DESCRIPTION; - break; - default: - return NPERR_INVALID_PARAM; - break; - } - return NPERR_NO_ERROR; - } - - NPError OSCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) { - HANDLE_CRASHES; - pluginFuncs->version = 11; - pluginFuncs->size = sizeof(*pluginFuncs); - pluginFuncs->newp = NPP_New; - pluginFuncs->destroy = NPP_Destroy; - pluginFuncs->setwindow = NPP_SetWindow; - pluginFuncs->newstream = NPP_NewStream; - pluginFuncs->destroystream = NPP_DestroyStream; - pluginFuncs->asfile = NPP_StreamAsFile; - pluginFuncs->writeready = NPP_WriteReady; - pluginFuncs->write = NPP_Write; - pluginFuncs->print = NPP_Print; - pluginFuncs->event = NPP_HandleEvent; - pluginFuncs->urlnotify = NPP_URLNotify; - pluginFuncs->getvalue = NPP_GetValue; - pluginFuncs->setvalue = NPP_SetValue; +#endif // O3D_INTERNAL_PLUGIN - return NPERR_NO_ERROR; - } +namespace o3d { - NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, - NPBool seekable, uint16 *stype) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - StreamManager *stream_manager = obj->stream_manager(); - if (stream_manager->NewStream(stream, stype)) { - return NPERR_NO_ERROR; - } else { - // TODO: find out which error we should return - return NPERR_INVALID_PARAM; - } - } +char *NP_GetMIMEDescription(void) { + return O3D_PLUGIN_MIME_TYPE "::O3D MIME"; +} - NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - StreamManager *stream_manager = obj->stream_manager(); - if (stream_manager->DestroyStream(stream, reason)) { - return NPERR_NO_ERROR; - } else { - // TODO: find out which error we should return +NPError NP_GetValue(void *instance, NPPVariable variable, void *value) { + switch (variable) { + case NPPVpluginNameString: + *static_cast<char **>(value) = O3D_PLUGIN_NAME; + break; + case NPPVpluginDescriptionString: + *static_cast<char **>(value) = O3D_PLUGIN_DESCRIPTION; + break; + default: return NPERR_INVALID_PARAM; - } + break; } - - int32 NPP_WriteReady(NPP instance, NPStream *stream) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - StreamManager *stream_manager = obj->stream_manager(); - return stream_manager->WriteReady(stream); - } - - int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, - void *buffer) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - StreamManager *stream_manager = obj->stream_manager(); - return stream_manager->Write(stream, offset, len, buffer); - } - - void NPP_Print(NPP instance, NPPrint *platformPrint) { - HANDLE_CRASHES; - } - - void NPP_URLNotify(NPP instance, const char *url, NPReason reason, - void *notifyData) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - StreamManager *stream_manager = obj->stream_manager(); - stream_manager->URLNotify(url, reason, notifyData); + return NPERR_NO_ERROR; +} + +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, + NPBool seekable, uint16 *stype) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + StreamManager *stream_manager = obj->stream_manager(); + if (stream_manager->NewStream(stream, stype)) { + return NPERR_NO_ERROR; + } else { + // TODO: find out which error we should return + return NPERR_INVALID_PARAM; } +} - NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) { - HANDLE_CRASHES; - switch (variable) { - case NPPVpluginScriptableNPObject: { - void **v = static_cast<void **>(value); - PluginObject *obj = static_cast<PluginObject *>(instance->pdata); - // Return value is expected to be retained - GLUE_PROFILE_START(instance, "retainobject"); - NPN_RetainObject(obj); - GLUE_PROFILE_STOP(instance, "retainobject"); - *v = obj; - break; - } - default: { - NPError ret = PlatformNPPGetValue(instance, variable, value); - if (ret == NPERR_INVALID_PARAM) - ret = NP_GetValue(instance, variable, value); - return ret; - } - } +NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + StreamManager *stream_manager = obj->stream_manager(); + if (stream_manager->DestroyStream(stream, reason)) { return NPERR_NO_ERROR; + } else { + // TODO: find out which error we should return + return NPERR_INVALID_PARAM; } - - NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) { - HANDLE_CRASHES; - return NPERR_GENERIC_ERROR; +} + +int32 NPP_WriteReady(NPP instance, NPStream *stream) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + StreamManager *stream_manager = obj->stream_manager(); + return stream_manager->WriteReady(stream); +} + +int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, + void *buffer) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + StreamManager *stream_manager = obj->stream_manager(); + return stream_manager->Write(stream, offset, len, buffer); +} + +void NPP_Print(NPP instance, NPPrint *platformPrint) { + HANDLE_CRASHES; +} + +void NPP_URLNotify(NPP instance, const char *url, NPReason reason, + void *notifyData) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + StreamManager *stream_manager = obj->stream_manager(); + stream_manager->URLNotify(url, reason, notifyData); +} + +NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) { + HANDLE_CRASHES; + switch (variable) { + case NPPVpluginScriptableNPObject: { + void **v = static_cast<void **>(value); + PluginObject *obj = static_cast<PluginObject *>(instance->pdata); + // Return value is expected to be retained + GLUE_PROFILE_START(instance, "retainobject"); + NPN_RetainObject(obj); + GLUE_PROFILE_STOP(instance, "retainobject"); + *v = obj; + break; + } + default: { + NPError ret = PlatformNPPGetValue(instance, variable, value); + if (ret == NPERR_INVALID_PARAM) + ret = o3d::NP_GetValue(instance, variable, value); + return ret; + } } -} // extern "C" + return NPERR_NO_ERROR; +} + +NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) { + HANDLE_CRASHES; + return NPERR_GENERIC_ERROR; +} +} // namespace o3d + +#if defined(O3D_INTERNAL_PLUGIN) +namespace o3d { +#else +extern "C" { +#endif + +NPError OSCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) { + HANDLE_CRASHES; + pluginFuncs->version = 11; + pluginFuncs->size = sizeof(*pluginFuncs); + pluginFuncs->newp = o3d::NPP_New; + pluginFuncs->destroy = o3d::NPP_Destroy; + pluginFuncs->setwindow = o3d::NPP_SetWindow; + pluginFuncs->newstream = o3d::NPP_NewStream; + pluginFuncs->destroystream = o3d::NPP_DestroyStream; + pluginFuncs->asfile = o3d::NPP_StreamAsFile; + pluginFuncs->writeready = o3d::NPP_WriteReady; + pluginFuncs->write = o3d::NPP_Write; + pluginFuncs->print = o3d::NPP_Print; + pluginFuncs->event = o3d::NPP_HandleEvent; + pluginFuncs->urlnotify = o3d::NPP_URLNotify; + pluginFuncs->getvalue = o3d::NPP_GetValue; + pluginFuncs->setvalue = o3d::NPP_SetValue; + + return NPERR_NO_ERROR; +} +} // namespace o3d / extern "C" diff --git a/o3d/plugin/cross/main.h b/o3d/plugin/cross/main.h index e72f458..003a63a 100644 --- a/o3d/plugin/cross/main.h +++ b/o3d/plugin/cross/main.h @@ -43,7 +43,10 @@ #include <fstream> #include <iostream> +#if !defined(O3D_INTERNAL_PLUGIN) #include "breakpad/win/exception_handler_win32.h" +#endif // O3D_INTERNAL_PLUGIN + #include "core/cross/renderer.h" #include "core/cross/renderer_platform.h" #include "plugin/cross/o3d_glue.h" @@ -52,20 +55,11 @@ #include "third_party/nixysa/files/static_glue/npapi/common.h" #include "third_party/nixysa/files/static_glue/npapi/npn_api.h" -extern ExceptionManager *g_exception_manager; - -class RenderOnDemandCallbackHandler - : public o3d::Client::RenderOnDemandCallback { - public: - explicit RenderOnDemandCallbackHandler(glue::_o3d::PluginObject* obj) - : obj_(obj) { - } +#if defined(O3D_INTERNAL_PLUGIN) +#define HANDLE_CRASHES void(0) +#else // O3D_INTERNAL_PLUGIN - // This function is implemented for each platform. - virtual void Run(); - private: - glue::_o3d::PluginObject* obj_; -}; +extern ExceptionManager *g_exception_manager; // BreakpadEnabler is a simple class to keep track of whether or not // we're executing code that we want to handle crashes for @@ -92,54 +86,71 @@ class BreakpadEnabler { static int scope_count_; }; +#endif // O3D_INTERNAL_PLUGIN +#if defined(O3D_INTERNAL_PLUGIN) namespace o3d { -void WriteLogString(const char* text, int length); -} // end namespace o3d - -NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value); - -// NPAPI declarations. Some of these are only implemented in the -// platform-specific versions of "main.cc". - +#else extern "C" { +#endif NPError OSCALL NP_Shutdown(void); NPError OSCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs); - NPError NPP_Destroy(NPP instance, NPSavedData **save); - NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason); - NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value); - - NPError NPP_New(NPMIMEType pluginType, - NPP instance, - uint16 mode, - int16 argc, - char *argn[], - char *argv[], - NPSavedData *saved); - - NPError NPP_NewStream(NPP instance, - NPMIMEType type, - NPStream *stream, - NPBool seekable, - uint16 *stype); - - NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value); - NPError NPP_SetWindow(NPP instance, NPWindow *window); - - int32 NPP_Write(NPP instance, - NPStream *stream, - int32 offset, - int32 len, - void *buffer); - - int32 NPP_WriteReady(NPP instance, NPStream *stream); - void NPP_Print(NPP instance, NPPrint *platformPrint); - void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname); - - void NPP_URLNotify(NPP instance, - const char *url, - NPReason reason, - void *notifyData); -}; // end extern "C" +} + +namespace o3d { + +class RenderOnDemandCallbackHandler + : public o3d::Client::RenderOnDemandCallback { + public: + explicit RenderOnDemandCallbackHandler(glue::_o3d::PluginObject* obj) + : obj_(obj) { + } + + // This function is implemented for each platform. + virtual void Run(); + private: + glue::_o3d::PluginObject* obj_; +}; + +void WriteLogString(const char* text, int length); +NPError NPP_Destroy(NPP instance, NPSavedData **save); +NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason); +NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value); + +NPError NPP_New(NPMIMEType pluginType, + NPP instance, + uint16 mode, + int16 argc, + char *argn[], + char *argv[], + NPSavedData *saved); + +NPError NPP_NewStream(NPP instance, + NPMIMEType type, + NPStream *stream, + NPBool seekable, + uint16 *stype); + +NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value); +NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value); +NPError NPP_SetWindow(NPP instance, NPWindow *window); + +int32 NPP_Write(NPP instance, + NPStream *stream, + int32 offset, + int32 len, + void *buffer); + +int32 NPP_WriteReady(NPP instance, NPStream *stream); +void NPP_Print(NPP instance, NPPrint *platformPrint); +int16 NPP_HandleEvent(NPP instance, void *event); + +void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname); + +void NPP_URLNotify(NPP instance, + const char *url, + NPReason reason, + void *notifyData); +}; // namespace o3d #endif // O3D_PLUGIN_CROSS_MAIN_H_ diff --git a/o3d/plugin/cross/o3d_glue.cc b/o3d/plugin/cross/o3d_glue.cc index 63c8a60..9eecd0d 100644 --- a/o3d/plugin/cross/o3d_glue.cc +++ b/o3d/plugin/cross/o3d_glue.cc @@ -167,7 +167,7 @@ PluginObject::PluginObject(NPP npp) globals_npobject_ = glue::CreateStaticNPObject(npp); client_npobject_ = glue::namespace_o3d::class_Client::GetNPObject(npp, client_); - user_agent_ = GetUserAgent(npp); + user_agent_ = o3d::GetUserAgent(npp); } PluginObject::~PluginObject() { @@ -205,7 +205,7 @@ void PluginObject::TearDown() { ClearPluginProperty(hWnd_); #endif // OS_WIN #ifdef OS_MACOSX - ReleaseSafariBrowserWindow(mac_cocoa_window_); + o3d::ReleaseSafariBrowserWindow(mac_cocoa_window_); #endif UnmapAll(); @@ -231,7 +231,7 @@ void PluginObject::TearDown() { } void PluginObject::CreateRenderer(const o3d::DisplayWindow& display_window) { - if (!CheckConfig(npp_)) { + if (!o3d::CheckConfig(npp_)) { renderer_init_status_ = o3d::Renderer::GPU_NOT_UP_TO_SPEC; } else { renderer_ = o3d::Renderer::CreateDefaultRenderer(&service_locator_); @@ -279,10 +279,10 @@ void PluginObject::MacEventReceived() { CFRelease(previousTime); } if (!mac_cocoa_window_) { - mac_cocoa_window_ = SafariBrowserWindowForWindowRef(mac_window_); + mac_cocoa_window_ = o3d::SafariBrowserWindowForWindowRef(mac_window_); } mac_window_selected_tab_ = - SelectedTabForSafariBrowserWindow(mac_cocoa_window_); + o3d::SelectedTabForSafariBrowserWindow(mac_cocoa_window_); } // Returns the time elapsed since the MacEventReceived function was last called. @@ -306,10 +306,10 @@ bool PluginObject::DetectTabHiding() { return false; if (!mac_cocoa_window_) { - mac_cocoa_window_ = SafariBrowserWindowForWindowRef(mac_window_); + mac_cocoa_window_ = o3d::SafariBrowserWindowForWindowRef(mac_window_); } - return SelectedTabForSafariBrowserWindow(mac_cocoa_window_) != + return o3d::SelectedTabForSafariBrowserWindow(mac_cocoa_window_) != mac_window_selected_tab_; } @@ -550,8 +550,8 @@ static bool PluginGetProperty(NPObject *header, NPIdentifier name, if (name == property_ids[PROP_GPU_CONFIG]) { // Gets the GPU config (VendorID, DeviceID, name) as a string. // NOTE: this should probably be removed before we ship. - GPUDevice device; - bool result = GetGPUDevice(npp, &device); + o3d::GPUDevice device; + bool result = o3d::GetGPUDevice(npp, &device); if (!result) return false; std::string return_value = std::string("VendorID = 0x"); char id_text[9]; diff --git a/o3d/plugin/linux/main_linux.cc b/o3d/plugin/linux/main_linux.cc index d381ae0..a0f1095 100644 --- a/o3d/plugin/linux/main_linux.cc +++ b/o3d/plugin/linux/main_linux.cc @@ -56,8 +56,6 @@ scoped_ptr<base::AtExitManager> g_at_exit_manager; bool g_xembed_support = false; -} // end anonymous namespace - static void DrawPlugin(PluginObject *obj) { // Limit drawing to no more than once every timer tick. if (!obj->draw_) return; @@ -65,10 +63,6 @@ static void DrawPlugin(PluginObject *obj) { obj->draw_ = false; } -void RenderOnDemandCallbackHandler::Run() { - DrawPlugin(obj_); -} - // Xt support functions void LinuxTimer(XtPointer data, XtIntervalId* id) { @@ -576,21 +570,6 @@ static gboolean GtkTimeoutCallback(gpointer user_data) { return TRUE; } -bool PluginObject::GetDisplayMode(int id, o3d::DisplayMode *mode) { - return false; -} - -// TODO: Where should this really live? It's platform-specific, but in -// PluginObject, which mainly lives in cross/o3d_glue.h+cc. -bool PluginObject::RequestFullscreenDisplay() { - // TODO: Unimplemented. - return false; -} - -void PluginObject::CancelFullscreenDisplay() { - // TODO: Unimplemented. -} - NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value) { switch (variable) { case NPPVpluginNeedsXEmbed: @@ -602,193 +581,228 @@ NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value) { return NPERR_NO_ERROR; } -extern "C" { - NPError InitializePlugin() { - if (!o3d::SetupOutOfMemoryHandler()) - return NPERR_MODULE_LOAD_FAILED_ERROR; - - // Initialize the AtExitManager so that base singletons can be - // destroyed properly. - g_at_exit_manager.reset(new base::AtExitManager()); - - CommandLine::Init(0, NULL); - InitLogging("debug.log", - logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, - logging::DONT_LOCK_LOG_FILE, - logging::APPEND_TO_OLD_LOG_FILE); - - DLOG(INFO) << "NP_Initialize"; - - // Check for XEmbed support in the browser. - NPBool xembed_support = 0; - NPError err = NPN_GetValue(NULL, NPNVSupportsXEmbedBool, &xembed_support); - if (err != NPERR_NO_ERROR) +NPError InitializePlugin() { + if (!o3d::SetupOutOfMemoryHandler()) + return NPERR_MODULE_LOAD_FAILED_ERROR; + + // Initialize the AtExitManager so that base singletons can be + // destroyed properly. + g_at_exit_manager.reset(new base::AtExitManager()); + + CommandLine::Init(0, NULL); + InitLogging("debug.log", + logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, + logging::DONT_LOCK_LOG_FILE, + logging::APPEND_TO_OLD_LOG_FILE); + + DLOG(INFO) << "NP_Initialize"; + + // Check for XEmbed support in the browser. + NPBool xembed_support = 0; + NPError err = NPN_GetValue(NULL, NPNVSupportsXEmbedBool, &xembed_support); + if (err != NPERR_NO_ERROR) + xembed_support = 0; + + if (xembed_support) { + // Check for Gtk2 toolkit support in the browser. + NPNToolkitType toolkit = static_cast<NPNToolkitType>(0); + err = NPN_GetValue(NULL, NPNVToolkit, &toolkit); + if (err != NPERR_NO_ERROR || toolkit != NPNVGtk2) xembed_support = 0; + } + g_xembed_support = xembed_support != 0; - if (xembed_support) { - // Check for Gtk2 toolkit support in the browser. - NPNToolkitType toolkit = static_cast<NPNToolkitType>(0); - err = NPN_GetValue(NULL, NPNVToolkit, &toolkit); - if (err != NPERR_NO_ERROR || toolkit != NPNVGtk2) - xembed_support = 0; - } - g_xembed_support = xembed_support != 0; + return NPERR_NO_ERROR; +} - return NPERR_NO_ERROR; - } +} // end anonymous namespace - NPError OSCALL NP_Initialize(NPNetscapeFuncs *browserFuncs, - NPPluginFuncs *pluginFuncs) { - NPError retval = InitializeNPNApi(browserFuncs); - if (retval != NPERR_NO_ERROR) return retval; - NP_GetEntryPoints(pluginFuncs); - return InitializePlugin(); - } +#if defined(O3D_INTERNAL_PLUGIN) +namespace o3d { +#else +extern "C" { +#endif - NPError OSCALL NP_Shutdown(void) { - HANDLE_CRASHES; - DLOG(INFO) << "NP_Shutdown"; +NPError OSCALL NP_Initialize(NPNetscapeFuncs *browserFuncs, + NPPluginFuncs *pluginFuncs) { + NPError retval = InitializeNPNApi(browserFuncs); + if (retval != NPERR_NO_ERROR) return retval; + NP_GetEntryPoints(pluginFuncs); + return InitializePlugin(); +} - CommandLine::Terminate(); +NPError OSCALL NP_Shutdown(void) { + HANDLE_CRASHES; + DLOG(INFO) << "NP_Shutdown"; - // Force all base singletons to be destroyed. - g_at_exit_manager.reset(NULL); + CommandLine::Terminate(); - return NPERR_NO_ERROR; - } + // Force all base singletons to be destroyed. + g_at_exit_manager.reset(NULL); - NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, - char *argn[], char *argv[], NPSavedData *saved) { - HANDLE_CRASHES; + return NPERR_NO_ERROR; +} - PluginObject* pluginObject = glue::_o3d::PluginObject::Create( - instance); - instance->pdata = pluginObject; - glue::_o3d::InitializeGlue(instance); - pluginObject->Init(argc, argn, argv); +} // namespace o3d / extern "C" - // Get the metrics for the system setup - GetUserConfigMetrics(); - return NPERR_NO_ERROR; - } +namespace o3d { - NPError NPP_Destroy(NPP instance, NPSavedData **save) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - if (obj) { - if (obj->xt_widget_) { - // NOTE: This crashes. Not sure why, possibly the widget has - // already been destroyed, but we haven't received a SetWindow(NULL). - // XtRemoveEventHandler(obj->xt_widget_, ExposureMask, False, - // LinuxExposeHandler, obj); - obj->xt_widget_ = NULL; - } - if (obj->xt_interval_) { - XtRemoveTimeOut(obj->xt_interval_); - obj->xt_interval_ = 0; - } - if (obj->timeout_id_) { - g_source_remove(obj->timeout_id_); - obj->timeout_id_ = 0; - } - if (obj->gtk_container_) { - gtk_widget_destroy(obj->gtk_container_); - gtk_widget_unref(obj->gtk_container_); - obj->gtk_container_ = NULL; - } - obj->window_ = 0; - obj->display_ = NULL; +void RenderOnDemandCallbackHandler::Run() { + DrawPlugin(obj_); +} + +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, + char *argn[], char *argv[], NPSavedData *saved) { + HANDLE_CRASHES; + + PluginObject* pluginObject = glue::_o3d::PluginObject::Create( + instance); + instance->pdata = pluginObject; + glue::_o3d::InitializeGlue(instance); + pluginObject->Init(argc, argn, argv); - obj->TearDown(); - NPN_ReleaseObject(obj); - instance->pdata = NULL; + // Get the metrics for the system setup + GetUserConfigMetrics(); + return NPERR_NO_ERROR; +} + +NPError NPP_Destroy(NPP instance, NPSavedData **save) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + if (obj) { + if (obj->xt_widget_) { + // NOTE: This crashes. Not sure why, possibly the widget has + // already been destroyed, but we haven't received a SetWindow(NULL). + // XtRemoveEventHandler(obj->xt_widget_, ExposureMask, False, + // LinuxExposeHandler, obj); + obj->xt_widget_ = NULL; + } + if (obj->xt_interval_) { + XtRemoveTimeOut(obj->xt_interval_); + obj->xt_interval_ = 0; + } + if (obj->timeout_id_) { + g_source_remove(obj->timeout_id_); + obj->timeout_id_ = 0; } + if (obj->gtk_container_) { + gtk_widget_destroy(obj->gtk_container_); + gtk_widget_unref(obj->gtk_container_); + obj->gtk_container_ = NULL; + } + obj->window_ = 0; + obj->display_ = NULL; - return NPERR_NO_ERROR; + obj->TearDown(); + NPN_ReleaseObject(obj); + instance->pdata = NULL; } + return NPERR_NO_ERROR; +} - NPError NPP_SetWindow(NPP instance, NPWindow *window) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - - NPSetWindowCallbackStruct *cb_struct = - static_cast<NPSetWindowCallbackStruct *>(window->ws_info); - Window xwindow = reinterpret_cast<Window>(window->window); - if (xwindow != obj->window_) { - Display *display = cb_struct->display; - Window drawable = xwindow; - if (g_xembed_support) { - // We asked for a XEmbed plugin, the xwindow is a GtkSocket, we create - // a GtkPlug to go into it. - obj->gtk_container_ = gtk_plug_new(xwindow); - gtk_widget_set_double_buffered(obj->gtk_container_, FALSE); - gtk_widget_add_events(obj->gtk_container_, - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_SCROLL_MASK | - GDK_KEY_PRESS_MASK | - GDK_KEY_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | - GDK_EXPOSURE_MASK | - GDK_ENTER_NOTIFY_MASK | - GDK_LEAVE_NOTIFY_MASK); - g_signal_connect(G_OBJECT(obj->gtk_container_), "event", - G_CALLBACK(GtkEventCallback), obj); - gtk_widget_show(obj->gtk_container_); - drawable = GDK_WINDOW_XID(obj->gtk_container_->window); - obj->timeout_id_ = g_timeout_add(10, GtkTimeoutCallback, obj); - } else { - // No XEmbed support, the xwindow is a Xt Widget. - Widget widget = XtWindowToWidget(display, xwindow); - if (!widget) { - DLOG(ERROR) << "window is not a Widget"; - return NPERR_MODULE_LOAD_FAILED_ERROR; - } - obj->xt_widget_ = widget; - XtAddEventHandler(widget, ExposureMask, 0, LinuxExposeHandler, obj); - XtAddEventHandler(widget, KeyPressMask|KeyReleaseMask, 0, - LinuxKeyHandler, obj); - XtAddEventHandler(widget, ButtonPressMask|ButtonReleaseMask, 0, - LinuxMouseButtonHandler, obj); - XtAddEventHandler(widget, PointerMotionMask, 0, - LinuxMouseMoveHandler, obj); - XtAddEventHandler(widget, EnterWindowMask|LeaveWindowMask, 0, - LinuxEnterLeaveHandler, obj); - obj->xt_app_context_ = XtWidgetToApplicationContext(widget); - obj->xt_interval_ = - XtAppAddTimeOut(obj->xt_app_context_, 10, LinuxTimer, obj); - } - // Create and assign the graphics context. - o3d::DisplayWindowLinux default_display; - default_display.set_display(display); - default_display.set_window(drawable); - - obj->CreateRenderer(default_display); - obj->client()->Init(); - obj->client()->SetRenderOnDemandCallback( - new RenderOnDemandCallbackHandler(obj)); - obj->display_ = display; - obj->window_ = xwindow; +NPError NPP_SetWindow(NPP instance, NPWindow *window) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + + NPSetWindowCallbackStruct *cb_struct = + static_cast<NPSetWindowCallbackStruct *>(window->ws_info); + Window xwindow = reinterpret_cast<Window>(window->window); + if (xwindow != obj->window_) { + Display *display = cb_struct->display; + Window drawable = xwindow; + if (g_xembed_support) { + // We asked for a XEmbed plugin, the xwindow is a GtkSocket, we create + // a GtkPlug to go into it. + obj->gtk_container_ = gtk_plug_new(xwindow); + gtk_widget_set_double_buffered(obj->gtk_container_, FALSE); + gtk_widget_add_events(obj->gtk_container_, + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_SCROLL_MASK | + GDK_KEY_PRESS_MASK | + GDK_KEY_RELEASE_MASK | + GDK_POINTER_MOTION_MASK | + GDK_EXPOSURE_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK); + g_signal_connect(G_OBJECT(obj->gtk_container_), "event", + G_CALLBACK(GtkEventCallback), obj); + gtk_widget_show(obj->gtk_container_); + drawable = GDK_WINDOW_XID(obj->gtk_container_->window); + obj->timeout_id_ = g_timeout_add(10, GtkTimeoutCallback, obj); + } else { + // No XEmbed support, the xwindow is a Xt Widget. + Widget widget = XtWindowToWidget(display, xwindow); + if (!widget) { + DLOG(ERROR) << "window is not a Widget"; + return NPERR_MODULE_LOAD_FAILED_ERROR; + } + obj->xt_widget_ = widget; + XtAddEventHandler(widget, ExposureMask, 0, LinuxExposeHandler, obj); + XtAddEventHandler(widget, KeyPressMask|KeyReleaseMask, 0, + LinuxKeyHandler, obj); + XtAddEventHandler(widget, ButtonPressMask|ButtonReleaseMask, 0, + LinuxMouseButtonHandler, obj); + XtAddEventHandler(widget, PointerMotionMask, 0, + LinuxMouseMoveHandler, obj); + XtAddEventHandler(widget, EnterWindowMask|LeaveWindowMask, 0, + LinuxEnterLeaveHandler, obj); + obj->xt_app_context_ = XtWidgetToApplicationContext(widget); + obj->xt_interval_ = + XtAppAddTimeOut(obj->xt_app_context_, 10, LinuxTimer, obj); } - obj->Resize(window->width, window->height); - return NPERR_NO_ERROR; + // Create and assign the graphics context. + o3d::DisplayWindowLinux default_display; + default_display.set_display(display); + default_display.set_window(drawable); + + obj->CreateRenderer(default_display); + obj->client()->Init(); + obj->client()->SetRenderOnDemandCallback( + new RenderOnDemandCallbackHandler(obj)); + obj->display_ = display; + obj->window_ = xwindow; } + obj->Resize(window->width, window->height); - // Called when the browser has finished attempting to stream data to - // a file as requested. If fname == NULL the attempt was not successful. - void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - StreamManager *stream_manager = obj->stream_manager(); + return NPERR_NO_ERROR; +} - stream_manager->SetStreamFile(stream, fname); - } +// Called when the browser has finished attempting to stream data to +// a file as requested. If fname == NULL the attempt was not successful. +void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + StreamManager *stream_manager = obj->stream_manager(); - int16 NPP_HandleEvent(NPP instance, void *event) { - HANDLE_CRASHES; - return 0; - } -}; // end extern "C" + stream_manager->SetStreamFile(stream, fname); +} + +int16 NPP_HandleEvent(NPP instance, void *event) { + HANDLE_CRASHES; + return 0; +} +} // namespace o3d + +namespace glue { +namespace _o3d { + +bool PluginObject::GetDisplayMode(int id, o3d::DisplayMode *mode) { + return false; +} + +// TODO: Where should this really live? It's platform-specific, but in +// PluginObject, which mainly lives in cross/o3d_glue.h+cc. +bool PluginObject::RequestFullscreenDisplay() { + // TODO: Unimplemented. + return false; +} + +void PluginObject::CancelFullscreenDisplay() { + // TODO: Unimplemented. +} +} // namespace _o3d +} // namespace glue diff --git a/o3d/plugin/mac/config_mac.mm b/o3d/plugin/mac/config_mac.mm index e5673b8..96701df 100644 --- a/o3d/plugin/mac/config_mac.mm +++ b/o3d/plugin/mac/config_mac.mm @@ -45,6 +45,7 @@ #include "plugin/cross/plugin_metrics.h" #include "plugin_mac.h" +namespace o3d { // Trivial little functions to check for the OS version boundaries we care about // and keep the result cached so they are cheap to call repeatedly. @@ -328,3 +329,5 @@ bool GetUserAgentMetrics(NPP npp) { return true; } + +} // namespace o3d diff --git a/o3d/plugin/mac/graphics_utils_mac.h b/o3d/plugin/mac/graphics_utils_mac.h index 9c4cee5..710e683 100644 --- a/o3d/plugin/mac/graphics_utils_mac.h +++ b/o3d/plugin/mac/graphics_utils_mac.h @@ -36,6 +36,8 @@ #include <Cocoa/Cocoa.h> #include <AGL/agl.h> +namespace o3d { + void SlideWindowToRect(WindowRef the_window, CGRect destination_rect, double transition_duration_seconds); @@ -53,4 +55,6 @@ CGRect Rect2CGRect(const Rect &inRect); void PaintRoundedCGRect(CGContextRef context, CGRect rect, float radius, bool fill); +} // namespace o3d + #endif // O3D_PLUGIN_MAC_GRAPHICS_UTILS_MAC_H_ diff --git a/o3d/plugin/mac/graphics_utils_mac.mm b/o3d/plugin/mac/graphics_utils_mac.mm index 88af452..4b8b45f90 100644 --- a/o3d/plugin/mac/graphics_utils_mac.mm +++ b/o3d/plugin/mac/graphics_utils_mac.mm @@ -32,6 +32,8 @@ #include "plugin/mac/graphics_utils_mac.h" +namespace o3d { + // Slide a window to a different rect, asynchronously, over a period of time. void SlideWindowToRect(WindowRef the_window, CGRect destination_rect, @@ -128,3 +130,5 @@ void PaintRoundedCGRect(CGContextRef context, else CGContextStrokePath(context); } + +} // namespace o3d diff --git a/o3d/plugin/mac/main_mac.mm b/o3d/plugin/mac/main_mac.mm index 45491a7..3427505 100644 --- a/o3d/plugin/mac/main_mac.mm +++ b/o3d/plugin/mac/main_mac.mm @@ -54,9 +54,10 @@ #include "plugin/mac/plugin_mac.h" #include "plugin/mac/graphics_utils_mac.h" - +#if !defined(O3D_INTERNAL_PLUGIN) o3d::PluginLogging* g_logger = NULL; bool g_logging_initialized = false; +#endif using glue::_o3d::PluginObject; using glue::StreamManager; @@ -68,7 +69,6 @@ namespace { // plugin, that's not possible, so we allocate it dynamically and // destroy it explicitly. scoped_ptr<base::AtExitManager> g_at_exit_manager; -} // end anonymous namespace // if defined, in AGL mode we do double buffered drawing // #define USE_AGL_DOUBLE_BUFFER @@ -81,7 +81,7 @@ scoped_ptr<base::AtExitManager> g_at_exit_manager; #undef USE_AGL_DOUBLE_BUFFER #endif -static void DrawPlugin(PluginObject* obj) { +void DrawPlugin(PluginObject* obj) { obj->client()->RenderClient(); #ifdef USE_AGL_DOUBLE_BUFFER // In AGL mode, we have to call aglSwapBuffers to guarantee that our @@ -91,16 +91,12 @@ static void DrawPlugin(PluginObject* obj) { #endif } -void RenderOnDemandCallbackHandler::Run() { - obj_->SetWantsRedraw(true); -} - -static unsigned char GetMacEventKeyChar(const EventRecord *the_event) { +unsigned char GetMacEventKeyChar(const EventRecord *the_event) { unsigned char the_char = the_event->message & charCodeMask; return the_char; } -static unsigned char GetMacEventKeyCode(const EventRecord *the_event) { +unsigned char GetMacEventKeyCode(const EventRecord *the_event) { unsigned char the_key_code = (the_event->message & keyCodeMask) >> 8; return the_key_code; } @@ -111,7 +107,7 @@ static unsigned char GetMacEventKeyCode(const EventRecord *the_event) { // These values are defined in NSEvent.h. // Map the ones we care about to the more commonly understood values in // the Mac system header Events.h, eg kUpArrowCharCode is 30. -static int TranslateMacUnicodeControlChar(int theChar) { +int TranslateMacUnicodeControlChar(int theChar) { switch(theChar) { case NSUpArrowFunctionKey: return kUpArrowCharCode; @@ -130,7 +126,7 @@ static int TranslateMacUnicodeControlChar(int theChar) { // web standard. // Also in the browser world the enter key gets mapped to be the same as the // return key. -static int TranslateMacControlCharToWebChar(int theChar) { +int TranslateMacControlCharToWebChar(int theChar) { switch(theChar) { case kUpArrowCharCode: return 38; @@ -150,11 +146,11 @@ static int TranslateMacControlCharToWebChar(int theChar) { // Given an instance, and some event data, calls Javascript methods // placed on the object tag so that the keystrokes can be handled in // Javascript. -static void DispatchKeyboardEvent(PluginObject* obj, - EventKind kind, - int theChar, - int theKeyCode, - EventModifiers mods) { +void DispatchKeyboardEvent(PluginObject* obj, + EventKind kind, + int theChar, + int theKeyCode, + EventModifiers mods) { theChar = TranslateMacUnicodeControlChar(theChar); theChar = TranslateMacControlCharToWebChar(theChar); int upperChar = (theChar >= 'a' && theChar <='z') ? theChar - 32 : theChar; @@ -212,8 +208,8 @@ static void DispatchKeyboardEvent(PluginObject* obj, // Given an instance, and a MacOS keyboard event, calls Javascript methods // placed on the object tag so that the keystrokes can be handled in // Javascript. -static void DispatchMacKeyboardEvent(PluginObject* obj, - EventRecord* the_event) { +void DispatchMacKeyboardEvent(PluginObject* obj, + EventRecord* the_event) { DispatchKeyboardEvent(obj, the_event->what, GetMacEventKeyChar(the_event), @@ -223,8 +219,8 @@ static void DispatchMacKeyboardEvent(PluginObject* obj, -static void HandleMouseEvent(PluginObject* obj, - EventRecord* the_event) { +void HandleMouseEvent(PluginObject* obj, + EventRecord* the_event) { DCHECK(obj); DCHECK(obj->client()); int screen_x = the_event->where.h; @@ -305,8 +301,8 @@ static void HandleMouseEvent(PluginObject* obj, // These events come from the new Cocoa revision of the NPAPI spec, // currently implemented only in Safari. // See https://wiki.mozilla.org/Mac:NPAPI_Event_Models -static void HandleCocoaMouseEvent(PluginObject* obj, - NPCocoaEvent* the_event) { +void HandleCocoaMouseEvent(PluginObject* obj, + NPCocoaEvent* the_event) { DCHECK(obj); DCHECK(obj->client()); int screen_x = the_event->data.mouse.pluginX; @@ -376,7 +372,7 @@ static void HandleCocoaMouseEvent(PluginObject* obj, if ((the_event->type == NPCocoaEventMouseDown) || (the_event->type == NPCocoaEventMouseUp)) { event.set_button( - MacOSMouseButtonNumberToO3DButton( + o3d::MacOSMouseButtonNumberToO3DButton( the_event->data.mouse.buttonNumber)); } @@ -396,7 +392,7 @@ static void HandleCocoaMouseEvent(PluginObject* obj, // Not all bits have a representation in the target type, eg NSFunctionKeyMask // but we just need to convert the basic modifiers that need to be passed on // to Javascript. -static EventModifiers CocoaToEventRecordModifiers(NSUInteger inMods) { +EventModifiers CocoaToEventRecordModifiers(NSUInteger inMods) { EventModifiers outMods = 0; // NSEvent distinuishes between the shift key being down and the capslock key, @@ -507,6 +503,225 @@ enum nsPluginEventType { nsPluginEventType_Idle = 0 }; +NPError InitializePlugin() { +#if !defined(O3D_INTERNAL_PLUGIN) + if (!o3d::SetupOutOfMemoryHandler()) + return NPERR_MODULE_LOAD_FAILED_ERROR; + + o3d::InitializeBreakpad(); + +#ifdef CFTIMER + o3d::gRenderTimer.Start(); +#endif // CFTIMER + + // Initialize the AtExitManager so that base singletons can be + // destroyed properly. + g_at_exit_manager.reset(new base::AtExitManager()); + + // Turn on the logging. + CommandLine::Init(0, NULL); + InitLogging("debug.log", + logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, + logging::DONT_LOCK_LOG_FILE, + logging::APPEND_TO_OLD_LOG_FILE); + + DLOG(INFO) << "NP_Initialize"; + + o3d::SetupOutOfMemoryHandler(); +#endif // O3D_INTERNAL_PLUGIN + + return NPERR_NO_ERROR; +} + +// Negotiates the best plugin event model, sets the browser to use that, +// and updates the PluginObject so we can remember which one we chose. +// We favor the newer Cocoa-based model, but can cope with browsers that +// only support the original event model, or indeed can't even understand +// what we are asking for. +// However, right at the minute, we shun the Cocoa event model because its +// NPP_SetWindow messages don't contain a WindowRef or NSWindow so we would +// not get enough info to create our AGL context. We'll go back to +// preferring Cocoa once we have worked out how to deal with that. +// Cannot actually fail - +void Mac_SetBestEventModel(NPP instance, PluginObject* obj) { + NPError err = NPERR_NO_ERROR; + NPEventModel event_model = NPEventModelCarbon; + NPBool supportsCocoaEventModel = FALSE; + NPBool supportsCarbonEventModel = FALSE; + + // See if browser supports Cocoa event model. + err = NPN_GetValue(instance, + NPNVsupportsCocoaBool, + &supportsCocoaEventModel); + if (err != NPERR_NO_ERROR) { + supportsCocoaEventModel = FALSE; + err = NPERR_NO_ERROR; // browser doesn't support switchable event models + } + + // See if browser supports Carbon event model. + err = NPN_GetValue(instance, + NPNVsupportsCarbonBool, + &supportsCarbonEventModel); + if (err != NPERR_NO_ERROR) { + supportsCarbonEventModel = FALSE; + err = NPERR_NO_ERROR; + } + + // Now we've collected our data, the decision phase begins. + + // If we didn't successfully get TRUE for either question, the browser + // just does not know about the new switchable event models, so must only + // support the old Carbon event model. + if (!(supportsCocoaEventModel || supportsCarbonEventModel)) { + supportsCarbonEventModel = TRUE; + obj->event_model_ = NPEventModelCarbon; + } + + // Default to Carbon event model, because the new version of the + // Cocoa event model spec does not supply sufficient window + // information in its Cocoa NPP_SetWindow calls for us to bind an + // AGL context to the browser window. + NPEventModel model_to_use = + (supportsCarbonEventModel) ? NPEventModelCarbon : NPEventModelCocoa; + NPN_SetValue(instance, NPPVpluginEventModel, + reinterpret_cast<void*>(model_to_use)); + obj->event_model_ = model_to_use; +} + + +// Negotiates the best plugin drawing model, sets the browser to use that, +// and updates the PluginObject so we can remember which one we chose. +// Returns NPERR_NO_ERROR (0) if successful, otherwise an NPError code. +NPError Mac_SetBestDrawingModel(NPP instance, PluginObject* obj) { + NPError err = NPERR_NO_ERROR; + NPBool supportsCoreGraphics = FALSE; + NPBool supportsOpenGL = FALSE; + NPBool supportsQuickDraw = FALSE; + NPDrawingModel drawing_model = NPDrawingModelQuickDraw; + + // test for direct OpenGL support + err = NPN_GetValue(instance, + NPNVsupportsOpenGLBool, + &supportsOpenGL); + if (err != NPERR_NO_ERROR) + supportsOpenGL = FALSE; + + // test for QuickDraw support + err = NPN_GetValue(instance, + NPNVsupportsQuickDrawBool, + &supportsQuickDraw); + if (err != NPERR_NO_ERROR) + supportsQuickDraw = FALSE; + + // Test for Core Graphics support + err = NPN_GetValue(instance, + NPNVsupportsCoreGraphicsBool, + &supportsCoreGraphics); + if (err != NPERR_NO_ERROR) + supportsCoreGraphics = FALSE; + + + // In order of preference. Preference is now determined by compatibility, + // not by modernity, and so is the opposite of the order I first used. + if (supportsQuickDraw && !(obj->event_model_ == NPEventModelCocoa)) { + drawing_model = NPDrawingModelQuickDraw; + } else if (supportsCoreGraphics) { + drawing_model = NPDrawingModelCoreGraphics; + } else if (supportsOpenGL) { + drawing_model = NPDrawingModelOpenGL; + } else { + // This case is for browsers that didn't even understand the question + // eg FF2, so drawing models are not supported, just assume QuickDraw. + obj->drawing_model_ = NPDrawingModelQuickDraw; + return NPERR_NO_ERROR; + } + + err = NPN_SetValue(instance, NPPVpluginDrawingModel, + reinterpret_cast<void*>(drawing_model)); + if (err != NPERR_NO_ERROR) + return err; + + obj->drawing_model_ = drawing_model; + + return NPERR_NO_ERROR; +} +} // end anonymous namespace + +#if defined(O3D_INTERNAL_PLUGIN) +namespace o3d { +#else +extern "C" { +#endif + +NPError OSCALL NP_Initialize(NPNetscapeFuncs* browserFuncs) { + HANDLE_CRASHES; + NPError retval = InitializeNPNApi(browserFuncs); + if (retval != NPERR_NO_ERROR) return retval; + return InitializePlugin(); +} + +#if !defined(O3D_INTERNAL_PLUGIN) + +// Wrapper that discards the return value to match the expected type of +// NPP_ShutdownUPP. +void NPP_ShutdownWrapper() { + NP_Shutdown(); +} + +// This code is needed to support browsers based on a slightly dated version +// of the NPAPI such as Firefox 2, and Camino 1.6. These browsers expect there +// to be a main() to call to do basic setup. +int main(NPNetscapeFuncs* browserFuncs, + NPPluginFuncs* pluginFuncs, + NPP_ShutdownUPP* shutdownProc) { + HANDLE_CRASHES; + NPError error = NP_Initialize(browserFuncs); + if (error == NPERR_NO_ERROR) + error = NP_GetEntryPoints(pluginFuncs); + *shutdownProc = NPP_ShutdownWrapper; + + return error; +} + +#endif // O3D_INTERNAL_PLUGIN + +NPError OSCALL NP_Shutdown(void) { +#if !defined(O3D_INTERNAL_PLUGIN) + HANDLE_CRASHES; + DLOG(INFO) << "NP_Shutdown"; + + if (g_logger) { + // Do a last sweep to aggregate metrics before we shut down + g_logger->ProcessMetrics(true, false); + delete g_logger; + g_logger = NULL; + g_logging_initialized = false; + stats_report::g_global_metrics.Uninitialize(); + } + + CommandLine::Terminate(); + +#ifdef CFTIMER + o3d::gRenderTimer.Stop(); +#endif + + // Force all base singletons to be destroyed. + g_at_exit_manager.reset(NULL); + + o3d::ShutdownBreakpad(); +#endif // O3D_INTERNAL_PLUGIN + + return NPERR_NO_ERROR; +} + +} // namespace o3d / extern "C" + + +namespace o3d { + +NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value) { + return NPERR_INVALID_PARAM; +} bool HandleMacEvent(EventRecord* the_event, NPP instance) { PluginObject* obj = static_cast<PluginObject*>(instance->pdata); @@ -594,332 +809,136 @@ bool HandleMacEvent(EventRecord* the_event, NPP instance) { return handled; } -NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value) { - return NPERR_INVALID_PARAM; +void RenderOnDemandCallbackHandler::Run() { + obj_->SetWantsRedraw(true); } -extern "C" { - NPError InitializePlugin() { - if (!o3d::SetupOutOfMemoryHandler()) - return NPERR_MODULE_LOAD_FAILED_ERROR; - - InitializeBreakpad(); - -#ifdef CFTIMER - gRenderTimer.Start(); -#endif // CFTIMER - - // Initialize the AtExitManager so that base singletons can be - // destroyed properly. - g_at_exit_manager.reset(new base::AtExitManager()); - - // Turn on the logging. - CommandLine::Init(0, NULL); - InitLogging("debug.log", - logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, - logging::DONT_LOCK_LOG_FILE, - logging::APPEND_TO_OLD_LOG_FILE); +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData* saved) { + HANDLE_CRASHES; - DLOG(INFO) << "NP_Initialize"; + NPError err = NPERR_NO_ERROR; - o3d::SetupOutOfMemoryHandler(); - - return NPERR_NO_ERROR; - } - - NPError OSCALL NP_Initialize(NPNetscapeFuncs* browserFuncs) { - HANDLE_CRASHES; - NPError retval = InitializeNPNApi(browserFuncs); - if (retval != NPERR_NO_ERROR) return retval; - return InitializePlugin(); +#if !defined(O3D_INTERNAL_PLUGIN) + if (!g_logging_initialized) { + GetUserAgentMetrics(instance); + GetUserConfigMetrics(); + // Create usage stats logs object + g_logger = o3d::PluginLogging::InitializeUsageStatsLogging(); + g_logging_initialized = true; } +#endif // O3D_INTERNAL_PLUGIN + + PluginObject* pluginObject = glue::_o3d::PluginObject::Create( + instance); + instance->pdata = pluginObject; + glue::_o3d::InitializeGlue(instance); + pluginObject->Init(argc, argn, argv); + + Mac_SetBestEventModel(instance, + static_cast<PluginObject*>(instance->pdata)); + + err = Mac_SetBestDrawingModel( + instance, static_cast<PluginObject*>(instance->pdata)); + if (err != NPERR_NO_ERROR) + return err; + return NPERR_NO_ERROR; +} - // Wrapper that discards the return value to match the expected type of - // NPP_ShutdownUPP. - void NPP_ShutdownWrapper() { - NP_Shutdown(); - } - - // This code is needed to support browsers based on a slightly dated version - // of the NPAPI such as Firefox 2, and Camino 1.6. These browsers expect there - // to be a main() to call to do basic setup. - int main(NPNetscapeFuncs* browserFuncs, - NPPluginFuncs* pluginFuncs, - NPP_ShutdownUPP* shutdownProc) { - HANDLE_CRASHES; - NPError error = NP_Initialize(browserFuncs); - if (error == NPERR_NO_ERROR) - error = NP_GetEntryPoints(pluginFuncs); - *shutdownProc = NPP_ShutdownWrapper; - - return error; - } - - NPError OSCALL NP_Shutdown(void) { - HANDLE_CRASHES; - DLOG(INFO) << "NP_Shutdown"; - - if (g_logger) { - // Do a last sweep to aggregate metrics before we shut down - g_logger->ProcessMetrics(true, false); - delete g_logger; - g_logger = NULL; - g_logging_initialized = false; - stats_report::g_global_metrics.Uninitialize(); - } - - CommandLine::Terminate(); - -#ifdef CFTIMER - gRenderTimer.Stop(); +NPError NPP_Destroy(NPP instance, NPSavedData** save) { + HANDLE_CRASHES; + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + if (obj) { +#if defined(CFTIMER) + o3d::gRenderTimer.RemoveInstance(instance); #endif - // Force all base singletons to be destroyed. - g_at_exit_manager.reset(NULL); - - ShutdownBreakpad(); - - return NPERR_NO_ERROR; + obj->TearDown(); + NPN_ReleaseObject(obj); + instance->pdata = NULL; } - // Negotiates the best plugin event model, sets the browser to use that, - // and updates the PluginObject so we can remember which one we chose. - // We favor the newer Cocoa-based model, but can cope with browsers that - // only support the original event model, or indeed can't even understand - // what we are asking for. - // However, right at the minute, we shun the Cocoa event model because its - // NPP_SetWindow messages don't contain a WindowRef or NSWindow so we would - // not get enough info to create our AGL context. We'll go back to - // preferring Cocoa once we have worked out how to deal with that. - // Cannot actually fail - - static void Mac_SetBestEventModel(NPP instance, PluginObject* obj) { - NPError err = NPERR_NO_ERROR; - NPEventModel event_model = NPEventModelCarbon; - NPBool supportsCocoaEventModel = FALSE; - NPBool supportsCarbonEventModel = FALSE; - - // See if browser supports Cocoa event model. - err = NPN_GetValue(instance, - NPNVsupportsCocoaBool, - &supportsCocoaEventModel); - if (err != NPERR_NO_ERROR) { - supportsCocoaEventModel = FALSE; - err = NPERR_NO_ERROR; // browser doesn't support switchable event models - } - - // See if browser supports Carbon event model. - err = NPN_GetValue(instance, - NPNVsupportsCarbonBool, - &supportsCarbonEventModel); - if (err != NPERR_NO_ERROR) { - supportsCarbonEventModel = FALSE; - err = NPERR_NO_ERROR; - } - - // Now we've collected our data, the decision phase begins. - - // If we didn't successfully get TRUE for either question, the browser - // just does not know about the new switchable event models, so must only - // support the old Carbon event model. - if (!(supportsCocoaEventModel || supportsCarbonEventModel)) { - supportsCarbonEventModel = TRUE; - obj->event_model_ = NPEventModelCarbon; - } - - // Default to Carbon event model, because the new version of the - // Cocoa event model spec does not supply sufficient window - // information in its Cocoa NPP_SetWindow calls for us to bind an - // AGL context to the browser window. - NPEventModel model_to_use = - (supportsCarbonEventModel) ? NPEventModelCarbon : NPEventModelCocoa; - NPN_SetValue(instance, NPPVpluginEventModel, - reinterpret_cast<void*>(model_to_use)); - obj->event_model_ = model_to_use; - } - - - // Negotiates the best plugin drawing model, sets the browser to use that, - // and updates the PluginObject so we can remember which one we chose. - // Returns NPERR_NO_ERROR (0) if successful, otherwise an NPError code. - static NPError Mac_SetBestDrawingModel(NPP instance, PluginObject* obj) { - NPError err = NPERR_NO_ERROR; - NPBool supportsCoreGraphics = FALSE; - NPBool supportsOpenGL = FALSE; - NPBool supportsQuickDraw = FALSE; - NPDrawingModel drawing_model = NPDrawingModelQuickDraw; - - // test for direct OpenGL support - err = NPN_GetValue(instance, - NPNVsupportsOpenGLBool, - &supportsOpenGL); - if (err != NPERR_NO_ERROR) - supportsOpenGL = FALSE; - - // test for QuickDraw support - err = NPN_GetValue(instance, - NPNVsupportsQuickDrawBool, - &supportsQuickDraw); - if (err != NPERR_NO_ERROR) - supportsQuickDraw = FALSE; - - // Test for Core Graphics support - err = NPN_GetValue(instance, - NPNVsupportsCoreGraphicsBool, - &supportsCoreGraphics); - if (err != NPERR_NO_ERROR) - supportsCoreGraphics = FALSE; - - - // In order of preference. Preference is now determined by compatibility, - // not by modernity, and so is the opposite of the order I first used. - if (supportsQuickDraw && !(obj->event_model_ == NPEventModelCocoa)) { - drawing_model = NPDrawingModelQuickDraw; - } else if (supportsCoreGraphics) { - drawing_model = NPDrawingModelCoreGraphics; - } else if (supportsOpenGL) { - drawing_model = NPDrawingModelOpenGL; - } else { - // This case is for browsers that didn't even understand the question - // eg FF2, so drawing models are not supported, just assume QuickDraw. - obj->drawing_model_ = NPDrawingModelQuickDraw; - return NPERR_NO_ERROR; - } - - err = NPN_SetValue(instance, NPPVpluginDrawingModel, - reinterpret_cast<void*>(drawing_model)); - if (err != NPERR_NO_ERROR) - return err; - - obj->drawing_model_ = drawing_model; - - return NPERR_NO_ERROR; - } - - - NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, - char* argn[], char* argv[], NPSavedData* saved) { - HANDLE_CRASHES; + return NPERR_NO_ERROR; +} - NPError err = NPERR_NO_ERROR; +bool CheckForAGLError() { + return aglGetError() != AGL_NO_ERROR; +} - if (!g_logging_initialized) { - GetUserAgentMetrics(instance); - GetUserConfigMetrics(); - // Create usage stats logs object - g_logger = o3d::PluginLogging::InitializeUsageStatsLogging(); - g_logging_initialized = true; - } - PluginObject* pluginObject = glue::_o3d::PluginObject::Create( - instance); - instance->pdata = pluginObject; - glue::_o3d::InitializeGlue(instance); - pluginObject->Init(argc, argn, argv); +NPError NPP_SetWindow(NPP instance, NPWindow* window) { + HANDLE_CRASHES; + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + WindowRef new_window = NULL; - Mac_SetBestEventModel(instance, - static_cast<PluginObject*>(instance->pdata)); + assert(window != NULL); - err = Mac_SetBestDrawingModel( - instance, static_cast<PluginObject*>(instance->pdata)); - if (err != NPERR_NO_ERROR) - return err; + if (window->window == NULL) return NPERR_NO_ERROR; - } - NPError NPP_Destroy(NPP instance, NPSavedData** save) { - HANDLE_CRASHES; - PluginObject* obj = static_cast<PluginObject*>(instance->pdata); - if (obj) { -#if defined(CFTIMER) - gRenderTimer.RemoveInstance(instance); -#endif + obj->last_plugin_loc_.h = window->x; + obj->last_plugin_loc_.v = window->y; - obj->TearDown(); - NPN_ReleaseObject(obj); - instance->pdata = NULL; + switch (obj->drawing_model_) { + case NPDrawingModelOpenGL: { + NP_GLContext* np_gl = reinterpret_cast<NP_GLContext*>(window->window); + if (obj->event_model_ == NPEventModelCocoa) { + NSWindow * ns_window = reinterpret_cast<NSWindow*>(np_gl->window); + new_window = reinterpret_cast<WindowRef>([ns_window windowRef]); + } else { + new_window = np_gl->window; + } + obj->mac_2d_context_ = NULL; + obj->mac_cgl_context_ = np_gl->context; + break; } - - return NPERR_NO_ERROR; - } - - static bool CheckForAGLError() { - return aglGetError() != AGL_NO_ERROR; - } - - - NPError NPP_SetWindow(NPP instance, NPWindow* window) { - HANDLE_CRASHES; - PluginObject* obj = static_cast<PluginObject*>(instance->pdata); - WindowRef new_window = NULL; - - assert(window != NULL); - - if (window->window == NULL) - return NPERR_NO_ERROR; - - obj->last_plugin_loc_.h = window->x; - obj->last_plugin_loc_.v = window->y; - - switch (obj->drawing_model_) { - case NPDrawingModelOpenGL: { - NP_GLContext* np_gl = reinterpret_cast<NP_GLContext*>(window->window); + case NPDrawingModelCoreGraphics: { + // Safari 4 sets window->window to NULL when in Cocoa event mode. + if (window->window != NULL) { + NP_CGContext* np_cg = reinterpret_cast<NP_CGContext*>(window->window); if (obj->event_model_ == NPEventModelCocoa) { - NSWindow * ns_window = reinterpret_cast<NSWindow*>(np_gl->window); + NSWindow * ns_window = reinterpret_cast<NSWindow*>(np_cg->window); new_window = reinterpret_cast<WindowRef>([ns_window windowRef]); } else { - new_window = np_gl->window; - } - obj->mac_2d_context_ = NULL; - obj->mac_cgl_context_ = np_gl->context; - break; - } - case NPDrawingModelCoreGraphics: { - // Safari 4 sets window->window to NULL when in Cocoa event mode. - if (window->window != NULL) { - NP_CGContext* np_cg = reinterpret_cast<NP_CGContext*>(window->window); - if (obj->event_model_ == NPEventModelCocoa) { - NSWindow * ns_window = reinterpret_cast<NSWindow*>(np_cg->window); - new_window = reinterpret_cast<WindowRef>([ns_window windowRef]); - } else { - new_window = np_cg->window; - } - obj->mac_2d_context_ = np_cg->context; + new_window = np_cg->window; } - break; + obj->mac_2d_context_ = np_cg->context; } - case NPDrawingModelQuickDraw: { - NP_Port* np_qd = reinterpret_cast<NP_Port*>(window->window); - obj->mac_2d_context_ = np_qd->port; - if (np_qd->port) - new_window = GetWindowFromPort(np_qd->port); - break; - } - default: - return NPERR_INCOMPATIBLE_VERSION_ERROR; - break; + break; } + case NPDrawingModelQuickDraw: { + NP_Port* np_qd = reinterpret_cast<NP_Port*>(window->window); + obj->mac_2d_context_ = np_qd->port; + if (np_qd->port) + new_window = GetWindowFromPort(np_qd->port); + break; + } + default: + return NPERR_INCOMPATIBLE_VERSION_ERROR; + break; + } - // Whether the target window has changed. - bool window_changed = new_window != obj->mac_window_; + // Whether the target window has changed. + bool window_changed = new_window != obj->mac_window_; - // Whether we already had a window before this call. - bool had_a_window = obj->mac_window_ != NULL; + // Whether we already had a window before this call. + bool had_a_window = obj->mac_window_ != NULL; - obj->mac_window_ = new_window; + obj->mac_window_ = new_window; - if (obj->drawing_model_ == NPDrawingModelOpenGL) { - CGLSetCurrentContext(obj->mac_cgl_context_); - } else if (!had_a_window && obj->mac_agl_context_ == NULL) { // setup AGL context - AGLPixelFormat myAGLPixelFormat = NULL; + if (obj->drawing_model_ == NPDrawingModelOpenGL) { + CGLSetCurrentContext(obj->mac_cgl_context_); + } else if (!had_a_window && obj->mac_agl_context_ == NULL) { // setup AGL context + AGLPixelFormat myAGLPixelFormat = NULL; - // We need to spec out a few similar but different sets of renderer - // specifications - define some macros to lessen the duplication. + // We need to spec out a few similar but different sets of renderer + // specifications - define some macros to lessen the duplication. #define O3D_DEPTH_SETTINGS AGL_RGBA, AGL_DEPTH_SIZE, 24, #define O3D_STENCIL_SETTINGS AGL_STENCIL_SIZE, 8, #define O3D_HARDWARE_RENDERER AGL_ACCELERATED, AGL_NO_RECOVERY, #define O3D_SOFTWARE_RENDERER AGL_RENDERER_ID, AGL_RENDERER_GENERIC_FLOAT_ID, #define O3D_MULTISAMPLE AGL_MULTISAMPLE, \ - AGL_SAMPLE_BUFFERS_ARB, 1, AGL_SAMPLES_ARB, 4, AGL_MULTISAMPLE, + AGL_SAMPLE_BUFFERS_ARB, 1, AGL_SAMPLES_ARB, 4, AGL_MULTISAMPLE, #define O3D_END AGL_NONE #ifdef USE_AGL_DOUBLE_BUFFER @@ -928,229 +947,230 @@ extern "C" { #define O3D_DOUBLE_BUFFER_SETTINGS #endif - if (!UseSoftwareRenderer()) { - // Try to create a hardware context with the following - // specification - GLint attributes[] = { + if (!UseSoftwareRenderer()) { + // Try to create a hardware context with the following + // specification + GLint attributes[] = { + O3D_DEPTH_SETTINGS + O3D_STENCIL_SETTINGS + O3D_DOUBLE_BUFFER_SETTINGS + O3D_HARDWARE_RENDERER + O3D_MULTISAMPLE + O3D_END + }; + myAGLPixelFormat = aglChoosePixelFormat(NULL, + 0, + attributes); + + // If this fails, then don't try to be as ambitious + // (so don't ask for multi-sampling), but still require hardware + if (myAGLPixelFormat == NULL) { + GLint low_end_attributes[] = { O3D_DEPTH_SETTINGS O3D_STENCIL_SETTINGS O3D_DOUBLE_BUFFER_SETTINGS O3D_HARDWARE_RENDERER - O3D_MULTISAMPLE O3D_END }; myAGLPixelFormat = aglChoosePixelFormat(NULL, 0, - attributes); - - // If this fails, then don't try to be as ambitious - // (so don't ask for multi-sampling), but still require hardware - if (myAGLPixelFormat == NULL) { - GLint low_end_attributes[] = { - O3D_DEPTH_SETTINGS - O3D_STENCIL_SETTINGS - O3D_DOUBLE_BUFFER_SETTINGS - O3D_HARDWARE_RENDERER - O3D_END - }; - myAGLPixelFormat = aglChoosePixelFormat(NULL, - 0, - low_end_attributes); - } + low_end_attributes); } + } - if (myAGLPixelFormat == NULL) { - // Fallback to software renderer either if the vendorID/gpuID - // is known to be problematic, or if the hardware context failed - // to get created - // - // Note that we don't request multisampling since it's too slow. - GLint software_renderer_attributes[] = { - O3D_DEPTH_SETTINGS - O3D_STENCIL_SETTINGS - O3D_DOUBLE_BUFFER_SETTINGS - O3D_SOFTWARE_RENDERER - O3D_END - }; - myAGLPixelFormat = aglChoosePixelFormat(NULL, - 0, - software_renderer_attributes); - - obj->SetRendererIsSoftware(true); - } + if (myAGLPixelFormat == NULL) { + // Fallback to software renderer either if the vendorID/gpuID + // is known to be problematic, or if the hardware context failed + // to get created + // + // Note that we don't request multisampling since it's too slow. + GLint software_renderer_attributes[] = { + O3D_DEPTH_SETTINGS + O3D_STENCIL_SETTINGS + O3D_DOUBLE_BUFFER_SETTINGS + O3D_SOFTWARE_RENDERER + O3D_END + }; + myAGLPixelFormat = aglChoosePixelFormat(NULL, + 0, + software_renderer_attributes); + + obj->SetRendererIsSoftware(true); + } - if (myAGLPixelFormat == NULL || CheckForAGLError()) - return NPERR_MODULE_LOAD_FAILED_ERROR; + if (myAGLPixelFormat == NULL || CheckForAGLError()) + return NPERR_MODULE_LOAD_FAILED_ERROR; - obj->mac_agl_context_ = aglCreateContext(myAGLPixelFormat, NULL); + obj->mac_agl_context_ = aglCreateContext(myAGLPixelFormat, NULL); - if (CheckForAGLError()) - return NPERR_MODULE_LOAD_FAILED_ERROR; + if (CheckForAGLError()) + return NPERR_MODULE_LOAD_FAILED_ERROR; - aglDestroyPixelFormat(myAGLPixelFormat); + aglDestroyPixelFormat(myAGLPixelFormat); - if (!SetWindowForAGLContext(obj->mac_agl_context_, obj->mac_window_)) - return NPERR_MODULE_LOAD_FAILED_ERROR; + if (!SetWindowForAGLContext(obj->mac_agl_context_, obj->mac_window_)) + return NPERR_MODULE_LOAD_FAILED_ERROR; - aglSetCurrentContext(obj->mac_agl_context_); + aglSetCurrentContext(obj->mac_agl_context_); - GetOpenGLMetrics(); + GetOpenGLMetrics(); #ifdef USE_AGL_DOUBLE_BUFFER - GLint swapInterval = 1; // request synchronization - aglSetInteger(obj->mac_agl_context_, AGL_SWAP_INTERVAL, &swapInterval); + GLint swapInterval = 1; // request synchronization + aglSetInteger(obj->mac_agl_context_, AGL_SWAP_INTERVAL, &swapInterval); #endif - } - - int clipHeight = window->clipRect.bottom - window->clipRect.top; - int clipWidth = window->clipRect.right - window->clipRect.left; - - int x_offset = window->clipRect.left - window->x; - int y_offset = window->clipRect.top - window->y; - int gl_x_origin = x_offset; - int gl_y_origin = window->clipRect.bottom - (window->y + window->height); - - // Firefox calls us with an empty cliprect all the time, toggling our - // cliprect back and forth between empty and the normal value, particularly - // during scrolling. - // As we need to make our AGL surface track the clip rect, honoring all of - // these calls would result in spectacular flashing. - // The goal here is to try to spot the calls we can safely ignore. - // The bogus empty cliprects always have left and top of the real clip. - // A null cliprect should always be honored ({0,0,0,0} means a hidden tab), - // as should the first ever call to this function, - // or an attempt to change the window. - // The call at the end of a scroll step is also honored. - // Otherwise, skip this change and do not hide our context. - bool is_empty_cliprect = (clipHeight <= 0 || clipWidth <= 0); - bool is_null_cliprect = (window->clipRect.bottom == 0 && - window->clipRect.top == 0 && - window->clipRect.left == 0 && - window->clipRect.right == 0); - - if (is_empty_cliprect && (!is_null_cliprect) && - had_a_window && (!window_changed) && !obj->ScrollIsInProgress()) { - return NPERR_NO_ERROR; - } + } - // Workaround - the Apple software renderer crashes if you set the drawing - // area to 0x0, so use 1x1. - if (is_empty_cliprect && obj->RendererIsSoftware()) - clipWidth = clipHeight = 1; + int clipHeight = window->clipRect.bottom - window->clipRect.top; + int clipWidth = window->clipRect.right - window->clipRect.left; + + int x_offset = window->clipRect.left - window->x; + int y_offset = window->clipRect.top - window->y; + int gl_x_origin = x_offset; + int gl_y_origin = window->clipRect.bottom - (window->y + window->height); + + // Firefox calls us with an empty cliprect all the time, toggling our + // cliprect back and forth between empty and the normal value, particularly + // during scrolling. + // As we need to make our AGL surface track the clip rect, honoring all of + // these calls would result in spectacular flashing. + // The goal here is to try to spot the calls we can safely ignore. + // The bogus empty cliprects always have left and top of the real clip. + // A null cliprect should always be honored ({0,0,0,0} means a hidden tab), + // as should the first ever call to this function, + // or an attempt to change the window. + // The call at the end of a scroll step is also honored. + // Otherwise, skip this change and do not hide our context. + bool is_empty_cliprect = (clipHeight <= 0 || clipWidth <= 0); + bool is_null_cliprect = (window->clipRect.bottom == 0 && + window->clipRect.top == 0 && + window->clipRect.left == 0 && + window->clipRect.right == 0); + + if (is_empty_cliprect && (!is_null_cliprect) && + had_a_window && (!window_changed) && !obj->ScrollIsInProgress()) { + return NPERR_NO_ERROR; + } - // update size and location of the agl context - if (obj->mac_agl_context_) { + // Workaround - the Apple software renderer crashes if you set the drawing + // area to 0x0, so use 1x1. + if (is_empty_cliprect && obj->RendererIsSoftware()) + clipWidth = clipHeight = 1; + + // update size and location of the agl context + if (obj->mac_agl_context_) { + + // We already had a window, and now we've got a different window - + // this can happen when the user drags out a tab in Safari into its own + // window. + if (had_a_window && window_changed) + SetWindowForAGLContext(obj->mac_agl_context_, obj->mac_window_); + + aglSetCurrentContext(obj->mac_agl_context_); + + Rect windowRect = {0, 0, 0, 0}; + if (obj->drawing_model_ == NPDrawingModelQuickDraw) + GetWindowBounds(obj->mac_window_, kWindowContentRgn, &windowRect); + else + GetWindowBounds(obj->mac_window_, kWindowStructureRgn, &windowRect); + + int windowHeight = windowRect.bottom - windowRect.top; + + // These are in window coords, the weird bit being that agl wants the + // location of the bottom of the GL context in y flipped coords, + // eg 100 would mean the bottom of the GL context was 100 up from the + // bottom of the window. + obj->last_buffer_rect_[0] = window->x + x_offset; + obj->last_buffer_rect_[1] = (windowHeight - (window->y + clipHeight)) + - y_offset; // this param is y flipped + obj->last_buffer_rect_[2] = clipWidth; + obj->last_buffer_rect_[3] = clipHeight; + obj->mac_surface_hidden_ = false; + + // If in fullscreen, just remember the desired change in geometry so + // we restore to the right rectangle. + if (obj->GetFullscreenMacWindow() != NULL) + return NPERR_NO_ERROR; - // We already had a window, and now we've got a different window - - // this can happen when the user drags out a tab in Safari into its own - // window. - if (had_a_window && window_changed) - SetWindowForAGLContext(obj->mac_agl_context_, obj->mac_window_); - - aglSetCurrentContext(obj->mac_agl_context_); - - Rect windowRect = {0, 0, 0, 0}; - if (obj->drawing_model_ == NPDrawingModelQuickDraw) - GetWindowBounds(obj->mac_window_, kWindowContentRgn, &windowRect); - else - GetWindowBounds(obj->mac_window_, kWindowStructureRgn, &windowRect); - - int windowHeight = windowRect.bottom - windowRect.top; - - // These are in window coords, the weird bit being that agl wants the - // location of the bottom of the GL context in y flipped coords, - // eg 100 would mean the bottom of the GL context was 100 up from the - // bottom of the window. - obj->last_buffer_rect_[0] = window->x + x_offset; - obj->last_buffer_rect_[1] = (windowHeight - (window->y + clipHeight)) - - y_offset; // this param is y flipped - obj->last_buffer_rect_[2] = clipWidth; - obj->last_buffer_rect_[3] = clipHeight; - obj->mac_surface_hidden_ = false; - - // If in fullscreen, just remember the desired change in geometry so - // we restore to the right rectangle. - if (obj->GetFullscreenMacWindow() != NULL) - return NPERR_NO_ERROR; - - aglSetInteger(obj->mac_agl_context_, AGL_BUFFER_RECT, - obj->last_buffer_rect_); - aglEnable(obj->mac_agl_context_, AGL_BUFFER_RECT); - } + aglSetInteger(obj->mac_agl_context_, AGL_BUFFER_RECT, + obj->last_buffer_rect_); + aglEnable(obj->mac_agl_context_, AGL_BUFFER_RECT); + } - // Renderer is already initialized from a previous call to this function, - // just update size and position and return. - if (had_a_window) { - if (obj->renderer()) { - obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin); - obj->Resize(window->width, window->height); - } - return NPERR_NO_ERROR; + // Renderer is already initialized from a previous call to this function, + // just update size and position and return. + if (had_a_window) { + if (obj->renderer()) { + obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin); + obj->Resize(window->width, window->height); } + return NPERR_NO_ERROR; + } - // Create and assign the graphics context. - o3d::DisplayWindowMac default_display; - default_display.set_agl_context(obj->mac_agl_context_); - default_display.set_cgl_context(obj->mac_cgl_context_); + // Create and assign the graphics context. + o3d::DisplayWindowMac default_display; + default_display.set_agl_context(obj->mac_agl_context_); + default_display.set_cgl_context(obj->mac_cgl_context_); - obj->CreateRenderer(default_display); + obj->CreateRenderer(default_display); - // if the renderer cannot be created (maybe the features are not supported) - // then we can proceed no further - if (!obj->renderer()) { - if (obj->mac_agl_context_) { - ::aglDestroyContext(obj->mac_agl_context_); - obj->mac_agl_context_ = NULL; - } + // if the renderer cannot be created (maybe the features are not supported) + // then we can proceed no further + if (!obj->renderer()) { + if (obj->mac_agl_context_) { + ::aglDestroyContext(obj->mac_agl_context_); + obj->mac_agl_context_ = NULL; } + } - obj->client()->Init(); - obj->client()->SetRenderOnDemandCallback( - new RenderOnDemandCallbackHandler(obj)); + obj->client()->Init(); + obj->client()->SetRenderOnDemandCallback( + new RenderOnDemandCallbackHandler(obj)); - if (obj->renderer()) { - obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin); - obj->Resize(window->width, window->height); + if (obj->renderer()) { + obj->renderer()->SetClientOriginOffset(gl_x_origin, gl_y_origin); + obj->Resize(window->width, window->height); #ifdef CFTIMER - // now that the grahics context is setup, add this instance to the timer - // list so it gets drawn repeatedly - gRenderTimer.AddInstance(instance); + // now that the grahics context is setup, add this instance to the timer + // list so it gets drawn repeatedly + gRenderTimer.AddInstance(instance); #endif // CFTIMER - } - - return NPERR_NO_ERROR; } - // Called when the browser has finished attempting to stream data to - // a file as requested. If fname == NULL the attempt was not successful. - void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) { - HANDLE_CRASHES; - PluginObject* obj = static_cast<PluginObject*>(instance->pdata); - StreamManager* stream_manager = obj->stream_manager(); - - // Some browsers give us an absolute HFS path in fname, some give us an - // absolute Posix path, so convert to Posix if needed. - if ((!fname) || (fname[0] == '/') || !fname[0]) { - stream_manager->SetStreamFile(stream, fname); - } else { - const char* converted_fname = CreatePosixFilePathFromHFSFilePath(fname); - if (converted_fname == NULL) - return; // TODO should also log error if we ever get here - stream_manager->SetStreamFile(stream, converted_fname); - delete converted_fname; - } + return NPERR_NO_ERROR; +} + +// Called when the browser has finished attempting to stream data to +// a file as requested. If fname == NULL the attempt was not successful. +void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) { + HANDLE_CRASHES; + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + StreamManager* stream_manager = obj->stream_manager(); + + // Some browsers give us an absolute HFS path in fname, some give us an + // absolute Posix path, so convert to Posix if needed. + if ((!fname) || (fname[0] == '/') || !fname[0]) { + stream_manager->SetStreamFile(stream, fname); + } else { + const char* converted_fname = CreatePosixFilePathFromHFSFilePath(fname); + if (converted_fname == NULL) + return; // TODO should also log error if we ever get here + stream_manager->SetStreamFile(stream, converted_fname); + delete converted_fname; } +} - int16 NPP_HandleEvent(NPP instance, void* event) { - HANDLE_CRASHES; - PluginObject* obj = static_cast<PluginObject*>(instance->pdata); - if (obj->event_model_ == NPEventModelCarbon) { - EventRecord* theEvent = static_cast<EventRecord*>(event); - return HandleMacEvent(theEvent, instance) ? 1 : 0; - } else if (obj->event_model_ == NPEventModelCocoa){ - return HandleCocoaEvent(instance, (NPCocoaEvent*)event) ? 1 : 0; - } - return 0; +int16 NPP_HandleEvent(NPP instance, void* event) { + HANDLE_CRASHES; + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + if (obj->event_model_ == NPEventModelCarbon) { + EventRecord* theEvent = static_cast<EventRecord*>(event); + return HandleMacEvent(theEvent, instance) ? 1 : 0; + } else if (obj->event_model_ == NPEventModelCocoa){ + return HandleCocoaEvent(instance, (NPCocoaEvent*)event) ? 1 : 0; } -}; // end extern "C" + return 0; +} + +} // namespace o3d diff --git a/o3d/plugin/mac/plugin_mac.h b/o3d/plugin/mac/plugin_mac.h index 1e9efe5..85d7c85 100644 --- a/o3d/plugin/mac/plugin_mac.h +++ b/o3d/plugin/mac/plugin_mac.h @@ -41,6 +41,7 @@ // Just for o3d::Event::Button at the moment. #include "core/cross/event.h" +namespace o3d { // RenderTimer maintains an animation timer (nominally running at 60fps) // @@ -101,4 +102,6 @@ bool GetBrowserVersionInfo(int *returned_major, bool UseSoftwareRenderer(); +} // namespace o3d + #endif // O3D_PLUGIN_MAC_PLUGIN_MAC_H_ diff --git a/o3d/plugin/mac/plugin_mac.mm b/o3d/plugin/mac/plugin_mac.mm index 9a70d1d..459f116 100644 --- a/o3d/plugin/mac/plugin_mac.mm +++ b/o3d/plugin/mac/plugin_mac.mm @@ -40,11 +40,18 @@ #include "core/mac/display_window_mac.h" #include "plugin/mac/graphics_utils_mac.h" +#if !defined(O3D_INTERNAL_PLUGIN) BreakpadRef gBreakpadRef = NULL; +#endif using glue::_o3d::PluginObject; using o3d::DisplayWindowMac; +@interface NSWindowController (plugin_hack) +- (id)selectedTab; +@end + +namespace o3d { // Returns the version number of the running Mac browser, as parsed from // the short version string in the plist of the app's bundle. @@ -104,10 +111,6 @@ bool GetBrowserVersionInfo(int *returned_major, // only care whether the value changes or not. -@interface NSWindowController (plugin_hack) -- (id)selectedTab; -@end - void ReleaseSafariBrowserWindow(void* browserWindow) { NSWindow* cocoaWindow = (NSWindow*) browserWindow; [cocoaWindow release]; @@ -890,13 +893,13 @@ void PluginObject::GetDisplayModes(std::vector<o3d::DisplayMode> *modes) { int refresh_rate = 0; int bpp = 0; - if (ExtractDisplayModeData([mac_modes objectAtIndex:i], + if (o3d::ExtractDisplayModeData([mac_modes objectAtIndex:i], &width, &height, &refresh_rate, &bpp) && bpp == 32) modes_found.push_back(o3d::DisplayMode(width, height, refresh_rate, - i + kO3D_MODE_OFFSET)); + i + o3d::kO3D_MODE_OFFSET)); } modes->swap(modes_found); @@ -949,13 +952,14 @@ bool PluginObject::RequestFullscreenDisplay() { mac_fullscreen_state_ = NULL; } - SetFullscreenMacWindow(CreateFullscreenWindow(NULL, - this, - fullscreen_region_mode_id_)); + SetFullscreenMacWindow(o3d::CreateFullscreenWindow( + NULL, + this, + fullscreen_region_mode_id_)); Rect bounds = {0,0,0,0}; GetWindowBounds(GetFullscreenMacWindow(), kWindowContentRgn, &bounds); - SetWindowForAGLContext(mac_agl_context_, GetFullscreenMacWindow()); + o3d::SetWindowForAGLContext(mac_agl_context_, GetFullscreenMacWindow()); aglDisable(mac_agl_context_, AGL_BUFFER_RECT); renderer()->SetClientOriginOffset(0, 0); renderer_->Resize(bounds.right - bounds.left, bounds.bottom - bounds.top); @@ -963,11 +967,11 @@ bool PluginObject::RequestFullscreenDisplay() { fullscreen_ = true; client()->SendResizeEvent(renderer_->width(), renderer_->height(), true); - SetFullscreenOverlayMacWindow(CreateOverlayWindow()); + SetFullscreenOverlayMacWindow(o3d::CreateOverlayWindow()); ShowWindow(mac_fullscreen_overlay_window_); - SlideWindowToRect(mac_fullscreen_overlay_window_, - Rect2CGRect(GetOverlayWindowRect(true)), - kTransitionTime); + o3d::SlideWindowToRect(mac_fullscreen_overlay_window_, + o3d::Rect2CGRect(o3d::GetOverlayWindowRect(true)), + kTransitionTime); // Hide the overlay text 4 seconds from now. time_to_hide_overlay_ = [NSDate timeIntervalSinceReferenceDate] + 4.0; @@ -980,9 +984,9 @@ void PluginObject::CancelFullscreenDisplay() { if (!GetFullscreenMacWindow()) return; - SetWindowForAGLContext(mac_agl_context_, mac_window_); + o3d::SetWindowForAGLContext(mac_agl_context_, mac_window_); - CleanupFullscreenWindow(this); + o3d::CleanupFullscreenWindow(this); renderer_->Resize(prev_width_, prev_height_); aglSetInteger(mac_agl_context_, AGL_BUFFER_RECT, last_buffer_rect_); @@ -1013,9 +1017,10 @@ void PluginObject::FullscreenIdle() { (time_to_hide_overlay_ != 0.0) && (time_to_hide_overlay_ < [NSDate timeIntervalSinceReferenceDate])) { time_to_hide_overlay_ = 0.0; - SlideWindowToRect(mac_fullscreen_overlay_window_, - Rect2CGRect(GetOverlayWindowRect(false)), - kTransitionTime); + o3d::SlideWindowToRect(mac_fullscreen_overlay_window_, + o3d::Rect2CGRect(o3d::GetOverlayWindowRect(false)), + kTransitionTime); } } +} // namespace o3d diff --git a/o3d/plugin/win/config.cc b/o3d/plugin/win/config.cc index dd08101..e47147a 100644 --- a/o3d/plugin/win/config.cc +++ b/o3d/plugin/win/config.cc @@ -57,6 +57,8 @@ #include "core/cross/install_check.h" #include "third_party/nixysa/files/static_glue/npapi/common.h" +namespace o3d { + // Check Windows version. bool CheckOSVersion(NPP npp) { OSVERSIONINFOEX version = {sizeof(OSVERSIONINFOEX)}; // NOLINT @@ -232,3 +234,4 @@ bool GetUserAgentMetrics(NPP npp) { } return true; } +} // namespace o3d diff --git a/o3d/plugin/win/main_win.cc b/o3d/plugin/win/main_win.cc index 57623d2..594dbff 100644 --- a/o3d/plugin/win/main_win.cc +++ b/o3d/plugin/win/main_win.cc @@ -59,16 +59,30 @@ o3d::PluginLogging* g_logger = NULL; bool g_logging_initialized = false; o3d::BluescreenDetector *g_bluescreen_detector = NULL; +#if !defined(O3D_INTERNAL_PLUGIN) +extern "C" BOOL WINAPI DllMain(HINSTANCE instance, + DWORD reason, + LPVOID reserved) { + if (reason == DLL_PROCESS_DETACH) { + // Teardown V8 when the plugin dll is unloaded. + // NOTE: NP_Shutdown would have been a good place for this code but + // unfortunately it looks like it gets called even when the dll + // isn't really unloaded. This is a problem since after calling + // V8::Dispose(), V8 cannot be initialized again. + bool v8_disposed = v8::V8::Dispose(); + if (!v8_disposed) + DLOG(ERROR) << "Failed to release V8 resources."; + return true; + } + return true; +} +#endif // O3D_INTERNAL_PLUGIN + namespace { // We would normally make this a stack variable in main(), but in a // plugin, that's not possible, so we allocate it dynamically and // destroy it explicitly. scoped_ptr<base::AtExitManager> g_at_exit_manager; -} // end anonymous namespace - -void RenderOnDemandCallbackHandler::Run() { - ::InvalidateRect(obj_->GetHWnd(), NULL, TRUE); -} static int HandleKeyboardEvent(PluginObject *obj, HWND hWnd, @@ -148,11 +162,11 @@ static int HandleKeyboardEvent(PluginObject *obj, return 0; } -static void HandleMouseEvent(PluginObject *obj, - HWND hWnd, - UINT Msg, - WPARAM wParam, - LPARAM lParam) { +void HandleMouseEvent(PluginObject *obj, + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) { DCHECK(obj); DCHECK(obj->client()); bool fake_dblclick = false; @@ -326,12 +340,12 @@ static void HandleMouseEvent(PluginObject *obj, } // This returns 0 on success, 1 on failure, to match WindowProc. -static LRESULT ForwardEvent(PluginObject *obj, - HWND hWnd, - UINT Msg, - WPARAM wParam, - LPARAM lParam, - bool translateCoords) { +LRESULT ForwardEvent(PluginObject *obj, + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + bool translateCoords) { DCHECK(obj); DCHECK(obj->GetPluginHWnd()); HWND dest_hwnd = obj->GetParentHWnd(); @@ -398,7 +412,7 @@ static LRESULT ForwardEvent(PluginObject *obj, return !::PostMessage(dest_hwnd, Msg, wParam, lParam); } -static LRESULT HandleDragAndDrop(PluginObject *obj, WPARAM wParam) { +LRESULT HandleDragAndDrop(PluginObject *obj, WPARAM wParam) { HDROP hDrop = reinterpret_cast<HDROP>(wParam); UINT num_files = ::DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); if (!num_files) { @@ -457,8 +471,7 @@ static LRESULT HandleDragAndDrop(PluginObject *obj, WPARAM wParam) { return 1; } -static LRESULT CALLBACK -WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { +LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PluginObject *obj = PluginObject::GetPluginProperty(hWnd); if (obj == NULL) { // It's not my window return 1; // 0 often means we handled it. @@ -644,345 +657,324 @@ WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { return 0; } -NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value) { - return NPERR_INVALID_PARAM; +NPError InitializePlugin() { +#if !defined(O3D_INTERNAL_PLUGIN) + if (!o3d::SetupOutOfMemoryHandler()) + return NPERR_MODULE_LOAD_FAILED_ERROR; + + // Setup crash handler + if (!g_exception_manager) { + g_exception_manager = new ExceptionManager(false); + g_exception_manager->StartMonitoring(); + } + + // Initialize the AtExitManager so that base singletons can be + // destroyed properly. + g_at_exit_manager.reset(new base::AtExitManager()); + + // Turn on the logging. + CommandLine::Init(0, NULL); + InitLogging(L"debug.log", + logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, + logging::DONT_LOCK_LOG_FILE, + logging::APPEND_TO_OLD_LOG_FILE); +#endif // O3D_INTERNAL_PLUGIN + + DLOG(INFO) << "NP_Initialize"; + + return NPERR_NO_ERROR; +} + +void CleanupFullscreenWindow(PluginObject *obj) { + DCHECK(obj->GetFullscreenHWnd()); + obj->StorePluginProperty(obj->GetPluginHWnd(), obj); + ::DestroyWindow(obj->GetFullscreenHWnd()); + obj->SetFullscreenHWnd(NULL); +} + +void CleanupAllWindows(PluginObject *obj) { + DCHECK(obj->GetHWnd()); + DCHECK(obj->GetPluginHWnd()); + ::KillTimer(obj->GetHWnd(), 0); + if (obj->GetFullscreenHWnd()) { + CleanupFullscreenWindow(obj); + } + PluginObject::ClearPluginProperty(obj->GetHWnd()); + ::SetWindowLongPtr(obj->GetPluginHWnd(), + GWL_WNDPROC, + reinterpret_cast<LONG_PTR>( + obj->GetDefaultPluginWindowProc())); + obj->SetPluginHWnd(NULL); + obj->SetHWnd(NULL); } +HWND CreateFullscreenWindow(PluginObject *obj, + int mode_id) { + o3d::DisplayMode mode; + if (!obj->renderer()->GetDisplayMode(mode_id, &mode)) { + return NULL; + } + CHECK(mode.width() > 0 && mode.height() > 0); + + HINSTANCE instance = + reinterpret_cast<HINSTANCE>( + ::GetWindowLongPtr(obj->GetPluginHWnd(), GWLP_HINSTANCE)); + WNDCLASSEX *wcx = obj->GetFullscreenWindowClass(instance, WindowProc); + HWND hWnd = CreateWindowEx(NULL, + wcx->lpszClassName, + L"O3D Test Fullscreen Window", + WS_POPUP, + 0, 0, + mode.width(), + mode.height(), + NULL, + NULL, + instance, + NULL); + + ShowWindow(hWnd, SW_SHOW); + return hWnd; +} +} // namespace anonymous + +#if defined(O3D_INTERNAL_PLUGIN) +namespace o3d { +#else extern "C" { - BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { - if (reason == DLL_PROCESS_DETACH) { - // Teardown V8 when the plugin dll is unloaded. - // NOTE: NP_Shutdown would have been a good place for this code but - // unfortunately it looks like it gets called even when the dll - // isn't really unloaded. This is a problem since after calling - // V8::Dispose(), V8 cannot be initialized again. - bool v8_disposed = v8::V8::Dispose(); - if (!v8_disposed) - DLOG(ERROR) << "Failed to release V8 resources."; - return true; - } - return true; - } - - NPError InitializePlugin() { - if (!o3d::SetupOutOfMemoryHandler()) - return NPERR_MODULE_LOAD_FAILED_ERROR; +#endif - // Setup crash handler - if (!g_exception_manager) { - g_exception_manager = new ExceptionManager(false); - g_exception_manager->StartMonitoring(); - } +NPError OSCALL NP_Initialize(NPNetscapeFuncs *browserFuncs) { + HANDLE_CRASHES; + NPError retval = InitializeNPNApi(browserFuncs); + if (retval != NPERR_NO_ERROR) return retval; + return InitializePlugin(); +} - // Initialize the AtExitManager so that base singletons can be - // destroyed properly. - g_at_exit_manager.reset(new base::AtExitManager()); - - // Turn on the logging. - CommandLine::Init(0, NULL); - InitLogging(L"debug.log", - logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, - logging::DONT_LOCK_LOG_FILE, - logging::APPEND_TO_OLD_LOG_FILE); - - DLOG(INFO) << "NP_Initialize"; - - // Limit the current thread to one processor (the current one). This ensures - // that timing code runs on only one processor, and will not suffer any ill - // effects from power management. See "Game Timing and Multicore Processors" - // in the DirectX docs for more details - { - HANDLE current_process_handle = GetCurrentProcess(); - - // Get the processor affinity mask for this process - DWORD_PTR process_affinity_mask = 0; - DWORD_PTR system_affinity_mask = 0; - - if (GetProcessAffinityMask(current_process_handle, - &process_affinity_mask, - &system_affinity_mask) != 0 && - process_affinity_mask) { - // Find the lowest processor that our process is allows to run against - DWORD_PTR affinity_mask = (process_affinity_mask & - ((~process_affinity_mask) + 1)); - - // Set this as the processor that our thread must always run against - // This must be a subset of the process affinity mask - HANDLE hCurrentThread = GetCurrentThread(); - if (INVALID_HANDLE_VALUE != hCurrentThread) { - SetThreadAffinityMask(hCurrentThread, affinity_mask); - CloseHandle(hCurrentThread); - } - } +NPError OSCALL NP_Shutdown(void) { + HANDLE_CRASHES; + DLOG(INFO) << "NP_Shutdown"; - CloseHandle(current_process_handle); - } +#if !defined(O3D_INTERNAL_PLUGIN) - return NPERR_NO_ERROR; + if (g_logger) { + // Do a last sweep to aggregate metrics before we shut down + g_logger->ProcessMetrics(true, false); + delete g_logger; + g_logger = NULL; + g_logging_initialized = false; + stats_report::g_global_metrics.Uninitialize(); } - NPError OSCALL NP_Initialize(NPNetscapeFuncs *browserFuncs) { - HANDLE_CRASHES; - NPError retval = InitializeNPNApi(browserFuncs); - if (retval != NPERR_NO_ERROR) return retval; - return InitializePlugin(); + CommandLine::Terminate(); + + // Force all base singletons to be destroyed. + g_at_exit_manager.reset(NULL); + + // TODO : This is commented out until we can determine if + // it's safe to shutdown breakpad at this stage (Gears, for + // example, never deletes...) + // Shutdown breakpad + // delete g_exception_manager; + + // Strictly speaking, on windows, it's not really necessary to call + // Stop(), but we do so for completeness + if (g_bluescreen_detector) { + g_bluescreen_detector->Stop(); + delete g_bluescreen_detector; + g_bluescreen_detector = NULL; } - NPError OSCALL NP_Shutdown(void) { - HANDLE_CRASHES; - DLOG(INFO) << "NP_Shutdown"; - if (g_logger) { - // Do a last sweep to aggregate metrics before we shut down - g_logger->ProcessMetrics(true, false); - delete g_logger; - g_logger = NULL; - g_logging_initialized = false; - stats_report::g_global_metrics.Uninitialize(); - } +#endif // O3D_INTERNAL_PLUGIN + + return NPERR_NO_ERROR; +} +} // extern "C" / namespace o3d - CommandLine::Terminate(); +namespace o3d { +void RenderOnDemandCallbackHandler::Run() { + ::InvalidateRect(obj_->GetHWnd(), NULL, TRUE); +} - // Force all base singletons to be destroyed. - g_at_exit_manager.reset(NULL); +NPError NPP_New(NPMIMEType pluginType, + NPP instance, + uint16 mode, + int16 argc, + char *argn[], + char *argv[], + NPSavedData *saved) { + HANDLE_CRASHES; + +#if !defined(O3D_INTERNAL_PLUGIN) + if (!g_logging_initialized) { + // Get user config metrics. These won't be stored though unless the user + // opts-in for usagestats logging + GetUserAgentMetrics(instance); + GetUserConfigMetrics(); + // Create usage stats logs object + g_logger = o3d::PluginLogging::InitializeUsageStatsLogging(); + if (g_logger) { + // Setup blue-screen detection + g_bluescreen_detector = new o3d::BluescreenDetector(); + g_bluescreen_detector->Start(); + } + g_logging_initialized = true; + } +#endif - // TODO : This is commented out until we can determine if - // it's safe to shutdown breakpad at this stage (Gears, for - // example, never deletes...) - // Shutdown breakpad - // delete g_exception_manager; + PluginObject* pluginObject = glue::_o3d::PluginObject::Create( + instance); + instance->pdata = pluginObject; + glue::_o3d::InitializeGlue(instance); + pluginObject->Init(argc, argn, argv); + return NPERR_NO_ERROR; +} - // Strictly speaking, on windows, it's not really necessary to call - // Stop(), but we do so for completeness - if (g_bluescreen_detector) { - g_bluescreen_detector->Stop(); - delete g_bluescreen_detector; - g_bluescreen_detector = NULL; +NPError NPP_Destroy(NPP instance, NPSavedData **save) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + if (obj) { + if (obj->GetHWnd()) { + CleanupAllWindows(obj); } - return NPERR_NO_ERROR; + obj->TearDown(); + NPN_ReleaseObject(obj); + instance->pdata = NULL; } - NPError NPP_New(NPMIMEType pluginType, - NPP instance, - uint16 mode, - int16 argc, - char *argn[], - char *argv[], - NPSavedData *saved) { - HANDLE_CRASHES; - - if (!g_logging_initialized) { - // Get user config metrics. These won't be stored though unless the user - // opts-in for usagestats logging - GetUserAgentMetrics(instance); - GetUserConfigMetrics(); - // Create usage stats logs object - g_logger = o3d::PluginLogging::InitializeUsageStatsLogging(); - if (g_logger) { - // Setup blue-screen detection - g_bluescreen_detector = new o3d::BluescreenDetector(); - g_bluescreen_detector->Start(); - } - g_logging_initialized = true; + return NPERR_NO_ERROR; +} + +NPError PlatformNPPGetValue(NPP instance, NPPVariable variable, void *value) { + return NPERR_INVALID_PARAM; +} + +NPError NPP_SetWindow(NPP instance, NPWindow *window) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + + HWND hWnd = static_cast<HWND>(window->window); + if (!hWnd) { + // Chrome calls us this way before NPP_Destroy. + if (obj->GetHWnd()) { + CleanupAllWindows(obj); } - PluginObject* pluginObject = glue::_o3d::PluginObject::Create( - instance); - instance->pdata = pluginObject; - glue::_o3d::InitializeGlue(instance); - pluginObject->Init(argc, argn, argv); return NPERR_NO_ERROR; } - - void CleanupFullscreenWindow(PluginObject *obj) { - DCHECK(obj->GetFullscreenHWnd()); - obj->StorePluginProperty(obj->GetPluginHWnd(), obj); - ::DestroyWindow(obj->GetFullscreenHWnd()); - obj->SetFullscreenHWnd(NULL); + if (obj->GetHWnd() == hWnd) { + return NPERR_NO_ERROR; } - - void CleanupAllWindows(PluginObject *obj) { - DCHECK(obj->GetHWnd()); + if (obj->fullscreen()) { + // We can get here if the user alt+tabs away from the fullscreen plugin + // window or JavaScript resizes the plugin window. DCHECK(obj->GetPluginHWnd()); - ::KillTimer(obj->GetHWnd(), 0); - if (obj->GetFullscreenHWnd()) { - CleanupFullscreenWindow(obj); - } - PluginObject::ClearPluginProperty(obj->GetHWnd()); - ::SetWindowLongPtr(obj->GetPluginHWnd(), - GWL_WNDPROC, - reinterpret_cast<LONG_PTR>( - obj->GetDefaultPluginWindowProc())); - obj->SetPluginHWnd(NULL); - obj->SetHWnd(NULL); - } - - NPError NPP_Destroy(NPP instance, NPSavedData **save) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - if (obj) { - if (obj->GetHWnd()) { - CleanupAllWindows(obj); - } - - obj->TearDown(); - NPN_ReleaseObject(obj); - instance->pdata = NULL; - } - + DCHECK(obj->GetFullscreenHWnd()); + DCHECK(obj->GetPluginHWnd() == hWnd); return NPERR_NO_ERROR; } + DCHECK(!obj->GetPluginHWnd()); + obj->SetPluginHWnd(hWnd); + obj->SetParentHWnd(::GetParent(hWnd)); + PluginObject::StorePluginProperty(hWnd, obj); + obj->SetDefaultPluginWindowProc( + reinterpret_cast<WNDPROC>( + ::SetWindowLongPtr(hWnd, + GWL_WNDPROC, + reinterpret_cast<LONG_PTR>(WindowProc)))); + + // create and assign the graphics context + DisplayWindowWindows default_display; + default_display.set_hwnd(obj->GetHWnd()); + + obj->CreateRenderer(default_display); + obj->client()->Init(); + obj->client()->SetRenderOnDemandCallback( + new RenderOnDemandCallbackHandler(obj)); + + // we set the timer to 10ms or 100fps. At the time of this comment + // the renderer does a vsync the max fps it will run will be the refresh + // rate of the monitor or 100fps, which ever is lower. + ::SetTimer(obj->GetHWnd(), 0, 10, NULL); + + return NPERR_NO_ERROR; +} - bool PluginObject::GetDisplayMode(int mode_id, o3d::DisplayMode *mode) { - return renderer()->GetDisplayMode(mode_id, mode); - } +// Called when the browser has finished attempting to stream data to +// a file as requested. If fname == NULL the attempt was not successful. +void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) { + HANDLE_CRASHES; + PluginObject *obj = static_cast<PluginObject*>(instance->pdata); + StreamManager *stream_manager = obj->stream_manager(); + stream_manager->SetStreamFile(stream, fname); +} - HWND CreateFullscreenWindow(PluginObject *obj, - int mode_id) { - o3d::DisplayMode mode; - if (!obj->renderer()->GetDisplayMode(mode_id, &mode)) { - return NULL; - } - CHECK(mode.width() > 0 && mode.height() > 0); - - HINSTANCE instance = - reinterpret_cast<HINSTANCE>( - ::GetWindowLongPtr(obj->GetPluginHWnd(), GWLP_HINSTANCE)); - WNDCLASSEX *wcx = obj->GetFullscreenWindowClass(instance, WindowProc); - HWND hWnd = CreateWindowEx(NULL, - wcx->lpszClassName, - L"O3D Test Fullscreen Window", - WS_POPUP, - 0, 0, - mode.width(), - mode.height(), - NULL, - NULL, - instance, - NULL); - - ShowWindow(hWnd, SW_SHOW); - return hWnd; - } - - // TODO: Where should this really live? It's platform-specific, but in - // PluginObject, which mainly lives in cross/o3d_glue.h+cc. - bool PluginObject::RequestFullscreenDisplay() { - bool success = false; - DCHECK(GetPluginHWnd()); - if (!fullscreen_ && renderer_ && fullscreen_region_valid_) { - DCHECK(renderer_->fullscreen() == fullscreen_); - DCHECK(!GetFullscreenHWnd()); - HWND drawing_hwnd = - CreateFullscreenWindow(this, fullscreen_region_mode_id_); - if (drawing_hwnd) { - ::KillTimer(GetHWnd(), 0); - SetFullscreenHWnd(drawing_hwnd); - StorePluginPropertyUnsafe(drawing_hwnd, this); - - DisplayWindowWindows display; - display.set_hwnd(GetHWnd()); - if (renderer_->SetFullscreen(true, display, - fullscreen_region_mode_id_)) { - fullscreen_ = true; - client()->SendResizeEvent(renderer_->width(), renderer_->height(), - true); - success = true; - } else { - CleanupFullscreenWindow(this); - } - prev_width_ = renderer_->width(); - prev_height_ = renderer_->height(); - ::SetTimer(GetHWnd(), 0, 10, NULL); - } else { - LOG(ERROR) << "Failed to create fullscreen window."; - } - } - return success; - } +int16 NPP_HandleEvent(NPP instance, void *event) { + HANDLE_CRASHES; + return 0; +} +} // namespace o3d + +namespace glue { +namespace _o3d { +bool PluginObject::GetDisplayMode(int mode_id, o3d::DisplayMode *mode) { + return renderer()->GetDisplayMode(mode_id, mode); +} - void PluginObject::CancelFullscreenDisplay() { - DCHECK(GetPluginHWnd()); - if (fullscreen_) { - DCHECK(renderer()); - DCHECK(renderer()->fullscreen()); +// TODO: Where should this really live? It's platform-specific, but in +// PluginObject, which mainly lives in cross/o3d_glue.h+cc. +bool PluginObject::RequestFullscreenDisplay() { + bool success = false; + DCHECK(GetPluginHWnd()); + if (!fullscreen_ && renderer_ && fullscreen_region_valid_) { + DCHECK(renderer_->fullscreen() == fullscreen_); + DCHECK(!GetFullscreenHWnd()); + HWND drawing_hwnd = + CreateFullscreenWindow(this, fullscreen_region_mode_id_); + if (drawing_hwnd) { ::KillTimer(GetHWnd(), 0); + SetFullscreenHWnd(drawing_hwnd); + StorePluginPropertyUnsafe(drawing_hwnd, this); + DisplayWindowWindows display; - display.set_hwnd(GetPluginHWnd()); - if (!renderer_->SetFullscreen(false, display, 0)) { - LOG(FATAL) << "Failed to get the renderer out of fullscreen mode!"; + display.set_hwnd(GetHWnd()); + if (renderer_->SetFullscreen(true, display, + fullscreen_region_mode_id_)) { + fullscreen_ = true; + client()->SendResizeEvent(renderer_->width(), renderer_->height(), + true); + success = true; + } else { + CleanupFullscreenWindow(this); } - CleanupFullscreenWindow(this); prev_width_ = renderer_->width(); prev_height_ = renderer_->height(); - client()->SendResizeEvent(prev_width_, prev_height_, false); ::SetTimer(GetHWnd(), 0, 10, NULL); - fullscreen_ = false; - } - } - - NPError NPP_SetWindow(NPP instance, NPWindow *window) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - - HWND hWnd = static_cast<HWND>(window->window); - if (!hWnd) { - // Chrome calls us this way before NPP_Destroy. - if (obj->GetHWnd()) { - CleanupAllWindows(obj); - } - return NPERR_NO_ERROR; - } - if (obj->GetHWnd() == hWnd) { - return NPERR_NO_ERROR; - } - if (obj->fullscreen()) { - // We can get here if the user alt+tabs away from the fullscreen plugin - // window or JavaScript resizes the plugin window. - DCHECK(obj->GetPluginHWnd()); - DCHECK(obj->GetFullscreenHWnd()); - DCHECK(obj->GetPluginHWnd() == hWnd); - return NPERR_NO_ERROR; + } else { + LOG(ERROR) << "Failed to create fullscreen window."; } - DCHECK(!obj->GetPluginHWnd()); - obj->SetPluginHWnd(hWnd); - obj->SetParentHWnd(::GetParent(hWnd)); - PluginObject::StorePluginProperty(hWnd, obj); - obj->SetDefaultPluginWindowProc( - reinterpret_cast<WNDPROC>( - ::SetWindowLongPtr(hWnd, - GWL_WNDPROC, - reinterpret_cast<LONG_PTR>(WindowProc)))); - - // create and assign the graphics context - DisplayWindowWindows default_display; - default_display.set_hwnd(obj->GetHWnd()); - - obj->CreateRenderer(default_display); - obj->client()->Init(); - obj->client()->SetRenderOnDemandCallback( - new RenderOnDemandCallbackHandler(obj)); - - // we set the timer to 10ms or 100fps. At the time of this comment - // the renderer does a vsync the max fps it will run will be the refresh - // rate of the monitor or 100fps, which ever is lower. - ::SetTimer(obj->GetHWnd(), 0, 10, NULL); - - return NPERR_NO_ERROR; - } - - // Called when the browser has finished attempting to stream data to - // a file as requested. If fname == NULL the attempt was not successful. - void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) { - HANDLE_CRASHES; - PluginObject *obj = static_cast<PluginObject*>(instance->pdata); - StreamManager *stream_manager = obj->stream_manager(); - - stream_manager->SetStreamFile(stream, fname); } + return success; +} - int16 NPP_HandleEvent(NPP instance, void *event) { - HANDLE_CRASHES; - return 0; +void PluginObject::CancelFullscreenDisplay() { + DCHECK(GetPluginHWnd()); + if (fullscreen_) { + DCHECK(renderer()); + DCHECK(renderer()->fullscreen()); + ::KillTimer(GetHWnd(), 0); + DisplayWindowWindows display; + display.set_hwnd(GetPluginHWnd()); + if (!renderer_->SetFullscreen(false, display, 0)) { + LOG(FATAL) << "Failed to get the renderer out of fullscreen mode!"; + } + CleanupFullscreenWindow(this); + prev_width_ = renderer_->width(); + prev_height_ = renderer_->height(); + client()->SendResizeEvent(prev_width_, prev_height_, false); + ::SetTimer(GetHWnd(), 0, 10, NULL); + fullscreen_ = false; } -} // end extern "C" +} +} // namespace _o3d +} // namespace glue diff --git a/o3d/plugin/win/update_lock.cc b/o3d/plugin/win/update_lock.cc index 3900365..257aeb2 100644 --- a/o3d/plugin/win/update_lock.cc +++ b/o3d/plugin/win/update_lock.cc @@ -32,8 +32,12 @@ #include "update_lock.h" +#if !defined(O3D_INTERNAL_PLUGIN) + namespace { // Instantiate a global object to indicate that the application is running. update_lock::HandleWrapper g_update_lock(update_lock::LockFromUpdates()); } // anonymous namespace + +#endif // O3D_INTERNAL_PLUGIN diff --git a/o3d/plugin/win/update_lock.h b/o3d/plugin/win/update_lock.h index dcf78ad..8e7b419 100644 --- a/o3d/plugin/win/update_lock.h +++ b/o3d/plugin/win/update_lock.h @@ -33,6 +33,8 @@ #ifndef O3D_PLUGIN_WIN_UPDATE_LOCK_H_ #define O3D_PLUGIN_WIN_UPDATE_LOCK_H_ +#if !defined(O3D_INTERNAL_PLUGIN) + #include <windows.h> #include "base/basictypes.h" @@ -96,5 +98,7 @@ HANDLE LockFromUpdates() { } } // namespace update_lock +#endif // O3D_INTERNAL_PLUGIN + #endif // O3D_PLUGIN_WIN_UPDATE_LOCK_H_ |