diff options
author | apatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-13 20:19:04 +0000 |
---|---|---|
committer | apatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-13 20:19:04 +0000 |
commit | cd7b299fd6053afcd625ce36f0e51f94c83b182c (patch) | |
tree | c8db33db4106077f2b9c16bc6b5e6822568e411f /o3d/plugin/cross | |
parent | 3d2da9c08491d46c0b3f8dcdccbb6d1c84bfbc40 (diff) | |
download | chromium_src-cd7b299fd6053afcd625ce36f0e51f94c83b182c.zip chromium_src-cd7b299fd6053afcd625ce36f0e51f94c83b182c.tar.gz chromium_src-cd7b299fd6053afcd625ce36f0e51f94c83b182c.tar.bz2 |
Plugin no longer makes synchronous NPAPI calls from a Windows message handler. This fixes deadlocks and slowdown in Chrome. The approach is strange. It asynchronously opens the url data:, and then invokes Tick from the finish callback. This is the simplest approach I could think of that hide widespread browser support. NPN_PluginThreadAsyncCall would be ideal but it is supported by all browsers we currently support.
Review URL: http://codereview.chromium.org/149415
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20517 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/plugin/cross')
-rw-r--r-- | o3d/plugin/cross/main.h | 13 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.cc | 71 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.h | 16 |
3 files changed, 65 insertions, 35 deletions
diff --git a/o3d/plugin/cross/main.h b/o3d/plugin/cross/main.h index 003a63a..c5de7b6 100644 --- a/o3d/plugin/cross/main.h +++ b/o3d/plugin/cross/main.h @@ -99,19 +99,6 @@ 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); diff --git a/o3d/plugin/cross/o3d_glue.cc b/o3d/plugin/cross/o3d_glue.cc index 68565aa..65912ba 100644 --- a/o3d/plugin/cross/o3d_glue.cc +++ b/o3d/plugin/cross/o3d_glue.cc @@ -106,6 +106,7 @@ PluginObject::PluginObject(NPP npp) features_(NULL), fullscreen_region_valid_(false), renderer_init_status_(Renderer::UNINITIALIZED), + pending_ticks_(0), #ifdef OS_WIN hWnd_(NULL), fullscreen_hWnd_(NULL), @@ -131,7 +132,6 @@ PluginObject::PluginObject(NPP npp) mac_agl_context_(0), mac_cgl_context_(0), last_mac_event_time_(0), - wants_redraw_(false), time_to_hide_overlay_(0.0), #endif #ifdef OS_LINUX @@ -388,15 +388,6 @@ void PluginObject::PlatformSpecificSetCursor() { } } -bool PluginObject::WantsRedraw() { - if (client()->render_mode() == o3d::Client::RENDERMODE_CONTINUOUS) - return true; - - // If we're rendering on-demand, then a call to client->render() should - // only force a redraw one time - return wants_redraw_; -} - bool PluginObject::SetRendererIsSoftware(bool state) { renderer_is_software_ = state; ClientInfoManager* client_info_manager = @@ -511,12 +502,14 @@ static void PluginDeallocate(NPObject *object) { static bool PluginHasMethod(NPObject *header, NPIdentifier name) { DebugScopedId id(name); PluginObject *plugin_object = static_cast<PluginObject *>(header); - if (name == method_ids[METHOD_EVAL]) { - return true; - } else { - NPObject *globals = plugin_object->globals_npobject(); - return globals->_class->hasMethod(globals, name); + for (int i = 0; i < NUM_METHOD_IDS; ++i) { + if (name == method_ids[i]) { + return true; + } } + + NPObject *globals = plugin_object->globals_npobject(); + return globals->_class->hasMethod(globals, name); } static bool PluginInvoke(NPObject *header, NPIdentifier name, @@ -829,6 +822,54 @@ void PluginObject::PlatformSpecificSetCursor() { #endif // OS_LINUX +void PluginObject::AsyncTick() { + if (pending_ticks_ >= 1) + return; + + class TickCallback : public StreamManager::FinishedCallback { + public: + explicit TickCallback(PluginObject* plugin_object) + : plugin_object_(plugin_object) { + } + + virtual void Run(DownloadStream*, + bool, + const std::string&, + const std::string&) { + plugin_object_->Tick(); + } + + private: + PluginObject* plugin_object_; + }; + + ++pending_ticks_; + + // Invoke Client::Tick and Client::RenderClient in a way that is asynchronous + // in Chrome. This avoids issues with making calls into the browser from a + // message handler. + // If NPN_PluginThreadAsyncCall worked in more browsers, it would be simpler + // to use that. + // We're calling LoadURL here with a URL that will return 0 bytes on browsers
+ // that support the "data:" protocol and fail in browsers that don't like IE.
+ // On browsers that support it, the side effect is to call the TickCallback.
+ if (!stream_manager_->LoadURL("data:,", NULL, NULL, NULL, + new TickCallback(this), NP_NORMAL)) { + // Fallback on synchronous call if asynchronous load fails. + Tick(); + } +} + +void PluginObject::Tick() { + client_->Tick(); + if (renderer_ && renderer_->need_to_render()) { + client_->RenderClient(); + } + + DCHECK(pending_ticks_ > 0); + --pending_ticks_; +} + } // namespace _o3d namespace globals { diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h index 016b58b..e67d8e6 100644 --- a/o3d/plugin/cross/o3d_glue.h +++ b/o3d/plugin/cross/o3d_glue.h @@ -140,6 +140,8 @@ class PluginObject: public NPObject { ClientNPObject *client_npobject_; std::string user_agent_; Renderer::InitStatus renderer_init_status_; + int pending_ticks_; + // The current cursor type. o3d::Cursor::CursorType cursor_type_; @@ -207,12 +209,6 @@ class PluginObject: public NPObject { return mac_fullscreen_window_; } - // Always returns |true| if RENDERMODE_CONTINUOUS, otherwise - // only if client->render() has been called and we haven't yet - // handled it - bool WantsRedraw(); - void SetWantsRedraw(bool wants) { wants_redraw_ = wants; } - bool ScrollIsInProgress() { return scroll_is_in_progress_; } void SetScrollIsInProgress(bool state) { scroll_is_in_progress_ = state; } bool scroll_is_in_progress_; @@ -226,7 +222,6 @@ class PluginObject: public NPObject { WindowRef mac_window_; // may be NULL in the Chrome case // these vars needed for the Safari tab switch detection hack CFDateRef last_mac_event_time_; - bool wants_redraw_; void * mac_cocoa_window_; void* mac_window_selected_tab_; bool mac_surface_hidden_; @@ -362,6 +357,13 @@ class PluginObject: public NPObject { // Sets the cursor to whatever the current cursor is. void PlatformSpecificSetCursor(); + // Asynchronously (if possible, synchronously otherwise) invoke Tick. No + // operation if an asynchronous tick is already pending. + void AsyncTick(); + + // Tick the client. + void Tick(); + const std::string& user_agent() const { return user_agent_; } bool IsFirefox() const { return user_agent_.find("Firefox") != user_agent_.npos; |