0

[remoting host][windows] Implement UrlForwarderConfiguratorWin

This CL implements UrlForwarderConfiguratorWin by launching the setup UI
as the currently logged in user, and also makes UrlForwarderConfigurator
no longer a singleton so that we can later provide an IPC-based
implementation in IpcDesktopEnvironment.

Bug: b:183135000
Change-Id: Ia7253b5cf0d8c916afac2b1bf20ca54793da26e5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3062583
Commit-Queue: Yuwei Huang <yuweih@chromium.org>
Reviewed-by: Joe Downing <joedow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#907782}
This commit is contained in:
Yuwei Huang
2021-08-03 00:36:58 +00:00
committed by Chromium LUCI CQ
parent 2cc75e72aa
commit 84af8d276a
19 changed files with 212 additions and 31 deletions

@ -19,6 +19,7 @@
#include "remoting/host/keyboard_layout_monitor.h"
#include "remoting/host/mouse_cursor_monitor_proxy.h"
#include "remoting/host/screen_controls.h"
#include "remoting/host/url_forwarder_configurator.h"
#include "remoting/protocol/capability_names.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
@ -118,6 +119,11 @@ BasicDesktopEnvironment::CreateFileOperations() {
return std::make_unique<LocalFileOperations>(ui_task_runner_);
}
std::unique_ptr<UrlForwarderConfigurator>
BasicDesktopEnvironment::CreateUrlForwarderConfigurator() {
return UrlForwarderConfigurator::Create();
}
std::string BasicDesktopEnvironment::GetCapabilities() const {
return std::string();
}

@ -44,6 +44,8 @@ class BasicDesktopEnvironment : public DesktopEnvironment {
base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback)
override;
std::unique_ptr<FileOperations> CreateFileOperations() override;
std::unique_ptr<UrlForwarderConfigurator> CreateUrlForwarderConfigurator()
override;
std::string GetCapabilities() const override;
void SetCapabilities(const std::string& capabilities) override;
uint32_t GetDesktopSessionId() const override;

@ -32,6 +32,7 @@
#include "remoting/host/remote_open_url_message_handler.h"
#include "remoting/host/screen_controls.h"
#include "remoting/host/screen_resolution.h"
#include "remoting/host/url_forwarder_configurator.h"
#include "remoting/host/url_forwarder_control_message_handler.h"
#include "remoting/proto/control.pb.h"
#include "remoting/proto/event.pb.h"
@ -909,7 +910,9 @@ void ClientSession::CreateUrlForwarderControlMessageHandler(
// UrlForwarderControlMessageHandler manages its own lifetime and is tied to
// the lifetime of |pipe|. Once |pipe| is closed, this instance will be
// cleaned up.
new UrlForwarderControlMessageHandler(channel_name, std::move(pipe));
new UrlForwarderControlMessageHandler(
desktop_environment_->CreateUrlForwarderConfigurator(), channel_name,
std::move(pipe));
}
} // namespace remoting

@ -29,6 +29,7 @@ class FileOperations;
class InputInjector;
class KeyboardLayoutMonitor;
class ScreenControls;
class UrlForwarderConfigurator;
namespace protocol {
class KeyboardLayout;
@ -53,6 +54,8 @@ class DesktopEnvironment {
base::RepeatingCallback<void(const protocol::KeyboardLayout&)>
callback) = 0;
virtual std::unique_ptr<FileOperations> CreateFileOperations() = 0;
virtual std::unique_ptr<UrlForwarderConfigurator>
CreateUrlForwarderConfigurator() = 0;
// For platforms that require the mouse cursor to be composited into the video
// stream when it is not rendered by the client, returns a composing capturer.

@ -12,6 +12,7 @@
#include "remoting/host/file_transfer/file_operations.h"
#include "remoting/host/input_injector.h"
#include "remoting/host/keyboard_layout_monitor.h"
#include "remoting/host/url_forwarder_configurator.h"
#include "remoting/proto/event.pb.h"
#include "remoting/protocol/fake_desktop_capturer.h"
@ -110,6 +111,11 @@ std::unique_ptr<FileOperations> FakeDesktopEnvironment::CreateFileOperations() {
return nullptr;
}
std::unique_ptr<UrlForwarderConfigurator>
FakeDesktopEnvironment::CreateUrlForwarderConfigurator() {
return nullptr;
}
std::string FakeDesktopEnvironment::GetCapabilities() const {
return std::string();
}

@ -103,6 +103,8 @@ class FakeDesktopEnvironment : public DesktopEnvironment {
base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback)
override;
std::unique_ptr<FileOperations> CreateFileOperations() override;
std::unique_ptr<UrlForwarderConfigurator> CreateUrlForwarderConfigurator()
override;
std::string GetCapabilities() const override;
void SetCapabilities(const std::string& capabilities) override;
uint32_t GetDesktopSessionId() const override;

@ -62,6 +62,11 @@ std::unique_ptr<FileOperations> MockDesktopEnvironment::CreateFileOperations() {
return base::WrapUnique(CreateFileOperationsPtr());
}
std::unique_ptr<UrlForwarderConfigurator>
MockDesktopEnvironment::CreateUrlForwarderConfigurator() {
return base::WrapUnique(CreateUrlForwarderConfiguratorPtr());
}
std::unique_ptr<DesktopAndCursorConditionalComposer>
MockDesktopEnvironment::CreateComposingVideoCapturer() {
return base::WrapUnique(CreateComposingVideoCapturerPtr());

@ -22,6 +22,7 @@
#include "remoting/host/screen_controls.h"
#include "remoting/host/screen_resolution.h"
#include "remoting/host/security_key/security_key_auth_handler.h"
#include "remoting/host/url_forwarder_configurator.h"
#include "remoting/proto/control.pb.h"
#include "remoting/proto/event.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
@ -51,6 +52,7 @@ class MockDesktopEnvironment : public DesktopEnvironment {
KeyboardLayoutMonitor*(
base::RepeatingCallback<void(const protocol::KeyboardLayout&)>));
MOCK_METHOD0(CreateFileOperationsPtr, FileOperations*());
MOCK_METHOD0(CreateUrlForwarderConfiguratorPtr, UrlForwarderConfigurator*());
MOCK_CONST_METHOD0(GetCapabilities, std::string());
MOCK_METHOD1(SetCapabilities, void(const std::string&));
MOCK_CONST_METHOD0(GetDesktopSessionId, uint32_t());
@ -69,6 +71,8 @@ class MockDesktopEnvironment : public DesktopEnvironment {
base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback)
override;
std::unique_ptr<FileOperations> CreateFileOperations() override;
std::unique_ptr<UrlForwarderConfigurator> CreateUrlForwarderConfigurator()
override;
std::unique_ptr<DesktopAndCursorConditionalComposer>
CreateComposingVideoCapturer() override;
};

@ -24,6 +24,7 @@
#include "remoting/host/input_injector.h"
#include "remoting/host/keyboard_layout_monitor.h"
#include "remoting/host/screen_controls.h"
#include "remoting/host/url_forwarder_configurator.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
@ -85,6 +86,12 @@ std::unique_ptr<FileOperations> IpcDesktopEnvironment::CreateFileOperations() {
return desktop_session_proxy_->CreateFileOperations();
}
std::unique_ptr<UrlForwarderConfigurator>
IpcDesktopEnvironment::CreateUrlForwarderConfigurator() {
// TODO(yuweih): Get it from |desktop_session_proxy_|.
return UrlForwarderConfigurator::Create();
}
std::string IpcDesktopEnvironment::GetCapabilities() const {
return desktop_session_proxy_->GetCapabilities();
}

@ -61,6 +61,8 @@ class IpcDesktopEnvironment : public DesktopEnvironment {
base::RepeatingCallback<void(const protocol::KeyboardLayout&)> callback)
override;
std::unique_ptr<FileOperations> CreateFileOperations() override;
std::unique_ptr<UrlForwarderConfigurator> CreateUrlForwarderConfigurator()
override;
std::string GetCapabilities() const override;
void SetCapabilities(const std::string& capabilities) override;
uint32_t GetDesktopSessionId() const override;

@ -16,7 +16,7 @@ UrlForwarderConfigurator::~UrlForwarderConfigurator() = default;
#if !defined(OS_LINUX) && !defined(OS_WIN)
// static
UrlForwarderConfigurator* UrlForwarderConfigurator::GetInstance() {
std::unique_ptr<UrlForwarderConfigurator> UrlForwarderConfigurator::Create() {
// Unsupported platforms.
NOTREACHED();
return nullptr;

@ -5,6 +5,8 @@
#ifndef REMOTING_HOST_URL_FORWARDER_CONFIGURATOR_H_
#define REMOTING_HOST_URL_FORWARDER_CONFIGURATOR_H_
#include <memory>
#include "base/callback.h"
#include "remoting/proto/url_forwarder_control.pb.h"
@ -14,24 +16,31 @@ namespace remoting {
// default browser of the OS).
class UrlForwarderConfigurator {
public:
using SetUpUrlForwarderResponse =
protocol::UrlForwarderControl::SetUpUrlForwarderResponse;
using IsUrlForwarderSetUpCallback = base::OnceCallback<void(bool)>;
using SetUpUrlForwarderCallback = base::RepeatingCallback<void(
protocol::UrlForwarderControl::SetUpUrlForwarderResponse::State)>;
using SetUpUrlForwarderCallback =
base::RepeatingCallback<void(SetUpUrlForwarderResponse::State)>;
static UrlForwarderConfigurator* GetInstance();
static std::unique_ptr<UrlForwarderConfigurator> Create();
virtual ~UrlForwarderConfigurator();
// Runs |callback| with a boolean indicating whether the URL forwarder has
// been properly set up.
// NOTE: |callback| may be called after |this| is destroyed. Make sure your
// callback can handle it.
virtual void IsUrlForwarderSetUp(IsUrlForwarderSetUpCallback callback) = 0;
// Sets the URL forwarder as the default browser; calls |callback| with any
// state changes during the setup process. |callback| may be called multiple
// times until the final state (either COMPLETE or ERROR) is reached.
// NOTE: |callback| may be called after |this| is destroyed. Make sure your
// callback can handle it.
virtual void SetUpUrlForwarder(const SetUpUrlForwarderCallback& callback) = 0;
protected:
UrlForwarderConfigurator();
virtual ~UrlForwarderConfigurator();
};
} // namespace remoting

@ -4,11 +4,12 @@
#include "remoting/host/url_forwarder_configurator_linux.h"
#include <memory>
#include "base/base_paths.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/task/thread_pool.h"
@ -42,7 +43,7 @@ SetUpForwarderAndGetResponseState() {
return ExecuteConfigScriptWithSwitch("setup")
? protocol::UrlForwarderControl::SetUpUrlForwarderResponse::
COMPLETE
: protocol::UrlForwarderControl::SetUpUrlForwarderResponse::ERROR;
: protocol::UrlForwarderControl::SetUpUrlForwarderResponse::FAILED;
}
} // namespace
@ -68,9 +69,8 @@ void UrlForwarderConfiguratorLinux::SetUpUrlForwarder(
}
// static
UrlForwarderConfigurator* UrlForwarderConfigurator::GetInstance() {
static base::NoDestructor<UrlForwarderConfiguratorLinux> instance;
return instance.get();
std::unique_ptr<UrlForwarderConfigurator> UrlForwarderConfigurator::Create() {
return std::make_unique<UrlForwarderConfiguratorLinux>();
}
} // namespace remoting

@ -15,6 +15,7 @@ namespace remoting {
class UrlForwarderConfiguratorLinux final : public UrlForwarderConfigurator {
public:
UrlForwarderConfiguratorLinux();
~UrlForwarderConfiguratorLinux() override;
void IsUrlForwarderSetUp(IsUrlForwarderSetUpCallback callback) override;
void SetUpUrlForwarder(const SetUpUrlForwarderCallback& callback) override;
@ -24,8 +25,6 @@ class UrlForwarderConfiguratorLinux final : public UrlForwarderConfigurator {
const UrlForwarderConfiguratorLinux&) = delete;
private:
~UrlForwarderConfiguratorLinux() override;
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
};

@ -4,32 +4,138 @@
#include "remoting/host/url_forwarder_configurator_win.h"
#include <windows.h>
#include <wtsapi32.h>
#include <memory>
#include <string>
#include "base/base_paths.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/sequence_checker.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/win/scoped_handle.h"
#include "remoting/host/switches.h"
namespace remoting {
UrlForwarderConfiguratorWin::UrlForwarderConfiguratorWin() = default;
namespace {
UrlForwarderConfiguratorWin::~UrlForwarderConfiguratorWin() = default;
// If the user has already changed the default browser to the URL forwarder,
// then the setup process will finish immediately without showing any UI, so we
// delay reporting USER_INTERVENTION_REQUIRED so that the client doesn't pop up
// a toast when it's unnecessary.
constexpr base::TimeDelta kReportUserInterventionRequiredDelay =
base::TimeDelta::FromMilliseconds(500);
base::win::ScopedHandle GetCurrentUserToken() {
HANDLE user_token = nullptr;
if (!WTSQueryUserToken(WTS_CURRENT_SESSION, &user_token)) {
PLOG(ERROR) << "Failed to get current user token";
return base::win::ScopedHandle();
}
return base::win::ScopedHandle(user_token);
}
// If |switch_name| is empty, the process will be launched with no extra
// switches.
bool LaunchConfiguratorProcess(const std::string& switch_name = std::string()) {
base::LaunchOptions launch_options;
auto current_user = GetCurrentUserToken();
if (!current_user.IsValid()) {
return false;
}
launch_options.as_user = current_user.Get();
// The remoting_desktop.exe binary (where this code runs) has extra manifest
// flags (uiAccess and requireAdministrator) that are undesirable for the
// url_forwarder_configurator child process, so remoting_host.exe is used
// instead.
base::FilePath path;
if (!base::PathService::Get(base::DIR_EXE, &path)) {
LOG(ERROR) << "Failed to get executable path.";
return false;
}
path = path.AppendASCII("remoting_host.exe");
base::CommandLine command(path);
command.AppendSwitchASCII(kProcessTypeSwitchName,
kProcessTypeUrlForwarderConfigurator);
if (!switch_name.empty()) {
command.AppendSwitch(switch_name);
}
int exit_code = -1;
base::LaunchProcess(command, launch_options).WaitForExit(&exit_code);
return exit_code == 0;
}
} // namespace
UrlForwarderConfiguratorWin::UrlForwarderConfiguratorWin()
: io_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::WithBaseSyncPrimitives()})) {}
UrlForwarderConfiguratorWin::~UrlForwarderConfiguratorWin() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void UrlForwarderConfiguratorWin::IsUrlForwarderSetUp(
IsUrlForwarderSetUpCallback callback) {
NOTIMPLEMENTED();
std::move(callback).Run(true);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
io_task_runner_->PostTaskAndReplyWithResult(
FROM_HERE, base::BindOnce(&LaunchConfiguratorProcess, std::string()),
std::move(callback));
}
void UrlForwarderConfiguratorWin::SetUpUrlForwarder(
const SetUpUrlForwarderCallback& callback) {
NOTIMPLEMENTED();
callback.Run(
protocol::UrlForwarderControl::SetUpUrlForwarderResponse::COMPLETE);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (set_up_url_forwarder_callback_) {
LOG(ERROR) << "Setup is already in progress.";
callback.Run(SetUpUrlForwarderResponse::FAILED);
return;
}
set_up_url_forwarder_callback_ = callback;
report_user_intervention_required_timer_.Start(
FROM_HERE, kReportUserInterventionRequiredDelay, this,
&UrlForwarderConfiguratorWin::OnReportUserInterventionRequired);
io_task_runner_->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&LaunchConfiguratorProcess, kSetUpUrlForwarderSwitchName),
base::BindOnce(&UrlForwarderConfiguratorWin::OnSetUpResponse,
weak_factory_.GetWeakPtr()));
}
void UrlForwarderConfiguratorWin::OnSetUpResponse(bool success) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
report_user_intervention_required_timer_.AbandonAndStop();
set_up_url_forwarder_callback_.Run(success
? SetUpUrlForwarderResponse::COMPLETE
: SetUpUrlForwarderResponse::FAILED);
set_up_url_forwarder_callback_.Reset();
}
void UrlForwarderConfiguratorWin::OnReportUserInterventionRequired() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
set_up_url_forwarder_callback_.Run(
SetUpUrlForwarderResponse::USER_INTERVENTION_REQUIRED);
}
// static
UrlForwarderConfigurator* UrlForwarderConfigurator::GetInstance() {
static base::NoDestructor<UrlForwarderConfiguratorWin> instance;
return instance.get();
std::unique_ptr<UrlForwarderConfigurator> UrlForwarderConfigurator::Create() {
return std::make_unique<UrlForwarderConfiguratorWin>();
}
} // namespace remoting

@ -5,14 +5,22 @@
#ifndef REMOTING_HOST_URL_FORWARDER_CONFIGURATOR_WIN_H_
#define REMOTING_HOST_URL_FORWARDER_CONFIGURATOR_WIN_H_
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "base/thread_annotations.h"
#include "base/timer/timer.h"
#include "remoting/host/url_forwarder_configurator.h"
namespace remoting {
// Windows implementation of UrlForwarderConfigurator.
// Note that this class requires elevated privileges.
class UrlForwarderConfiguratorWin final : public UrlForwarderConfigurator {
public:
UrlForwarderConfiguratorWin();
~UrlForwarderConfiguratorWin() override;
void IsUrlForwarderSetUp(IsUrlForwarderSetUpCallback callback) override;
void SetUpUrlForwarder(const SetUpUrlForwarderCallback& callback) override;
@ -22,7 +30,18 @@ class UrlForwarderConfiguratorWin final : public UrlForwarderConfigurator {
delete;
private:
~UrlForwarderConfiguratorWin() override;
void OnSetUpResponse(bool success);
void OnReportUserInterventionRequired();
SEQUENCE_CHECKER(sequence_checker_);
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
SetUpUrlForwarderCallback set_up_url_forwarder_callback_
GUARDED_BY_CONTEXT(sequence_checker_);
base::OneShotTimer report_user_intervention_required_timer_
GUARDED_BY_CONTEXT(sequence_checker_);
base::WeakPtrFactory<UrlForwarderConfiguratorWin> weak_factory_{this};
};
} // namespace remoting

@ -17,9 +17,11 @@ namespace remoting {
constexpr char UrlForwarderControlMessageHandler::kDataChannelName[];
UrlForwarderControlMessageHandler::UrlForwarderControlMessageHandler(
std::unique_ptr<UrlForwarderConfigurator> url_forwarder_configurator,
const std::string& name,
std::unique_ptr<protocol::MessagePipe> pipe)
: protocol::NamedMessagePipeHandler(name, std::move(pipe)) {
: protocol::NamedMessagePipeHandler(name, std::move(pipe)),
url_forwarder_configurator_(std::move(url_forwarder_configurator)) {
DCHECK_EQ(kDataChannelName, name);
}
@ -35,14 +37,13 @@ void UrlForwarderControlMessageHandler::OnIncomingMessage(
auto url_forwarder_config =
protocol::ParseMessage<protocol::UrlForwarderControl>(message.get());
if (url_forwarder_config->has_query_config_state_request()) {
UrlForwarderConfigurator::GetInstance()->IsUrlForwarderSetUp(base::BindOnce(
url_forwarder_configurator_->IsUrlForwarderSetUp(base::BindOnce(
&UrlForwarderControlMessageHandler::OnIsUrlForwarderSetUpResult,
weak_factory_.GetWeakPtr()));
} else if (url_forwarder_config->has_set_up_url_forwarder_request()) {
UrlForwarderConfigurator::GetInstance()->SetUpUrlForwarder(
base::BindRepeating(
&UrlForwarderControlMessageHandler::OnSetUpUrlForwarderResult,
weak_factory_.GetWeakPtr()));
url_forwarder_configurator_->SetUpUrlForwarder(base::BindRepeating(
&UrlForwarderControlMessageHandler::OnSetUpUrlForwarderResult,
weak_factory_.GetWeakPtr()));
} else {
LOG(ERROR) << "Unrecognized UrlForwarderControl message.";
}

@ -7,11 +7,15 @@
#include "remoting/protocol/named_message_pipe_handler.h"
#include <memory>
#include "base/memory/weak_ptr.h"
#include "remoting/proto/url_forwarder_control.pb.h"
namespace remoting {
class UrlForwarderConfigurator;
// Message handler for the url-forwarder-control data channel.
class UrlForwarderControlMessageHandler final
: public protocol::NamedMessagePipeHandler {
@ -19,6 +23,7 @@ class UrlForwarderControlMessageHandler final
static constexpr char kDataChannelName[] = "url-forwarder-control";
UrlForwarderControlMessageHandler(
std::unique_ptr<UrlForwarderConfigurator> url_forwarder_configurator,
const std::string& name,
std::unique_ptr<protocol::MessagePipe> pipe);
~UrlForwarderControlMessageHandler() override;
@ -38,6 +43,8 @@ class UrlForwarderControlMessageHandler final
void OnSetUpUrlForwarderResult(
protocol::UrlForwarderControl::SetUpUrlForwarderResponse::State state);
std::unique_ptr<UrlForwarderConfigurator> url_forwarder_configurator_;
base::WeakPtrFactory<UrlForwarderControlMessageHandler> weak_factory_{this};
};

@ -41,7 +41,7 @@ message UrlForwarderControl {
COMPLETE = 1;
// The setup process has failed.
ERROR = 2;
FAILED = 2;
// The setup process requires user intervention. The host will send
// another SetUpUrlForwarderResponse once the setup process becomes