| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/gcm_driver/fake_gcm_profile_service.h" |
| |
| #include <utility> |
| |
| #include "base/format_macros.h" |
| #include "base/functional/bind.h" |
| #include "base/location.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "base/time/time.h" |
| #include "components/gcm_driver/crypto/gcm_encryption_result.h" |
| #include "components/gcm_driver/gcm_driver.h" |
| #include "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h" |
| |
| namespace gcm { |
| |
| class FakeGCMProfileService::CustomFakeGCMDriver |
| : public instance_id::FakeGCMDriverForInstanceID { |
| public: |
| CustomFakeGCMDriver(); |
| |
| // Must be called before any other methods. |
| void SetService(FakeGCMProfileService* service); |
| |
| CustomFakeGCMDriver(const CustomFakeGCMDriver&) = delete; |
| CustomFakeGCMDriver& operator=(const CustomFakeGCMDriver&) = delete; |
| |
| ~CustomFakeGCMDriver() override; |
| |
| void OnRegisterFinished(const std::string& app_id, |
| const std::string& registration_id, |
| GCMClient::Result result); |
| void OnSendFinished(const std::string& app_id, |
| const std::string& message_id, |
| GCMClient::Result result); |
| |
| // GCMDriver overrides: |
| void EncryptMessage(const std::string& app_id, |
| const std::string& authorized_entity, |
| const std::string& p256dh, |
| const std::string& auth_secret, |
| const std::string& message, |
| EncryptMessageCallback callback) override; |
| |
| protected: |
| // FakeGCMDriver overrides: |
| void RegisterImpl(const std::string& app_id, |
| const std::vector<std::string>& sender_ids) override; |
| void UnregisterImpl(const std::string& app_id) override; |
| void UnregisterWithSenderIdImpl(const std::string& app_id, |
| const std::string& sender_id) override; |
| void SendImpl(const std::string& app_id, |
| const std::string& receiver_id, |
| const OutgoingMessage& message) override; |
| |
| // FakeGCMDriverForInstanceID overrides: |
| void GetToken(const std::string& app_id, |
| const std::string& authorized_entity, |
| const std::string& scope, |
| base::TimeDelta time_to_live, |
| GetTokenCallback callback) override; |
| void DeleteToken(const std::string& app_id, |
| const std::string& authorized_entity, |
| const std::string& scope, |
| DeleteTokenCallback callback) override; |
| |
| private: |
| void DoRegister(const std::string& app_id, |
| const std::vector<std::string>& sender_ids, |
| const std::string& registration_id); |
| void DoSend(const std::string& app_id, |
| const std::string& receiver_id, |
| const OutgoingMessage& message); |
| |
| raw_ptr<FakeGCMProfileService> service_ = nullptr; |
| |
| // Used to give each registration a unique registration id. Does not decrease |
| // when unregister is called. |
| int registration_count_ = 0; |
| |
| base::WeakPtrFactory<CustomFakeGCMDriver> weak_factory_{ |
| this}; // Must be last. |
| }; |
| |
| FakeGCMProfileService::CustomFakeGCMDriver::CustomFakeGCMDriver() = default; |
| |
| FakeGCMProfileService::CustomFakeGCMDriver::~CustomFakeGCMDriver() = default; |
| |
| void FakeGCMProfileService::CustomFakeGCMDriver::RegisterImpl( |
| const std::string& app_id, |
| const std::vector<std::string>& sender_ids) { |
| if (service_->is_offline_) |
| return; // Drop request. |
| |
| // Generate fake registration IDs, encoding the number of sender IDs (used by |
| // GcmApiTest.RegisterValidation), then an incrementing count (even for the |
| // same app_id - there's no caching) so tests can distinguish registrations. |
| std::string registration_id = base::StringPrintf( |
| "%" PRIuS "-%d", sender_ids.size(), registration_count_); |
| ++registration_count_; |
| |
| base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( |
| FROM_HERE, base::BindOnce(&CustomFakeGCMDriver::DoRegister, |
| weak_factory_.GetWeakPtr(), app_id, sender_ids, |
| registration_id)); |
| } |
| |
| void FakeGCMProfileService::CustomFakeGCMDriver::DoRegister( |
| const std::string& app_id, |
| const std::vector<std::string>& sender_ids, |
| const std::string& registration_id) { |
| if (service_->collect_) { |
| service_->last_registered_app_id_ = app_id; |
| service_->last_registered_sender_ids_ = sender_ids; |
| } |
| RegisterFinished(app_id, registration_id, GCMClient::SUCCESS); |
| } |
| |
| void FakeGCMProfileService::CustomFakeGCMDriver::UnregisterImpl( |
| const std::string& app_id) { |
| if (service_->is_offline_) |
| return; // Drop request. |
| |
| GCMClient::Result result = GCMClient::SUCCESS; |
| if (!service_->unregister_responses_.empty()) { |
| result = service_->unregister_responses_.front(); |
| service_->unregister_responses_.pop_front(); |
| } |
| base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( |
| FROM_HERE, base::BindOnce(&CustomFakeGCMDriver::UnregisterFinished, |
| weak_factory_.GetWeakPtr(), app_id, result)); |
| } |
| |
| void FakeGCMProfileService::CustomFakeGCMDriver::UnregisterWithSenderIdImpl( |
| const std::string& app_id, |
| const std::string& sender_id) { |
| NOTREACHED() << "This Android-specific method is not yet faked."; |
| } |
| |
| void FakeGCMProfileService::CustomFakeGCMDriver::SendImpl( |
| const std::string& app_id, |
| const std::string& receiver_id, |
| const OutgoingMessage& message) { |
| if (service_->is_offline_) |
| return; // Drop request. |
| |
| base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( |
| FROM_HERE, |
| base::BindOnce(&CustomFakeGCMDriver::DoSend, weak_factory_.GetWeakPtr(), |
| app_id, receiver_id, message)); |
| } |
| |
| void FakeGCMProfileService::CustomFakeGCMDriver::EncryptMessage( |
| const std::string& app_id, |
| const std::string& authorized_entity, |
| const std::string& p256dh, |
| const std::string& auth_secret, |
| const std::string& message, |
| EncryptMessageCallback callback) { |
| // Pretend that message has been encrypted. |
| std::move(callback).Run(GCMEncryptionResult::ENCRYPTED_DRAFT_08, message); |
| } |
| |
| void FakeGCMProfileService::CustomFakeGCMDriver::SetService( |
| FakeGCMProfileService* service) { |
| service_ = service; |
| } |
| |
| void FakeGCMProfileService::CustomFakeGCMDriver::DoSend( |
| const std::string& app_id, |
| const std::string& receiver_id, |
| const OutgoingMessage& message) { |
| if (service_->collect_) { |
| service_->last_sent_message_ = message; |
| service_->last_receiver_id_ = receiver_id; |
| } |
| SendFinished(app_id, message.id, GCMClient::SUCCESS); |
| } |
| |
| void FakeGCMProfileService::CustomFakeGCMDriver::GetToken( |
| const std::string& app_id, |
| const std::string& authorized_entity, |
| const std::string& scope, |
| base::TimeDelta time_to_live, |
| GetTokenCallback callback) { |
| if (service_->is_offline_) |
| return; // Drop request. |
| |
| instance_id::FakeGCMDriverForInstanceID::GetToken( |
| app_id, authorized_entity, scope, time_to_live, std::move(callback)); |
| } |
| |
| void FakeGCMProfileService::CustomFakeGCMDriver::DeleteToken( |
| const std::string& app_id, |
| const std::string& authorized_entity, |
| const std::string& scope, |
| DeleteTokenCallback callback) { |
| if (service_->is_offline_) |
| return; // Drop request. |
| |
| instance_id::FakeGCMDriverForInstanceID::DeleteToken( |
| app_id, authorized_entity, scope, std::move(callback)); |
| } |
| |
| // static |
| std::unique_ptr<KeyedService> FakeGCMProfileService::Build( |
| content::BrowserContext* context) { |
| auto custom_driver = std::make_unique<CustomFakeGCMDriver>(); |
| CustomFakeGCMDriver* custom_driver_ptr = custom_driver.get(); |
| |
| std::unique_ptr<FakeGCMProfileService> service = |
| std::make_unique<FakeGCMProfileService>(std::move(custom_driver)); |
| |
| custom_driver_ptr->SetService(service.get()); |
| return service; |
| } |
| |
| FakeGCMProfileService::FakeGCMProfileService( |
| std::unique_ptr<instance_id::FakeGCMDriverForInstanceID> fake_gcm_driver) |
| : GCMProfileService(std::move(fake_gcm_driver)) {} |
| |
| FakeGCMProfileService::~FakeGCMProfileService() = default; |
| |
| void FakeGCMProfileService::AddExpectedUnregisterResponse( |
| GCMClient::Result result) { |
| unregister_responses_.push_back(result); |
| } |
| |
| void FakeGCMProfileService::DispatchMessage(const std::string& app_id, |
| const IncomingMessage& message) { |
| GetFakeGCMDriver()->DispatchMessage(app_id, message); |
| } |
| |
| instance_id::FakeGCMDriverForInstanceID* |
| FakeGCMProfileService::GetFakeGCMDriver() { |
| return static_cast<instance_id::FakeGCMDriverForInstanceID*>(driver()); |
| } |
| |
| } // namespace gcm |