summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorwez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-30 21:09:33 +0000
committerwez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-30 21:09:33 +0000
commitb6791a77ae5c2eec843b8c9b4ad3d9fa9c11fda7 (patch)
tree608a649c16b2af968a0d250ba1c30b118e6bb3ba /remoting
parent910875d9a35955b0e51d150c40879eb892250155 (diff)
downloadchromium_src-b6791a77ae5c2eec843b8c9b4ad3d9fa9c11fda7.zip
chromium_src-b6791a77ae5c2eec843b8c9b4ad3d9fa9c11fda7.tar.gz
chromium_src-b6791a77ae5c2eec843b8c9b4ad3d9fa9c11fda7.tar.bz2
Revert 139623 - Replace ScopedThreadProxy with MessageLoopProxy & WeakPtrs.
This affects the following classes: * ChromotingClient * ChromotingInstance * HostUserInterface * It2MeHostUserInterface The MessageLoopProxy/WeakPtr combination requires that the WeakPtr is created on the thread referred to by the proxy; code in which that is hard to arrange usually has subtle race-conditions. TEST=Existing unit-tests, and manual testing. Review URL: https://chromiumcodereview.appspot.com/10454040 TBR=wez@chromium.org Review URL: https://chromiumcodereview.appspot.com/10446088 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139633 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/base/scoped_thread_proxy.cc86
-rw-r--r--remoting/base/scoped_thread_proxy.h73
-rw-r--r--remoting/client/chromoting_client.cc15
-rw-r--r--remoting/client/chromoting_client.h6
-rw-r--r--remoting/client/plugin/chromoting_instance.cc57
-rw-r--r--remoting/client/plugin/chromoting_instance.h3
-rw-r--r--remoting/host/desktop_environment.h1
-rw-r--r--remoting/host/host_user_interface.cc30
-rw-r--r--remoting/host/host_user_interface.h8
-rw-r--r--remoting/host/it2me_host_user_interface.cc41
-rw-r--r--remoting/host/it2me_host_user_interface.h6
-rw-r--r--remoting/remoting.gyp2
12 files changed, 244 insertions, 84 deletions
diff --git a/remoting/base/scoped_thread_proxy.cc b/remoting/base/scoped_thread_proxy.cc
new file mode 100644
index 0000000..d1dcc26
--- /dev/null
+++ b/remoting/base/scoped_thread_proxy.cc
@@ -0,0 +1,86 @@
+// 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"
+
+#include "base/bind.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..9e43a15
--- /dev/null
+++ b/remoting/base/scoped_thread_proxy.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 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/callback_forward.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<> 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/client/chromoting_client.cc b/remoting/client/chromoting_client.cc
index 2a3aa56..4dabdd2 100644
--- a/remoting/client/chromoting_client.cc
+++ b/remoting/client/chromoting_client.cc
@@ -41,7 +41,7 @@ ChromotingClient::ChromotingClient(const ClientConfig& config,
client_done_(client_done),
packet_being_processed_(false),
last_sequence_number_(0),
- weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ thread_proxy_(context_->network_message_loop()) {
}
ChromotingClient::~ChromotingClient() {
@@ -52,9 +52,6 @@ void ChromotingClient::Start(
scoped_ptr<protocol::TransportFactory> transport_factory) {
DCHECK(message_loop()->BelongsToCurrentThread());
- // Create a WeakPtr to ourself for to use for all posted tasks.
- weak_ptr_ = weak_factory_.GetWeakPtr();
-
scoped_ptr<protocol::Authenticator> authenticator;
if (config_.use_v1_authenticator) {
authenticator.reset(new protocol::V1ClientAuthenticator(
@@ -78,7 +75,7 @@ void ChromotingClient::Stop(const base::Closure& shutdown_task) {
if (!message_loop()->BelongsToCurrentThread()) {
message_loop()->PostTask(
FROM_HERE, base::Bind(&ChromotingClient::Stop,
- weak_ptr_, shutdown_task));
+ base::Unretained(this), shutdown_task));
return;
}
@@ -90,7 +87,7 @@ void ChromotingClient::Stop(const base::Closure& shutdown_task) {
}
connection_->Disconnect(base::Bind(&ChromotingClient::OnDisconnected,
- weak_ptr_, shutdown_task));
+ base::Unretained(this), shutdown_task));
}
void ChromotingClient::OnDisconnected(const base::Closure& shutdown_task) {
@@ -195,7 +192,7 @@ base::MessageLoopProxy* ChromotingClient::message_loop() {
void ChromotingClient::OnPacketDone(bool last_packet,
base::Time decode_start) {
if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(FROM_HERE, base::Bind(
+ thread_proxy_.PostTask(FROM_HERE, base::Bind(
&ChromotingClient::OnPacketDone, base::Unretained(this),
last_packet, decode_start));
return;
@@ -219,8 +216,8 @@ void ChromotingClient::OnPacketDone(bool last_packet,
void ChromotingClient::Initialize() {
if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(FROM_HERE, base::Bind(
- &ChromotingClient::Initialize, weak_ptr_));
+ thread_proxy_.PostTask(FROM_HERE, base::Bind(
+ &ChromotingClient::Initialize, base::Unretained(this)));
return;
}
diff --git a/remoting/client/chromoting_client.h b/remoting/client/chromoting_client.h
index 7b90be3..d784b5a 100644
--- a/remoting/client/chromoting_client.h
+++ b/remoting/client/chromoting_client.h
@@ -10,8 +10,8 @@
#include <list>
#include "base/callback.h"
-#include "base/memory/weak_ptr.h"
#include "base/time.h"
+#include "remoting/base/scoped_thread_proxy.h"
#include "remoting/client/client_config.h"
#include "remoting/client/chromoting_stats.h"
#include "remoting/client/chromoting_view.h"
@@ -120,9 +120,7 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
// Keep track of the last sequence number bounced back from the host.
int64 last_sequence_number_;
- // WeakPtr used to avoid tasks accessing the client after it is deleted.
- base::WeakPtrFactory<ChromotingClient> weak_factory_;
- base::WeakPtr<ChromotingClient> weak_ptr_;
+ ScopedThreadProxy thread_proxy_;
DISALLOW_COPY_AND_ASSIGN(ChromotingClient);
};
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc
index 28556b4..fec261e 100644
--- a/remoting/client/plugin/chromoting_instance.cc
+++ b/remoting/client/plugin/chromoting_instance.cc
@@ -97,10 +97,7 @@ std::string ConnectionErrorToString(ChromotingInstance::ConnectionError error) {
// while sending the log message to the UI.
static bool g_logging_to_plugin = false;
static bool g_has_logging_instance = false;
-CR_DEFINE_STATIC_LOCAL(
- scoped_refptr<base::SingleThreadTaskRunner>, g_logging_task_runner, ());
-CR_DEFINE_STATIC_LOCAL(
- base::WeakPtr<ChromotingInstance>, g_logging_instance, ());
+static ChromotingInstance* g_logging_instance = NULL;
static logging::LogMessageHandlerFunction g_logging_old_handler = NULL;
static base::LazyInstance<base::Lock>::Leaky
@@ -142,7 +139,7 @@ ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
plugin_message_loop_(
new PluginMessageLoopProxy(&plugin_thread_delegate_)),
context_(plugin_message_loop_),
- weak_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);
@@ -160,6 +157,10 @@ ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
ChromotingInstance::~ChromotingInstance() {
DCHECK(plugin_message_loop_->BelongsToCurrentThread());
+ // 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.
+ 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.
UnregisterLoggingInstance();
@@ -174,7 +175,10 @@ ChromotingInstance::~ChromotingInstance() {
// Stopping the context shuts down all chromoting threads.
context_.Stop();
- // Ensure that nothing touches the plugin thread delegate after this point.
+ // Delete |thread_proxy_| before we detach |plugin_message_loop_|,
+ // otherwise ScopedThreadProxy may DCHECK when being destroyed.
+ thread_proxy_.reset();
+
plugin_message_loop_->Detach();
}
@@ -610,8 +614,7 @@ void ChromotingInstance::RegisterLoggingInstance() {
// and display them to the user.
// If multiple plugins are run, then the last one registered will handle all
// logging for all instances.
- g_logging_instance = weak_factory_.GetWeakPtr();
- g_logging_task_runner = plugin_message_loop_;
+ g_logging_instance = this;
g_has_logging_instance = true;
}
@@ -619,13 +622,12 @@ void ChromotingInstance::UnregisterLoggingInstance() {
base::AutoLock lock(g_logging_lock.Get());
// Don't unregister unless we're the currently registered instance.
- if (this != g_logging_instance.get())
+ if (this != g_logging_instance)
return;
// Unregister this instance for logging.
g_has_logging_instance = false;
- g_logging_instance.reset();
- g_logging_task_runner = NULL;
+ g_logging_instance = NULL;
VLOG(1) << "Unregistering global log handler";
}
@@ -647,26 +649,24 @@ bool ChromotingInstance::LogToUI(int severity, const char* file, int line,
// the lock and check |g_logging_instance| unnecessarily. This is not
// problematic because we always set |g_logging_instance| inside a lock.
if (g_has_logging_instance) {
- scoped_refptr<base::SingleThreadTaskRunner> logging_task_runner;
-
- {
- base::AutoLock lock(g_logging_lock.Get());
- // If we're on the logging thread and |g_logging_to_plugin| is set then
- // this LOG message came from handling a previous LOG message and we
- // should skip it to avoid an infinite loop of LOG messages.
- if (!g_logging_task_runner->BelongsToCurrentThread() ||
- !g_logging_to_plugin) {
- logging_task_runner = g_logging_task_runner;
- }
- }
-
- if (logging_task_runner.get()) {
+ // Do not LOG anything while holding this lock or else the code will
+ // deadlock while trying to re-get the lock we're already in.
+ base::AutoLock lock(g_logging_lock.Get());
+ if (g_logging_instance &&
+ // If |g_logging_to_plugin| is set and we're on the logging thread, then
+ // this LOG message came from handling a previous LOG message and we
+ // should skip it to avoid an infinite loop of LOG messages.
+ // We don't have a lock around |g_in_processtoui|, but that's OK since
+ // the value is only read/written on the logging thread.
+ (!g_logging_instance->plugin_message_loop_->BelongsToCurrentThread() ||
+ !g_logging_to_plugin)) {
std::string message = remoting::GetTimestampString();
message += (str.c_str() + message_start);
-
- g_logging_task_runner->PostTask(
+ // |thread_proxy_| is safe to use here because we detach it before
+ // tearing down the |g_logging_instance|.
+ g_logging_instance->thread_proxy_->PostTask(
FROM_HERE, base::Bind(&ChromotingInstance::ProcessLogToUI,
- g_logging_instance, message));
+ base::Unretained(g_logging_instance), message));
}
}
@@ -681,7 +681,6 @@ void ChromotingInstance::ProcessLogToUI(const std::string& message) {
// This flag (which is set only here) is used to prevent LogToUI from posting
// new tasks while we're in the middle of servicing a LOG call. This can
// happen if the call to LogDebugInfo tries to LOG anything.
- // Since it is read on the plugin thread, we don't need to lock to set it.
g_logging_to_plugin = true;
ChromotingScriptableObject* scriptable_object = GetScriptableObject();
if (scriptable_object) {
diff --git a/remoting/client/plugin/chromoting_instance.h b/remoting/client/plugin/chromoting_instance.h
index 0f1bdde..a489bde 100644
--- a/remoting/client/plugin/chromoting_instance.h
+++ b/remoting/client/plugin/chromoting_instance.h
@@ -25,6 +25,7 @@
#endif
#include "ppapi/cpp/private/instance_private.h"
+#include "remoting/base/scoped_thread_proxy.h"
#include "remoting/client/client_context.h"
#include "remoting/client/key_event_mapper.h"
#include "remoting/client/plugin/mac_key_event_processor.h"
@@ -224,7 +225,7 @@ class ChromotingInstance :
// This wraps a ChromotingScriptableObject in a pp::Var.
pp::Var instance_object_;
- base::WeakPtrFactory<ChromotingInstance> weak_factory_;
+ scoped_ptr<ScopedThreadProxy> thread_proxy_;
DISALLOW_COPY_AND_ASSIGN(ChromotingInstance);
};
diff --git a/remoting/host/desktop_environment.h b/remoting/host/desktop_environment.h
index 6d1d80c..f49fcdc 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"
#include "remoting/host/event_executor.h"
namespace remoting {
diff --git a/remoting/host/host_user_interface.cc b/remoting/host/host_user_interface.cc
index 964473b..4401fb5 100644
--- a/remoting/host/host_user_interface.cc
+++ b/remoting/host/host_user_interface.cc
@@ -16,8 +16,7 @@ HostUserInterface::HostUserInterface(ChromotingHostContext* context)
: host_(NULL),
context_(context),
is_monitoring_local_inputs_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
- weak_ptr_(weak_factory_.GetWeakPtr()) {
+ ui_thread_proxy_(context->ui_message_loop()) {
}
HostUserInterface::~HostUserInterface() {
@@ -25,6 +24,8 @@ HostUserInterface::~HostUserInterface() {
MonitorLocalInputs(false);
ShowDisconnectWindow(false, std::string());
+
+ ui_thread_proxy_.Detach();
}
void HostUserInterface::Start(ChromotingHost* host,
@@ -41,23 +42,19 @@ void HostUserInterface::Start(ChromotingHost* host,
}
void HostUserInterface::OnClientAuthenticated(const std::string& jid) {
- DCHECK(network_message_loop()->BelongsToCurrentThread());
-
authenticated_jid_ = jid;
std::string username = jid.substr(0, jid.find('/'));
- ui_message_loop()->PostTask(FROM_HERE, base::Bind(
+ ui_thread_proxy_.PostTask(FROM_HERE, base::Bind(
&HostUserInterface::ProcessOnClientAuthenticated,
- weak_ptr_, username));
+ base::Unretained(this), username));
}
void HostUserInterface::OnClientDisconnected(const std::string& jid) {
- DCHECK(network_message_loop()->BelongsToCurrentThread());
-
if (jid == authenticated_jid_) {
- ui_message_loop()->PostTask(FROM_HERE, base::Bind(
+ ui_thread_proxy_.PostTask(FROM_HERE, base::Bind(
&HostUserInterface::ProcessOnClientDisconnected,
- weak_ptr_));
+ base::Unretained(this)));
}
}
@@ -65,20 +62,20 @@ void HostUserInterface::OnAccessDenied(const std::string& jid) {
}
void HostUserInterface::OnShutdown() {
- DCHECK(network_message_loop()->BelongsToCurrentThread());
-
// Host status observers must be removed on the network thread, so
// it must happen here instead of in the destructor.
host_->RemoveStatusObserver(this);
host_ = NULL;
+ disconnect_callback_ = base::Closure();
}
void HostUserInterface::OnDisconnectCallback() {
DCHECK(ui_message_loop()->BelongsToCurrentThread());
+ DCHECK(!disconnect_callback_.is_null());
MonitorLocalInputs(false);
ShowDisconnectWindow(false, std::string());
- DisconnectSession();
+ disconnect_callback_.Run();
}
base::MessageLoopProxy* HostUserInterface::network_message_loop() const {
@@ -89,10 +86,7 @@ base::MessageLoopProxy* HostUserInterface::ui_message_loop() const {
}
void HostUserInterface::DisconnectSession() const {
- DCHECK(ui_message_loop()->BelongsToCurrentThread());
- DCHECK(!disconnect_callback_.is_null());
-
- disconnect_callback_.Run();
+ return disconnect_callback_.Run();
}
void HostUserInterface::ProcessOnClientAuthenticated(
@@ -146,7 +140,7 @@ void HostUserInterface::ShowDisconnectWindow(bool show,
disconnect_window_->Show(
host_,
base::Bind(&HostUserInterface::OnDisconnectCallback,
- weak_ptr_),
+ base::Unretained(this)),
username);
} else {
disconnect_window_->Hide();
diff --git a/remoting/host/host_user_interface.h b/remoting/host/host_user_interface.h
index 942cd2a..9c2729e 100644
--- a/remoting/host/host_user_interface.h
+++ b/remoting/host/host_user_interface.h
@@ -11,8 +11,8 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop_proxy.h"
+
+#include "remoting/base/scoped_thread_proxy.h"
#include "remoting/host/host_status_observer.h"
namespace remoting {
@@ -95,9 +95,7 @@ class HostUserInterface : public HostStatusObserver {
bool is_monitoring_local_inputs_;
- // WeakPtr used to avoid tasks accessing the client after it is deleted.
- base::WeakPtrFactory<HostUserInterface> weak_factory_;
- base::WeakPtr<HostUserInterface> weak_ptr_;
+ ScopedThreadProxy ui_thread_proxy_;
DISALLOW_COPY_AND_ASSIGN(HostUserInterface);
};
diff --git a/remoting/host/it2me_host_user_interface.cc b/remoting/host/it2me_host_user_interface.cc
index 1b2f392..c39f6d3 100644
--- a/remoting/host/it2me_host_user_interface.cc
+++ b/remoting/host/it2me_host_user_interface.cc
@@ -24,15 +24,29 @@ static const int kContinueWindowHideTimeoutMs = 60 * 1000;
namespace remoting {
+class It2MeHostUserInterface::TimerTask {
+ public:
+ TimerTask(base::MessageLoopProxy* message_loop,
+ const base::Closure& task,
+ int delay_ms)
+ : thread_proxy_(message_loop) {
+ thread_proxy_.PostDelayedTask(FROM_HERE, task, delay_ms);
+ }
+
+ private:
+ ScopedThreadProxy thread_proxy_;
+};
+
+
It2MeHostUserInterface::It2MeHostUserInterface(ChromotingHostContext* context)
- : HostUserInterface(context),
- ALLOW_THIS_IN_INITIALIZER_LIST(timer_weak_factory_(this)) {
+ : HostUserInterface(context) {
}
It2MeHostUserInterface::~It2MeHostUserInterface() {
DCHECK(ui_message_loop()->BelongsToCurrentThread());
ShowContinueWindow(false);
+ StartContinueWindowTimer(false);
}
void It2MeHostUserInterface::Start(ChromotingHost* host,
@@ -89,6 +103,7 @@ void It2MeHostUserInterface::ContinueSession(bool continue_session) {
if (continue_session) {
get_host()->PauseSession(false);
+ timer_task_.reset();
StartContinueWindowTimer(true);
} else {
DisconnectSession();
@@ -101,13 +116,11 @@ void It2MeHostUserInterface::OnContinueWindowTimer() {
get_host()->PauseSession(true);
ShowContinueWindow(true);
- // Cancel any pending timer and post one to hide the continue window.
- timer_weak_factory_.InvalidateWeakPtrs();
- ui_message_loop()->PostDelayedTask(
- FROM_HERE,
+ timer_task_.reset(new TimerTask(
+ ui_message_loop(),
base::Bind(&It2MeHostUserInterface::OnShutdownHostTimer,
- timer_weak_factory_.GetWeakPtr()),
- kContinueWindowHideTimeoutMs);
+ base::Unretained(this)),
+ kContinueWindowHideTimeoutMs));
}
void It2MeHostUserInterface::OnShutdownHostTimer() {
@@ -131,14 +144,14 @@ void It2MeHostUserInterface::ShowContinueWindow(bool show) {
void It2MeHostUserInterface::StartContinueWindowTimer(bool start) {
DCHECK(ui_message_loop()->BelongsToCurrentThread());
- // Abandon previous timer events by invalidating their weak pointer to us.
- timer_weak_factory_.InvalidateWeakPtrs();
if (start) {
- ui_message_loop()->PostDelayedTask(
- FROM_HERE,
+ timer_task_.reset(new TimerTask(
+ ui_message_loop(),
base::Bind(&It2MeHostUserInterface::OnContinueWindowTimer,
- timer_weak_factory_.GetWeakPtr()),
- kContinueWindowShowTimeoutMs);
+ base::Unretained(this)),
+ kContinueWindowShowTimeoutMs));
+ } else {
+ timer_task_.reset();
}
}
diff --git a/remoting/host/it2me_host_user_interface.h b/remoting/host/it2me_host_user_interface.h
index 71619ea..b054c65 100644
--- a/remoting/host/it2me_host_user_interface.h
+++ b/remoting/host/it2me_host_user_interface.h
@@ -11,7 +11,6 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
#include "remoting/host/host_user_interface.h"
@@ -68,9 +67,8 @@ class It2MeHostUserInterface : public HostUserInterface {
// the connection.
scoped_ptr<ContinueWindow> continue_window_;
- // Weak pointer factory used to abandon the "continue session" timer when
- // hiding the "continue session" dialog, or tearing down the IT2Me UI.
- base::WeakPtrFactory<It2MeHostUserInterface> timer_weak_factory_;
+ // Timer controlling the "continue session" dialog.
+ scoped_ptr<TimerTask> timer_task_;
DISALLOW_COPY_AND_ASSIGN(It2MeHostUserInterface);
};
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 4485937..2d4648b 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -1043,6 +1043,8 @@
'base/rate_counter.h',
'base/running_average.cc',
'base/running_average.h',
+ 'base/scoped_thread_proxy.cc',
+ 'base/scoped_thread_proxy.h',
'base/util.cc',
'base/util.h',
],