Home | History | Annotate | Download | only in cloud_print
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
      6 
      7 #include <stack>
      8 #include <vector>
      9 
     10 #include "base/bind.h"
     11 #include "base/bind_helpers.h"
     12 #include "base/command_line.h"
     13 #include "base/file_util.h"
     14 #include "base/json/json_reader.h"
     15 #include "base/message_loop/message_loop.h"
     16 #include "base/metrics/histogram.h"
     17 #include "base/prefs/pref_service.h"
     18 #include "base/strings/utf_string_conversions.h"
     19 #include "chrome/browser/browser_process.h"
     20 #include "chrome/browser/chrome_notification_types.h"
     21 #include "chrome/browser/lifetime/application_lifetime.h"
     22 #include "chrome/browser/notifications/desktop_notification_service.h"
     23 #include "chrome/browser/notifications/notification.h"
     24 #include "chrome/browser/notifications/notification_ui_manager.h"
     25 #include "chrome/browser/profiles/profile.h"
     26 #include "chrome/browser/service_process/service_process_control.h"
     27 #include "chrome/common/chrome_switches.h"
     28 #include "chrome/common/cloud_print/cloud_print_proxy_info.h"
     29 #include "chrome/common/pref_names.h"
     30 #include "chrome/common/service_messages.h"
     31 #include "content/public/browser/browser_thread.h"
     32 #include "grit/generated_resources.h"
     33 #include "printing/backend/print_backend.h"
     34 #include "ui/base/l10n/l10n_util.h"
     35 
     36 using content::BrowserThread;
     37 
     38 CloudPrintProxyService::CloudPrintProxyService(Profile* profile)
     39     : profile_(profile),
     40       weak_factory_(this),
     41       enforcing_connector_policy_(false) {
     42 }
     43 
     44 CloudPrintProxyService::~CloudPrintProxyService() {
     45 }
     46 
     47 void CloudPrintProxyService::Initialize() {
     48   DCHECK_CURRENTLY_ON(BrowserThread::UI);
     49   UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
     50                             ServiceProcessControl::SERVICE_EVENT_INITIALIZE,
     51                             ServiceProcessControl::SERVICE_EVENT_MAX);
     52   if (profile_->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
     53       (!profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty() ||
     54        !profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled))) {
     55     // If the cloud print proxy is enabled, or the policy preventing it from
     56     // being enabled is set, establish a channel with the service process and
     57     // update the status. This will check the policy when the status is sent
     58     // back.
     59     UMA_HISTOGRAM_ENUMERATION(
     60         "CloudPrint.ServiceEvents",
     61         ServiceProcessControl::SERVICE_EVENT_ENABLED_ON_LAUNCH,
     62         ServiceProcessControl::SERVICE_EVENT_MAX);
     63     RefreshStatusFromService();
     64   }
     65 
     66   pref_change_registrar_.Init(profile_->GetPrefs());
     67   pref_change_registrar_.Add(
     68       prefs::kCloudPrintProxyEnabled,
     69       base::Bind(
     70           base::IgnoreResult(
     71               &CloudPrintProxyService::ApplyCloudPrintConnectorPolicy),
     72           base::Unretained(this)));
     73 }
     74 
     75 void CloudPrintProxyService::RefreshStatusFromService() {
     76   DCHECK_CURRENTLY_ON(BrowserThread::UI);
     77   InvokeServiceTask(
     78       base::Bind(&CloudPrintProxyService::RefreshCloudPrintProxyStatus,
     79                  weak_factory_.GetWeakPtr()));
     80 }
     81 
     82 bool CloudPrintProxyService::EnforceCloudPrintConnectorPolicyAndQuit() {
     83   DCHECK_CURRENTLY_ON(BrowserThread::UI);
     84   enforcing_connector_policy_ = true;
     85   if (ApplyCloudPrintConnectorPolicy())
     86     return true;
     87   return false;
     88 }
     89 
     90 void CloudPrintProxyService::EnableForUserWithRobot(
     91     const std::string& robot_auth_code,
     92     const std::string& robot_email,
     93     const std::string& user_email,
     94     const base::DictionaryValue& user_preferences) {
     95   DCHECK_CURRENTLY_ON(BrowserThread::UI);
     96   UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
     97                             ServiceProcessControl::SERVICE_EVENT_ENABLE,
     98                             ServiceProcessControl::SERVICE_EVENT_MAX);
     99   if (profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
    100     InvokeServiceTask(
    101         base::Bind(&CloudPrintProxyService::EnableCloudPrintProxyWithRobot,
    102                    weak_factory_.GetWeakPtr(), robot_auth_code, robot_email,
    103                    user_email, base::Owned(user_preferences.DeepCopy())));
    104   }
    105 }
    106 
    107 void CloudPrintProxyService::DisableForUser() {
    108   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    109   UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
    110                             ServiceProcessControl::SERVICE_EVENT_DISABLE,
    111                             ServiceProcessControl::SERVICE_EVENT_MAX);
    112   InvokeServiceTask(
    113       base::Bind(&CloudPrintProxyService::DisableCloudPrintProxy,
    114                  weak_factory_.GetWeakPtr()));
    115 }
    116 
    117 bool CloudPrintProxyService::ApplyCloudPrintConnectorPolicy() {
    118   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    119   if (!profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
    120     std::string email =
    121         profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail);
    122     if (!email.empty()) {
    123       UMA_HISTOGRAM_ENUMERATION(
    124           "CloudPrint.ServiceEvents",
    125           ServiceProcessControl::SERVICE_EVENT_DISABLE_BY_POLICY,
    126           ServiceProcessControl::SERVICE_EVENT_MAX);
    127       DisableForUser();
    128       profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
    129       if (enforcing_connector_policy_) {
    130         base::MessageLoop::current()->PostTask(
    131             FROM_HERE,
    132             base::Bind(&CloudPrintProxyService::RefreshCloudPrintProxyStatus,
    133                        weak_factory_.GetWeakPtr()));
    134       }
    135       return false;
    136     } else if (enforcing_connector_policy_) {
    137       base::MessageLoop::current()->PostTask(FROM_HERE,
    138                                              base::MessageLoop::QuitClosure());
    139     }
    140   }
    141   return true;
    142 }
    143 
    144 void CloudPrintProxyService::GetPrinters(const PrintersCallback& callback) {
    145   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    146   if (!profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled))
    147     return;
    148 
    149   base::FilePath list_path(
    150       CommandLine::ForCurrentProcess()->GetSwitchValuePath(
    151           switches::kCloudPrintSetupProxy));
    152   if (!list_path.empty()) {
    153     std::string printers_json;
    154     base::ReadFileToString(list_path, &printers_json);
    155     scoped_ptr<base::Value> value(base::JSONReader::Read(printers_json));
    156     base::ListValue* list = NULL;
    157     std::vector<std::string> printers;
    158     if (value && value->GetAsList(&list) && list) {
    159       for (size_t i = 0; i < list->GetSize(); ++i) {
    160         std::string printer;
    161         if (list->GetString(i, &printer))
    162           printers.push_back(printer);
    163       }
    164     }
    165     UMA_HISTOGRAM_COUNTS_10000("CloudPrint.AvailablePrintersList",
    166                                printers.size());
    167     base::MessageLoop::current()->PostTask(FROM_HERE,
    168                                            base::Bind(callback, printers));
    169   } else {
    170     InvokeServiceTask(
    171         base::Bind(&CloudPrintProxyService::GetCloudPrintProxyPrinters,
    172                    weak_factory_.GetWeakPtr(),
    173                    callback));
    174   }
    175 }
    176 
    177 void CloudPrintProxyService::GetCloudPrintProxyPrinters(
    178     const PrintersCallback& callback) {
    179   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    180   ServiceProcessControl* process_control = GetServiceProcessControl();
    181   DCHECK(process_control->IsConnected());
    182   process_control->GetPrinters(callback);
    183 }
    184 
    185 void CloudPrintProxyService::RefreshCloudPrintProxyStatus() {
    186   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    187   ServiceProcessControl* process_control = GetServiceProcessControl();
    188   DCHECK(process_control->IsConnected());
    189   ServiceProcessControl::CloudPrintProxyInfoCallback callback = base::Bind(
    190       &CloudPrintProxyService::ProxyInfoCallback, base::Unretained(this));
    191   process_control->GetCloudPrintProxyInfo(callback);
    192 }
    193 
    194 void CloudPrintProxyService::EnableCloudPrintProxyWithRobot(
    195     const std::string& robot_auth_code,
    196     const std::string& robot_email,
    197     const std::string& user_email,
    198     const base::DictionaryValue* user_preferences) {
    199   ServiceProcessControl* process_control = GetServiceProcessControl();
    200   DCHECK(process_control->IsConnected());
    201   process_control->Send(
    202       new ServiceMsg_EnableCloudPrintProxyWithRobot(
    203           robot_auth_code, robot_email, user_email, *user_preferences));
    204   // Assume the IPC worked.
    205   profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, user_email);
    206 }
    207 
    208 void CloudPrintProxyService::DisableCloudPrintProxy() {
    209   ServiceProcessControl* process_control = GetServiceProcessControl();
    210   DCHECK(process_control->IsConnected());
    211   process_control->Send(new ServiceMsg_DisableCloudPrintProxy);
    212   // Assume the IPC worked.
    213   profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
    214 }
    215 
    216 void CloudPrintProxyService::ProxyInfoCallback(
    217     const cloud_print::CloudPrintProxyInfo& proxy_info) {
    218   proxy_id_ = proxy_info.proxy_id;
    219   profile_->GetPrefs()->SetString(
    220       prefs::kCloudPrintEmail,
    221       proxy_info.enabled ? proxy_info.email : std::string());
    222   ApplyCloudPrintConnectorPolicy();
    223 }
    224 
    225 bool CloudPrintProxyService::InvokeServiceTask(const base::Closure& task) {
    226   GetServiceProcessControl()->Launch(task, base::Closure());
    227   return true;
    228 }
    229 
    230 ServiceProcessControl* CloudPrintProxyService::GetServiceProcessControl() {
    231   return ServiceProcessControl::GetInstance();
    232 }
    233