cloud_print_proxy_service.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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.h"
16#include "base/prefs/pref_service.h"
17#include "base/strings/utf_string_conversions.h"
18#include "chrome/browser/browser_process.h"
19#include "chrome/browser/lifetime/application_lifetime.h"
20#include "chrome/browser/notifications/desktop_notification_service.h"
21#include "chrome/browser/notifications/notification.h"
22#include "chrome/browser/notifications/notification_ui_manager.h"
23#include "chrome/browser/profiles/profile.h"
24#include "chrome/browser/service/service_process_control.h"
25#include "chrome/common/chrome_notification_types.h"
26#include "chrome/common/chrome_switches.h"
27#include "chrome/common/cloud_print/cloud_print_proxy_info.h"
28#include "chrome/common/pref_names.h"
29#include "chrome/common/service_messages.h"
30#include "content/public/browser/browser_thread.h"
31#include "grit/generated_resources.h"
32#include "printing/backend/print_backend.h"
33#include "ui/base/l10n/l10n_util.h"
34
35using content::BrowserThread;
36
37CloudPrintProxyService::CloudPrintProxyService(Profile* profile)
38    : profile_(profile),
39      weak_factory_(this),
40      enforcing_connector_policy_(false) {
41}
42
43CloudPrintProxyService::~CloudPrintProxyService() {
44}
45
46void CloudPrintProxyService::Initialize() {
47  if (profile_->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
48      (!profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty() ||
49       !profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled))) {
50    // If the cloud print proxy is enabled, or the policy preventing it from
51    // being enabled is set, establish a channel with the service process and
52    // update the status. This will check the policy when the status is sent
53    // back.
54    RefreshStatusFromService();
55  }
56
57  pref_change_registrar_.Init(profile_->GetPrefs());
58  pref_change_registrar_.Add(
59      prefs::kCloudPrintProxyEnabled,
60      base::Bind(
61          base::IgnoreResult(
62              &CloudPrintProxyService::ApplyCloudPrintConnectorPolicy),
63          base::Unretained(this)));
64}
65
66void CloudPrintProxyService::RefreshStatusFromService() {
67  InvokeServiceTask(
68      base::Bind(&CloudPrintProxyService::RefreshCloudPrintProxyStatus,
69                 weak_factory_.GetWeakPtr()));
70}
71
72bool CloudPrintProxyService::EnforceCloudPrintConnectorPolicyAndQuit() {
73  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74  enforcing_connector_policy_ = true;
75  if (ApplyCloudPrintConnectorPolicy())
76    return true;
77  return false;
78}
79
80void CloudPrintProxyService::EnableForUserWithRobot(
81    const std::string& robot_auth_code,
82    const std::string& robot_email,
83    const std::string& user_email,
84    const base::DictionaryValue& user_preferences) {
85  if (profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
86    InvokeServiceTask(
87        base::Bind(&CloudPrintProxyService::EnableCloudPrintProxyWithRobot,
88                   weak_factory_.GetWeakPtr(), robot_auth_code, robot_email,
89                   user_email, base::Owned(user_preferences.DeepCopy())));
90  }
91}
92
93void CloudPrintProxyService::DisableForUser() {
94  InvokeServiceTask(
95      base::Bind(&CloudPrintProxyService::DisableCloudPrintProxy,
96                 weak_factory_.GetWeakPtr()));
97}
98
99bool CloudPrintProxyService::ApplyCloudPrintConnectorPolicy() {
100  if (!profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
101    std::string email =
102        profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail);
103    if (!email.empty()) {
104      DisableForUser();
105      profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
106      if (enforcing_connector_policy_) {
107        base::MessageLoop::current()->PostTask(
108            FROM_HERE,
109            base::Bind(&CloudPrintProxyService::RefreshCloudPrintProxyStatus,
110                       weak_factory_.GetWeakPtr()));
111      }
112      return false;
113    } else if (enforcing_connector_policy_) {
114      base::MessageLoop::current()->PostTask(FROM_HERE,
115                                             base::MessageLoop::QuitClosure());
116    }
117  }
118  return true;
119}
120
121void CloudPrintProxyService::GetPrintersAvalibleForRegistration(
122      std::vector<std::string>* printers) {
123  base::FilePath list_path(
124      CommandLine::ForCurrentProcess()->GetSwitchValuePath(
125          switches::kCloudPrintSetupProxy));
126  if (!list_path.empty()) {
127    std::string printers_json;
128    file_util::ReadFileToString(list_path, &printers_json);
129    scoped_ptr<Value> value(base::JSONReader::Read(printers_json));
130    base::ListValue* list = NULL;
131    if (value && value->GetAsList(&list) && list) {
132      for (size_t i = 0; i < list->GetSize(); ++i) {
133        std::string printer;
134        if (list->GetString(i, &printer))
135          printers->push_back(printer);
136      }
137    }
138  } else {
139    printing::PrinterList printer_list;
140    scoped_refptr<printing::PrintBackend> backend(
141        printing::PrintBackend::CreateInstance(NULL));
142    if (backend.get())
143      backend->EnumeratePrinters(&printer_list);
144    for (size_t i = 0; i < printer_list.size(); ++i)
145      printers->push_back(printer_list[i].printer_name);
146  }
147}
148
149void CloudPrintProxyService::RefreshCloudPrintProxyStatus() {
150  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
151  ServiceProcessControl* process_control = GetServiceProcessControl();
152  DCHECK(process_control->IsConnected());
153  ServiceProcessControl::CloudPrintProxyInfoHandler callback =
154       base::Bind(&CloudPrintProxyService::ProxyInfoCallback,
155                  base::Unretained(this));
156  // GetCloudPrintProxyInfo takes ownership of callback.
157  process_control->GetCloudPrintProxyInfo(callback);
158}
159
160void CloudPrintProxyService::EnableCloudPrintProxyWithRobot(
161    const std::string& robot_auth_code,
162    const std::string& robot_email,
163    const std::string& user_email,
164    const base::DictionaryValue* user_preferences) {
165  ServiceProcessControl* process_control = GetServiceProcessControl();
166  DCHECK(process_control->IsConnected());
167  process_control->Send(
168      new ServiceMsg_EnableCloudPrintProxyWithRobot(
169          robot_auth_code, robot_email, user_email, *user_preferences));
170  // Assume the IPC worked.
171  profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, user_email);
172}
173
174void CloudPrintProxyService::DisableCloudPrintProxy() {
175  ServiceProcessControl* process_control = GetServiceProcessControl();
176  DCHECK(process_control->IsConnected());
177  process_control->Send(new ServiceMsg_DisableCloudPrintProxy);
178  // Assume the IPC worked.
179  profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
180}
181
182void CloudPrintProxyService::ProxyInfoCallback(
183    const cloud_print::CloudPrintProxyInfo& proxy_info) {
184  proxy_id_ = proxy_info.proxy_id;
185  profile_->GetPrefs()->SetString(
186      prefs::kCloudPrintEmail,
187      proxy_info.enabled ? proxy_info.email : std::string());
188  ApplyCloudPrintConnectorPolicy();
189}
190
191bool CloudPrintProxyService::InvokeServiceTask(const base::Closure& task) {
192  GetServiceProcessControl()->Launch(task, base::Closure());
193  return true;
194}
195
196ServiceProcessControl* CloudPrintProxyService::GetServiceProcessControl() {
197  return ServiceProcessControl::GetInstance();
198}
199