summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--remoting/base/scoped_thread_proxy.cc84
-rw-r--r--remoting/base/scoped_thread_proxy.h73
-rw-r--r--remoting/base/task_thread_proxy.cc34
-rw-r--r--remoting/base/task_thread_proxy.h50
-rw-r--r--remoting/client/plugin/chromoting_instance.cc31
-rw-r--r--remoting/client/plugin/chromoting_instance.h9
-rw-r--r--remoting/host/desktop_environment.cc71
-rw-r--r--remoting/host/desktop_environment.h4
-rw-r--r--remoting/remoting.gyp4
9 files changed, 189 insertions, 171 deletions
diff --git a/remoting/base/scoped_thread_proxy.cc b/remoting/base/scoped_thread_proxy.cc
new file mode 100644
index 0000000..b526d6af
--- /dev/null
+++ b/remoting/base/scoped_thread_proxy.cc
@@ -0,0 +1,84 @@
+// 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/scoped_thread_proxy.h"
+
+namespace remoting {
+
+class ScopedThreadProxy::Core : public base::RefCountedThreadSafe<Core> {
+ public:
+ Core(base::MessageLoopProxy* message_loop)
+ : message_loop_(message_loop),
+ canceled_(false) {
+ }
+
+ void PostTask(const tracked_objects::Location& from_here,
+ const base::Closure& closure) {
+ if (!canceled_)
+ message_loop_->PostTask(from_here, Wrap(closure));
+ }
+
+ void PostDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& closure,
+ int64 delay_ms) {
+ if (!canceled_) {
+ message_loop_->PostDelayedTask(from_here, Wrap(closure), delay_ms);
+ }
+ }
+
+ void Detach() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ canceled_ = true;
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<Core>;
+
+ ~Core() {
+ DCHECK(canceled_);
+ }
+
+ base::Closure Wrap(const base::Closure& closure) {
+ return base::Bind(&Core::CallClosure, this, closure);
+ }
+
+ void CallClosure(const base::Closure& closure) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+
+ if (!canceled_)
+ closure.Run();
+ }
+
+ scoped_refptr<base::MessageLoopProxy> message_loop_;
+ bool canceled_;
+
+ DISALLOW_COPY_AND_ASSIGN(Core);
+};
+
+ScopedThreadProxy::ScopedThreadProxy(base::MessageLoopProxy* message_loop)
+ : core_(new Core(message_loop)) {
+}
+
+ScopedThreadProxy::~ScopedThreadProxy() {
+ Detach();
+}
+
+void ScopedThreadProxy::PostTask(const tracked_objects::Location& from_here,
+ const base::Closure& closure) {
+ core_->PostTask(from_here, closure);
+}
+
+void ScopedThreadProxy::PostDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& closure,
+ int64 delay_ms) {
+ core_->PostDelayedTask(from_here, closure, delay_ms);
+}
+
+void ScopedThreadProxy::Detach() {
+ core_->Detach();
+}
+
+} // namespace remoting
diff --git a/remoting/base/scoped_thread_proxy.h b/remoting/base/scoped_thread_proxy.h
new file mode 100644
index 0000000..63dcaf8
--- /dev/null
+++ b/remoting/base/scoped_thread_proxy.h
@@ -0,0 +1,73 @@
+// 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_SCOPED_THREAD_PROXY_H_
+#define REMOTING_BASE_SCOPED_THREAD_PROXY_H_
+
+#include "base/bind.h"
+#include "base/message_loop_proxy.h"
+
+namespace remoting {
+
+// ScopedThreadProxy is proxy for message loops that cancels all
+// pending tasks when it is destroyed. It can be used to post tasks
+// for a non-refcounted object. Must be deleted on the thread it
+// belongs to.
+//
+// The main difference from WeakPtr<> and ScopedRunnableMethodFactory<>
+// is that this class can be used safely to post tasks from different
+// threads.
+// It is similar to WeakHandle<> used in sync: the main difference is
+// that WeakHandle<> creates closures itself, while ScopedThreadProxy
+// accepts base::Closure instances which caller needs to create using
+// base::Bind().
+//
+// TODO(sergeyu): Potentially we could use WeakHandle<> instead of
+// this class. Consider migrating to WeakHandle<> when it is moved to
+// src/base and support for delayed tasks is implemented.
+//
+// Usage:
+// class MyClass {
+// public:
+// MyClass()
+// : thread_proxy_(base::MessageLoopProxy::current()) {}
+//
+// // Always called on the thread on which this object was created.
+// void NonThreadSafeMethod() {}
+//
+// // Can be called on any thread.
+// void ThreadSafeMethod() {
+// thread_proxy_.PostTask(FROM_HERE, base::Bind(
+// &MyClass::NonThreadSafeMethod, base::Unretained(this)));
+// }
+//
+// private:
+// ScopedThreadProxy thread_proxy_;
+// };
+class ScopedThreadProxy {
+ public:
+ ScopedThreadProxy(base::MessageLoopProxy* message_loop);
+ ~ScopedThreadProxy();
+
+ void PostTask(const tracked_objects::Location& from_here,
+ const base::Closure& closure);
+ void PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& closure,
+ int64 delay_ms);
+
+ // Cancels all tasks posted via this proxy. Must be called on the
+ // thread this object belongs to.
+ void Detach();
+
+ private:
+ class Core;
+
+ scoped_refptr<Core> core_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedThreadProxy);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_BASE_SCOPED_THREAD_PROXY_H_
diff --git a/remoting/base/task_thread_proxy.cc b/remoting/base/task_thread_proxy.cc
deleted file mode 100644
index d379620..0000000
--- a/remoting/base/task_thread_proxy.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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/task_thread_proxy.h"
-
-#include "base/bind.h"
-
-namespace remoting {
-
-TaskThreadProxy::TaskThreadProxy(MessageLoop* loop)
- : message_loop_(loop) {
-}
-
-TaskThreadProxy::~TaskThreadProxy() {
-}
-
-void TaskThreadProxy::Detach() {
- message_loop_ = NULL;
-}
-
-void TaskThreadProxy::Call(const base::Closure& closure) {
- if (message_loop_) {
- message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
- this, &TaskThreadProxy::CallClosure, closure));
- }
-}
-
-void TaskThreadProxy::CallClosure(const base::Closure& closure) {
- if (message_loop_)
- closure.Run();
-}
-
-} // namespace remoting
diff --git a/remoting/base/task_thread_proxy.h b/remoting/base/task_thread_proxy.h
deleted file mode 100644
index 67ccc2d..0000000
--- a/remoting/base/task_thread_proxy.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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_TASK_THREAD_PROXY_H_
-#define REMOTING_BASE_TASK_THREAD_PROXY_H_
-
-#include "base/message_loop.h"
-
-namespace remoting {
-
-// This is a refcounted class that is used to switch to the appropriate thread
-// before running a task on a target object. It should be used whenever you
-// need to post to an object, but:
-// (1) You don't know when the object might be deleted, and
-// (2) You cannot subclass the target from RefCountedThreadSafe.
-//
-// Example usage:
-// Instead of:
-// MyClass* obj;
-// obj->Method(param);
-// Use:
-// proxy->Call(base::Bind(&MyClass::Method,
-// base::Unretained(obj),
-// param);
-class TaskThreadProxy : public base::RefCountedThreadSafe<TaskThreadProxy> {
- public:
- TaskThreadProxy(MessageLoop* loop);
-
- // Detach should be called when the target of the posted task is being
- // destroyed.
- void Detach();
-
- void Call(const base::Closure& closure);
-
- private:
- friend class base::RefCountedThreadSafe<TaskThreadProxy>;
-
- virtual ~TaskThreadProxy();
-
- void CallClosure(const base::Closure& closure);
-
- MessageLoop* message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskThreadProxy);
-};
-
-} // namespace remoting
-
-#endif // REMOTING_BASE_TASK_THREAD_PROXY_H_
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc
index 6281a24..d4176ed 100644
--- a/remoting/client/plugin/chromoting_instance.cc
+++ b/remoting/client/plugin/chromoting_instance.cc
@@ -24,7 +24,6 @@
#include "ppapi/cpp/rect.h"
// TODO(wez): Remove this when crbug.com/86353 is complete.
#include "ppapi/cpp/private/var_private.h"
-#include "remoting/base/task_thread_proxy.h"
#include "remoting/base/util.h"
#include "remoting/client/client_config.h"
#include "remoting/client/chromoting_client.h"
@@ -71,12 +70,10 @@ ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
scale_to_fit_(false),
enable_client_nat_traversal_(false),
initial_policy_received_(false),
- task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ thread_proxy_(new ScopedThreadProxy(plugin_message_loop_)) {
RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL);
RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
- log_proxy_ = new TaskThreadProxy(MessageLoop::current());
-
// Resister this instance to handle debug log messsages.
RegisterLoggingInstance();
}
@@ -86,7 +83,7 @@ ChromotingInstance::~ChromotingInstance() {
// Detach the log proxy so we don't log anything else to the UI.
// This needs to be done before the instance is unregistered for logging.
- log_proxy_->Detach();
+ thread_proxy_->Detach();
// Unregister this instance so that debug log messages will no longer be sent
// to it. This will stop all logging in all Chromoting instances.
@@ -107,6 +104,10 @@ ChromotingInstance::~ChromotingInstance() {
view_proxy_->Detach();
}
+ // Delete |thread_proxy_| before we detach |plugin_message_loop_|,
+ // otherwise ScopedThreadProxy may DCHECK when destroying.
+ thread_proxy_.reset();
+
plugin_message_loop_->Detach();
}
@@ -150,8 +151,10 @@ void ChromotingInstance::Connect(const ClientConfig& config) {
// enterprise policy is pushed at least once, we we delay the connect call.
if (!initial_policy_received_) {
VLOG(1) << "Delaying connect until initial policy is read.";
- delayed_connect_.reset(
- task_factory_.NewRunnableMethod(&ChromotingInstance::Connect, config));
+ // base::Unretained() is safe here because |delayed_connect_| is
+ // used only with |thread_proxy_|.
+ delayed_connect_ = base::Bind(&ChromotingInstance::Connect,
+ base::Unretained(this), config);
return;
}
@@ -395,11 +398,11 @@ bool ChromotingInstance::LogToUI(int severity, const char* file, int line,
if (g_logging_instance) {
std::string message = remoting::GetTimestampString();
message += (str.c_str() + message_start);
- // |log_proxy_| is safe to use here because we detach the proxy before
+ // |thread_proxy_| is safe to use here because we detach it before
// tearing down the |g_logging_instance|.
- g_logging_instance->log_proxy_->Call(
- base::Bind(&ChromotingInstance::ProcessLogToUI,
- base::Unretained(g_logging_instance), message));
+ g_logging_instance->thread_proxy_->PostTask(
+ FROM_HERE, base::Bind(&ChromotingInstance::ProcessLogToUI,
+ base::Unretained(g_logging_instance), message));
}
}
@@ -514,8 +517,10 @@ void ChromotingInstance::HandlePolicyUpdate(const std::string policy_json) {
initial_policy_received_ = true;
enable_client_nat_traversal_ = traversal_policy;
- if (delayed_connect_.get())
- plugin_message_loop_->PostTask(FROM_HERE, delayed_connect_.release());
+ if (!delayed_connect_.is_null()) {
+ thread_proxy_->PostTask(FROM_HERE, delayed_connect_);
+ delayed_connect_.Reset();
+ }
}
} // namespace remoting
diff --git a/remoting/client/plugin/chromoting_instance.h b/remoting/client/plugin/chromoting_instance.h
index 856f040..d17f371 100644
--- a/remoting/client/plugin/chromoting_instance.h
+++ b/remoting/client/plugin/chromoting_instance.h
@@ -19,6 +19,7 @@
#include "ppapi/c/pp_var.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/private/instance_private.h"
+#include "remoting/base/scoped_thread_proxy.h"
#include "remoting/client/client_context.h"
#include "remoting/client/plugin/chromoting_scriptable_object.h"
#include "remoting/client/plugin/pepper_plugin_thread_delegate.h"
@@ -47,7 +48,6 @@ class JingleThread;
class PepperView;
class PepperViewProxy;
class RectangleUpdateDecoder;
-class TaskThreadProxy;
struct ClientConfig;
@@ -139,9 +139,6 @@ class ChromotingInstance : public pp::InstancePrivate {
// True if scale to fit is enabled.
bool scale_to_fit_;
- // A refcounted class to perform thread-switching for logging tasks.
- scoped_refptr<TaskThreadProxy> log_proxy_;
-
// PepperViewProxy is refcounted and used to interface between chromoting
// objects and PepperView and perform thread switching. It wraps around
// |view_| and receives method calls on chromoting threads. These method
@@ -173,8 +170,8 @@ class ChromotingInstance : public pp::InstancePrivate {
// settings.
bool initial_policy_received_;
- ScopedRunnableMethodFactory<ChromotingInstance> task_factory_;
- scoped_ptr<Task> delayed_connect_;
+ scoped_ptr<ScopedThreadProxy> thread_proxy_;
+ base::Closure delayed_connect_;
DISALLOW_COPY_AND_ASSIGN(ChromotingInstance);
};
diff --git a/remoting/host/desktop_environment.cc b/remoting/host/desktop_environment.cc
index ada7c2a..3f1bf89 100644
--- a/remoting/host/desktop_environment.cc
+++ b/remoting/host/desktop_environment.cc
@@ -24,63 +24,6 @@ static const int kContinueWindowHideTimeoutMs = 60 * 1000;
namespace remoting {
-// UIThreadProxy proxies DesktopEnvironment method calls to the UI
-// thread. This is neccessary so that DesktopEnvironment can be
-// deleted synchronously even while there are pending tasks on the
-// 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> {
- public:
- explicit UIThreadProxy(base::MessageLoopProxy* message_loop)
- : message_loop_(message_loop) {
- }
-
- // TODO(sergeyu): Rename this method.
- void Detach() {
- DCHECK(message_loop_->BelongsToCurrentThread());
- message_loop_ = NULL;
- }
-
- void CallOnUIThread(const tracked_objects::Location& from_here,
- const base::Closure& closure) {
- scoped_refptr<base::MessageLoopProxy> message_loop = message_loop_;
- if (message_loop) {
- message_loop->PostTask(from_here, base::Bind(
- &UIThreadProxy::CallClosure, this, closure));
- }
- }
-
- void CallOnUIThreadDelayed(const tracked_objects::Location& from_here,
- const base::Closure& closure,
- int delay_ms) {
- scoped_refptr<base::MessageLoopProxy> message_loop = message_loop_;
- if (message_loop) {
- message_loop->PostDelayedTask(from_here, base::Bind(
- &UIThreadProxy::CallClosure, this, closure), delay_ms);
- }
- }
-
- private:
- friend class base::RefCountedThreadSafe<UIThreadProxy>;
-
- virtual ~UIThreadProxy() { }
-
- void CallClosure(const base::Closure& closure) {
- if (message_loop_)
- closure.Run();
- }
-
- scoped_refptr<base::MessageLoopProxy> message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(UIThreadProxy);
-};
-
// static
DesktopEnvironment* DesktopEnvironment::Create(ChromotingHostContext* context) {
scoped_ptr<Capturer> capturer(Capturer::Create());
@@ -125,7 +68,7 @@ DesktopEnvironment::DesktopEnvironment(ChromotingHostContext* context,
local_input_monitor_(local_input_monitor),
is_monitoring_local_inputs_(false),
continue_timer_state_(INACTIVE),
- proxy_(new UIThreadProxy(context->ui_message_loop())) {
+ ui_thread_proxy_(context->ui_message_loop()) {
}
DesktopEnvironment::~DesktopEnvironment() {
@@ -139,21 +82,21 @@ void DesktopEnvironment::Shutdown() {
ShowContinueWindow(false);
StartContinueWindowTimer(false);
- proxy_->Detach();
+ ui_thread_proxy_.Detach();
}
void DesktopEnvironment::OnConnect(const std::string& username) {
- proxy_->CallOnUIThread(FROM_HERE, base::Bind(
+ ui_thread_proxy_.PostTask(FROM_HERE, base::Bind(
&DesktopEnvironment::ProcessOnConnect, base::Unretained(this), username));
}
void DesktopEnvironment::OnLastDisconnect() {
- proxy_->CallOnUIThread(FROM_HERE, base::Bind(
+ ui_thread_proxy_.PostTask(FROM_HERE, base::Bind(
&DesktopEnvironment::ProcessOnLastDisconnect, base::Unretained(this)));
}
void DesktopEnvironment::OnPause(bool pause) {
- proxy_->CallOnUIThread(FROM_HERE, base::Bind(
+ ui_thread_proxy_.PostTask(FROM_HERE, base::Bind(
&DesktopEnvironment::ProcessOnPause, base::Unretained(this), pause));
}
@@ -221,7 +164,7 @@ void DesktopEnvironment::StartContinueWindowTimer(bool start) {
if (start && continue_timer_state_ == INACTIVE) {
continue_timer_target_time_ = base::Time::Now() +
base::TimeDelta::FromMilliseconds(kContinueWindowShowTimeoutMs);
- proxy_->CallOnUIThreadDelayed(
+ ui_thread_proxy_.PostDelayedTask(
FROM_HERE, base::Bind(&DesktopEnvironment::ContinueWindowTimerFunc,
base::Unretained(this)),
kContinueWindowShowTimeoutMs);
@@ -249,7 +192,7 @@ void DesktopEnvironment::ContinueWindowTimerFunc() {
ShowContinueWindow(true);
continue_timer_target_time_ = base::Time::Now() +
base::TimeDelta::FromMilliseconds(kContinueWindowHideTimeoutMs);
- proxy_->CallOnUIThreadDelayed(
+ ui_thread_proxy_.PostDelayedTask(
FROM_HERE, base::Bind(&DesktopEnvironment::ContinueWindowTimerFunc,
base::Unretained(this)),
kContinueWindowHideTimeoutMs);
diff --git a/remoting/host/desktop_environment.h b/remoting/host/desktop_environment.h
index 0fc00c9..e0ed196 100644
--- a/remoting/host/desktop_environment.h
+++ b/remoting/host/desktop_environment.h
@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time.h"
+#include "remoting/base/scoped_thread_proxy.h"
namespace remoting {
@@ -22,7 +23,6 @@ class Curtain;
class DisconnectWindow;
class EventExecutor;
class LocalInputMonitor;
-class UIThreadProxy;
class DesktopEnvironment {
public:
@@ -114,7 +114,7 @@ class DesktopEnvironment {
ContinueTimerState continue_timer_state_;
base::Time continue_timer_target_time_;
- scoped_refptr<UIThreadProxy> proxy_;
+ ScopedThreadProxy ui_thread_proxy_;
DISALLOW_COPY_AND_ASSIGN(DesktopEnvironment);
};
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 6f1fa50..d79b8bb 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -396,8 +396,8 @@
'base/rate_counter.h',
'base/running_average.cc',
'base/running_average.h',
- 'base/task_thread_proxy.cc',
- 'base/task_thread_proxy.h',
+ 'base/scoped_thread_proxy.cc',
+ 'base/scoped_thread_proxy.h',
'base/util.cc',
'base/util.h',
],