Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: chrome/browser/extensions/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc

Issue 562913002: Move web_request_condition* files to extensions/browser/api/declarative_webrequest/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase to master@294403 Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "chrome/browser/extensions/api/declarative_webrequest/webrequest_condit ion_attribute.h"
6
7 #include "base/basictypes.h"
8 #include "base/files/file_path.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/values.h"
12 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condit ion.h"
13 #include "content/public/browser/resource_request_info.h"
14 #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
15 #include "net/base/request_priority.h"
16 #include "net/test/embedded_test_server/embedded_test_server.h"
17 #include "net/url_request/url_request.h"
18 #include "net/url_request/url_request_test_util.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 using base::DictionaryValue;
22 using base::FundamentalValue;
23 using base::ListValue;
24 using base::StringValue;
25 using base::Value;
26 using content::ResourceType;
27
28 namespace extensions {
29
30 namespace keys = declarative_webrequest_constants;
31
32 namespace {
33 const char kUnknownConditionName[] = "unknownType";
34
35 base::FilePath TestDataPath(base::StringPiece relative_to_src) {
36 base::FilePath src_dir;
37 CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
38 return src_dir.AppendASCII(relative_to_src);
39 }
40
41 TEST(WebRequestConditionAttributeTest, CreateConditionAttribute) {
42 // Necessary for TestURLRequest.
43 base::MessageLoopForIO message_loop;
44
45 std::string error;
46 scoped_refptr<const WebRequestConditionAttribute> result;
47 base::StringValue string_value("main_frame");
48 base::ListValue resource_types;
49 resource_types.Append(new base::StringValue("main_frame"));
50
51 // Test wrong condition name passed.
52 error.clear();
53 result = WebRequestConditionAttribute::Create(
54 kUnknownConditionName, &resource_types, &error);
55 EXPECT_FALSE(error.empty());
56 EXPECT_FALSE(result.get());
57
58 // Test wrong data type passed
59 error.clear();
60 result = WebRequestConditionAttribute::Create(
61 keys::kResourceTypeKey, &string_value, &error);
62 EXPECT_FALSE(error.empty());
63 EXPECT_FALSE(result.get());
64
65 error.clear();
66 result = WebRequestConditionAttribute::Create(
67 keys::kContentTypeKey, &string_value, &error);
68 EXPECT_FALSE(error.empty());
69 EXPECT_FALSE(result.get());
70
71 // Test success
72 error.clear();
73 result = WebRequestConditionAttribute::Create(
74 keys::kResourceTypeKey, &resource_types, &error);
75 EXPECT_EQ("", error);
76 ASSERT_TRUE(result.get());
77 EXPECT_EQ(WebRequestConditionAttribute::CONDITION_RESOURCE_TYPE,
78 result->GetType());
79 EXPECT_EQ(std::string(keys::kResourceTypeKey), result->GetName());
80 }
81
82 TEST(WebRequestConditionAttributeTest, ResourceType) {
83 // Necessary for TestURLRequest.
84 base::MessageLoopForIO message_loop;
85
86 std::string error;
87 base::ListValue resource_types;
88 // The 'sub_frame' value is chosen arbitrarily, so as the corresponding
89 // content::ResourceType is not 0, the default value.
90 resource_types.Append(new base::StringValue("sub_frame"));
91
92 scoped_refptr<const WebRequestConditionAttribute> attribute =
93 WebRequestConditionAttribute::Create(
94 keys::kResourceTypeKey, &resource_types, &error);
95 EXPECT_EQ("", error);
96 ASSERT_TRUE(attribute.get());
97 EXPECT_EQ(std::string(keys::kResourceTypeKey), attribute->GetName());
98
99 net::TestURLRequestContext context;
100 scoped_ptr<net::URLRequest> url_request_ok(context.CreateRequest(
101 GURL("http://www.example.com"), net::DEFAULT_PRIORITY, NULL, NULL));
102 content::ResourceRequestInfo::AllocateForTesting(
103 url_request_ok.get(),
104 content::RESOURCE_TYPE_SUB_FRAME,
105 NULL,
106 -1,
107 -1,
108 -1,
109 false);
110 EXPECT_TRUE(attribute->IsFulfilled(WebRequestData(url_request_ok.get(),
111 ON_BEFORE_REQUEST)));
112
113 scoped_ptr<net::URLRequest> url_request_fail(context.CreateRequest(
114 GURL("http://www.example.com"), net::DEFAULT_PRIORITY, NULL, NULL));
115 content::ResourceRequestInfo::AllocateForTesting(
116 url_request_fail.get(),
117 content::RESOURCE_TYPE_MAIN_FRAME,
118 NULL,
119 -1,
120 -1,
121 -1,
122 false);
123 EXPECT_FALSE(attribute->IsFulfilled(WebRequestData(url_request_fail.get(),
124 ON_BEFORE_REQUEST)));
125 }
126
127 TEST(WebRequestConditionAttributeTest, ContentType) {
128 // Necessary for TestURLRequest.
129 base::MessageLoopForIO message_loop;
130
131 std::string error;
132 scoped_refptr<const WebRequestConditionAttribute> result;
133
134 net::test_server::EmbeddedTestServer test_server;
135 test_server.ServeFilesFromDirectory(TestDataPath(
136 "chrome/test/data/extensions/api_test/webrequest/declarative"));
137 ASSERT_TRUE(test_server.InitializeAndWaitUntilReady());
138
139 net::TestURLRequestContext context;
140 net::TestDelegate delegate;
141 scoped_ptr<net::URLRequest> url_request(
142 context.CreateRequest(test_server.GetURL("/headers.html"),
143 net::DEFAULT_PRIORITY,
144 &delegate,
145 NULL));
146 url_request->Start();
147 base::MessageLoop::current()->Run();
148
149 base::ListValue content_types;
150 content_types.Append(new base::StringValue("text/plain"));
151 scoped_refptr<const WebRequestConditionAttribute> attribute_include =
152 WebRequestConditionAttribute::Create(
153 keys::kContentTypeKey, &content_types, &error);
154 EXPECT_EQ("", error);
155 ASSERT_TRUE(attribute_include.get());
156 EXPECT_FALSE(attribute_include->IsFulfilled(
157 WebRequestData(url_request.get(), ON_BEFORE_REQUEST,
158 url_request->response_headers())));
159 EXPECT_TRUE(attribute_include->IsFulfilled(
160 WebRequestData(url_request.get(), ON_HEADERS_RECEIVED,
161 url_request->response_headers())));
162 EXPECT_EQ(std::string(keys::kContentTypeKey), attribute_include->GetName());
163
164 scoped_refptr<const WebRequestConditionAttribute> attribute_exclude =
165 WebRequestConditionAttribute::Create(
166 keys::kExcludeContentTypeKey, &content_types, &error);
167 EXPECT_EQ("", error);
168 ASSERT_TRUE(attribute_exclude.get());
169 EXPECT_FALSE(attribute_exclude->IsFulfilled(
170 WebRequestData(url_request.get(), ON_HEADERS_RECEIVED,
171 url_request->response_headers())));
172
173 content_types.Clear();
174 content_types.Append(new base::StringValue("something/invalid"));
175 scoped_refptr<const WebRequestConditionAttribute> attribute_unincluded =
176 WebRequestConditionAttribute::Create(
177 keys::kContentTypeKey, &content_types, &error);
178 EXPECT_EQ("", error);
179 ASSERT_TRUE(attribute_unincluded.get());
180 EXPECT_FALSE(attribute_unincluded->IsFulfilled(
181 WebRequestData(url_request.get(), ON_HEADERS_RECEIVED,
182 url_request->response_headers())));
183
184 scoped_refptr<const WebRequestConditionAttribute> attribute_unexcluded =
185 WebRequestConditionAttribute::Create(
186 keys::kExcludeContentTypeKey, &content_types, &error);
187 EXPECT_EQ("", error);
188 ASSERT_TRUE(attribute_unexcluded.get());
189 EXPECT_TRUE(attribute_unexcluded->IsFulfilled(
190 WebRequestData(url_request.get(), ON_HEADERS_RECEIVED,
191 url_request->response_headers())));
192 EXPECT_EQ(std::string(keys::kExcludeContentTypeKey),
193 attribute_unexcluded->GetName());
194 }
195
196 // Testing WebRequestConditionAttributeThirdParty.
197 TEST(WebRequestConditionAttributeTest, ThirdParty) {
198 // Necessary for TestURLRequest.
199 base::MessageLoopForIO message_loop;
200
201 std::string error;
202 const FundamentalValue value_true(true);
203 // This attribute matches only third party requests.
204 scoped_refptr<const WebRequestConditionAttribute> third_party_attribute =
205 WebRequestConditionAttribute::Create(keys::kThirdPartyKey,
206 &value_true,
207 &error);
208 ASSERT_EQ("", error);
209 ASSERT_TRUE(third_party_attribute.get());
210 EXPECT_EQ(std::string(keys::kThirdPartyKey),
211 third_party_attribute->GetName());
212 const FundamentalValue value_false(false);
213 // This attribute matches only first party requests.
214 scoped_refptr<const WebRequestConditionAttribute> first_party_attribute =
215 WebRequestConditionAttribute::Create(keys::kThirdPartyKey,
216 &value_false,
217 &error);
218 ASSERT_EQ("", error);
219 ASSERT_TRUE(first_party_attribute.get());
220 EXPECT_EQ(std::string(keys::kThirdPartyKey),
221 first_party_attribute->GetName());
222
223 const GURL url_empty;
224 const GURL url_a("http://a.com");
225 const GURL url_b("http://b.com");
226 net::TestURLRequestContext context;
227 net::TestDelegate delegate;
228 scoped_ptr<net::URLRequest> url_request(
229 context.CreateRequest(url_a, net::DEFAULT_PRIORITY, &delegate, NULL));
230
231 for (unsigned int i = 1; i <= kLastActiveStage; i <<= 1) {
232 if (!(kActiveStages & i))
233 continue;
234 const RequestStage stage = static_cast<RequestStage>(i);
235 url_request->set_first_party_for_cookies(url_empty);
236 EXPECT_FALSE(third_party_attribute->IsFulfilled(
237 WebRequestData(url_request.get(), stage)));
238 EXPECT_TRUE(first_party_attribute->IsFulfilled(
239 WebRequestData(url_request.get(), stage)));
240
241 url_request->set_first_party_for_cookies(url_b);
242 EXPECT_TRUE(third_party_attribute->IsFulfilled(
243 WebRequestData(url_request.get(), stage)));
244 EXPECT_FALSE(first_party_attribute->IsFulfilled(
245 WebRequestData(url_request.get(), stage)));
246
247 url_request->set_first_party_for_cookies(url_a);
248 EXPECT_FALSE(third_party_attribute->IsFulfilled(
249 WebRequestData(url_request.get(), stage)));
250 EXPECT_TRUE(first_party_attribute->IsFulfilled(
251 WebRequestData(url_request.get(), stage)));
252 }
253 }
254
255 // Testing WebRequestConditionAttributeStages. This iterates over all stages,
256 // and tests a couple of "stage" attributes -- one created with an empty set of
257 // applicable stages, one for each stage applicable for that stage, and one
258 // applicable in all stages.
259 TEST(WebRequestConditionAttributeTest, Stages) {
260 // Necessary for TestURLRequest.
261 base::MessageLoopForIO message_loop;
262
263 typedef std::pair<RequestStage, const char*> StageNamePair;
264 static const StageNamePair active_stages[] = {
265 StageNamePair(ON_BEFORE_REQUEST, keys::kOnBeforeRequestEnum),
266 StageNamePair(ON_BEFORE_SEND_HEADERS, keys::kOnBeforeSendHeadersEnum),
267 StageNamePair(ON_HEADERS_RECEIVED, keys::kOnHeadersReceivedEnum),
268 StageNamePair(ON_AUTH_REQUIRED, keys::kOnAuthRequiredEnum)
269 };
270
271 // Check that exactly all active stages are considered in this test.
272 unsigned int covered_stages = 0;
273 for (size_t i = 0; i < arraysize(active_stages); ++i)
274 covered_stages |= active_stages[i].first;
275 EXPECT_EQ(kActiveStages, covered_stages);
276
277 std::string error;
278
279 // Create an attribute with an empty set of applicable stages.
280 base::ListValue empty_list;
281 scoped_refptr<const WebRequestConditionAttribute> empty_attribute =
282 WebRequestConditionAttribute::Create(keys::kStagesKey,
283 &empty_list,
284 &error);
285 EXPECT_EQ("", error);
286 ASSERT_TRUE(empty_attribute.get());
287 EXPECT_EQ(std::string(keys::kStagesKey), empty_attribute->GetName());
288
289 // Create an attribute with all possible applicable stages.
290 base::ListValue all_stages;
291 for (size_t i = 0; i < arraysize(active_stages); ++i)
292 all_stages.AppendString(active_stages[i].second);
293 scoped_refptr<const WebRequestConditionAttribute> attribute_with_all =
294 WebRequestConditionAttribute::Create(keys::kStagesKey,
295 &all_stages,
296 &error);
297 EXPECT_EQ("", error);
298 ASSERT_TRUE(attribute_with_all.get());
299 EXPECT_EQ(std::string(keys::kStagesKey), attribute_with_all->GetName());
300
301 // Create one attribute for each single stage, to be applicable in that stage.
302 std::vector<scoped_refptr<const WebRequestConditionAttribute> >
303 one_stage_attributes;
304
305 for (size_t i = 0; i < arraysize(active_stages); ++i) {
306 base::ListValue single_stage_list;
307 single_stage_list.AppendString(active_stages[i].second);
308 one_stage_attributes.push_back(
309 WebRequestConditionAttribute::Create(keys::kStagesKey,
310 &single_stage_list,
311 &error));
312 EXPECT_EQ("", error);
313 ASSERT_TRUE(one_stage_attributes.back().get() != NULL);
314 }
315
316 const GURL url_empty;
317 net::TestURLRequestContext context;
318 net::TestDelegate delegate;
319 scoped_ptr<net::URLRequest> url_request(
320 context.CreateRequest(url_empty, net::DEFAULT_PRIORITY, &delegate, NULL));
321
322 for (size_t i = 0; i < arraysize(active_stages); ++i) {
323 EXPECT_FALSE(empty_attribute->IsFulfilled(
324 WebRequestData(url_request.get(), active_stages[i].first)));
325
326 for (size_t j = 0; j < one_stage_attributes.size(); ++j) {
327 EXPECT_EQ(i == j,
328 one_stage_attributes[j]->IsFulfilled(
329 WebRequestData(url_request.get(), active_stages[i].first)));
330 }
331
332 EXPECT_TRUE(attribute_with_all->IsFulfilled(
333 WebRequestData(url_request.get(), active_stages[i].first)));
334 }
335 }
336
337 namespace {
338
339 // Builds a vector of vectors of string pointers from an array of strings.
340 // |array| is in fact a sequence of arrays. The array |sizes| captures the sizes
341 // of all parts of |array|, and |size| is the length of |sizes| itself.
342 // Example (this is pseudo-code, not C++):
343 // array = { "a", "b", "c", "d", "e", "f" }
344 // sizes = { 2, 0, 4 }
345 // size = 3
346 // results in out == { {&"a", &"b"}, {}, {&"c", &"d", &"e", &"f"} }
347 void GetArrayAsVector(const std::string array[],
348 const size_t sizes[],
349 const size_t size,
350 std::vector< std::vector<const std::string*> >* out) {
351 out->clear();
352 size_t next = 0;
353 for (size_t i = 0; i < size; ++i) {
354 out->push_back(std::vector<const std::string*>());
355 for (size_t j = next; j < next + sizes[i]; ++j) {
356 out->back().push_back(&(array[j]));
357 }
358 next += sizes[i];
359 }
360 }
361
362 // Builds a DictionaryValue from an array of the form {name1, value1, name2,
363 // value2, ...}. Values for the same key are grouped in a ListValue.
364 scoped_ptr<base::DictionaryValue> GetDictionaryFromArray(
365 const std::vector<const std::string*>& array) {
366 const size_t length = array.size();
367 CHECK(length % 2 == 0);
368
369 scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue);
370 for (size_t i = 0; i < length; i += 2) {
371 const std::string* name = array[i];
372 const std::string* value = array[i+1];
373 if (dictionary->HasKey(*name)) {
374 base::Value* entry = NULL;
375 scoped_ptr<base::Value> entry_owned;
376 base::ListValue* list = NULL;
377 if (!dictionary->GetWithoutPathExpansion(*name, &entry))
378 return scoped_ptr<base::DictionaryValue>();
379 switch (entry->GetType()) {
380 case base::Value::TYPE_STRING:
381 // Replace the present string with a list.
382 list = new base::ListValue;
383 // Ignoring return value, we already verified the entry is there.
384 dictionary->RemoveWithoutPathExpansion(*name, &entry_owned);
385 list->Append(entry_owned.release());
386 list->Append(new base::StringValue(*value));
387 dictionary->SetWithoutPathExpansion(*name, list);
388 break;
389 case base::Value::TYPE_LIST: // Just append to the list.
390 CHECK(entry->GetAsList(&list));
391 list->Append(new base::StringValue(*value));
392 break;
393 default:
394 NOTREACHED(); // We never put other Values here.
395 return scoped_ptr<base::DictionaryValue>();
396 }
397 } else {
398 dictionary->SetString(*name, *value);
399 }
400 }
401 return dictionary.Pass();
402 }
403
404 // Returns whether the response headers from |url_request| satisfy the match
405 // criteria given in |tests|. For at least one |i| all tests from |tests[i]|
406 // must pass. If |positive_test| is true, the dictionary is interpreted as the
407 // containsHeaders property of a RequestMatcher, otherwise as
408 // doesNotContainHeaders.
409 void MatchAndCheck(const std::vector< std::vector<const std::string*> >& tests,
410 const std::string& key,
411 RequestStage stage,
412 net::URLRequest* url_request,
413 bool* result) {
414 base::ListValue contains_headers;
415 for (size_t i = 0; i < tests.size(); ++i) {
416 scoped_ptr<base::DictionaryValue> temp(GetDictionaryFromArray(tests[i]));
417 ASSERT_TRUE(temp.get());
418 contains_headers.Append(temp.release());
419 }
420
421 std::string error;
422 scoped_refptr<const WebRequestConditionAttribute> attribute =
423 WebRequestConditionAttribute::Create(key, &contains_headers, &error);
424 ASSERT_EQ("", error);
425 ASSERT_TRUE(attribute.get());
426 EXPECT_EQ(key, attribute->GetName());
427
428 *result = attribute->IsFulfilled(WebRequestData(
429 url_request, stage, url_request->response_headers()));
430 }
431
432 } // namespace
433
434 // Here we test WebRequestConditionAttributeRequestHeaders for matching
435 // correctly against request headers. This test is not as extensive as
436 // "ResponseHeaders" (below), because the header-matching code is shared
437 // by both types of condition attributes, so it is enough to test it once.
438 TEST(WebRequestConditionAttributeTest, RequestHeaders) {
439 // Necessary for TestURLRequest.
440 base::MessageLoopForIO message_loop;
441
442 net::TestURLRequestContext context;
443 net::TestDelegate delegate;
444 scoped_ptr<net::URLRequest> url_request(
445 context.CreateRequest(GURL("http://example.com"), // Dummy URL.
446 net::DEFAULT_PRIORITY,
447 &delegate,
448 NULL));
449 url_request->SetExtraRequestHeaderByName(
450 "Custom-header", "custom/value", true /* overwrite */);
451 url_request->Start();
452 base::MessageLoop::current()->Run();
453
454 std::vector<std::vector<const std::string*> > tests;
455 bool result = false;
456
457 const RequestStage stage = ON_BEFORE_SEND_HEADERS;
458
459 // First set of test data -- passing conjunction.
460 const std::string kPassingCondition[] = {
461 keys::kNameContainsKey, "CuStOm", // Header names are case insensitive.
462 keys::kNameEqualsKey, "custom-header",
463 keys::kValueSuffixKey, "alue",
464 keys::kValuePrefixKey, "custom/value"
465 };
466 const size_t kPassingConditionSizes[] = { arraysize(kPassingCondition) };
467 GetArrayAsVector(kPassingCondition, kPassingConditionSizes, 1u, &tests);
468 // Positive filter, passing (conjunction of tests).
469 MatchAndCheck(
470 tests, keys::kRequestHeadersKey, stage, url_request.get(), &result);
471 EXPECT_TRUE(result);
472 // Negative filter, failing (conjunction of tests).
473 MatchAndCheck(tests, keys::kExcludeRequestHeadersKey, stage,
474 url_request.get(), &result);
475 EXPECT_FALSE(result);
476
477 // Second set of test data -- failing disjunction.
478 const std::string kFailCondition[] = {
479 keys::kNameSuffixKey, "Custom", // Test 1.
480 keys::kNameEqualsKey, "ustom-valu", // Test 2.
481 keys::kValuePrefixKey, "custom ", // Test 3.
482 keys::kValueContainsKey, " value" // Test 4.
483 };
484 const size_t kFailConditionSizes[] = { 2u, 2u, 2u, 2u };
485 GetArrayAsVector(kFailCondition, kFailConditionSizes, 4u, &tests);
486 // Positive filter, failing (disjunction of tests).
487 MatchAndCheck(tests, keys::kRequestHeadersKey, stage, url_request.get(),
488 &result);
489 EXPECT_FALSE(result);
490 // Negative filter, passing (disjunction of tests).
491 MatchAndCheck(tests, keys::kExcludeRequestHeadersKey, stage,
492 url_request.get(), &result);
493 EXPECT_TRUE(result);
494
495 // Third set of test data, corner case -- empty disjunction.
496 GetArrayAsVector(NULL, NULL, 0u, &tests);
497 // Positive filter, failing (no test to pass).
498 MatchAndCheck(tests, keys::kRequestHeadersKey, stage, url_request.get(),
499 &result);
500 EXPECT_FALSE(result);
501 // Negative filter, passing (no test to fail).
502 MatchAndCheck(tests, keys::kExcludeRequestHeadersKey, stage,
503 url_request.get(), &result);
504 EXPECT_TRUE(result);
505
506 // Fourth set of test data, corner case -- empty conjunction.
507 const size_t kEmptyConjunctionSizes[] = { 0u };
508 GetArrayAsVector(NULL, kEmptyConjunctionSizes, 1u, &tests);
509 // Positive filter, passing (trivial test).
510 MatchAndCheck(tests, keys::kRequestHeadersKey, stage, url_request.get(),
511 &result);
512 EXPECT_TRUE(result);
513 // Negative filter, failing.
514 MatchAndCheck(tests, keys::kExcludeRequestHeadersKey, stage,
515 url_request.get(), &result);
516 EXPECT_FALSE(result);
517 }
518
519 // Here we test WebRequestConditionAttributeResponseHeaders for:
520 // 1. Correct implementation of prefix/suffix/contains/equals matching.
521 // 2. Performing logical disjunction (||) between multiple specifications.
522 // 3. Negating the match in case of 'doesNotContainHeaders'.
523 TEST(WebRequestConditionAttributeTest, ResponseHeaders) {
524 // Necessary for TestURLRequest.
525 base::MessageLoopForIO message_loop;
526
527 net::test_server::EmbeddedTestServer test_server;
528 test_server.ServeFilesFromDirectory(TestDataPath(
529 "chrome/test/data/extensions/api_test/webrequest/declarative"));
530 ASSERT_TRUE(test_server.InitializeAndWaitUntilReady());
531
532 net::TestURLRequestContext context;
533 net::TestDelegate delegate;
534 scoped_ptr<net::URLRequest> url_request(
535 context.CreateRequest(test_server.GetURL("/headers.html"),
536 net::DEFAULT_PRIORITY,
537 &delegate,
538 NULL));
539 url_request->Start();
540 base::MessageLoop::current()->Run();
541
542 // In all the tests below we assume that the server includes the headers
543 // Custom-Header: custom/value
544 // Custom-Header-B: valueA
545 // Custom-Header-B: valueB
546 // Custom-Header-C: valueC, valueD
547 // Custom-Header-D:
548 // in the response, but does not include "Non-existing: void".
549
550 std::vector< std::vector<const std::string*> > tests;
551 bool result;
552
553 const RequestStage stage = ON_HEADERS_RECEIVED;
554
555 // 1.a. -- All these tests should pass.
556 const std::string kPassingCondition[] = {
557 keys::kNamePrefixKey, "Custom",
558 keys::kNameSuffixKey, "m-header", // Header names are case insensitive.
559 keys::kValueContainsKey, "alu",
560 keys::kValueEqualsKey, "custom/value"
561 };
562 const size_t kPassingConditionSizes[] = { arraysize(kPassingCondition) };
563 GetArrayAsVector(kPassingCondition, kPassingConditionSizes, 1u, &tests);
564 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
565 &result);
566 EXPECT_TRUE(result);
567
568 // 1.b. -- None of the following tests in the discjunction should pass.
569 const std::string kFailCondition[] = {
570 keys::kNamePrefixKey, " Custom", // Test 1.
571 keys::kNameContainsKey, " -", // Test 2.
572 keys::kValueSuffixKey, "alu", // Test 3.
573 keys::kValueEqualsKey, "custom" // Test 4.
574 };
575 const size_t kFailConditionSizes[] = { 2u, 2u, 2u, 2u };
576 GetArrayAsVector(kFailCondition, kFailConditionSizes, 4u, &tests);
577 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
578 &result);
579 EXPECT_FALSE(result);
580
581 // 1.c. -- This should fail (mixing name and value from different headers)
582 const std::string kMixingCondition[] = {
583 keys::kNameSuffixKey, "Header-B",
584 keys::kValueEqualsKey, "custom/value"
585 };
586 const size_t kMixingConditionSizes[] = { arraysize(kMixingCondition) };
587 GetArrayAsVector(kMixingCondition, kMixingConditionSizes, 1u, &tests);
588 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
589 &result);
590 EXPECT_FALSE(result);
591
592 // 1.d. -- Test handling multiple values for one header (both should pass).
593 const std::string kMoreValues1[] = {
594 keys::kNameEqualsKey, "Custom-header-b",
595 keys::kValueEqualsKey, "valueA"
596 };
597 const size_t kMoreValues1Sizes[] = { arraysize(kMoreValues1) };
598 GetArrayAsVector(kMoreValues1, kMoreValues1Sizes, 1u, &tests);
599 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
600 &result);
601 EXPECT_TRUE(result);
602 const std::string kMoreValues2[] = {
603 keys::kNameEqualsKey, "Custom-header-b",
604 keys::kValueEqualsKey, "valueB"
605 };
606 const size_t kMoreValues2Sizes[] = { arraysize(kMoreValues2) };
607 GetArrayAsVector(kMoreValues2, kMoreValues2Sizes, 1u, &tests);
608 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
609 &result);
610 EXPECT_TRUE(result);
611
612 // 1.e. -- This should fail as conjunction but pass as disjunction.
613 const std::string kConflict[] = {
614 keys::kNameSuffixKey, "Header", // True for some header.
615 keys::kNameContainsKey, "Header-B" // True for a different header.
616 };
617 // First disjunction, no conflict.
618 const size_t kNoConflictSizes[] = { 2u, 2u };
619 GetArrayAsVector(kConflict, kNoConflictSizes, 2u, &tests);
620 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
621 &result);
622 EXPECT_TRUE(result);
623 // Then conjunction, conflict.
624 const size_t kConflictSizes[] = { arraysize(kConflict) };
625 GetArrayAsVector(kConflict, kConflictSizes, 1u, &tests);
626 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
627 &result);
628 EXPECT_FALSE(result);
629
630 // 1.f. -- This should pass, checking for correct treatment of ',' in values.
631 const std::string kComma[] = {
632 keys::kNameSuffixKey, "Header-C",
633 keys::kValueEqualsKey, "valueC, valueD"
634 };
635 const size_t kCommaSizes[] = { arraysize(kComma) };
636 GetArrayAsVector(kComma, kCommaSizes, 1u, &tests);
637 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
638 &result);
639 EXPECT_TRUE(result);
640
641 // 1.g. -- This should pass, empty values are values as well.
642 const std::string kEmpty[] = {
643 keys::kNameEqualsKey, "custom-header-d",
644 keys::kValueEqualsKey, ""
645 };
646 const size_t kEmptySizes[] = { arraysize(kEmpty) };
647 GetArrayAsVector(kEmpty, kEmptySizes, 1u, &tests);
648 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
649 &result);
650 EXPECT_TRUE(result);
651
652 // 1.h. -- Values are case-sensitive, this should fail.
653 const std::string kLowercase[] = {
654 keys::kNameEqualsKey, "Custom-header-b",
655 keys::kValuePrefixKey, "valueb", // valueb != valueB
656 keys::kNameEqualsKey, "Custom-header-b",
657 keys::kValueSuffixKey, "valueb",
658 keys::kNameEqualsKey, "Custom-header-b",
659 keys::kValueContainsKey, "valueb",
660 keys::kNameEqualsKey, "Custom-header-b",
661 keys::kValueEqualsKey, "valueb"
662 };
663 const size_t kLowercaseSizes[] = { 4u, 4u, 4u, 4u }; // As disjunction.
664 GetArrayAsVector(kLowercase, kLowercaseSizes, 4u, &tests);
665 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
666 &result);
667 EXPECT_FALSE(result);
668
669 // 1.i. -- Names are case-insensitive, this should pass.
670 const std::string kUppercase[] = {
671 keys::kNamePrefixKey, "CUSTOM-HEADER-B",
672 keys::kNameSuffixKey, "CUSTOM-HEADER-B",
673 keys::kNameEqualsKey, "CUSTOM-HEADER-B",
674 keys::kNameContainsKey, "CUSTOM-HEADER-B"
675 };
676 const size_t kUppercaseSizes[] = { arraysize(kUppercase) }; // Conjunction.
677 GetArrayAsVector(kUppercase, kUppercaseSizes, 1u, &tests);
678 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
679 &result);
680 EXPECT_TRUE(result);
681
682 // 2.a. -- This should pass as disjunction, because one of the tests passes.
683 const std::string kDisjunction[] = {
684 keys::kNamePrefixKey, "Non-existing", // This one fails.
685 keys::kNameSuffixKey, "Non-existing", // This one fails.
686 keys::kValueEqualsKey, "void", // This one fails.
687 keys::kValueContainsKey, "alu" // This passes.
688 };
689 const size_t kDisjunctionSizes[] = { 2u, 2u, 2u, 2u };
690 GetArrayAsVector(kDisjunction, kDisjunctionSizes, 4u, &tests);
691 MatchAndCheck(tests, keys::kResponseHeadersKey, stage, url_request.get(),
692 &result);
693 EXPECT_TRUE(result);
694
695 // 3.a. -- This should pass.
696 const std::string kNonExistent[] = {
697 keys::kNameEqualsKey, "Non-existing",
698 keys::kValueEqualsKey, "void"
699 };
700 const size_t kNonExistentSizes[] = { arraysize(kNonExistent) };
701 GetArrayAsVector(kNonExistent, kNonExistentSizes, 1u, &tests);
702 MatchAndCheck(tests, keys::kExcludeResponseHeadersKey, stage,
703 url_request.get(), &result);
704 EXPECT_TRUE(result);
705
706 // 3.b. -- This should fail.
707 const std::string kExisting[] = {
708 keys::kNameEqualsKey, "custom-header-b",
709 keys::kValueEqualsKey, "valueB"
710 };
711 const size_t kExistingSize[] = { arraysize(kExisting) };
712 GetArrayAsVector(kExisting, kExistingSize, 1u, &tests);
713 MatchAndCheck(tests, keys::kExcludeResponseHeadersKey, stage,
714 url_request.get(), &result);
715 EXPECT_FALSE(result);
716 }
717
718 } // namespace
719 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698