blob: e654fd2d4098e46296eb02955e0dc730ecb69cb1 [file] [log] [blame]
// Copyright 2013 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/host/setup/daemon_controller.h"
#include <utility>
#include "base/bind.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "build/build_config.h"
#include "remoting/base/auto_thread.h"
#include "remoting/base/auto_thread_task_runner.h"
namespace remoting {
// Name of the Daemon Controller's worker thread.
const char kDaemonControllerThreadName[] = "Daemon Controller thread";
DaemonController::DaemonController(std::unique_ptr<Delegate> delegate)
: caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
delegate_(std::move(delegate)) {
// Launch the delegate thread.
delegate_thread_.reset(new AutoThread(kDaemonControllerThreadName));
#if defined(OS_WIN)
delegate_thread_->SetComInitType(AutoThread::COM_INIT_STA);
delegate_task_runner_ =
delegate_thread_->StartWithType(base::MessageLoop::TYPE_UI);
#else
delegate_task_runner_ =
delegate_thread_->StartWithType(base::MessageLoop::TYPE_DEFAULT);
#endif
}
DaemonController::State DaemonController::GetState() {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
return delegate_->GetState();
}
void DaemonController::GetConfig(const GetConfigCallback& done) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
DaemonController::GetConfigCallback wrapped_done = base::Bind(
&DaemonController::InvokeConfigCallbackAndScheduleNext, this, done);
base::Closure request = base::Bind(
&DaemonController::DoGetConfig, this, wrapped_done);
ServiceOrQueueRequest(request);
}
void DaemonController::SetConfigAndStart(
std::unique_ptr<base::DictionaryValue> config,
bool consent,
const CompletionCallback& done) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
DaemonController::CompletionCallback wrapped_done = base::Bind(
&DaemonController::InvokeCompletionCallbackAndScheduleNext, this, done);
base::Closure request = base::Bind(
&DaemonController::DoSetConfigAndStart, this, base::Passed(&config),
consent, wrapped_done);
ServiceOrQueueRequest(request);
}
void DaemonController::UpdateConfig(
std::unique_ptr<base::DictionaryValue> config,
const CompletionCallback& done) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
DaemonController::CompletionCallback wrapped_done = base::Bind(
&DaemonController::InvokeCompletionCallbackAndScheduleNext, this, done);
base::Closure request = base::Bind(
&DaemonController::DoUpdateConfig, this, base::Passed(&config),
wrapped_done);
ServiceOrQueueRequest(request);
}
void DaemonController::Stop(const CompletionCallback& done) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
DaemonController::CompletionCallback wrapped_done = base::Bind(
&DaemonController::InvokeCompletionCallbackAndScheduleNext, this, done);
base::Closure request = base::Bind(
&DaemonController::DoStop, this, wrapped_done);
ServiceOrQueueRequest(request);
}
void DaemonController::GetUsageStatsConsent(
const GetUsageStatsConsentCallback& done) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
DaemonController::GetUsageStatsConsentCallback wrapped_done = base::Bind(
&DaemonController::InvokeConsentCallbackAndScheduleNext, this, done);
base::Closure request = base::Bind(
&DaemonController::DoGetUsageStatsConsent, this, wrapped_done);
ServiceOrQueueRequest(request);
}
DaemonController::~DaemonController() {
// Make sure |delegate_| is deleted on the background thread.
delegate_task_runner_->DeleteSoon(FROM_HERE, delegate_.release());
// Stop the thread.
delegate_task_runner_ = nullptr;
caller_task_runner_->DeleteSoon(FROM_HERE, delegate_thread_.release());
}
void DaemonController::DoGetConfig(const GetConfigCallback& done) {
DCHECK(delegate_task_runner_->BelongsToCurrentThread());
std::unique_ptr<base::DictionaryValue> config = delegate_->GetConfig();
caller_task_runner_->PostTask(FROM_HERE,
base::BindOnce(done, std::move(config)));
}
void DaemonController::DoSetConfigAndStart(
std::unique_ptr<base::DictionaryValue> config,
bool consent,
const CompletionCallback& done) {
DCHECK(delegate_task_runner_->BelongsToCurrentThread());
delegate_->SetConfigAndStart(std::move(config), consent, done);
}
void DaemonController::DoUpdateConfig(
std::unique_ptr<base::DictionaryValue> config,
const CompletionCallback& done) {
DCHECK(delegate_task_runner_->BelongsToCurrentThread());
delegate_->UpdateConfig(std::move(config), done);
}
void DaemonController::DoStop(const CompletionCallback& done) {
DCHECK(delegate_task_runner_->BelongsToCurrentThread());
delegate_->Stop(done);
}
void DaemonController::DoGetUsageStatsConsent(
const GetUsageStatsConsentCallback& done) {
DCHECK(delegate_task_runner_->BelongsToCurrentThread());
DaemonController::UsageStatsConsent consent =
delegate_->GetUsageStatsConsent();
caller_task_runner_->PostTask(FROM_HERE, base::BindOnce(done, consent));
}
void DaemonController::InvokeCompletionCallbackAndScheduleNext(
const CompletionCallback& done,
AsyncResult result) {
if (!caller_task_runner_->BelongsToCurrentThread()) {
caller_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&DaemonController::InvokeCompletionCallbackAndScheduleNext, this,
done, result));
return;
}
done.Run(result);
ScheduleNext();
}
void DaemonController::InvokeConfigCallbackAndScheduleNext(
const GetConfigCallback& done,
std::unique_ptr<base::DictionaryValue> config) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
done.Run(std::move(config));
ScheduleNext();
}
void DaemonController::InvokeConsentCallbackAndScheduleNext(
const GetUsageStatsConsentCallback& done,
const UsageStatsConsent& consent) {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
done.Run(consent);
ScheduleNext();
}
void DaemonController::ScheduleNext() {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
pending_requests_.pop();
ServiceNextRequest();
}
void DaemonController::ServiceOrQueueRequest(const base::Closure& request) {
bool servicing_request = !pending_requests_.empty();
pending_requests_.push(request);
if (!servicing_request)
ServiceNextRequest();
}
void DaemonController::ServiceNextRequest() {
if (!pending_requests_.empty())
delegate_task_runner_->PostTask(FROM_HERE, pending_requests_.front());
}
} // namespace remoting