• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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();
IsValidCheckinInfo142     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