1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138 |
- // Copyright 2014 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 "components/gcm_driver/gcm_driver_desktop.h"
- #include <stdint.h>
- #include <memory>
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/files/scoped_temp_dir.h"
- #include "base/location.h"
- #include "base/run_loop.h"
- #include "base/strings/string_util.h"
- #include "base/task/current_thread.h"
- #include "base/test/task_environment.h"
- #include "base/test/test_simple_task_runner.h"
- #include "base/threading/thread.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "base/time/time.h"
- #include "components/gcm_driver/crypto/gcm_encryption_provider.h"
- #include "components/gcm_driver/fake_gcm_app_handler.h"
- #include "components/gcm_driver/fake_gcm_client.h"
- #include "components/gcm_driver/fake_gcm_client_factory.h"
- #include "components/gcm_driver/gcm_app_handler.h"
- #include "components/gcm_driver/gcm_client_factory.h"
- #include "components/gcm_driver/gcm_connection_observer.h"
- #include "components/prefs/pref_registry_simple.h"
- #include "components/prefs/testing_pref_service.h"
- #include "net/url_request/url_request_context_getter.h"
- #include "net/url_request/url_request_test_util.h"
- #include "services/network/public/cpp/shared_url_loader_factory.h"
- #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
- #include "services/network/test/test_network_connection_tracker.h"
- #include "services/network/test/test_url_loader_factory.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace gcm {
- namespace {
- const char kTestAppID1[] = "TestApp1";
- const char kTestAppID2[] = "TestApp2";
- const char kUserID1[] = "user1";
- const char kScope[] = "GCM";
- const char kInstanceID1[] = "IID1";
- const char kInstanceID2[] = "IID2";
- class FakeGCMConnectionObserver : public GCMConnectionObserver {
- public:
- FakeGCMConnectionObserver();
- ~FakeGCMConnectionObserver() override;
- // gcm::GCMConnectionObserver implementation:
- void OnConnected(const net::IPEndPoint& ip_endpoint) override;
- void OnDisconnected() override;
- bool connected() const { return connected_; }
- private:
- bool connected_;
- };
- FakeGCMConnectionObserver::FakeGCMConnectionObserver() : connected_(false) {
- }
- FakeGCMConnectionObserver::~FakeGCMConnectionObserver() {
- }
- void FakeGCMConnectionObserver::OnConnected(
- const net::IPEndPoint& ip_endpoint) {
- connected_ = true;
- }
- void FakeGCMConnectionObserver::OnDisconnected() {
- connected_ = false;
- }
- void PumpCurrentLoop() {
- base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
- }
- void PumpUILoop() {
- PumpCurrentLoop();
- }
- std::vector<std::string> ToSenderList(const std::string& sender_ids) {
- return base::SplitString(
- sender_ids, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- }
- } // namespace
- class GCMDriverTest : public testing::Test {
- public:
- enum WaitToFinish {
- DO_NOT_WAIT,
- WAIT
- };
- GCMDriverTest();
- GCMDriverTest(const GCMDriverTest&) = delete;
- GCMDriverTest& operator=(const GCMDriverTest&) = delete;
- ~GCMDriverTest() override;
- // testing::Test:
- void SetUp() override;
- void TearDown() override;
- GCMDriverDesktop* driver() { return driver_.get(); }
- FakeGCMAppHandler* gcm_app_handler() { return gcm_app_handler_.get(); }
- FakeGCMConnectionObserver* gcm_connection_observer() {
- return gcm_connection_observer_.get();
- }
- const std::string& registration_id() const { return registration_id_; }
- GCMClient::Result registration_result() const { return registration_result_; }
- const std::string& send_message_id() const { return send_message_id_; }
- GCMClient::Result send_result() const { return send_result_; }
- GCMClient::Result unregistration_result() const {
- return unregistration_result_;
- }
- const std::string& p256dh() const { return p256dh_; }
- const std::string& auth_secret() const { return auth_secret_; }
- void PumpIOLoop();
- void ClearResults();
- bool HasAppHandlers() const;
- FakeGCMClient* GetGCMClient();
- void CreateDriver();
- void ShutdownDriver();
- void AddAppHandlers();
- void RemoveAppHandlers();
- void Register(const std::string& app_id,
- const std::vector<std::string>& sender_ids,
- WaitToFinish wait_to_finish);
- void Send(const std::string& app_id,
- const std::string& receiver_id,
- const OutgoingMessage& message,
- WaitToFinish wait_to_finish);
- void GetEncryptionInfo(const std::string& app_id,
- WaitToFinish wait_to_finish);
- void Unregister(const std::string& app_id, WaitToFinish wait_to_finish);
- void WaitForAsyncOperation();
- void RegisterCompleted(const std::string& registration_id,
- GCMClient::Result result);
- void SendCompleted(const std::string& message_id, GCMClient::Result result);
- void GetEncryptionInfoCompleted(std::string p256dh, std::string auth_secret);
- void UnregisterCompleted(GCMClient::Result result);
- void AsyncOperationCompleted() {
- if (async_operation_completed_callback_)
- std::move(async_operation_completed_callback_).Run();
- }
- void set_async_operation_completed_callback(base::OnceClosure callback) {
- async_operation_completed_callback_ = std::move(callback);
- }
- private:
- base::ScopedTempDir temp_dir_;
- TestingPrefServiceSimple prefs_;
- base::test::SingleThreadTaskEnvironment task_environment_{
- base::test::SingleThreadTaskEnvironment::MainThreadType::UI};
- base::Thread io_thread_;
- network::TestURLLoaderFactory test_url_loader_factory_;
- std::unique_ptr<GCMDriverDesktop> driver_;
- std::unique_ptr<FakeGCMAppHandler> gcm_app_handler_;
- std::unique_ptr<FakeGCMConnectionObserver> gcm_connection_observer_;
- base::OnceClosure async_operation_completed_callback_;
- std::string registration_id_;
- GCMClient::Result registration_result_;
- std::string send_message_id_;
- GCMClient::Result send_result_;
- GCMClient::Result unregistration_result_;
- std::string p256dh_;
- std::string auth_secret_;
- };
- GCMDriverTest::GCMDriverTest()
- : io_thread_("IOThread"),
- registration_result_(GCMClient::UNKNOWN_ERROR),
- send_result_(GCMClient::UNKNOWN_ERROR),
- unregistration_result_(GCMClient::UNKNOWN_ERROR) {}
- GCMDriverTest::~GCMDriverTest() {
- }
- void GCMDriverTest::SetUp() {
- io_thread_.Start();
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- }
- void GCMDriverTest::TearDown() {
- if (!driver_)
- return;
- ShutdownDriver();
- driver_.reset();
- PumpIOLoop();
- io_thread_.Stop();
- task_environment_.RunUntilIdle();
- ASSERT_TRUE(temp_dir_.Delete());
- }
- void GCMDriverTest::PumpIOLoop() {
- base::RunLoop run_loop;
- io_thread_.task_runner()->PostTaskAndReply(
- FROM_HERE, base::BindOnce(&PumpCurrentLoop), run_loop.QuitClosure());
- run_loop.Run();
- }
- void GCMDriverTest::ClearResults() {
- registration_id_.clear();
- registration_result_ = GCMClient::UNKNOWN_ERROR;
- send_message_id_.clear();
- send_result_ = GCMClient::UNKNOWN_ERROR;
- unregistration_result_ = GCMClient::UNKNOWN_ERROR;
- }
- bool GCMDriverTest::HasAppHandlers() const {
- return !driver_->app_handlers().empty();
- }
- FakeGCMClient* GCMDriverTest::GetGCMClient() {
- return static_cast<FakeGCMClient*>(driver_->GetGCMClientForTesting());
- }
- void GCMDriverTest::CreateDriver() {
- GCMClient::ChromeBuildInfo chrome_build_info;
- chrome_build_info.product_category_for_subtypes = "com.chrome.macosx";
- driver_ = std::make_unique<GCMDriverDesktop>(
- std::unique_ptr<GCMClientFactory>(new FakeGCMClientFactory(
- base::ThreadTaskRunnerHandle::Get(), io_thread_.task_runner())),
- chrome_build_info, &prefs_, temp_dir_.GetPath(),
- /*remove_account_mappings_with_email_key=*/true, base::DoNothing(),
- base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
- &test_url_loader_factory_),
- network::TestNetworkConnectionTracker::GetInstance(),
- base::ThreadTaskRunnerHandle::Get(), io_thread_.task_runner(),
- task_environment_.GetMainThreadTaskRunner());
- gcm_app_handler_ = std::make_unique<FakeGCMAppHandler>();
- gcm_connection_observer_ = std::make_unique<FakeGCMConnectionObserver>();
- driver_->AddConnectionObserver(gcm_connection_observer_.get());
- }
- void GCMDriverTest::ShutdownDriver() {
- if (gcm_connection_observer())
- driver()->RemoveConnectionObserver(gcm_connection_observer());
- driver()->Shutdown();
- }
- void GCMDriverTest::AddAppHandlers() {
- driver_->AddAppHandler(kTestAppID1, gcm_app_handler_.get());
- driver_->AddAppHandler(kTestAppID2, gcm_app_handler_.get());
- }
- void GCMDriverTest::RemoveAppHandlers() {
- driver_->RemoveAppHandler(kTestAppID1);
- driver_->RemoveAppHandler(kTestAppID2);
- }
- void GCMDriverTest::Register(const std::string& app_id,
- const std::vector<std::string>& sender_ids,
- WaitToFinish wait_to_finish) {
- base::RunLoop run_loop;
- async_operation_completed_callback_ = run_loop.QuitClosure();
- driver_->Register(app_id, sender_ids,
- base::BindOnce(&GCMDriverTest::RegisterCompleted,
- base::Unretained(this)));
- if (wait_to_finish == WAIT)
- run_loop.Run();
- }
- void GCMDriverTest::Send(const std::string& app_id,
- const std::string& receiver_id,
- const OutgoingMessage& message,
- WaitToFinish wait_to_finish) {
- base::RunLoop run_loop;
- async_operation_completed_callback_ = run_loop.QuitClosure();
- driver_->Send(
- app_id, receiver_id, message,
- base::BindOnce(&GCMDriverTest::SendCompleted, base::Unretained(this)));
- if (wait_to_finish == WAIT)
- run_loop.Run();
- }
- void GCMDriverTest::GetEncryptionInfo(const std::string& app_id,
- WaitToFinish wait_to_finish) {
- base::RunLoop run_loop;
- async_operation_completed_callback_ = run_loop.QuitClosure();
- driver_->GetEncryptionInfo(
- app_id, base::BindOnce(&GCMDriverTest::GetEncryptionInfoCompleted,
- base::Unretained(this)));
- if (wait_to_finish == WAIT)
- run_loop.Run();
- }
- void GCMDriverTest::Unregister(const std::string& app_id,
- WaitToFinish wait_to_finish) {
- base::RunLoop run_loop;
- async_operation_completed_callback_ = run_loop.QuitClosure();
- driver_->Unregister(app_id,
- base::BindOnce(&GCMDriverTest::UnregisterCompleted,
- base::Unretained(this)));
- if (wait_to_finish == WAIT)
- run_loop.Run();
- }
- void GCMDriverTest::WaitForAsyncOperation() {
- base::RunLoop run_loop;
- async_operation_completed_callback_ = run_loop.QuitClosure();
- run_loop.Run();
- }
- void GCMDriverTest::RegisterCompleted(const std::string& registration_id,
- GCMClient::Result result) {
- registration_id_ = registration_id;
- registration_result_ = result;
- AsyncOperationCompleted();
- }
- void GCMDriverTest::SendCompleted(const std::string& message_id,
- GCMClient::Result result) {
- send_message_id_ = message_id;
- send_result_ = result;
- AsyncOperationCompleted();
- }
- void GCMDriverTest::GetEncryptionInfoCompleted(std::string p256dh,
- std::string auth_secret) {
- p256dh_ = std::move(p256dh);
- auth_secret_ = std::move(auth_secret);
- AsyncOperationCompleted();
- }
- void GCMDriverTest::UnregisterCompleted(GCMClient::Result result) {
- unregistration_result_ = result;
- AsyncOperationCompleted();
- }
- TEST_F(GCMDriverTest, Create) {
- // Create GCMDriver first. By default GCM is set to delay start.
- CreateDriver();
- EXPECT_FALSE(driver()->IsStarted());
- // Adding an app handler will not start GCM.
- AddAppHandlers();
- PumpIOLoop();
- PumpUILoop();
- EXPECT_FALSE(driver()->IsStarted());
- EXPECT_FALSE(driver()->IsConnected());
- EXPECT_FALSE(gcm_connection_observer()->connected());
- // The GCM registration will kick off the GCM.
- Register(kTestAppID1, ToSenderList("sender"), GCMDriverTest::WAIT);
- EXPECT_TRUE(driver()->IsStarted());
- EXPECT_TRUE(driver()->IsConnected());
- EXPECT_TRUE(gcm_connection_observer()->connected());
- }
- TEST_F(GCMDriverTest, Shutdown) {
- CreateDriver();
- EXPECT_FALSE(HasAppHandlers());
- AddAppHandlers();
- EXPECT_TRUE(HasAppHandlers());
- ShutdownDriver();
- EXPECT_FALSE(HasAppHandlers());
- EXPECT_FALSE(driver()->IsConnected());
- EXPECT_FALSE(gcm_connection_observer()->connected());
- }
- TEST_F(GCMDriverTest, StartOrStopGCMOnDemand) {
- CreateDriver();
- PumpIOLoop();
- PumpUILoop();
- EXPECT_FALSE(driver()->IsStarted());
- // Adding an app handler will not start GCM.
- driver()->AddAppHandler(kTestAppID1, gcm_app_handler());
- PumpIOLoop();
- PumpUILoop();
- EXPECT_FALSE(driver()->IsStarted());
- // The GCM registration will kick off the GCM.
- Register(kTestAppID1, ToSenderList("sender"), GCMDriverTest::WAIT);
- EXPECT_TRUE(driver()->IsStarted());
- // Add another app handler.
- driver()->AddAppHandler(kTestAppID2, gcm_app_handler());
- PumpIOLoop();
- PumpUILoop();
- EXPECT_TRUE(driver()->IsStarted());
- // GCMClient remains active after one app handler is gone.
- driver()->RemoveAppHandler(kTestAppID1);
- PumpIOLoop();
- PumpUILoop();
- EXPECT_TRUE(driver()->IsStarted());
- // GCMClient should be stopped after the last app handler is gone.
- driver()->RemoveAppHandler(kTestAppID2);
- PumpIOLoop();
- PumpUILoop();
- EXPECT_FALSE(driver()->IsStarted());
- // GCMClient is restarted after an app handler has been added.
- driver()->AddAppHandler(kTestAppID2, gcm_app_handler());
- PumpIOLoop();
- PumpUILoop();
- EXPECT_TRUE(driver()->IsStarted());
- }
- TEST_F(GCMDriverTest, RegisterFailed) {
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1");
- CreateDriver();
- // Registration fails when the no app handler is added.
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- EXPECT_TRUE(registration_id().empty());
- EXPECT_EQ(GCMClient::UNKNOWN_ERROR, registration_result());
- }
- TEST_F(GCMDriverTest, UnregisterFailed) {
- CreateDriver();
- // Unregistration fails when the no app handler is added.
- Unregister(kTestAppID1, GCMDriverTest::WAIT);
- EXPECT_EQ(GCMClient::UNKNOWN_ERROR, unregistration_result());
- }
- TEST_F(GCMDriverTest, SendFailed) {
- OutgoingMessage message;
- message.id = "1";
- message.data["key1"] = "value1";
- CreateDriver();
- // Sending fails when the no app handler is added.
- Send(kTestAppID1, kUserID1, message, GCMDriverTest::WAIT);
- EXPECT_TRUE(send_message_id().empty());
- EXPECT_EQ(GCMClient::UNKNOWN_ERROR, send_result());
- }
- TEST_F(GCMDriverTest, DISABLED_GCMClientNotReadyBeforeRegistration) {
- CreateDriver();
- PumpIOLoop();
- PumpUILoop();
- // Make GCMClient not ready until PerformDelayedStart is called.
- GetGCMClient()->set_start_mode_overridding(
- FakeGCMClient::FORCE_TO_ALWAYS_DELAY_START_GCM);
- AddAppHandlers();
- // The registration is on hold until GCMClient is ready.
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1");
- Register(kTestAppID1,
- sender_ids,
- GCMDriverTest::DO_NOT_WAIT);
- PumpIOLoop();
- PumpUILoop();
- EXPECT_TRUE(registration_id().empty());
- EXPECT_EQ(GCMClient::UNKNOWN_ERROR, registration_result());
- // Register operation will be invoked after GCMClient becomes ready.
- GetGCMClient()->PerformDelayedStart();
- WaitForAsyncOperation();
- EXPECT_FALSE(registration_id().empty());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- }
- TEST_F(GCMDriverTest, GCMClientNotReadyBeforeSending) {
- CreateDriver();
- PumpIOLoop();
- PumpUILoop();
- // Make GCMClient not ready until PerformDelayedStart is called.
- GetGCMClient()->set_start_mode_overridding(
- FakeGCMClient::FORCE_TO_ALWAYS_DELAY_START_GCM);
- AddAppHandlers();
- // The sending is on hold until GCMClient is ready.
- OutgoingMessage message;
- message.id = "1";
- message.data["key1"] = "value1";
- message.data["key2"] = "value2";
- Send(kTestAppID1, kUserID1, message, GCMDriverTest::DO_NOT_WAIT);
- PumpIOLoop();
- PumpUILoop();
- EXPECT_TRUE(send_message_id().empty());
- EXPECT_EQ(GCMClient::UNKNOWN_ERROR, send_result());
- // Send operation will be invoked after GCMClient becomes ready.
- GetGCMClient()->PerformDelayedStart();
- WaitForAsyncOperation();
- EXPECT_EQ(message.id, send_message_id());
- EXPECT_EQ(GCMClient::SUCCESS, send_result());
- }
- // Tests a single instance of GCMDriver.
- class GCMDriverFunctionalTest : public GCMDriverTest {
- public:
- GCMDriverFunctionalTest();
- GCMDriverFunctionalTest(const GCMDriverFunctionalTest&) = delete;
- GCMDriverFunctionalTest& operator=(const GCMDriverFunctionalTest&) = delete;
- ~GCMDriverFunctionalTest() override;
- // GCMDriverTest:
- void SetUp() override;
- };
- GCMDriverFunctionalTest::GCMDriverFunctionalTest() {
- }
- GCMDriverFunctionalTest::~GCMDriverFunctionalTest() {
- }
- void GCMDriverFunctionalTest::SetUp() {
- GCMDriverTest::SetUp();
- CreateDriver();
- AddAppHandlers();
- PumpIOLoop();
- PumpUILoop();
- }
- TEST_F(GCMDriverFunctionalTest, DISABLED_Register) {
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1");
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- const std::string expected_registration_id =
- FakeGCMClient::GenerateGCMRegistrationID(sender_ids);
- EXPECT_EQ(expected_registration_id, registration_id());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- }
- // This test is flaky, see https://crbug.com/1010462
- TEST_F(GCMDriverFunctionalTest, DISABLED_RegisterError) {
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1@error");
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- EXPECT_TRUE(registration_id().empty());
- EXPECT_NE(GCMClient::SUCCESS, registration_result());
- }
- // This test is flaky, see https://crbug.com/1010462
- TEST_F(GCMDriverFunctionalTest, DISABLED_RegisterAgainWithSameSenderIDs) {
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1");
- sender_ids.push_back("sender2");
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- const std::string expected_registration_id =
- FakeGCMClient::GenerateGCMRegistrationID(sender_ids);
- EXPECT_EQ(expected_registration_id, registration_id());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- // Clears the results the would be set by the Register callback in preparation
- // to call register 2nd time.
- ClearResults();
- // Calling register 2nd time with the same set of sender IDs but different
- // ordering will get back the same registration ID.
- std::vector<std::string> another_sender_ids;
- another_sender_ids.push_back("sender2");
- another_sender_ids.push_back("sender1");
- Register(kTestAppID1, another_sender_ids, GCMDriverTest::WAIT);
- EXPECT_EQ(expected_registration_id, registration_id());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- }
- // This test is flaky, see https://crbug.com/1010462
- TEST_F(GCMDriverFunctionalTest, DISABLED_RegisterAgainWithDifferentSenderIDs) {
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1");
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- const std::string expected_registration_id =
- FakeGCMClient::GenerateGCMRegistrationID(sender_ids);
- EXPECT_EQ(expected_registration_id, registration_id());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- // Make sender IDs different.
- sender_ids.push_back("sender2");
- const std::string expected_registration_id2 =
- FakeGCMClient::GenerateGCMRegistrationID(sender_ids);
- // Calling register 2nd time with the different sender IDs will get back a new
- // registration ID.
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- EXPECT_EQ(expected_registration_id2, registration_id());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- }
- TEST_F(GCMDriverFunctionalTest, UnregisterExplicitly) {
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1");
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- EXPECT_FALSE(registration_id().empty());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- Unregister(kTestAppID1, GCMDriverTest::WAIT);
- EXPECT_EQ(GCMClient::SUCCESS, unregistration_result());
- }
- // TODO(crbug.com/1009185): Test is failing on ASan build.
- #if defined(ADDRESS_SANITIZER)
- TEST_F(GCMDriverFunctionalTest, DISABLED_UnregisterRemovesEncryptionInfo) {
- #else
- TEST_F(GCMDriverFunctionalTest, UnregisterRemovesEncryptionInfo) {
- #endif
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1");
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- EXPECT_FALSE(registration_id().empty());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- GetEncryptionInfo(kTestAppID1, GCMDriverTest::WAIT);
- EXPECT_FALSE(p256dh().empty());
- EXPECT_FALSE(auth_secret().empty());
- const std::string app_p256dh = p256dh();
- const std::string app_auth_secret = auth_secret();
- GetEncryptionInfo(kTestAppID1, GCMDriverTest::WAIT);
- EXPECT_EQ(app_p256dh, p256dh());
- EXPECT_EQ(app_auth_secret, auth_secret());
- Unregister(kTestAppID1, GCMDriverTest::WAIT);
- EXPECT_EQ(GCMClient::SUCCESS, unregistration_result());
- GetEncryptionInfo(kTestAppID1, GCMDriverTest::WAIT);
- // The GCMKeyStore eagerly creates new keying material for registrations that
- // don't have any associated with them, so the most appropriate check to do is
- // to verify that the returned material is different from before.
- EXPECT_NE(app_p256dh, p256dh());
- EXPECT_NE(app_auth_secret, auth_secret());
- }
- TEST_F(GCMDriverFunctionalTest, DISABLED_UnregisterWhenAsyncOperationPending) {
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1");
- // First start registration without waiting for it to complete.
- Register(kTestAppID1, sender_ids, GCMDriverTest::DO_NOT_WAIT);
- // Test that unregistration fails with async operation pending when there is a
- // registration already in progress.
- Unregister(kTestAppID1, GCMDriverTest::WAIT);
- EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
- unregistration_result());
- // Complete the unregistration.
- WaitForAsyncOperation();
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- // Start unregistration without waiting for it to complete. This time no async
- // operation is pending.
- Unregister(kTestAppID1, GCMDriverTest::DO_NOT_WAIT);
- // Test that unregistration fails with async operation pending when there is
- // an unregistration already in progress.
- Unregister(kTestAppID1, GCMDriverTest::WAIT);
- EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
- unregistration_result());
- ClearResults();
- // Complete unregistration.
- WaitForAsyncOperation();
- EXPECT_EQ(GCMClient::SUCCESS, unregistration_result());
- }
- TEST_F(GCMDriverFunctionalTest, RegisterWhenAsyncOperationPending) {
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1");
- // First start registration without waiting for it to complete.
- Register(kTestAppID1, sender_ids, GCMDriverTest::DO_NOT_WAIT);
- // Test that registration fails with async operation pending when there is a
- // registration already in progress.
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- EXPECT_EQ(GCMClient::ASYNC_OPERATION_PENDING,
- registration_result());
- ClearResults();
- // Complete the registration.
- WaitForAsyncOperation();
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- }
- // This test is flaky, see https://crbug.com/1010462
- TEST_F(GCMDriverFunctionalTest, DISABLED_RegisterAfterUnfinishedUnregister) {
- // Register and wait for it to complete.
- std::vector<std::string> sender_ids;
- sender_ids.push_back("sender1");
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- EXPECT_EQ(FakeGCMClient::GenerateGCMRegistrationID(sender_ids),
- registration_id());
- // Clears the results the would be set by the Register callback in preparation
- // to call register 2nd time.
- ClearResults();
- // Start unregistration without waiting for it to complete.
- Unregister(kTestAppID1, GCMDriverTest::DO_NOT_WAIT);
- // Register immediately after unregistration is not completed.
- sender_ids.push_back("sender2");
- Register(kTestAppID1, sender_ids, GCMDriverTest::WAIT);
- // We need one more waiting since the waiting in Register is indeed for
- // uncompleted Unregister.
- WaitForAsyncOperation();
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- EXPECT_EQ(FakeGCMClient::GenerateGCMRegistrationID(sender_ids),
- registration_id());
- }
- TEST_F(GCMDriverFunctionalTest, Send) {
- OutgoingMessage message;
- message.id = "1@ack";
- message.data["key1"] = "value1";
- message.data["key2"] = "value2";
- Send(kTestAppID1, kUserID1, message, GCMDriverTest::WAIT);
- EXPECT_EQ(message.id, send_message_id());
- EXPECT_EQ(GCMClient::SUCCESS, send_result());
- gcm_app_handler()->WaitForNotification();
- EXPECT_EQ(message.id, gcm_app_handler()->acked_message_id());
- EXPECT_EQ(kTestAppID1, gcm_app_handler()->app_id());
- }
- TEST_F(GCMDriverFunctionalTest, SendError) {
- OutgoingMessage message;
- // Embedding error in id will tell the mock to simulate the send error.
- message.id = "1@error";
- message.data["key1"] = "value1";
- message.data["key2"] = "value2";
- Send(kTestAppID1, kUserID1, message, GCMDriverTest::WAIT);
- EXPECT_EQ(message.id, send_message_id());
- EXPECT_EQ(GCMClient::SUCCESS, send_result());
- // Wait for the send error.
- gcm_app_handler()->WaitForNotification();
- EXPECT_EQ(FakeGCMAppHandler::SEND_ERROR_EVENT,
- gcm_app_handler()->received_event());
- EXPECT_EQ(kTestAppID1, gcm_app_handler()->app_id());
- EXPECT_EQ(message.id,
- gcm_app_handler()->send_error_details().message_id);
- EXPECT_NE(GCMClient::SUCCESS,
- gcm_app_handler()->send_error_details().result);
- EXPECT_EQ(message.data,
- gcm_app_handler()->send_error_details().additional_data);
- }
- // This test is flaky, see https://crbug.com/1010462
- TEST_F(GCMDriverFunctionalTest, DISABLED_MessageReceived) {
- // GCM registration has to be performed otherwise GCM will not be started.
- Register(kTestAppID1, ToSenderList("sender"), GCMDriverTest::WAIT);
- IncomingMessage message;
- message.data["key1"] = "value1";
- message.data["key2"] = "value2";
- message.sender_id = "sender";
- GetGCMClient()->ReceiveMessage(kTestAppID1, message);
- gcm_app_handler()->WaitForNotification();
- EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
- gcm_app_handler()->received_event());
- EXPECT_EQ(kTestAppID1, gcm_app_handler()->app_id());
- EXPECT_EQ(message.data, gcm_app_handler()->message().data);
- EXPECT_TRUE(gcm_app_handler()->message().collapse_key.empty());
- EXPECT_EQ(message.sender_id, gcm_app_handler()->message().sender_id);
- }
- // This test is flaky, see https://crbug.com/1010462
- TEST_F(GCMDriverFunctionalTest, DISABLED_MessageWithCollapseKeyReceived) {
- // GCM registration has to be performed otherwise GCM will not be started.
- Register(kTestAppID1, ToSenderList("sender"), GCMDriverTest::WAIT);
- IncomingMessage message;
- message.data["key1"] = "value1";
- message.collapse_key = "collapse_key_value";
- message.sender_id = "sender";
- GetGCMClient()->ReceiveMessage(kTestAppID1, message);
- gcm_app_handler()->WaitForNotification();
- EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
- gcm_app_handler()->received_event());
- EXPECT_EQ(kTestAppID1, gcm_app_handler()->app_id());
- EXPECT_EQ(message.data, gcm_app_handler()->message().data);
- EXPECT_EQ(message.collapse_key,
- gcm_app_handler()->message().collapse_key);
- }
- TEST_F(GCMDriverFunctionalTest, EncryptedMessageReceivedError) {
- // GCM registration has to be performed otherwise GCM will not be started.
- Register(kTestAppID1, ToSenderList("sender"), GCMDriverTest::WAIT);
- IncomingMessage message;
- // All required information to trigger the encryption path, but with an
- // invalid Crypto-Key header value to trigger an error.
- message.data["encryption"] = "salt=ysyxqlYTgE0WvcZrmHbUbg";
- message.data["crypto-key"] = "hey=thereisnopublickey";
- message.sender_id = "sender";
- message.raw_data = "foobar";
- GetGCMClient()->SetRecording(true);
- GetGCMClient()->ReceiveMessage(kTestAppID1, message);
- PumpIOLoop();
- PumpUILoop();
- PumpIOLoop();
- EXPECT_EQ(FakeGCMAppHandler::DECRYPTION_FAILED_EVENT,
- gcm_app_handler()->received_event());
- GCMClient::GCMStatistics statistics = GetGCMClient()->GetStatistics();
- EXPECT_TRUE(statistics.is_recording);
- EXPECT_EQ(
- 1u, statistics.recorded_activities.decryption_failure_activities.size());
- }
- TEST_F(GCMDriverFunctionalTest, MessagesDeleted) {
- // GCM registration has to be performed otherwise GCM will not be started.
- Register(kTestAppID1, ToSenderList("sender"), GCMDriverTest::WAIT);
- GetGCMClient()->DeleteMessages(kTestAppID1);
- gcm_app_handler()->WaitForNotification();
- EXPECT_EQ(FakeGCMAppHandler::MESSAGES_DELETED_EVENT,
- gcm_app_handler()->received_event());
- EXPECT_EQ(kTestAppID1, gcm_app_handler()->app_id());
- }
- TEST_F(GCMDriverFunctionalTest, LastTokenFetchTime) {
- // GCM registration has to be performed otherwise GCM will not be started.
- Register(kTestAppID1, ToSenderList("sender"), GCMDriverTest::WAIT);
- EXPECT_EQ(base::Time(), driver()->GetLastTokenFetchTime());
- base::Time fetch_time = base::Time::Now();
- driver()->SetLastTokenFetchTime(fetch_time);
- EXPECT_EQ(fetch_time, driver()->GetLastTokenFetchTime());
- }
- class GCMDriverInstanceIDTest : public GCMDriverTest {
- public:
- GCMDriverInstanceIDTest();
- GCMDriverInstanceIDTest(const GCMDriverInstanceIDTest&) = delete;
- GCMDriverInstanceIDTest& operator=(const GCMDriverInstanceIDTest&) = delete;
- ~GCMDriverInstanceIDTest() override;
- void GetReady();
- void GetInstanceID(const std::string& app_id, WaitToFinish wait_to_finish);
- void GetInstanceIDDataCompleted(const std::string& instance_id,
- const std::string& extra_data);
- void GetToken(const std::string& app_id,
- const std::string& authorized_entity,
- const std::string& scope,
- WaitToFinish wait_to_finish);
- void DeleteToken(const std::string& app_id,
- const std::string& authorized_entity,
- const std::string& scope,
- WaitToFinish wait_to_finish);
- void AddInstanceIDData(const std::string& app_id,
- const std::string& instance_id,
- const std::string& extra_data);
- void RemoveInstanceIDData(const std::string& app_id);
- std::string instance_id() const { return instance_id_; }
- std::string extra_data() const { return extra_data_; }
- int instance_id_resolved_counter() const {
- return instance_id_resolved_counter_;
- }
- private:
- std::string instance_id_;
- std::string extra_data_;
- int instance_id_resolved_counter_ = 0;
- };
- GCMDriverInstanceIDTest::GCMDriverInstanceIDTest() {
- }
- GCMDriverInstanceIDTest::~GCMDriverInstanceIDTest() {
- }
- void GCMDriverInstanceIDTest::GetReady() {
- CreateDriver();
- AddAppHandlers();
- PumpIOLoop();
- PumpUILoop();
- }
- void GCMDriverInstanceIDTest::GetInstanceID(const std::string& app_id,
- WaitToFinish wait_to_finish) {
- base::RunLoop run_loop;
- set_async_operation_completed_callback(run_loop.QuitClosure());
- driver()->GetInstanceIDHandlerInternal()->GetInstanceIDData(
- app_id,
- base::BindOnce(&GCMDriverInstanceIDTest::GetInstanceIDDataCompleted,
- base::Unretained(this)));
- if (wait_to_finish == WAIT)
- run_loop.Run();
- }
- void GCMDriverInstanceIDTest::GetInstanceIDDataCompleted(
- const std::string& instance_id, const std::string& extra_data) {
- instance_id_ = instance_id;
- extra_data_ = extra_data;
- instance_id_resolved_counter_++;
- AsyncOperationCompleted();
- }
- void GCMDriverInstanceIDTest::GetToken(const std::string& app_id,
- const std::string& authorized_entity,
- const std::string& scope,
- WaitToFinish wait_to_finish) {
- base::RunLoop run_loop;
- set_async_operation_completed_callback(run_loop.QuitClosure());
- driver()->GetInstanceIDHandlerInternal()->GetToken(
- app_id, authorized_entity, scope, /*time_to_live=*/base::TimeDelta(),
- base::BindOnce(&GCMDriverTest::RegisterCompleted,
- base::Unretained(this)));
- if (wait_to_finish == WAIT)
- run_loop.Run();
- }
- void GCMDriverInstanceIDTest::DeleteToken(const std::string& app_id,
- const std::string& authorized_entity,
- const std::string& scope,
- WaitToFinish wait_to_finish) {
- base::RunLoop run_loop;
- set_async_operation_completed_callback(run_loop.QuitClosure());
- driver()->GetInstanceIDHandlerInternal()->DeleteToken(
- app_id, authorized_entity, scope,
- base::BindOnce(&GCMDriverTest::UnregisterCompleted,
- base::Unretained(this)));
- if (wait_to_finish == WAIT)
- run_loop.Run();
- }
- void GCMDriverInstanceIDTest::AddInstanceIDData(const std::string& app_id,
- const std::string& instance_id,
- const std::string& extra_data) {
- driver()->GetInstanceIDHandlerInternal()->AddInstanceIDData(
- app_id, instance_id, extra_data);
- }
- void GCMDriverInstanceIDTest::RemoveInstanceIDData(const std::string& app_id) {
- driver()->GetInstanceIDHandlerInternal()->RemoveInstanceIDData(app_id);
- }
- TEST_F(GCMDriverInstanceIDTest, InstanceIDData) {
- GetReady();
- AddInstanceIDData(kTestAppID1, kInstanceID1, "Foo");
- GetInstanceID(kTestAppID1, GCMDriverTest::WAIT);
- EXPECT_EQ(kInstanceID1, instance_id());
- EXPECT_EQ("Foo", extra_data());
- EXPECT_EQ(1, instance_id_resolved_counter());
- RemoveInstanceIDData(kTestAppID1);
- GetInstanceID(kTestAppID1, GCMDriverTest::WAIT);
- EXPECT_TRUE(instance_id().empty());
- EXPECT_TRUE(extra_data().empty());
- EXPECT_EQ(2, instance_id_resolved_counter());
- AddInstanceIDData(kTestAppID1, kInstanceID1, "Bar");
- GetInstanceID(kTestAppID1, GCMDriverTest::DO_NOT_WAIT);
- GetInstanceID(kTestAppID1, GCMDriverTest::DO_NOT_WAIT);
- WaitForAsyncOperation();
- WaitForAsyncOperation();
- EXPECT_EQ(kInstanceID1, instance_id());
- EXPECT_EQ("Bar", extra_data());
- EXPECT_EQ(4, instance_id_resolved_counter());
- }
- // This test is flaky, see https://crbug.com/1010462
- TEST_F(GCMDriverInstanceIDTest,
- DISABLED_GCMClientNotReadyBeforeInstanceIDData) {
- CreateDriver();
- PumpIOLoop();
- PumpUILoop();
- // Make GCMClient not ready until PerformDelayedStart is called.
- GetGCMClient()->set_start_mode_overridding(
- FakeGCMClient::FORCE_TO_ALWAYS_DELAY_START_GCM);
- AddAppHandlers();
- // All operations are on hold until GCMClient is ready.
- AddInstanceIDData(kTestAppID1, kInstanceID1, "Foo");
- AddInstanceIDData(kTestAppID2, kInstanceID2, "Bar");
- RemoveInstanceIDData(kTestAppID1);
- GetInstanceID(kTestAppID2, GCMDriverTest::DO_NOT_WAIT);
- PumpIOLoop();
- PumpUILoop();
- EXPECT_TRUE(instance_id().empty());
- EXPECT_TRUE(extra_data().empty());
- // All operations will be performed after GCMClient becomes ready.
- GetGCMClient()->PerformDelayedStart();
- WaitForAsyncOperation();
- EXPECT_EQ(kInstanceID2, instance_id());
- EXPECT_EQ("Bar", extra_data());
- }
- TEST_F(GCMDriverInstanceIDTest, DISABLED_GetToken) {
- GetReady();
- const std::string expected_token =
- FakeGCMClient::GenerateInstanceIDToken(kUserID1, kScope);
- GetToken(kTestAppID1, kUserID1, kScope, GCMDriverTest::WAIT);
- EXPECT_EQ(expected_token, registration_id());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- }
- TEST_F(GCMDriverInstanceIDTest, GetTokenError) {
- GetReady();
- std::string error_entity = "sender@error";
- GetToken(kTestAppID1, error_entity, kScope, GCMDriverTest::WAIT);
- EXPECT_TRUE(registration_id().empty());
- EXPECT_NE(GCMClient::SUCCESS, registration_result());
- }
- TEST_F(GCMDriverInstanceIDTest, GCMClientNotReadyBeforeGetToken) {
- CreateDriver();
- PumpIOLoop();
- PumpUILoop();
- // Make GCMClient not ready until PerformDelayedStart is called.
- GetGCMClient()->set_start_mode_overridding(
- FakeGCMClient::FORCE_TO_ALWAYS_DELAY_START_GCM);
- AddAppHandlers();
- // GetToken operation is on hold until GCMClient is ready.
- GetToken(kTestAppID1, kUserID1, kScope, GCMDriverTest::DO_NOT_WAIT);
- PumpIOLoop();
- PumpUILoop();
- EXPECT_TRUE(registration_id().empty());
- EXPECT_EQ(GCMClient::UNKNOWN_ERROR, registration_result());
- // GetToken operation will be invoked after GCMClient becomes ready.
- GetGCMClient()->PerformDelayedStart();
- WaitForAsyncOperation();
- EXPECT_FALSE(registration_id().empty());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- }
- TEST_F(GCMDriverInstanceIDTest, DeleteToken) {
- GetReady();
- const std::string expected_token =
- FakeGCMClient::GenerateInstanceIDToken(kUserID1, kScope);
- GetToken(kTestAppID1, kUserID1, kScope, GCMDriverTest::WAIT);
- EXPECT_EQ(expected_token, registration_id());
- EXPECT_EQ(GCMClient::SUCCESS, registration_result());
- DeleteToken(kTestAppID1, kUserID1, kScope, GCMDriverTest::WAIT);
- EXPECT_EQ(GCMClient::SUCCESS, unregistration_result());
- }
- TEST_F(GCMDriverInstanceIDTest, GCMClientNotReadyBeforeDeleteToken) {
- CreateDriver();
- PumpIOLoop();
- PumpUILoop();
- // Make GCMClient not ready until PerformDelayedStart is called.
- GetGCMClient()->set_start_mode_overridding(
- FakeGCMClient::FORCE_TO_ALWAYS_DELAY_START_GCM);
- AddAppHandlers();
- // DeleteToken operation is on hold until GCMClient is ready.
- DeleteToken(kTestAppID1, kUserID1, kScope, GCMDriverTest::DO_NOT_WAIT);
- PumpIOLoop();
- PumpUILoop();
- EXPECT_EQ(GCMClient::UNKNOWN_ERROR, unregistration_result());
- // DeleteToken operation will be invoked after GCMClient becomes ready.
- GetGCMClient()->PerformDelayedStart();
- WaitForAsyncOperation();
- EXPECT_EQ(GCMClient::SUCCESS, unregistration_result());
- }
- } // namespace gcm
|