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   UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
     49                             ServiceProcessControl::SERVICE_EVENT_INITIALIZE,
     50                             ServiceProcessControl::SERVICE_EVENT_MAX);
     51   if (profile_->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
     52       (!profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty() ||
     53        !profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled))) {
     54     // If the cloud print proxy is enabled, or the policy preventing it from
     55     // being enabled is set, establish a channel with the service process and
     56     // update the status. This will check the policy when the status is sent
     57     // back.
     58     UMA_HISTOGRAM_ENUMERATION(
     59         "CloudPrint.ServiceEvents",
     60         ServiceProcessControl::SERVICE_EVENT_ENABLED_ON_LAUNCH,
     61         ServiceProcessControl::SERVICE_EVENT_MAX);
     62     RefreshStatusFromService();
     63   }
     64 
     65   pref_change_registrar_.Init(profile_->GetPrefs());
     66   pref_change_registrar_.Add(
     67       prefs::kCloudPrintProxyEnabled,
     68       base::Bind(
     69           base::IgnoreResult(
     70               &CloudPrintProxyService::ApplyCloudPrintConnectorPolicy),
     71           base::Unretained(this)));
     72 }
     73 
     74 void CloudPrintProxyService::RefreshStatusFromService() {
     75   InvokeServiceTask(
     76       base::Bind(&CloudPrintProxyService::RefreshCloudPrintProxyStatus,
     77                  weak_factory_.GetWeakPtr()));
     78 }
     79 
     80 bool CloudPrintProxyService::EnforceCloudPrintConnectorPolicyAndQuit() {
     81   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     82   enforcing_connector_policy_ = true;
     83   if (ApplyCloudPrintConnectorPolicy())
     84     return true;
     85   return false;
     86 }
     87 
     88 void CloudPrintProxyService::EnableForUserWithRobot(
     89     const std::string& robot_auth_code,
     90     const std::string& robot_email,
     91     const std::string& user_email,
     92     const base::DictionaryValue& user_preferences) {
     93   UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
     94                             ServiceProcessControl::SERVICE_EVENT_ENABLE,
     95                             ServiceProcessControl::SERVICE_EVENT_MAX);
     96   if (profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
     97     InvokeServiceTask(
     98         base::Bind(&CloudPrintProxyService::EnableCloudPrintProxyWithRobot,
     99                    weak_factory_.GetWeakPtr(), robot_auth_code, robot_email,
    100                    user_email, base::Owned(user_preferences.DeepCopy())));
    101   }
    102 }
    103 
    104 void CloudPrintProxyService::DisableForUser() {
    105   UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
    106                             ServiceProcessControl::SERVICE_EVENT_DISABLE,
    107                             ServiceProcessControl::SERVICE_EVENT_MAX);
    108   InvokeServiceTask(
    109       base::Bind(&CloudPrintProxyService::DisableCloudPrintProxy,
    110                  weak_factory_.GetWeakPtr()));
    111 }
    112 
    113 bool CloudPrintProxyService::ApplyCloudPrintConnectorPolicy() {
    114   if (!profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
    115     std::string email =
    116         profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail);
    117     if (!email.empty()) {
    118       UMA_HISTOGRAM_ENUMERATION(
    119           "CloudPrint.ServiceEvents",
    120           ServiceProcessControl::SERVICE_EVENT_DISABLE_BY_POLICY,
    121           ServiceProcessControl::SERVICE_EVENT_MAX);
    122       DisableForUser();
    123       profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
    124       if (enforcing_connector_policy_) {
    125         base::MessageLoop::current()->PostTask(
    126             FROM_HERE,
    127             base::Bind(&CloudPrintProxyService::RefreshCloudPrintProxyStatus,
    128                        weak_factory_.GetWeakPtr()));
    129       }
    130       return false;
    131     } else if (enforcing_connector_policy_) {
    132       base::MessageLoop::current()->PostTask(FROM_HERE,
    133                                              base::MessageLoop::QuitClosure());
    134     }
    135   }
    136   return true;
    137 }
    138 
    139 void CloudPrintProxyService::GetPrintersAvalibleForRegistration(
    140       std::vector<std::string>* printers) {
    141   base::FilePath list_path(
    142       CommandLine::ForCurrentProcess()->GetSwitchValuePath(
    143           switches::kCloudPrintSetupProxy));
    144   if (!list_path.empty()) {
    145     std::string printers_json;
    146     base::ReadFileToString(list_path, &printers_json);
    147     scoped_ptr<Value> value(base::JSONReader::Read(printers_json));
    148     base::ListValue* list = NULL;
    149     if (value && value->GetAsList(&list) && list) {
    150       for (size_t i = 0; i < list->GetSize(); ++i) {
    151         std::string printer;
    152         if (list->GetString(i, &printer))
    153           printers->push_back(printer);
    154       }
    155     }
    156     UMA_HISTOGRAM_COUNTS_10000("CloudPrint.AvailablePrintersList",
    157                                printers->size());
    158   } else {
    159     printing::PrinterList printer_list;
    160     scoped_refptr<printing::PrintBackend> backend(
    161         printing::PrintBackend::CreateInstance(NULL));
    162     if (backend.get())
    163       backend->EnumeratePrinters(&printer_list);
    164     for (size_t i = 0; i < printer_list.size(); ++i)
    165       printers->push_back(printer_list[i].printer_name);
    166     UMA_HISTOGRAM_COUNTS_10000("CloudPrint.AvailablePrinters",
    167                                printers->size());
    168   }
    169 }
    170 
    171 void CloudPrintProxyService::RefreshCloudPrintProxyStatus() {
    172   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    173   ServiceProcessControl* process_control = GetServiceProcessControl();
    174   DCHECK(process_control->IsConnected());
    175   ServiceProcessControl::CloudPrintProxyInfoHandler callback =
    176        base::Bind(&CloudPrintProxyService::ProxyInfoCallback,
    177                   base::Unretained(this));
    178   // GetCloudPrintProxyInfo takes ownership of callback.
    179   process_control->GetCloudPrintProxyInfo(callback);
    180 }
    181 
    182 void CloudPrintProxyService::EnableCloudPrintProxyWithRobot(
    183     const std::string& robot_auth_code,
    184     const std::string& robot_email,
    185     const std::string& user_email,
    186     const base::DictionaryValue* user_preferences) {
    187   ServiceProcessControl* process_control = GetServiceProcessControl();
    188   DCHECK(process_control->IsConnected());
    189   process_control->Send(
    190       new ServiceMsg_EnableCloudPrintProxyWithRobot(
    191           robot_auth_code, robot_email, user_email, *user_preferences));
    192   // Assume the IPC worked.
    193   profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, user_email);
    194 }
    195 
    196 void CloudPrintProxyService::DisableCloudPrintProxy() {
    197   ServiceProcessControl* process_control = GetServiceProcessControl();
    198   DCHECK(process_control->IsConnected());
    199   process_control->Send(new ServiceMsg_DisableCloudPrintProxy);
    200   // Assume the IPC worked.
    201   profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
    202 }
    203 
    204 void CloudPrintProxyService::ProxyInfoCallback(
    205     const cloud_print::CloudPrintProxyInfo& proxy_info) {
    206   proxy_id_ = proxy_info.proxy_id;
    207   profile_->GetPrefs()->SetString(
    208       prefs::kCloudPrintEmail,
    209       proxy_info.enabled ? proxy_info.email : std::string());
    210   ApplyCloudPrintConnectorPolicy();
    211 }
    212 
    213 bool CloudPrintProxyService::InvokeServiceTask(const base::Closure& task) {
    214   GetServiceProcessControl()->Launch(task, base::Closure());
    215   return true;
    216 }
    217 
    218 ServiceProcessControl* CloudPrintProxyService::GetServiceProcessControl() {
    219   return ServiceProcessControl::GetInstance();
    220 }
    221