diff options
Diffstat (limited to 'o3d/plugin/cross')
-rw-r--r-- | o3d/plugin/cross/main_thread_task_poster.cc | 64 | ||||
-rw-r--r-- | o3d/plugin/cross/main_thread_task_poster.h | 57 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.cc | 61 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.h | 3 |
4 files changed, 155 insertions, 30 deletions
diff --git a/o3d/plugin/cross/main_thread_task_poster.cc b/o3d/plugin/cross/main_thread_task_poster.cc new file mode 100644 index 0000000..24a42e2 --- /dev/null +++ b/o3d/plugin/cross/main_thread_task_poster.cc @@ -0,0 +1,64 @@ +/* + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include <npapi.h> +#include "plugin/cross/main_thread_task_poster.h" + +namespace o3d { + +MainThreadTaskPoster::MainThreadTaskPoster(ServiceLocator* service_locator, + NPP npp) + : service_(service_locator, this), + npp_(npp) { +} + +MainThreadTaskPoster::~MainThreadTaskPoster() { +} + +bool MainThreadTaskPoster::IsSupported() { + int plugin_major, plugin_minor, browser_major, browser_minor; + NPN_Version(&plugin_major, &plugin_minor, &browser_major, &browser_minor); + return browser_major > 0 || + browser_minor >= NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL; +} + +void MainThreadTaskPoster::PostTask(Task* task) { + DCHECK(IsSupported()); + NPN_PluginThreadAsyncCall(npp_, &MainThreadTaskPoster::RunTask, task); +} + +void MainThreadTaskPoster::RunTask(void* data) { + Task* task = static_cast<Task*>(data); + task->Run(); + delete task; +} +} // namespace o3d diff --git a/o3d/plugin/cross/main_thread_task_poster.h b/o3d/plugin/cross/main_thread_task_poster.h new file mode 100644 index 0000000..e322af1 --- /dev/null +++ b/o3d/plugin/cross/main_thread_task_poster.h @@ -0,0 +1,57 @@ +/* + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef O3D_PLUGIN_CROSS_MAIN_THREAD_TASK_POSTER_H +#define O3D_PLUGIN_CROSS_MAIN_THREAD_TASK_POSTER_H + +#include <npapi.h> +#include "core/cross/imain_thread_task_poster.h" +#include "core/cross/service_implementation.h" + +namespace o3d { + +class MainThreadTaskPoster : public IMainThreadTaskPoster { + public: + MainThreadTaskPoster(ServiceLocator* service_locator, NPP npp); + virtual ~MainThreadTaskPoster(); + virtual bool IsSupported(); + virtual void PostTask(Task* task); + private: + static void RunTask(void* data); + ServiceImplementation<IMainThreadTaskPoster> service_; + NPP npp_; + DISALLOW_COPY_AND_ASSIGN(MainThreadTaskPoster); +}; + +} // namespace o3d + +#endif // O3D_PLUGIN_CROSS_MAIN_THREAD_TASK_POSTER_H diff --git a/o3d/plugin/cross/o3d_glue.cc b/o3d/plugin/cross/o3d_glue.cc index 9d6c24e..9053255 100644 --- a/o3d/plugin/cross/o3d_glue.cc +++ b/o3d/plugin/cross/o3d_glue.cc @@ -101,6 +101,7 @@ PluginObject::PluginObject(NPP npp) client_info_manager_(&service_locator_), object_manager_(&service_locator_), profiler_(&service_locator_), + main_thread_task_poster_(&service_locator_, npp), fullscreen_(false), renderer_(NULL), features_(NULL), @@ -822,52 +823,52 @@ void PluginObject::PlatformSpecificSetCursor() { #endif // OS_LINUX -void PluginObject::AsyncTick() { - if (pending_ticks_ >= 1) +namespace { +void TickPluginObject(void* data) { + PluginObject* plugin_object = static_cast<PluginObject*>(data); + + // Check the plugin has not been destroyed already. Chrome sometimes invokes + // async callbacks after destruction. + if (!plugin_object->client()) return; - class TickCallback : public StreamManager::FinishedCallback { - public: - explicit TickCallback(PluginObject* plugin_object) - : plugin_object_(plugin_object) { - } + // Don't allow reentrancy through asynchronous ticks. Chrome sometimes does + // this. It is also possible for the asyncronous call to be invoked while + // a message is being handled. This prevents that. + Client::ScopedIncrement reentrance_count(plugin_object->client()); + if (reentrance_count.get() > 1) + return; - virtual void Run(DownloadStream*, - bool, - const std::string&, - const std::string&) { - plugin_object_->Tick(); - } + plugin_object->Tick(); +} +} - private: - PluginObject* plugin_object_; - }; +void PluginObject::AsyncTick() { + if (pending_ticks_ >= 1) + return; ++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. + // Invoke Tick asynchronously if NPN_PluginThreadAsyncCall is supported. + // Otherwise invoke it synchronously. + int plugin_major, plugin_minor, browser_major, browser_minor; + NPN_Version(&plugin_major, &plugin_minor, &browser_major, &browser_minor); + if (browser_major > 0 || + browser_minor >= NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL) { + NPN_PluginThreadAsyncCall(npp_, TickPluginObject, this); + } else { Tick(); } } void PluginObject::Tick() { + DCHECK(pending_ticks_ > 0); + --pending_ticks_; + client_->Tick(); if (renderer_ && renderer_->need_to_render()) { client_->RenderClient(true); } - - DCHECK(pending_ticks_ > 0); - --pending_ticks_; } } // namespace _o3d diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h index c61d1d9..c318ea5 100644 --- a/o3d/plugin/cross/o3d_glue.h +++ b/o3d/plugin/cross/o3d_glue.h @@ -64,6 +64,7 @@ #include "core/cross/object_manager.h" #include "core/cross/error.h" #include "core/cross/profiler.h" +#include "plugin/cross/main_thread_task_poster.h" #include "plugin/cross/np_v8_bridge.h" #include "client_glue.h" #include "third_party/nixysa/static_glue/npapi/common.h" @@ -85,6 +86,7 @@ using o3d::ClientInfoManager; using o3d::EvaluationCounter; using o3d::Features; using o3d::EvaluationCounter; +using o3d::MainThreadTaskPoster; using o3d::ObjectManager; using o3d::Profiler; using o3d::Renderer; @@ -129,6 +131,7 @@ class PluginObject: public NPObject { ClientInfoManager client_info_manager_; ObjectManager object_manager_; Profiler profiler_; + MainThreadTaskPoster main_thread_task_poster_; bool fullscreen_; // Are we rendered fullscreen or in the plugin region? Renderer *renderer_; Client *client_; |