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"
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"
27 void LaunchBrowserProcessWithSwitch(const std::string
& switch_string
) {
28 DCHECK(g_service_process
->io_thread()->message_loop_proxy()->
29 BelongsToCurrentThread());
30 base::FilePath exe_path
;
31 PathService::Get(base::FILE_EXE
, &exe_path
);
32 if (exe_path
.empty()) {
33 NOTREACHED() << "Unable to get browser process binary name.";
35 CommandLine
cmd_line(exe_path
);
37 const CommandLine
& process_command_line
= *CommandLine::ForCurrentProcess();
38 base::FilePath user_data_dir
=
39 process_command_line
.GetSwitchValuePath(switches::kUserDataDir
);
40 if (!user_data_dir
.empty())
41 cmd_line
.AppendSwitchPath(switches::kUserDataDir
, user_data_dir
);
42 cmd_line
.AppendSwitch(switch_string
);
44 #if defined(OS_POSIX) && !defined(OS_MACOSX)
45 base::ProcessHandle pid
= 0;
46 base::LaunchProcess(cmd_line
, base::LaunchOptions(), &pid
);
47 base::EnsureProcessGetsReaped(pid
);
49 base::LaunchOptions launch_options
;
51 launch_options
.force_breakaway_from_job_
= true;
53 base::LaunchProcess(cmd_line
, launch_options
, NULL
);
57 void CheckCloudPrintProxyPolicyInBrowser() {
58 LaunchBrowserProcessWithSwitch(switches::kCheckCloudPrintConnectorPolicy
);
63 namespace cloud_print
{
65 CloudPrintProxy::CloudPrintProxy()
66 : service_prefs_(NULL
),
71 CloudPrintProxy::~CloudPrintProxy() {
72 DCHECK(CalledOnValidThread());
76 void CloudPrintProxy::Initialize(ServiceProcessPrefs
* service_prefs
,
78 DCHECK(CalledOnValidThread());
79 service_prefs_
= service_prefs
;
83 void CloudPrintProxy::EnableForUser() {
84 DCHECK(CalledOnValidThread());
87 DCHECK(backend_
.get());
88 // Read persisted robot credentials because we may decide to reuse it if the
89 // passed in LSID belongs the same user.
90 std::string robot_refresh_token
= service_prefs_
->GetString(
91 prefs::kCloudPrintRobotRefreshToken
, std::string());
92 std::string robot_email
=
93 service_prefs_
->GetString(prefs::kCloudPrintRobotEmail
, std::string());
94 user_email_
= service_prefs_
->GetString(prefs::kCloudPrintEmail
, user_email_
);
96 // See if we have persisted robot credentials.
97 if (!robot_refresh_token
.empty()) {
98 DCHECK(!robot_email
.empty());
99 backend_
->InitializeWithRobotToken(robot_refresh_token
, robot_email
);
101 // Finally see if we have persisted user credentials (legacy case).
102 std::string cloud_print_token
=
103 service_prefs_
->GetString(prefs::kCloudPrintAuthToken
, std::string());
104 DCHECK(!cloud_print_token
.empty());
105 backend_
->InitializeWithToken(cloud_print_token
);
108 client_
->OnCloudPrintProxyEnabled(true);
112 void CloudPrintProxy::EnableForUserWithRobot(
113 const std::string
& robot_auth_code
,
114 const std::string
& robot_email
,
115 const std::string
& user_email
,
116 const base::DictionaryValue
& user_settings
) {
117 DCHECK(CalledOnValidThread());
120 std::string
proxy_id(
121 service_prefs_
->GetString(prefs::kCloudPrintProxyId
, std::string()));
122 service_prefs_
->RemovePref(prefs::kCloudPrintRoot
);
123 if (!proxy_id
.empty()) {
124 // Keep only proxy id;
125 service_prefs_
->SetString(prefs::kCloudPrintProxyId
, proxy_id
);
127 service_prefs_
->SetValue(prefs::kCloudPrintUserSettings
,
128 user_settings
.DeepCopy());
129 service_prefs_
->WritePrefs();
131 if (!CreateBackend())
133 DCHECK(backend_
.get());
134 user_email_
= user_email
;
135 backend_
->InitializeWithRobotAuthCode(robot_auth_code
, robot_email
);
137 client_
->OnCloudPrintProxyEnabled(true);
141 bool CloudPrintProxy::CreateBackend() {
142 DCHECK(CalledOnValidThread());
146 settings_
.InitFrom(service_prefs_
);
148 // By default we don't poll for jobs when we lose XMPP connection. But this
149 // behavior can be overridden by a preference.
150 bool enable_job_poll
=
151 service_prefs_
->GetBoolean(prefs::kCloudPrintEnableJobPoll
, false);
153 gaia::OAuthClientInfo oauth_client_info
;
154 oauth_client_info
.client_id
=
155 google_apis::GetOAuth2ClientID(google_apis::CLIENT_CLOUD_PRINT
);
156 oauth_client_info
.client_secret
=
157 google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_CLOUD_PRINT
);
158 oauth_client_info
.redirect_uri
= "oob";
159 backend_
.reset(new CloudPrintProxyBackend(this, settings_
, oauth_client_info
,
164 void CloudPrintProxy::UnregisterPrintersAndDisableForUser() {
165 DCHECK(CalledOnValidThread());
166 if (backend_
.get()) {
167 // Try getting auth and printers info from the backend.
168 // We'll get notified in this case.
169 backend_
->UnregisterPrinters();
171 // If no backend avaialble, disable connector immidiately.
176 void CloudPrintProxy::DisableForUser() {
177 DCHECK(CalledOnValidThread());
181 client_
->OnCloudPrintProxyDisabled(true);
186 void CloudPrintProxy::GetProxyInfo(CloudPrintProxyInfo
* info
) {
187 info
->enabled
= enabled_
;
190 info
->email
= user_email();
191 info
->proxy_id
= settings_
.proxy_id();
192 // If the Cloud Print service is not enabled, we may need to read the old
193 // value of proxy_id from prefs.
194 if (info
->proxy_id
.empty())
196 service_prefs_
->GetString(prefs::kCloudPrintProxyId
, std::string());
199 void CloudPrintProxy::CheckCloudPrintProxyPolicy() {
200 g_service_process
->io_thread()->message_loop_proxy()->PostTask(
201 FROM_HERE
, base::Bind(&CheckCloudPrintProxyPolicyInBrowser
));
204 void CloudPrintProxy::OnAuthenticated(
205 const std::string
& robot_oauth_refresh_token
,
206 const std::string
& robot_email
,
207 const std::string
& user_email
) {
208 DCHECK(CalledOnValidThread());
209 service_prefs_
->SetString(prefs::kCloudPrintRobotRefreshToken
,
210 robot_oauth_refresh_token
);
211 service_prefs_
->SetString(prefs::kCloudPrintRobotEmail
,
213 // If authenticating from a robot, the user email will be empty.
214 if (!user_email
.empty()) {
215 user_email_
= user_email
;
217 service_prefs_
->SetString(prefs::kCloudPrintEmail
, user_email_
);
219 DCHECK(!user_email_
.empty());
220 service_prefs_
->WritePrefs();
221 // When this switch used we don't want connector continue running, we just
222 // need authentication.
223 if (CommandLine::ForCurrentProcess()->HasSwitch(
224 switches::kCloudPrintSetupProxy
)) {
227 client_
->OnCloudPrintProxyDisabled(false);
232 void CloudPrintProxy::OnAuthenticationFailed() {
233 DCHECK(CalledOnValidThread());
234 // Don't disable permanently. Could be just connection issue.
237 client_
->OnCloudPrintProxyDisabled(false);
241 void CloudPrintProxy::OnPrintSystemUnavailable() {
242 // If the print system is unavailable, we want to shutdown the proxy and
243 // disable it non-persistently.
246 client_
->OnCloudPrintProxyDisabled(false);
250 void CloudPrintProxy::OnUnregisterPrinters(
251 const std::string
& auth_token
,
252 const std::list
<std::string
>& printer_ids
) {
253 UMA_HISTOGRAM_COUNTS_10000("CloudPrint.UnregisterPrinters",
256 wipeout_
.reset(new CloudPrintWipeout(this, settings_
.server_url()));
257 wipeout_
->UnregisterPrinters(auth_token
, printer_ids
);
260 void CloudPrintProxy::OnXmppPingUpdated(int ping_timeout
) {
261 DCHECK(CalledOnValidThread());
262 service_prefs_
->SetInt(prefs::kCloudPrintXmppPingTimeout
, ping_timeout
);
263 service_prefs_
->WritePrefs();
266 void CloudPrintProxy::OnUnregisterPrintersComplete() {
268 // Finish disabling cloud print for this user.
272 void CloudPrintProxy::ShutdownBackend() {
273 DCHECK(CalledOnValidThread());
275 backend_
->Shutdown();
279 } // namespace cloud_print