Index: chrome/browser/extensions/app_notify_channel_setup.cc |
=================================================================== |
--- chrome/browser/extensions/app_notify_channel_setup.cc (revision 108838) |
+++ chrome/browser/extensions/app_notify_channel_setup.cc (working copy) |
@@ -4,6 +4,7 @@ |
#include "chrome/browser/extensions/app_notify_channel_setup.h" |
+#include "base/basictypes.h" |
#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/json/json_reader.h" |
@@ -11,11 +12,14 @@ |
#include "chrome/browser/net/gaia/token_service.h" |
#include "chrome/browser/prefs/pref_service.h" |
#include "chrome/browser/profiles/profile.h" |
+#include "chrome/common/chrome_notification_types.h" |
#include "chrome/common/chrome_switches.h" |
#include "chrome/common/net/gaia/gaia_constants.h" |
#include "chrome/common/net/http_return.h" |
#include "chrome/common/pref_names.h" |
#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/notification_details.h" |
+#include "content/public/browser/notification_service.h" |
#include "content/public/common/url_fetcher.h" |
#include "net/base/escape.h" |
#include "net/base/load_flags.h" |
@@ -46,6 +50,11 @@ |
static const char kCWSChannelServiceURL[] = |
"https://www-googleapis-staging.sandbox.google.com/chromewebstore/" |
"v1internal/channels/app_id/oauth_client_id"; |
+static const char* kRelevantGaiaServices[] = { |
+ GaiaConstants::kCWSService, |
+ GaiaConstants::kLSOService, |
+}; |
+static const int kRelevantGaiaServicesCount = arraysize(kRelevantGaiaServices); |
} // namespace. |
AppNotifyChannelSetup::AppNotifyChannelSetup( |
@@ -65,43 +74,63 @@ |
callback_id_(callback_id), |
delegate_(delegate), |
ui_(ui), |
- state_(INITIAL) {} |
+ state_(INITIAL), |
+ fetch_token_success_count_(0), |
+ fetch_token_fail_count_(0) {} |
AppNotifyChannelSetup::~AppNotifyChannelSetup() {} |
void AppNotifyChannelSetup::Start() { |
- AddRef(); // Balanced in ReportResult. |
+ AddRef(); // Balanced in ReportResult. |
+ BeginLogin(); |
+} |
- CHECK_EQ(INITIAL, state_); |
+void AppNotifyChannelSetup::Observe( |
+ int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ if (type == chrome::NOTIFICATION_TOKEN_AVAILABLE) { |
+ TokenService::TokenAvailableDetails* tok_details = |
+ content::Details<TokenService::TokenAvailableDetails>(details).ptr(); |
+ if (IsGaiaServiceRelevant(tok_details->service())) |
+ ++fetch_token_success_count_; |
+ } else if (type == chrome::NOTIFICATION_TOKEN_REQUEST_FAILED) { |
+ TokenService::TokenRequestFailedDetails* error_details = |
+ content::Details<TokenService::TokenRequestFailedDetails>( |
+ details).ptr(); |
+ if (IsGaiaServiceRelevant(error_details->service())) |
+ ++fetch_token_fail_count_; |
+ } else { |
+ CHECK(false) << "Received a notification not registered for."; |
+ } |
- // Check if the user is logged in to the browser. |
- std::string username = profile_->GetPrefs()->GetString( |
- prefs::kGoogleServicesUsername); |
+ // If we already got fetch results (success + failure) for all services |
+ // we care about, we are done with fetching tokens. |
+ if (fetch_token_success_count_ + fetch_token_fail_count_ == |
+ kRelevantGaiaServicesCount) { |
+ UnregisterForTokenServiceNotifications(); |
+ // We successfully fetched tokens if success count is equal to the |
+ // number of services we care about. |
+ bool success = (fetch_token_success_count_ == kRelevantGaiaServicesCount); |
+ EndFetchTokens(success); |
+ } |
+} |
- if (username.empty()) { |
- state_ = LOGIN_STARTED; |
- ui_->PromptSyncSetup(this); |
- return; // We'll get called back in OnSyncSetupResult |
+bool AppNotifyChannelSetup::ShouldFetchServiceTokens() const { |
+ TokenService* token_service = profile_->GetTokenService(); |
+ for (int i = 0; i < kRelevantGaiaServicesCount; ++i) { |
+ if (!token_service->HasTokenForService(kRelevantGaiaServices[i])) |
+ return true; |
} |
- |
- state_ = LOGIN_DONE; |
- BeginRecordGrant(); |
+ return false; |
} |
void AppNotifyChannelSetup::OnSyncSetupResult(bool enabled) { |
- CHECK_EQ(LOGIN_STARTED, state_); |
- if (enabled) { |
- state_ = LOGIN_DONE; |
- BeginRecordGrant(); |
- } else { |
- state_ = ERROR_STATE; |
- ReportResult("", kChannelSetupCanceledByUser); |
- } |
+ EndLogin(enabled); |
} |
void AppNotifyChannelSetup::OnURLFetchComplete(const URLFetcher* source) { |
CHECK(source); |
- |
switch (state_) { |
case RECORD_GRANT_STARTED: |
EndRecordGrant(source); |
@@ -133,8 +162,85 @@ |
return fetcher; |
} |
+// static |
+bool AppNotifyChannelSetup::IsGaiaServiceRelevant(const std::string& service) { |
+ for (int i = 0; i < kRelevantGaiaServicesCount; ++i) { |
+ if (service == kRelevantGaiaServices[i]) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+void AppNotifyChannelSetup::RegisterForTokenServiceNotifications() { |
+ content::Source<TokenService> token_service(profile_->GetTokenService()); |
+ registrar_.Add(this, |
+ chrome::NOTIFICATION_TOKEN_AVAILABLE, |
+ token_service); |
+ registrar_.Add(this, |
+ chrome::NOTIFICATION_TOKEN_REQUEST_FAILED, |
+ token_service); |
+} |
+ |
+void AppNotifyChannelSetup::UnregisterForTokenServiceNotifications() { |
+ registrar_.RemoveAll(); |
+} |
+ |
+bool AppNotifyChannelSetup::ShouldPromptForLogin() const { |
+ std::string username = profile_->GetPrefs()->GetString( |
+ prefs::kGoogleServicesUsername); |
+ return username.empty(); |
+} |
+ |
+void AppNotifyChannelSetup::BeginLogin() { |
+ CHECK_EQ(INITIAL, state_); |
+ state_ = LOGIN_STARTED; |
+ if (ShouldPromptForLogin()) { |
+ ui_->PromptSyncSetup(this); |
+ // We'll get called back in OnSyncSetupResult |
+ } else { |
+ EndLogin(true); |
+ } |
+} |
+ |
+void AppNotifyChannelSetup::EndLogin(bool success) { |
+ CHECK_EQ(LOGIN_STARTED, state_); |
+ if (success) { |
+ state_ = LOGIN_DONE; |
+ BeginFetchTokens(); |
+ } else { |
+ state_ = ERROR_STATE; |
+ ReportResult("", kChannelSetupCanceledByUser); |
+ } |
+} |
+ |
+void AppNotifyChannelSetup::BeginFetchTokens() { |
+ CHECK_EQ(LOGIN_DONE, state_); |
+ state_ = FETCH_TOKEN_STARTED; |
+ if (ShouldFetchServiceTokens()) { |
+ // If a user is logged in already, and a new version of Chrome is released |
+ // with new services added to Tokenservice, TokenService will not have |
+ // tokens for the new services. |
+ RegisterForTokenServiceNotifications(); |
+ profile_->GetTokenService()->StartFetchingMissingTokens(); |
+ // Observe will get called with notifications from TokenService. |
+ } else { |
+ EndFetchTokens(true); |
+ } |
+} |
+ |
+void AppNotifyChannelSetup::EndFetchTokens(bool success) { |
+ CHECK_EQ(FETCH_TOKEN_STARTED, state_); |
+ if (success) { |
+ state_ = FETCH_TOKEN_DONE; |
+ BeginRecordGrant(); |
+ } else { |
+ state_ = ERROR_STATE; |
+ ReportResult("", kChannelSetupInternalError); |
+ } |
+} |
+ |
void AppNotifyChannelSetup::BeginRecordGrant() { |
- CHECK_EQ(LOGIN_DONE, state_); |
+ CHECK(FETCH_TOKEN_DONE == state_); |
state_ = RECORD_GRANT_STARTED; |
GURL url = GetOAuth2IssueTokenURL(); |