15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#ifndef COMPONENTS_INVALIDATION_GCM_NETWORK_CHANNEL_H_
646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#define COMPONENTS_INVALIDATION_GCM_NETWORK_CHANNEL_H_
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string>
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/compiler_specific.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/threading/non_thread_safe.h"
1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/invalidation/gcm_network_channel_delegate.h"
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/invalidation/invalidation_export.h"
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/invalidation/sync_system_resources.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/backoff_entry.h"
18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "net/base/network_change_notifier.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "url/gurl.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class GoogleServiceAuthError;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace syncer {
2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)class GCMNetworkChannel;
2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// POD with copy of some statuses for debugging purposes.
2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)struct GCMNetworkChannelDiagnostic {
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  explicit GCMNetworkChannelDiagnostic(GCMNetworkChannel* parent);
3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Collect all the internal variables in a single readable dictionary.
3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> CollectDebugData() const;
3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // TODO(pavely): Move this toString to a more appropiate place in GCMClient.
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::string GCMClientResultToString(
3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      const gcm::GCMClient::Result result) const;
3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  GCMNetworkChannel* parent_;
3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool last_message_empty_echo_token_;
4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::Time last_message_received_time_;
4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int last_post_response_code_;
4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::string registration_id_;
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  gcm::GCMClient::Result registration_result_;
4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int sent_messages_count_;
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)};
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// GCMNetworkChannel is an implementation of SyncNetworkChannel that routes
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// messages through GCMService.
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class INVALIDATION_EXPORT_PRIVATE GCMNetworkChannel
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : public SyncNetworkChannel,
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      public net::URLFetcherDelegate,
52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      public net::NetworkChangeNotifier::NetworkChangeObserver,
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      public base::NonThreadSafe {
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GCMNetworkChannel(
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_refptr<net::URLRequestContextGetter> request_context_getter,
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_ptr<GCMNetworkChannelDelegate> delegate);
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~GCMNetworkChannel();
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // invalidation::NetworkChannel implementation.
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void SendMessage(const std::string& message) OVERRIDE;
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void SetMessageReceiver(
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      invalidation::MessageCallback* incoming_receiver) OVERRIDE;
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // SyncNetworkChannel implementation.
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void UpdateCredentials(const std::string& email,
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 const std::string& token) OVERRIDE;
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  virtual int GetInvalidationClientType() OVERRIDE;
7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual void RequestDetailedStatus(
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      base::Callback<void(const base::DictionaryValue&)> callback) OVERRIDE;
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // URLFetcherDelegate implementation.
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // NetworkChangeObserver implementation.
77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual void OnNetworkChanged(
78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      net::NetworkChangeNotifier::ConnectionType connection_type) OVERRIDE;
79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected:
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ResetRegisterBackoffEntryForTest(
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const net::BackoffEntry::Policy* policy);
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual GURL BuildUrl(const std::string& registration_id);
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  friend class GCMNetworkChannelTest;
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Register();
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnRegisterComplete(const std::string& registration_id,
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          gcm::GCMClient::Result result);
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void RequestAccessToken();
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnGetTokenComplete(const GoogleServiceAuthError& error,
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          const std::string& token);
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void OnIncomingMessage(const std::string& message,
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         const std::string& echo_token);
966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  void OnConnectionStateChanged(bool online);
976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  void UpdateGcmChannelState(bool online);
986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  void UpdateHttpChannelState(bool online);
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Base64 encoding/decoding with URL safe alphabet.
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // http://tools.ietf.org/html/rfc4648#page-7
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static void Base64EncodeURLSafe(const std::string& input,
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  std::string* output);
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static bool Base64DecodeURLSafe(const std::string& input,
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                  std::string* output);
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<GCMNetworkChannelDelegate> delegate_;
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Message is saved until all conditions are met: there is valid
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // registration_id and access_token.
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string cached_message_;
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Access token is saved because in case of auth failure from server we need
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // to invalidate it.
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string access_token_;
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // GCM registration_id is requested one at startup and never refreshed until
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // next restart.
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string registration_id_;
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<net::BackoffEntry> register_backoff_entry_;
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<net::URLFetcher> fetcher_;
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // cacheinvalidation client receives echo_token with incoming message from
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // GCM and shuld include it in headers with outgoing message over http.
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string echo_token_;
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // State of gcm and http channels. GCMNetworkChannel will only report
1296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // INVALIDATIONS_ENABLED if both channels are online.
1306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  bool gcm_channel_online_;
1316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  bool http_channel_online_;
1326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  GCMNetworkChannelDiagnostic diagnostic_info_;
13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WeakPtrFactory<GCMNetworkChannel> weak_factory_;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(GCMNetworkChannel);
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace syncer
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif  // COMPONENTS_INVALIDATION_GCM_NETWORK_CHANNEL_H_
143