summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authormunjal@chromium.org <munjal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-17 00:59:35 +0000
committermunjal@chromium.org <munjal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-17 00:59:35 +0000
commit0293a70dbc055eb610e4f59ff9ffc6420ef0a719 (patch)
tree8938e913e56c80639708e16667472e846e2f235f /chrome/browser
parentf256d3b5a521adddb7aaeeb8ec336038be8d6581 (diff)
downloadchromium_src-0293a70dbc055eb610e4f59ff9ffc6420ef0a719.zip
chromium_src-0293a70dbc055eb610e4f59ff9ffc6420ef0a719.tar.gz
chromium_src-0293a70dbc055eb610e4f59ff9ffc6420ef0a719.tar.bz2
Integrate AppNotifyChannelSetup with TokenService.
Review URL: http://codereview.chromium.org/8526015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110410 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/extensions/app_notify_channel_setup.cc152
-rw-r--r--chrome/browser/extensions/app_notify_channel_setup.h29
-rw-r--r--chrome/browser/extensions/app_notify_channel_setup_unittest.cc87
3 files changed, 234 insertions, 34 deletions
diff --git a/chrome/browser/extensions/app_notify_channel_setup.cc b/chrome/browser/extensions/app_notify_channel_setup.cc
index 429ea86..4712c4c 100644
--- a/chrome/browser/extensions/app_notify_channel_setup.cc
+++ b/chrome/browser/extensions/app_notify_channel_setup.cc
@@ -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 kOAuth2IssueTokenScope[] =
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 @@ AppNotifyChannelSetup::AppNotifyChannelSetup(
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.
-
- CHECK_EQ(INITIAL, state_);
+ AddRef(); // Balanced in ReportResult.
+ BeginLogin();
+}
- // Check if the user is logged in to the browser.
- std::string username = profile_->GetPrefs()->GetString(
- prefs::kGoogleServicesUsername);
+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.";
+ }
- if (username.empty()) {
- state_ = LOGIN_STARTED;
- ui_->PromptSyncSetup(this);
- return; // We'll get called back in OnSyncSetupResult
+ // 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);
}
+}
- state_ = LOGIN_DONE;
- BeginRecordGrant();
+bool AppNotifyChannelSetup::ShouldFetchServiceTokens() const {
+ TokenService* token_service = profile_->GetTokenService();
+ for (int i = 0; i < kRelevantGaiaServicesCount; ++i) {
+ if (!token_service->HasTokenForService(kRelevantGaiaServices[i]))
+ return true;
+ }
+ 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 @@ URLFetcher* AppNotifyChannelSetup::CreateURLFetcher(
return fetcher;
}
-void AppNotifyChannelSetup::BeginRecordGrant() {
+// 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(FETCH_TOKEN_DONE == state_);
state_ = RECORD_GRANT_STARTED;
GURL url = GetOAuth2IssueTokenURL();
diff --git a/chrome/browser/extensions/app_notify_channel_setup.h b/chrome/browser/extensions/app_notify_channel_setup.h
index e748e15..d960ee0 100644
--- a/chrome/browser/extensions/app_notify_channel_setup.h
+++ b/chrome/browser/extensions/app_notify_channel_setup.h
@@ -9,6 +9,8 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/extensions/app_notify_channel_ui.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
#include "content/public/common/url_fetcher.h"
#include "content/public/common/url_fetcher_delegate.h"
#include "googleurl/src/gurl.h"
@@ -16,6 +18,10 @@
class AppNotifyChannelSetupTest;
class Profile;
+namespace content {
+class NotificationDetails;
+}
+
// This class uses the browser login credentials to setup app notifications
// for a given app.
//
@@ -27,6 +33,7 @@ class Profile;
// the above steps.
class AppNotifyChannelSetup
: public content::URLFetcherDelegate,
+ public content::NotificationObserver,
public AppNotifyChannelUI::Delegate,
public base::RefCountedThreadSafe<AppNotifyChannelSetup> {
public:
@@ -51,10 +58,16 @@ class AppNotifyChannelSetup
AppNotifyChannelUI* ui,
base::WeakPtr<Delegate> delegate);
+ AppNotifyChannelUI* ui() { return ui_.get(); }
+
// This begins the process of fetching the channel id using the browser login
// credentials (or using |ui_| to prompt for login if needed).
void Start();
+ // Implementing content::NotificationObserver interface.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
protected:
// content::URLFetcherDelegate.
virtual void OnURLFetchComplete(const content::URLFetcher* source) OVERRIDE;
@@ -67,6 +80,8 @@ class AppNotifyChannelSetup
INITIAL,
LOGIN_STARTED,
LOGIN_DONE,
+ FETCH_TOKEN_STARTED,
+ FETCH_TOKEN_DONE,
RECORD_GRANT_STARTED,
RECORD_GRANT_DONE,
CHANNEL_ID_SETUP_STARTED,
@@ -84,6 +99,10 @@ class AppNotifyChannelSetup
// Caller owns the returned instance.
content::URLFetcher* CreateURLFetcher(
const GURL& url, const std::string& body, const std::string& auth_token);
+ void BeginLogin();
+ void EndLogin(bool success);
+ void BeginFetchTokens();
+ void EndFetchTokens(bool success);
void BeginRecordGrant();
void EndRecordGrant(const content::URLFetcher* source);
void BeginGetChannelId();
@@ -100,8 +119,16 @@ class AppNotifyChannelSetup
std::string GetCWSAuthToken();
static bool ParseCWSChannelServiceResponse(
const std::string& data, std::string* result);
+ static bool IsGaiaServiceRelevant(const std::string& service);
+ // Checks if the user needs to be prompted for login.
+ bool ShouldPromptForLogin() const;
+ // Checks if we need to fetch auth tokens for services we care about.
+ virtual bool ShouldFetchServiceTokens() const;
+ void RegisterForTokenServiceNotifications();
+ void UnregisterForTokenServiceNotifications();
Profile* profile_;
+ content::NotificationRegistrar registrar_;
std::string extension_id_;
std::string client_id_;
GURL requestor_url_;
@@ -111,6 +138,8 @@ class AppNotifyChannelSetup
scoped_ptr<content::URLFetcher> url_fetcher_;
scoped_ptr<AppNotifyChannelUI> ui_;
State state_;
+ int fetch_token_success_count_;
+ int fetch_token_fail_count_;
DISALLOW_COPY_AND_ASSIGN(AppNotifyChannelSetup);
};
diff --git a/chrome/browser/extensions/app_notify_channel_setup_unittest.cc b/chrome/browser/extensions/app_notify_channel_setup_unittest.cc
index 70ce352..29c4511 100644
--- a/chrome/browser/extensions/app_notify_channel_setup_unittest.cc
+++ b/chrome/browser/extensions/app_notify_channel_setup_unittest.cc
@@ -8,16 +8,23 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "chrome/browser/extensions/app_notify_channel_setup.h"
+#include "chrome/browser/extensions/app_notify_channel_ui.h"
+#include "chrome/browser/net/gaia/token_service.h"
+#include "chrome/browser/net/gaia/token_service_unittest.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/net/gaia/gaia_urls.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_pref_service.h"
#include "chrome/test/base/testing_profile.h"
#include "content/test/test_browser_thread.h"
#include "content/test/test_url_fetcher_factory.h"
#include "googleurl/src/gurl.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using content::BrowserThread;
+using testing::_;
+using testing::Return;
namespace {
@@ -25,6 +32,36 @@ const int kRouteId = 4;
const int kCallbackId = 5;
const char* kFakeExtensionId = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+class MockTokenService : public TokenService {
+ public:
+ MockTokenService() { }
+ virtual ~MockTokenService() { }
+
+ bool AreCredentialsValid() const OVERRIDE {
+ return true;
+ }
+
+ MOCK_CONST_METHOD1(HasTokenForService, bool(const char*));
+};
+
+class TestProfile : public TestingProfile {
+ public:
+ TestProfile() : TestingProfile() { }
+ virtual ~TestProfile() { }
+
+ virtual TokenService* GetTokenService() OVERRIDE {
+ return &token_service_;
+ }
+
+ void SetTokenServiceHasTokenResult(bool result) {
+ EXPECT_CALL(token_service_, HasTokenForService(_))
+ .WillRepeatedly(Return(result));
+ }
+
+ private:
+ MockTokenService token_service_;
+};
+
class TestDelegate : public AppNotifyChannelSetup::Delegate,
public base::SupportsWeakPtr<TestDelegate> {
public:
@@ -127,13 +164,13 @@ class AppNotifyChannelSetupTest : public testing::Test {
virtual AppNotifyChannelSetup* CreateInstance() {
GURL page_url("http://www.google.com");
return new AppNotifyChannelSetup(&profile_,
- kFakeExtensionId,
- "1234",
- page_url,
- kRouteId,
- kCallbackId,
- ui_.release(),
- delegate_.AsWeakPtr());
+ kFakeExtensionId,
+ "1234",
+ page_url,
+ kRouteId,
+ kCallbackId,
+ ui_.release(),
+ delegate_.AsWeakPtr());
}
virtual void SetupLogin(bool should_succeed) {
@@ -143,6 +180,16 @@ class AppNotifyChannelSetupTest : public testing::Test {
ui_->SetSyncSetupResult(false);
}
+ virtual void SetupFetchTokens(bool should_have_tokens, bool should_succeed) {
+ profile_.SetTokenServiceHasTokenResult(should_have_tokens);
+ if (!should_have_tokens) {
+ factory_.SetFakeResponse(
+ GaiaUrls::GetInstance()->issue_auth_token_url(),
+ "some_token",
+ should_succeed);
+ }
+ }
+
virtual void SetupRecordGrant(bool should_succeed) {
factory_.SetFakeResponse(
AppNotifyChannelSetup::GetOAuth2IssueTokenURL().spec(),
@@ -157,7 +204,6 @@ class AppNotifyChannelSetupTest : public testing::Test {
should_succeed);
}
-
virtual void RunServerTest(AppNotifyChannelSetup* setup,
const std::string& expected_code,
const std::string& expected_error) {
@@ -169,22 +215,39 @@ class AppNotifyChannelSetupTest : public testing::Test {
protected:
MessageLoop message_loop_;
content::TestBrowserThread ui_thread_;
- TestingProfile profile_;
+ TestProfile profile_;
TestDelegate delegate_;
scoped_ptr<TestUI> ui_;
FakeURLFetcherFactory factory_;
};
TEST_F(AppNotifyChannelSetupTest, LoginFailure) {
- // Set login to fail.
SetupLogin(false);
scoped_refptr<AppNotifyChannelSetup> setup = CreateInstance();
RunServerTest(setup, "", "canceled_by_user");
}
-TEST_F(AppNotifyChannelSetupTest, RecordGrantFailure) {
+TEST_F(AppNotifyChannelSetupTest, FetchTokensFailure) {
+ SetupLogin(true);
+ SetupFetchTokens(false, false);
+
+ scoped_refptr<AppNotifyChannelSetup> setup = CreateInstance();
+ RunServerTest(setup, "", "internal_error");
+}
+
+TEST_F(AppNotifyChannelSetupTest, TokensAvailableRecordGrantFailure) {
+ SetupLogin(true);
+ SetupFetchTokens(true, false);
+ SetupRecordGrant(false);
+
+ scoped_refptr<AppNotifyChannelSetup> setup = CreateInstance();
+ RunServerTest(setup, "", "internal_error");
+}
+
+TEST_F(AppNotifyChannelSetupTest, TokenFetchSuccessAndRecordGrantFailure) {
SetupLogin(true);
+ SetupFetchTokens(false , true);
SetupRecordGrant(false);
scoped_refptr<AppNotifyChannelSetup> setup = CreateInstance();
@@ -193,6 +256,7 @@ TEST_F(AppNotifyChannelSetupTest, RecordGrantFailure) {
TEST_F(AppNotifyChannelSetupTest, GetChannelIdFailure) {
SetupLogin(true);
+ SetupFetchTokens(true, false);
SetupRecordGrant(true);
SetupGetChannelId(false);
@@ -202,6 +266,7 @@ TEST_F(AppNotifyChannelSetupTest, GetChannelIdFailure) {
TEST_F(AppNotifyChannelSetupTest, ServerSuccess) {
SetupLogin(true);
+ SetupFetchTokens(true, false);
SetupRecordGrant(true);
SetupGetChannelId(true);