1 // Copyright 2016 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 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
6 
7 #include <stdint.h>
8 
9 #include "base/stl_util.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/time/time.h"
12 #include "base/version.h"
13 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
14 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
15 #include "components/data_reduction_proxy/core/common/version.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/url_util.h"
18 #include "net/http/http_response_headers.h"
19 #include "net/http/http_status_code.h"
20 #include "net/http/http_util.h"
21 
22 #if defined(USE_GOOGLE_API_KEYS)
23 #include "google_apis/google_api_keys.h"
24 #endif
25 
26 namespace data_reduction_proxy {
27 
28 namespace {
29 
30 #if defined(USE_GOOGLE_API_KEYS)
31 // Used in all Data Reduction Proxy URLs to specify API Key.
32 const char kApiKeyName[] = "key";
33 #endif
34 
35 // Hostname used for the other bucket which consists of chrome-services traffic.
36 // This should be in sync with the same in DataReductionSiteBreakdownView.java
37 const char kOtherHostName[] = "Other";
38 
39 }  // namespace
40 
41 namespace util {
42 
ChromiumVersion()43 const char* ChromiumVersion() {
44   // Assert at compile time that the Chromium version is at least somewhat
45   // properly formed, e.g. the version string is at least as long as "0.0.0.0",
46   // and starts and ends with numeric digits. This is to prevent another
47   // regression like http://crbug.com/595471.
48   static_assert(base::size(PRODUCT_VERSION) >= base::size("0.0.0.0") &&
49                     '0' <= PRODUCT_VERSION[0] && PRODUCT_VERSION[0] <= '9' &&
50                     '0' <= PRODUCT_VERSION[base::size(PRODUCT_VERSION) - 2] &&
51                     PRODUCT_VERSION[base::size(PRODUCT_VERSION) - 2] <= '9',
52                 "PRODUCT_VERSION must be a string of the form "
53                 "'MAJOR.MINOR.BUILD.PATCH', e.g. '1.2.3.4'. "
54                 "PRODUCT_VERSION='" PRODUCT_VERSION "' is badly formed.");
55 
56   return PRODUCT_VERSION;
57 }
58 
GetChromiumBuildAndPatch(const std::string & version_string,std::string * build,std::string * patch)59 void GetChromiumBuildAndPatch(const std::string& version_string,
60                               std::string* build,
61                               std::string* patch) {
62   uint32_t build_number;
63   uint32_t patch_number;
64   GetChromiumBuildAndPatchAsInts(version_string, &build_number, &patch_number);
65   *build = base::NumberToString(build_number);
66   *patch = base::NumberToString(patch_number);
67 }
68 
GetChromiumBuildAndPatchAsInts(const std::string & version_string,uint32_t * build,uint32_t * patch)69 void GetChromiumBuildAndPatchAsInts(const std::string& version_string,
70                                     uint32_t* build,
71                                     uint32_t* patch) {
72   base::Version version(version_string);
73   DCHECK(version.IsValid());
74   DCHECK_EQ(4U, version.components().size());
75   *build = version.components()[2];
76   *patch = version.components()[3];
77 }
78 
GetStringForClient(Client client)79 const char* GetStringForClient(Client client) {
80   switch (client) {
81     case Client::UNKNOWN:
82       return "";
83     case Client::CRONET_ANDROID:
84       return "cronet";
85     case Client::WEBVIEW_ANDROID:
86       return "webview";
87     case Client::CHROME_ANDROID:
88       return "android";
89     case Client::CHROME_IOS:
90       return "ios";
91     case Client::CHROME_MAC:
92       return "mac";
93     case Client::CHROME_CHROMEOS:
94       return "chromeos";
95     case Client::CHROME_LINUX:
96       return "linux";
97     case Client::CHROME_WINDOWS:
98       return "win";
99     case Client::CHROME_DRAGONFLY:
100       return "dragonfly";
101     case Client::CHROME_FREEBSD:
102       return "freebsd";
103     case Client::CHROME_OPENBSD:
104       return "openbsd";
105     case Client::CHROME_SOLARIS:
106       return "solaris";
107     case Client::CHROME_QNX:
108       return "qnx";
109     default:
110       NOTREACHED();
111       return "";
112   }
113 }
114 
AddApiKeyToUrl(const GURL & url)115 GURL AddApiKeyToUrl(const GURL& url) {
116   GURL new_url = url;
117 #if defined(USE_GOOGLE_API_KEYS)
118   std::string api_key = google_apis::GetAPIKey();
119   if (google_apis::HasAPIKeyConfigured() && !api_key.empty()) {
120     new_url = net::AppendOrReplaceQueryParameter(url, kApiKeyName, api_key);
121   }
122 #endif
123   return net::AppendOrReplaceQueryParameter(new_url, "alt", "proto");
124 }
125 
GetSiteBreakdownOtherHostName()126 const char* GetSiteBreakdownOtherHostName() {
127   return kOtherHostName;
128 }
129 
130 }  // namespace util
131 
132 namespace protobuf_parser {
133 
SchemeFromPrefetchScheme(PrefetchProxyConfig_Proxy_Scheme proxy_scheme)134 std::string SchemeFromPrefetchScheme(
135     PrefetchProxyConfig_Proxy_Scheme proxy_scheme) {
136   switch (proxy_scheme) {
137     case PrefetchProxyConfig_Proxy_Scheme_HTTP:
138       return "http";
139     case PrefetchProxyConfig_Proxy_Scheme_HTTPS:
140       return "https";
141     default:
142       return std::string();
143   }
144 }
145 
TimeDeltaToDuration(const base::TimeDelta & time_delta,Duration * duration)146 void TimeDeltaToDuration(const base::TimeDelta& time_delta,
147                          Duration* duration) {
148   duration->set_seconds(time_delta.InSeconds());
149   base::TimeDelta partial_seconds =
150       time_delta - base::TimeDelta::FromSeconds(time_delta.InSeconds());
151   duration->set_nanos(partial_seconds.InMicroseconds() *
152                       base::Time::kNanosecondsPerMicrosecond);
153 }
154 
DurationToTimeDelta(const Duration & duration)155 base::TimeDelta DurationToTimeDelta(const Duration& duration) {
156   return base::TimeDelta::FromSeconds(duration.seconds()) +
157          base::TimeDelta::FromMicroseconds(
158              duration.nanos() / base::Time::kNanosecondsPerMicrosecond);
159 }
160 
TimeToTimestamp(const base::Time & time,Timestamp * timestamp)161 void TimeToTimestamp(const base::Time& time, Timestamp* timestamp) {
162   timestamp->set_seconds((time - base::Time::UnixEpoch()).InSeconds());
163   timestamp->set_nanos(((time - base::Time::UnixEpoch()).InMicroseconds() %
164                         base::Time::kMicrosecondsPerSecond) *
165                        base::Time::kNanosecondsPerMicrosecond);
166 }
167 
TimestampToTime(const Timestamp & timestamp)168 base::Time TimestampToTime(const Timestamp& timestamp) {
169   base::Time t = base::Time::UnixEpoch();
170   t += base::TimeDelta::FromSeconds(timestamp.seconds());
171   t += base::TimeDelta::FromMicroseconds(
172       timestamp.nanos() / base::Time::kNanosecondsPerMicrosecond);
173   return t;
174 }
175 
CreateDurationFromTimeDelta(const base::TimeDelta & time_delta)176 std::unique_ptr<Duration> CreateDurationFromTimeDelta(
177     const base::TimeDelta& time_delta) {
178   std::unique_ptr<Duration> duration(new Duration);
179   TimeDeltaToDuration(time_delta, duration.get());
180   return duration;
181 }
182 
CreateTimestampFromTime(const base::Time & time)183 std::unique_ptr<Timestamp> CreateTimestampFromTime(const base::Time& time) {
184   std::unique_ptr<Timestamp> timestamp(new Timestamp);
185   TimeToTimestamp(time, timestamp.get());
186   return timestamp;
187 }
188 
189 }  // namespace protobuf_parser
190 
191 }  // namespace data_reduction_proxy
192