| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/service/cloud_print/cloud_print_proxy.h" |
| |
| #include <stddef.h> |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/path_service.h" |
| #include "base/process/kill.h" |
| #include "base/process/launch.h" |
| #include "base/values.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/cloud_print/cloud_print_constants.h" |
| #include "chrome/common/cloud_print/cloud_print_proxy_info.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/service/cloud_print/print_system.h" |
| #include "chrome/service/service_process.h" |
| #include "chrome/service/service_process_prefs.h" |
| #include "google_apis/gaia/gaia_oauth_client.h" |
| #include "google_apis/google_api_keys.h" |
| #include "url/gurl.h" |
| |
| namespace cloud_print { |
| |
| CloudPrintProxy::CloudPrintProxy() |
| : service_prefs_(NULL), |
| client_(NULL), |
| enabled_(false) { |
| } |
| |
| CloudPrintProxy::~CloudPrintProxy() { |
| DCHECK(CalledOnValidThread()); |
| ShutdownBackend(); |
| } |
| |
| void CloudPrintProxy::Initialize(ServiceProcessPrefs* service_prefs, |
| Client* client) { |
| DCHECK(CalledOnValidThread()); |
| service_prefs_ = service_prefs; |
| client_ = client; |
| } |
| |
| void CloudPrintProxy::EnableForUser() { |
| DCHECK(CalledOnValidThread()); |
| if (!CreateBackend()) |
| return; |
| DCHECK(backend_.get()); |
| // Read persisted robot credentials because we may decide to reuse it if the |
| // passed in LSID belongs the same user. |
| std::string robot_refresh_token = service_prefs_->GetString( |
| prefs::kCloudPrintRobotRefreshToken, std::string()); |
| std::string robot_email = |
| service_prefs_->GetString(prefs::kCloudPrintRobotEmail, std::string()); |
| user_email_ = service_prefs_->GetString(prefs::kCloudPrintEmail, user_email_); |
| |
| // See if we have persisted robot credentials. |
| if (!robot_refresh_token.empty()) { |
| DCHECK(!robot_email.empty()); |
| backend_->InitializeWithRobotToken(robot_refresh_token, robot_email); |
| } else { |
| // Finally see if we have persisted user credentials (legacy case). |
| std::string cloud_print_token = |
| service_prefs_->GetString(prefs::kCloudPrintAuthToken, std::string()); |
| DCHECK(!cloud_print_token.empty()); |
| backend_->InitializeWithToken(cloud_print_token); |
| } |
| if (client_) { |
| client_->OnCloudPrintProxyEnabled(true); |
| } |
| } |
| |
| void CloudPrintProxy::EnableForUserWithRobot( |
| const std::string& robot_auth_code, |
| const std::string& robot_email, |
| const std::string& user_email, |
| const base::DictionaryValue& user_settings) { |
| DCHECK(CalledOnValidThread()); |
| |
| ShutdownBackend(); |
| std::string proxy_id( |
| service_prefs_->GetString(prefs::kCloudPrintProxyId, std::string())); |
| service_prefs_->RemovePref(prefs::kCloudPrintRoot); |
| if (!proxy_id.empty()) { |
| // Keep only proxy id; |
| service_prefs_->SetString(prefs::kCloudPrintProxyId, proxy_id); |
| } |
| service_prefs_->SetValue(prefs::kCloudPrintUserSettings, |
| user_settings.CreateDeepCopy()); |
| service_prefs_->WritePrefs(); |
| |
| if (!CreateBackend()) |
| return; |
| DCHECK(backend_.get()); |
| user_email_ = user_email; |
| backend_->InitializeWithRobotAuthCode(robot_auth_code, robot_email); |
| if (client_) { |
| client_->OnCloudPrintProxyEnabled(true); |
| } |
| } |
| |
| bool CloudPrintProxy::CreateBackend() { |
| DCHECK(CalledOnValidThread()); |
| if (backend_.get()) |
| return false; |
| |
| ConnectorSettings settings; |
| settings.InitFrom(service_prefs_); |
| |
| // By default we don't poll for jobs when we lose XMPP connection. But this |
| // behavior can be overridden by a preference. |
| bool enable_job_poll = |
| service_prefs_->GetBoolean(prefs::kCloudPrintEnableJobPoll, false); |
| |
| gaia::OAuthClientInfo oauth_client_info; |
| oauth_client_info.client_id = |
| google_apis::GetOAuth2ClientID(google_apis::CLIENT_CLOUD_PRINT); |
| oauth_client_info.client_secret = |
| google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_CLOUD_PRINT); |
| oauth_client_info.redirect_uri = "oob"; |
| backend_.reset(new CloudPrintProxyBackend( |
| this, settings, oauth_client_info, enable_job_poll)); |
| return true; |
| } |
| |
| void CloudPrintProxy::UnregisterPrintersAndDisableForUser() { |
| DCHECK(CalledOnValidThread()); |
| if (backend_.get()) { |
| // Try getting auth and printers info from the backend. |
| // We'll get notified in this case. |
| backend_->UnregisterPrinters(); |
| } else { |
| // If no backend available, disable connector immediately. |
| DisableForUser(); |
| } |
| } |
| |
| void CloudPrintProxy::DisableForUser() { |
| DCHECK(CalledOnValidThread()); |
| user_email_.clear(); |
| enabled_ = false; |
| if (client_) { |
| client_->OnCloudPrintProxyDisabled(true); |
| } |
| ShutdownBackend(); |
| } |
| |
| void CloudPrintProxy::GetProxyInfo(CloudPrintProxyInfo* info) { |
| info->enabled = enabled_; |
| info->email.clear(); |
| if (enabled_) |
| info->email = user_email(); |
| ConnectorSettings settings; |
| settings.InitFrom(service_prefs_); |
| info->proxy_id = settings.proxy_id(); |
| } |
| |
| void CloudPrintProxy::GetPrinters(std::vector<std::string>* printers) { |
| ConnectorSettings settings; |
| settings.InitFrom(service_prefs_); |
| scoped_refptr<PrintSystem> print_system = |
| PrintSystem::CreateInstance(settings.print_system_settings()); |
| if (!print_system.get()) |
| return; |
| PrintSystem::PrintSystemResult result = print_system->Init(); |
| if (!result.succeeded()) |
| return; |
| printing::PrinterList printer_list; |
| print_system->EnumeratePrinters(&printer_list); |
| for (size_t i = 0; i < printer_list.size(); ++i) |
| printers->push_back(printer_list[i].printer_name); |
| } |
| |
| void CloudPrintProxy::OnAuthenticated( |
| const std::string& robot_oauth_refresh_token, |
| const std::string& robot_email, |
| const std::string& user_email) { |
| DCHECK(CalledOnValidThread()); |
| service_prefs_->SetString(prefs::kCloudPrintRobotRefreshToken, |
| robot_oauth_refresh_token); |
| service_prefs_->SetString(prefs::kCloudPrintRobotEmail, |
| robot_email); |
| // If authenticating from a robot, the user email will be empty. |
| if (!user_email.empty()) { |
| user_email_ = user_email; |
| } |
| service_prefs_->SetString(prefs::kCloudPrintEmail, user_email_); |
| enabled_ = true; |
| DCHECK(!user_email_.empty()); |
| service_prefs_->WritePrefs(); |
| // When this switch used we don't want connector continue running, we just |
| // need authentication. |
| if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kCloudPrintSetupProxy)) { |
| ShutdownBackend(); |
| if (client_) { |
| client_->OnCloudPrintProxyDisabled(false); |
| } |
| } |
| } |
| |
| void CloudPrintProxy::OnAuthenticationFailed() { |
| DCHECK(CalledOnValidThread()); |
| // Don't disable permanently. Could be just connection issue. |
| ShutdownBackend(); |
| if (client_) { |
| client_->OnCloudPrintProxyDisabled(false); |
| } |
| } |
| |
| void CloudPrintProxy::OnPrintSystemUnavailable() { |
| // If the print system is unavailable, we want to shutdown the proxy and |
| // disable it non-persistently. |
| ShutdownBackend(); |
| if (client_) { |
| client_->OnCloudPrintProxyDisabled(false); |
| } |
| } |
| |
| void CloudPrintProxy::OnUnregisterPrinters( |
| const std::string& auth_token, |
| const std::list<std::string>& printer_ids) { |
| UMA_HISTOGRAM_COUNTS_10000("CloudPrint.UnregisterPrinters", |
| printer_ids.size()); |
| ShutdownBackend(); |
| ConnectorSettings settings; |
| settings.InitFrom(service_prefs_); |
| wipeout_.reset(new CloudPrintWipeout(this, settings.server_url())); |
| wipeout_->UnregisterPrinters(auth_token, printer_ids); |
| } |
| |
| void CloudPrintProxy::OnXmppPingUpdated(int ping_timeout) { |
| DCHECK(CalledOnValidThread()); |
| service_prefs_->SetInt(prefs::kCloudPrintXmppPingTimeout, ping_timeout); |
| service_prefs_->WritePrefs(); |
| } |
| |
| void CloudPrintProxy::OnUnregisterPrintersComplete() { |
| wipeout_.reset(); |
| // Finish disabling cloud print for this user. |
| DisableForUser(); |
| } |
| |
| void CloudPrintProxy::ShutdownBackend() { |
| DCHECK(CalledOnValidThread()); |
| if (backend_.get()) |
| backend_->Shutdown(); |
| backend_.reset(); |
| } |
| |
| } // namespace cloud_print |