15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/run_loop.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/gcm_driver/fake_gcm_driver.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/gcm_driver/gcm_driver.h"
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/invalidation/gcm_invalidation_bridge.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/test/test_browser_thread_bundle.h"
140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "google_apis/gaia/fake_identity_provider.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h"
166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "net/base/ip_endpoint.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace invalidation {
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Implementation of GCMDriver::Register that always succeeds with the same
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// registrationId.
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class CustomFakeGCMDriver : public gcm::FakeGCMDriver {
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  CustomFakeGCMDriver() {}
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~CustomFakeGCMDriver() {}
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) protected:
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // FakeGCMDriver override:
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual void RegisterImpl(
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const std::string& app_id,
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      const std::vector<std::string>& sender_ids) OVERRIDE {
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::MessageLoop::current()->PostTask(
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        FROM_HERE,
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(&CustomFakeGCMDriver::RegisterFinished,
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   base::Unretained(this),
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   app_id,
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   std::string("registration.id"),
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   gcm::GCMClient::SUCCESS));
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CustomFakeGCMDriver);
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class GCMInvalidationBridgeTest : public ::testing::Test {
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected:
496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  GCMInvalidationBridgeTest()
506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      : connection_online_(false) {}
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~GCMInvalidationBridgeTest() {}
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestingProfile::Builder builder;
56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                              &BuildAutoIssuingFakeProfileOAuth2TokenService);
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    profile_ = builder.Build();
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FakeProfileOAuth2TokenService* token_service =
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        (FakeProfileOAuth2TokenService*)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    token_service->IssueRefreshTokenForUser("", "fake_refresh_token");
6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    gcm_driver_.reset(new CustomFakeGCMDriver());
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    identity_provider_.reset(new FakeIdentityProvider(token_service));
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bridge_.reset(new GCMInvalidationBridge(gcm_driver_.get(),
680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                            identity_provider_.get()));
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    delegate_ = bridge_->CreateDelegate();
716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    delegate_->Initialize(
726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        base::Bind(&GCMInvalidationBridgeTest::ConnectionStateChanged,
736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                   base::Unretained(this)));
746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    RunLoop();
756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  void RunLoop() {
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::RunLoop run_loop;
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    run_loop.RunUntilIdle();
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void RegisterFinished(const std::string& registration_id,
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        gcm::GCMClient::Result result) {
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    registration_id_ = registration_id;
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void RequestTokenFinished(const GoogleServiceAuthError& error,
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            const std::string& token) {
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    issued_tokens_.push_back(token);
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request_token_errors_.push_back(error);
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  void ConnectionStateChanged(bool online) {
956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    connection_online_ = online;
966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::TestBrowserThreadBundle thread_bundle_;
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<Profile> profile_;
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<gcm::GCMDriver> gcm_driver_;
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<FakeIdentityProvider> identity_provider_;
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<std::string> issued_tokens_;
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<GoogleServiceAuthError> request_token_errors_;
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string registration_id_;
1066d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  bool connection_online_;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<GCMInvalidationBridge> bridge_;
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<syncer::GCMNetworkChannelDelegate> delegate_;
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(GCMInvalidationBridgeTest, RequestToken) {
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Make sure that call to RequestToken reaches OAuth2TokenService and gets
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // back to callback.
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delegate_->RequestToken(
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&GCMInvalidationBridgeTest::RequestTokenFinished,
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Unretained(this)));
1186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  RunLoop();
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1U, issued_tokens_.size());
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_NE("", issued_tokens_[0]);
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), request_token_errors_[0]);
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(GCMInvalidationBridgeTest, RequestTokenTwoConcurrentRequests) {
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // First call should finish with REQUEST_CANCELLED error.
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delegate_->RequestToken(
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&GCMInvalidationBridgeTest::RequestTokenFinished,
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Unretained(this)));
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Second request should succeed.
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delegate_->RequestToken(
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&GCMInvalidationBridgeTest::RequestTokenFinished,
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Unretained(this)));
1336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  RunLoop();
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2U, issued_tokens_.size());
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ("", issued_tokens_[0]);
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(GoogleServiceAuthError::REQUEST_CANCELED,
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            request_token_errors_[0].state());
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_NE("", issued_tokens_[1]);
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), request_token_errors_[1]);
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(GCMInvalidationBridgeTest, Register) {
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(registration_id_.empty());
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  delegate_->Register(base::Bind(&GCMInvalidationBridgeTest::RegisterFinished,
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 base::Unretained(this)));
1496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  RunLoop();
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(registration_id_.empty());
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)TEST_F(GCMInvalidationBridgeTest, ConnectionState) {
1556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  EXPECT_FALSE(connection_online_);
1566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  bridge_->OnConnected(net::IPEndPoint());
1576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  RunLoop();
1586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  EXPECT_TRUE(connection_online_);
1596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  bridge_->OnDisconnected();
1606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  RunLoop();
1616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  EXPECT_FALSE(connection_online_);
1626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
1636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace invalidation
166