|  | // 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. | 
|  |  | 
|  | #ifndef COMPONENTS_GCM_DRIVER_GCM_DRIVER_H_ | 
|  | #define COMPONENTS_GCM_DRIVER_GCM_DRIVER_H_ | 
|  |  | 
|  | #include <map> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/callback.h" | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/ref_counted.h" | 
|  | #include "base/memory/weak_ptr.h" | 
|  | #include "base/threading/thread_checker.h" | 
|  | #include "components/gcm_driver/common/gcm_messages.h" | 
|  | #include "components/gcm_driver/crypto/gcm_encryption_provider.h" | 
|  | #include "components/gcm_driver/gcm_client.h" | 
|  |  | 
|  | namespace base { | 
|  | class FilePath; | 
|  | class SequencedTaskRunner; | 
|  | } | 
|  |  | 
|  | namespace gcm { | 
|  |  | 
|  | class GCMAppHandler; | 
|  | class GCMConnectionObserver; | 
|  | struct AccountMapping; | 
|  |  | 
|  | // Provides the InstanceID support via GCMDriver. | 
|  | class InstanceIDHandler { | 
|  | public: | 
|  | using GetTokenCallback = | 
|  | base::Callback<void(const std::string& token, GCMClient::Result result)>; | 
|  | using ValidateTokenCallback = base::Callback<void(bool is_valid)>; | 
|  | using DeleteTokenCallback = base::Callback<void(GCMClient::Result result)>; | 
|  | using GetInstanceIDDataCallback = | 
|  | base::Callback<void(const std::string& instance_id, | 
|  | const std::string& extra_data)>; | 
|  |  | 
|  | InstanceIDHandler(); | 
|  | virtual ~InstanceIDHandler(); | 
|  |  | 
|  | // Token service. | 
|  | virtual void GetToken(const std::string& app_id, | 
|  | const std::string& authorized_entity, | 
|  | const std::string& scope, | 
|  | const std::map<std::string, std::string>& options, | 
|  | const GetTokenCallback& callback) = 0; | 
|  | virtual void ValidateToken(const std::string& app_id, | 
|  | const std::string& authorized_entity, | 
|  | const std::string& scope, | 
|  | const std::string& token, | 
|  | const ValidateTokenCallback& callback) = 0; | 
|  | virtual void DeleteToken(const std::string& app_id, | 
|  | const std::string& authorized_entity, | 
|  | const std::string& scope, | 
|  | const DeleteTokenCallback& callback) = 0; | 
|  | void DeleteAllTokensForApp(const std::string& app_id, | 
|  | const DeleteTokenCallback& callback); | 
|  |  | 
|  | // Persistence support. | 
|  | virtual void AddInstanceIDData(const std::string& app_id, | 
|  | const std::string& instance_id, | 
|  | const std::string& extra_data) = 0; | 
|  | virtual void RemoveInstanceIDData(const std::string& app_id) = 0; | 
|  | virtual void GetInstanceIDData( | 
|  | const std::string& app_id, | 
|  | const GetInstanceIDDataCallback& callback) = 0; | 
|  |  | 
|  | private: | 
|  | DISALLOW_COPY_AND_ASSIGN(InstanceIDHandler); | 
|  | }; | 
|  |  | 
|  | // Bridge between GCM users in Chrome and the platform-specific implementation. | 
|  | class GCMDriver { | 
|  | public: | 
|  | // Max number of sender IDs that can be passed to |Register| on desktop. | 
|  | constexpr static size_t kMaxSenders = 100; | 
|  |  | 
|  | using GCMAppHandlerMap = std::map<std::string, GCMAppHandler*>; | 
|  | using RegisterCallback = | 
|  | base::Callback<void(const std::string& registration_id, | 
|  | GCMClient::Result result)>; | 
|  | using ValidateRegistrationCallback = base::Callback<void(bool is_valid)>; | 
|  | using UnregisterCallback = base::Callback<void(GCMClient::Result result)>; | 
|  | using SendCallback = base::Callback<void(const std::string& message_id, | 
|  | GCMClient::Result result)>; | 
|  | using GetEncryptionInfoCallback = | 
|  | base::Callback<void(const std::string&, const std::string&)>; | 
|  | using GetGCMStatisticsCallback = | 
|  | base::Callback<void(const GCMClient::GCMStatistics& stats)>; | 
|  |  | 
|  | // Enumeration to be used with GetGCMStatistics() for indicating whether the | 
|  | // existing logs should be cleared or kept. | 
|  | enum ClearActivityLogs { | 
|  | CLEAR_LOGS, | 
|  | KEEP_LOGS | 
|  | }; | 
|  |  | 
|  | GCMDriver( | 
|  | const base::FilePath& store_path, | 
|  | const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner); | 
|  | virtual ~GCMDriver(); | 
|  |  | 
|  | // Registers |sender_ids| for an app. A registration ID will be returned by | 
|  | // the GCM server. On Android, only a single sender ID is supported, but | 
|  | // instead multiple simultaneous registrations are allowed. | 
|  | // |app_id|: application ID. | 
|  | // |sender_ids|: list of IDs of the servers allowed to send messages to the | 
|  | //               application. The IDs are assigned by the Google API Console. | 
|  | //               Max number of IDs is 1 on Android, |kMaxSenders| on desktop. | 
|  | // |callback|: to be called once the asynchronous operation is done. | 
|  | void Register(const std::string& app_id, | 
|  | const std::vector<std::string>& sender_ids, | 
|  | const RegisterCallback& callback); | 
|  |  | 
|  | // Checks that the provided |sender_ids| and |registration_id| matches the | 
|  | // stored registration info for |app_id|. | 
|  | virtual void ValidateRegistration( | 
|  | const std::string& app_id, | 
|  | const std::vector<std::string>& sender_ids, | 
|  | const std::string& registration_id, | 
|  | const ValidateRegistrationCallback& callback) = 0; | 
|  |  | 
|  | // Unregisters all sender_ids for an app. Only works on non-Android. Will also | 
|  | // remove any encryption keys associated with the |app_id|. | 
|  | // |app_id|: application ID. | 
|  | // |callback|: to be called once the asynchronous operation is done. | 
|  | void Unregister(const std::string& app_id, | 
|  | const UnregisterCallback& callback); | 
|  |  | 
|  | // Unregisters an (app_id, sender_id) pair from using GCM. Only works on | 
|  | // Android. Will also remove any encryption keys associated with the |app_id|. | 
|  | // TODO(jianli): Switch to using GCM's unsubscribe API. | 
|  | // |app_id|: application ID. | 
|  | // |sender_id|: the sender ID that was passed when registering. | 
|  | // |callback|: to be called once the asynchronous operation is done. | 
|  | void UnregisterWithSenderId(const std::string& app_id, | 
|  | const std::string& sender_id, | 
|  | const UnregisterCallback& callback); | 
|  |  | 
|  | // Sends a message to a given receiver. | 
|  | // |app_id|: application ID. | 
|  | // |receiver_id|: registration ID of the receiver party. | 
|  | // |message|: message to be sent. | 
|  | // |callback|: to be called once the asynchronous operation is done. | 
|  | void Send(const std::string& app_id, | 
|  | const std::string& receiver_id, | 
|  | const OutgoingMessage& message, | 
|  | const SendCallback& callback); | 
|  |  | 
|  | // Get the public encryption key and the authentication secret associated with | 
|  | // |app_id|. If none have been associated with |app_id| yet, they will be | 
|  | // created. The |callback| will be invoked when it is available. Only use with | 
|  | // GCM registrations; use InstanceID::GetEncryptionInfo for InstanceID tokens. | 
|  | void GetEncryptionInfo(const std::string& app_id, | 
|  | const GetEncryptionInfoCallback& callback); | 
|  |  | 
|  | const GCMAppHandlerMap& app_handlers() const { return app_handlers_; } | 
|  |  | 
|  | // This method must be called before destroying the GCMDriver. Once it has | 
|  | // been called, no other GCMDriver methods may be used. | 
|  | virtual void Shutdown(); | 
|  |  | 
|  | // Called when the user signs in to or out of a GAIA account. | 
|  | virtual void OnSignedIn() = 0; | 
|  | virtual void OnSignedOut() = 0; | 
|  |  | 
|  | // Adds a handler for a given app. | 
|  | virtual void AddAppHandler(const std::string& app_id, GCMAppHandler* handler); | 
|  |  | 
|  | // Remove the handler for a given app. | 
|  | virtual void RemoveAppHandler(const std::string& app_id); | 
|  |  | 
|  | // Returns the handler for the given app. May return a nullptr when no handler | 
|  | // could be found for the |app_id|. | 
|  | GCMAppHandler* GetAppHandler(const std::string& app_id); | 
|  |  | 
|  | // Adds a connection state observer. | 
|  | virtual void AddConnectionObserver(GCMConnectionObserver* observer) = 0; | 
|  |  | 
|  | // Removes a connection state observer. | 
|  | virtual void RemoveConnectionObserver(GCMConnectionObserver* observer) = 0; | 
|  |  | 
|  | // Enables/disables GCM service. | 
|  | virtual void Enable() = 0; | 
|  | virtual void Disable() = 0; | 
|  |  | 
|  | // For testing purpose. Always NULL on Android. | 
|  | virtual GCMClient* GetGCMClientForTesting() const = 0; | 
|  |  | 
|  | // Returns true if the service was started. | 
|  | virtual bool IsStarted() const = 0; | 
|  |  | 
|  | // Returns true if the gcm client has an open and active connection. | 
|  | virtual bool IsConnected() const = 0; | 
|  |  | 
|  | // Get GCM client internal states and statistics. The activity logs will be | 
|  | // cleared before returning the stats when |clear_logs| is set to CLEAR_LOGS. | 
|  | virtual void GetGCMStatistics(const GetGCMStatisticsCallback& callback, | 
|  | ClearActivityLogs clear_logs) = 0; | 
|  |  | 
|  | // Enables/disables GCM activity recording, and then returns the stats. | 
|  | virtual void SetGCMRecording(const GetGCMStatisticsCallback& callback, | 
|  | bool recording) = 0; | 
|  |  | 
|  | // sets a list of signed in accounts with OAuth2 access tokens, when GCMDriver | 
|  | // works in context of a signed in entity (e.g. browser profile where user is | 
|  | // signed into sync). | 
|  | // |account_tokens|: list of email addresses, account IDs and OAuth2 access | 
|  | //                   tokens. | 
|  | virtual void SetAccountTokens( | 
|  | const std::vector<GCMClient::AccountTokenInfo>& account_tokens) = 0; | 
|  |  | 
|  | // Updates the |account_mapping| information in persistent store. | 
|  | virtual void UpdateAccountMapping(const AccountMapping& account_mapping) = 0; | 
|  |  | 
|  | // Removes the account mapping information reated to |account_id| from | 
|  | // persistent store. | 
|  | virtual void RemoveAccountMapping(const std::string& account_id) = 0; | 
|  |  | 
|  | // Getter and setter of last token fetch time. | 
|  | virtual base::Time GetLastTokenFetchTime() = 0; | 
|  | virtual void SetLastTokenFetchTime(const base::Time& time) = 0; | 
|  |  | 
|  | // Sets whether or not GCM should try to wake the system from suspend in order | 
|  | // to send a heartbeat message. | 
|  | virtual void WakeFromSuspendForHeartbeat(bool wake) = 0; | 
|  |  | 
|  | // These methods must only be used by the InstanceID system. | 
|  | // The InstanceIDHandler provides an implementation for the InstanceID system. | 
|  | virtual InstanceIDHandler* GetInstanceIDHandlerInternal() = 0; | 
|  | // Allows the InstanceID system to integrate with GCM encryption storage. | 
|  | GCMEncryptionProvider* GetEncryptionProviderInternal(); | 
|  |  | 
|  | // Adds or removes a custom client requested heartbeat interval. If multiple | 
|  | // components set that setting, the lowest setting will be used. If the | 
|  | // setting is outside of GetMax/MinClientHeartbeatIntervalMs() it will be | 
|  | // ignored. If a new setting is less than the currently used, the connection | 
|  | // will be reset with the new heartbeat. Client that no longer require | 
|  | // aggressive heartbeats, should remove their requested interval. Heartbeats | 
|  | // set this way survive connection/Chrome restart. | 
|  | // | 
|  | // GCM Driver can decide to postpone the action until Client is properly | 
|  | // initialized, hence this setting can be called at any time. | 
|  | // | 
|  | // Server can overwrite the setting to a different value. | 
|  | // | 
|  | // |scope| is used to identify the component that requests a custom interval | 
|  | // to be set, and allows that component to later revoke the setting. | 
|  | // |interval_ms| should be between 2 minues and 15 minues (28 minues on | 
|  | // cellular networks). For details check | 
|  | // GetMin/MaxClientHeartbeatItnervalMs() in HeartbeatManager. | 
|  | virtual void AddHeartbeatInterval(const std::string& scope, | 
|  | int interval_ms) = 0; | 
|  | virtual void RemoveHeartbeatInterval(const std::string& scope) = 0; | 
|  |  | 
|  | protected: | 
|  | // Ensures that the GCM service starts (if necessary conditions are met). | 
|  | virtual GCMClient::Result EnsureStarted(GCMClient::StartMode start_mode) = 0; | 
|  |  | 
|  | // Platform-specific implementation of Register. | 
|  | virtual void RegisterImpl(const std::string& app_id, | 
|  | const std::vector<std::string>& sender_ids) = 0; | 
|  |  | 
|  | // Platform-specific implementation of Unregister. | 
|  | virtual void UnregisterImpl(const std::string& app_id) = 0; | 
|  |  | 
|  | // Platform-specific implementation of UnregisterWithSenderId. | 
|  | virtual void UnregisterWithSenderIdImpl(const std::string& app_id, | 
|  | const std::string& sender_id); | 
|  |  | 
|  | // Platform-specific implementation of Send. | 
|  | virtual void SendImpl(const std::string& app_id, | 
|  | const std::string& receiver_id, | 
|  | const OutgoingMessage& message) = 0; | 
|  |  | 
|  | // Platform-specific implementation of recording message decryption failures. | 
|  | virtual void RecordDecryptionFailure( | 
|  | const std::string& app_id, | 
|  | GCMEncryptionProvider::DecryptionResult result) = 0; | 
|  |  | 
|  | // Runs the Register callback. | 
|  | void RegisterFinished(const std::string& app_id, | 
|  | const std::string& registration_id, | 
|  | GCMClient::Result result); | 
|  |  | 
|  | // To be called when a registration for |app_id| has been unregistered, having | 
|  | // |result| as the result of the unregistration. Will remove any encryption | 
|  | // information associated with the |app_id| and then calls UnregisterFinished. | 
|  | void RemoveEncryptionInfoAfterUnregister(const std::string& app_id, | 
|  | GCMClient::Result result); | 
|  |  | 
|  | // Runs the Unregister callback. | 
|  | void UnregisterFinished(const std::string& app_id, GCMClient::Result result); | 
|  |  | 
|  | // Runs the Send callback. | 
|  | void SendFinished(const std::string& app_id, | 
|  | const std::string& message_id, | 
|  | GCMClient::Result result); | 
|  |  | 
|  | bool HasRegisterCallback(const std::string& app_id); | 
|  |  | 
|  | void ClearCallbacks(); | 
|  |  | 
|  | // Dispatches the OnMessage event to the app handler associated with |app_id|. | 
|  | // If |message| has been encrypted, it will be decrypted asynchronously and | 
|  | // dispatched when the decryption operation was successful. Otherwise, the | 
|  | // |message| will be dispatched immediately to the handler for |app_id|. | 
|  | void DispatchMessage(const std::string& app_id, | 
|  | const IncomingMessage& message); | 
|  |  | 
|  | private: | 
|  | // Common code shared by Unregister and UnregisterWithSenderId. | 
|  | void UnregisterInternal(const std::string& app_id, | 
|  | const std::string* sender_id, | 
|  | const UnregisterCallback& callback); | 
|  |  | 
|  | // Dispatches the OnMessage event to the app handler associated with |app_id| | 
|  | // if |result| indicates that it is safe to do so, or will report a decryption | 
|  | // failure for the |app_id| otherwise. | 
|  | void DispatchMessageInternal(const std::string& app_id, | 
|  | GCMEncryptionProvider::DecryptionResult result, | 
|  | const IncomingMessage& message); | 
|  |  | 
|  | // Called after unregistration completes in order to trigger the pending | 
|  | // registration. | 
|  | void RegisterAfterUnregister( | 
|  | const std::string& app_id, | 
|  | const std::vector<std::string>& normalized_sender_ids, | 
|  | const UnregisterCallback& unregister_callback, | 
|  | GCMClient::Result result); | 
|  |  | 
|  | // Callback map (from app_id to callback) for Register. | 
|  | std::map<std::string, RegisterCallback> register_callbacks_; | 
|  |  | 
|  | // Callback map (from app_id to callback) for Unregister. | 
|  | std::map<std::string, UnregisterCallback> unregister_callbacks_; | 
|  |  | 
|  | // Callback map (from <app_id, message_id> to callback) for Send. | 
|  | std::map<std::pair<std::string, std::string>, SendCallback> send_callbacks_; | 
|  |  | 
|  | // The encryption provider, used for key management and decryption of | 
|  | // encrypted, incoming messages. | 
|  | GCMEncryptionProvider encryption_provider_; | 
|  |  | 
|  | // App handler map (from app_id to handler pointer). The handler is not owned. | 
|  | GCMAppHandlerMap app_handlers_; | 
|  |  | 
|  | base::WeakPtrFactory<GCMDriver> weak_ptr_factory_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(GCMDriver); | 
|  | }; | 
|  |  | 
|  | }  // namespace gcm | 
|  |  | 
|  | #endif  // COMPONENTS_GCM_DRIVER_GCM_DRIVER_H_ |