summaryrefslogtreecommitdiff
path: root/chromium/components/data_use_measurement/core/data_use_measurement.h
blob: f72dc860416e7dbbeb56a21379010bcf61d8ab06 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_DATA_USE_MEASUREMENT_CONTENT_DATA_USE_MEASUREMENT_H_
#define COMPONENTS_DATA_USE_MEASUREMENT_CONTENT_DATA_USE_MEASUREMENT_H_

#include <stdint.h>

#include <memory>
#include <string>

#include "base/callback.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
#include "components/metrics/data_use_tracker.h"

#if defined(OS_ANDROID)
#include "base/android/application_status_listener.h"
#endif

class GURL;

namespace net {
class HttpResponseHeaders;
class URLRequest;
}

namespace data_use_measurement {

class DataUseAscriber;
class URLRequestClassifier;

// Records the data use of user traffic and various services in UMA histograms.
// The UMA is broken down by network technology used (Wi-Fi vs cellular). On
// Android, the UMA is further broken down by whether the application was in the
// background or foreground during the request.
// TODO(amohammadkhan): Complete the layered architecture.
// http://crbug.com/527460
class DataUseMeasurement {
 public:
  DataUseMeasurement(
      std::unique_ptr<URLRequestClassifier> url_request_classifier,
      const metrics::UpdateUsagePrefCallbackType& metrics_data_use_forwarder,
      DataUseAscriber* ascriber);
  ~DataUseMeasurement();

  // Called before a request is sent.
  void OnBeforeURLRequest(net::URLRequest* request);

  // Called right after a redirect response code was received for |request|.
  void OnBeforeRedirect(const net::URLRequest& request,
                        const GURL& new_location);

  // Called when response headers are received for |request|.
  void OnHeadersReceived(net::URLRequest* request,
                         const net::HttpResponseHeaders* response_headers);

  // Called when data is received or sent on the network, respectively.
  void OnNetworkBytesReceived(const net::URLRequest& request,
                              int64_t bytes_received);
  void OnNetworkBytesSent(const net::URLRequest& request, int64_t bytes_sent);

  // Indicates that |request| has been completed or failed.
  void OnCompleted(const net::URLRequest& request, bool started);

#if defined(OS_ANDROID)
  // This function should just be used for testing purposes. A change in
  // application state can be simulated by calling this function.
  void OnApplicationStateChangeForTesting(
      base::android::ApplicationState application_state);
#endif

 private:
  friend class DataUseMeasurementTest;
  FRIEND_TEST_ALL_PREFIXES(DataUseMeasurementTest,
                           TimeOfBackgroundDownstreamBytes);

  // Specifies that data is received or sent, respectively.
  enum TrafficDirection { DOWNSTREAM, UPSTREAM };

  // Returns the current application state (Foreground or Background). It always
  // returns Foreground if Chrome is not running on Android.
  DataUseUserData::AppState CurrentAppState() const;

  // Makes the full name of the histogram. It is made from |prefix| and suffix
  // which is made based on network and application status. suffix is a string
  // representing whether the data use was on the send ("Upstream") or receive
  // ("Downstream") path, and whether the app was in the "Foreground" or
  // "Background".
  std::string GetHistogramNameWithConnectionType(
      const char* prefix,
      TrafficDirection dir,
      DataUseUserData::AppState app_state) const;

  // Makes the full name of the histogram. It is made from |prefix| and suffix
  // which is made based on network and application status. suffix is a string
  // representing whether the data use was on the send ("Upstream") or receive
  // ("Downstream") path, whether the app was in the "Foreground" or
  // "Background", and whether a "Cellular" or "WiFi" network was use. For
  // example, "Prefix.Upstream.Foreground.Cellular" is a possible output.
  // |app_state| indicates the app state which can be foreground, background, or
  // unknown.
  std::string GetHistogramName(const char* prefix,
                               TrafficDirection dir,
                               DataUseUserData::AppState app_state,
                               bool is_connection_cellular) const;

#if defined(OS_ANDROID)
  // Called whenever the application transitions from foreground to background
  // and vice versa.
  void OnApplicationStateChange(
      base::android::ApplicationState application_state);

  // Records the count of bytes received and sent by Chrome on the network as
  // reported by the operating system.
  void MaybeRecordNetworkBytesOS();
#endif

  // Records the data use of the |request|, thus |request| must be non-null.
  // |dir| is the direction (which is upstream or downstream) and |bytes| is the
  // number of bytes in the direction.
  void ReportDataUseUMA(const net::URLRequest& request,
                        TrafficDirection dir,
                        int64_t bytes);

  // Updates the data use of the |request|, thus |request| must be non-null.
  void UpdateDataUsePrefs(const net::URLRequest& request) const;

  // Reports the message size of the service requests.
  void ReportServicesMessageSizeUMA(const net::URLRequest& request);

  // Records data use histograms of services. It gets the size of exchanged
  // message, its direction (which is upstream or downstream) and reports to the
  // histogram DataUse.Services.{Dimensions} with, services as the buckets.
  // |app_state| indicates the app state which can be foreground, or background.
  void ReportDataUsageServices(int32_t traffic_annotation_hash,
                               TrafficDirection dir,
                               DataUseUserData::AppState app_state,
                               int64_t message_size) const;

  // Records data use histograms split on TrafficDirection, AppState and
  // TabState.
  void RecordTabStateHistogram(TrafficDirection dir,
                               DataUseUserData::AppState app_state,
                               bool is_tab_visible,
                               int64_t bytes) const;

  // Records data use histograms split on page tranition.
  void RecordPageTransitionUMA(const net::URLRequest& request) const;

  // Records data use histograms of user traffic and services traffic split on
  // content type, AppState and TabState.
  void RecordContentTypeHistogram(
      DataUseUserData::DataUseContentType content_type,
      bool is_user_traffic,
      DataUseUserData::AppState app_state,
      bool is_tab_visible,
      int64_t bytes);

  // Returns true if the |request| is initiated by user traffic.
  bool IsUserRequest(const net::URLRequest& request) const;

  // Classifier for identifying if an URL request is user initiated.
  std::unique_ptr<URLRequestClassifier> url_request_classifier_;

  // Callback for updating metrics about data use of user traffic and services.
  // TODO(rajendrant): Change this to not report data use service name. Instead
  // pass a bool to distinguish if the data use is for metrics services
  // (UMA, UKM).
  metrics::UpdateUsagePrefCallbackType metrics_data_use_forwarder_;

  // DataUseAscriber used to get the attributes of data use.
  DataUseAscriber* ascriber_;

#if defined(OS_ANDROID)
  // Application listener store the last known state of the application in this
  // field.
  base::android::ApplicationState app_state_;

  // ApplicationStatusListener used to monitor whether the application is in the
  // foreground or in the background. It is owned by DataUseMeasurement.
  std::unique_ptr<base::android::ApplicationStatusListener> app_listener_;

  // Number of bytes received and sent by Chromium as reported by the operating
  // system when it was last queried for traffic statistics. Set to 0 if the
  // operating system was never queried.
  int64_t rx_bytes_os_;
  int64_t tx_bytes_os_;

  // Number of bytes received and sent by Chromium as reported by the network
  // delegate since the operating system was last queried for traffic
  // statistics.
  int64_t bytes_transferred_since_last_traffic_stats_query_;

  // The time at which Chromium app state changed to background. Can be null if
  // app is not in background.
  base::TimeTicks last_app_background_time_;

  // True if app is in background and first network read has not yet happened.
  bool no_reads_since_background_;
#endif

  DISALLOW_COPY_AND_ASSIGN(DataUseMeasurement);
};

}  // namespace data_use_measurement

#endif  // COMPONENTS_DATA_USE_MEASUREMENT_CONTENT_DATA_USE_MEASUREMENT_H_