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