summaryrefslogtreecommitdiffstats
path: root/chrome/service
diff options
context:
space:
mode:
authorsanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-06 23:22:21 +0000
committersanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-06 23:22:21 +0000
commitbb0733862079a1bdca18bedfbd5a17dc1ce700db (patch)
treed83668c995c5b11e1a6c7125eedc544b3bbed35f /chrome/service
parentfa9c732ee03201e331df4c2d04f21740ec09f565 (diff)
downloadchromium_src-bb0733862079a1bdca18bedfbd5a17dc1ce700db.zip
chromium_src-bb0733862079a1bdca18bedfbd5a17dc1ce700db.tar.gz
chromium_src-bb0733862079a1bdca18bedfbd5a17dc1ce700db.tar.bz2
Changed the cloud print connector logic to request the OAuth2 credentials of a robot account and use those credentials for all cloud print and Talk authentication. The OAuth2 tokens are also periodically refreshed.
BUG=None TEST=Unit-tests, Cloud Print connector. R=scottbyer@chromium.org Review URL: http://codereview.chromium.org/6705013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84525 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/service')
-rw-r--r--chrome/service/cloud_print/cloud_print_consts.cc10
-rw-r--r--chrome/service/cloud_print/cloud_print_consts.h12
-rw-r--r--chrome/service/cloud_print/cloud_print_helpers.cc16
-rw-r--r--chrome/service/cloud_print/cloud_print_helpers.h6
-rw-r--r--chrome/service/cloud_print/cloud_print_helpers_unittest.cc11
-rw-r--r--chrome/service/cloud_print/cloud_print_proxy.cc93
-rw-r--r--chrome/service/cloud_print/cloud_print_proxy.h15
-rw-r--r--chrome/service/cloud_print/cloud_print_proxy_backend.cc356
-rw-r--r--chrome/service/cloud_print/cloud_print_proxy_backend.h38
-rw-r--r--chrome/service/cloud_print/cloud_print_token_store.cc31
-rw-r--r--chrome/service/cloud_print/cloud_print_token_store.h43
-rw-r--r--chrome/service/cloud_print/cloud_print_token_store_unittest.cc22
-rw-r--r--chrome/service/cloud_print/cloud_print_url_fetcher.cc62
-rw-r--r--chrome/service/cloud_print/cloud_print_url_fetcher.h7
-rw-r--r--chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc7
-rw-r--r--chrome/service/cloud_print/job_status_updater.cc6
-rw-r--r--chrome/service/cloud_print/job_status_updater.h2
-rw-r--r--chrome/service/cloud_print/printer_job_handler.cc10
-rw-r--r--chrome/service/cloud_print/printer_job_handler.h2
-rw-r--r--chrome/service/service_process_prefs.cc4
-rw-r--r--chrome/service/service_process_prefs.h3
21 files changed, 580 insertions, 176 deletions
diff --git a/chrome/service/cloud_print/cloud_print_consts.cc b/chrome/service/cloud_print/cloud_print_consts.cc
index 4481384..e53e411 100644
--- a/chrome/service/cloud_print/cloud_print_consts.cc
+++ b/chrome/service/cloud_print/cloud_print_consts.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -27,6 +27,9 @@ const char kJobListValue[] = "jobs";
const char kTitleValue[] = "title";
const char kPrinterCapsHashValue[] = "capsHash";
const char kTagsValue[] = "tags";
+const char kXMPPJidValue[] = "xmpp_jid";
+const char kOAuthCodeValue[] = "authorization_code";
+
const char kProxyTagPrefix[] = "__cp__";
const char kTagsHashTagName[] = "__cp__tagshash";
const char kTagDryRunFlag[] = "__cp__dry_run";
@@ -58,3 +61,8 @@ const char kJobFetchReasonQueryMore[] = "querymore";
const char kPrintSystemFailedMessageId[] = "printsystemfail";
const char kGetPrinterCapsFailedMessageId[] = "getprncapsfail";
const char kEnumPrintersFailedMessageId[] = "enumfail";
+
+const char kDefaultCloudPrintOAuthClientId[] =
+ "551556820943.apps.googleusercontent.com";
+const char kDefaultCloudPrintOAuthClientSecret[] = "u3/mp8CgLFxh4uiX1855/MHe";
+
diff --git a/chrome/service/cloud_print/cloud_print_consts.h b/chrome/service/cloud_print/cloud_print_consts.h
index 160f20f..bf8ca55 100644
--- a/chrome/service/cloud_print/cloud_print_consts.h
+++ b/chrome/service/cloud_print/cloud_print_consts.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -29,6 +29,9 @@ extern const char kJobListValue[];
extern const char kTitleValue[];
extern const char kPrinterCapsHashValue[];
extern const char kTagsValue[];
+extern const char kXMPPJidValue[];
+extern const char kOAuthCodeValue[];
+
extern const char kProxyTagPrefix[];
extern const char kTagsHashTagName[];
extern const char kTagDryRunFlag[];
@@ -46,6 +49,9 @@ extern const char kJobFetchReasonQueryMore[];
extern const char kPrintSystemFailedMessageId[];
extern const char kGetPrinterCapsFailedMessageId[];
extern const char kEnumPrintersFailedMessageId[];
+extern const char kDefaultCloudPrintOAuthClientId[];
+extern const char kDefaultCloudPrintOAuthClientSecret[];
+
// Max retry count for job data fetch requests.
const int kJobDataMaxRetryCount = 5;
@@ -57,5 +63,9 @@ const int kCloudPrintAPIMaxRetryCount = -1;
const int kMinJobPollIntervalSecs = 5*60; // 5 minutes in seconds
const int kMaxJobPollIntervalSecs = 8*60; // 8 minutes in seconds
+// The number of seconds before the OAuth2 access token is due to expire that
+// we try and refresh it.
+const int kTokenRefreshGracePeriodSecs = 5*60; // 5 minutes in seconds
+
#endif // CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_CONSTS_H_
diff --git a/chrome/service/cloud_print/cloud_print_helpers.cc b/chrome/service/cloud_print/cloud_print_helpers.cc
index 1b253cf..7fb9ddd 100644
--- a/chrome/service/cloud_print/cloud_print_helpers.cc
+++ b/chrome/service/cloud_print/cloud_print_helpers.cc
@@ -147,6 +147,22 @@ GURL CloudPrintHelpers::GetUrlForUserMessage(const GURL& cloud_print_server_url,
return cloud_print_server_url.ReplaceComponents(replacements);
}
+GURL CloudPrintHelpers::GetUrlForGetAuthCode(const GURL& cloud_print_server_url,
+ const std::string& oauth_client_id,
+ const std::string& proxy_id) {
+ // We use the internal API "createrobot" instead of "getauthcode". This API
+ // will add the robot as owner to all the existing printers for this user.
+ std::string path(AppendPathToUrl(cloud_print_server_url, "createrobot"));
+ GURL::Replacements replacements;
+ replacements.SetPathStr(path);
+ std::string query = StringPrintf("oauth_client_id=%s&proxy=%s",
+ oauth_client_id.c_str(),
+ proxy_id.c_str());
+ replacements.SetQueryStr(query);
+ return cloud_print_server_url.ReplaceComponents(replacements);
+}
+
+
bool CloudPrintHelpers::ParseResponseJSON(
const std::string& response_data, bool* succeeded,
DictionaryValue** response_dict) {
diff --git a/chrome/service/cloud_print/cloud_print_helpers.h b/chrome/service/cloud_print/cloud_print_helpers.h
index 7ee1ded..6f2034f 100644
--- a/chrome/service/cloud_print/cloud_print_helpers.h
+++ b/chrome/service/cloud_print/cloud_print_helpers.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -37,6 +37,10 @@ class CloudPrintHelpers {
const cloud_print::PrintJobDetails& details);
static GURL GetUrlForUserMessage(const GURL& cloud_print_server_url,
const std::string& message_id);
+ static GURL GetUrlForGetAuthCode(const GURL& cloud_print_server_url,
+ const std::string& oauth_client_id,
+ const std::string& proxy_id);
+
// Parses the response data for any cloud print server request. The method
// returns false if there was an error in parsing the JSON. The succeeded
diff --git a/chrome/service/cloud_print/cloud_print_helpers_unittest.cc b/chrome/service/cloud_print/cloud_print_helpers_unittest.cc
index c60a0c3..cb1999a 100644
--- a/chrome/service/cloud_print/cloud_print_helpers_unittest.cc
+++ b/chrome/service/cloud_print/cloud_print_helpers_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -79,6 +79,15 @@ void CheckURLs(const GURL& server_base_url) {
expected_url = StringPrintf("%suser/message?code=blahmessageid",
expected_url_base.c_str());
EXPECT_EQ(expected_url, url.spec());
+
+ url = CloudPrintHelpers::GetUrlForGetAuthCode(
+ server_base_url,
+ "fooclientid.apps.googleusercontent.com",
+ "test_proxy");
+ expected_url = StringPrintf(
+ "%screaterobot?oauth_client_id=fooclientid.apps.googleusercontent.com&"
+ "proxy=test_proxy", expected_url_base.c_str());
+ EXPECT_EQ(expected_url, url.spec());
}
} // namespace
diff --git a/chrome/service/cloud_print/cloud_print_proxy.cc b/chrome/service/cloud_print/cloud_print_proxy.cc
index 7a5759b..8a99596 100644
--- a/chrome/service/cloud_print/cloud_print_proxy.cc
+++ b/chrome/service/cloud_print/cloud_print_proxy.cc
@@ -9,6 +9,7 @@
#include "base/process_util.h"
#include "base/values.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/net/gaia/gaia_oauth_client.h"
#include "chrome/common/pref_names.h"
#include "chrome/service/cloud_print/cloud_print_consts.h"
#include "chrome/service/cloud_print/print_system.h"
@@ -41,7 +42,8 @@ static void ShowTokenExpiredNotificationInBrowser() {
CloudPrintProxy::CloudPrintProxy()
: service_prefs_(NULL),
- client_(NULL) {
+ client_(NULL),
+ enabled_(false) {
}
CloudPrintProxy::~CloudPrintProxy() {
@@ -81,6 +83,7 @@ void CloudPrintProxy::EnableForUser(const std::string& lsid) {
if (cloud_print_server_url_str.empty()) {
cloud_print_server_url_str = kDefaultCloudPrintServerUrl;
}
+ service_prefs_->GetString(prefs::kCloudPrintEmail, &user_email_);
// By default we don't poll for jobs when we lose XMPP connection. But this
// behavior can be overridden by a preference.
@@ -88,29 +91,49 @@ void CloudPrintProxy::EnableForUser(const std::string& lsid) {
service_prefs_->GetBoolean(prefs::kCloudPrintEnableJobPoll,
&enable_job_poll);
+ // TODO(sanjeevr): Allow overriding OAuthClientInfo in prefs.
+ gaia::OAuthClientInfo oauth_client_info;
+ oauth_client_info.client_id = kDefaultCloudPrintOAuthClientId;
+ oauth_client_info.client_secret = kDefaultCloudPrintOAuthClientSecret;
+
GURL cloud_print_server_url(cloud_print_server_url_str.c_str());
DCHECK(cloud_print_server_url.is_valid());
backend_.reset(new CloudPrintProxyBackend(this, cloud_print_server_url,
print_system_settings,
+ oauth_client_info,
enable_job_poll));
+ // 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,
+ &robot_refresh_token);
+ std::string robot_email;
+ service_prefs_->GetString(prefs::kCloudPrintRobotEmail,
+ &robot_email);
+
// If we have been passed in an LSID, we want to use this to authenticate.
// Else we will try and retrieve the last used auth tokens from prefs.
if (!lsid.empty()) {
- backend_->InitializeWithLsid(lsid, proxy_id);
+ backend_->InitializeWithLsid(lsid,
+ proxy_id,
+ robot_refresh_token,
+ robot_email,
+ user_email_);
} else {
- std::string cloud_print_token;
- service_prefs_->GetString(prefs::kCloudPrintAuthToken,
- &cloud_print_token);
- DCHECK(!cloud_print_token.empty());
- std::string cloud_print_xmpp_token;
- service_prefs_->GetString(prefs::kCloudPrintXMPPAuthToken,
- &cloud_print_xmpp_token);
- DCHECK(!cloud_print_xmpp_token.empty());
- service_prefs_->GetString(prefs::kCloudPrintEmail,
- &cloud_print_email_);
- DCHECK(!cloud_print_email_.empty());
- backend_->InitializeWithToken(cloud_print_token, cloud_print_xmpp_token,
- cloud_print_email_, proxy_id);
+ // See if we have persisted robot credentials.
+ if (!robot_refresh_token.empty()) {
+ DCHECK(!robot_email.empty());
+ backend_->InitializeWithRobotToken(robot_refresh_token,
+ robot_email,
+ proxy_id);
+ } else {
+ // Finally see if we have persisted user credentials (legacy case).
+ std::string cloud_print_token;
+ service_prefs_->GetString(prefs::kCloudPrintAuthToken,
+ &cloud_print_token);
+ DCHECK(!cloud_print_token.empty());
+ backend_->InitializeWithToken(cloud_print_token, proxy_id);
+ }
}
if (client_) {
client_->OnCloudPrintProxyEnabled(true);
@@ -119,7 +142,8 @@ void CloudPrintProxy::EnableForUser(const std::string& lsid) {
void CloudPrintProxy::DisableForUser() {
DCHECK(CalledOnValidThread());
- cloud_print_email_.clear();
+ user_email_.clear();
+ enabled_ = false;
Shutdown();
if (client_) {
client_->OnCloudPrintProxyDisabled(true);
@@ -127,11 +151,10 @@ void CloudPrintProxy::DisableForUser() {
}
bool CloudPrintProxy::IsEnabled(std::string* email) const {
- bool enabled = !cloud_print_email().empty();
- if (enabled && email) {
- *email = cloud_print_email();
+ if (enabled_ && email) {
+ *email = user_email();
}
- return enabled;
+ return enabled_;
}
// Notification methods from the backend. Called on UI thread.
@@ -144,17 +167,21 @@ void CloudPrintProxy::OnPrinterListAvailable(
}
void CloudPrintProxy::OnAuthenticated(
- const std::string& cloud_print_token,
- const std::string& cloud_print_xmpp_token,
- const std::string& email) {
+ const std::string& robot_oauth_refresh_token,
+ const std::string& robot_email,
+ const std::string& user_email) {
DCHECK(CalledOnValidThread());
- cloud_print_email_ = email;
- service_prefs_->SetString(prefs::kCloudPrintAuthToken,
- cloud_print_token);
- service_prefs_->SetString(prefs::kCloudPrintXMPPAuthToken,
- cloud_print_xmpp_token);
- service_prefs_->SetString(prefs::kCloudPrintEmail,
- email);
+ 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();
}
@@ -162,6 +189,12 @@ void CloudPrintProxy::OnAuthenticationFailed() {
DCHECK(CalledOnValidThread());
// If authenticated failed, we will disable the cloud print proxy.
DisableForUser();
+ // Also delete the cached robot credentials since they may not be valid any
+ // longer.
+ service_prefs_->RemovePref(prefs::kCloudPrintRobotRefreshToken);
+ service_prefs_->RemovePref(prefs::kCloudPrintRobotEmail);
+ service_prefs_->WritePrefs();
+
// Launch the browser to display a notification that the credentials have
// expired (unless error dialogs are disabled).
if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoErrorDialogs))
diff --git a/chrome/service/cloud_print/cloud_print_proxy.h b/chrome/service/cloud_print/cloud_print_proxy.h
index 3727c55..2ff6dfb 100644
--- a/chrome/service/cloud_print/cloud_print_proxy.h
+++ b/chrome/service/cloud_print/cloud_print_proxy.h
@@ -40,16 +40,16 @@ class CloudPrintProxy : public CloudPrintProxyFrontend,
// for authentication is also returned in the optional |email| argument.
bool IsEnabled(std::string* email) const;
- const std::string& cloud_print_email() const {
- return cloud_print_email_;
+ const std::string& user_email() const {
+ return user_email_;
}
// CloudPrintProxyFrontend implementation. Called on UI thread.
virtual void OnPrinterListAvailable(
const printing::PrinterList& printer_list);
- virtual void OnAuthenticated(const std::string& cloud_print_token,
- const std::string& cloud_print_xmpp_token,
- const std::string& email);
+ virtual void OnAuthenticated(const std::string& robot_oauth_refresh_token,
+ const std::string& robot_email,
+ const std::string& user_email);
virtual void OnAuthenticationFailed();
virtual void OnPrintSystemUnavailable();
@@ -67,7 +67,10 @@ class CloudPrintProxy : public CloudPrintProxyFrontend,
Client* client_;
// The email address of the account used to authenticate to the Cloud Print
// service.
- std::string cloud_print_email_;
+ std::string user_email_;
+ // This is set to true when the Cloud Print proxy is enabled and after
+ // successful authentication with the Cloud Print service.
+ bool enabled_;
DISALLOW_COPY_AND_ASSIGN(CloudPrintProxy);
};
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.cc b/chrome/service/cloud_print/cloud_print_proxy_backend.cc
index 6681b12..490c30c 100644
--- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc
+++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc
@@ -15,8 +15,10 @@
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
+#include "chrome/common/net/gaia/gaia_oauth_client.h"
#include "chrome/service/cloud_print/cloud_print_consts.h"
#include "chrome/service/cloud_print/cloud_print_helpers.h"
+#include "chrome/service/cloud_print/cloud_print_token_store.h"
#include "chrome/service/cloud_print/cloud_print_url_fetcher.h"
#include "chrome/service/cloud_print/printer_job_handler.h"
#include "chrome/service/gaia/service_gaia_authenticator.h"
@@ -36,13 +38,15 @@ class CloudPrintProxyBackend::Core
public CloudPrintURLFetcherDelegate,
public cloud_print::PrintServerWatcherDelegate,
public PrinterJobHandlerDelegate,
- public notifier::TalkMediator::Delegate {
+ public notifier::TalkMediator::Delegate,
+ public gaia::GaiaOAuthClient::Delegate {
public:
// It is OK for print_server_url to be empty. In this case system should
// use system default (local) print server.
explicit Core(CloudPrintProxyBackend* backend,
const GURL& cloud_print_server_url,
const DictionaryValue* print_system_settings,
+ const gaia::OAuthClientInfo& oauth_client_info,
bool enable_job_poll);
// Note:
@@ -55,11 +59,16 @@ class CloudPrintProxyBackend::Core
// initialization. When we are passed in an LSID we authenticate using that
// and retrieve new auth tokens.
void DoInitializeWithLsid(const std::string& lsid,
- const std::string& proxy_id);
+ const std::string& proxy_id,
+ const std::string& last_robot_refresh_token,
+ const std::string& last_robot_email,
+ const std::string& last_user_email);
+
void DoInitializeWithToken(const std::string cloud_print_token,
- const std::string cloud_print_xmpp_token,
- const std::string email,
const std::string& proxy_id);
+ void DoInitializeWithRobotToken(const std::string& robot_oauth_refresh_token,
+ const std::string& robot_email,
+ const std::string& proxy_id);
// Called on the CloudPrintProxyBackend core_thread_ to perform
// shutdown.
@@ -92,6 +101,15 @@ class CloudPrintProxyBackend::Core
const notifier::Notification& notification);
virtual void OnOutgoingNotification();
+ // gaia::GaiaOAuthClient::Delegate implementation.
+ virtual void OnGetTokensResponse(const std::string& refresh_token,
+ const std::string& access_token,
+ int expires_in_seconds);
+ virtual void OnRefreshTokenResponse(const std::string& access_token,
+ int expires_in_seconds);
+ virtual void OnOAuthError();
+ virtual void OnNetworkError(int response_code);
+
private:
// Prototype for a response handler.
typedef CloudPrintURLFetcher::ResponseAction
@@ -130,6 +148,13 @@ class CloudPrintProxyBackend::Core
const GURL& url,
DictionaryValue* json_data,
bool succeeded);
+
+ CloudPrintURLFetcher::ResponseAction HandleGetAuthCodeResponse(
+ const URLFetcher* source,
+ const GURL& url,
+ DictionaryValue* json_data,
+ bool succeeded);
+
// End response handlers
// NotifyXXX is how the Core communicates with the frontend across
@@ -137,12 +162,14 @@ class CloudPrintProxyBackend::Core
void NotifyPrinterListAvailable(
const printing::PrinterList& printer_list);
void NotifyAuthenticated(
- const std::string& cloud_print_token,
- const std::string& cloud_print_xmpp_token,
- const std::string& email);
+ const std::string& robot_oauth_refresh_token,
+ const std::string& robot_email,
+ const std::string& user_email);
void NotifyAuthenticationFailed();
void NotifyPrintSystemUnavailable();
+ // Once we have robot credentials, this method gets the ball rolling.
+ void PostAuthInitialization();
// Starts a new printer registration process.
void StartRegistration();
// Ends the printer registration process.
@@ -164,6 +191,8 @@ class CloudPrintProxyBackend::Core
void ReportUserMessage(const std::string& message_id,
const std::string& failure_message,
ResponseHandler handler);
+ // Make a GAIA request to refresh the access token.
+ void RefreshAccessToken();
// Callback method for GetPrinterCapsAndDefaults.
void OnReceivePrinterCaps(
@@ -176,11 +205,13 @@ class CloudPrintProxyBackend::Core
// Schedules a task to poll for jobs. Does nothing if a task is already
// scheduled.
void ScheduleJobPoll();
+ CloudPrintTokenStore* GetTokenStore();
// Our parent CloudPrintProxyBackend
CloudPrintProxyBackend* backend_;
GURL cloud_print_server_url_;
+ gaia::OAuthClientInfo oauth_client_info_;
scoped_ptr<DictionaryValue> print_system_settings_;
// Pointer to current print system.
scoped_refptr<cloud_print::PrintSystem> print_system_;
@@ -201,8 +232,14 @@ class CloudPrintProxyBackend::Core
size_t next_upload_index_;
// The unique id for this proxy
std::string proxy_id_;
- // The GAIA auth token
- std::string auth_token_;
+ // The OAuth2 refresh token for the robot.
+ std::string refresh_token_;
+ // The email address of the user. This is only used during initial
+ // authentication with an LSID. This is only used for storing in prefs for
+ // display purposes.
+ std::string user_email_;
+ // The email address of the robot account.
+ std::string robot_email_;
// Cached info about the last printer that we tried to upload. We cache this
// so we won't have to requery the printer if the upload fails and we need
// to retry.
@@ -231,6 +268,8 @@ class CloudPrintProxyBackend::Core
// The channel we are interested in receiving push notifications for.
// This is "cloudprint.google.com/proxy/<proxy_id>"
std::string push_notifications_channel_;
+ scoped_ptr<gaia::GaiaOAuthClient> oauth_client_;
+ scoped_ptr<CloudPrintTokenStore> token_store_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
@@ -239,6 +278,7 @@ CloudPrintProxyBackend::CloudPrintProxyBackend(
CloudPrintProxyFrontend* frontend,
const GURL& cloud_print_server_url,
const DictionaryValue* print_system_settings,
+ const gaia::OAuthClientInfo& oauth_client_info,
bool enable_job_poll)
: core_thread_("Chrome_CloudPrintProxyCoreThread"),
frontend_loop_(MessageLoop::current()),
@@ -247,6 +287,7 @@ CloudPrintProxyBackend::CloudPrintProxyBackend(
core_ = new Core(this,
cloud_print_server_url,
print_system_settings,
+ oauth_client_info,
enable_job_poll);
}
@@ -254,31 +295,55 @@ CloudPrintProxyBackend::~CloudPrintProxyBackend() {
DCHECK(!core_);
}
-bool CloudPrintProxyBackend::InitializeWithLsid(const std::string& lsid,
- const std::string& proxy_id) {
+bool CloudPrintProxyBackend::InitializeWithLsid(
+ const std::string& lsid,
+ const std::string& proxy_id,
+ const std::string& last_robot_refresh_token,
+ const std::string& last_robot_email,
+ const std::string& last_user_email) {
if (!core_thread_.Start())
return false;
core_thread_.message_loop()->PostTask(FROM_HERE,
NewRunnableMethod(
- core_.get(), &CloudPrintProxyBackend::Core::DoInitializeWithLsid, lsid,
- proxy_id));
+ core_.get(),
+ &CloudPrintProxyBackend::Core::DoInitializeWithLsid,
+ lsid,
+ proxy_id,
+ last_robot_refresh_token,
+ last_robot_email,
+ last_user_email));
return true;
}
bool CloudPrintProxyBackend::InitializeWithToken(
const std::string& cloud_print_token,
- const std::string& cloud_print_xmpp_token,
- const std::string& email,
const std::string& proxy_id) {
if (!core_thread_.Start())
return false;
core_thread_.message_loop()->PostTask(FROM_HERE,
NewRunnableMethod(
core_.get(), &CloudPrintProxyBackend::Core::DoInitializeWithToken,
- cloud_print_token, cloud_print_xmpp_token, email, proxy_id));
+ cloud_print_token, proxy_id));
return true;
}
+bool CloudPrintProxyBackend::InitializeWithRobotToken(
+ const std::string& robot_oauth_refresh_token,
+ const std::string& robot_email,
+ const std::string& proxy_id) {
+ if (!core_thread_.Start())
+ return false;
+ core_thread_.message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(
+ core_.get(),
+ &CloudPrintProxyBackend::Core::DoInitializeWithRobotToken,
+ robot_oauth_refresh_token,
+ robot_email,
+ proxy_id));
+ return true;
+}
+
+
void CloudPrintProxyBackend::Shutdown() {
core_thread_.message_loop()->PostTask(FROM_HERE,
NewRunnableMethod(core_.get(),
@@ -296,20 +361,23 @@ void CloudPrintProxyBackend::RegisterPrinters(
printer_list));
}
-CloudPrintProxyBackend::Core::Core(CloudPrintProxyBackend* backend,
- const GURL& cloud_print_server_url,
- const DictionaryValue* print_system_settings,
- bool enable_job_poll)
- : backend_(backend),
- cloud_print_server_url_(cloud_print_server_url),
- complete_list_available_(false),
- next_upload_index_(0),
- next_response_handler_(NULL),
- new_printers_available_(false),
- registration_in_progress_(false),
- notifications_enabled_(false),
- job_poll_scheduled_(false),
- enable_job_poll_(enable_job_poll) {
+CloudPrintProxyBackend::Core::Core(
+ CloudPrintProxyBackend* backend,
+ const GURL& cloud_print_server_url,
+ const DictionaryValue* print_system_settings,
+ const gaia::OAuthClientInfo& oauth_client_info,
+ bool enable_job_poll)
+ : backend_(backend),
+ cloud_print_server_url_(cloud_print_server_url),
+ oauth_client_info_(oauth_client_info),
+ complete_list_available_(false),
+ next_upload_index_(0),
+ next_response_handler_(NULL),
+ new_printers_available_(false),
+ registration_in_progress_(false),
+ notifications_enabled_(false),
+ job_poll_scheduled_(false),
+ enable_job_poll_(enable_job_poll) {
if (print_system_settings) {
// It is possible to have no print settings specified.
print_system_settings_.reset(print_system_settings->DeepCopy());
@@ -317,93 +385,109 @@ CloudPrintProxyBackend::Core::Core(CloudPrintProxyBackend* backend,
}
void CloudPrintProxyBackend::Core::DoInitializeWithLsid(
- const std::string& lsid, const std::string& proxy_id) {
+ const std::string& lsid,
+ const std::string& proxy_id,
+ const std::string& last_robot_refresh_token,
+ const std::string& last_robot_email,
+ const std::string& last_user_email) {
DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
- // Since Talk does not accept a Cloud Print token, for now, we make 2 auth
- // requests, one for the chromiumsync service and another for print. This is
- // temporary and should be removed once Talk supports our token.
// Note: The GAIA login is synchronous but that should be OK because we are in
// the CloudPrintProxyCoreThread and we cannot really do anything else until
// the GAIA signin is successful.
std::string user_agent = "ChromiumBrowser";
- scoped_refptr<ServiceGaiaAuthenticator> gaia_auth_for_talk(
+ scoped_refptr<ServiceGaiaAuthenticator> gaia_auth_for_print(
new ServiceGaiaAuthenticator(
- user_agent, kSyncGaiaServiceId, kGaiaUrl,
+ user_agent, kCloudPrintGaiaServiceId, kGaiaUrl,
g_service_process->io_thread()->message_loop_proxy()));
- gaia_auth_for_talk->set_message_loop(MessageLoop::current());
- bool auth_succeeded = false;
- if (gaia_auth_for_talk->AuthenticateWithLsid(lsid)) {
- scoped_refptr<ServiceGaiaAuthenticator> gaia_auth_for_print(
- new ServiceGaiaAuthenticator(
- user_agent, kCloudPrintGaiaServiceId, kGaiaUrl,
- g_service_process->io_thread()->message_loop_proxy()));
- gaia_auth_for_print->set_message_loop(MessageLoop::current());
- if (gaia_auth_for_print->AuthenticateWithLsid(lsid)) {
- auth_succeeded = true;
- // Let the frontend know that we have authenticated.
- backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &Core::NotifyAuthenticated, gaia_auth_for_print->auth_token(),
- gaia_auth_for_talk->auth_token(), gaia_auth_for_talk->email()));
- backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &Core::NotifyAuthenticated, gaia_auth_for_print->auth_token(),
- gaia_auth_for_talk->auth_token(), gaia_auth_for_talk->email()));
- DoInitializeWithToken(gaia_auth_for_print->auth_token(),
- gaia_auth_for_talk->auth_token(),
- gaia_auth_for_talk->email(),
- proxy_id);
+ gaia_auth_for_print->set_message_loop(MessageLoop::current());
+ if (gaia_auth_for_print->AuthenticateWithLsid(lsid)) {
+ // Stash away the user email so we can save it in prefs.
+ user_email_ = gaia_auth_for_print->email();
+ // If the same user is re-enabling Cloud Print and we have stashed robot
+ // credentials, we will use those.
+ if ((0 == base::strcasecmp(user_email_.c_str(), last_user_email.c_str())) &&
+ !last_robot_refresh_token.empty() &&
+ !last_robot_email.empty()) {
+ DoInitializeWithRobotToken(last_robot_refresh_token,
+ last_robot_email,
+ proxy_id);
}
- }
-
- if (!auth_succeeded) {
+ DoInitializeWithToken(gaia_auth_for_print->auth_token(),
+ proxy_id);
+ } else {
// Let the frontend know the of authentication failure.
- backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &Core::NotifyAuthenticationFailed));
+ OnAuthError();
}
}
void CloudPrintProxyBackend::Core::DoInitializeWithToken(
const std::string cloud_print_token,
- const std::string cloud_print_xmpp_token,
- const std::string email, const std::string& proxy_id) {
+ const std::string& proxy_id) {
DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
VLOG(1) << "CP_PROXY: Starting proxy, id: " << proxy_id;
+ proxy_id_ = proxy_id;
+ GetTokenStore()->SetToken(cloud_print_token, false);
+
+ // We need to get the credentials of the robot here.
+ GURL get_authcode_url =
+ CloudPrintHelpers::GetUrlForGetAuthCode(cloud_print_server_url_,
+ oauth_client_info_.client_id,
+ proxy_id_);
+ next_response_handler_ =
+ &CloudPrintProxyBackend::Core::HandleGetAuthCodeResponse;
+ request_ = new CloudPrintURLFetcher;
+ request_->StartGetRequest(get_authcode_url,
+ this,
+ kCloudPrintAPIMaxRetryCount,
+ std::string());
+}
+
+void CloudPrintProxyBackend::Core::DoInitializeWithRobotToken(
+ const std::string& robot_oauth_refresh_token,
+ const std::string& robot_email,
+ const std::string& proxy_id) {
+ robot_email_ = robot_email;
+ proxy_id_ = proxy_id;
+ refresh_token_ = robot_oauth_refresh_token;
+ RefreshAccessToken();
+}
+void CloudPrintProxyBackend::Core::PostAuthInitialization() {
+ DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
+ // Now we can get down to registering printers.
print_system_ =
cloud_print::PrintSystem::CreateInstance(print_system_settings_.get());
if (!print_system_.get()) {
NOTREACHED();
return; // No print system available, fail initalization.
}
-
cloud_print::PrintSystem::PrintSystemResult result = print_system_->Init();
- // TODO(sanjeevr): Validate the tokens.
- auth_token_ = cloud_print_token;
-
if (result.succeeded()) {
notifier::NotifierOptions notifier_options;
notifier_options.request_context_getter =
g_service_process->GetServiceURLRequestContextGetter();
+ notifier_options.auth_mechanism = "X-OAUTH2";
talk_mediator_.reset(new notifier::TalkMediatorImpl(
new notifier::MediatorThreadImpl(notifier_options),
notifier_options));
notifier::Subscription subscription;
subscription.channel = kCloudPrintPushNotificationsSource;
subscription.channel.append("/proxy/");
- subscription.channel.append(proxy_id);
+ subscription.channel.append(proxy_id_);
subscription.from = kCloudPrintPushNotificationsSource;
push_notifications_channel_ = subscription.channel;
talk_mediator_->AddSubscription(subscription);
talk_mediator_->SetDelegate(this);
- talk_mediator_->SetAuthToken(email, cloud_print_xmpp_token,
- kSyncGaiaServiceId);
+ talk_mediator_->SetAuthToken(
+ robot_email_,
+ CloudPrintTokenStore::current()->token(),
+ kSyncGaiaServiceId);
talk_mediator_->Login();
print_server_watcher_ = print_system_->CreatePrintServerWatcher();
print_server_watcher_->StartWatching(this);
- proxy_id_ = proxy_id;
-
StartRegistration();
} else {
// We could not initialize the print system. We need to notify the server.
@@ -466,6 +550,7 @@ void CloudPrintProxyBackend::Core::DoShutdown() {
notifications_enabled_ = false;
notifications_enabled_since_ = base::TimeTicks();
request_ = NULL;
+ token_store_.reset();
}
void CloudPrintProxyBackend::Core::DoRegisterSelectedPrinters(
@@ -488,7 +573,6 @@ void CloudPrintProxyBackend::Core::GetRegisteredPrinters() {
request_ = new CloudPrintURLFetcher;
request_->StartGetRequest(printer_list_url,
this,
- auth_token_,
kCloudPrintAPIMaxRetryCount,
std::string());
}
@@ -581,7 +665,6 @@ void CloudPrintProxyBackend::Core::OnReceivePrinterCaps(
request_ = new CloudPrintURLFetcher;
request_->StartPostRequest(post_url,
this,
- auth_token_,
kCloudPrintAPIMaxRetryCount,
mime_type,
post_data,
@@ -642,6 +725,13 @@ void CloudPrintProxyBackend::Core::ScheduleJobPoll() {
}
}
+CloudPrintTokenStore* CloudPrintProxyBackend::Core::GetTokenStore() {
+ DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
+ if (!token_store_.get())
+ token_store_.reset(new CloudPrintTokenStore);
+ return token_store_.get();
+}
+
// CloudPrintURLFetcher::Delegate implementation.
CloudPrintURLFetcher::ResponseAction
CloudPrintProxyBackend::Core::HandleJSONData(
@@ -664,12 +754,13 @@ void CloudPrintProxyBackend::Core::NotifyPrinterListAvailable(
}
void CloudPrintProxyBackend::Core::NotifyAuthenticated(
- const std::string& cloud_print_token,
- const std::string& cloud_print_xmpp_token,
- const std::string& email) {
+ const std::string& robot_oauth_refresh_token,
+ const std::string& robot_email,
+ const std::string& user_email) {
DCHECK(MessageLoop::current() == backend_->frontend_loop_);
- backend_->frontend_->OnAuthenticated(cloud_print_token,
- cloud_print_xmpp_token, email);
+ backend_->frontend_->OnAuthenticated(robot_oauth_refresh_token,
+ robot_email,
+ user_email);
}
void CloudPrintProxyBackend::Core::NotifyAuthenticationFailed() {
@@ -683,6 +774,35 @@ void CloudPrintProxyBackend::Core::NotifyPrintSystemUnavailable() {
}
CloudPrintURLFetcher::ResponseAction
+CloudPrintProxyBackend::Core::HandleGetAuthCodeResponse(
+ const URLFetcher* source,
+ const GURL& url,
+ DictionaryValue* json_data,
+ bool succeeded) {
+ DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
+ if (!succeeded) {
+ OnAuthError();
+ return CloudPrintURLFetcher::STOP_PROCESSING;
+ }
+ std::string auth_code;
+ if (!json_data->GetString(kOAuthCodeValue, &auth_code)) {
+ OnAuthError();
+ return CloudPrintURLFetcher::STOP_PROCESSING;
+ }
+ json_data->GetString(kXMPPJidValue, &robot_email_);
+ // Now that we have an auth code we need to get the refresh and access tokens.
+ oauth_client_.reset(new gaia::GaiaOAuthClient(
+ gaia::kGaiaOAuth2Url,
+ g_service_process->GetServiceURLRequestContextGetter()));
+ oauth_client_->GetTokensFromAuthCode(oauth_client_info_,
+ auth_code,
+ kCloudPrintAPIMaxRetryCount,
+ this);
+
+ return CloudPrintURLFetcher::STOP_PROCESSING;
+}
+
+CloudPrintURLFetcher::ResponseAction
CloudPrintProxyBackend::Core::HandlePrinterListResponse(
const URLFetcher* source,
const GURL& url,
@@ -763,9 +883,11 @@ void CloudPrintProxyBackend::Core::InitJobHandlerForPrinter(
}
}
scoped_refptr<PrinterJobHandler> job_handler;
- job_handler = new PrinterJobHandler(printer_info, printer_info_cloud,
- auth_token_, cloud_print_server_url_,
- print_system_.get(), this);
+ job_handler = new PrinterJobHandler(printer_info,
+ printer_info_cloud,
+ cloud_print_server_url_,
+ print_system_.get(),
+ this);
job_handler_map_[printer_info_cloud.printer_id] = job_handler;
job_handler->Initialize();
}
@@ -795,7 +917,6 @@ void CloudPrintProxyBackend::Core::ReportUserMessage(
request_ = new CloudPrintURLFetcher;
request_->StartPostRequest(post_url,
this,
- auth_token_,
kCloudPrintAPIMaxRetryCount,
mime_type,
post_data,
@@ -885,6 +1006,17 @@ bool CloudPrintProxyBackend::Core::RemovePrinterFromList(
return false;
}
+void CloudPrintProxyBackend::Core::RefreshAccessToken() {
+ DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
+ oauth_client_.reset(new gaia::GaiaOAuthClient(
+ gaia::kGaiaOAuth2Url,
+ g_service_process->GetServiceURLRequestContextGetter()));
+ oauth_client_->RefreshToken(oauth_client_info_,
+ refresh_token_,
+ kCloudPrintAPIMaxRetryCount,
+ this);
+}
+
void CloudPrintProxyBackend::Core::OnNotificationStateChange(
bool notification_enabled) {
DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
@@ -951,3 +1083,59 @@ void CloudPrintProxyBackend::Core::OnPrinterNotFound(
// from the server.
*delete_from_server = complete_list_available_;
}
+
+ // gaia::GaiaOAuthClient::Delegate implementation.
+void CloudPrintProxyBackend::Core::OnGetTokensResponse(
+ const std::string& refresh_token,
+ const std::string& access_token,
+ int expires_in_seconds) {
+ refresh_token_ = refresh_token;
+ // After saving the refresh token, this is just like having just refreshed
+ // the access token. Just call OnRefreshTokenResponse.
+ OnRefreshTokenResponse(access_token, expires_in_seconds);
+}
+
+void CloudPrintProxyBackend::Core::OnRefreshTokenResponse(
+ const std::string& access_token, int expires_in_seconds) {
+ // If our current token is not OAuth, we either have no token at all or we
+ // have a ClientLogin token which we just exchanged for an OAuth token.
+ // In this case we need to do the startup initialiazation.
+ // TODO(sanjeevr): Use an enum for state instead of using this as a signal.
+ // I will do this in a follow-up change.
+ CloudPrintTokenStore* token_store = GetTokenStore();
+ bool first_time = !token_store->token_is_oauth();
+ token_store->SetToken(access_token, true);
+ // Let the frontend know that we have authenticated.
+ backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &Core::NotifyAuthenticated, refresh_token_, robot_email_, user_email_));
+ if (first_time) {
+ PostAuthInitialization();
+ } else {
+ // If we are refreshing a token, update the XMPP token too.
+ DCHECK(talk_mediator_.get());
+ talk_mediator_->SetAuthToken(robot_email_,
+ access_token,
+ kSyncGaiaServiceId);
+ }
+ // Schedule a task to refresh the access token again when it is about to
+ // expire.
+ DCHECK(expires_in_seconds > kTokenRefreshGracePeriodSecs);
+ int64 refresh_delay =
+ (expires_in_seconds - kTokenRefreshGracePeriodSecs)*1000;
+ MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &Core::RefreshAccessToken),
+ refresh_delay);
+}
+
+void CloudPrintProxyBackend::Core::OnOAuthError() {
+ OnAuthError();
+}
+
+void CloudPrintProxyBackend::Core::OnNetworkError(int response_code) {
+ // Since we specify inifinite retries on network errors, this should never
+ // be called.
+ NOTREACHED() <<
+ "OnNetworkError invoked when not expected, response code is " <<
+ response_code;
+}
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.h b/chrome/service/cloud_print/cloud_print_proxy_backend.h
index e1a3ef9..71cf92f 100644
--- a/chrome/service/cloud_print/cloud_print_proxy_backend.h
+++ b/chrome/service/cloud_print/cloud_print_proxy_backend.h
@@ -15,6 +15,10 @@ class CloudPrintProxyService;
class GURL;
class DictionaryValue;
+namespace gaia {
+struct OAuthClientInfo;
+}
+
// CloudPrintProxyFrontend is the interface used by CloudPrintProxyBackend to
// communicate with the entity that created it and, presumably, is interested in
// cloud print proxy related activity.
@@ -29,9 +33,9 @@ class CloudPrintProxyFrontend {
const printing::PrinterList& printer_list) = 0;
// We successfully authenticated with the cloud print server. This callback
// allows the frontend to persist the tokens.
- virtual void OnAuthenticated(const std::string& cloud_print_token,
- const std::string& cloud_print_xmpp_token,
- const std::string& email) = 0;
+ virtual void OnAuthenticated(const std::string& robot_oauth_refresh_token,
+ const std::string& robot_email,
+ const std::string& user_email) = 0;
// We have invalid/expired credentials.
virtual void OnAuthenticationFailed() = 0;
// The print system could not be initialized.
@@ -49,17 +53,31 @@ class CloudPrintProxyBackend {
public:
// It is OK for print_system_settings to be NULL. In this case system should
// use system default settings.
- explicit CloudPrintProxyBackend(CloudPrintProxyFrontend* frontend,
- const GURL& cloud_print_server_url,
- const DictionaryValue* print_sys_settings,
- bool enable_job_poll);
+ CloudPrintProxyBackend(
+ CloudPrintProxyFrontend* frontend,
+ const GURL& cloud_print_server_url,
+ const DictionaryValue* print_sys_settings,
+ const gaia::OAuthClientInfo& oauth_client_info,
+ bool enable_job_poll);
~CloudPrintProxyBackend();
- bool InitializeWithLsid(const std::string& lsid, const std::string& proxy_id);
+ // Called when the user enables Google Cloud Print.
+ // |last_robot_refresh_token|, |last_robot_email| and |last_user_email| are
+ // the previously persisted credentials if any. We will use this is the passed
+ // in LSID belongs to the same user as |last_user_email|.
+ bool InitializeWithLsid(const std::string& lsid,
+ const std::string& proxy_id,
+ const std::string& last_robot_refresh_token,
+ const std::string& last_robot_email,
+ const std::string& last_user_email);
+ // Legacy mechanism when we have saved user credentials but no saved robot
+ // credentials.
bool InitializeWithToken(const std::string& cloud_print_token,
- const std::string& cloud_print_xmpp_token,
- const std::string& email,
const std::string& proxy_id);
+ // Called when we have saved robot credentials.
+ bool InitializeWithRobotToken(const std::string& robot_oauth_refresh_token,
+ const std::string& robot_email,
+ const std::string& proxy_id);
void Shutdown();
void RegisterPrinters(const printing::PrinterList& printer_list);
diff --git a/chrome/service/cloud_print/cloud_print_token_store.cc b/chrome/service/cloud_print/cloud_print_token_store.cc
new file mode 100644
index 0000000..5c38314
--- /dev/null
+++ b/chrome/service/cloud_print/cloud_print_token_store.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 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_token_store.h"
+
+#include "base/lazy_instance.h"
+#include "base/threading/thread_local.h"
+
+// Keep the global CloudPrintTokenStore in a TLS slot so it is impossible to
+// incorrectly from the wrong thread.
+static base::LazyInstance<base::ThreadLocalPointer<CloudPrintTokenStore> >
+ lazy_tls(base::LINKER_INITIALIZED);
+
+CloudPrintTokenStore* CloudPrintTokenStore::current() {
+ return lazy_tls.Pointer()->Get();
+}
+
+CloudPrintTokenStore::CloudPrintTokenStore() : token_is_oauth_(false) {
+ lazy_tls.Pointer()->Set(this);
+}
+
+CloudPrintTokenStore::~CloudPrintTokenStore() {
+ lazy_tls.Pointer()->Set(NULL);
+}
+
+void CloudPrintTokenStore::SetToken(const std::string& token, bool is_oauth) {
+ DCHECK(CalledOnValidThread());
+ token_ = token;
+ token_is_oauth_ = is_oauth;
+}
diff --git a/chrome/service/cloud_print/cloud_print_token_store.h b/chrome/service/cloud_print/cloud_print_token_store.h
new file mode 100644
index 0000000..b136983
--- /dev/null
+++ b/chrome/service/cloud_print/cloud_print_token_store.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 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.
+
+#ifndef CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_TOKEN_STORE_H_
+#define CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_TOKEN_STORE_H_
+#pragma once
+
+#include <string>
+
+// This class serves as the single repository for cloud print auth tokens. This
+// is only used within the CloudPrintProxyCoreThread.
+
+#include "base/logging.h"
+#include "base/threading/non_thread_safe.h"
+
+class CloudPrintTokenStore : public base::NonThreadSafe {
+ public:
+ // Returns the CloudPrintTokenStore instance for this thread. Will be NULL
+ // if no instance was created in this thread before.
+ static CloudPrintTokenStore* current();
+
+ CloudPrintTokenStore();
+ ~CloudPrintTokenStore();
+
+ void SetToken(const std::string& token, bool is_oauth);
+ std::string token() const {
+ DCHECK(CalledOnValidThread());
+ return token_;
+ }
+ bool token_is_oauth() const {
+ DCHECK(CalledOnValidThread());
+ return token_is_oauth_;
+ }
+
+ private:
+ std::string token_;
+ bool token_is_oauth_;
+
+ DISALLOW_COPY_AND_ASSIGN(CloudPrintTokenStore);
+};
+
+#endif // CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_TOKEN_STORE_H_
diff --git a/chrome/service/cloud_print/cloud_print_token_store_unittest.cc b/chrome/service/cloud_print/cloud_print_token_store_unittest.cc
new file mode 100644
index 0000000..9cf9339
--- /dev/null
+++ b/chrome/service/cloud_print/cloud_print_token_store_unittest.cc
@@ -0,0 +1,22 @@
+// Copyright (c) 2011 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_token_store.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(CloudPrintTokenStoreTest, Basic) {
+ EXPECT_EQ(NULL, CloudPrintTokenStore::current());
+ CloudPrintTokenStore* store = new CloudPrintTokenStore;
+ EXPECT_EQ(store, CloudPrintTokenStore::current());
+ CloudPrintTokenStore::current()->SetToken("myclientlogintoken", false);
+ EXPECT_EQ(CloudPrintTokenStore::current()->token(), "myclientlogintoken");
+ EXPECT_FALSE(CloudPrintTokenStore::current()->token_is_oauth());
+ CloudPrintTokenStore::current()->SetToken("myoauth2token", true);
+ EXPECT_EQ(CloudPrintTokenStore::current()->token(), "myoauth2token");
+ EXPECT_TRUE(CloudPrintTokenStore::current()->token_is_oauth());
+ delete store;
+ EXPECT_EQ(NULL, CloudPrintTokenStore::current());
+}
+
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher.cc b/chrome/service/cloud_print/cloud_print_url_fetcher.cc
index 6fa7510..ad4734e 100644
--- a/chrome/service/cloud_print/cloud_print_url_fetcher.cc
+++ b/chrome/service/cloud_print/cloud_print_url_fetcher.cc
@@ -9,6 +9,7 @@
#include "chrome/common/net/http_return.h"
#include "chrome/service/cloud_print/cloud_print_consts.h"
#include "chrome/service/cloud_print/cloud_print_helpers.h"
+#include "chrome/service/cloud_print/cloud_print_token_store.h"
#include "chrome/service/net/service_url_request_context.h"
#include "chrome/service/service_process.h"
#include "googleurl/src/gurl.h"
@@ -22,23 +23,31 @@ CloudPrintURLFetcher::CloudPrintURLFetcher()
void CloudPrintURLFetcher::StartGetRequest(
const GURL& url,
Delegate* delegate,
- const std::string& auth_token,
int max_retries,
const std::string& additional_headers) {
- StartRequestHelper(url, URLFetcher::GET, delegate, auth_token, max_retries,
- std::string(), std::string(), additional_headers);
+ StartRequestHelper(url,
+ URLFetcher::GET,
+ delegate,
+ max_retries,
+ std::string(),
+ std::string(),
+ additional_headers);
}
void CloudPrintURLFetcher::StartPostRequest(
const GURL& url,
Delegate* delegate,
- const std::string& auth_token,
int max_retries,
const std::string& post_data_mime_type,
const std::string& post_data,
const std::string& additional_headers) {
- StartRequestHelper(url, URLFetcher::POST, delegate, auth_token, max_retries,
- post_data_mime_type, post_data, additional_headers);
+ StartRequestHelper(url,
+ URLFetcher::POST,
+ delegate,
+ max_retries,
+ post_data_mime_type,
+ post_data,
+ additional_headers);
}
// URLFetcher::Delegate implementation.
@@ -60,8 +69,11 @@ void CloudPrintURLFetcher::OnURLFetchComplete(
cookies,
data);
if (action == CONTINUE_PROCESSING) {
- // If there was an auth error, we are done.
- if (RC_FORBIDDEN == response_code) {
+ // If we are not using an OAuth token, and we got an auth error, we are
+ // done. Else, the token may have been refreshed. Let us try again.
+ if ((RC_FORBIDDEN == response_code) &&
+ (!CloudPrintTokenStore::current() ||
+ !CloudPrintTokenStore::current()->token_is_oauth())) {
delegate_->OnRequestAuthError();
return;
}
@@ -104,7 +116,9 @@ void CloudPrintURLFetcher::OnURLFetchComplete(
delegate_->OnRequestGiveUp();
} else {
// Either no retry limit specified or retry limit has not yet been
- // reached. Try again.
+ // reached. Try again. Set up the request headers again because the token
+ // may have changed.
+ SetupRequestHeaders();
request_->Start();
}
}
@@ -114,27 +128,20 @@ void CloudPrintURLFetcher::StartRequestHelper(
const GURL& url,
URLFetcher::RequestType request_type,
Delegate* delegate,
- const std::string& auth_token,
int max_retries,
const std::string& post_data_mime_type,
const std::string& post_data,
const std::string& additional_headers) {
DCHECK(delegate);
+ // Persist the additional headers in case we need to retry the request.
+ additional_headers_ = additional_headers;
request_.reset(new URLFetcher(url, request_type, this));
request_->set_request_context(GetRequestContextGetter());
// Since we implement our own retry logic, disable the retry in URLFetcher.
request_->set_automatically_retry_on_5xx(false);
request_->set_max_retries(max_retries);
+ SetupRequestHeaders();
delegate_ = delegate;
- std::string headers = "Authorization: GoogleLogin auth=";
- headers += auth_token;
- headers += "\r\n";
- headers += kChromeCloudPrintProxyHeader;
- if (!additional_headers.empty()) {
- headers += "\r\n";
- headers += additional_headers;
- }
- request_->set_extra_request_headers(headers);
if (request_type == URLFetcher::POST) {
request_->set_upload_data(post_data_mime_type, post_data);
}
@@ -142,6 +149,23 @@ void CloudPrintURLFetcher::StartRequestHelper(
request_->Start();
}
+void CloudPrintURLFetcher::SetupRequestHeaders() {
+ std::string headers;
+ CloudPrintTokenStore* token_store = CloudPrintTokenStore::current();
+ if (token_store) {
+ headers = token_store->token_is_oauth() ?
+ "Authorization: OAuth " : "Authorization: GoogleLogin auth=";
+ headers += token_store->token();
+ headers += "\r\n";
+ }
+ headers += kChromeCloudPrintProxyHeader;
+ if (!additional_headers_.empty()) {
+ headers += "\r\n";
+ headers += additional_headers_;
+ }
+ request_->set_extra_request_headers(headers);
+}
+
CloudPrintURLFetcher::~CloudPrintURLFetcher() {}
net::URLRequestContextGetter* CloudPrintURLFetcher::GetRequestContextGetter() {
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher.h b/chrome/service/cloud_print/cloud_print_url_fetcher.h
index c56fd16..433ed56 100644
--- a/chrome/service/cloud_print/cloud_print_url_fetcher.h
+++ b/chrome/service/cloud_print/cloud_print_url_fetcher.h
@@ -73,19 +73,17 @@ class CloudPrintURLFetcher
// was a retry limit - a limit of -1 implies no limit).
virtual void OnRequestGiveUp() { }
// Invoked when the request returns a 403 error (applicable only when
- // HandleRawResponse returns CONTINUE_PROCESSING)
+ // HandleRawResponse returns CONTINUE_PROCESSING).
virtual void OnRequestAuthError() = 0;
};
CloudPrintURLFetcher();
void StartGetRequest(const GURL& url,
Delegate* delegate,
- const std::string& auth_token,
int max_retries,
const std::string& additional_headers);
void StartPostRequest(const GURL& url,
Delegate* delegate,
- const std::string& auth_token,
int max_retries,
const std::string& post_data_mime_type,
const std::string& post_data,
@@ -108,15 +106,16 @@ class CloudPrintURLFetcher
void StartRequestHelper(const GURL& url,
URLFetcher::RequestType request_type,
Delegate* delegate,
- const std::string& auth_token,
int max_retries,
const std::string& post_data_mime_type,
const std::string& post_data,
const std::string& additional_headers);
+ void SetupRequestHeaders();
scoped_ptr<URLFetcher> request_;
Delegate* delegate_;
int num_retries_;
+ std::string additional_headers_;
};
typedef CloudPrintURLFetcher::Delegate CloudPrintURLFetcherDelegate;
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc b/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc
index 4e61856..6a2637d 100644
--- a/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc
+++ b/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc
@@ -192,7 +192,7 @@ void CloudPrintURLFetcherTest::CreateFetcher(const GURL& url, int max_retries) {
fetcher_ = new TestCloudPrintURLFetcher(io_message_loop_proxy());
max_retries_ = max_retries;
start_time_ = Time::Now();
- fetcher_->StartGetRequest(url, this, "", max_retries_, std::string());
+ fetcher_->StartGetRequest(url, this, max_retries_, std::string());
}
CloudPrintURLFetcher::ResponseAction
@@ -264,7 +264,10 @@ CloudPrintURLFetcherOverloadTest::HandleRawData(const URLFetcher* source,
const TimeDelta one_second = TimeDelta::FromMilliseconds(1000);
response_count_++;
if (response_count_ < 20) {
- fetcher_->StartGetRequest(url, this, "", max_retries_, std::string());
+ fetcher_->StartGetRequest(url,
+ this,
+ max_retries_,
+ std::string());
} else {
// We have already sent 20 requests continuously. And we expect that
// it takes more than 1 second due to the overload protection settings.
diff --git a/chrome/service/cloud_print/job_status_updater.cc b/chrome/service/cloud_print/job_status_updater.cc
index 56632b1..2f16536 100644
--- a/chrome/service/cloud_print/job_status_updater.cc
+++ b/chrome/service/cloud_print/job_status_updater.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -15,12 +15,11 @@
JobStatusUpdater::JobStatusUpdater(const std::string& printer_name,
const std::string& job_id,
cloud_print::PlatformJobId& local_job_id,
- const std::string& auth_token,
const GURL& cloud_print_server_url,
cloud_print::PrintSystem* print_system,
Delegate* delegate)
: printer_name_(printer_name), job_id_(job_id),
- local_job_id_(local_job_id), auth_token_(auth_token),
+ local_job_id_(local_job_id),
cloud_print_server_url_(cloud_print_server_url),
print_system_(print_system), delegate_(delegate), stopped_(false) {
DCHECK(delegate_);
@@ -63,7 +62,6 @@ void JobStatusUpdater::UpdateStatus() {
CloudPrintHelpers::GetUrlForJobStatusUpdate(
cloud_print_server_url_, job_id_, last_job_details_),
this,
- auth_token_,
kCloudPrintAPIMaxRetryCount,
std::string());
}
diff --git a/chrome/service/cloud_print/job_status_updater.h b/chrome/service/cloud_print/job_status_updater.h
index 9c7f6cf..cece13a 100644
--- a/chrome/service/cloud_print/job_status_updater.h
+++ b/chrome/service/cloud_print/job_status_updater.h
@@ -35,7 +35,6 @@ class JobStatusUpdater : public base::RefCountedThreadSafe<JobStatusUpdater>,
JobStatusUpdater(const std::string& printer_name,
const std::string& job_id,
cloud_print::PlatformJobId& local_job_id,
- const std::string& auth_token,
const GURL& cloud_print_server_url,
cloud_print::PrintSystem* print_system,
Delegate* delegate);
@@ -59,7 +58,6 @@ class JobStatusUpdater : public base::RefCountedThreadSafe<JobStatusUpdater>,
cloud_print::PlatformJobId local_job_id_;
cloud_print::PrintJobDetails last_job_details_;
scoped_refptr<CloudPrintURLFetcher> request_;
- std::string auth_token_;
GURL cloud_print_server_url_;
scoped_refptr<cloud_print::PrintSystem> print_system_;
Delegate* delegate_;
diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc
index 20ea7f4..5aba550 100644
--- a/chrome/service/cloud_print/printer_job_handler.cc
+++ b/chrome/service/cloud_print/printer_job_handler.cc
@@ -33,14 +33,12 @@ void PrinterJobHandler::JobDetails::Clear() {
PrinterJobHandler::PrinterJobHandler(
const printing::PrinterBasicInfo& printer_info,
const PrinterInfoFromCloud& printer_info_cloud,
- const std::string& auth_token,
const GURL& cloud_print_server_url,
cloud_print::PrintSystem* print_system,
Delegate* delegate)
: print_system_(print_system),
printer_info_(printer_info),
printer_info_cloud_(printer_info_cloud),
- auth_token_(auth_token),
cloud_print_server_url_(cloud_print_server_url),
delegate_(delegate),
local_job_id_(-1),
@@ -110,7 +108,6 @@ void PrinterJobHandler::Start() {
CloudPrintHelpers::GetUrlForPrinterDelete(
cloud_print_server_url_, printer_info_cloud_.printer_id),
this,
- auth_token_,
kCloudPrintAPIMaxRetryCount,
std::string());
}
@@ -129,7 +126,6 @@ void PrinterJobHandler::Start() {
cloud_print_server_url_, printer_info_cloud_.printer_id,
job_fetch_reason_),
this,
- auth_token_,
kCloudPrintAPIMaxRetryCount,
std::string());
last_job_fetch_time_ = base::TimeTicks::Now();
@@ -261,7 +257,6 @@ void PrinterJobHandler::OnReceivePrinterCaps(
CloudPrintHelpers::GetUrlForPrinterUpdate(
cloud_print_server_url_, printer_info_cloud_.printer_id),
this,
- auth_token_,
kCloudPrintAPIMaxRetryCount,
mime_type,
post_data,
@@ -443,7 +438,6 @@ PrinterJobHandler::HandleJobMetadataResponse(
request_ = new CloudPrintURLFetcher;
request_->StartGetRequest(GURL(print_ticket_url.c_str()),
this,
- auth_token_,
kCloudPrintAPIMaxRetryCount,
std::string());
}
@@ -470,7 +464,6 @@ PrinterJobHandler::HandlePrintTicketResponse(const URLFetcher* source,
accept_headers += print_system_->GetSupportedMimeTypes();
request_->StartGetRequest(GURL(print_data_url_.c_str()),
this,
- auth_token_,
kJobDataMaxRetryCount,
accept_headers);
} else {
@@ -520,7 +513,7 @@ PrinterJobHandler::HandleSuccessStatusUpdateResponse(
// that monitors the status of the job and updates the server.
scoped_refptr<JobStatusUpdater> job_status_updater(
new JobStatusUpdater(printer_info_.printer_name, job_details_.job_id_,
- local_job_id_, auth_token_, cloud_print_server_url_,
+ local_job_id_, cloud_print_server_url_,
print_system_.get(), this));
job_status_updater_list_.push_back(job_status_updater);
MessageLoop::current()->PostTask(
@@ -619,7 +612,6 @@ void PrinterJobHandler::UpdateJobStatus(cloud_print::PrintJobStatus status,
job_details_.job_id_,
status),
this,
- auth_token_,
kCloudPrintAPIMaxRetryCount,
std::string());
}
diff --git a/chrome/service/cloud_print/printer_job_handler.h b/chrome/service/cloud_print/printer_job_handler.h
index 8633875..6e804f9 100644
--- a/chrome/service/cloud_print/printer_job_handler.h
+++ b/chrome/service/cloud_print/printer_job_handler.h
@@ -110,7 +110,6 @@ class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>,
// Begin public interface
PrinterJobHandler(const printing::PrinterBasicInfo& printer_info,
const PrinterInfoFromCloud& printer_info_from_server,
- const std::string& auth_token,
const GURL& cloud_print_server_url,
cloud_print::PrintSystem* print_system,
Delegate* delegate);
@@ -256,7 +255,6 @@ class PrinterJobHandler : public base::RefCountedThreadSafe<PrinterJobHandler>,
scoped_refptr<cloud_print::PrintSystem> print_system_;
printing::PrinterBasicInfo printer_info_;
PrinterInfoFromCloud printer_info_cloud_;
- std::string auth_token_;
GURL cloud_print_server_url_;
std::string print_data_url_;
JobDetails job_details_;
diff --git a/chrome/service/service_process_prefs.cc b/chrome/service/service_process_prefs.cc
index 7aa94b05..8eb2962 100644
--- a/chrome/service/service_process_prefs.cc
+++ b/chrome/service/service_process_prefs.cc
@@ -54,3 +54,7 @@ void ServiceProcessPrefs::GetDictionary(const std::string& key,
*result = static_cast<const DictionaryValue*>(value);
}
+
+void ServiceProcessPrefs::RemovePref(const std::string& key) {
+ prefs_->RemoveValue(key);
+}
diff --git a/chrome/service/service_process_prefs.h b/chrome/service/service_process_prefs.h
index a16f620..6816f50 100644
--- a/chrome/service/service_process_prefs.h
+++ b/chrome/service/service_process_prefs.h
@@ -41,6 +41,9 @@ class ServiceProcessPrefs {
// Get a dictionary preference for |key| and store it in |result|.
void GetDictionary(const std::string& key, const DictionaryValue** result);
+ // Removes the pref specified by |key|.
+ void RemovePref(const std::string& key);
+
private:
scoped_refptr<JsonPrefStore> prefs_;