blob: 7190c49f2b3c339493198760872afbf47e1505d4 [file] [log] [blame]
// 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.
#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
#include <stddef.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/service_process/service_process_control.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_file_task_runner.h"
using content::BrowserThread;
namespace {
void ForwardGetPrintersResult(CloudPrintProxyService::PrintersCallback callback,
const std::vector<std::string>& printers) {
UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
ServiceProcessControl::SERVICE_PRINTERS_REPLY,
ServiceProcessControl::SERVICE_EVENT_MAX);
UMA_HISTOGRAM_COUNTS_10000("CloudPrint.AvailablePrinters", printers.size());
std::move(callback).Run(printers);
}
std::string ReadCloudPrintSetupProxyList(const base::FilePath& path) {
std::string printers_json;
base::ReadFileToString(path, &printers_json);
return printers_json;
}
} // namespace
CloudPrintProxyService::CloudPrintProxyService(Profile* profile)
: profile_(profile),
weak_factory_(this) {
}
CloudPrintProxyService::~CloudPrintProxyService() {
}
void CloudPrintProxyService::Initialize() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
ServiceProcessControl::SERVICE_EVENT_INITIALIZE,
ServiceProcessControl::SERVICE_EVENT_MAX);
if (profile_->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
(!profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty() ||
!profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled))) {
// If the cloud print proxy is enabled, or the policy preventing it from
// being enabled is set, establish a channel with the service process and
// update the status. This will check the policy when the status is sent
// back.
UMA_HISTOGRAM_ENUMERATION(
"CloudPrint.ServiceEvents",
ServiceProcessControl::SERVICE_EVENT_ENABLED_ON_LAUNCH,
ServiceProcessControl::SERVICE_EVENT_MAX);
RefreshStatusFromService();
}
pref_change_registrar_.Init(profile_->GetPrefs());
pref_change_registrar_.Add(
prefs::kCloudPrintProxyEnabled,
base::Bind(
base::IgnoreResult(
&CloudPrintProxyService::ApplyCloudPrintConnectorPolicy),
base::Unretained(this)));
}
void CloudPrintProxyService::RefreshStatusFromService() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
InvokeServiceTask(
base::Bind(&CloudPrintProxyService::RefreshCloudPrintProxyStatus,
weak_factory_.GetWeakPtr()));
}
void CloudPrintProxyService::EnableForUserWithRobot(
const std::string& robot_auth_code,
const std::string& robot_email,
const std::string& user_email,
base::Value user_preferences) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
ServiceProcessControl::SERVICE_EVENT_ENABLE,
ServiceProcessControl::SERVICE_EVENT_MAX);
if (profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
InvokeServiceTask(
base::BindOnce(&CloudPrintProxyService::EnableCloudPrintProxyWithRobot,
weak_factory_.GetWeakPtr(), robot_auth_code, robot_email,
user_email, std::move(user_preferences)));
}
}
void CloudPrintProxyService::DisableForUser() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
ServiceProcessControl::SERVICE_EVENT_DISABLE,
ServiceProcessControl::SERVICE_EVENT_MAX);
InvokeServiceTask(
base::Bind(&CloudPrintProxyService::DisableCloudPrintProxy,
weak_factory_.GetWeakPtr()));
}
bool CloudPrintProxyService::ApplyCloudPrintConnectorPolicy() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
std::string email =
profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail);
if (!email.empty()) {
UMA_HISTOGRAM_ENUMERATION(
"CloudPrint.ServiceEvents",
ServiceProcessControl::SERVICE_EVENT_DISABLE_BY_POLICY,
ServiceProcessControl::SERVICE_EVENT_MAX);
DisableForUser();
profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
return false;
}
}
return true;
}
void CloudPrintProxyService::GetPrinters(PrintersCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), std::vector<std::string>()));
return;
}
base::FilePath list_path(
base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kCloudPrintSetupProxy));
if (list_path.empty()) {
InvokeServiceTask(
base::BindOnce(&CloudPrintProxyService::GetCloudPrintProxyPrinters,
weak_factory_.GetWeakPtr(), std::move(callback)));
return;
}
base::PostTaskAndReplyWithResult(
extensions::GetExtensionFileTaskRunner().get(), FROM_HERE,
base::BindOnce(&ReadCloudPrintSetupProxyList, list_path),
base::BindOnce(&CloudPrintProxyService::OnReadCloudPrintSetupProxyList,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void CloudPrintProxyService::GetCloudPrintProxyPrinters(
PrintersCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
ServiceProcessControl::SERVICE_PRINTERS_REQUEST,
ServiceProcessControl::SERVICE_EVENT_MAX);
ServiceProcessControl* process_control = GetServiceProcessControl();
DCHECK(process_control->IsConnected());
GetCloudPrintProxy().GetPrinters(
base::BindOnce(&ForwardGetPrintersResult, std::move(callback)));
}
void CloudPrintProxyService::RefreshCloudPrintProxyStatus() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
ServiceProcessControl::SERVICE_EVENT_INFO_REQUEST,
ServiceProcessControl::SERVICE_EVENT_MAX);
ServiceProcessControl* process_control = GetServiceProcessControl();
DCHECK(process_control->IsConnected());
auto callback = base::BindOnce(&CloudPrintProxyService::ProxyInfoCallback,
base::Unretained(this));
GetCloudPrintProxy().GetCloudPrintProxyInfo(std::move(callback));
}
void CloudPrintProxyService::EnableCloudPrintProxyWithRobot(
const std::string& robot_auth_code,
const std::string& robot_email,
const std::string& user_email,
base::Value user_preferences) {
ServiceProcessControl* process_control = GetServiceProcessControl();
DCHECK(process_control->IsConnected());
GetCloudPrintProxy().EnableCloudPrintProxyWithRobot(
robot_auth_code, robot_email, user_email, std::move(user_preferences));
// Assume the IPC worked.
profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, user_email);
}
void CloudPrintProxyService::DisableCloudPrintProxy() {
ServiceProcessControl* process_control = GetServiceProcessControl();
DCHECK(process_control->IsConnected());
GetCloudPrintProxy().DisableCloudPrintProxy();
// Assume the IPC worked.
profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
}
void CloudPrintProxyService::ProxyInfoCallback(bool enabled,
const std::string& email,
const std::string& proxy_id) {
UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
ServiceProcessControl::SERVICE_EVENT_INFO_REPLY,
ServiceProcessControl::SERVICE_EVENT_MAX);
proxy_id_ = proxy_id;
profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail,
enabled ? email : std::string());
ApplyCloudPrintConnectorPolicy();
}
bool CloudPrintProxyService::InvokeServiceTask(base::OnceClosure task) {
GetServiceProcessControl()->Launch(std::move(task), base::OnceClosure());
return true;
}
ServiceProcessControl* CloudPrintProxyService::GetServiceProcessControl() {
return ServiceProcessControl::GetInstance();
}
cloud_print::mojom::CloudPrint& CloudPrintProxyService::GetCloudPrintProxy() {
if (!cloud_print_proxy_ || cloud_print_proxy_.encountered_error()) {
GetServiceProcessControl()->remote_interfaces().GetInterface(
&cloud_print_proxy_);
}
return *cloud_print_proxy_;
}
void CloudPrintProxyService::OnReadCloudPrintSetupProxyList(
PrintersCallback callback,
const std::string& printers_json) {
std::unique_ptr<base::Value> list_value =
base::ListValue::From(base::JSONReader::Read(printers_json));
std::vector<std::string> printers;
if (list_value) {
for (const auto& element : list_value->GetList()) {
if (element.is_string())
printers.push_back(element.GetString());
}
}
UMA_HISTOGRAM_COUNTS_10000("CloudPrint.AvailablePrintersList",
printers.size());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), printers));
}