Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / service / cloud_print / cloud_print_proxy.cc
blob9e07db91d67c647b20515f7a1fc2f6059519b02c
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 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);
48 #else
49 base::LaunchOptions launch_options;
50 #if defined(OS_WIN)
51 launch_options.force_breakaway_from_job_ = true;
52 #endif // OS_WIN
53 base::LaunchProcess(cmd_line, launch_options, NULL);
54 #endif
57 void CheckCloudPrintProxyPolicyInBrowser() {
58 LaunchBrowserProcessWithSwitch(switches::kCheckCloudPrintConnectorPolicy);
61 } // namespace
63 namespace cloud_print {
65 CloudPrintProxy::CloudPrintProxy()
66 : service_prefs_(NULL),
67 client_(NULL),
68 enabled_(false) {
71 CloudPrintProxy::~CloudPrintProxy() {
72 DCHECK(CalledOnValidThread());
73 ShutdownBackend();
76 void CloudPrintProxy::Initialize(ServiceProcessPrefs* service_prefs,
77 Client* client) {
78 DCHECK(CalledOnValidThread());
79 service_prefs_ = service_prefs;
80 client_ = client;
83 void CloudPrintProxy::EnableForUser() {
84 DCHECK(CalledOnValidThread());
85 if (!CreateBackend())
86 return;
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);
100 } else {
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);
107 if (client_) {
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());
119 ShutdownBackend();
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())
132 return;
133 DCHECK(backend_.get());
134 user_email_ = user_email;
135 backend_->InitializeWithRobotAuthCode(robot_auth_code, robot_email);
136 if (client_) {
137 client_->OnCloudPrintProxyEnabled(true);
141 bool CloudPrintProxy::CreateBackend() {
142 DCHECK(CalledOnValidThread());
143 if (backend_.get())
144 return false;
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,
160 enable_job_poll));
161 return true;
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();
170 } else {
171 // If no backend avaialble, disable connector immidiately.
172 DisableForUser();
176 void CloudPrintProxy::DisableForUser() {
177 DCHECK(CalledOnValidThread());
178 user_email_.clear();
179 enabled_ = false;
180 if (client_) {
181 client_->OnCloudPrintProxyDisabled(true);
183 ShutdownBackend();
186 void CloudPrintProxy::GetProxyInfo(CloudPrintProxyInfo* info) {
187 info->enabled = enabled_;
188 info->email.clear();
189 if (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())
195 info->proxy_id =
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,
212 robot_email);
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_);
218 enabled_ = true;
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)) {
225 ShutdownBackend();
226 if (client_) {
227 client_->OnCloudPrintProxyDisabled(false);
232 void CloudPrintProxy::OnAuthenticationFailed() {
233 DCHECK(CalledOnValidThread());
234 // Don't disable permanently. Could be just connection issue.
235 ShutdownBackend();
236 if (client_) {
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.
244 ShutdownBackend();
245 if (client_) {
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",
254 printer_ids.size());
255 ShutdownBackend();
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() {
267 wipeout_.reset();
268 // Finish disabling cloud print for this user.
269 DisableForUser();
272 void CloudPrintProxy::ShutdownBackend() {
273 DCHECK(CalledOnValidThread());
274 if (backend_.get())
275 backend_->Shutdown();
276 backend_.reset();
279 } // namespace cloud_print