blob: a39ffddd16e7df3bf6897d6ecfbb432dc038eeb1 [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
[email protected]b83122a92014-01-22 21:29:298#include <map>
[email protected]7df5ef22014-07-17 07:35:589#include <set>
[email protected]b83122a92014-01-22 21:29:2910#include <string>
jianli7a0c9b62015-05-26 23:24:4711#include <utility>
[email protected]848b1b62014-01-30 23:51:0412#include <vector>
[email protected]b83122a92014-01-22 21:29:2913
[email protected]e4097c82013-11-08 00:16:1214#include "base/compiler_specific.h"
[email protected]79994f42014-01-16 16:05:3615#include "base/memory/ref_counted.h"
[email protected]955e0ff2014-01-31 20:42:1216#include "base/memory/weak_ptr.h"
[email protected]b83122a92014-01-22 21:29:2917#include "base/stl_util.h"
[email protected]cd57f372014-06-09 17:13:0618#include "components/gcm_driver/gcm_client.h"
19#include "components/gcm_driver/gcm_stats_recorder_impl.h"
[email protected]b83122a92014-01-22 21:29:2920#include "google_apis/gcm/base/mcs_message.h"
21#include "google_apis/gcm/engine/gcm_store.h"
[email protected]06e45272014-05-06 03:41:3422#include "google_apis/gcm/engine/gservices_settings.h"
[email protected]b83122a92014-01-22 21:29:2923#include "google_apis/gcm/engine/mcs_client.h"
[email protected]b4dd0232014-02-08 02:37:3124#include "google_apis/gcm/engine/registration_request.h"
[email protected]0e88e1d12014-03-19 06:53:0825#include "google_apis/gcm/engine/unregistration_request.h"
[email protected]436bcb82014-04-18 00:40:5726#include "google_apis/gcm/protocol/android_checkin.pb.h"
[email protected]2c4d4cd2014-04-10 21:10:2227#include "google_apis/gcm/protocol/checkin.pb.h"
eroman58e913a2015-04-02 17:23:3128#include "net/log/net_log.h"
[email protected]b83122a92014-01-22 21:29:2929#include "net/url_request/url_request_context_getter.h"
[email protected]e4097c82013-11-08 00:16:1230
[email protected]2bbe0a682014-03-26 00:08:3131class GURL;
32
[email protected]79994f42014-01-16 16:05:3633namespace base {
[email protected]955e0ff2014-01-31 20:42:1234class Clock;
[email protected]764c0442014-05-01 04:30:5535class Time;
[email protected]79994f42014-01-16 16:05:3636} // namespace base
37
[email protected]436bcb82014-04-18 00:40:5738namespace mcs_proto {
39class DataMessageStanza;
40} // namespace mcs_proto
41
[email protected]b83122a92014-01-22 21:29:2942namespace net {
43class HttpNetworkSession;
[email protected]955e0ff2014-01-31 20:42:1244} // namespace net
[email protected]b83122a92014-01-22 21:29:2945
[email protected]e4097c82013-11-08 00:16:1246namespace gcm {
47
[email protected]b83122a92014-01-22 21:29:2948class CheckinRequest;
49class ConnectionFactory;
50class GCMClientImplTest;
[email protected]79994f42014-01-16 16:05:3651
[email protected]2bbe0a682014-03-26 00:08:3152// Helper class for building GCM internals. Allows tests to inject fake versions
53// as necessary.
[email protected]cd57f372014-06-09 17:13:0654class GCMInternalsBuilder {
[email protected]2bbe0a682014-03-26 00:08:3155 public:
56 GCMInternalsBuilder();
57 virtual ~GCMInternalsBuilder();
58
59 virtual scoped_ptr<base::Clock> BuildClock();
60 virtual scoped_ptr<MCSClient> BuildMCSClient(
61 const std::string& version,
62 base::Clock* clock,
63 ConnectionFactory* connection_factory,
[email protected]436bcb82014-04-18 00:40:5764 GCMStore* gcm_store,
65 GCMStatsRecorder* recorder);
[email protected]2bbe0a682014-03-26 00:08:3166 virtual scoped_ptr<ConnectionFactory> BuildConnectionFactory(
67 const std::vector<GURL>& endpoints,
68 const net::BackoffEntry::Policy& backoff_policy,
[email protected]6f63606a2014-07-18 02:18:5569 const scoped_refptr<net::HttpNetworkSession>& gcm_network_session,
70 const scoped_refptr<net::HttpNetworkSession>& http_network_session,
[email protected]9df5b932014-04-30 00:39:0671 net::NetLog* net_log,
72 GCMStatsRecorder* recorder);
[email protected]2bbe0a682014-03-26 00:08:3173};
74
[email protected]b83122a92014-01-22 21:29:2975// Implements the GCM Client. It is used to coordinate MCS Client (communication
76// with MCS) and other pieces of GCM infrastructure like Registration and
77// Checkins. It also allows for registering user delegates that host
78// applications that send and receive messages.
[email protected]cd57f372014-06-09 17:13:0679class GCMClientImpl
[email protected]c31e1b52014-06-12 21:00:4780 : public GCMClient, public GCMStatsRecorder::Delegate,
81 public ConnectionFactory::ConnectionListener {
[email protected]e4097c82013-11-08 00:16:1282 public:
jianlif3e52af42015-01-21 23:18:4783 // State representation of the GCMClient.
84 // Any change made to this enum should have corresponding change in the
85 // GetStateString(...) function.
86 enum State {
87 // Uninitialized.
88 UNINITIALIZED,
89 // Initialized,
90 INITIALIZED,
91 // GCM store loading is in progress.
92 LOADING,
93 // GCM store is loaded.
94 LOADED,
95 // Initial device checkin is in progress.
96 INITIAL_DEVICE_CHECKIN,
97 // Ready to accept requests.
98 READY,
99 };
100
[email protected]2bbe0a682014-03-26 00:08:31101 explicit GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder);
dcheng00ea022b2014-10-21 11:24:56102 ~GCMClientImpl() override;
[email protected]e4097c82013-11-08 00:16:12103
[email protected]c31e1b52014-06-12 21:00:47104 // GCMClient implementation.
dcheng00ea022b2014-10-21 11:24:56105 void Initialize(
[email protected]8ad80512014-05-23 09:40:47106 const ChromeBuildInfo& chrome_build_info,
[email protected]e2a4a8012014-02-07 22:32:52107 const base::FilePath& store_path,
108 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner,
109 const scoped_refptr<net::URLRequestContextGetter>&
[email protected]5799d052014-02-12 20:47:39110 url_request_context_getter,
[email protected]446f73c22014-05-14 20:47:18111 scoped_ptr<Encryptor> encryptor,
mostynbfe59f482014-10-06 15:04:46112 GCMClient::Delegate* delegate) override;
jianlif3e52af42015-01-21 23:18:47113 void Start(StartMode start_mode) override;
dcheng00ea022b2014-10-21 11:24:56114 void Stop() override;
jianli7a0c9b62015-05-26 23:24:47115 void Register(const linked_ptr<RegistrationInfo>& registration_info) override;
116 void Unregister(
117 const linked_ptr<RegistrationInfo>& registration_info) override;
dcheng00ea022b2014-10-21 11:24:56118 void Send(const std::string& app_id,
119 const std::string& receiver_id,
120 const OutgoingMessage& message) override;
121 void SetRecording(bool recording) override;
122 void ClearActivityLogs() override;
123 GCMStatistics GetStatistics() const override;
124 void SetAccountTokens(
mostynbfe59f482014-10-06 15:04:46125 const std::vector<AccountTokenInfo>& account_tokens) override;
dcheng00ea022b2014-10-21 11:24:56126 void UpdateAccountMapping(const AccountMapping& account_mapping) override;
127 void RemoveAccountMapping(const std::string& account_id) override;
fgorski5df101702014-10-28 02:09:31128 void SetLastTokenFetchTime(const base::Time& time) override;
chirantan192a9212014-12-06 03:30:45129 void UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) override;
jianli10018b2d2015-05-11 21:14:13130 void AddInstanceIDData(const std::string& app_id,
jianli7a0c9b62015-05-26 23:24:47131 const std::string& instance_id,
132 const std::string& extra_data) override;
jianli10018b2d2015-05-11 21:14:13133 void RemoveInstanceIDData(const std::string& app_id) override;
jianli7a0c9b62015-05-26 23:24:47134 void GetInstanceIDData(const std::string& app_id,
135 std::string* instance_id,
136 std::string* extra_data) override;
fgorski22754462015-05-14 00:05:22137 void AddHeartbeatInterval(const std::string& scope, int interval_ms) override;
138 void RemoveHeartbeatInterval(const std::string& scope) override;
[email protected]c31e1b52014-06-12 21:00:47139
140 // GCMStatsRecorder::Delegate implemenation.
dcheng00ea022b2014-10-21 11:24:56141 void OnActivityRecorded() override;
[email protected]e4097c82013-11-08 00:16:12142
[email protected]c31e1b52014-06-12 21:00:47143 // ConnectionFactory::ConnectionListener implementation.
dcheng00ea022b2014-10-21 11:24:56144 void OnConnected(const GURL& current_server,
145 const net::IPEndPoint& ip_endpoint) override;
146 void OnDisconnected() override;
[email protected]c31e1b52014-06-12 21:00:47147
[email protected]e4097c82013-11-08 00:16:12148 private:
[email protected]7df5ef22014-07-17 07:35:58149 // The check-in info for the device.
150 // TODO(fgorski): Convert to a class with explicit getters/setters.
[email protected]cd57f372014-06-09 17:13:06151 struct CheckinInfo {
[email protected]7df5ef22014-07-17 07:35:58152 CheckinInfo();
153 ~CheckinInfo();
[email protected]5799d052014-02-12 20:47:39154 bool IsValid() const { return android_id != 0 && secret != 0; }
[email protected]7df5ef22014-07-17 07:35:58155 void SnapshotCheckinAccounts();
156 void Reset();
[email protected]b83122a92014-01-22 21:29:29157
[email protected]7df5ef22014-07-17 07:35:58158 // Android ID of the device as assigned by the server.
[email protected]5799d052014-02-12 20:47:39159 uint64 android_id;
[email protected]7df5ef22014-07-17 07:35:58160 // Security token of the device as assigned by the server.
[email protected]5799d052014-02-12 20:47:39161 uint64 secret;
[email protected]7df5ef22014-07-17 07:35:58162 // True if accounts were already provided through SetAccountsForCheckin(),
163 // or when |last_checkin_accounts| was loaded as empty.
164 bool accounts_set;
165 // Map of account email addresses and OAuth2 tokens that will be sent to the
166 // checkin server on a next checkin.
167 std::map<std::string, std::string> account_tokens;
168 // As set of accounts last checkin was completed with.
169 std::set<std::string> last_checkin_accounts;
[email protected]848b1b62014-01-30 23:51:04170 };
171
jianli7a0c9b62015-05-26 23:24:47172 // Collection of pending registration requests. Keys are RegistrationInfo
173 // instance, while values are pending registration requests to obtain a
174 // registration ID for requesting application.
175 typedef std::map<linked_ptr<RegistrationInfo>,
176 RegistrationRequest*,
177 RegistrationInfoComparer> PendingRegistrationRequests;
[email protected]848b1b62014-01-30 23:51:04178
jianli7a0c9b62015-05-26 23:24:47179 // Collection of pending unregistration requests. Keys are RegistrationInfo
180 // instance, while values are pending unregistration requests to disable the
181 // registration ID currently assigned to the application.
182 typedef std::map<linked_ptr<RegistrationInfo>,
183 UnregistrationRequest*,
184 RegistrationInfoComparer> PendingUnregistrationRequests;
[email protected]e4007042014-02-15 20:34:28185
[email protected]b83122a92014-01-22 21:29:29186 friend class GCMClientImplTest;
187
[email protected]35601812014-03-07 19:52:43188 // Returns text representation of the enum State.
189 std::string GetStateString() const;
190
[email protected]b83122a92014-01-22 21:29:29191 // Callbacks for the MCSClient.
192 // Receives messages and dispatches them to relevant user delegates.
193 void OnMessageReceivedFromMCS(const gcm::MCSMessage& message);
194 // Receives confirmation of sent messages or information about errors.
195 void OnMessageSentToMCS(int64 user_serial_number,
196 const std::string& app_id,
197 const std::string& message_id,
198 MCSClient::MessageSendStatus status);
199 // Receives information about mcs_client_ errors.
200 void OnMCSError();
201
202 // Runs after GCM Store load is done to trigger continuation of the
203 // initialization.
[email protected]2809af72014-01-25 09:23:57204 void OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result);
jianlif3e52af42015-01-21 23:18:47205 // Starts the GCM.
206 void StartGCM();
[email protected]b83122a92014-01-22 21:29:29207 // Initializes mcs_client_, which handles the connection to MCS.
jianlif3e52af42015-01-21 23:18:47208 void InitializeMCSClient();
[email protected]b83122a92014-01-22 21:29:29209 // Complets the first time device checkin.
210 void OnFirstTimeDeviceCheckinCompleted(const CheckinInfo& checkin_info);
211 // Starts a login on mcs_client_.
212 void StartMCSLogin();
jianli00b4600f2015-02-10 23:32:49213 // Resets the GCM store when it is corrupted.
214 void ResetStore();
[email protected]86625df2014-01-31 03:47:58215 // Sets state to ready. This will initiate the MCS login and notify the
216 // delegates.
fgorski5df101702014-10-28 02:09:31217 void OnReady(const std::vector<AccountMapping>& account_mappings,
218 const base::Time& last_token_fetch_time);
[email protected]b83122a92014-01-22 21:29:29219
[email protected]5799d052014-02-12 20:47:39220 // Starts a first time device checkin.
[email protected]25b5f50e2014-04-03 08:27:23221 void StartCheckin();
[email protected]2c4d4cd2014-04-10 21:10:22222 // Completes the device checkin request by parsing the |checkin_response|.
223 // Function also cleans up the pending checkin.
224 void OnCheckinCompleted(
225 const checkin_proto::AndroidCheckinResponse& checkin_response);
[email protected]06e45272014-05-06 03:41:34226
227 // Callback passed to GCMStore::SetGServicesSettings.
228 void SetGServicesSettingsCallback(bool success);
229
[email protected]764c0442014-05-01 04:30:55230 // Schedules next periodic device checkin and makes sure there is at most one
231 // pending checkin at a time. This function is meant to be called after a
232 // successful checkin.
233 void SchedulePeriodicCheckin();
234 // Gets the time until next checkin.
235 base::TimeDelta GetTimeToNextCheckin() const;
[email protected]7df5ef22014-07-17 07:35:58236 // Callback for setting last checkin information in the |gcm_store_|.
237 void SetLastCheckinInfoCallback(bool success);
[email protected]b83122a92014-01-22 21:29:29238
239 // Callback for persisting device credentials in the |gcm_store_|.
240 void SetDeviceCredentialsCallback(bool success);
241
[email protected]3a20a4d2014-03-21 22:54:21242 // Callback for persisting registration info in the |gcm_store_|.
243 void UpdateRegistrationCallback(bool success);
244
[email protected]72d4f252014-08-20 22:34:28245 // Callback for all store operations that do not try to recover, if write in
246 // |gcm_store_| fails.
247 void DefaultStoreCallback(bool success);
248
fgorski9a405102014-11-19 01:25:16249 // Callback for store operation where result does not matter.
250 void IgnoreWriteResultCallback(bool success);
251
jianli00b4600f2015-02-10 23:32:49252 // Callback for resetting the GCM store.
253 void ResetStoreCallback(bool success);
254
[email protected]848b1b62014-01-30 23:51:04255 // Completes the registration request.
jianli7a0c9b62015-05-26 23:24:47256 void OnRegisterCompleted(
257 const linked_ptr<RegistrationInfo>& registration_info,
258 RegistrationRequest::Status status,
259 const std::string& registration_id);
[email protected]848b1b62014-01-30 23:51:04260
[email protected]e4007042014-02-15 20:34:28261 // Completes the unregistration request.
jianli7a0c9b62015-05-26 23:24:47262 void OnUnregisterCompleted(
263 const linked_ptr<RegistrationInfo>& registration_info,
264 UnregistrationRequest::Status status);
[email protected]e4007042014-02-15 20:34:28265
[email protected]d3a4b2e2014-02-27 13:46:54266 // Completes the GCM store destroy request.
267 void OnGCMStoreDestroyed(bool success);
268
[email protected]c6fe36b2014-03-11 10:58:12269 // Handles incoming data message and dispatches it the delegate of this class.
[email protected]b83122a92014-01-22 21:29:29270 void HandleIncomingMessage(const gcm::MCSMessage& message);
271
[email protected]c6fe36b2014-03-11 10:58:12272 // Fires OnMessageReceived event on the delegate of this class, based on the
273 // details in |data_message_stanza| and |message_data|.
274 void HandleIncomingDataMessage(
275 const mcs_proto::DataMessageStanza& data_message_stanza,
276 MessageData& message_data);
277
278 // Fires OnMessageSendError event on the delegate of this calss, based on the
279 // details in |data_message_stanza| and |message_data|.
280 void HandleIncomingSendError(
281 const mcs_proto::DataMessageStanza& data_message_stanza,
282 MessageData& message_data);
[email protected]848b1b62014-01-30 23:51:04283
jianlif3e52af42015-01-21 23:18:47284 // Is there any standalone app being registered for GCM?
285 bool HasStandaloneRegisteredApp() const;
286
[email protected]2bbe0a682014-03-26 00:08:31287 // Builder for the GCM internals (mcs client, etc.).
288 scoped_ptr<GCMInternalsBuilder> internals_builder_;
[email protected]b83122a92014-01-22 21:29:29289
[email protected]436bcb82014-04-18 00:40:57290 // Recorder that logs GCM activities.
[email protected]025adfa2014-06-03 21:51:12291 GCMStatsRecorderImpl recorder_;
[email protected]436bcb82014-04-18 00:40:57292
[email protected]b83122a92014-01-22 21:29:29293 // State of the GCM Client Implementation.
294 State state_;
295
[email protected]7de78802014-05-10 19:49:40296 GCMClient::Delegate* delegate_;
[email protected]5799d052014-02-12 20:47:39297
jianlif3e52af42015-01-21 23:18:47298 // Flag to indicate if the GCM should be delay started until it is actually
299 // used in either of the following cases:
300 // 1) The GCM store contains the registration records.
301 // 2) GCM functionailities are explicitly called.
302 StartMode start_mode_;
303
[email protected]b83122a92014-01-22 21:29:29304 // Device checkin info (android ID and security token used by device).
305 CheckinInfo device_checkin_info_;
306
[email protected]848b1b62014-01-30 23:51:04307 // Clock used for timing of retry logic. Passed in for testing. Owned by
308 // GCMClientImpl.
309 scoped_ptr<base::Clock> clock_;
[email protected]b83122a92014-01-22 21:29:29310
311 // Information about the chrome build.
312 // TODO(fgorski): Check if it can be passed in constructor and made const.
[email protected]8ad80512014-05-23 09:40:47313 ChromeBuildInfo chrome_build_info_;
[email protected]b83122a92014-01-22 21:29:29314
315 // Persistent data store for keeping device credentials, messages and user to
316 // serial number mappings.
[email protected]79994f42014-01-16 16:05:36317 scoped_ptr<GCMStore> gcm_store_;
[email protected]b83122a92014-01-22 21:29:29318
jianlif3e52af42015-01-21 23:18:47319 // Data loaded from the GCM store.
320 scoped_ptr<GCMStore::LoadResult> load_result_;
321
jianli00b4600f2015-02-10 23:32:49322 // Tracks if the GCM store has been reset. This is used to prevent from
323 // resetting and loading from the store again and again.
324 bool gcm_store_reset_;
325
[email protected]b83122a92014-01-22 21:29:29326 scoped_refptr<net::HttpNetworkSession> network_session_;
327 net::BoundNetLog net_log_;
328 scoped_ptr<ConnectionFactory> connection_factory_;
329 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
330
331 // Controls receiving and sending of packets and reliable message queueing.
332 scoped_ptr<MCSClient> mcs_client_;
333
[email protected]5799d052014-02-12 20:47:39334 scoped_ptr<CheckinRequest> checkin_request_;
[email protected]b83122a92014-01-22 21:29:29335
[email protected]3a20a4d2014-03-21 22:54:21336 // Cached registration info.
337 RegistrationInfoMap registrations_;
[email protected]848b1b62014-01-30 23:51:04338
[email protected]3a20a4d2014-03-21 22:54:21339 // Currently pending registration requests. GCMClientImpl owns the
340 // RegistrationRequests.
341 PendingRegistrationRequests pending_registration_requests_;
342 STLValueDeleter<PendingRegistrationRequests>
343 pending_registration_requests_deleter_;
344
345 // Currently pending unregistration requests. GCMClientImpl owns the
[email protected]e4007042014-02-15 20:34:28346 // UnregistrationRequests.
[email protected]3a20a4d2014-03-21 22:54:21347 PendingUnregistrationRequests pending_unregistration_requests_;
348 STLValueDeleter<PendingUnregistrationRequests>
349 pending_unregistration_requests_deleter_;
[email protected]e4007042014-02-15 20:34:28350
[email protected]764c0442014-05-01 04:30:55351 // G-services settings that were provided by MCS.
[email protected]06e45272014-05-06 03:41:34352 GServicesSettings gservices_settings_;
[email protected]764c0442014-05-01 04:30:55353
354 // Time of the last successful checkin.
355 base::Time last_checkin_time_;
356
jianli7a0c9b62015-05-26 23:24:47357 // Cached instance ID data, key is app ID and value is pair of instance ID
358 // and extra data.
359 std::map<std::string, std::pair<std::string, std::string>> instance_id_data_;
jianli10018b2d2015-05-11 21:14:13360
[email protected]764c0442014-05-01 04:30:55361 // Factory for creating references when scheduling periodic checkin.
362 base::WeakPtrFactory<GCMClientImpl> periodic_checkin_ptr_factory_;
363
[email protected]955e0ff2014-01-31 20:42:12364 // Factory for creating references in callbacks.
365 base::WeakPtrFactory<GCMClientImpl> weak_ptr_factory_;
366
[email protected]e4097c82013-11-08 00:16:12367 DISALLOW_COPY_AND_ASSIGN(GCMClientImpl);
368};
369
370} // namespace gcm
371
[email protected]cd57f372014-06-09 17:13:06372#endif // COMPONENTS_GCM_DRIVER_GCM_CLIENT_IMPL_H_