summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsergeyu <sergeyu@chromium.org>2015-02-02 10:01:26 -0800
committerCommit bot <commit-bot@chromium.org>2015-02-02 18:02:19 +0000
commitc099813e194006d7ba33b71d7f62cc782a36d6a6 (patch)
treee831a26c68b6824e27f64542ad5ff870106deba8
parentfd0b94cd15337a91d167a3b931ac4252e1174042 (diff)
downloadchromium_src-c099813e194006d7ba33b71d7f62cc782a36d6a6.zip
chromium_src-c099813e194006d7ba33b71d7f62cc782a36d6a6.tar.gz
chromium_src-c099813e194006d7ba33b71d7f62cc782a36d6a6.tar.bz2
Add blocking IO restriction on the network thread.
Now ChromotingHostContext disallows blocking operations on then network thread. This will help to avoid issues such as the one that was fixed in https://codereview.chromium.org/886913002/ (Network thread was used to load policies from disk). Also made the following changes to avoid blocking operation on the network thread: - Moved PolicyWatcher to the main thread in the Me2Me host. PolicyLoader uses blocking IO for initialization. Also this is more consistent with the It2Me host where PolicyWatcher also runs on the UI thread. - Moved NetworkChangeNotifier initialization out of HostSignalingManager. NetworkChangeNotifier creates a thread internally and therefore should be destroyed on the main thread. - Added a reference to URLRequestContextGetter in HostProcessMain to make sure it's destroyed on the main thread. This is necessary because BasicURLRequestContext owns threads and needs to be deleted on the main thread. Review URL: https://codereview.chromium.org/891663005 Cr-Commit-Position: refs/heads/master@{#314165}
-rw-r--r--remoting/host/chromoting_host_context.cc13
-rw-r--r--remoting/host/host_signaling_manager.cc11
-rw-r--r--remoting/host/host_signaling_manager.h12
-rw-r--r--remoting/host/remoting_me2me_host.cc89
4 files changed, 84 insertions, 41 deletions
diff --git a/remoting/host/chromoting_host_context.cc b/remoting/host/chromoting_host_context.cc
index 60e3a73..319cc77 100644
--- a/remoting/host/chromoting_host_context.cc
+++ b/remoting/host/chromoting_host_context.cc
@@ -4,12 +4,22 @@
#include "remoting/host/chromoting_host_context.h"
+#include "base/threading/thread_restrictions.h"
#include "content/public/browser/browser_thread.h"
#include "remoting/base/auto_thread.h"
#include "remoting/base/url_request_context_getter.h"
namespace remoting {
+namespace {
+
+void DisallowBlockingOperations() {
+ base::ThreadRestrictions::SetIOAllowed(false);
+ base::ThreadRestrictions::DisallowWaiting();
+}
+
+} // namespace
+
ChromotingHostContext::ChromotingHostContext(
scoped_refptr<AutoThreadTaskRunner> ui_task_runner,
scoped_refptr<AutoThreadTaskRunner> audio_task_runner,
@@ -96,9 +106,12 @@ scoped_ptr<ChromotingHostContext> ChromotingHostContext::Create(
scoped_refptr<AutoThreadTaskRunner> file_task_runner =
AutoThread::CreateWithType("ChromotingFileThread", ui_task_runner,
base::MessageLoop::TYPE_IO);
+
scoped_refptr<AutoThreadTaskRunner> network_task_runner =
AutoThread::CreateWithType("ChromotingNetworkThread", ui_task_runner,
base::MessageLoop::TYPE_IO);
+ network_task_runner->PostTask(FROM_HERE,
+ base::Bind(&DisallowBlockingOperations));
return make_scoped_ptr(new ChromotingHostContext(
ui_task_runner,
diff --git a/remoting/host/host_signaling_manager.cc b/remoting/host/host_signaling_manager.cc
index 37da304..20abbd1 100644
--- a/remoting/host/host_signaling_manager.cc
+++ b/remoting/host/host_signaling_manager.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/time/time.h"
-#include "net/base/network_change_notifier.h"
#include "net/socket/client_socket_factory.h"
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/base/logging.h"
@@ -22,13 +21,11 @@ namespace remoting {
HostSignalingManager::HostSignalingManager(
scoped_ptr<base::WeakPtrFactory<Listener>> weak_factory_for_listener,
const scoped_refptr<AutoThreadTaskRunner>& network_task_runner,
- scoped_ptr<net::NetworkChangeNotifier> network_change_notifier,
scoped_ptr<SignalStrategy> signal_strategy,
scoped_ptr<SignalingConnector> signaling_connector,
scoped_ptr<HeartbeatSender> heartbeat_sender)
: weak_factory_for_listener_(weak_factory_for_listener.Pass()),
network_task_runner_(network_task_runner),
- network_change_notifier_(network_change_notifier.Pass()),
signal_strategy_(signal_strategy.Pass()),
signaling_connector_(signaling_connector.Pass()),
heartbeat_sender_(heartbeat_sender.Pass()) {
@@ -50,9 +47,6 @@ scoped_ptr<HostSignalingManager> HostSignalingManager::Create(
scoped_ptr<base::WeakPtrFactory<Listener>> weak_factory(
new base::WeakPtrFactory<Listener>(listener));
- scoped_ptr<net::NetworkChangeNotifier> network_change_notifier(
- net::NetworkChangeNotifier::Create());
-
scoped_ptr<XmppSignalStrategy> signal_strategy(
new XmppSignalStrategy(net::ClientSocketFactory::GetDefaultFactory(),
url_request_context_getter, xmpp_server_config));
@@ -77,9 +71,8 @@ scoped_ptr<HostSignalingManager> HostSignalingManager::Create(
host_id, signal_strategy.get(), host_key_pair, directory_bot_jid));
return scoped_ptr<HostSignalingManager>(new HostSignalingManager(
- weak_factory.Pass(), network_task_runner, network_change_notifier.Pass(),
- signal_strategy.Pass(), signaling_connector.Pass(),
- heartbeat_sender.Pass()));
+ weak_factory.Pass(), network_task_runner, signal_strategy.Pass(),
+ signaling_connector.Pass(), heartbeat_sender.Pass()));
}
HostSignalingManager::~HostSignalingManager() {
diff --git a/remoting/host/host_signaling_manager.h b/remoting/host/host_signaling_manager.h
index 1004dd8..22f0567 100644
--- a/remoting/host/host_signaling_manager.h
+++ b/remoting/host/host_signaling_manager.h
@@ -90,7 +90,6 @@ class HostSignalingManager {
HostSignalingManager(
scoped_ptr<base::WeakPtrFactory<Listener>> weak_factory_for_listener,
const scoped_refptr<AutoThreadTaskRunner>& network_task_runner,
- scoped_ptr<net::NetworkChangeNotifier> network_change_notifier,
scoped_ptr<SignalStrategy> signal_strategy,
scoped_ptr<SignalingConnector> signaling_connector,
scoped_ptr<HeartbeatSender> heartbeat_sender);
@@ -109,14 +108,9 @@ class HostSignalingManager {
// host-offline-reason.
scoped_refptr<AutoThreadTaskRunner> network_task_runner_;
- // Order of fields below is important for destroying them in the right order.
- // - |heartbeat_sender_| and |signaling_connector_| have to be destroyed
- // before |signal_strategy_| because their destructors need to call
- // signal_strategy_->RemoveListener(this)
- // - |signaling_connector_| has to be destroyed before
- // |network_change_notifier_| because its destructor needs to deregister
- // network change notifications
- scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
+ // |heartbeat_sender_| and |signaling_connector_| have to be destroyed before
+ // |signal_strategy_| because their destructors need to call
+ // signal_strategy_->RemoveListener(this)
scoped_ptr<SignalStrategy> signal_strategy_;
scoped_ptr<SignalingConnector> signaling_connector_;
scoped_ptr<HeartbeatSender> heartbeat_sender_;
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index aa0bf6f..291aba6 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -26,6 +26,7 @@
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_listener.h"
#include "media/base/media.h"
+#include "net/base/network_change_notifier.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/ssl_server_socket.h"
#include "net/url_request/url_fetcher.h"
@@ -259,6 +260,7 @@ class HostProcess : public ConfigWatcher::Delegate,
scoped_ptr<HostSignalingManager> CreateHostSignalingManager();
+ void StartHostIfReady();
void StartHost();
// Overrides for HostSignalingManager::Listener interface.
@@ -323,6 +325,7 @@ class HostProcess : public ConfigWatcher::Delegate,
int64_t frame_recorder_buffer_size_;
scoped_ptr<PolicyWatcher> policy_watcher_;
+ bool policies_loaded_;
std::string host_domain_;
bool host_username_match_required_;
bool allow_nat_traversal_;
@@ -336,7 +339,7 @@ class HostProcess : public ConfigWatcher::Delegate,
ThirdPartyAuthConfig third_party_auth_config_;
bool enable_gnubby_auth_;
- // Boolean to change flow, where ncessary, if we're
+ // Boolean to change flow, where necessary, if we're
// capturing a window instead of the entire desktop.
bool enable_window_capture_;
@@ -378,6 +381,7 @@ HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context,
use_service_account_(false),
enable_vp9_(false),
frame_recorder_buffer_size_(0),
+ policies_loaded_(false),
host_username_match_required_(false),
allow_nat_traversal_(true),
allow_relay_(true),
@@ -548,26 +552,18 @@ void HostProcess::OnConfigUpdated(
}
if (state_ == HOST_INITIALIZING) {
- // TODO(sergeyu): Currently OnPolicyUpdate() assumes that host config is
- // already loaded so PolicyWatcher has to be started here. Separate policy
- // loading from policy verifications and move |policy_watcher_|
- // initialization to StartOnNetworkThread().
- policy_watcher_ =
- PolicyWatcher::Create(nullptr, context_->file_task_runner());
- policy_watcher_->StartWatching(
- base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)),
- base::Bind(&HostProcess::OnPolicyError, base::Unretained(this)));
- } else {
+ StartHostIfReady();
+ } else if (state_ == HOST_STARTED) {
+ DCHECK(policies_loaded_);
+
// Reapply policies that could be affected by a new config.
ApplyHostDomainPolicy();
ApplyUsernamePolicy();
- if (state_ == HOST_STARTED) {
- // TODO(sergeyu): Here we assume that PIN is the only part of the config
- // that may change while the service is running. Change ApplyConfig() to
- // detect other changes in the config and restart host if necessary here.
- CreateAuthenticatorFactory();
- }
+ // TODO(sergeyu): Here we assume that PIN is the only part of the config
+ // that may change while the service is running. Change ApplyConfig() to
+ // detect other changes in the config and restart host if necessary here.
+ CreateAuthenticatorFactory();
}
}
@@ -724,6 +720,12 @@ void HostProcess::StartOnUiThread() {
return;
}
+ policy_watcher_ =
+ PolicyWatcher::Create(nullptr, context_->file_task_runner());
+ policy_watcher_->StartWatching(
+ base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)),
+ base::Bind(&HostProcess::OnPolicyError, base::Unretained(this)));
+
#if defined(OS_LINUX)
// If an audio pipe is specific on the command-line then initialize
// AudioCapturerLinux to capture from it.
@@ -784,6 +786,8 @@ void HostProcess::ShutdownOnUiThread() {
daemon_channel_.reset();
desktop_environment_factory_.reset();
+ policy_watcher_.reset();
+
// It is now safe for the HostProcess to be deleted.
self_ = nullptr;
@@ -956,7 +960,12 @@ bool HostProcess::ApplyConfig(const base::DictionaryValue& config) {
}
void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
- DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
+ if (!context_->network_task_runner()->BelongsToCurrentThread()) {
+ context_->network_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&HostProcess::OnPolicyUpdate, this,
+ base::Passed(&policies)));
+ return;
+ }
bool restart_required = false;
restart_required |= OnHostDomainPolicyUpdate(policies.get());
@@ -971,20 +980,30 @@ void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
restart_required |= OnPairingPolicyUpdate(policies.get());
restart_required |= OnGnubbyAuthPolicyUpdate(policies.get());
+ policies_loaded_ = true;
+
if (state_ == HOST_INITIALIZING) {
- StartHost();
- } else if (state_ == HOST_STARTED && restart_required) {
- RestartHost();
+ StartHostIfReady();
+ } else if (state_ == HOST_STARTED) {
+ if (restart_required)
+ RestartHost();
}
}
void HostProcess::OnPolicyError() {
- DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
+ if (!context_->network_task_runner()->BelongsToCurrentThread()) {
+ context_->network_task_runner()->PostTask(
+ FROM_HERE, base::Bind(&HostProcess::OnPolicyError, this));
+ return;
+ }
ShutdownHost(kInvalidHostConfigurationExitCode);
}
void HostProcess::ApplyHostDomainPolicy() {
+ if (state_ != HOST_STARTED)
+ return;
+
HOST_LOG << "Policy sets host domain: " << host_domain_;
if (!host_domain_.empty()) {
@@ -1019,6 +1038,9 @@ bool HostProcess::OnHostDomainPolicyUpdate(base::DictionaryValue* policies) {
}
void HostProcess::ApplyUsernamePolicy() {
+ if (state_ != HOST_STARTED)
+ return;
+
if (host_username_match_required_) {
HOST_LOG << "Policy requires host username match.";
@@ -1284,6 +1306,15 @@ scoped_ptr<HostSignalingManager> HostProcess::CreateHostSignalingManager() {
oauth_credentials.Pass());
}
+void HostProcess::StartHostIfReady() {
+ DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
+ DCHECK_EQ(state_, HOST_INITIALIZING);
+
+ // Start the host if both the config and the policies are loaded.
+ if (!serialized_config_.empty() && policies_loaded_)
+ StartHost();
+}
+
void HostProcess::StartHost() {
DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
DCHECK(!host_);
@@ -1368,6 +1399,9 @@ void HostProcess::StartHost() {
host_->Start(host_owner_email_);
CreateAuthenticatorFactory();
+
+ ApplyHostDomainPolicy();
+ ApplyUsernamePolicy();
}
void HostProcess::OnAuthFailed() {
@@ -1439,7 +1473,6 @@ void HostProcess::ShutdownOnNetworkThread() {
shutdown_watchdog_->Arm();
config_watcher_.reset();
- policy_watcher_.reset();
// Complete the rest of shutdown on the main thread.
context_->ui_task_runner()->PostTask(
@@ -1481,6 +1514,9 @@ int HostProcessMain() {
// Ensures runtime specific CPU features are initialized.
media::InitializeCPUSpecificMediaFeatures();
+ scoped_ptr<net::NetworkChangeNotifier> network_change_notifier(
+ net::NetworkChangeNotifier::Create());
+
// Create the main message loop and start helper threads.
base::MessageLoopForUI message_loop;
scoped_ptr<ChromotingHostContext> context =
@@ -1489,6 +1525,13 @@ int HostProcessMain() {
if (!context)
return kInitializationFailed;
+ // BasicURLRequestContext holds references to threads, so it needs to be
+ // dereferences on UI threads. Store the reference to the URLRequestGetter to
+ // make sure it's not destroyed on other threads.
+ // TODO(sergeyu): Consider fixing it in BasicURLRequestContext.
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
+ context->url_request_context_getter();
+
// Create & start the HostProcess using these threads.
// TODO(wez): The HostProcess holds a reference to itself until Shutdown().
// Remove this hack as part of the multi-process refactoring.