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