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_CLIENT_IMPL_H_ 6#define COMPONENTS_GCM_DRIVER_GCM_CLIENT_IMPL_H_ 7 8#include <map> 9#include <string> 10#include <vector> 11 12#include "base/compiler_specific.h" 13#include "base/memory/ref_counted.h" 14#include "base/memory/weak_ptr.h" 15#include "base/stl_util.h" 16#include "components/gcm_driver/gcm_client.h" 17#include "components/gcm_driver/gcm_stats_recorder_impl.h" 18#include "google_apis/gcm/base/mcs_message.h" 19#include "google_apis/gcm/engine/gcm_store.h" 20#include "google_apis/gcm/engine/gservices_settings.h" 21#include "google_apis/gcm/engine/mcs_client.h" 22#include "google_apis/gcm/engine/registration_request.h" 23#include "google_apis/gcm/engine/unregistration_request.h" 24#include "google_apis/gcm/protocol/android_checkin.pb.h" 25#include "google_apis/gcm/protocol/checkin.pb.h" 26#include "net/base/net_log.h" 27#include "net/url_request/url_request_context_getter.h" 28 29class GURL; 30 31namespace base { 32class Clock; 33class Time; 34} // namespace base 35 36namespace mcs_proto { 37class DataMessageStanza; 38} // namespace mcs_proto 39 40namespace net { 41class HttpNetworkSession; 42} // namespace net 43 44namespace gcm { 45 46class CheckinRequest; 47class ConnectionFactory; 48class GCMClientImplTest; 49 50// Helper class for building GCM internals. Allows tests to inject fake versions 51// as necessary. 52class GCMInternalsBuilder { 53 public: 54 GCMInternalsBuilder(); 55 virtual ~GCMInternalsBuilder(); 56 57 virtual scoped_ptr<base::Clock> BuildClock(); 58 virtual scoped_ptr<MCSClient> BuildMCSClient( 59 const std::string& version, 60 base::Clock* clock, 61 ConnectionFactory* connection_factory, 62 GCMStore* gcm_store, 63 GCMStatsRecorder* recorder); 64 virtual scoped_ptr<ConnectionFactory> BuildConnectionFactory( 65 const std::vector<GURL>& endpoints, 66 const net::BackoffEntry::Policy& backoff_policy, 67 scoped_refptr<net::HttpNetworkSession> network_session, 68 net::NetLog* net_log, 69 GCMStatsRecorder* recorder); 70}; 71 72// Implements the GCM Client. It is used to coordinate MCS Client (communication 73// with MCS) and other pieces of GCM infrastructure like Registration and 74// Checkins. It also allows for registering user delegates that host 75// applications that send and receive messages. 76class GCMClientImpl 77 : public GCMClient, public GCMStatsRecorder::Delegate, 78 public ConnectionFactory::ConnectionListener { 79 public: 80 explicit GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder); 81 virtual ~GCMClientImpl(); 82 83 // GCMClient implementation. 84 virtual void Initialize( 85 const ChromeBuildInfo& chrome_build_info, 86 const base::FilePath& store_path, 87 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner, 88 const scoped_refptr<net::URLRequestContextGetter>& 89 url_request_context_getter, 90 scoped_ptr<Encryptor> encryptor, 91 GCMClient::Delegate* delegate) OVERRIDE; 92 virtual void Start() OVERRIDE; 93 virtual void Stop() OVERRIDE; 94 virtual void CheckOut() OVERRIDE; 95 virtual void Register(const std::string& app_id, 96 const std::vector<std::string>& sender_ids) OVERRIDE; 97 virtual void Unregister(const std::string& app_id) OVERRIDE; 98 virtual void Send(const std::string& app_id, 99 const std::string& receiver_id, 100 const OutgoingMessage& message) OVERRIDE; 101 virtual void SetRecording(bool recording) OVERRIDE; 102 virtual void ClearActivityLogs() OVERRIDE; 103 virtual GCMStatistics GetStatistics() const OVERRIDE; 104 105 // GCMStatsRecorder::Delegate implemenation. 106 virtual void OnActivityRecorded() OVERRIDE; 107 108 // ConnectionFactory::ConnectionListener implementation. 109 virtual void OnConnected(const GURL& current_server, 110 const net::IPEndPoint& ip_endpoint) OVERRIDE; 111 virtual void OnDisconnected() OVERRIDE; 112 113 private: 114 // State representation of the GCMClient. 115 // Any change made to this enum should have corresponding change in the 116 // GetStateString(...) function. 117 enum State { 118 // Uninitialized. 119 UNINITIALIZED, 120 // Initialized, 121 INITIALIZED, 122 // GCM store loading is in progress. 123 LOADING, 124 // Initial device checkin is in progress. 125 INITIAL_DEVICE_CHECKIN, 126 // Ready to accept requests. 127 READY, 128 }; 129 130 // The check-in info for the user. Returned by the server. 131 struct CheckinInfo { 132 CheckinInfo() : android_id(0), secret(0) {} 133 bool IsValid() const { return android_id != 0 && secret != 0; } 134 void Reset() { 135 android_id = 0; 136 secret = 0; 137 } 138 139 uint64 android_id; 140 uint64 secret; 141 }; 142 143 // Collection of pending registration requests. Keys are app IDs, while values 144 // are pending registration requests to obtain a registration ID for 145 // requesting application. 146 typedef std::map<std::string, RegistrationRequest*> 147 PendingRegistrationRequests; 148 149 // Collection of pending unregistration requests. Keys are app IDs, while 150 // values are pending unregistration requests to disable the registration ID 151 // currently assigned to the application. 152 typedef std::map<std::string, UnregistrationRequest*> 153 PendingUnregistrationRequests; 154 155 friend class GCMClientImplTest; 156 157 // Returns text representation of the enum State. 158 std::string GetStateString() const; 159 160 // Callbacks for the MCSClient. 161 // Receives messages and dispatches them to relevant user delegates. 162 void OnMessageReceivedFromMCS(const gcm::MCSMessage& message); 163 // Receives confirmation of sent messages or information about errors. 164 void OnMessageSentToMCS(int64 user_serial_number, 165 const std::string& app_id, 166 const std::string& message_id, 167 MCSClient::MessageSendStatus status); 168 // Receives information about mcs_client_ errors. 169 void OnMCSError(); 170 171 // Runs after GCM Store load is done to trigger continuation of the 172 // initialization. 173 void OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result); 174 // Initializes mcs_client_, which handles the connection to MCS. 175 void InitializeMCSClient(scoped_ptr<GCMStore::LoadResult> result); 176 // Complets the first time device checkin. 177 void OnFirstTimeDeviceCheckinCompleted(const CheckinInfo& checkin_info); 178 // Starts a login on mcs_client_. 179 void StartMCSLogin(); 180 // Resets state to before initialization. 181 void ResetState(); 182 // Sets state to ready. This will initiate the MCS login and notify the 183 // delegates. 184 void OnReady(); 185 186 // Starts a first time device checkin. 187 void StartCheckin(); 188 // Completes the device checkin request by parsing the |checkin_response|. 189 // Function also cleans up the pending checkin. 190 void OnCheckinCompleted( 191 const checkin_proto::AndroidCheckinResponse& checkin_response); 192 193 // Callback passed to GCMStore::SetGServicesSettings. 194 void SetGServicesSettingsCallback(bool success); 195 196 // Schedules next periodic device checkin and makes sure there is at most one 197 // pending checkin at a time. This function is meant to be called after a 198 // successful checkin. 199 void SchedulePeriodicCheckin(); 200 // Gets the time until next checkin. 201 base::TimeDelta GetTimeToNextCheckin() const; 202 // Callback for setting last checkin time in the |gcm_store_|. 203 void SetLastCheckinTimeCallback(bool success); 204 205 // Callback for persisting device credentials in the |gcm_store_|. 206 void SetDeviceCredentialsCallback(bool success); 207 208 // Callback for persisting registration info in the |gcm_store_|. 209 void UpdateRegistrationCallback(bool success); 210 211 // Completes the registration request. 212 void OnRegisterCompleted(const std::string& app_id, 213 const std::vector<std::string>& sender_ids, 214 RegistrationRequest::Status status, 215 const std::string& registration_id); 216 217 // Completes the unregistration request. 218 void OnUnregisterCompleted(const std::string& app_id, 219 UnregistrationRequest::Status status); 220 221 // Completes the GCM store destroy request. 222 void OnGCMStoreDestroyed(bool success); 223 224 // Handles incoming data message and dispatches it the delegate of this class. 225 void HandleIncomingMessage(const gcm::MCSMessage& message); 226 227 // Fires OnMessageReceived event on the delegate of this class, based on the 228 // details in |data_message_stanza| and |message_data|. 229 void HandleIncomingDataMessage( 230 const mcs_proto::DataMessageStanza& data_message_stanza, 231 MessageData& message_data); 232 233 // Fires OnMessageSendError event on the delegate of this calss, based on the 234 // details in |data_message_stanza| and |message_data|. 235 void HandleIncomingSendError( 236 const mcs_proto::DataMessageStanza& data_message_stanza, 237 MessageData& message_data); 238 239 // Builder for the GCM internals (mcs client, etc.). 240 scoped_ptr<GCMInternalsBuilder> internals_builder_; 241 242 // Recorder that logs GCM activities. 243 GCMStatsRecorderImpl recorder_; 244 245 // State of the GCM Client Implementation. 246 State state_; 247 248 GCMClient::Delegate* delegate_; 249 250 // Device checkin info (android ID and security token used by device). 251 CheckinInfo device_checkin_info_; 252 253 // Clock used for timing of retry logic. Passed in for testing. Owned by 254 // GCMClientImpl. 255 scoped_ptr<base::Clock> clock_; 256 257 // Information about the chrome build. 258 // TODO(fgorski): Check if it can be passed in constructor and made const. 259 ChromeBuildInfo chrome_build_info_; 260 261 // Persistent data store for keeping device credentials, messages and user to 262 // serial number mappings. 263 scoped_ptr<GCMStore> gcm_store_; 264 265 scoped_refptr<net::HttpNetworkSession> network_session_; 266 net::BoundNetLog net_log_; 267 scoped_ptr<ConnectionFactory> connection_factory_; 268 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; 269 270 // Controls receiving and sending of packets and reliable message queueing. 271 scoped_ptr<MCSClient> mcs_client_; 272 273 scoped_ptr<CheckinRequest> checkin_request_; 274 275 // Cached registration info. 276 RegistrationInfoMap registrations_; 277 278 // Currently pending registration requests. GCMClientImpl owns the 279 // RegistrationRequests. 280 PendingRegistrationRequests pending_registration_requests_; 281 STLValueDeleter<PendingRegistrationRequests> 282 pending_registration_requests_deleter_; 283 284 // Currently pending unregistration requests. GCMClientImpl owns the 285 // UnregistrationRequests. 286 PendingUnregistrationRequests pending_unregistration_requests_; 287 STLValueDeleter<PendingUnregistrationRequests> 288 pending_unregistration_requests_deleter_; 289 290 // G-services settings that were provided by MCS. 291 GServicesSettings gservices_settings_; 292 293 // Time of the last successful checkin. 294 base::Time last_checkin_time_; 295 296 // Factory for creating references when scheduling periodic checkin. 297 base::WeakPtrFactory<GCMClientImpl> periodic_checkin_ptr_factory_; 298 299 // Factory for creating references in callbacks. 300 base::WeakPtrFactory<GCMClientImpl> weak_ptr_factory_; 301 302 DISALLOW_COPY_AND_ASSIGN(GCMClientImpl); 303}; 304 305} // namespace gcm 306 307#endif // COMPONENTS_GCM_DRIVER_GCM_CLIENT_IMPL_H_ 308