| // Copyright 2020 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef COMPONENTS_SYNC_INVALIDATIONS_FCM_HANDLER_H_ | |
| #define COMPONENTS_SYNC_INVALIDATIONS_FCM_HANDLER_H_ | |
| #include <optional> | |
| #include <string> | |
| #include "base/containers/circular_deque.h" | |
| #include "base/memory/raw_ptr.h" | |
| #include "base/observer_list.h" | |
| #include "base/sequence_checker.h" | |
| #include "base/time/time.h" | |
| #include "base/timer/timer.h" | |
| #include "components/gcm_driver/gcm_app_handler.h" | |
| #include "components/gcm_driver/instance_id/instance_id.h" | |
| #include "components/keyed_service/core/keyed_service.h" | |
| namespace gcm { | |
| class GCMDriver; | |
| } | |
| namespace instance_id { | |
| class InstanceIDDriver; | |
| } | |
| namespace syncer { | |
| class FCMRegistrationTokenObserver; | |
| class InvalidationsListener; | |
| // This handler is used to register with FCM and to process incoming messages. | |
| class FCMHandler : public gcm::GCMAppHandler { | |
| public: | |
| FCMHandler(gcm::GCMDriver* gcm_driver, | |
| instance_id::InstanceIDDriver* instance_id_driver, | |
| const std::string& sender_id, | |
| const std::string& app_id); | |
| ~FCMHandler() override; | |
| FCMHandler(const FCMHandler&) = delete; | |
| FCMHandler& operator=(const FCMHandler&) = delete; | |
| // Used to start handling incoming invalidations from the server and to obtain | |
| // an FCM token. This method gets called after data types are configured. | |
| // Before StartListening() is called for the first time, the FCM registration | |
| // token will be null. | |
| void StartListening(); | |
| // Stop handling incoming invalidations. It doesn't cleanup the FCM | |
| // registration token and doesn't unsubscribe from FCM. All incoming | |
| // invalidations will be dropped. This method gets called during browser | |
| // shutdown. | |
| void StopListening(); | |
| // Stop handling incoming invalidations and delete Instance ID. It clears the | |
| // FCM registration token. This method gets called during sign-out. | |
| void StopListeningPermanently(); | |
| // Returns if the handler is listening for incoming invalidations. | |
| bool IsListening() const; | |
| // Add a new `listener` which will be notified on each new incoming | |
| // invalidation. `listener` must not be nullptr. Does nothing if the | |
| // `listener` has already been added before. When a new `listener` is added, | |
| // previously received messages will be immediately replayed. | |
| void AddListener(InvalidationsListener* listener); | |
| // Returns whether `listener` was added before. | |
| bool HasListener(InvalidationsListener* listener); | |
| // Removes `listener`, does nothing if it wasn't added before. `listener` must | |
| // not be nullptr. | |
| void RemoveListener(InvalidationsListener* listener); | |
| // Add or remove an FCM token change observer. `observer` must not be nullptr. | |
| void AddTokenObserver(FCMRegistrationTokenObserver* observer); | |
| void RemoveTokenObserver(FCMRegistrationTokenObserver* observer); | |
| // Used to get an obtained FCM token. Returns null if it doesn't have a token. | |
| const std::optional<std::string>& GetFCMRegistrationToken() const; | |
| // GCMAppHandler overrides. | |
| void ShutdownHandler() override; | |
| void OnStoreReset() override; | |
| void OnMessage(const std::string& app_id, | |
| const gcm::IncomingMessage& message) override; | |
| void OnMessagesDeleted(const std::string& app_id) override; | |
| void OnSendError(const std::string& app_id, | |
| const gcm::GCMClient::SendErrorDetails& details) override; | |
| void OnSendAcknowledged(const std::string& app_id, | |
| const std::string& message_id) override; | |
| private: | |
| // Called when a subscription token is obtained from the GCM server. | |
| void DidRetrieveToken(const std::string& subscription_token, | |
| instance_id::InstanceID::Result result); | |
| void ScheduleNextTokenValidation(); | |
| void StartTokenValidation(); | |
| void StartTokenFetch(); | |
| SEQUENCE_CHECKER(sequence_checker_); | |
| raw_ptr<gcm::GCMDriver> gcm_driver_ = nullptr; | |
| raw_ptr<instance_id::InstanceIDDriver> instance_id_driver_ = nullptr; | |
| const std::string sender_id_; | |
| const std::string app_id_; | |
| // Contains an FCM registration token. Token is null if the experiment is off | |
| // or we don't have a valid token yet and contains valid token otherwise. | |
| std::optional<std::string> fcm_registration_token_; | |
| base::OneShotTimer token_validation_timer_; | |
| // A list of the latest incoming messages, used to replay incoming messages | |
| // whenever a new listener is added. | |
| base::circular_deque<std::string> last_received_messages_; | |
| // Contains all listeners to notify about each incoming message in OnMessage | |
| // method. | |
| base::ObserverList<InvalidationsListener, | |
| /*check_empty=*/true, | |
| base::ObserverListReentrancyPolicy::kDisallowReentrancy> | |
| listeners_; | |
| // Contains all FCM token observers to notify about each token change. | |
| base::ObserverList<FCMRegistrationTokenObserver, | |
| /*check_empty=*/true, | |
| base::ObserverListReentrancyPolicy::kDisallowReentrancy> | |
| token_observers_; | |
| base::WeakPtrFactory<FCMHandler> weak_ptr_factory_{this}; | |
| }; | |
| } // namespace syncer | |
| #endif // COMPONENTS_SYNC_INVALIDATIONS_FCM_HANDLER_H_ |