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_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_USAGE_STATS_H_ 6 #define COMPONENTS_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_USAGE_STATS_H_ 7 8 #include "base/callback.h" 9 #include "base/message_loop/message_loop_proxy.h" 10 #include "base/prefs/pref_member.h" 11 #include "base/threading/thread_checker.h" 12 #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h" 13 #include "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" 14 #include "net/base/host_port_pair.h" 15 #include "net/base/network_change_notifier.h" 16 #include "net/url_request/url_request.h" 17 18 namespace net { 19 class HttpResponseHeaders; 20 class ProxyConfig; 21 class ProxyServer; 22 } 23 24 namespace data_reduction_proxy { 25 26 class DataReductionProxyUsageStats 27 : public net::NetworkChangeNotifier::NetworkChangeObserver { 28 public: 29 // Records a data reduction proxy bypass event as a "BlockType" if 30 // |bypass_all| is true and as a "BypassType" otherwise. Records the event as 31 // "Primary" if |is_primary| is true and "Fallback" otherwise. 32 static void RecordDataReductionProxyBypassInfo( 33 bool is_primary, 34 bool bypass_all, 35 const net::ProxyServer& proxy_server, 36 DataReductionProxyBypassType bypass_type); 37 38 // For the given response |headers| that are expected to include the data 39 // reduction proxy via header, records response code UMA if the data reduction 40 // proxy via header is not present. 41 static void DetectAndRecordMissingViaHeaderResponseCode( 42 bool is_primary, 43 const net::HttpResponseHeaders* headers); 44 45 // MessageLoopProxy instance is owned by io_thread. |params| outlives 46 // this class instance. 47 DataReductionProxyUsageStats( 48 DataReductionProxyParams* params, 49 const scoped_refptr<base::MessageLoopProxy>& ui_thread_proxy); 50 virtual ~DataReductionProxyUsageStats(); 51 52 // Sets the callback to be called on the UI thread when the unavailability 53 // status has changed. 54 void set_unavailable_callback( 55 const base::Callback<void(bool)>& unavailable_callback) { 56 unavailable_callback_ = unavailable_callback; 57 } 58 59 // Callback intended to be called from |ChromeNetworkDelegate| when a 60 // request completes. This method is used to gather usage stats. 61 void OnUrlRequestCompleted(const net::URLRequest* request, bool started); 62 63 // Records the last bypass reason to |bypass_type_| and sets 64 // |triggering_request_| to true. A triggering request is the first request to 65 // cause the current bypass. 66 void SetBypassType(DataReductionProxyBypassType type); 67 68 // Records all the data reduction proxy bytes-related histograms for the 69 // completed URLRequest |request|. 70 void RecordBytesHistograms( 71 net::URLRequest* request, 72 const BooleanPrefMember& data_reduction_proxy_enabled, 73 const net::ProxyConfig& data_reduction_proxy_config); 74 75 // Called by |ChromeNetworkDelegate| when a proxy is put into the bad proxy 76 // list. Used to track when the data reduction proxy falls back. 77 void OnProxyFallback(const net::ProxyServer& bypassed_proxy, 78 int net_error); 79 80 private: 81 friend class DataReductionProxyUsageStatsTest; 82 FRIEND_TEST_ALL_PREFIXES(DataReductionProxyUsageStatsTest, 83 RecordMissingViaHeaderBytes); 84 85 enum BypassedBytesType { 86 NOT_BYPASSED = 0, /* Not bypassed. */ 87 SSL, /* Bypass due to SSL. */ 88 LOCAL_BYPASS_RULES, /* Bypass due to client-side bypass rules. */ 89 MANAGED_PROXY_CONFIG, /* Bypass due to managed config. */ 90 AUDIO_VIDEO, /* Audio/Video bypass. */ 91 TRIGGERING_REQUEST, /* Triggering request bypass. */ 92 NETWORK_ERROR, /* Network error. */ 93 BYPASSED_BYTES_TYPE_MAX /* This must always be last.*/ 94 }; 95 96 // Given |data_reduction_proxy_enabled|, a |request|, and the 97 // |data_reduction_proxy_config| records the number of bypassed bytes for that 98 // |request| into UMAs based on bypass type. |data_reduction_proxy_enabled| 99 // tells us the state of the kDataReductionProxyEnabled preference. 100 void RecordBypassedBytesHistograms( 101 net::URLRequest* request, 102 const BooleanPrefMember& data_reduction_proxy_enabled, 103 const net::ProxyConfig& data_reduction_proxy_config); 104 105 // Records UMA of the number of response bytes of responses that are expected 106 // to have the data reduction proxy via header, but where the data reduction 107 // proxy via header is not present. 108 void RecordMissingViaHeaderBytes(net::URLRequest* request); 109 110 // NetworkChangeNotifier::NetworkChangeObserver: 111 virtual void OnNetworkChanged( 112 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE; 113 114 // Called when request counts change. Resets counts if they exceed thresholds, 115 // and calls MaybeNotifyUnavailability otherwise. 116 void OnRequestCountChanged(); 117 118 // Clears request counts unconditionally. 119 void ClearRequestCounts(); 120 121 // Checks if the availability status of the data reduction proxy has changed, 122 // and notifies the UIThread via NotifyUnavailabilityOnUIThread if so. The 123 // data reduction proxy is considered unavailable if and only if no requests 124 // went through the proxy but some eligible requests were service by other 125 // routes. 126 void NotifyUnavailabilityIfChanged(); 127 void NotifyUnavailabilityOnUIThread(bool unavailable); 128 129 DataReductionProxyParams* data_reduction_proxy_params_; 130 // The last reason for bypass as determined by 131 // MaybeBypassProxyAndPrepareToRetry 132 DataReductionProxyBypassType last_bypass_type_; 133 // True if the last request triggered the current bypass. 134 bool triggering_request_; 135 const scoped_refptr<base::MessageLoopProxy> ui_thread_proxy_; 136 137 // The following 2 fields are used to determine if data reduction proxy is 138 // unreachable. We keep a count of requests which should go through 139 // data request proxy, as well as those which actually do. The proxy is 140 // unreachable if no successful requests are made through it despite a 141 // non-zero number of requests being eligible. 142 143 // Count of successful requests through the data reduction proxy. 144 unsigned long successful_requests_through_proxy_count_; 145 146 // Count of network errors encountered when connecting to a data reduction 147 // proxy. 148 unsigned long proxy_net_errors_count_; 149 150 // Whether or not the data reduction proxy is unavailable. 151 bool unavailable_; 152 153 base::ThreadChecker thread_checker_; 154 155 void RecordBypassedBytes( 156 DataReductionProxyBypassType bypass_type, 157 BypassedBytesType bypassed_bytes_type, 158 int64 content_length); 159 160 // Called when the unavailability status has changed. Runs on the UI thread. 161 base::Callback<void(bool)> unavailable_callback_; 162 163 DISALLOW_COPY_AND_ASSIGN(DataReductionProxyUsageStats); 164 }; 165 166 } // namespace data_reduction_proxy 167 168 #endif // COMPONENTS_DATA_REDUCTION_PROXY_BROWSER_DATA_REDUCTION_PROXY_USAGE_STATS_H_ 169