blob: 120f9367a3187e7fb0fa439578442d93e4cf7417 [file] [log] [blame]
[email protected]cd57f372014-06-09 17:13:061// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]e4097c82013-11-08 00:16:122// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]cd57f372014-06-09 17:13:065#ifndef COMPONENTS_GCM_DRIVER_GCM_CLIENT_IMPL_H_
6#define COMPONENTS_GCM_DRIVER_GCM_CLIENT_IMPL_H_
[email protected]e4097c82013-11-08 00:16:127
avi26062922015-12-26 00:14:188#include <stdint.h>
9
[email protected]b83122a92014-01-22 21:29:2910#include <map>
[email protected]7df5ef22014-07-17 07:35:5811#include <set>
[email protected]b83122a92014-01-22 21:29:2912#include <string>
jianli7a0c9b62015-05-26 23:24:4713#include <utility>
[email protected]848b1b62014-01-30 23:51:0414#include <vector>
[email protected]b83122a92014-01-22 21:29:2915
[email protected]e4097c82013-11-08 00:16:1216#include "base/compiler_specific.h"
avi26062922015-12-26 00:14:1817#include "base/macros.h"
[email protected]79994f42014-01-16 16:05:3618#include "base/memory/ref_counted.h"
mgiucaf59c7a82015-06-25 09:11:5719#include "base/memory/scoped_ptr.h"
[email protected]955e0ff2014-01-31 20:42:1220#include "base/memory/weak_ptr.h"
[email protected]cd57f372014-06-09 17:13:0621#include "components/gcm_driver/gcm_client.h"
22#include "components/gcm_driver/gcm_stats_recorder_impl.h"
[email protected]b83122a92014-01-22 21:29:2923#include "google_apis/gcm/base/mcs_message.h"
24#include "google_apis/gcm/engine/gcm_store.h"
[email protected]06e45272014-05-06 03:41:3425#include "google_apis/gcm/engine/gservices_settings.h"
[email protected]b83122a92014-01-22 21:29:2926#include "google_apis/gcm/engine/mcs_client.h"
[email protected]b4dd0232014-02-08 02:37:3127#include "google_apis/gcm/engine/registration_request.h"
[email protected]0e88e1d12014-03-19 06:53:0828#include "google_apis/gcm/engine/unregistration_request.h"
[email protected]436bcb82014-04-18 00:40:5729#include "google_apis/gcm/protocol/android_checkin.pb.h"
[email protected]2c4d4cd2014-04-10 21:10:2230#include "google_apis/gcm/protocol/checkin.pb.h"
[email protected]b83122a92014-01-22 21:29:2931#include "net/url_request/url_request_context_getter.h"
[email protected]e4097c82013-11-08 00:16:1232
[email protected]2bbe0a682014-03-26 00:08:3133class GURL;
34
[email protected]79994f42014-01-16 16:05:3635namespace base {
[email protected]955e0ff2014-01-31 20:42:1236class Clock;
[email protected]764c0442014-05-01 04:30:5537class Time;
[email protected]79994f42014-01-16 16:05:3638} // namespace base
39
[email protected]436bcb82014-04-18 00:40:5740namespace mcs_proto {
41class DataMessageStanza;
42} // namespace mcs_proto
43
[email protected]b83122a92014-01-22 21:29:2944namespace net {
45class HttpNetworkSession;
[email protected]955e0ff2014-01-31 20:42:1246} // namespace net
[email protected]b83122a92014-01-22 21:29:2947
[email protected]e4097c82013-11-08 00:16:1248namespace gcm {
49
[email protected]b83122a92014-01-22 21:29:2950class CheckinRequest;
51class ConnectionFactory;
52class GCMClientImplTest;
[email protected]79994f42014-01-16 16:05:3653
[email protected]2bbe0a682014-03-26 00:08:3154// Helper class for building GCM internals. Allows tests to inject fake versions
55// as necessary.
[email protected]cd57f372014-06-09 17:13:0656class GCMInternalsBuilder {
[email protected]2bbe0a682014-03-26 00:08:3157 public:
58 GCMInternalsBuilder();
59 virtual ~GCMInternalsBuilder();
60
61 virtual scoped_ptr<base::Clock> BuildClock();
62 virtual scoped_ptr<MCSClient> BuildMCSClient(
63 const std::string& version,
64 base::Clock* clock,
65 ConnectionFactory* connection_factory,
[email protected]436bcb82014-04-18 00:40:5766 GCMStore* gcm_store,
67 GCMStatsRecorder* recorder);
[email protected]2bbe0a682014-03-26 00:08:3168 virtual scoped_ptr<ConnectionFactory> BuildConnectionFactory(
69 const std::vector<GURL>& endpoints,
70 const net::BackoffEntry::Policy& backoff_policy,
mmenkee65e7af2015-10-13 17:16:4271 net::HttpNetworkSession* gcm_network_session,
72 net::HttpNetworkSession* http_network_session,
[email protected]9df5b932014-04-30 00:39:0673 GCMStatsRecorder* recorder);
[email protected]2bbe0a682014-03-26 00:08:3174};
75
[email protected]b83122a92014-01-22 21:29:2976// Implements the GCM Client. It is used to coordinate MCS Client (communication
77// with MCS) and other pieces of GCM infrastructure like Registration and
78// Checkins. It also allows for registering user delegates that host
79// applications that send and receive messages.
[email protected]cd57f372014-06-09 17:13:0680class GCMClientImpl
[email protected]c31e1b52014-06-12 21:00:4781 : public GCMClient, public GCMStatsRecorder::Delegate,
82 public ConnectionFactory::ConnectionListener {
[email protected]e4097c82013-11-08 00:16:1283 public:
jianlif3e52af42015-01-21 23:18:4784 // State representation of the GCMClient.
85 // Any change made to this enum should have corresponding change in the
86 // GetStateString(...) function.
87 enum State {
88 // Uninitialized.
89 UNINITIALIZED,
90 // Initialized,
91 INITIALIZED,
92 // GCM store loading is in progress.
93 LOADING,
94 // GCM store is loaded.
95 LOADED,
96 // Initial device checkin is in progress.
97 INITIAL_DEVICE_CHECKIN,
98 // Ready to accept requests.
99 READY,
100 };
101
[email protected]2bbe0a682014-03-26 00:08:31102 explicit GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder);
dcheng00ea022b2014-10-21 11:24:56103 ~GCMClientImpl() override;
[email protected]e4097c82013-11-08 00:16:12104
[email protected]c31e1b52014-06-12 21:00:47105 // GCMClient implementation.
dcheng00ea022b2014-10-21 11:24:56106 void Initialize(
[email protected]8ad80512014-05-23 09:40:47107 const ChromeBuildInfo& chrome_build_info,
[email protected]e2a4a8012014-02-07 22:32:52108 const base::FilePath& store_path,
109 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner,
110 const scoped_refptr<net::URLRequestContextGetter>&
[email protected]5799d052014-02-12 20:47:39111 url_request_context_getter,
[email protected]446f73c22014-05-14 20:47:18112 scoped_ptr<Encryptor> encryptor,
mostynbfe59f482014-10-06 15:04:46113 GCMClient::Delegate* delegate) override;
jianlif3e52af42015-01-21 23:18:47114 void Start(StartMode start_mode) override;
dcheng00ea022b2014-10-21 11:24:56115 void Stop() override;
jianli7a0c9b62015-05-26 23:24:47116 void Register(const linked_ptr<RegistrationInfo>& registration_info) override;
117 void Unregister(
118 const linked_ptr<RegistrationInfo>& registration_info) override;
dcheng00ea022b2014-10-21 11:24:56119 void Send(const std::string& app_id,
120 const std::string& receiver_id,
121 const OutgoingMessage& message) override;
122 void SetRecording(bool recording) override;
123 void ClearActivityLogs() override;
124 GCMStatistics GetStatistics() const override;
125 void SetAccountTokens(
mostynbfe59f482014-10-06 15:04:46126 const std::vector<AccountTokenInfo>& account_tokens) override;
dcheng00ea022b2014-10-21 11:24:56127 void UpdateAccountMapping(const AccountMapping& account_mapping) override;
128 void RemoveAccountMapping(const std::string& account_id) override;
fgorski5df101702014-10-28 02:09:31129 void SetLastTokenFetchTime(const base::Time& time) override;
chirantan192a9212014-12-06 03:30:45130 void UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) override;
jianli10018b2d2015-05-11 21:14:13131 void AddInstanceIDData(const std::string& app_id,
jianli7a0c9b62015-05-26 23:24:47132 const std::string& instance_id,
133 const std::string& extra_data) override;
jianli10018b2d2015-05-11 21:14:13134 void RemoveInstanceIDData(const std::string& app_id) override;
jianli7a0c9b62015-05-26 23:24:47135 void GetInstanceIDData(const std::string& app_id,
136 std::string* instance_id,
137 std::string* extra_data) override;
fgorski22754462015-05-14 00:05:22138 void AddHeartbeatInterval(const std::string& scope, int interval_ms) override;
139 void RemoveHeartbeatInterval(const std::string& scope) override;
[email protected]c31e1b52014-06-12 21:00:47140
141 // GCMStatsRecorder::Delegate implemenation.
dcheng00ea022b2014-10-21 11:24:56142 void OnActivityRecorded() override;
[email protected]e4097c82013-11-08 00:16:12143
[email protected]c31e1b52014-06-12 21:00:47144 // ConnectionFactory::ConnectionListener implementation.
dcheng00ea022b2014-10-21 11:24:56145 void OnConnected(const GURL& current_server,
146 const net::IPEndPoint& ip_endpoint) override;
147 void OnDisconnected() override;
[email protected]c31e1b52014-06-12 21:00:47148
[email protected]e4097c82013-11-08 00:16:12149 private:
[email protected]7df5ef22014-07-17 07:35:58150 // The check-in info for the device.
151 // TODO(fgorski): Convert to a class with explicit getters/setters.
[email protected]cd57f372014-06-09 17:13:06152 struct CheckinInfo {
[email protected]7df5ef22014-07-17 07:35:58153 CheckinInfo();
154 ~CheckinInfo();
[email protected]5799d052014-02-12 20:47:39155 bool IsValid() const { return android_id != 0 && secret != 0; }
[email protected]7df5ef22014-07-17 07:35:58156 void SnapshotCheckinAccounts();
157 void Reset();
[email protected]b83122a92014-01-22 21:29:29158
[email protected]7df5ef22014-07-17 07:35:58159 // Android ID of the device as assigned by the server.
avi26062922015-12-26 00:14:18160 uint64_t android_id;
[email protected]7df5ef22014-07-17 07:35:58161 // Security token of the device as assigned by the server.
avi26062922015-12-26 00:14:18162 uint64_t secret;
[email protected]7df5ef22014-07-17 07:35:58163 // True if accounts were already provided through SetAccountsForCheckin(),
164 // or when |last_checkin_accounts| was loaded as empty.
165 bool accounts_set;
166 // Map of account email addresses and OAuth2 tokens that will be sent to the
167 // checkin server on a next checkin.
168 std::map<std::string, std::string> account_tokens;
169 // As set of accounts last checkin was completed with.
170 std::set<std::string> last_checkin_accounts;
[email protected]848b1b62014-01-30 23:51:04171 };
172
jianli7a0c9b62015-05-26 23:24:47173 // Collection of pending registration requests. Keys are RegistrationInfo
174 // instance, while values are pending registration requests to obtain a
175 // registration ID for requesting application.
limasdf20c5d7a2015-12-01 01:16:19176 using PendingRegistrationRequests = std::map<linked_ptr<RegistrationInfo>,
177 scoped_ptr<RegistrationRequest>,
178 RegistrationInfoComparer>;
[email protected]848b1b62014-01-30 23:51:04179
jianli7a0c9b62015-05-26 23:24:47180 // Collection of pending unregistration requests. Keys are RegistrationInfo
181 // instance, while values are pending unregistration requests to disable the
182 // registration ID currently assigned to the application.
limasdf20c5d7a2015-12-01 01:16:19183 using PendingUnregistrationRequests =
184 std::map<linked_ptr<RegistrationInfo>,
185 scoped_ptr<UnregistrationRequest>,
186 RegistrationInfoComparer>;
[email protected]e4007042014-02-15 20:34:28187
[email protected]b83122a92014-01-22 21:29:29188 friend class GCMClientImplTest;
jianlic02d25e2015-05-27 22:24:31189 friend class GCMClientInstanceIDTest;
[email protected]b83122a92014-01-22 21:29:29190
[email protected]35601812014-03-07 19:52:43191 // Returns text representation of the enum State.
192 std::string GetStateString() const;
193
[email protected]b83122a92014-01-22 21:29:29194 // Callbacks for the MCSClient.
195 // Receives messages and dispatches them to relevant user delegates.
196 void OnMessageReceivedFromMCS(const gcm::MCSMessage& message);
197 // Receives confirmation of sent messages or information about errors.
avi26062922015-12-26 00:14:18198 void OnMessageSentToMCS(int64_t user_serial_number,
[email protected]b83122a92014-01-22 21:29:29199 const std::string& app_id,
200 const std::string& message_id,
201 MCSClient::MessageSendStatus status);
202 // Receives information about mcs_client_ errors.
203 void OnMCSError();
204
205 // Runs after GCM Store load is done to trigger continuation of the
206 // initialization.
[email protected]2809af72014-01-25 09:23:57207 void OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result);
jianlif3e52af42015-01-21 23:18:47208 // Starts the GCM.
209 void StartGCM();
[email protected]b83122a92014-01-22 21:29:29210 // Initializes mcs_client_, which handles the connection to MCS.
jianlif3e52af42015-01-21 23:18:47211 void InitializeMCSClient();
[email protected]b83122a92014-01-22 21:29:29212 // Complets the first time device checkin.
213 void OnFirstTimeDeviceCheckinCompleted(const CheckinInfo& checkin_info);
214 // Starts a login on mcs_client_.
215 void StartMCSLogin();
jianli00b4600f2015-02-10 23:32:49216 // Resets the GCM store when it is corrupted.
217 void ResetStore();
[email protected]86625df2014-01-31 03:47:58218 // Sets state to ready. This will initiate the MCS login and notify the
219 // delegates.
fgorski5df101702014-10-28 02:09:31220 void OnReady(const std::vector<AccountMapping>& account_mappings,
221 const base::Time& last_token_fetch_time);
[email protected]b83122a92014-01-22 21:29:29222
[email protected]5799d052014-02-12 20:47:39223 // Starts a first time device checkin.
[email protected]25b5f50e2014-04-03 08:27:23224 void StartCheckin();
[email protected]2c4d4cd2014-04-10 21:10:22225 // Completes the device checkin request by parsing the |checkin_response|.
226 // Function also cleans up the pending checkin.
227 void OnCheckinCompleted(
228 const checkin_proto::AndroidCheckinResponse& checkin_response);
[email protected]06e45272014-05-06 03:41:34229
230 // Callback passed to GCMStore::SetGServicesSettings.
231 void SetGServicesSettingsCallback(bool success);
232
[email protected]764c0442014-05-01 04:30:55233 // Schedules next periodic device checkin and makes sure there is at most one
234 // pending checkin at a time. This function is meant to be called after a
235 // successful checkin.
236 void SchedulePeriodicCheckin();
237 // Gets the time until next checkin.
238 base::TimeDelta GetTimeToNextCheckin() const;
[email protected]7df5ef22014-07-17 07:35:58239 // Callback for setting last checkin information in the |gcm_store_|.
240 void SetLastCheckinInfoCallback(bool success);
[email protected]b83122a92014-01-22 21:29:29241
242 // Callback for persisting device credentials in the |gcm_store_|.
243 void SetDeviceCredentialsCallback(bool success);
244
[email protected]3a20a4d2014-03-21 22:54:21245 // Callback for persisting registration info in the |gcm_store_|.
246 void UpdateRegistrationCallback(bool success);
247
[email protected]72d4f252014-08-20 22:34:28248 // Callback for all store operations that do not try to recover, if write in
249 // |gcm_store_| fails.
250 void DefaultStoreCallback(bool success);
251
fgorski9a405102014-11-19 01:25:16252 // Callback for store operation where result does not matter.
253 void IgnoreWriteResultCallback(bool success);
254
jianli78b56042015-06-17 01:21:22255 // Callback for destroying the GCM store.
256 void DestroyStoreCallback(bool success);
257
258 // Callback for resetting the GCM store. The store will be reloaded.
jianli00b4600f2015-02-10 23:32:49259 void ResetStoreCallback(bool success);
260
[email protected]848b1b62014-01-30 23:51:04261 // Completes the registration request.
jianli7a0c9b62015-05-26 23:24:47262 void OnRegisterCompleted(
263 const linked_ptr<RegistrationInfo>& registration_info,
264 RegistrationRequest::Status status,
265 const std::string& registration_id);
[email protected]848b1b62014-01-30 23:51:04266
[email protected]e4007042014-02-15 20:34:28267 // Completes the unregistration request.
jianli7a0c9b62015-05-26 23:24:47268 void OnUnregisterCompleted(
269 const linked_ptr<RegistrationInfo>& registration_info,
270 UnregistrationRequest::Status status);
[email protected]e4007042014-02-15 20:34:28271
[email protected]d3a4b2e2014-02-27 13:46:54272 // Completes the GCM store destroy request.
273 void OnGCMStoreDestroyed(bool success);
274
[email protected]c6fe36b2014-03-11 10:58:12275 // Handles incoming data message and dispatches it the delegate of this class.
[email protected]b83122a92014-01-22 21:29:29276 void HandleIncomingMessage(const gcm::MCSMessage& message);
277
[email protected]c6fe36b2014-03-11 10:58:12278 // Fires OnMessageReceived event on the delegate of this class, based on the
279 // details in |data_message_stanza| and |message_data|.
280 void HandleIncomingDataMessage(
281 const mcs_proto::DataMessageStanza& data_message_stanza,
282 MessageData& message_data);
283
284 // Fires OnMessageSendError event on the delegate of this calss, based on the
285 // details in |data_message_stanza| and |message_data|.
286 void HandleIncomingSendError(
287 const mcs_proto::DataMessageStanza& data_message_stanza,
288 MessageData& message_data);
[email protected]848b1b62014-01-30 23:51:04289
jianlif3e52af42015-01-21 23:18:47290 // Is there any standalone app being registered for GCM?
291 bool HasStandaloneRegisteredApp() const;
292
jianli78b56042015-06-17 01:21:22293 // Destroys the store when it is not needed.
294 void DestroyStoreWhenNotNeeded();
295
296 // Reset all cahced values.
297 void ResetCache();
298
[email protected]2bbe0a682014-03-26 00:08:31299 // Builder for the GCM internals (mcs client, etc.).
300 scoped_ptr<GCMInternalsBuilder> internals_builder_;
[email protected]b83122a92014-01-22 21:29:29301
[email protected]436bcb82014-04-18 00:40:57302 // Recorder that logs GCM activities.
[email protected]025adfa2014-06-03 21:51:12303 GCMStatsRecorderImpl recorder_;
[email protected]436bcb82014-04-18 00:40:57304
[email protected]b83122a92014-01-22 21:29:29305 // State of the GCM Client Implementation.
306 State state_;
307
[email protected]7de78802014-05-10 19:49:40308 GCMClient::Delegate* delegate_;
[email protected]5799d052014-02-12 20:47:39309
jianlif3e52af42015-01-21 23:18:47310 // Flag to indicate if the GCM should be delay started until it is actually
311 // used in either of the following cases:
312 // 1) The GCM store contains the registration records.
313 // 2) GCM functionailities are explicitly called.
314 StartMode start_mode_;
315
[email protected]b83122a92014-01-22 21:29:29316 // Device checkin info (android ID and security token used by device).
317 CheckinInfo device_checkin_info_;
318
[email protected]848b1b62014-01-30 23:51:04319 // Clock used for timing of retry logic. Passed in for testing. Owned by
320 // GCMClientImpl.
321 scoped_ptr<base::Clock> clock_;
[email protected]b83122a92014-01-22 21:29:29322
323 // Information about the chrome build.
324 // TODO(fgorski): Check if it can be passed in constructor and made const.
[email protected]8ad80512014-05-23 09:40:47325 ChromeBuildInfo chrome_build_info_;
[email protected]b83122a92014-01-22 21:29:29326
327 // Persistent data store for keeping device credentials, messages and user to
328 // serial number mappings.
[email protected]79994f42014-01-16 16:05:36329 scoped_ptr<GCMStore> gcm_store_;
[email protected]b83122a92014-01-22 21:29:29330
jianlif3e52af42015-01-21 23:18:47331 // Data loaded from the GCM store.
332 scoped_ptr<GCMStore::LoadResult> load_result_;
333
jianli00b4600f2015-02-10 23:32:49334 // Tracks if the GCM store has been reset. This is used to prevent from
335 // resetting and loading from the store again and again.
336 bool gcm_store_reset_;
337
mmenkee65e7af2015-10-13 17:16:42338 scoped_ptr<net::HttpNetworkSession> network_session_;
[email protected]b83122a92014-01-22 21:29:29339 scoped_ptr<ConnectionFactory> connection_factory_;
340 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
341
342 // Controls receiving and sending of packets and reliable message queueing.
mmenkee65e7af2015-10-13 17:16:42343 // Must be destroyed before |network_session_|.
[email protected]b83122a92014-01-22 21:29:29344 scoped_ptr<MCSClient> mcs_client_;
345
[email protected]5799d052014-02-12 20:47:39346 scoped_ptr<CheckinRequest> checkin_request_;
[email protected]b83122a92014-01-22 21:29:29347
[email protected]3a20a4d2014-03-21 22:54:21348 // Cached registration info.
349 RegistrationInfoMap registrations_;
[email protected]848b1b62014-01-30 23:51:04350
[email protected]3a20a4d2014-03-21 22:54:21351 // Currently pending registration requests. GCMClientImpl owns the
352 // RegistrationRequests.
353 PendingRegistrationRequests pending_registration_requests_;
[email protected]3a20a4d2014-03-21 22:54:21354
355 // Currently pending unregistration requests. GCMClientImpl owns the
[email protected]e4007042014-02-15 20:34:28356 // UnregistrationRequests.
[email protected]3a20a4d2014-03-21 22:54:21357 PendingUnregistrationRequests pending_unregistration_requests_;
[email protected]e4007042014-02-15 20:34:28358
[email protected]764c0442014-05-01 04:30:55359 // G-services settings that were provided by MCS.
[email protected]06e45272014-05-06 03:41:34360 GServicesSettings gservices_settings_;
[email protected]764c0442014-05-01 04:30:55361
362 // Time of the last successful checkin.
363 base::Time last_checkin_time_;
364
jianli7a0c9b62015-05-26 23:24:47365 // Cached instance ID data, key is app ID and value is pair of instance ID
366 // and extra data.
367 std::map<std::string, std::pair<std::string, std::string>> instance_id_data_;
jianli10018b2d2015-05-11 21:14:13368
[email protected]764c0442014-05-01 04:30:55369 // Factory for creating references when scheduling periodic checkin.
370 base::WeakPtrFactory<GCMClientImpl> periodic_checkin_ptr_factory_;
371
jianli78b56042015-06-17 01:21:22372 // Factory for wiping out GCM store.
373 base::WeakPtrFactory<GCMClientImpl> destroying_gcm_store_ptr_factory_;
374
[email protected]955e0ff2014-01-31 20:42:12375 // Factory for creating references in callbacks.
376 base::WeakPtrFactory<GCMClientImpl> weak_ptr_factory_;
377
[email protected]e4097c82013-11-08 00:16:12378 DISALLOW_COPY_AND_ASSIGN(GCMClientImpl);
379};
380
381} // namespace gcm
382
[email protected]cd57f372014-06-09 17:13:06383#endif // COMPONENTS_GCM_DRIVER_GCM_CLIENT_IMPL_H_