Commit 6d549365 authored by Jamie Walch's avatar Jamie Walch Committed by Commit Bot

Add support for the "noDialogs" option to "connect".

Bug: 864384
Change-Id: I23845a183196ce7e2d9dd4cd50fbfc63f0d9f289
Reviewed-on: https://chromium-review.googlesource.com/1182199
Commit-Queue: Jamie Walch <jamiewalch@chromium.org>
Reviewed-by: default avatarJoe Downing <joedow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585987}
parent 7f33da45
...@@ -85,6 +85,9 @@ class ChromotingHost : public ClientSession::EventHandler { ...@@ -85,6 +85,9 @@ class ChromotingHost : public ClientSession::EventHandler {
void Start(const std::string& host_owner); void Start(const std::string& host_owner);
scoped_refptr<HostStatusMonitor> status_monitor() { return status_monitor_; } scoped_refptr<HostStatusMonitor> status_monitor() { return status_monitor_; }
const DesktopEnvironmentOptions& desktop_environment_options() const {
return desktop_environment_options_;
}
// Registers a host extension. // Registers a host extension.
void AddExtension(std::unique_ptr<HostExtension> extension); void AddExtension(std::unique_ptr<HostExtension> extension);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/policy/policy_constants.h" #include "components/policy/policy_constants.h"
#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_context_getter.h"
#include "remoting/base/auto_thread.h" #include "remoting/base/auto_thread.h"
...@@ -64,6 +65,14 @@ It2MeHost::~It2MeHost() { ...@@ -64,6 +65,14 @@ It2MeHost::~It2MeHost() {
DCHECK(!desktop_environment_factory_.get()); DCHECK(!desktop_environment_factory_.get());
} }
void It2MeHost::set_enable_dialogs(bool enable) {
#if defined(OS_CHROMEOS)
enable_dialogs_ = enable;
#else
NOTREACHED() << "It2MeHost::set_enable_dialogs is only supported on ChromeOS";
#endif
}
void It2MeHost::Connect( void It2MeHost::Connect(
std::unique_ptr<ChromotingHostContext> host_context, std::unique_ptr<ChromotingHostContext> host_context,
std::unique_ptr<base::DictionaryValue> policies, std::unique_ptr<base::DictionaryValue> policies,
...@@ -177,11 +186,12 @@ void It2MeHost::ConnectOnNetworkThread(const std::string& username, ...@@ -177,11 +186,12 @@ void It2MeHost::ConnectOnNetworkThread(const std::string& username,
session_manager->set_protocol_config(std::move(protocol_config)); session_manager->set_protocol_config(std::move(protocol_config));
// Create the host. // Create the host.
host_.reset(new ChromotingHost(desktop_environment_factory_.get(), DesktopEnvironmentOptions options(DesktopEnvironmentOptions::CreateDefault());
std::move(session_manager), transport_context, options.set_enable_user_interface(enable_dialogs_);
host_context_->audio_task_runner(), host_.reset(new ChromotingHost(
host_context_->video_encode_task_runner(), desktop_environment_factory_.get(), std::move(session_manager),
DesktopEnvironmentOptions::CreateDefault())); transport_context, host_context_->audio_task_runner(),
host_context_->video_encode_task_runner(), options));
host_->status_monitor()->AddStatusObserver(this); host_->status_monitor()->AddStatusObserver(this);
host_status_logger_.reset( host_status_logger_.reset(
new HostStatusLogger(host_->status_monitor(), ServerLogEntry::IT2ME, new HostStatusLogger(host_->status_monitor(), ServerLogEntry::IT2ME,
...@@ -532,12 +542,19 @@ void It2MeHost::ValidateConnectionDetails( ...@@ -532,12 +542,19 @@ void It2MeHost::ValidateConnectionDetails(
SetState(kConnecting, ErrorCode::OK); SetState(kConnecting, ErrorCode::OK);
// Show a confirmation dialog to the user to allow them to confirm/reject it. // Show a confirmation dialog to the user to allow them to confirm/reject it.
confirmation_dialog_proxy_.reset(new It2MeConfirmationDialogProxy( // If dialogs are suppressed, just call the callback directly.
host_context_->ui_task_runner(), confirmation_dialog_factory_->Create())); if (enable_dialogs_) {
confirmation_dialog_proxy_.reset(new It2MeConfirmationDialogProxy(
confirmation_dialog_proxy_->Show( host_context_->ui_task_runner(),
client_username, base::Bind(&It2MeHost::OnConfirmationResult, confirmation_dialog_factory_->Create()));
base::Unretained(this), result_callback)); confirmation_dialog_proxy_->Show(
client_username, base::Bind(&It2MeHost::OnConfirmationResult,
base::Unretained(this), result_callback));
} else {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(result_callback, ValidationResult::SUCCESS));
}
} }
void It2MeHost::OnConfirmationResult( void It2MeHost::OnConfirmationResult(
......
...@@ -68,6 +68,11 @@ class It2MeHost : public base::RefCountedThreadSafe<It2MeHost>, ...@@ -68,6 +68,11 @@ class It2MeHost : public base::RefCountedThreadSafe<It2MeHost>,
It2MeHost(); It2MeHost();
// Enable, disable, or query whether or not the confirm, continue, and
// disconnect dialogs are shown.
void set_enable_dialogs(bool enable);
bool enable_dialogs() const { return enable_dialogs_; }
// Methods called by the script object, from the plugin thread. // Methods called by the script object, from the plugin thread.
// Creates It2Me host structures and starts the host. // Creates It2Me host structures and starts the host.
...@@ -182,6 +187,8 @@ class It2MeHost : public base::RefCountedThreadSafe<It2MeHost>, ...@@ -182,6 +187,8 @@ class It2MeHost : public base::RefCountedThreadSafe<It2MeHost>,
// Tracks the JID of the remote user when in a connecting state. // Tracks the JID of the remote user when in a connecting state.
std::string connecting_jid_; std::string connecting_jid_;
bool enable_dialogs_ = true;
DISALLOW_COPY_AND_ASSIGN(It2MeHost); DISALLOW_COPY_AND_ASSIGN(It2MeHost);
}; };
......
...@@ -111,9 +111,12 @@ class FakeIt2MeDialogFactory : public It2MeConfirmationDialogFactory { ...@@ -111,9 +111,12 @@ class FakeIt2MeDialogFactory : public It2MeConfirmationDialogFactory {
remote_user_email_ = remote_user_email; remote_user_email_ = remote_user_email;
} }
bool dialog_created() const { return dialog_created_; }
private: private:
std::string remote_user_email_; std::string remote_user_email_;
DialogResult dialog_result_ = DialogResult::OK; DialogResult dialog_result_ = DialogResult::OK;
bool dialog_created_ = false;
DISALLOW_COPY_AND_ASSIGN(FakeIt2MeDialogFactory); DISALLOW_COPY_AND_ASSIGN(FakeIt2MeDialogFactory);
}; };
...@@ -125,6 +128,7 @@ FakeIt2MeDialogFactory::~FakeIt2MeDialogFactory() = default; ...@@ -125,6 +128,7 @@ FakeIt2MeDialogFactory::~FakeIt2MeDialogFactory() = default;
std::unique_ptr<It2MeConfirmationDialog> FakeIt2MeDialogFactory::Create() { std::unique_ptr<It2MeConfirmationDialog> FakeIt2MeDialogFactory::Create() {
EXPECT_FALSE(remote_user_email_.empty()); EXPECT_FALSE(remote_user_email_.empty());
dialog_created_ = true;
return std::make_unique<FakeIt2MeConfirmationDialog>(remote_user_email_, return std::make_unique<FakeIt2MeConfirmationDialog>(remote_user_email_,
dialog_result_); dialog_result_);
} }
...@@ -157,7 +161,7 @@ class It2MeHostTest : public testing::Test, public It2MeHost::Observer { ...@@ -157,7 +161,7 @@ class It2MeHostTest : public testing::Test, public It2MeHost::Observer {
void RunValidationCallback(const std::string& remote_jid); void RunValidationCallback(const std::string& remote_jid);
void StartHost(); void StartHost(bool enable_dialogs = true);
void ShutdownHost(); void ShutdownHost();
static base::ListValue MakeList( static base::ListValue MakeList(
...@@ -258,7 +262,7 @@ void It2MeHostTest::StartupHostStateHelper(const base::Closure& quit_closure) { ...@@ -258,7 +262,7 @@ void It2MeHostTest::StartupHostStateHelper(const base::Closure& quit_closure) {
base::Unretained(this), quit_closure); base::Unretained(this), quit_closure);
} }
void It2MeHostTest::StartHost() { void It2MeHostTest::StartHost(bool enable_dialogs) {
if (!policies_) { if (!policies_) {
policies_ = PolicyWatcher::GetDefaultPolicies(); policies_ = PolicyWatcher::GetDefaultPolicies();
} }
...@@ -277,6 +281,11 @@ void It2MeHostTest::StartHost() { ...@@ -277,6 +281,11 @@ void It2MeHostTest::StartHost() {
fake_bot_signal_strategy_->ConnectTo(fake_signal_strategy.get()); fake_bot_signal_strategy_->ConnectTo(fake_signal_strategy.get());
it2me_host_ = new It2MeHost(); it2me_host_ = new It2MeHost();
if (!enable_dialogs) {
// Only ChromeOS supports this method, so tests setting enable_dialogs to
// false should only be run on ChromeOS.
it2me_host_->set_enable_dialogs(enable_dialogs);
}
it2me_host_->Connect(host_context_->Copy(), policies_->CreateDeepCopy(), it2me_host_->Connect(host_context_->Copy(), policies_->CreateDeepCopy(),
std::move(dialog_factory), weak_factory_.GetWeakPtr(), std::move(dialog_factory), weak_factory_.GetWeakPtr(),
std::move(fake_signal_strategy), kTestUserName, std::move(fake_signal_strategy), kTestUserName,
...@@ -602,4 +611,13 @@ TEST_F(It2MeHostTest, MultipleConnectionsTriggerDisconnect) { ...@@ -602,4 +611,13 @@ TEST_F(It2MeHostTest, MultipleConnectionsTriggerDisconnect) {
ASSERT_EQ(It2MeHostState::kDisconnected, last_host_state_); ASSERT_EQ(It2MeHostState::kDisconnected, last_host_state_);
} }
#if defined(OS_CHROMEOS)
TEST_F(It2MeHostTest, ConnectRespectsNoDialogsParameter) {
StartHost(false);
EXPECT_FALSE(dialog_factory_->dialog_created());
EXPECT_FALSE(
GetHost()->desktop_environment_options().enable_user_interface());
}
#endif
} // namespace remoting } // namespace remoting
...@@ -235,6 +235,9 @@ void It2MeNativeMessagingHost::ProcessConnect( ...@@ -235,6 +235,9 @@ void It2MeNativeMessagingHost::ProcessConnect(
std::string username; std::string username;
message->GetString("userName", &username); message->GetString("userName", &username);
bool no_dialogs = false;
message->GetBoolean("noDialogs", &no_dialogs);
std::unique_ptr<SignalStrategy> signal_strategy; std::unique_ptr<SignalStrategy> signal_strategy;
if (use_signaling_proxy) { if (use_signaling_proxy) {
if (username.empty()) { if (username.empty()) {
...@@ -278,8 +281,12 @@ void It2MeNativeMessagingHost::ProcessConnect( ...@@ -278,8 +281,12 @@ void It2MeNativeMessagingHost::ProcessConnect(
return; return;
} }
// Create the It2Me host and start connecting. // Create the It2Me host and start connecting. Note that disabling dialogs is
// only supported on ChromeOS.
it2me_host_ = factory_->CreateIt2MeHost(); it2me_host_ = factory_->CreateIt2MeHost();
#if defined(OS_CHROMEOS)
it2me_host_->set_enable_dialogs(!no_dialogs);
#endif
it2me_host_->Connect(host_context_->Copy(), std::move(policies), it2me_host_->Connect(host_context_->Copy(), std::move(policies),
std::make_unique<It2MeConfirmationDialogFactory>(), std::make_unique<It2MeConfirmationDialogFactory>(),
weak_ptr_, std::move(signal_strategy), username, weak_ptr_, std::move(signal_strategy), username,
......
...@@ -84,6 +84,30 @@ void VerifyCommonProperties(std::unique_ptr<base::DictionaryValue> response, ...@@ -84,6 +84,30 @@ void VerifyCommonProperties(std::unique_ptr<base::DictionaryValue> response,
EXPECT_EQ(id, int_value); EXPECT_EQ(id, int_value);
} }
base::DictionaryValue CreateConnectMessage(int id) {
base::DictionaryValue connect_message;
connect_message.SetInteger("id", id);
connect_message.SetString("type", "connect");
connect_message.SetString("xmppServerAddress", "talk.google.com:5222");
connect_message.SetBoolean("xmppServerUseTls", true);
connect_message.SetString("directoryBotJid", kTestBotJid);
connect_message.SetString("userName", kTestClientUsername);
connect_message.SetString("authServiceWithToken", "oauth2:sometoken");
connect_message.Set(
"iceConfig",
base::JSONReader::Read("{ \"iceServers\": [ { \"urls\": [ \"stun:" +
std::string(kTestStunServer) + "\" ] } ] }"));
return connect_message;
}
base::DictionaryValue CreateDisconnectMessage(int id) {
base::DictionaryValue disconnect_message;
disconnect_message.SetInteger("id", id);
disconnect_message.SetString("type", "disconnect");
return disconnect_message;
}
} // namespace } // namespace
class MockIt2MeHost : public It2MeHost { class MockIt2MeHost : public It2MeHost {
...@@ -171,13 +195,15 @@ void MockIt2MeHost::RunSetState(It2MeHostState state) { ...@@ -171,13 +195,15 @@ void MockIt2MeHost::RunSetState(It2MeHostState state) {
class MockIt2MeHostFactory : public It2MeHostFactory { class MockIt2MeHostFactory : public It2MeHostFactory {
public: public:
MockIt2MeHostFactory() = default; MockIt2MeHostFactory() : host(new MockIt2MeHost()) {}
~MockIt2MeHostFactory() override = default; ~MockIt2MeHostFactory() override = default;
scoped_refptr<It2MeHost> CreateIt2MeHost() override { scoped_refptr<It2MeHost> CreateIt2MeHost() override {
return new MockIt2MeHost(); return host;
} }
scoped_refptr<MockIt2MeHost> host;
private: private:
DISALLOW_COPY_AND_ASSIGN(MockIt2MeHostFactory); DISALLOW_COPY_AND_ASSIGN(MockIt2MeHostFactory);
}; };
...@@ -208,8 +234,8 @@ class It2MeNativeMessagingHostTest : public testing::Test { ...@@ -208,8 +234,8 @@ class It2MeNativeMessagingHostTest : public testing::Test {
void TestBadRequest(const base::Value& message, bool expect_error_response); void TestBadRequest(const base::Value& message, bool expect_error_response);
void TestConnect(); void TestConnect();
void SendConnectMessage(int id); // Raw pointer to host factory (owned by It2MeNativeMessagingHost).
void SendDisconnectMessage(int id); MockIt2MeHostFactory* factory_raw_ptr_ = nullptr;
private: private:
void StartHost(); void StartHost();
...@@ -521,10 +547,12 @@ void It2MeNativeMessagingHostTest::StartHost() { ...@@ -521,10 +547,12 @@ void It2MeNativeMessagingHostTest::StartHost() {
policy_loader_ = policy_loader.get(); policy_loader_ = policy_loader.get();
std::unique_ptr<PolicyWatcher> policy_watcher = std::unique_ptr<PolicyWatcher> policy_watcher =
PolicyWatcher::CreateFromPolicyLoaderForTesting(std::move(policy_loader)); PolicyWatcher::CreateFromPolicyLoaderForTesting(std::move(policy_loader));
auto factory = std::make_unique<MockIt2MeHostFactory>();
factory_raw_ptr_ = factory.get();
std::unique_ptr<It2MeNativeMessagingHost> it2me_host( std::unique_ptr<It2MeNativeMessagingHost> it2me_host(
new It2MeNativeMessagingHost( new It2MeNativeMessagingHost(
/*needs_elevation=*/false, std::move(policy_watcher), /*needs_elevation=*/false, std::move(policy_watcher),
std::move(context), base::WrapUnique(new MockIt2MeHostFactory()))); std::move(context), std::move(factory)));
it2me_host->SetPolicyErrorClosureForTesting( it2me_host->SetPolicyErrorClosureForTesting(
base::Bind(base::IgnoreResult(&base::TaskRunner::PostTask), base::Bind(base::IgnoreResult(&base::TaskRunner::PostTask),
test_message_loop_->task_runner(), FROM_HERE, test_message_loop_->task_runner(), FROM_HERE,
...@@ -557,36 +585,12 @@ void It2MeNativeMessagingHostTest::ExitPolicyRunLoop() { ...@@ -557,36 +585,12 @@ void It2MeNativeMessagingHostTest::ExitPolicyRunLoop() {
} }
} }
void It2MeNativeMessagingHostTest::SendConnectMessage(int id) {
base::DictionaryValue connect_message;
connect_message.SetInteger("id", id);
connect_message.SetString("type", "connect");
connect_message.SetString("xmppServerAddress", "talk.google.com:5222");
connect_message.SetBoolean("xmppServerUseTls", true);
connect_message.SetString("directoryBotJid", kTestBotJid);
connect_message.SetString("userName", kTestClientUsername);
connect_message.SetString("authServiceWithToken", "oauth2:sometoken");
connect_message.Set(
"iceConfig",
base::JSONReader::Read("{ \"iceServers\": [ { \"urls\": [ \"stun:" +
std::string(kTestStunServer) + "\" ] } ] }"));
WriteMessageToInputPipe(connect_message);
}
void It2MeNativeMessagingHostTest::SendDisconnectMessage(int id) {
base::DictionaryValue disconnect_message;
disconnect_message.SetInteger("id", id);
disconnect_message.SetString("type", "disconnect");
WriteMessageToInputPipe(disconnect_message);
}
void It2MeNativeMessagingHostTest::TestConnect() { void It2MeNativeMessagingHostTest::TestConnect() {
int next_id = 1; int next_id = 1;
SendConnectMessage(next_id); WriteMessageToInputPipe(CreateConnectMessage(next_id));
VerifyConnectResponses(next_id); VerifyConnectResponses(next_id);
++next_id; ++next_id;
SendDisconnectMessage(next_id); WriteMessageToInputPipe(CreateDisconnectMessage(next_id));
VerifyDisconnectResponses(next_id); VerifyDisconnectResponses(next_id);
} }
...@@ -629,6 +633,24 @@ TEST_F(It2MeNativeMessagingHostTest, ConnectMultiple) { ...@@ -629,6 +633,24 @@ TEST_F(It2MeNativeMessagingHostTest, ConnectMultiple) {
} }
} }
TEST_F(It2MeNativeMessagingHostTest,
ConnectRespectsNoDialogsParameterOnChromeOsOnly) {
int next_id = 1;
base::DictionaryValue connect_message = CreateConnectMessage(next_id);
connect_message.SetBoolean("noDialogs", true);
WriteMessageToInputPipe(connect_message);
VerifyConnectResponses(next_id);
#if defined(OS_CHROMEOS)
EXPECT_FALSE(factory_raw_ptr_->host->enable_dialogs());
#else
EXPECT_TRUE(factory_raw_ptr_->host->enable_dialogs());
#endif
++next_id;
WriteMessageToInputPipe(CreateDisconnectMessage(next_id));
VerifyDisconnectResponses(next_id);
}
// Verify non-Dictionary requests are rejected. // Verify non-Dictionary requests are rejected.
TEST_F(It2MeNativeMessagingHostTest, WrongFormat) { TEST_F(It2MeNativeMessagingHostTest, WrongFormat) {
base::ListValue message; base::ListValue message;
...@@ -654,7 +676,7 @@ TEST_F(It2MeNativeMessagingHostTest, BadPoliciesBeforeConnect) { ...@@ -654,7 +676,7 @@ TEST_F(It2MeNativeMessagingHostTest, BadPoliciesBeforeConnect) {
base::DictionaryValue bad_policy; base::DictionaryValue bad_policy;
bad_policy.SetInteger(policy::key::kRemoteAccessHostFirewallTraversal, 1); bad_policy.SetInteger(policy::key::kRemoteAccessHostFirewallTraversal, 1);
SetPolicies(bad_policy); SetPolicies(bad_policy);
SendConnectMessage(1); WriteMessageToInputPipe(CreateConnectMessage(1));
VerifyPolicyErrorResponse(); VerifyPolicyErrorResponse();
} }
...@@ -662,7 +684,7 @@ TEST_F(It2MeNativeMessagingHostTest, BadPoliciesBeforeConnect) { ...@@ -662,7 +684,7 @@ TEST_F(It2MeNativeMessagingHostTest, BadPoliciesBeforeConnect) {
TEST_F(It2MeNativeMessagingHostTest, BadPoliciesAfterConnect) { TEST_F(It2MeNativeMessagingHostTest, BadPoliciesAfterConnect) {
base::DictionaryValue bad_policy; base::DictionaryValue bad_policy;
bad_policy.SetInteger(policy::key::kRemoteAccessHostFirewallTraversal, 1); bad_policy.SetInteger(policy::key::kRemoteAccessHostFirewallTraversal, 1);
SendConnectMessage(1); WriteMessageToInputPipe(CreateConnectMessage(1));
VerifyConnectResponses(1); VerifyConnectResponses(1);
SetPolicies(bad_policy); SetPolicies(bad_policy);
VerifyPolicyErrorResponse(); VerifyPolicyErrorResponse();
......
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