1 // Copyright 2014 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_GCM_DRIVER_GCM_DRIVER_H_
6 #define COMPONENTS_GCM_DRIVER_GCM_DRIVER_H_
7 
8 #include <map>
9 #include <string>
10 #include <vector>
11 
12 #include "base/callback.h"
13 #include "base/macros.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/threading/thread_checker.h"
17 #include "base/time/time.h"
18 #include "components/gcm_driver/common/gcm_message.h"
19 #include "components/gcm_driver/crypto/gcm_encryption_provider.h"
20 #include "components/gcm_driver/gcm_client.h"
21 
22 namespace base {
23 class FilePath;
24 class SequencedTaskRunner;
25 }  // namespace base
26 
27 namespace gcm {
28 
29 class GCMAppHandler;
30 class GCMConnectionObserver;
31 enum class GCMDecryptionResult;
32 enum class GCMEncryptionResult;
33 struct AccountMapping;
34 
35 // Provides the InstanceID support via GCMDriver.
36 class InstanceIDHandler {
37  public:
38   using GetTokenCallback = base::OnceCallback<void(const std::string& token,
39                                                    GCMClient::Result result)>;
40   using ValidateTokenCallback = base::OnceCallback<void(bool is_valid)>;
41   using DeleteTokenCallback =
42       base::OnceCallback<void(GCMClient::Result result)>;
43   using GetInstanceIDDataCallback =
44       base::OnceCallback<void(const std::string& instance_id,
45                               const std::string& extra_data)>;
46 
47   InstanceIDHandler();
48   virtual ~InstanceIDHandler();
49 
50   // Token service.
51   virtual void GetToken(const std::string& app_id,
52                         const std::string& authorized_entity,
53                         const std::string& scope,
54                         base::TimeDelta time_to_live,
55                         const std::map<std::string, std::string>& options,
56                         GetTokenCallback callback) = 0;
57   virtual void ValidateToken(const std::string& app_id,
58                              const std::string& authorized_entity,
59                              const std::string& scope,
60                              const std::string& token,
61                              ValidateTokenCallback callback) = 0;
62   virtual void DeleteToken(const std::string& app_id,
63                            const std::string& authorized_entity,
64                            const std::string& scope,
65                            DeleteTokenCallback callback) = 0;
66   void DeleteAllTokensForApp(const std::string& app_id,
67                              DeleteTokenCallback callback);
68 
69   // Persistence support.
70   virtual void AddInstanceIDData(const std::string& app_id,
71                                  const std::string& instance_id,
72                                  const std::string& extra_data) = 0;
73   virtual void RemoveInstanceIDData(const std::string& app_id) = 0;
74   virtual void GetInstanceIDData(const std::string& app_id,
75                                  GetInstanceIDDataCallback callback) = 0;
76 
77  private:
78   DISALLOW_COPY_AND_ASSIGN(InstanceIDHandler);
79 };
80 
81 // Bridge between GCM users in Chrome and the platform-specific implementation.
82 // Obtain instances of this object by using |GCMProfileServiceFactory|.
83 class GCMDriver {
84  public:
85   // Max number of sender IDs that can be passed to |Register| on desktop.
86   constexpr static size_t kMaxSenders = 100;
87 
88   using GCMAppHandlerMap = std::map<std::string, GCMAppHandler*>;
89   using RegisterCallback =
90       base::OnceCallback<void(const std::string& registration_id,
91                               GCMClient::Result result)>;
92   using ValidateRegistrationCallback = base::OnceCallback<void(bool is_valid)>;
93   using UnregisterCallback = base::OnceCallback<void(GCMClient::Result result)>;
94   using SendCallback = base::OnceCallback<void(const std::string& message_id,
95                                                GCMClient::Result result)>;
96   using GetEncryptionInfoCallback =
97       base::OnceCallback<void(std::string p256dh, std::string auth_secret)>;
98   using EncryptMessageCallback =
99       base::OnceCallback<void(GCMEncryptionResult result, std::string message)>;
100   using DecryptMessageCallback =
101       base::OnceCallback<void(GCMDecryptionResult result, std::string message)>;
102 
103   using GetGCMStatisticsCallback =
104       base::OnceCallback<void(const GCMClient::GCMStatistics& stats)>;
105   using GCMStatisticsRecordingCallback =
106       base::RepeatingCallback<void(const GCMClient::GCMStatistics& stats)>;
107 
108   // Enumeration to be used with GetGCMStatistics() for indicating whether the
109   // existing logs should be cleared or kept.
110   enum ClearActivityLogs { CLEAR_LOGS, KEEP_LOGS };
111 
112   GCMDriver(
113       const base::FilePath& store_path,
114       const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner);
115   virtual ~GCMDriver();
116 
117   // Registers |sender_ids| for an app. *Use |InstanceID| instead in new code.*
118   //
119   // A registration ID will be returned by the GCM server. On Android, only a
120   // single sender ID is supported, but instead multiple simultaneous
121   // registrations are allowed.
122   // |app_id|: application ID.
123   // |sender_ids|: list of IDs of the servers allowed to send messages to the
124   //               application. The IDs are assigned by the Google API Console.
125   //               Max number of IDs is 1 on Android, |kMaxSenders| on desktop.
126   // |callback|: to be called once the asynchronous operation is done.
127   void Register(const std::string& app_id,
128                 const std::vector<std::string>& sender_ids,
129                 RegisterCallback callback);
130 
131   // Checks that the provided |sender_ids| and |registration_id| matches the
132   // stored registration info for |app_id|.
133   virtual void ValidateRegistration(const std::string& app_id,
134                                     const std::vector<std::string>& sender_ids,
135                                     const std::string& registration_id,
136                                     ValidateRegistrationCallback callback) = 0;
137 
138   // Unregisters all sender_ids for an app. Only works on non-Android. Will also
139   // remove any encryption keys associated with the |app_id|.
140   // |app_id|: application ID.
141   // |callback|: to be called once the asynchronous operation is done.
142   void Unregister(const std::string& app_id, UnregisterCallback callback);
143 
144   // Unregisters an (app_id, sender_id) pair from using GCM. Only works on
145   // Android. Will also remove any encryption keys associated with the |app_id|.
146   // TODO(jianli): Switch to using GCM's unsubscribe API.
147   // |app_id|: application ID.
148   // |sender_id|: the sender ID that was passed when registering.
149   // |callback|: to be called once the asynchronous operation is done.
150   void UnregisterWithSenderId(const std::string& app_id,
151                               const std::string& sender_id,
152                               UnregisterCallback callback);
153 
154   // Sends a message to a given receiver.
155   // |app_id|: application ID.
156   // |receiver_id|: registration ID of the receiver party.
157   // |message|: message to be sent.
158   // |callback|: to be called once the asynchronous operation is done.
159   void Send(const std::string& app_id,
160             const std::string& receiver_id,
161             const OutgoingMessage& message,
162             SendCallback callback);
163 
164   // Get the public encryption key and the authentication secret associated with
165   // |app_id|. If none have been associated with |app_id| yet, they will be
166   // created. The |callback| will be invoked when it is available. Only use with
167   // GCM registrations; use InstanceID::GetEncryptionInfo for InstanceID tokens.
168   virtual void GetEncryptionInfo(const std::string& app_id,
169                                  GetEncryptionInfoCallback callback);
170 
171   // Attempts to encrypt the |message| using draft-ietf-webpush-encryption-08
172   // scheme using keys from internal key store. Either GetEncryptionInfo or
173   // InstanceID::GetEncryptionInfo must be called once for keys to be available.
174   // |callback| will be called asynchronously when |message| has been encrypted.
175   // A dispatchable message will be used in case of success, an empty message in
176   // case of failure.
177   virtual void EncryptMessage(const std::string& app_id,
178                               const std::string& authorized_entity,
179                               const std::string& p256dh,
180                               const std::string& auth_secret,
181                               const std::string& message,
182                               EncryptMessageCallback callback);
183 
184   // Attempts to decrypt the |message|using draft-ietf-webpush-encryption-08
185   // scheme using keys from internal key store. Either GetEncryptionInfo or
186   // InstanceID::GetEncryptionInfo must be called once for keys to be available.
187   // |callback| will be called asynchronously when |message| has been decrypted.
188   // A dispatchable message will be used in case of success, an empty message in
189   // case of failure.
190   // TODO(crbug/1045907): Decouple this from GCMDriver.
191   virtual void DecryptMessage(const std::string& app_id,
192                               const std::string& authorized_entity,
193                               const std::string& message,
194                               DecryptMessageCallback callback);
195 
app_handlers()196   const GCMAppHandlerMap& app_handlers() const { return app_handlers_; }
197 
198   // This method must be called before destroying the GCMDriver. Once it has
199   // been called, no other GCMDriver methods may be used.
200   virtual void Shutdown();
201 
202   // Called when the user signs in to or out of a GAIA account.
203   virtual void OnSignedIn() = 0;
204   virtual void OnSignedOut() = 0;
205 
206   // Adds a handler for a given app.
207   virtual void AddAppHandler(const std::string& app_id, GCMAppHandler* handler);
208 
209   // Remove the handler for a given app.
210   virtual void RemoveAppHandler(const std::string& app_id);
211 
212   // Returns the handler for the given app. May return a nullptr when no handler
213   // could be found for the |app_id|.
214   GCMAppHandler* GetAppHandler(const std::string& app_id);
215 
216   // Adds a connection state observer.
217   virtual void AddConnectionObserver(GCMConnectionObserver* observer) = 0;
218 
219   // Removes a connection state observer.
220   virtual void RemoveConnectionObserver(GCMConnectionObserver* observer) = 0;
221 
222   // For testing purpose. Always NULL on Android.
223   virtual GCMClient* GetGCMClientForTesting() const = 0;
224 
225   // Returns true if the service was started.
226   virtual bool IsStarted() const = 0;
227 
228   // Returns true if the gcm client has an open and active connection.
229   virtual bool IsConnected() const = 0;
230 
231   // Get GCM client internal states and statistics. The activity logs will be
232   // cleared before returning the stats when |clear_logs| is set to CLEAR_LOGS.
233   virtual void GetGCMStatistics(GetGCMStatisticsCallback callback,
234                                 ClearActivityLogs clear_logs) = 0;
235 
236   // Enables/disables GCM activity recording, and then returns the stats.
237   // |callback| will be called for new activity.
238   virtual void SetGCMRecording(const GCMStatisticsRecordingCallback& callback,
239                                bool recording) = 0;
240 
241   // sets a list of signed in accounts with OAuth2 access tokens, when GCMDriver
242   // works in context of a signed in entity (e.g. browser profile where user is
243   // signed into sync).
244   // |account_tokens|: list of email addresses, account IDs and OAuth2 access
245   //                   tokens.
246   virtual void SetAccountTokens(
247       const std::vector<GCMClient::AccountTokenInfo>& account_tokens) = 0;
248 
249   // Updates the |account_mapping| information in persistent store.
250   virtual void UpdateAccountMapping(const AccountMapping& account_mapping) = 0;
251 
252   // Removes the account mapping information reated to |account_id| from
253   // persistent store.
254   virtual void RemoveAccountMapping(const CoreAccountId& account_id) = 0;
255 
256   // Getter and setter of last token fetch time.
257   virtual base::Time GetLastTokenFetchTime() = 0;
258   virtual void SetLastTokenFetchTime(const base::Time& time) = 0;
259 
260   // Sets whether or not GCM should try to wake the system from suspend in order
261   // to send a heartbeat message.
262   virtual void WakeFromSuspendForHeartbeat(bool wake) = 0;
263 
264   // These methods must only be used by the InstanceID system.
265   // The InstanceIDHandler provides an implementation for the InstanceID system.
266   virtual InstanceIDHandler* GetInstanceIDHandlerInternal() = 0;
267   // Allows the InstanceID system to integrate with GCM encryption storage.
268   virtual GCMEncryptionProvider* GetEncryptionProviderInternal();
269 
270   // Adds or removes a custom client requested heartbeat interval. If multiple
271   // components set that setting, the lowest setting will be used. If the
272   // setting is outside of GetMax/MinClientHeartbeatIntervalMs() it will be
273   // ignored. If a new setting is less than the currently used, the connection
274   // will be reset with the new heartbeat. Client that no longer require
275   // aggressive heartbeats, should remove their requested interval. Heartbeats
276   // set this way survive connection/Chrome restart.
277   //
278   // GCM Driver can decide to postpone the action until Client is properly
279   // initialized, hence this setting can be called at any time.
280   //
281   // Server can overwrite the setting to a different value.
282   //
283   // |scope| is used to identify the component that requests a custom interval
284   // to be set, and allows that component to later revoke the setting.
285   // |interval_ms| should be between 2 minues and 15 minues (28 minues on
286   // cellular networks). For details check
287   // GetMin/MaxClientHeartbeatItnervalMs() in HeartbeatManager.
288   virtual void AddHeartbeatInterval(const std::string& scope,
289                                     int interval_ms) = 0;
290   virtual void RemoveHeartbeatInterval(const std::string& scope) = 0;
291 
292  protected:
293   // Ensures that the GCM service starts (if necessary conditions are met).
294   virtual GCMClient::Result EnsureStarted(GCMClient::StartMode start_mode) = 0;
295 
296   // Platform-specific implementation of Register.
297   virtual void RegisterImpl(const std::string& app_id,
298                             const std::vector<std::string>& sender_ids) = 0;
299 
300   // Platform-specific implementation of Unregister.
301   virtual void UnregisterImpl(const std::string& app_id) = 0;
302 
303   // Platform-specific implementation of UnregisterWithSenderId.
304   virtual void UnregisterWithSenderIdImpl(const std::string& app_id,
305                                           const std::string& sender_id);
306 
307   // Platform-specific implementation of Send.
308   virtual void SendImpl(const std::string& app_id,
309                         const std::string& receiver_id,
310                         const OutgoingMessage& message) = 0;
311 
312   // Platform-specific implementation of recording message decryption failures.
313   virtual void RecordDecryptionFailure(const std::string& app_id,
314                                        GCMDecryptionResult result) = 0;
315 
316   // Runs the Register callback.
317   void RegisterFinished(const std::string& app_id,
318                         const std::string& registration_id,
319                         GCMClient::Result result);
320 
321   // To be called when a registration for |app_id| has been unregistered, having
322   // |result| as the result of the unregistration. Will remove any encryption
323   // information associated with the |app_id| and then calls UnregisterFinished.
324   void RemoveEncryptionInfoAfterUnregister(const std::string& app_id,
325                                            GCMClient::Result result);
326 
327   // Runs the Unregister callback.
328   void UnregisterFinished(const std::string& app_id, GCMClient::Result result);
329 
330   // Runs the Send callback.
331   void SendFinished(const std::string& app_id,
332                     const std::string& message_id,
333                     GCMClient::Result result);
334 
335   bool HasRegisterCallback(const std::string& app_id);
336 
337   void ClearCallbacks();
338 
339   // Dispatches the OnMessage event to the app handler associated with |app_id|.
340   // If |message| has been encrypted, it will be decrypted asynchronously and
341   // dispatched when the decryption operation was successful. Otherwise, the
342   // |message| will be dispatched immediately to the handler for |app_id|.
343   void DispatchMessage(const std::string& app_id,
344                        const IncomingMessage& message);
345 
346  private:
347   // Common code shared by Unregister and UnregisterWithSenderId.
348   void UnregisterInternal(const std::string& app_id,
349                           const std::string* sender_id,
350                           UnregisterCallback callback);
351 
352   // Dispatches the OnMessage event to the app handler associated with |app_id|
353   // if |result| indicates that it is safe to do so, or will report a decryption
354   // failure for the |app_id| otherwise.
355   void DispatchMessageInternal(const std::string& app_id,
356                                GCMDecryptionResult result,
357                                IncomingMessage message);
358 
359   // Called after unregistration completes in order to trigger the pending
360   // registration.
361   void RegisterAfterUnregister(
362       const std::string& app_id,
363       const std::vector<std::string>& normalized_sender_ids,
364       UnregisterCallback unregister_callback,
365       GCMClient::Result result);
366 
367   void OnMessageEncrypted(EncryptMessageCallback callback,
368                           GCMEncryptionResult result,
369                           std::string message);
370 
371   void OnMessageDecrypted(DecryptMessageCallback callback,
372                           GCMDecryptionResult result,
373                           IncomingMessage message);
374 
375   // Callback map (from app_id to callback) for Register.
376   std::map<std::string, RegisterCallback> register_callbacks_;
377 
378   // Callback map (from app_id to callback) for Unregister.
379   std::map<std::string, UnregisterCallback> unregister_callbacks_;
380 
381   // Callback map (from <app_id, message_id> to callback) for Send.
382   std::map<std::pair<std::string, std::string>, SendCallback> send_callbacks_;
383 
384   // The encryption provider, used for key management and decryption of
385   // encrypted, incoming messages.
386   GCMEncryptionProvider encryption_provider_;
387 
388   // App handler map (from app_id to handler pointer). The handler is not owned.
389   GCMAppHandlerMap app_handlers_;
390 
391   base::WeakPtrFactory<GCMDriver> weak_ptr_factory_{this};
392 
393   DISALLOW_COPY_AND_ASSIGN(GCMDriver);
394 };
395 
396 }  // namespace gcm
397 
398 #endif  // COMPONENTS_GCM_DRIVER_GCM_DRIVER_H_
399