blob: 0bdb150a2a65b17ea87335d321c5f239dc56f588 [file] [log] [blame]
// 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.
#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;
enum class GCMDecryptionResult;
struct AccountMapping;
// Provides the InstanceID support via GCMDriver.
class InstanceIDHandler {
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)>;
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;
// Bridge between GCM users in Chrome and the platform-specific implementation.
class GCMDriver {
// 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 {
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;
// 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,
GCMDecryptionResult 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);
// 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,
GCMDecryptionResult 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_;
} // namespace gcm