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