Commit bfd9d5af authored by sergeyu@chromium.org's avatar sergeyu@chromium.org

Revert 96981 - Add PluginMessageLoopProxy and use it for Host plugin UI thread.

The new class will also be used in the client plugin for the main plugin thread.

BUG=None
TEST=Everything works.

Review URL: http://codereview.chromium.org/7635030

TBR=sergeyu@chromium.org
Review URL: http://codereview.chromium.org/7665002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96984 0039d316-1c4b-4281-b951-d872f2087c98
parent ad8ef9ac
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/base/plugin_message_loop_proxy.h"
namespace remoting {
PluginMessageLoopProxy::PluginMessageLoopProxy(Delegate* delegate)
: delegate_(delegate) {
}
PluginMessageLoopProxy::~PluginMessageLoopProxy() {
}
void PluginMessageLoopProxy::Detach() {
base::AutoLock auto_lock(lock_);
delegate_ = NULL;
}
// MessageLoopProxy interface implementation.
bool PluginMessageLoopProxy::PostTask(
const tracked_objects::Location& from_here,
Task* task) {
return PostDelayedTask(from_here, task, 0);
}
bool PluginMessageLoopProxy::PostDelayedTask(
const tracked_objects::Location& from_here,
Task* task,
int64 delay_ms) {
base::AutoLock auto_lock(lock_);
if (!delegate_) {
return false;
} else {
return delegate_->RunOnPluginThread(
delay_ms, &PluginMessageLoopProxy::RunTask, task);
}
}
bool PluginMessageLoopProxy::PostNonNestableTask(
const tracked_objects::Location& from_here,
Task* task) {
// All tasks running on this message loop are non-nestable.
return PostTask(from_here, task);
}
bool PluginMessageLoopProxy::PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
Task* task,
int64 delay_ms) {
// All tasks running on this message loop are non-nestable.
return PostDelayedTask(from_here, task, delay_ms);
}
bool PluginMessageLoopProxy::PostTask(
const tracked_objects::Location& from_here,
const base::Closure& task) {
return PostDelayedTask(from_here, task, 0);
}
bool PluginMessageLoopProxy::PostDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
int64 delay_ms) {
base::AutoLock auto_lock(lock_);
if (!delegate_) {
return false;
} else {
base::Closure* task_on_heap = new base::Closure(task);
return delegate_->RunOnPluginThread(
delay_ms, &PluginMessageLoopProxy::RunClosure, task_on_heap);
}
}
bool PluginMessageLoopProxy::PostNonNestableTask(
const tracked_objects::Location& from_here,
const base::Closure& task) {
// All tasks running on this message loop are non-nestable.
return PostTask(from_here, task);
}
bool PluginMessageLoopProxy::PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
int64 delay_ms) {
// All tasks running on this message loop are non-nestable.
return PostDelayedTask(from_here, task, delay_ms);
}
bool PluginMessageLoopProxy::BelongsToCurrentThread() {
base::AutoLock auto_lock(lock_);
if (delegate_) {
return delegate_->IsPluginThread();
} else {
return false;
}
}
// static
void PluginMessageLoopProxy::RunTask(void* data) {
Task* task = reinterpret_cast<Task*>(data);
task->Run();
delete task;
}
// static
void PluginMessageLoopProxy::RunClosure(void* data) {
base::Closure* task = reinterpret_cast<base::Closure*>(data);
task->Run();
delete task;
}
} // namespace remoting
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_BASE_PLUGIN_MESSAGE_LOOP_H_
#define REMOTING_BASE_PLUGIN_MESSAGE_LOOP_H_
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/message_loop_proxy.h"
namespace remoting {
// MessageLoopProxy for plugin main threads.
class PluginMessageLoopProxy : public base::MessageLoopProxy {
public:
class Delegate {
public:
Delegate() { }
virtual ~Delegate() { }
virtual bool RunOnPluginThread(
int delay_ms, void(function)(void*), void* data) = 0;
virtual bool IsPluginThread() = 0;
};
// Caller keeps ownership of delegate.
PluginMessageLoopProxy(Delegate* delegate);
virtual ~PluginMessageLoopProxy();
void Detach();
// base::MessageLoopProxy interface.
virtual bool PostTask(
const tracked_objects::Location& from_here,
Task* task) OVERRIDE;
virtual bool PostDelayedTask(
const tracked_objects::Location& from_here,
Task* task,
int64 delay_ms) OVERRIDE;
virtual bool PostNonNestableTask(
const tracked_objects::Location& from_here,
Task* task) OVERRIDE;
virtual bool PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
Task* task,
int64 delay_ms) OVERRIDE;
virtual bool PostTask(
const tracked_objects::Location& from_here,
const base::Closure& task) OVERRIDE;
virtual bool PostDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
int64 delay_ms) OVERRIDE;
virtual bool PostNonNestableTask(
const tracked_objects::Location& from_here,
const base::Closure& task) OVERRIDE;
virtual bool PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
int64 delay_ms) OVERRIDE;
virtual bool BelongsToCurrentThread() OVERRIDE;
private:
// |lock_| must be acquired when accessing |delegate_|.
base::Lock lock_;
Delegate* delegate_;
static void RunTask(void* data);
static void RunClosure(void* data);
DISALLOW_COPY_AND_ASSIGN(PluginMessageLoopProxy);
};
} // namespace remoting
#endif // REMOTING_BASE_PLUGIN_MESSAGE_LOOP_H_
...@@ -12,12 +12,10 @@ ...@@ -12,12 +12,10 @@
namespace remoting { namespace remoting {
ChromotingHostContext::ChromotingHostContext( ChromotingHostContext::ChromotingHostContext()
base::MessageLoopProxy* ui_message_loop)
: main_thread_("ChromotingMainThread"), : main_thread_("ChromotingMainThread"),
encode_thread_("ChromotingEncodeThread"), encode_thread_("ChromotingEncodeThread"),
desktop_thread_("ChromotingDesktopThread"), desktop_thread_("ChromotingDesktopThread") {
ui_message_loop_(ui_message_loop) {
} }
ChromotingHostContext::~ChromotingHostContext() { ChromotingHostContext::~ChromotingHostContext() {
...@@ -43,10 +41,6 @@ JingleThread* ChromotingHostContext::jingle_thread() { ...@@ -43,10 +41,6 @@ JingleThread* ChromotingHostContext::jingle_thread() {
return &jingle_thread_; return &jingle_thread_;
} }
base::MessageLoopProxy* ChromotingHostContext::ui_message_loop() {
return ui_message_loop_;
}
MessageLoop* ChromotingHostContext::main_message_loop() { MessageLoop* ChromotingHostContext::main_message_loop() {
return main_thread_.message_loop(); return main_thread_.message_loop();
} }
...@@ -63,4 +57,31 @@ MessageLoop* ChromotingHostContext::desktop_message_loop() { ...@@ -63,4 +57,31 @@ MessageLoop* ChromotingHostContext::desktop_message_loop() {
return desktop_thread_.message_loop(); return desktop_thread_.message_loop();
} }
void ChromotingHostContext::SetUITaskPostFunction(
const UIThreadPostTaskFunction& poster) {
ui_poster_ = poster;
ui_main_thread_id_ = base::PlatformThread::CurrentId();
}
void ChromotingHostContext::PostTaskToUIThread(
const tracked_objects::Location& from_here, const base::Closure& task) {
ui_poster_.Run(from_here, task);
}
void ChromotingHostContext::PostDelayedTaskToUIThread(
const tracked_objects::Location& from_here,
const base::Closure& task,
int delay_ms) {
// Post delayed task on the main thread that will post task on UI
// thread. It is safe to use base::Unretained() here because
// ChromotingHostContext owns |main_thread_|.
main_message_loop()->PostDelayedTask(from_here, base::Bind(
&ChromotingHostContext::PostTaskToUIThread, base::Unretained(this),
from_here, task), delay_ms);
}
bool ChromotingHostContext::IsUIThread() const {
return ui_main_thread_id_ == base::PlatformThread::CurrentId();
}
} // namespace remoting } // namespace remoting
...@@ -25,8 +25,12 @@ namespace remoting { ...@@ -25,8 +25,12 @@ namespace remoting {
// process. This class is virtual only for testing purposes (see below). // process. This class is virtual only for testing purposes (see below).
class ChromotingHostContext { class ChromotingHostContext {
public: public:
typedef base::Callback<void(
const tracked_objects::Location& from_here,
const base::Closure& task)> UIThreadPostTaskFunction;
// Create a context. // Create a context.
ChromotingHostContext(base::MessageLoopProxy* ui_message_loop); ChromotingHostContext();
virtual ~ChromotingHostContext(); virtual ~ChromotingHostContext();
// TODO(ajwong): Move the Start/Stop methods out of this class. Then // TODO(ajwong): Move the Start/Stop methods out of this class. Then
...@@ -38,12 +42,21 @@ class ChromotingHostContext { ...@@ -38,12 +42,21 @@ class ChromotingHostContext {
virtual JingleThread* jingle_thread(); virtual JingleThread* jingle_thread();
virtual base::MessageLoopProxy* ui_message_loop();
virtual MessageLoop* main_message_loop(); virtual MessageLoop* main_message_loop();
virtual MessageLoop* encode_message_loop(); virtual MessageLoop* encode_message_loop();
virtual base::MessageLoopProxy* network_message_loop(); virtual base::MessageLoopProxy* network_message_loop();
virtual MessageLoop* desktop_message_loop(); virtual MessageLoop* desktop_message_loop();
// Must be called from the main GUI thread.
void SetUITaskPostFunction(const UIThreadPostTaskFunction& poster);
void PostTaskToUIThread(const tracked_objects::Location& from_here,
const base::Closure& task);
void PostDelayedTaskToUIThread(const tracked_objects::Location& from_here,
const base::Closure& task,
int delay_ms);
bool IsUIThread() const;
private: private:
FRIEND_TEST_ALL_PREFIXES(ChromotingHostContextTest, StartAndStop); FRIEND_TEST_ALL_PREFIXES(ChromotingHostContextTest, StartAndStop);
...@@ -60,7 +73,10 @@ class ChromotingHostContext { ...@@ -60,7 +73,10 @@ class ChromotingHostContext {
// This is NOT a Chrome-style UI thread. // This is NOT a Chrome-style UI thread.
base::Thread desktop_thread_; base::Thread desktop_thread_;
scoped_refptr<base::MessageLoopProxy> ui_message_loop_; UIThreadPostTaskFunction ui_poster_;
// This IS the main Chrome GUI thread that |ui_poster_| will post to.
base::PlatformThreadId ui_main_thread_id_;
DISALLOW_COPY_AND_ASSIGN(ChromotingHostContext); DISALLOW_COPY_AND_ASSIGN(ChromotingHostContext);
}; };
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "remoting/host/chromoting_host_context.h" #include "remoting/host/chromoting_host_context.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -12,10 +11,7 @@ namespace remoting { ...@@ -12,10 +11,7 @@ namespace remoting {
// A simple test that starts and stop the context. This tests the context // A simple test that starts and stop the context. This tests the context
// operates properly and all threads and message loops are valid. // operates properly and all threads and message loops are valid.
TEST(ChromotingHostContextTest, StartAndStop) { TEST(ChromotingHostContextTest, StartAndStop) {
MessageLoop message_loop; ChromotingHostContext context;
ChromotingHostContext context(
base::MessageLoopProxy::CreateForCurrentThread());
context.Start(); context.Start();
EXPECT_TRUE(context.jingle_thread()); EXPECT_TRUE(context.jingle_thread());
EXPECT_TRUE(context.main_message_loop()); EXPECT_TRUE(context.main_message_loop());
......
...@@ -78,7 +78,7 @@ class ChromotingHostTest : public testing::Test { ...@@ -78,7 +78,7 @@ class ChromotingHostTest : public testing::Test {
ON_CALL(context_, network_message_loop()) ON_CALL(context_, network_message_loop())
.WillByDefault(Return(message_loop_proxy_.get())); .WillByDefault(Return(message_loop_proxy_.get()));
ON_CALL(context_, ui_message_loop()) ON_CALL(context_, ui_message_loop())
.WillByDefault(Return(message_loop_proxy_.get())); .WillByDefault(Return(&message_loop_));
EXPECT_CALL(context_, main_message_loop()) EXPECT_CALL(context_, main_message_loop())
.Times(AnyNumber()); .Times(AnyNumber());
EXPECT_CALL(context_, encode_message_loop()) EXPECT_CALL(context_, encode_message_loop())
...@@ -88,6 +88,12 @@ class ChromotingHostTest : public testing::Test { ...@@ -88,6 +88,12 @@ class ChromotingHostTest : public testing::Test {
EXPECT_CALL(context_, ui_message_loop()) EXPECT_CALL(context_, ui_message_loop())
.Times(AnyNumber()); .Times(AnyNumber());
context_.SetUITaskPostFunction(base::Bind(
static_cast<void(MessageLoop::*)(
const tracked_objects::Location&,
const base::Closure&)>(&MessageLoop::PostTask),
base::Unretained(&message_loop_)));
Capturer* capturer = new CapturerFake(); Capturer* capturer = new CapturerFake();
event_executor_ = new MockEventExecutor(); event_executor_ = new MockEventExecutor();
curtain_ = new MockCurtain(); curtain_ = new MockCurtain();
......
...@@ -23,30 +23,21 @@ namespace remoting { ...@@ -23,30 +23,21 @@ namespace remoting {
// thread. This is neccessary so that DesktopEnvironment can be // thread. This is neccessary so that DesktopEnvironment can be
// deleted synchronously even while there are pending tasks on the // deleted synchronously even while there are pending tasks on the
// message queue. // message queue.
//
// TODO(sergeyu): Merge this code with remoting::TaskThreadProxy. The
// problem solved by this class is very simular to the one solved by
// ScopedRunnableMethodFactory. The main difference is that this class
// is thread-safe. Change the interface to make it look more like
// ScopedRunnableMethodFactory and rename it to avoid confusion with
// MessageLoopProxy.
class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> { class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> {
public: public:
UIThreadProxy(base::MessageLoopProxy* message_loop) UIThreadProxy(ChromotingHostContext* context)
: message_loop_(message_loop) { : context_(context) {
} }
// TODO(sergeyu): Rename this method.
void Detach() { void Detach() {
DCHECK(message_loop_->BelongsToCurrentThread()); DCHECK(context_->IsUIThread());
message_loop_ = NULL; context_ = NULL;
} }
void CallOnUIThread(const tracked_objects::Location& from_here, void CallOnUIThread(const tracked_objects::Location& from_here,
const base::Closure& closure) { const base::Closure& closure) {
scoped_refptr<base::MessageLoopProxy> message_loop = message_loop_; if (context_) {
if (message_loop) { context_->PostTaskToUIThread(from_here, base::Bind(
message_loop->PostTask(from_here, base::Bind(
&UIThreadProxy::CallClosure, this, closure)); &UIThreadProxy::CallClosure, this, closure));
} }
} }
...@@ -54,9 +45,8 @@ class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> { ...@@ -54,9 +45,8 @@ class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> {
void CallOnUIThreadDelayed(const tracked_objects::Location& from_here, void CallOnUIThreadDelayed(const tracked_objects::Location& from_here,
const base::Closure& closure, const base::Closure& closure,
int delay_ms) { int delay_ms) {
scoped_refptr<base::MessageLoopProxy> message_loop = message_loop_; if (context_) {
if (message_loop) { context_->PostDelayedTaskToUIThread(from_here, base::Bind(
message_loop->PostDelayedTask(from_here, base::Bind(
&UIThreadProxy::CallClosure, this, closure), delay_ms); &UIThreadProxy::CallClosure, this, closure), delay_ms);
} }
} }
...@@ -67,11 +57,11 @@ class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> { ...@@ -67,11 +57,11 @@ class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> {
virtual ~UIThreadProxy() { } virtual ~UIThreadProxy() { }
void CallClosure(const base::Closure& closure) { void CallClosure(const base::Closure& closure) {
if (message_loop_) if (context_)
closure.Run(); closure.Run();
} }
scoped_refptr<base::MessageLoopProxy> message_loop_; ChromotingHostContext* context_;
DISALLOW_COPY_AND_ASSIGN(UIThreadProxy); DISALLOW_COPY_AND_ASSIGN(UIThreadProxy);
}; };
...@@ -108,14 +98,14 @@ DesktopEnvironment::DesktopEnvironment(ChromotingHostContext* context, ...@@ -108,14 +98,14 @@ DesktopEnvironment::DesktopEnvironment(ChromotingHostContext* context,
local_input_monitor_(local_input_monitor), local_input_monitor_(local_input_monitor),
is_monitoring_local_inputs_(false), is_monitoring_local_inputs_(false),
continue_timer_started_(false), continue_timer_started_(false),
proxy_(new UIThreadProxy(context->ui_message_loop())) { proxy_(new UIThreadProxy(context)) {
} }
DesktopEnvironment::~DesktopEnvironment() { DesktopEnvironment::~DesktopEnvironment() {
} }
void DesktopEnvironment::Shutdown() { void DesktopEnvironment::Shutdown() {
DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); DCHECK(context_->IsUIThread());
MonitorLocalInputs(false); MonitorLocalInputs(false);
ShowDisconnectWindow(false, std::string()); ShowDisconnectWindow(false, std::string());
...@@ -141,7 +131,7 @@ void DesktopEnvironment::OnPause(bool pause) { ...@@ -141,7 +131,7 @@ void DesktopEnvironment::OnPause(bool pause) {
} }
void DesktopEnvironment::ProcessOnConnect(const std::string& username) { void DesktopEnvironment::ProcessOnConnect(const std::string& username) {
DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); DCHECK(context_->IsUIThread());
MonitorLocalInputs(true); MonitorLocalInputs(true);
ShowDisconnectWindow(true, username); ShowDisconnectWindow(true, username);
...@@ -149,7 +139,7 @@ void DesktopEnvironment::ProcessOnConnect(const std::string& username) { ...@@ -149,7 +139,7 @@ void DesktopEnvironment::ProcessOnConnect(const std::string& username) {
} }
void DesktopEnvironment::ProcessOnLastDisconnect() { void DesktopEnvironment::ProcessOnLastDisconnect() {
DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); DCHECK(context_->IsUIThread());
MonitorLocalInputs(false); MonitorLocalInputs(false);
ShowDisconnectWindow(false, std::string()); ShowDisconnectWindow(false, std::string());
...@@ -162,7 +152,7 @@ void DesktopEnvironment::ProcessOnPause(bool pause) { ...@@ -162,7 +152,7 @@ void DesktopEnvironment::ProcessOnPause(bool pause) {
} }
void DesktopEnvironment::MonitorLocalInputs(bool enable) { void DesktopEnvironment::MonitorLocalInputs(bool enable) {
DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); DCHECK(context_->IsUIThread());
if (enable == is_monitoring_local_inputs_) if (enable == is_monitoring_local_inputs_)
return; return;
...@@ -176,7 +166,7 @@ void DesktopEnvironment::MonitorLocalInputs(bool enable) { ...@@ -176,7 +166,7 @@ void DesktopEnvironment::MonitorLocalInputs(bool enable) {
void DesktopEnvironment::ShowDisconnectWindow(bool show, void DesktopEnvironment::ShowDisconnectWindow(bool show,
const std::string& username) { const std::string& username) {
DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); DCHECK(context_->IsUIThread());
if (show) { if (show) {
disconnect_window_->Show(host_, username); disconnect_window_->Show(host_, username);
...@@ -186,7 +176,7 @@ void DesktopEnvironment::ShowDisconnectWindow(bool show, ...@@ -186,7 +176,7 @@ void DesktopEnvironment::ShowDisconnectWindow(bool show,
} }
void DesktopEnvironment::ShowContinueWindow(bool show) { void DesktopEnvironment::ShowContinueWindow(bool show) {
DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); DCHECK(context_->IsUIThread());
if (show) { if (show) {
continue_window_->Show(host_); continue_window_->Show(host_);
...@@ -196,7 +186,7 @@ void DesktopEnvironment::ShowContinueWindow(bool show) { ...@@ -196,7 +186,7 @@ void DesktopEnvironment::ShowContinueWindow(bool show) {
} }
void DesktopEnvironment::StartContinueWindowTimer(bool start) { void DesktopEnvironment::StartContinueWindowTimer(bool start) {
DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); DCHECK(context_->IsUIThread());
if (start && !continue_timer_started_) { if (start && !continue_timer_started_) {
continue_timer_target_time_ = base::Time::Now() + continue_timer_target_time_ = base::Time::Now() +
...@@ -211,7 +201,7 @@ void DesktopEnvironment::StartContinueWindowTimer(bool start) { ...@@ -211,7 +201,7 @@ void DesktopEnvironment::StartContinueWindowTimer(bool start) {
} }
void DesktopEnvironment::ContinueWindowTimerFunc() { void DesktopEnvironment::ContinueWindowTimerFunc() {
DCHECK(context_->ui_message_loop()->BelongsToCurrentThread()); DCHECK(context_->IsUIThread());
// This function may be called prematurely if timer was stopped and // This function may be called prematurely if timer was stopped and
// then started again. In that case we just ignore this call. // then started again. In that case we just ignore this call.
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
#include "remoting/host/host_mock_objects.h" #include "remoting/host/host_mock_objects.h"
#include "base/message_loop_proxy.h"
namespace remoting { namespace remoting {
MockCapturer::MockCapturer() {} MockCapturer::MockCapturer() {}
...@@ -48,9 +46,7 @@ LocalInputMonitor* LocalInputMonitor::Create() { ...@@ -48,9 +46,7 @@ LocalInputMonitor* LocalInputMonitor::Create() {
return new MockLocalInputMonitor(); return new MockLocalInputMonitor();
} }
MockChromotingHostContext::MockChromotingHostContext() MockChromotingHostContext::MockChromotingHostContext() {}
: ChromotingHostContext(base::MessageLoopProxy::CreateForCurrentThread()) {
}
MockChromotingHostContext::~MockChromotingHostContext() {} MockChromotingHostContext::~MockChromotingHostContext() {}
......
...@@ -81,10 +81,10 @@ class MockChromotingHostContext : public ChromotingHostContext { ...@@ -81,10 +81,10 @@ class MockChromotingHostContext : public ChromotingHostContext {
MOCK_METHOD0(Start, void()); MOCK_METHOD0(Start, void());
MOCK_METHOD0(Stop, void()); MOCK_METHOD0(Stop, void());
MOCK_METHOD0(jingle_thread, JingleThread*()); MOCK_METHOD0(jingle_thread, JingleThread*());
MOCK_METHOD0(ui_message_loop, base::MessageLoopProxy*());
MOCK_METHOD0(main_message_loop, MessageLoop*()); MOCK_METHOD0(main_message_loop, MessageLoop*());
MOCK_METHOD0(encode_message_loop, MessageLoop*()); MOCK_METHOD0(encode_message_loop, MessageLoop*());
MOCK_METHOD0(network_message_loop, base::MessageLoopProxy*()); MOCK_METHOD0(network_message_loop, base::MessageLoopProxy*());
MOCK_METHOD0(ui_message_loop, MessageLoop*());
private: private:
DISALLOW_COPY_AND_ASSIGN(MockChromotingHostContext); DISALLOW_COPY_AND_ASSIGN(MockChromotingHostContext);
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/stringize_macros.h" #include "base/stringize_macros.h"
#include "remoting/base/plugin_message_loop_proxy.h"
#include "remoting/host/plugin/host_plugin_utils.h" #include "remoting/host/plugin/host_plugin_utils.h"
#include "remoting/host/plugin/host_script_object.h" #include "remoting/host/plugin/host_script_object.h"
#include "third_party/npapi/bindings/npapi.h" #include "third_party/npapi/bindings/npapi.h"
...@@ -59,7 +58,7 @@ base::AtExitManager* g_at_exit_manager = NULL; ...@@ -59,7 +58,7 @@ base::AtExitManager* g_at_exit_manager = NULL;
// NPAPI plugin implementation for remoting host. // NPAPI plugin implementation for remoting host.
// Documentation for most of the calls in this class can be found here: // Documentation for most of the calls in this class can be found here:
// https://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Scripting_plugins // https://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Scripting_plugins
class HostNPPlugin : public remoting::PluginMessageLoopProxy::Delegate { class HostNPPlugin {
public: public:
// |mode| is the display mode of plug-in. Values: // |mode| is the display mode of plug-in. Values:
// NP_EMBED: (1) Instance was created by an EMBED tag and shares the browser // NP_EMBED: (1) Instance was created by an EMBED tag and shares the browser
...@@ -67,10 +66,7 @@ class HostNPPlugin : public remoting::PluginMessageLoopProxy::Delegate { ...@@ -67,10 +66,7 @@ class HostNPPlugin : public remoting::PluginMessageLoopProxy::Delegate {
// NP_FULL: (2) Instance was created by a separate file and is the primary // NP_FULL: (2) Instance was created by a separate file and is the primary
// content in the window. // content in the window.
HostNPPlugin(NPP instance, uint16 mode) HostNPPlugin(NPP instance, uint16 mode)
: instance_(instance), : instance_(instance), scriptable_object_(NULL) {}
scriptable_object_(NULL),
np_thread_id_(base::PlatformThread::CurrentId()) {
}
~HostNPPlugin() { ~HostNPPlugin() {
if (scriptable_object_) { if (scriptable_object_) {
...@@ -150,49 +146,11 @@ class HostNPPlugin : public remoting::PluginMessageLoopProxy::Delegate { ...@@ -150,49 +146,11 @@ class HostNPPlugin : public remoting::PluginMessageLoopProxy::Delegate {
return scriptable_object_; return scriptable_object_;
} }
// PluginMessageLoopProxy::Delegate implementation.
virtual bool RunOnPluginThread(
int delay_ms, void(function)(void*), void* data) OVERRIDE {
if (delay_ms == 0) {
g_npnetscape_funcs->pluginthreadasynccall(instance_, function, data);
} else {
base::AutoLock auto_lock(timers_lock_);
uint32_t timer_id = g_npnetscape_funcs->scheduletimer(
instance_, delay_ms, false, &NPDelayedTaskSpringboard);
DelayedTask task = {function, data};
timers_[timer_id] = task;
}
return true;
}
virtual bool IsPluginThread() OVERRIDE {
return np_thread_id_ == base::PlatformThread::CurrentId();
}
static void NPDelayedTaskSpringboard(NPP npp, uint32_t timer_id) {
HostNPPlugin* self = reinterpret_cast<HostNPPlugin*>(npp->pdata);
DelayedTask task;
{
base::AutoLock auto_lock(self->timers_lock_);
std::map<uint32_t, DelayedTask>::iterator it =
self->timers_.find(timer_id);
CHECK(it != self->timers_.end());
task = it->second;
self->timers_.erase(it);
}
task.function(task.data);
}
private: private:
struct ScriptableNPObject : public NPObject { struct ScriptableNPObject : public NPObject {
HostNPScriptObject* scriptable_object; HostNPScriptObject* scriptable_object;
}; };
struct DelayedTask {
void (*function)(void*);
void* data;
};
static HostNPScriptObject* ScriptableFromObject(NPObject* obj) { static HostNPScriptObject* ScriptableFromObject(NPObject* obj) {
return reinterpret_cast<ScriptableNPObject*>(obj)->scriptable_object; return reinterpret_cast<ScriptableNPObject*>(obj)->scriptable_object;
} }
...@@ -202,11 +160,10 @@ class HostNPPlugin : public remoting::PluginMessageLoopProxy::Delegate { ...@@ -202,11 +160,10 @@ class HostNPPlugin : public remoting::PluginMessageLoopProxy::Delegate {
ScriptableNPObject* object = ScriptableNPObject* object =
reinterpret_cast<ScriptableNPObject*>( reinterpret_cast<ScriptableNPObject*>(
g_npnetscape_funcs->memalloc(sizeof(ScriptableNPObject))); g_npnetscape_funcs->memalloc(sizeof(ScriptableNPObject)));
HostNPPlugin* plugin = reinterpret_cast<HostNPPlugin*>(npp->pdata);
object->_class = aClass; object->_class = aClass;
object->referenceCount = 1; object->referenceCount = 1;
object->scriptable_object = new HostNPScriptObject(npp, object, plugin); object->scriptable_object = new HostNPScriptObject(npp, object);
if (!object->scriptable_object->Init()) { if (!object->scriptable_object->Init()) {
Deallocate(object); Deallocate(object);
object = NULL; object = NULL;
...@@ -333,10 +290,6 @@ class HostNPPlugin : public remoting::PluginMessageLoopProxy::Delegate { ...@@ -333,10 +290,6 @@ class HostNPPlugin : public remoting::PluginMessageLoopProxy::Delegate {
NPP instance_; NPP instance_;
NPObject* scriptable_object_; NPObject* scriptable_object_;
base::PlatformThreadId np_thread_id_;
std::map<uint32_t, DelayedTask> timers_;
base::Lock timers_lock_;
}; };
// Utility functions to map NPAPI Entry Points to C++ Objects. // Utility functions to map NPAPI Entry Points to C++ Objects.
......
...@@ -78,17 +78,11 @@ static bool g_logging_to_plugin = false; ...@@ -78,17 +78,11 @@ static bool g_logging_to_plugin = false;
static HostNPScriptObject* g_logging_scriptable_object = NULL; static HostNPScriptObject* g_logging_scriptable_object = NULL;
static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; static logging::LogMessageHandlerFunction g_logging_old_handler = NULL;
HostNPScriptObject::HostNPScriptObject( HostNPScriptObject::HostNPScriptObject(NPP plugin, NPObject* parent)
NPP plugin,
NPObject* parent,
PluginMessageLoopProxy::Delegate* plugin_thread_delegate)
: plugin_(plugin), : plugin_(plugin),
parent_(parent), parent_(parent),
state_(kDisconnected), state_(kDisconnected),
np_thread_id_(base::PlatformThread::CurrentId()), np_thread_id_(base::PlatformThread::CurrentId()),
plugin_message_loop_proxy_(
new PluginMessageLoopProxy(plugin_thread_delegate)),
host_context_(plugin_message_loop_proxy_),
failed_login_attempts_(0), failed_login_attempts_(0),
disconnected_event_(true, false), disconnected_event_(true, false),
nat_traversal_enabled_(false), nat_traversal_enabled_(false),
...@@ -105,6 +99,10 @@ HostNPScriptObject::HostNPScriptObject( ...@@ -105,6 +99,10 @@ HostNPScriptObject::HostNPScriptObject(
g_logging_old_handler = logging::GetLogMessageHandler(); g_logging_old_handler = logging::GetLogMessageHandler();
logging::SetLogMessageHandler(&LogToUI); logging::SetLogMessageHandler(&LogToUI);
g_logging_scriptable_object = this; g_logging_scriptable_object = this;
VLOG(2) << "HostNPScriptObject";
host_context_.SetUITaskPostFunction(base::Bind(
&HostNPScriptObject::PostTaskToNPThread, base::Unretained(this)));
} }
HostNPScriptObject::~HostNPScriptObject() { HostNPScriptObject::~HostNPScriptObject() {
...@@ -118,8 +116,6 @@ HostNPScriptObject::~HostNPScriptObject() { ...@@ -118,8 +116,6 @@ HostNPScriptObject::~HostNPScriptObject() {
g_logging_old_handler = NULL; g_logging_old_handler = NULL;
g_logging_scriptable_object = NULL; g_logging_scriptable_object = NULL;
plugin_message_loop_proxy_->Detach();
// Stop listening for policy updates. // Stop listening for policy updates.
if (nat_policy_.get()) { if (nat_policy_.get()) {
base::WaitableEvent nat_policy_stopped_(true, false); base::WaitableEvent nat_policy_stopped_(true, false);
...@@ -132,6 +128,7 @@ HostNPScriptObject::~HostNPScriptObject() { ...@@ -132,6 +128,7 @@ HostNPScriptObject::~HostNPScriptObject() {
// here because |host_context_| needs to be stopped on the plugin // here because |host_context_| needs to be stopped on the plugin
// thread, but the plugin thread may not exist after the instance // thread, but the plugin thread may not exist after the instance
// is destroyed. // is destroyed.
destructing_.Set();
disconnected_event_.Reset(); disconnected_event_.Reset();
DisconnectInternal(); DisconnectInternal();
disconnected_event_.Wait(); disconnected_event_.Wait();
...@@ -580,8 +577,11 @@ void HostNPScriptObject::OnReceivedSupportID( ...@@ -580,8 +577,11 @@ void HostNPScriptObject::OnReceivedSupportID(
} }
void HostNPScriptObject::OnStateChanged(State state) { void HostNPScriptObject::OnStateChanged(State state) {
if (!plugin_message_loop_proxy_->BelongsToCurrentThread()) { if (destructing_.IsSet())
plugin_message_loop_proxy_->PostTask( return;
if (!host_context_.IsUIThread()) {
host_context_.PostTaskToUIThread(
FROM_HERE, base::Bind(&HostNPScriptObject::OnStateChanged, FROM_HERE, base::Bind(&HostNPScriptObject::OnStateChanged,
base::Unretained(this), state)); base::Unretained(this), state));
return; return;
...@@ -615,8 +615,11 @@ bool HostNPScriptObject::LogToUI(int severity, const char* file, int line, ...@@ -615,8 +615,11 @@ bool HostNPScriptObject::LogToUI(int severity, const char* file, int line,
} }
void HostNPScriptObject::LogDebugInfo(const std::string& message) { void HostNPScriptObject::LogDebugInfo(const std::string& message) {
if (!plugin_message_loop_proxy_->BelongsToCurrentThread()) { if (destructing_.IsSet())
plugin_message_loop_proxy_->PostTask( return;
if (!host_context_.IsUIThread()) {
host_context_.PostTaskToUIThread(
FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo, FROM_HERE, base::Bind(&HostNPScriptObject::LogDebugInfo,
base::Unretained(this), message)); base::Unretained(this), message));
return; return;
...@@ -701,4 +704,25 @@ bool HostNPScriptObject::InvokeAndIgnoreResult(NPObject* func, ...@@ -701,4 +704,25 @@ bool HostNPScriptObject::InvokeAndIgnoreResult(NPObject* func,
return is_good; return is_good;
} }
void HostNPScriptObject::PostTaskToNPThread(
const tracked_objects::Location& from_here, const base::Closure& task) {
// The NPAPI functions cannot make use of |from_here|, but this method is
// passed as a callback to ChromotingHostContext, so it needs to have the
// appropriate signature.
// Copy task to the heap so that we can pass it to NPTaskSpringboard().
base::Closure* task_in_heap = new base::Closure(task);
// Can be called from any thread.
g_npnetscape_funcs->pluginthreadasynccall(plugin_, &NPTaskSpringboard,
task_in_heap);
}
// static
void HostNPScriptObject::NPTaskSpringboard(void* task) {
base::Closure* real_task = reinterpret_cast<base::Closure*>(task);
real_task->Run();
delete real_task;
}
} // namespace remoting } // namespace remoting
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "base/time.h" #include "base/time.h"
#include "remoting/base/plugin_message_loop_proxy.h"
#include "remoting/host/chromoting_host_context.h" #include "remoting/host/chromoting_host_context.h"
#include "remoting/host/host_status_observer.h" #include "remoting/host/host_status_observer.h"
#include "remoting/host/plugin/host_plugin_utils.h" #include "remoting/host/plugin/host_plugin_utils.h"
...@@ -46,8 +45,7 @@ class NatPolicy; ...@@ -46,8 +45,7 @@ class NatPolicy;
// destroyed it sychronously shuts down the host and all threads. // destroyed it sychronously shuts down the host and all threads.
class HostNPScriptObject : public HostStatusObserver { class HostNPScriptObject : public HostStatusObserver {
public: public:
HostNPScriptObject(NPP plugin, NPObject* parent, HostNPScriptObject(NPP plugin, NPObject* parent);
PluginMessageLoopProxy::Delegate* plugin_thread_delegate);
virtual ~HostNPScriptObject(); virtual ~HostNPScriptObject();
bool Init(); bool Init();
...@@ -144,6 +142,13 @@ class HostNPScriptObject : public HostStatusObserver { ...@@ -144,6 +142,13 @@ class HostNPScriptObject : public HostStatusObserver {
const NPVariant* args, const NPVariant* args,
uint32_t argCount); uint32_t argCount);
// Posts a task on the main NP thread.
void PostTaskToNPThread(
const tracked_objects::Location& from_here, const base::Closure& task);
// Utility function for PostTaskToNPThread.
static void NPTaskSpringboard(void* task);
// Set an exception for the current call. // Set an exception for the current call.
void SetException(const std::string& exception_string); void SetException(const std::string& exception_string);
...@@ -157,7 +162,6 @@ class HostNPScriptObject : public HostStatusObserver { ...@@ -157,7 +162,6 @@ class HostNPScriptObject : public HostStatusObserver {
ScopedRefNPObject log_debug_info_func_; ScopedRefNPObject log_debug_info_func_;
ScopedRefNPObject on_state_changed_func_; ScopedRefNPObject on_state_changed_func_;
base::PlatformThreadId np_thread_id_; base::PlatformThreadId np_thread_id_;
scoped_refptr<PluginMessageLoopProxy> plugin_message_loop_proxy_;
scoped_ptr<RegisterSupportHostRequest> register_request_; scoped_ptr<RegisterSupportHostRequest> register_request_;
scoped_refptr<MutableHostConfig> host_config_; scoped_refptr<MutableHostConfig> host_config_;
...@@ -168,6 +172,7 @@ class HostNPScriptObject : public HostStatusObserver { ...@@ -168,6 +172,7 @@ class HostNPScriptObject : public HostStatusObserver {
int failed_login_attempts_; int failed_login_attempts_;
base::WaitableEvent disconnected_event_; base::WaitableEvent disconnected_event_;
base::CancellationFlag destructing_;
scoped_ptr<policy_hack::NatPolicy> nat_policy_; scoped_ptr<policy_hack::NatPolicy> nat_policy_;
......
...@@ -104,8 +104,13 @@ class SimpleHost { ...@@ -104,8 +104,13 @@ class SimpleHost {
// It needs to be a UI message loop to keep runloops spinning on the Mac. // It needs to be a UI message loop to keep runloops spinning on the Mac.
MessageLoop message_loop(MessageLoop::TYPE_UI); MessageLoop message_loop(MessageLoop::TYPE_UI);
remoting::ChromotingHostContext context( remoting::ChromotingHostContext context;
base::MessageLoopProxy::CreateForCurrentThread()); // static_cast needed to resolve overloaded PostTask member-function.
context.SetUITaskPostFunction(base::Bind(
static_cast<void(MessageLoop::*)(
const tracked_objects::Location&,
const base::Closure&)>(&MessageLoop::PostTask),
base::Unretained(&message_loop)));
context.Start(); context.Start();
base::Thread file_io_thread("FileIO"); base::Thread file_io_thread("FileIO");
......
...@@ -337,8 +337,6 @@ ...@@ -337,8 +337,6 @@
'base/encoder_vp8.h', 'base/encoder_vp8.h',
'base/encoder_row_based.cc', 'base/encoder_row_based.cc',
'base/encoder_row_based.h', 'base/encoder_row_based.h',
'base/plugin_message_loop_proxy.cc',
'base/plugin_message_loop_proxy.h',
'base/rate_counter.cc', 'base/rate_counter.cc',
'base/rate_counter.h', 'base/rate_counter.h',
'base/running_average.cc', 'base/running_average.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment