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 29 class GURL; 30 31 namespace base { 32 class Clock; 33 class Time; 34 } // namespace base 35 36 namespace mcs_proto { 37 class DataMessageStanza; 38 } // namespace mcs_proto 39 40 namespace net { 41 class HttpNetworkSession; 42 } // namespace net 43 44 namespace gcm { 45 46 class CheckinRequest; 47 class ConnectionFactory; 48 class GCMClientImplTest; 49 50 // Helper class for building GCM internals. Allows tests to inject fake versions 51 // as necessary. 52 class 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. 76 class 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