Skip to content

Commit

Permalink
Add PluginMessageLoopProxy and use it for Host plugin UI thread.
Browse files Browse the repository at this point in the history
The new class will also be used in the client plugin for the main plugin thread.

BUG=None
TEST=Everything works.

Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=96981

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97050 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
sergeyu@chromium.org committed Aug 16, 2011
1 parent e04e824 commit 12835bf
Show file tree
Hide file tree
Showing 14 changed files with 316 additions and 133 deletions.
114 changes: 114 additions & 0 deletions remoting/base/plugin_message_loop_proxy.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// 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
79 changes: 79 additions & 0 deletions remoting/base/plugin_message_loop_proxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// 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_
37 changes: 8 additions & 29 deletions remoting/host/chromoting_host_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@

namespace remoting {

ChromotingHostContext::ChromotingHostContext()
ChromotingHostContext::ChromotingHostContext(
base::MessageLoopProxy* ui_message_loop)
: main_thread_("ChromotingMainThread"),
encode_thread_("ChromotingEncodeThread"),
desktop_thread_("ChromotingDesktopThread") {
desktop_thread_("ChromotingDesktopThread"),
ui_message_loop_(ui_message_loop) {
}

ChromotingHostContext::~ChromotingHostContext() {
Expand All @@ -41,6 +43,10 @@ JingleThread* ChromotingHostContext::jingle_thread() {
return &jingle_thread_;
}

base::MessageLoopProxy* ChromotingHostContext::ui_message_loop() {
return ui_message_loop_;
}

MessageLoop* ChromotingHostContext::main_message_loop() {
return main_thread_.message_loop();
}
Expand All @@ -57,31 +63,4 @@ MessageLoop* ChromotingHostContext::desktop_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
22 changes: 3 additions & 19 deletions remoting/host/chromoting_host_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,8 @@ namespace remoting {
// process. This class is virtual only for testing purposes (see below).
class ChromotingHostContext {
public:
typedef base::Callback<void(
const tracked_objects::Location& from_here,
const base::Closure& task)> UIThreadPostTaskFunction;

// Create a context.
ChromotingHostContext();
ChromotingHostContext(base::MessageLoopProxy* ui_message_loop);
virtual ~ChromotingHostContext();

// TODO(ajwong): Move the Start/Stop methods out of this class. Then
Expand All @@ -42,21 +38,12 @@ class ChromotingHostContext {

virtual JingleThread* jingle_thread();

virtual base::MessageLoopProxy* ui_message_loop();
virtual MessageLoop* main_message_loop();
virtual MessageLoop* encode_message_loop();
virtual base::MessageLoopProxy* network_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:
FRIEND_TEST_ALL_PREFIXES(ChromotingHostContextTest, StartAndStop);

Expand All @@ -73,10 +60,7 @@ class ChromotingHostContext {
// This is NOT a Chrome-style UI thread.
base::Thread desktop_thread_;

UIThreadPostTaskFunction ui_poster_;
// This IS the main Chrome GUI thread that |ui_poster_| will post to.
base::PlatformThreadId ui_main_thread_id_;

scoped_refptr<base::MessageLoopProxy> ui_message_loop_;

DISALLOW_COPY_AND_ASSIGN(ChromotingHostContext);
};
Expand Down
6 changes: 5 additions & 1 deletion remoting/host/chromoting_host_context_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "remoting/host/chromoting_host_context.h"
#include "testing/gtest/include/gtest/gtest.h"

Expand All @@ -11,7 +12,10 @@ namespace remoting {
// A simple test that starts and stop the context. This tests the context
// operates properly and all threads and message loops are valid.
TEST(ChromotingHostContextTest, StartAndStop) {
ChromotingHostContext context;
MessageLoop message_loop;
ChromotingHostContext context(
base::MessageLoopProxy::current());

context.Start();
EXPECT_TRUE(context.jingle_thread());
EXPECT_TRUE(context.main_message_loop());
Expand Down
8 changes: 1 addition & 7 deletions remoting/host/chromoting_host_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class ChromotingHostTest : public testing::Test {
ON_CALL(context_, network_message_loop())
.WillByDefault(Return(message_loop_proxy_.get()));
ON_CALL(context_, ui_message_loop())
.WillByDefault(Return(&message_loop_));
.WillByDefault(Return(message_loop_proxy_.get()));
EXPECT_CALL(context_, main_message_loop())
.Times(AnyNumber());
EXPECT_CALL(context_, encode_message_loop())
Expand All @@ -88,12 +88,6 @@ class ChromotingHostTest : public testing::Test {
EXPECT_CALL(context_, ui_message_loop())
.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();
event_executor_ = new MockEventExecutor();
curtain_ = new MockCurtain();
Expand Down
Loading

0 comments on commit 12835bf

Please sign in to comment.