summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxingx@chromium.org <xingx@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-05 18:04:32 +0000
committerxingx@chromium.org <xingx@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-05 18:04:32 +0000
commit0dbf12022b283cb383fde607344a556a42fe8b28 (patch)
tree83c3b1a808452501f41e4e0b407882d98cb242e8
parent3c625c84114901c9866bddfe1abed858da13e538 (diff)
downloadchromium_src-0dbf12022b283cb383fde607344a556a42fe8b28.zip
chromium_src-0dbf12022b283cb383fde607344a556a42fe8b28.tar.gz
chromium_src-0dbf12022b283cb383fde607344a556a42fe8b28.tar.bz2
1. Adds action-parsing functionality for data reduction proxy header.
2. Adds a couple of functions to return different fingerprint value for tamper detection. 3. Adds a function to remove Chrome-Proxy header's fingerprint from its header values, and return the rest of header values. 4. Changes HasDataReductionProxyViaHeader to also tell whether data reduction proxy Via header occurs at the last or not. BUG=381907 Review URL: https://codereview.chromium.org/387353003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@287561 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/android/intercept_download_resource_throttle.cc2
-rw-r--r--chrome/renderer/page_load_histograms.cc3
-rw-r--r--components/data_reduction_proxy/browser/data_reduction_proxy_metrics.cc2
-rw-r--r--components/data_reduction_proxy/common/data_reduction_proxy_headers.cc130
-rw-r--r--components/data_reduction_proxy/common/data_reduction_proxy_headers.h41
-rw-r--r--components/data_reduction_proxy/common/data_reduction_proxy_headers_unittest.cc388
6 files changed, 545 insertions, 21 deletions
diff --git a/chrome/browser/android/intercept_download_resource_throttle.cc b/chrome/browser/android/intercept_download_resource_throttle.cc
index 1101b1e..721ed3d 100644
--- a/chrome/browser/android/intercept_download_resource_throttle.cc
+++ b/chrome/browser/android/intercept_download_resource_throttle.cc
@@ -62,7 +62,7 @@ void InterceptDownloadResourceThrottle::ProcessDownloadRequest() {
if (headers.HasHeader(net::HttpRequestHeaders::kAuthorization) ||
!(request_->response_info().headers &&
data_reduction_proxy::HasDataReductionProxyViaHeader(
- request_->response_info().headers))) {
+ request_->response_info().headers, NULL))) {
return;
}
#else
diff --git a/chrome/renderer/page_load_histograms.cc b/chrome/renderer/page_load_histograms.cc
index 21dd2ef..8360428 100644
--- a/chrome/renderer/page_load_histograms.cc
+++ b/chrome/renderer/page_load_histograms.cc
@@ -177,7 +177,8 @@ bool DataReductionProxyWasUsed(WebFrame* frame) {
std::replace(headers.begin(), headers.end(), '\n', '\0');
scoped_refptr<net::HttpResponseHeaders> response_headers(
new net::HttpResponseHeaders(headers));
- return data_reduction_proxy::HasDataReductionProxyViaHeader(response_headers);
+ return data_reduction_proxy::HasDataReductionProxyViaHeader(
+ response_headers, NULL);
}
// Returns true if the provided URL is a referrer string that came from
diff --git a/components/data_reduction_proxy/browser/data_reduction_proxy_metrics.cc b/components/data_reduction_proxy/browser/data_reduction_proxy_metrics.cc
index 2093d84..795dbea 100644
--- a/components/data_reduction_proxy/browser/data_reduction_proxy_metrics.cc
+++ b/components/data_reduction_proxy/browser/data_reduction_proxy_metrics.cc
@@ -315,7 +315,7 @@ DataReductionProxyRequestType GetDataReductionProxyRequestType(
}
#endif
if (request->response_info().headers &&
- HasDataReductionProxyViaHeader(request->response_info().headers)) {
+ HasDataReductionProxyViaHeader(request->response_info().headers, NULL)) {
return VIA_DATA_REDUCTION_PROXY;
}
return UNKNOWN_TYPE;
diff --git a/components/data_reduction_proxy/common/data_reduction_proxy_headers.cc b/components/data_reduction_proxy/common/data_reduction_proxy_headers.cc
index d97c35c..ebd48c4 100644
--- a/components/data_reduction_proxy/common/data_reduction_proxy_headers.cc
+++ b/components/data_reduction_proxy/common/data_reduction_proxy_headers.cc
@@ -21,6 +21,18 @@ using net::ProxyService;
namespace {
+const char kChromeProxyHeader[] = "chrome-proxy";
+const char kActionValueDelimiter = '=';
+
+const char kChromeProxyActionBlock[] = "block";
+const char kChromeProxyActionBypass[] = "bypass";
+
+// Actions for tamper detection fingerprints.
+const char kChromeProxyActionFingerprintChromeProxy[] = "fcp";
+const char kChromeProxyActionFingerprintVia[] = "fvia";
+const char kChromeProxyActionFingerprintOtherHeaders[] = "foh";
+const char kChromeProxyActionFingerprintContentLength[] = "fcl";
+
const int kShortBypassMaxSeconds = 59;
const int kMediumBypassMaxSeconds = 300;
@@ -35,21 +47,51 @@ base::TimeDelta GetDefaultBypassDuration() {
namespace data_reduction_proxy {
+bool GetDataReductionProxyActionValue(
+ const net::HttpResponseHeaders* headers,
+ const std::string& action_prefix,
+ std::string* action_value) {
+ DCHECK(headers);
+ DCHECK(!action_prefix.empty());
+ // A valid action does not include a trailing '='.
+ DCHECK(action_prefix[action_prefix.size() - 1] != kActionValueDelimiter);
+ void* iter = NULL;
+ std::string value;
+ std::string prefix = action_prefix + kActionValueDelimiter;
+
+ while (headers->EnumerateHeader(&iter, kChromeProxyHeader, &value)) {
+ if (value.size() > prefix.size()) {
+ if (LowerCaseEqualsASCII(value.begin(),
+ value.begin() + prefix.size(),
+ prefix.c_str())) {
+ if (action_value)
+ *action_value = value.substr(prefix.size());
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
bool ParseHeadersAndSetBypassDuration(const net::HttpResponseHeaders* headers,
const std::string& action_prefix,
base::TimeDelta* bypass_duration) {
+ DCHECK(headers);
+ DCHECK(!action_prefix.empty());
+ // A valid action does not include a trailing '='.
+ DCHECK(action_prefix[action_prefix.size() - 1] != kActionValueDelimiter);
void* iter = NULL;
std::string value;
- std::string name = "chrome-proxy";
+ std::string prefix = action_prefix + kActionValueDelimiter;
- while (headers->EnumerateHeader(&iter, name, &value)) {
- if (value.size() > action_prefix.size()) {
+ while (headers->EnumerateHeader(&iter, kChromeProxyHeader, &value)) {
+ if (value.size() > prefix.size()) {
if (LowerCaseEqualsASCII(value.begin(),
- value.begin() + action_prefix.size(),
- action_prefix.c_str())) {
+ value.begin() + prefix.size(),
+ prefix.c_str())) {
int64 seconds;
if (!base::StringToInt64(
- StringPiece(value.begin() + action_prefix.size(), value.end()),
+ StringPiece(value.begin() + prefix.size(), value.end()),
&seconds) || seconds < 0) {
continue; // In case there is a well formed instruction.
}
@@ -82,20 +124,21 @@ bool ParseHeadersAndSetProxyInfo(const net::HttpResponseHeaders* headers,
// 'block' takes precedence over 'bypass', so look for it first.
// TODO(bengr): Reduce checks for 'block' and 'bypass' to a single loop.
if (ParseHeadersAndSetBypassDuration(
- headers, "block=", &proxy_info->bypass_duration)) {
+ headers, kChromeProxyActionBlock, &proxy_info->bypass_duration)) {
proxy_info->bypass_all = true;
return true;
}
// Next, look for 'bypass'.
if (ParseHeadersAndSetBypassDuration(
- headers, "bypass=", &proxy_info->bypass_duration)) {
+ headers, kChromeProxyActionBypass, &proxy_info->bypass_duration)) {
return true;
}
return false;
}
-bool HasDataReductionProxyViaHeader(const net::HttpResponseHeaders* headers) {
+bool HasDataReductionProxyViaHeader(const net::HttpResponseHeaders* headers,
+ bool* has_intermediary) {
const size_t kVersionSize = 4;
const char kDataReductionProxyViaValue[] = "Chrome-Compression-Proxy";
size_t value_len = strlen(kDataReductionProxyViaValue);
@@ -107,8 +150,13 @@ bool HasDataReductionProxyViaHeader(const net::HttpResponseHeaders* headers) {
// 'Via: 1.1 Chrome-Compression-Proxy'
while (headers->EnumerateHeader(&iter, "via", &value)) {
if (value.size() >= kVersionSize + value_len &&
- !value.compare(kVersionSize, value_len, kDataReductionProxyViaValue))
+ !value.compare(kVersionSize, value_len, kDataReductionProxyViaValue)) {
+ if (has_intermediary)
+ // We assume intermediary exists if there is another Via header after
+ // the data reduction proxy's Via header.
+ *has_intermediary = !(headers->EnumerateHeader(&iter, "via", &value));
return true;
+ }
}
// TODO(bengr): Remove deprecated header value.
@@ -116,8 +164,11 @@ bool HasDataReductionProxyViaHeader(const net::HttpResponseHeaders* headers) {
"1.1 Chrome Compression Proxy";
iter = NULL;
while (headers->EnumerateHeader(&iter, "via", &value))
- if (value == kDeprecatedDataReductionProxyViaValue)
+ if (value == kDeprecatedDataReductionProxyViaValue) {
+ if (has_intermediary)
+ *has_intermediary = !(headers->EnumerateHeader(&iter, "via", &value));
return true;
+ }
return false;
}
@@ -151,7 +202,7 @@ GetDataReductionProxyBypassType(
!headers->HasHeader("Proxy-Authenticate")) {
return ProxyService::MALFORMED_407;
}
- if (!HasDataReductionProxyViaHeader(headers) &&
+ if (!HasDataReductionProxyViaHeader(headers, NULL) &&
(headers->response_code() != net::HTTP_NOT_MODIFIED)) {
// A Via header might not be present in a 304. Since the goal of a 304
// response is to minimize information transfer, a sender in general
@@ -170,4 +221,59 @@ GetDataReductionProxyBypassType(
return ProxyService::BYPASS_EVENT_TYPE_MAX;
}
+bool GetDataReductionProxyActionFingerprintChromeProxy(
+ const net::HttpResponseHeaders* headers,
+ std::string* chrome_proxy_fingerprint) {
+ return GetDataReductionProxyActionValue(
+ headers,
+ kChromeProxyActionFingerprintChromeProxy,
+ chrome_proxy_fingerprint);
+}
+
+bool GetDataReductionProxyActionFingerprintVia(
+ const net::HttpResponseHeaders* headers,
+ std::string* via_fingerprint) {
+ return GetDataReductionProxyActionValue(
+ headers,
+ kChromeProxyActionFingerprintVia,
+ via_fingerprint);
+}
+
+bool GetDataReductionProxyActionFingerprintOtherHeaders(
+ const net::HttpResponseHeaders* headers,
+ std::string* other_headers_fingerprint) {
+ return GetDataReductionProxyActionValue(
+ headers,
+ kChromeProxyActionFingerprintOtherHeaders,
+ other_headers_fingerprint);
+}
+
+bool GetDataReductionProxyActionFingerprintContentLength(
+ const net::HttpResponseHeaders* headers,
+ std::string* content_length_fingerprint) {
+ return GetDataReductionProxyActionValue(
+ headers,
+ kChromeProxyActionFingerprintContentLength,
+ content_length_fingerprint);
+}
+
+void GetDataReductionProxyHeaderWithFingerprintRemoved(
+ const net::HttpResponseHeaders* headers,
+ std::vector<std::string>* values) {
+ DCHECK(values);
+ std::string chrome_proxy_fingerprint_prefix = std::string(
+ kChromeProxyActionFingerprintChromeProxy) + kActionValueDelimiter;
+
+ std::string value;
+ void* iter = NULL;
+ while (headers->EnumerateHeader(&iter, kChromeProxyHeader, &value)) {
+ if (!LowerCaseEqualsASCII(
+ value.begin(),
+ value.begin() + chrome_proxy_fingerprint_prefix.size(),
+ chrome_proxy_fingerprint_prefix.c_str())) {
+ values->push_back(value);
+ }
+ }
+}
+
} // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/common/data_reduction_proxy_headers.h b/components/data_reduction_proxy/common/data_reduction_proxy_headers.h
index 28eccee..319d90d 100644
--- a/components/data_reduction_proxy/common/data_reduction_proxy_headers.h
+++ b/components/data_reduction_proxy/common/data_reduction_proxy_headers.h
@@ -41,8 +41,12 @@ bool ParseHeadersAndSetProxyInfo(const net::HttpResponseHeaders* headers,
DataReductionProxyInfo* proxy_info);
// Returns true if the response contains the data reduction proxy Via header
-// value. Used to check the integrity of data reduction proxy responses.
-bool HasDataReductionProxyViaHeader(const net::HttpResponseHeaders* headers);
+// value. If non-NULL, sets |has_intermediary| to true if another server added
+// a Via header after the data reduction proxy, and to false otherwise. Used to
+// check the integrity of data reduction proxy responses and whether there are
+// other middleboxes between the data reduction proxy and the client.
+bool HasDataReductionProxyViaHeader(const net::HttpResponseHeaders* headers,
+ bool* has_intermediary);
// Returns the reason why the Chrome proxy should be bypassed or not, and
// populates |proxy_info| with information on how long to bypass if
@@ -51,11 +55,44 @@ net::ProxyService::DataReductionProxyBypassType GetDataReductionProxyBypassType(
const net::HttpResponseHeaders* headers,
DataReductionProxyInfo* proxy_info);
+// Searches for the specified Chrome-Proxy action, and if present saves its
+// value as a string in |action_value|. Only returns the first one and ignores
+// the rest if multiple actions match |action_prefix|.
+bool GetDataReductionProxyActionValue(
+ const net::HttpResponseHeaders* headers,
+ const std::string& action_prefix,
+ std::string* action_value);
+
// Searches for the specified Chrome-Proxy action, and if present interprets
// its value as a duration in seconds.
bool ParseHeadersAndSetBypassDuration(const net::HttpResponseHeaders* headers,
const std::string& action_prefix,
base::TimeDelta* bypass_duration);
+// Gets the fingerprint of the Chrome-Proxy header.
+bool GetDataReductionProxyActionFingerprintChromeProxy(
+ const net::HttpResponseHeaders* headers,
+ std::string* chrome_proxy_fingerprint);
+
+// Gets the fingerprint of the Via header.
+bool GetDataReductionProxyActionFingerprintVia(
+ const net::HttpResponseHeaders* headers,
+ std::string* via_fingerprint);
+
+// Gets the fingerprint of a list of headers.
+bool GetDataReductionProxyActionFingerprintOtherHeaders(
+ const net::HttpResponseHeaders* headers,
+ std::string* other_headers_fingerprint);
+
+// Gets the fingerprint of Content-Length header.
+bool GetDataReductionProxyActionFingerprintContentLength(
+ const net::HttpResponseHeaders* headers,
+ std::string* content_length_fingerprint);
+
+// Returns values of the Chrome-Proxy header, but with its fingerprint removed.
+void GetDataReductionProxyHeaderWithFingerprintRemoved(
+ const net::HttpResponseHeaders* headers,
+ std::vector<std::string>* values);
+
} // namespace data_reduction_proxy
#endif // COMPONENTS_DATA_REDUCTION_PROXY_COMMON_DATA_REDUCTION_PROXY_HEADERS_H_
diff --git a/components/data_reduction_proxy/common/data_reduction_proxy_headers_unittest.cc b/components/data_reduction_proxy/common/data_reduction_proxy_headers_unittest.cc
index ef3de65..6a98dd1 100644
--- a/components/data_reduction_proxy/common/data_reduction_proxy_headers_unittest.cc
+++ b/components/data_reduction_proxy/common/data_reduction_proxy_headers_unittest.cc
@@ -24,6 +24,92 @@ namespace data_reduction_proxy {
class DataReductionProxyHeadersTest : public testing::Test {};
+TEST_F(DataReductionProxyHeadersTest, GetDataReductionProxyActionValue) {
+ const struct {
+ const char* headers;
+ std::string action_key;
+ bool expected_result;
+ std::string expected_action_value;
+ } tests[] = {
+ { "HTTP/1.1 200 OK\n"
+ "Content-Length: 999\n",
+ "a",
+ false,
+ "",
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Content-Length: 999\n",
+ "a",
+ false,
+ "",
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=86400\n"
+ "Content-Length: 999\n",
+ "bypass",
+ true,
+ "86400",
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass86400\n"
+ "Content-Length: 999\n",
+ "bypass",
+ false,
+ "",
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=0\n"
+ "Content-Length: 999\n",
+ "bypass",
+ true,
+ "0",
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=1500\n"
+ "Chrome-Proxy: bypass=86400\n"
+ "Content-Length: 999\n",
+ "bypass",
+ true,
+ "1500",
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: block=1500, block=3600\n"
+ "Content-Length: 999\n",
+ "block",
+ true,
+ "1500",
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: proxy-bypass\n"
+ "Chrome-Proxy: key=123 \n"
+ "Content-Length: 999\n",
+ "key",
+ true,
+ "123",
+ },
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ std::string headers(tests[i].headers);
+ HeadersToRaw(&headers);
+ scoped_refptr<net::HttpResponseHeaders> parsed(
+ new net::HttpResponseHeaders(headers));
+
+ std::string action_value;
+ bool has_action_key = GetDataReductionProxyActionValue(
+ parsed, tests[i].action_key, &action_value);
+ EXPECT_EQ(tests[i].expected_result, has_action_key);
+ if (has_action_key) {
+ EXPECT_EQ(tests[i].expected_action_value, action_value);
+ }
+ }
+}
+
TEST_F(DataReductionProxyHeadersTest, GetProxyBypassInfo) {
const struct {
const char* headers;
@@ -202,66 +288,117 @@ TEST_F(DataReductionProxyHeadersTest, ParseHeadersAndSetProxyInfo) {
TEST_F(DataReductionProxyHeadersTest, HasDataReductionProxyViaHeader) {
const struct {
- const char* headers;
- bool expected_result;
+ const char* headers;
+ bool expected_result;
+ bool expected_has_intermediary;
+ bool ignore_intermediary;
} tests[] = {
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 Chrome-Proxy\n",
false,
+ false,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1\n",
false,
+ false,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 Chrome-Compression-Proxy\n",
true,
+ true,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.0 Chrome-Compression-Proxy\n",
true,
+ true,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 Foo-Bar, 1.1 Chrome-Compression-Proxy\n",
true,
+ true,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 Chrome-Compression-Proxy, 1.1 Bar-Foo\n",
true,
+ false,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 chrome-compression-proxy\n",
false,
+ false,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 Foo-Bar\n"
"Via: 1.1 Chrome-Compression-Proxy\n",
true,
+ true,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "Via: 1.1 Chrome-Compression-Proxy\n"
+ "Via: 1.1 Foo-Bar\n",
+ true,
+ false,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 Chrome-Proxy\n",
false,
+ false,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 Chrome Compression Proxy\n",
true,
+ true,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 Foo-Bar, 1.1 Chrome Compression Proxy\n",
true,
+ true,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 Chrome Compression Proxy, 1.1 Bar-Foo\n",
true,
+ false,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 chrome compression proxy\n",
false,
+ false,
+ false,
},
{ "HTTP/1.1 200 OK\n"
"Via: 1.1 Foo-Bar\n"
"Via: 1.1 Chrome Compression Proxy\n",
true,
+ true,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "Via: 1.1 Chrome Compression Proxy\n"
+ "Via: 1.1 Foo-Bar\n",
+ true,
+ false,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "Via: 1.1 Chrome Compression Proxy\n"
+ "Via: 1.1 Foo-Bar\n",
+ true,
+ false,
+ true,
},
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
@@ -270,8 +407,19 @@ TEST_F(DataReductionProxyHeadersTest, HasDataReductionProxyViaHeader) {
scoped_refptr<net::HttpResponseHeaders> parsed(
new net::HttpResponseHeaders(headers));
- EXPECT_EQ(tests[i].expected_result,
- HasDataReductionProxyViaHeader(parsed));
+ bool has_chrome_proxy_via_header, has_intermediary;
+ if (tests[i].ignore_intermediary) {
+ has_chrome_proxy_via_header =
+ HasDataReductionProxyViaHeader(parsed, NULL);
+ }
+ else {
+ has_chrome_proxy_via_header =
+ HasDataReductionProxyViaHeader(parsed, &has_intermediary);
+ }
+ EXPECT_EQ(tests[i].expected_result, has_chrome_proxy_via_header);
+ if (has_chrome_proxy_via_header && !tests[i].ignore_intermediary) {
+ EXPECT_EQ(tests[i].expected_has_intermediary, has_intermediary);
+ }
}
}
@@ -381,4 +529,236 @@ TEST_F(DataReductionProxyHeadersTest, GetDataReductionProxyBypassEventType) {
GetDataReductionProxyBypassType(parsed, &chrome_proxy_info));
}
}
+
+TEST_F(DataReductionProxyHeadersTest,
+ GetDataReductionProxyActionFingerprintChromeProxy) {
+ const struct {
+ std::string label;
+ const char* headers;
+ bool expected_fingerprint_exist;
+ std::string expected_fingerprint;
+ } tests[] = {
+ { "fingerprint doesn't exist",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=0\n",
+ false,
+ "",
+ },
+ { "fingerprint occurs once",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=1, fcp=fp\n",
+ true,
+ "fp",
+ },
+ { "fingerprint occurs twice",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=2, fcp=fp1, fcp=fp2\n",
+ true,
+ "fp1",
+ },
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ std::string headers(tests[i].headers);
+ HeadersToRaw(&headers);
+ scoped_refptr<net::HttpResponseHeaders> parsed(
+ new net::HttpResponseHeaders(headers));
+
+ std::string fingerprint;
+ bool fingerprint_exist = GetDataReductionProxyActionFingerprintChromeProxy(
+ parsed, &fingerprint);
+ EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
+ << tests[i].label;
+
+ if (fingerprint_exist)
+ EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
+ }
+}
+
+TEST_F(DataReductionProxyHeadersTest,
+ GetDataReductionProxyActionFingerprintVia) {
+ const struct {
+ std::string label;
+ const char* headers;
+ bool expected_fingerprint_exist;
+ std::string expected_fingerprint;
+ } tests[] = {
+ { "fingerprint doesn't exist",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=0\n",
+ false,
+ "",
+ },
+ { "fingerprint occurs once",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=1, fvia=fvia\n",
+ true,
+ "fvia",
+ },
+ { "fingerprint occurs twice",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=2, fvia=fvia1, fvia=fvia2\n",
+ true,
+ "fvia1",
+ },
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ std::string headers(tests[i].headers);
+ HeadersToRaw(&headers);
+ scoped_refptr<net::HttpResponseHeaders> parsed(
+ new net::HttpResponseHeaders(headers));
+
+ std::string fingerprint;
+ bool fingerprint_exist =
+ GetDataReductionProxyActionFingerprintVia(parsed, &fingerprint);
+ EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
+ << tests[i].label;
+
+ if (fingerprint_exist)
+ EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
+ }
+}
+
+TEST_F(DataReductionProxyHeadersTest,
+ GetDataReductionProxyActionFingerprintOtherHeaders) {
+ const struct {
+ std::string label;
+ const char* headers;
+ bool expected_fingerprint_exist;
+ std::string expected_fingerprint;
+ } tests[] = {
+ { "fingerprint doesn't exist",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=0\n",
+ false,
+ "",
+ },
+ { "fingerprint occurs once",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=1, foh=foh\n",
+ true,
+ "foh",
+ },
+ { "fingerprint occurs twice",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=2, foh=foh1, foh=foh2\n",
+ true,
+ "foh1",
+ },
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ std::string headers(tests[i].headers);
+ HeadersToRaw(&headers);
+ scoped_refptr<net::HttpResponseHeaders> parsed(
+ new net::HttpResponseHeaders(headers));
+
+ std::string fingerprint;
+ bool fingerprint_exist =
+ GetDataReductionProxyActionFingerprintOtherHeaders(
+ parsed, &fingerprint);
+ EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
+ << tests[i].label;
+
+ if (fingerprint_exist)
+ EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
+ }
+}
+
+TEST_F(DataReductionProxyHeadersTest,
+ GetDataReductionProxyActionFingerprintContentLength) {
+ const struct {
+ std::string label;
+ const char* headers;
+ bool expected_fingerprint_exist;
+ std::string expected_fingerprint;
+ } tests[] = {
+ { "fingerprint doesn't exist",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=0\n",
+ false,
+ "",
+ },
+ { "fingerprint occurs once",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=1, fcl=fcl\n",
+ true,
+ "fcl",
+ },
+ { "fingerprint occurs twice",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: bypass=2, fcl=fcl1, fcl=fcl2\n",
+ true,
+ "fcl1",
+ },
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ std::string headers(tests[i].headers);
+ HeadersToRaw(&headers);
+ scoped_refptr<net::HttpResponseHeaders> parsed(
+ new net::HttpResponseHeaders(headers));
+
+ std::string fingerprint;
+ bool fingerprint_exist =
+ GetDataReductionProxyActionFingerprintContentLength(
+ parsed, &fingerprint);
+ EXPECT_EQ(tests[i].expected_fingerprint_exist, fingerprint_exist)
+ << tests[i].label;
+
+ if (fingerprint_exist)
+ EXPECT_EQ(tests[i].expected_fingerprint, fingerprint) << tests[i].label;
+ }
+}
+
+TEST_F(DataReductionProxyHeadersTest,
+ GetDataReductionProxyHeaderWithFingerprintRemoved) {
+ struct {
+ std::string label;
+ const char* headers;
+ std::string expected_output_values_string;
+ } test[] = {
+ {
+ "Checks the case that there is no Chrome-Proxy header's fingerprint.",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: 1,2,3,5\n",
+ "1,2,3,5,",
+ },
+ {
+ "Checks the case that there is Chrome-Proxy header's fingerprint.",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: 1,2,3,fcp=4,5\n",
+ "1,2,3,5,",
+ },
+ {
+ "Checks the case that there is Chrome-Proxy header's fingerprint, and it"
+ "occurs at the end.",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: 1,2,3,fcp=4,",
+ "1,2,3,",
+ },
+ {
+ "Checks the case that there is Chrome-Proxy header's fingerprint, and it"
+ "occurs at the beginning.",
+ "HTTP/1.1 200 OK\n"
+ "Chrome-Proxy: fcp=1,2,3,",
+ "2,3,",
+ },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test); ++i) {
+ std::string headers(test[i].headers);
+ HeadersToRaw(&headers);
+ scoped_refptr<net::HttpResponseHeaders> parsed(
+ new net::HttpResponseHeaders(headers));
+
+ std::vector<std::string> output_values;
+ GetDataReductionProxyHeaderWithFingerprintRemoved(parsed, &output_values);
+
+ std::string output_values_string;
+ for (size_t j = 0; j < output_values.size(); ++j)
+ output_values_string += output_values[j] + ",";
+
+ EXPECT_EQ(test[i].expected_output_values_string, output_values_string)
+ << test[i].label;
+ }
+}
+
} // namespace data_reduction_proxy