summaryrefslogtreecommitdiffstats
path: root/o3d/plugin/cross
diff options
context:
space:
mode:
authorapatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-13 20:19:04 +0000
committerapatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-13 20:19:04 +0000
commitcd7b299fd6053afcd625ce36f0e51f94c83b182c (patch)
treec8db33db4106077f2b9c16bc6b5e6822568e411f /o3d/plugin/cross
parent3d2da9c08491d46c0b3f8dcdccbb6d1c84bfbc40 (diff)
downloadchromium_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.h13
-rw-r--r--o3d/plugin/cross/o3d_glue.cc71
-rw-r--r--o3d/plugin/cross/o3d_glue.h16
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;