1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef COMPONENTS_SYNC_INVALIDATIONS_FCM_HANDLER_H_
6 #define COMPONENTS_SYNC_INVALIDATIONS_FCM_HANDLER_H_
7 
8 #include <string>
9 #include <vector>
10 
11 #include "base/observer_list.h"
12 #include "base/sequence_checker.h"
13 #include "base/timer/timer.h"
14 #include "components/gcm_driver/gcm_app_handler.h"
15 #include "components/gcm_driver/instance_id/instance_id.h"
16 #include "components/keyed_service/core/keyed_service.h"
17 
18 namespace gcm {
19 class GCMDriver;
20 }
21 
22 namespace instance_id {
23 class InstanceIDDriver;
24 }
25 
26 namespace syncer {
27 
28 class FCMRegistrationTokenObserver;
29 class InvalidationsListener;
30 
31 // This handler is used to register with FCM and to process incoming messages.
32 class FCMHandler : public gcm::GCMAppHandler {
33  public:
34   FCMHandler(gcm::GCMDriver* gcm_driver,
35              instance_id::InstanceIDDriver* instance_id_driver,
36              const std::string& sender_id,
37              const std::string& app_id);
38   ~FCMHandler() override;
39   FCMHandler(const FCMHandler&) = delete;
40   FCMHandler& operator=(const FCMHandler&) = delete;
41 
42   // Used to start handling incoming invalidations from the server and to obtain
43   // an FCM token. This method gets called after sign-in, or during browser
44   // startup if the user is already signed in. Before StartListening() is called
45   // for the first time, the FCM registration token will be empty.
46   void StartListening();
47 
48   // Stop handling incoming invalidations. It doesn't cleanup the FCM
49   // registration token and doesn't unsubscribe from FCM. All incoming
50   // invalidations will be dropped. This method gets called during browser
51   // shutdown.
52   void StopListening();
53 
54   // Stop handling incoming invalidations and delete Instance ID. It clears the
55   // FCM registration token. This method gets called during sign-out.
56   void StopListeningPermanently();
57 
58   // Returns if the handler is listening for incoming invalidations.
59   bool IsListening() const;
60 
61   // Add or remove a new listener which will be notified on each new incoming
62   // invalidation. |listener| must not be nullptr.
63   void AddListener(InvalidationsListener* listener);
64   void RemoveListener(InvalidationsListener* listener);
65 
66   // Add or remove an FCM token change observer. |observer| must not be nullptr.
67   void AddTokenObserver(FCMRegistrationTokenObserver* observer);
68   void RemoveTokenObserver(FCMRegistrationTokenObserver* observer);
69 
70   // Used to get an obtained FCM token. Returns empty string if it hasn't
71   // been received yet, or if the handler has stopped listening permanently.
72   const std::string& GetFCMRegistrationToken() const;
73 
74   // GCMAppHandler overrides.
75   void ShutdownHandler() override;
76   void OnStoreReset() override;
77   void OnMessage(const std::string& app_id,
78                  const gcm::IncomingMessage& message) override;
79   void OnMessagesDeleted(const std::string& app_id) override;
80   void OnSendError(const std::string& app_id,
81                    const gcm::GCMClient::SendErrorDetails& details) override;
82   void OnSendAcknowledged(const std::string& app_id,
83                           const std::string& message_id) override;
84 
85  private:
86   // Called when a subscription token is obtained from the GCM server.
87   void DidRetrieveToken(const std::string& subscription_token,
88                         instance_id::InstanceID::Result result);
89   void ScheduleNextTokenValidation();
90   void StartTokenValidation();
91   void DidReceiveTokenForValidation(const std::string& new_token,
92                                     instance_id::InstanceID::Result result);
93 
94   void StartTokenFetch(instance_id::InstanceID::GetTokenCallback callback);
95 
96   SEQUENCE_CHECKER(sequence_checker_);
97 
98   gcm::GCMDriver* gcm_driver_ = nullptr;
99   instance_id::InstanceIDDriver* instance_id_driver_ = nullptr;
100   const std::string sender_id_;
101   const std::string app_id_;
102 
103   // Contains an FCM registration token if not empty.
104   std::string fcm_registration_token_;
105 
106   base::OneShotTimer token_validation_timer_;
107 
108   // Contains all listeners to notify about each incoming message in OnMessage
109   // method.
110   base::ObserverList<InvalidationsListener,
111                      /*check_empty=*/true,
112                      /*allow_reentrancy=*/false>
113       listeners_;
114 
115   // Contains all FCM token observers to notify about each token change.
116   base::ObserverList<FCMRegistrationTokenObserver,
117                      /*check_empty=*/true,
118                      /*allow_reentrancy=*/false>
119       token_observers_;
120 
121   base::WeakPtrFactory<FCMHandler> weak_ptr_factory_{this};
122 };
123 
124 }  // namespace syncer
125 
126 #endif  // COMPONENTS_SYNC_INVALIDATIONS_FCM_HANDLER_H_
127