Don't use --check-cloud-print-connector-policy on MAC
[chromium-blink-merge.git] / chrome / service / cloud_print / cloud_print_proxy.cc
blobccf930fbe3b165a7f1becb22157644655baf5bae
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.
5 #include "chrome/service/cloud_print/cloud_print_proxy.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/metrics/histogram.h"
10 #include "base/path_service.h"
11 #include "base/process/kill.h"
12 #include "base/process/launch.h"
13 #include "base/values.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/cloud_print/cloud_print_constants.h"
16 #include "chrome/common/cloud_print/cloud_print_proxy_info.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/service/cloud_print/print_system.h"
19 #include "chrome/service/service_process.h"
20 #include "chrome/service/service_process_prefs.h"
21 #include "google_apis/gaia/gaia_oauth_client.h"
22 #include "google_apis/google_api_keys.h"
23 #include "url/gurl.h"
25 namespace {
27 #if !defined(OS_MACOSX)
28 void LaunchBrowserProcessWithSwitch(const std::string& switch_string) {
29 DCHECK(g_service_process->io_thread()->message_loop_proxy()->
30 BelongsToCurrentThread());
31 base::FilePath exe_path;
32 PathService::Get(base::FILE_EXE, &exe_path);
33 if (exe_path.empty()) {
34 NOTREACHED() << "Unable to get browser process binary name.";
36 base::CommandLine cmd_line(exe_path);
38 // Propagate an explicit --user-data-dir value if one was given. The new
39 // browser process will pick up a policy override during initialization.
40 const base::CommandLine& process_command_line =
41 *base::CommandLine::ForCurrentProcess();
42 base::FilePath user_data_dir =
43 process_command_line.GetSwitchValuePath(switches::kUserDataDir);
44 if (!user_data_dir.empty())
45 cmd_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
46 cmd_line.AppendSwitch(switch_string);
48 #if defined(OS_POSIX) && !defined(OS_MACOSX)
49 base::Process process = base::LaunchProcess(cmd_line, base::LaunchOptions());
50 if (process.IsValid())
51 base::EnsureProcessGetsReaped(process.Pid());
52 #else
53 base::LaunchOptions launch_options;
54 #if defined(OS_WIN)
55 launch_options.force_breakaway_from_job_ = true;
56 #endif // OS_WIN
57 base::LaunchProcess(cmd_line, launch_options);
58 #endif
61 void CheckCloudPrintProxyPolicyInBrowser() {
62 LaunchBrowserProcessWithSwitch(switches::kCheckCloudPrintConnectorPolicy);
65 #endif // !OS_MACOSX
67 } // namespace
69 namespace cloud_print {
71 CloudPrintProxy::CloudPrintProxy()
72 : service_prefs_(NULL),
73 client_(NULL),
74 enabled_(false) {
77 CloudPrintProxy::~CloudPrintProxy() {
78 DCHECK(CalledOnValidThread());
79 ShutdownBackend();
82 void CloudPrintProxy::Initialize(ServiceProcessPrefs* service_prefs,
83 Client* client) {
84 DCHECK(CalledOnValidThread());
85 service_prefs_ = service_prefs;
86 client_ = client;
89 void CloudPrintProxy::EnableForUser() {
90 DCHECK(CalledOnValidThread());
91 if (!CreateBackend())
92 return;
93 DCHECK(backend_.get());
94 // Read persisted robot credentials because we may decide to reuse it if the
95 // passed in LSID belongs the same user.
96 std::string robot_refresh_token = service_prefs_->GetString(
97 prefs::kCloudPrintRobotRefreshToken, std::string());
98 std::string robot_email =
99 service_prefs_->GetString(prefs::kCloudPrintRobotEmail, std::string());
100 user_email_ = service_prefs_->GetString(prefs::kCloudPrintEmail, user_email_);
102 // See if we have persisted robot credentials.
103 if (!robot_refresh_token.empty()) {
104 DCHECK(!robot_email.empty());
105 backend_->InitializeWithRobotToken(robot_refresh_token, robot_email);
106 } else {
107 // Finally see if we have persisted user credentials (legacy case).
108 std::string cloud_print_token =
109 service_prefs_->GetString(prefs::kCloudPrintAuthToken, std::string());
110 DCHECK(!cloud_print_token.empty());
111 backend_->InitializeWithToken(cloud_print_token);
113 if (client_) {
114 client_->OnCloudPrintProxyEnabled(true);
118 void CloudPrintProxy::EnableForUserWithRobot(
119 const std::string& robot_auth_code,
120 const std::string& robot_email,
121 const std::string& user_email,
122 const base::DictionaryValue& user_settings) {
123 DCHECK(CalledOnValidThread());
125 ShutdownBackend();
126 std::string proxy_id(
127 service_prefs_->GetString(prefs::kCloudPrintProxyId, std::string()));
128 service_prefs_->RemovePref(prefs::kCloudPrintRoot);
129 if (!proxy_id.empty()) {
130 // Keep only proxy id;
131 service_prefs_->SetString(prefs::kCloudPrintProxyId, proxy_id);
133 service_prefs_->SetValue(prefs::kCloudPrintUserSettings,
134 user_settings.DeepCopy());
135 service_prefs_->WritePrefs();
137 if (!CreateBackend())
138 return;
139 DCHECK(backend_.get());
140 user_email_ = user_email;
141 backend_->InitializeWithRobotAuthCode(robot_auth_code, robot_email);
142 if (client_) {
143 client_->OnCloudPrintProxyEnabled(true);
147 bool CloudPrintProxy::CreateBackend() {
148 DCHECK(CalledOnValidThread());
149 if (backend_.get())
150 return false;
152 ConnectorSettings settings;
153 settings.InitFrom(service_prefs_);
155 // By default we don't poll for jobs when we lose XMPP connection. But this
156 // behavior can be overridden by a preference.
157 bool enable_job_poll =
158 service_prefs_->GetBoolean(prefs::kCloudPrintEnableJobPoll, false);
160 gaia::OAuthClientInfo oauth_client_info;
161 oauth_client_info.client_id =
162 google_apis::GetOAuth2ClientID(google_apis::CLIENT_CLOUD_PRINT);
163 oauth_client_info.client_secret =
164 google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_CLOUD_PRINT);
165 oauth_client_info.redirect_uri = "oob";
166 backend_.reset(new CloudPrintProxyBackend(
167 this, settings, oauth_client_info, enable_job_poll));
168 return true;
171 void CloudPrintProxy::UnregisterPrintersAndDisableForUser() {
172 DCHECK(CalledOnValidThread());
173 if (backend_.get()) {
174 // Try getting auth and printers info from the backend.
175 // We'll get notified in this case.
176 backend_->UnregisterPrinters();
177 } else {
178 // If no backend avaialble, disable connector immidiately.
179 DisableForUser();
183 void CloudPrintProxy::DisableForUser() {
184 DCHECK(CalledOnValidThread());
185 user_email_.clear();
186 enabled_ = false;
187 if (client_) {
188 client_->OnCloudPrintProxyDisabled(true);
190 ShutdownBackend();
193 void CloudPrintProxy::GetProxyInfo(CloudPrintProxyInfo* info) {
194 info->enabled = enabled_;
195 info->email.clear();
196 if (enabled_)
197 info->email = user_email();
198 ConnectorSettings settings;
199 settings.InitFrom(service_prefs_);
200 info->proxy_id = settings.proxy_id();
203 void CloudPrintProxy::GetPrinters(std::vector<std::string>* printers) {
204 ConnectorSettings settings;
205 settings.InitFrom(service_prefs_);
206 scoped_refptr<PrintSystem> print_system =
207 PrintSystem::CreateInstance(settings.print_system_settings());
208 if (!print_system.get())
209 return;
210 PrintSystem::PrintSystemResult result = print_system->Init();
211 if (!result.succeeded())
212 return;
213 printing::PrinterList printer_list;
214 print_system->EnumeratePrinters(&printer_list);
215 for (size_t i = 0; i < printer_list.size(); ++i)
216 printers->push_back(printer_list[i].printer_name);
219 void CloudPrintProxy::CheckCloudPrintProxyPolicy() {
220 #if !defined(OS_MACOSX)
221 g_service_process->io_thread()->message_loop_proxy()->PostTask(
222 FROM_HERE, base::Bind(&CheckCloudPrintProxyPolicyInBrowser));
223 #endif
226 void CloudPrintProxy::OnAuthenticated(
227 const std::string& robot_oauth_refresh_token,
228 const std::string& robot_email,
229 const std::string& user_email) {
230 DCHECK(CalledOnValidThread());
231 service_prefs_->SetString(prefs::kCloudPrintRobotRefreshToken,
232 robot_oauth_refresh_token);
233 service_prefs_->SetString(prefs::kCloudPrintRobotEmail,
234 robot_email);
235 // If authenticating from a robot, the user email will be empty.
236 if (!user_email.empty()) {
237 user_email_ = user_email;
239 service_prefs_->SetString(prefs::kCloudPrintEmail, user_email_);
240 enabled_ = true;
241 DCHECK(!user_email_.empty());
242 service_prefs_->WritePrefs();
243 // When this switch used we don't want connector continue running, we just
244 // need authentication.
245 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
246 switches::kCloudPrintSetupProxy)) {
247 ShutdownBackend();
248 if (client_) {
249 client_->OnCloudPrintProxyDisabled(false);
254 void CloudPrintProxy::OnAuthenticationFailed() {
255 DCHECK(CalledOnValidThread());
256 // Don't disable permanently. Could be just connection issue.
257 ShutdownBackend();
258 if (client_) {
259 client_->OnCloudPrintProxyDisabled(false);
263 void CloudPrintProxy::OnPrintSystemUnavailable() {
264 // If the print system is unavailable, we want to shutdown the proxy and
265 // disable it non-persistently.
266 ShutdownBackend();
267 if (client_) {
268 client_->OnCloudPrintProxyDisabled(false);
272 void CloudPrintProxy::OnUnregisterPrinters(
273 const std::string& auth_token,
274 const std::list<std::string>& printer_ids) {
275 UMA_HISTOGRAM_COUNTS_10000("CloudPrint.UnregisterPrinters",
276 printer_ids.size());
277 ShutdownBackend();
278 ConnectorSettings settings;
279 settings.InitFrom(service_prefs_);
280 wipeout_.reset(new CloudPrintWipeout(this, settings.server_url()));
281 wipeout_->UnregisterPrinters(auth_token, printer_ids);
284 void CloudPrintProxy::OnXmppPingUpdated(int ping_timeout) {
285 DCHECK(CalledOnValidThread());
286 service_prefs_->SetInt(prefs::kCloudPrintXmppPingTimeout, ping_timeout);
287 service_prefs_->WritePrefs();
290 void CloudPrintProxy::OnUnregisterPrintersComplete() {
291 wipeout_.reset();
292 // Finish disabling cloud print for this user.
293 DisableForUser();
296 void CloudPrintProxy::ShutdownBackend() {
297 DCHECK(CalledOnValidThread());
298 if (backend_.get())
299 backend_->Shutdown();
300 backend_.reset();
303 } // namespace cloud_print