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.
8 #include "base/basictypes.h"
10 #include "base/callback.h"
11 #include "base/files/file_path.h"
12 #include "base/json/json_reader.h"
13 #include "base/json/json_string_value_serializer.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/path_service.h"
17 #include "base/prefs/pref_member.h"
18 #include "base/stl_util.h"
19 #include "base/strings/string_piece.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/time/time.h"
23 #include "chrome/browser/content_settings/cookie_settings.h"
24 #include "chrome/browser/extensions/api/web_request/upload_data_presenter.h"
25 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
26 #include "chrome/browser/extensions/api/web_request/web_request_api_constants.h"
27 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
28 #include "chrome/browser/extensions/event_router_forwarder.h"
29 #include "chrome/browser/extensions/extension_warning_set.h"
30 #include "chrome/browser/net/about_protocol_handler.h"
31 #include "chrome/browser/net/chrome_network_delegate.h"
32 #include "chrome/common/extensions/api/web_request.h"
33 #include "chrome/common/pref_names.h"
34 #include "chrome/test/base/testing_browser_process.h"
35 #include "chrome/test/base/testing_pref_service_syncable.h"
36 #include "chrome/test/base/testing_profile.h"
37 #include "chrome/test/base/testing_profile_manager.h"
38 #include "content/public/common/url_constants.h"
39 #include "content/public/test/test_browser_thread_bundle.h"
40 #include "extensions/common/extension_messages.h"
41 #include "extensions/common/features/feature.h"
42 #include "net/base/auth.h"
43 #include "net/base/capturing_net_log.h"
44 #include "net/base/net_util.h"
45 #include "net/base/request_priority.h"
46 #include "net/base/upload_bytes_element_reader.h"
47 #include "net/base/upload_data_stream.h"
48 #include "net/base/upload_file_element_reader.h"
49 #include "net/dns/mock_host_resolver.h"
50 #include "net/url_request/url_request_job_factory_impl.h"
51 #include "net/url_request/url_request_test_util.h"
52 #include "testing/gtest/include/gtest/gtest-message.h"
53 #include "testing/gtest/include/gtest/gtest.h"
55 namespace helpers
= extension_web_request_api_helpers
;
56 namespace keys
= extension_web_request_api_constants
;
57 namespace web_request
= extensions::api::web_request
;
59 using base::BinaryValue
;
60 using base::DictionaryValue
;
61 using base::ListValue
;
62 using base::StringValue
;
64 using base::TimeDelta
;
66 using helpers::CalculateOnAuthRequiredDelta
;
67 using helpers::CalculateOnBeforeRequestDelta
;
68 using helpers::CalculateOnBeforeSendHeadersDelta
;
69 using helpers::CalculateOnHeadersReceivedDelta
;
70 using helpers::CharListToString
;
71 using helpers::EventResponseDelta
;
72 using helpers::EventResponseDeltas
;
73 using helpers::EventResponseDeltas
;
74 using helpers::InDecreasingExtensionInstallationTimeOrder
;
75 using helpers::MergeCancelOfResponses
;
76 using helpers::MergeOnBeforeRequestResponses
;
77 using helpers::RequestCookieModification
;
78 using helpers::ResponseCookieModification
;
79 using helpers::ResponseHeader
;
80 using helpers::ResponseHeaders
;
81 using helpers::StringToCharList
;
83 namespace extensions
{
86 static void EventHandledOnIOThread(
88 const std::string
& extension_id
,
89 const std::string
& event_name
,
90 const std::string
& sub_event_name
,
92 ExtensionWebRequestEventRouter::EventResponse
* response
) {
93 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
94 profile
, extension_id
, event_name
, sub_event_name
, request_id
,
98 // Searches |key| in |collection| by iterating over its elements and returns
100 template <typename Collection
, typename Key
>
101 bool Contains(const Collection
& collection
, const Key
& key
) {
102 return std::find(collection
.begin(), collection
.end(), key
) !=
106 // Returns whether |warnings| contains an extension for |extension_id|.
107 bool HasWarning(const ExtensionWarningSet
& warnings
,
108 const std::string
& extension_id
) {
109 for (ExtensionWarningSet::const_iterator i
= warnings
.begin();
110 i
!= warnings
.end(); ++i
) {
111 if (i
->extension_id() == extension_id
)
117 // Parses the JSON data attached to the |message| and tries to return it.
118 // |param| must outlive |out|. Returns NULL on failure.
119 void GetPartOfMessageArguments(IPC::Message
* message
,
120 const base::DictionaryValue
** out
,
121 ExtensionMsg_MessageInvoke::Param
* param
) {
122 ASSERT_EQ(ExtensionMsg_MessageInvoke::ID
, message
->type());
123 ASSERT_TRUE(ExtensionMsg_MessageInvoke::Read(message
, param
));
124 ASSERT_GE(param
->d
.GetSize(), 2u);
125 const base::Value
* value
= NULL
;
126 ASSERT_TRUE(param
->d
.Get(1, &value
));
127 const base::ListValue
* list
= NULL
;
128 ASSERT_TRUE(value
->GetAsList(&list
));
129 ASSERT_EQ(1u, list
->GetSize());
130 ASSERT_TRUE(list
->GetDictionary(0, out
));
135 // A mock event router that responds to events with a pre-arranged queue of
137 class TestIPCSender
: public IPC::Sender
{
139 typedef std::list
<linked_ptr
<IPC::Message
> > SentMessages
;
141 // Adds a Task to the queue. We will fire these in order as events are
143 void PushTask(const base::Closure
& task
) {
144 task_queue_
.push(task
);
147 size_t GetNumTasks() { return task_queue_
.size(); }
149 SentMessages::const_iterator
sent_begin() const {
150 return sent_messages_
.begin();
153 SentMessages::const_iterator
sent_end() const {
154 return sent_messages_
.end();
159 virtual bool Send(IPC::Message
* message
) OVERRIDE
{
160 EXPECT_EQ(ExtensionMsg_MessageInvoke::ID
, message
->type());
162 EXPECT_FALSE(task_queue_
.empty());
163 base::MessageLoop::current()->PostTask(FROM_HERE
, task_queue_
.front());
166 sent_messages_
.push_back(linked_ptr
<IPC::Message
>(message
));
170 std::queue
<base::Closure
> task_queue_
;
171 SentMessages sent_messages_
;
174 class ExtensionWebRequestTest
: public testing::Test
{
176 ExtensionWebRequestTest()
177 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
178 profile_manager_(TestingBrowserProcess::GetGlobal()),
179 event_router_(new EventRouterForwarder
) {}
182 virtual void SetUp() OVERRIDE
{
183 ASSERT_TRUE(profile_manager_
.SetUp());
184 ChromeNetworkDelegate::InitializePrefsOnUIThread(
185 &enable_referrers_
, NULL
, NULL
, profile_
.GetTestingPrefService());
186 network_delegate_
.reset(
187 new ChromeNetworkDelegate(event_router_
.get(), &enable_referrers_
));
188 network_delegate_
->set_profile(&profile_
);
189 network_delegate_
->set_cookie_settings(
190 CookieSettings::Factory::GetForProfile(&profile_
).get());
191 context_
.reset(new net::TestURLRequestContext(true));
192 context_
->set_network_delegate(network_delegate_
.get());
196 // Fires a URLRequest with the specified |method|, |content_type| and three
197 // elements of upload data: bytes_1, a dummy empty file, bytes_2.
198 void FireURLRequestWithData(const std::string
& method
,
199 const char* content_type
,
200 const std::vector
<char>& bytes_1
,
201 const std::vector
<char>& bytes_2
);
203 content::TestBrowserThreadBundle thread_bundle_
;
204 TestingProfile profile_
;
205 TestingProfileManager profile_manager_
;
206 net::TestDelegate delegate_
;
207 BooleanPrefMember enable_referrers_
;
208 TestIPCSender ipc_sender_
;
209 scoped_refptr
<EventRouterForwarder
> event_router_
;
210 scoped_refptr
<InfoMap
> extension_info_map_
;
211 scoped_ptr
<ChromeNetworkDelegate
> network_delegate_
;
212 scoped_ptr
<net::TestURLRequestContext
> context_
;
215 // Tests that we handle disagreements among extensions about responses to
216 // blocking events (redirection) by choosing the response from the
217 // most-recently-installed extension.
218 TEST_F(ExtensionWebRequestTest
, BlockingEventPrecedenceRedirect
) {
219 std::string
extension1_id("1");
220 std::string
extension2_id("2");
221 ExtensionWebRequestEventRouter::RequestFilter filter
;
222 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
223 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
224 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
225 &profile_
, extension1_id
, extension1_id
, kEventName
, kEventName
+ "/1",
226 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, -1, -1,
227 ipc_sender_factory
.GetWeakPtr());
228 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
229 &profile_
, extension2_id
, extension2_id
, kEventName
, kEventName
+ "/2",
230 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, -1, -1,
231 ipc_sender_factory
.GetWeakPtr());
233 net::URLRequestJobFactoryImpl job_factory
;
234 job_factory
.SetProtocolHandler(
235 content::kAboutScheme
, new chrome_browser_net::AboutProtocolHandler());
236 context_
->set_job_factory(&job_factory
);
238 GURL
redirect_url("about:redirected");
239 GURL
not_chosen_redirect_url("about:not_chosen");
241 net::URLRequest
request(
242 GURL("about:blank"), net::DEFAULT_PRIORITY
, &delegate_
, context_
.get());
244 // onBeforeRequest will be dispatched twice initially. The second response -
245 // the redirect - should win, since it has a later |install_time|. The
246 // redirect will dispatch another pair of onBeforeRequest. There, the first
247 // response should win (later |install_time|).
248 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
250 // Extension1 response. Arrives first, but ignored due to install_time.
251 response
= new ExtensionWebRequestEventRouter::EventResponse(
252 extension1_id
, base::Time::FromDoubleT(1));
253 response
->new_url
= not_chosen_redirect_url
;
254 ipc_sender_
.PushTask(
255 base::Bind(&EventHandledOnIOThread
,
256 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
257 request
.identifier(), response
));
259 // Extension2 response. Arrives second, and chosen because of install_time.
260 response
= new ExtensionWebRequestEventRouter::EventResponse(
261 extension2_id
, base::Time::FromDoubleT(2));
262 response
->new_url
= redirect_url
;
263 ipc_sender_
.PushTask(
264 base::Bind(&EventHandledOnIOThread
,
265 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
266 request
.identifier(), response
));
268 // Extension2 response to the redirected URL. Arrives first, and chosen.
269 response
= new ExtensionWebRequestEventRouter::EventResponse(
270 extension2_id
, base::Time::FromDoubleT(2));
271 ipc_sender_
.PushTask(
272 base::Bind(&EventHandledOnIOThread
,
273 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
274 request
.identifier(), response
));
276 // Extension1 response to the redirected URL. Arrives second, and ignored.
277 response
= new ExtensionWebRequestEventRouter::EventResponse(
278 extension1_id
, base::Time::FromDoubleT(1));
279 ipc_sender_
.PushTask(
280 base::Bind(&EventHandledOnIOThread
,
281 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
282 request
.identifier(), response
));
285 base::MessageLoop::current()->Run();
287 EXPECT_TRUE(!request
.is_pending());
288 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, request
.status().status());
289 EXPECT_EQ(0, request
.status().error());
290 EXPECT_EQ(redirect_url
, request
.url());
291 EXPECT_EQ(2U, request
.url_chain().size());
292 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
295 // Now test the same thing but the extensions answer in reverse order.
296 net::URLRequest
request2(
297 GURL("about:blank"), net::DEFAULT_PRIORITY
, &delegate_
, context_
.get());
299 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
301 // Extension2 response. Arrives first, and chosen because of install_time.
302 response
= new ExtensionWebRequestEventRouter::EventResponse(
303 extension2_id
, base::Time::FromDoubleT(2));
304 response
->new_url
= redirect_url
;
305 ipc_sender_
.PushTask(
306 base::Bind(&EventHandledOnIOThread
,
307 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
308 request2
.identifier(), response
));
310 // Extension1 response. Arrives second, but ignored due to install_time.
311 response
= new ExtensionWebRequestEventRouter::EventResponse(
312 extension1_id
, base::Time::FromDoubleT(1));
313 response
->new_url
= not_chosen_redirect_url
;
314 ipc_sender_
.PushTask(
315 base::Bind(&EventHandledOnIOThread
,
316 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
317 request2
.identifier(), response
));
319 // Extension2 response to the redirected URL. Arrives first, and chosen.
320 response
= new ExtensionWebRequestEventRouter::EventResponse(
321 extension2_id
, base::Time::FromDoubleT(2));
322 ipc_sender_
.PushTask(
323 base::Bind(&EventHandledOnIOThread
,
324 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
325 request2
.identifier(), response
));
327 // Extension1 response to the redirected URL. Arrives second, and ignored.
328 response
= new ExtensionWebRequestEventRouter::EventResponse(
329 extension1_id
, base::Time::FromDoubleT(1));
330 ipc_sender_
.PushTask(
331 base::Bind(&EventHandledOnIOThread
,
332 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
333 request2
.identifier(), response
));
336 base::MessageLoop::current()->Run();
338 EXPECT_TRUE(!request2
.is_pending());
339 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, request2
.status().status());
340 EXPECT_EQ(0, request2
.status().error());
341 EXPECT_EQ(redirect_url
, request2
.url());
342 EXPECT_EQ(2U, request2
.url_chain().size());
343 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
346 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
347 &profile_
, extension1_id
, kEventName
+ "/1");
348 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
349 &profile_
, extension2_id
, kEventName
+ "/2");
352 // Test that a request is canceled if this is requested by any extension
353 // regardless whether it is the extension with the highest precedence.
354 TEST_F(ExtensionWebRequestTest
, BlockingEventPrecedenceCancel
) {
355 std::string
extension1_id("1");
356 std::string
extension2_id("2");
357 ExtensionWebRequestEventRouter::RequestFilter filter
;
358 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
359 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
360 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
361 &profile_
, extension1_id
, extension1_id
, kEventName
, kEventName
+ "/1",
362 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, -1, -1,
363 ipc_sender_factory
.GetWeakPtr());
364 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
365 &profile_
, extension2_id
, extension2_id
, kEventName
, kEventName
+ "/2",
366 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, -1, -1,
367 ipc_sender_factory
.GetWeakPtr());
369 GURL
request_url("about:blank");
370 net::URLRequest
request(
371 request_url
, net::DEFAULT_PRIORITY
, &delegate_
, context_
.get());
373 // onBeforeRequest will be dispatched twice. The second response -
374 // the redirect - would win, since it has a later |install_time|, but
375 // the first response takes precedence because cancel >> redirect.
376 GURL
redirect_url("about:redirected");
377 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
379 // Extension1 response. Arrives first, would be ignored in principle due to
380 // install_time but "cancel" always wins.
381 response
= new ExtensionWebRequestEventRouter::EventResponse(
382 extension1_id
, base::Time::FromDoubleT(1));
383 response
->cancel
= true;
384 ipc_sender_
.PushTask(
385 base::Bind(&EventHandledOnIOThread
,
386 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
387 request
.identifier(), response
));
389 // Extension2 response. Arrives second, but has higher precedence
390 // due to its later install_time.
391 response
= new ExtensionWebRequestEventRouter::EventResponse(
392 extension2_id
, base::Time::FromDoubleT(2));
393 response
->new_url
= redirect_url
;
394 ipc_sender_
.PushTask(
395 base::Bind(&EventHandledOnIOThread
,
396 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
397 request
.identifier(), response
));
401 base::MessageLoop::current()->Run();
403 EXPECT_TRUE(!request
.is_pending());
404 EXPECT_EQ(net::URLRequestStatus::FAILED
, request
.status().status());
405 EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT
, request
.status().error());
406 EXPECT_EQ(request_url
, request
.url());
407 EXPECT_EQ(1U, request
.url_chain().size());
408 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
410 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
411 &profile_
, extension1_id
, kEventName
+ "/1");
412 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
413 &profile_
, extension2_id
, kEventName
+ "/2");
416 TEST_F(ExtensionWebRequestTest
, SimulateChancelWhileBlocked
) {
417 // We subscribe to OnBeforeRequest and OnErrorOccurred.
418 // While the OnBeforeRequest handler is blocked, we cancel the request.
419 // We verify that the response of the blocked OnBeforeRequest handler
422 std::string
extension_id("1");
423 ExtensionWebRequestEventRouter::RequestFilter filter
;
425 // Subscribe to OnBeforeRequest and OnErrorOccurred.
426 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
427 const std::string
kEventName2(web_request::OnErrorOccurred::kEventName
);
428 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
429 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
430 &profile_
, extension_id
, extension_id
, kEventName
, kEventName
+ "/1",
431 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, -1, -1,
432 ipc_sender_factory
.GetWeakPtr());
433 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
434 &profile_
, extension_id
, extension_id
, kEventName2
, kEventName2
+ "/1",
435 filter
, 0, -1, -1, ipc_sender_factory
.GetWeakPtr());
437 GURL
request_url("about:blank");
438 net::URLRequest
request(
439 request_url
, net::DEFAULT_PRIORITY
, &delegate_
, context_
.get());
441 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
443 // Extension response for the OnBeforeRequest handler. This should not be
444 // processed because request is canceled before the handler responds.
445 response
= new ExtensionWebRequestEventRouter::EventResponse(
446 extension_id
, base::Time::FromDoubleT(1));
447 GURL
redirect_url("about:redirected");
448 response
->new_url
= redirect_url
;
449 ipc_sender_
.PushTask(
450 base::Bind(&EventHandledOnIOThread
,
451 &profile_
, extension_id
, kEventName
, kEventName
+ "/1",
452 request
.identifier(), response
));
454 // Extension response for OnErrorOccurred: Terminate the message loop.
455 ipc_sender_
.PushTask(
456 base::Bind(&base::MessageLoop::PostTask
,
457 base::Unretained(base::MessageLoop::current()),
458 FROM_HERE
, base::MessageLoop::QuitClosure()));
461 // request.Start() will have submitted OnBeforeRequest by the time we cancel.
463 base::MessageLoop::current()->Run();
465 EXPECT_TRUE(!request
.is_pending());
466 EXPECT_EQ(net::URLRequestStatus::CANCELED
, request
.status().status());
467 EXPECT_EQ(net::ERR_ABORTED
, request
.status().error());
468 EXPECT_EQ(request_url
, request
.url());
469 EXPECT_EQ(1U, request
.url_chain().size());
470 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
472 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
473 &profile_
, extension_id
, kEventName
+ "/1");
474 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
475 &profile_
, extension_id
, kEventName2
+ "/1");
480 // Create the numerical representation of |values|, strings passed as
481 // extraInfoSpec by the event handler. Returns true on success, otherwise false.
482 bool GenerateInfoSpec(const std::string
& values
, int* result
) {
483 // Create a base::ListValue of strings.
484 std::vector
<std::string
> split_values
;
485 base::ListValue list_value
;
486 size_t num_values
= Tokenize(values
, ",", &split_values
);
487 for (size_t i
= 0; i
< num_values
; ++i
)
488 list_value
.Append(new base::StringValue(split_values
[i
]));
489 return ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
495 void ExtensionWebRequestTest::FireURLRequestWithData(
496 const std::string
& method
,
497 const char* content_type
,
498 const std::vector
<char>& bytes_1
,
499 const std::vector
<char>& bytes_2
) {
500 // The request URL can be arbitrary but must have an HTTP or HTTPS scheme.
501 GURL
request_url("http://www.example.com");
502 net::URLRequest
request(
503 request_url
, net::DEFAULT_PRIORITY
, &delegate_
, context_
.get());
504 request
.set_method(method
);
505 if (content_type
!= NULL
)
506 request
.SetExtraRequestHeaderByName(net::HttpRequestHeaders::kContentType
,
508 true /* overwrite */);
509 ScopedVector
<net::UploadElementReader
> element_readers
;
510 element_readers
.push_back(new net::UploadBytesElementReader(
511 &(bytes_1
[0]), bytes_1
.size()));
512 element_readers
.push_back(
513 new net::UploadFileElementReader(base::MessageLoopProxy::current().get(),
518 element_readers
.push_back(
519 new net::UploadBytesElementReader(&(bytes_2
[0]), bytes_2
.size()));
520 request
.set_upload(make_scoped_ptr(
521 new net::UploadDataStream(element_readers
.Pass(), 0)));
522 ipc_sender_
.PushTask(base::Bind(&base::DoNothing
));
526 TEST_F(ExtensionWebRequestTest
, AccessRequestBodyData
) {
527 // We verify that URLRequest body is accessible to OnBeforeRequest listeners.
528 // These testing steps are repeated twice in a row:
529 // 1. Register an extension requesting "requestBody" in ExtraInfoSpec and
530 // file a POST URLRequest with a multipart-encoded form. See it getting
532 // 2. Do the same, but without requesting "requestBody". Nothing should be
534 // 3. With "requestBody", fire a POST URLRequest which is not a parseable
535 // HTML form. Raw data should be returned.
536 // 4. Do the same, but with a PUT method. Result should be the same.
537 const std::string
kMethodPost("POST");
538 const std::string
kMethodPut("PUT");
541 const char kPlainBlock1
[] = "abcd\n";
542 const size_t kPlainBlock1Length
= sizeof(kPlainBlock1
) - 1;
543 std::vector
<char> plain_1(kPlainBlock1
, kPlainBlock1
+ kPlainBlock1Length
);
544 const char kPlainBlock2
[] = "1234\n";
545 const size_t kPlainBlock2Length
= sizeof(kPlainBlock2
) - 1;
546 std::vector
<char> plain_2(kPlainBlock2
, kPlainBlock2
+ kPlainBlock2Length
);
547 #define kBoundary "THIS_IS_A_BOUNDARY"
548 const char kFormBlock1
[] = "--" kBoundary
"\r\n"
549 "Content-Disposition: form-data; name=\"A\"\r\n"
552 "--" kBoundary
"\r\n"
553 "Content-Disposition: form-data; name=\"B\"; filename=\"\"\r\n"
554 "Content-Type: application/octet-stream\r\n"
556 std::vector
<char> form_1(kFormBlock1
, kFormBlock1
+ sizeof(kFormBlock1
) - 1);
557 const char kFormBlock2
[] = "\r\n"
558 "--" kBoundary
"\r\n"
559 "Content-Disposition: form-data; name=\"C\"\r\n"
563 std::vector
<char> form_2(kFormBlock2
, kFormBlock2
+ sizeof(kFormBlock2
) - 1);
566 // Paths to look for in returned dictionaries.
567 const std::string
kBodyPath(keys::kRequestBodyKey
);
568 const std::string
kFormDataPath(
569 kBodyPath
+ "." + keys::kRequestBodyFormDataKey
);
570 const std::string
kRawPath(kBodyPath
+ "." + keys::kRequestBodyRawKey
);
571 const std::string
kErrorPath(kBodyPath
+ "." + keys::kRequestBodyErrorKey
);
572 const std::string
* const kPath
[] = {
578 // Contents of formData.
579 const char kFormData
[] =
580 "{\"A\":[\"test text\"],\"B\":[\"\"],\"C\":[\"test password\"]}";
581 scoped_ptr
<const base::Value
> form_data(base::JSONReader::Read(kFormData
));
582 ASSERT_TRUE(form_data
.get() != NULL
);
583 ASSERT_TRUE(form_data
->GetType() == base::Value::TYPE_DICTIONARY
);
586 extensions::subtle::AppendKeyValuePair(
587 keys::kRequestBodyRawBytesKey
,
588 BinaryValue::CreateWithCopiedBuffer(kPlainBlock1
, kPlainBlock1Length
),
590 extensions::subtle::AppendKeyValuePair(
591 keys::kRequestBodyRawFileKey
,
592 new base::StringValue(std::string()),
594 extensions::subtle::AppendKeyValuePair(
595 keys::kRequestBodyRawBytesKey
,
596 BinaryValue::CreateWithCopiedBuffer(kPlainBlock2
, kPlainBlock2Length
),
599 const base::Value
* const kExpected
[] = {
605 COMPILE_ASSERT(arraysize(kPath
) == arraysize(kExpected
),
606 the_arrays_kPath_and_kExpected_need_to_be_the_same_size
);
608 const char kMultipart
[] = "multipart/form-data; boundary=" kBoundary
;
611 // Set up a dummy extension name.
612 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
613 ExtensionWebRequestEventRouter::RequestFilter filter
;
614 std::string
extension_id("1");
615 const std::string
string_spec_post("blocking,requestBody");
616 const std::string
string_spec_no_post("blocking");
617 int extra_info_spec_empty
= 0;
618 int extra_info_spec_body
= 0;
619 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
622 // Subscribe to OnBeforeRequest with requestBody requirement.
623 ASSERT_TRUE(GenerateInfoSpec(string_spec_post
, &extra_info_spec_body
));
624 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
625 &profile_
, extension_id
, extension_id
, kEventName
, kEventName
+ "/1",
626 filter
, extra_info_spec_body
, -1, -1, ipc_sender_factory
.GetWeakPtr());
628 FireURLRequestWithData(kMethodPost
, kMultipart
, form_1
, form_2
);
630 // We inspect the result in the message list of |ipc_sender_| later.
631 base::MessageLoop::current()->RunUntilIdle();
633 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
634 &profile_
, extension_id
, kEventName
+ "/1");
637 // Now subscribe to OnBeforeRequest *without* the requestBody requirement.
639 GenerateInfoSpec(string_spec_no_post
, &extra_info_spec_empty
));
640 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
641 &profile_
, extension_id
, extension_id
, kEventName
, kEventName
+ "/1",
642 filter
, extra_info_spec_empty
, -1, -1, ipc_sender_factory
.GetWeakPtr());
644 FireURLRequestWithData(kMethodPost
, kMultipart
, form_1
, form_2
);
646 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
647 &profile_
, extension_id
, kEventName
+ "/1");
649 // Subscribe to OnBeforeRequest with requestBody requirement.
650 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
651 &profile_
, extension_id
, extension_id
, kEventName
, kEventName
+ "/1",
652 filter
, extra_info_spec_body
, -1, -1, ipc_sender_factory
.GetWeakPtr());
655 // Now send a POST request with body which is not parseable as a form.
656 FireURLRequestWithData(kMethodPost
, NULL
/*no header*/, plain_1
, plain_2
);
659 // Now send a PUT request with the same body as above.
660 FireURLRequestWithData(kMethodPut
, NULL
/*no header*/, plain_1
, plain_2
);
662 base::MessageLoop::current()->RunUntilIdle();
665 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
666 &profile_
, extension_id
, kEventName
+ "/1");
668 IPC::Message
* message
= NULL
;
669 TestIPCSender::SentMessages::const_iterator i
= ipc_sender_
.sent_begin();
670 for (size_t test
= 0; test
< arraysize(kExpected
); ++test
) {
671 SCOPED_TRACE(testing::Message("iteration number ") << test
);
672 EXPECT_NE(i
, ipc_sender_
.sent_end());
673 message
= (i
++)->get();
674 const base::DictionaryValue
* details
;
675 ExtensionMsg_MessageInvoke::Param param
;
676 GetPartOfMessageArguments(message
, &details
, ¶m
);
677 ASSERT_TRUE(details
!= NULL
);
678 const base::Value
* result
= NULL
;
679 if (kExpected
[test
]) {
680 EXPECT_TRUE(details
->Get(*(kPath
[test
]), &result
));
681 EXPECT_TRUE(kExpected
[test
]->Equals(result
));
683 EXPECT_FALSE(details
->Get(*(kPath
[test
]), &result
));
687 EXPECT_EQ(i
, ipc_sender_
.sent_end());
690 TEST_F(ExtensionWebRequestTest
, NoAccessRequestBodyData
) {
691 // We verify that URLRequest body is NOT accessible to OnBeforeRequest
692 // listeners when the type of the request is different from POST or PUT, or
693 // when the request body is empty. 3 requests are fired, without upload data,
694 // a POST, PUT and GET request. For none of them the "requestBody" object
695 // property should be present in the details passed to the onBeforeRequest
697 const char* kMethods
[] = { "POST", "PUT", "GET" };
699 // Set up a dummy extension name.
700 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
701 ExtensionWebRequestEventRouter::RequestFilter filter
;
702 const std::string
extension_id("1");
703 int extra_info_spec
= 0;
704 ASSERT_TRUE(GenerateInfoSpec("blocking,requestBody", &extra_info_spec
));
705 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
707 // Subscribe to OnBeforeRequest with requestBody requirement.
708 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
709 &profile_
, extension_id
, extension_id
, kEventName
, kEventName
+ "/1",
710 filter
, extra_info_spec
, -1, -1, ipc_sender_factory
.GetWeakPtr());
712 // The request URL can be arbitrary but must have an HTTP or HTTPS scheme.
713 const GURL
request_url("http://www.example.com");
715 for (size_t i
= 0; i
< arraysize(kMethods
); ++i
) {
716 net::URLRequest
request(
717 request_url
, net::DEFAULT_PRIORITY
, &delegate_
, context_
.get());
718 request
.set_method(kMethods
[i
]);
719 ipc_sender_
.PushTask(base::Bind(&base::DoNothing
));
723 // We inspect the result in the message list of |ipc_sender_| later.
724 base::MessageLoop::current()->RunUntilIdle();
726 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
727 &profile_
, extension_id
, kEventName
+ "/1");
729 TestIPCSender::SentMessages::const_iterator i
= ipc_sender_
.sent_begin();
730 for (size_t test
= 0; test
< arraysize(kMethods
); ++test
, ++i
) {
731 SCOPED_TRACE(testing::Message("iteration number ") << test
);
732 EXPECT_NE(i
, ipc_sender_
.sent_end());
733 IPC::Message
* message
= i
->get();
734 const base::DictionaryValue
* details
= NULL
;
735 ExtensionMsg_MessageInvoke::Param param
;
736 GetPartOfMessageArguments(message
, &details
, ¶m
);
737 ASSERT_TRUE(details
!= NULL
);
738 EXPECT_FALSE(details
->HasKey(keys::kRequestBodyKey
));
741 EXPECT_EQ(i
, ipc_sender_
.sent_end());
744 struct HeaderModificationTest_Header
{
749 struct HeaderModificationTest_Modification
{
761 struct HeaderModificationTest
{
763 HeaderModificationTest_Header before
[10];
764 int modification_size
;
765 HeaderModificationTest_Modification modification
[10];
767 HeaderModificationTest_Header after
[10];
770 class ExtensionWebRequestHeaderModificationTest
771 : public testing::TestWithParam
<HeaderModificationTest
> {
773 ExtensionWebRequestHeaderModificationTest()
774 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
775 profile_manager_(TestingBrowserProcess::GetGlobal()),
776 event_router_(new EventRouterForwarder
) {}
779 virtual void SetUp() {
780 ASSERT_TRUE(profile_manager_
.SetUp());
781 ChromeNetworkDelegate::InitializePrefsOnUIThread(
782 &enable_referrers_
, NULL
, NULL
, profile_
.GetTestingPrefService());
783 network_delegate_
.reset(
784 new ChromeNetworkDelegate(event_router_
.get(), &enable_referrers_
));
785 network_delegate_
->set_profile(&profile_
);
786 network_delegate_
->set_cookie_settings(
787 CookieSettings::Factory::GetForProfile(&profile_
).get());
788 context_
.reset(new net::TestURLRequestContext(true));
789 host_resolver_
.reset(new net::MockHostResolver());
790 host_resolver_
->rules()->AddSimulatedFailure("doesnotexist");
791 context_
->set_host_resolver(host_resolver_
.get());
792 context_
->set_network_delegate(network_delegate_
.get());
796 content::TestBrowserThreadBundle thread_bundle_
;
797 TestingProfile profile_
;
798 TestingProfileManager profile_manager_
;
799 net::TestDelegate delegate_
;
800 BooleanPrefMember enable_referrers_
;
801 TestIPCSender ipc_sender_
;
802 scoped_refptr
<EventRouterForwarder
> event_router_
;
803 scoped_refptr
<InfoMap
> extension_info_map_
;
804 scoped_ptr
<ChromeNetworkDelegate
> network_delegate_
;
805 scoped_ptr
<net::MockHostResolver
> host_resolver_
;
806 scoped_ptr
<net::TestURLRequestContext
> context_
;
809 TEST_P(ExtensionWebRequestHeaderModificationTest
, TestModifications
) {
810 std::string
extension1_id("1");
811 std::string
extension2_id("2");
812 std::string
extension3_id("3");
813 ExtensionWebRequestEventRouter::RequestFilter filter
;
814 const std::string
kEventName(keys::kOnBeforeSendHeadersEvent
);
815 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
817 // Install two extensions that can modify headers. Extension 2 has
818 // higher precedence than extension 1.
819 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
820 &profile_
, extension1_id
, extension1_id
, kEventName
, kEventName
+ "/1",
821 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, -1, -1,
822 ipc_sender_factory
.GetWeakPtr());
823 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
824 &profile_
, extension2_id
, extension2_id
, kEventName
, kEventName
+ "/2",
825 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, -1, -1,
826 ipc_sender_factory
.GetWeakPtr());
828 // Install one extension that observes the final headers.
829 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
830 &profile_
, extension3_id
, extension3_id
, keys::kOnSendHeadersEvent
,
831 std::string(keys::kOnSendHeadersEvent
) + "/3", filter
,
832 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS
, -1, -1,
833 ipc_sender_factory
.GetWeakPtr());
835 GURL
request_url("http://doesnotexist/does_not_exist.html");
836 net::URLRequest
request(
837 request_url
, net::DEFAULT_PRIORITY
, &delegate_
, context_
.get());
839 // Initialize headers available before extensions are notified of the
840 // onBeforeSendHeaders event.
841 HeaderModificationTest test
= GetParam();
842 net::HttpRequestHeaders before_headers
;
843 for (int i
= 0; i
< test
.before_size
; ++i
)
844 before_headers
.SetHeader(test
.before
[i
].name
, test
.before
[i
].value
);
845 request
.SetExtraRequestHeaders(before_headers
);
847 // Gather the modifications to the headers for the respective extensions.
848 // We assume here that all modifications of one extension are listed
849 // in a continuous block of |test.modifications_|.
850 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
851 for (int i
= 0; i
< test
.modification_size
; ++i
) {
852 const HeaderModificationTest_Modification
& mod
= test
.modification
[i
];
853 if (response
== NULL
) {
854 response
= new ExtensionWebRequestEventRouter::EventResponse(
855 mod
.extension_id
== 1 ? extension1_id
: extension2_id
,
856 base::Time::FromDoubleT(mod
.extension_id
));
857 response
->request_headers
.reset(new net::HttpRequestHeaders());
858 response
->request_headers
->MergeFrom(request
.extra_request_headers());
862 case HeaderModificationTest_Modification::SET
:
863 response
->request_headers
->SetHeader(mod
.key
, mod
.value
);
865 case HeaderModificationTest_Modification::REMOVE
:
866 response
->request_headers
->RemoveHeader(mod
.key
);
870 // Trigger the result when this is the last modification statement or
871 // the block of modifications for the next extension starts.
872 if (i
+1 == test
.modification_size
||
873 mod
.extension_id
!= test
.modification
[i
+1].extension_id
) {
874 ipc_sender_
.PushTask(
875 base::Bind(&EventHandledOnIOThread
,
876 &profile_
, mod
.extension_id
== 1 ? extension1_id
: extension2_id
,
877 kEventName
, kEventName
+ (mod
.extension_id
== 1 ? "/1" : "/2"),
878 request
.identifier(), response
));
883 // Don't do anything for the onSendHeaders message.
884 ipc_sender_
.PushTask(base::Bind(&base::DoNothing
));
886 // Note that we mess up the headers slightly:
887 // request.Start() will first add additional headers (e.g. the User-Agent)
888 // and then send an event to the extension. When we have prepared our
889 // answers to the onBeforeSendHeaders events above, these headers did not
890 // exists and are therefore not listed in the responses. This makes
891 // them seem deleted.
893 base::MessageLoop::current()->Run();
895 EXPECT_TRUE(!request
.is_pending());
896 // This cannot succeed as we send the request to a server that does not exist.
897 EXPECT_EQ(net::URLRequestStatus::FAILED
, request
.status().status());
898 EXPECT_EQ(request_url
, request
.url());
899 EXPECT_EQ(1U, request
.url_chain().size());
900 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
902 // Calculate the expected headers.
903 net::HttpRequestHeaders expected_headers
;
904 for (int i
= 0; i
< test
.after_size
; ++i
) {
905 expected_headers
.SetHeader(test
.after
[i
].name
,
906 test
.after
[i
].value
);
909 // Counter for the number of observed onSendHeaders events.
910 int num_headers_observed
= 0;
912 // Search the onSendHeaders signal in the IPC messages and check that
913 // it contained the correct headers.
914 TestIPCSender::SentMessages::const_iterator i
;
915 for (i
= ipc_sender_
.sent_begin(); i
!= ipc_sender_
.sent_end(); ++i
) {
916 IPC::Message
* message
= i
->get();
917 if (ExtensionMsg_MessageInvoke::ID
!= message
->type())
919 ExtensionMsg_MessageInvoke::Param message_tuple
;
920 ExtensionMsg_MessageInvoke::Read(message
, &message_tuple
);
921 base::ListValue
& args
= message_tuple
.d
;
923 std::string event_name
;
924 if (!args
.GetString(0, &event_name
) ||
925 event_name
!= std::string(keys::kOnSendHeadersEvent
) + "/3") {
929 base::ListValue
* event_arg
= NULL
;
930 ASSERT_TRUE(args
.GetList(1, &event_arg
));
932 base::DictionaryValue
* event_arg_dict
= NULL
;
933 ASSERT_TRUE(event_arg
->GetDictionary(0, &event_arg_dict
));
935 base::ListValue
* request_headers
= NULL
;
936 ASSERT_TRUE(event_arg_dict
->GetList(keys::kRequestHeadersKey
,
939 net::HttpRequestHeaders observed_headers
;
940 for (size_t j
= 0; j
< request_headers
->GetSize(); ++j
) {
941 base::DictionaryValue
* header
= NULL
;
942 ASSERT_TRUE(request_headers
->GetDictionary(j
, &header
));
945 ASSERT_TRUE(header
->GetString(keys::kHeaderNameKey
, &key
));
946 ASSERT_TRUE(header
->GetString(keys::kHeaderValueKey
, &value
));
947 observed_headers
.SetHeader(key
, value
);
950 EXPECT_EQ(expected_headers
.ToString(), observed_headers
.ToString());
951 ++num_headers_observed
;
953 EXPECT_EQ(1, num_headers_observed
);
954 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
955 &profile_
, extension1_id
, kEventName
+ "/1");
956 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
957 &profile_
, extension2_id
, kEventName
+ "/2");
958 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
959 &profile_
, extension3_id
, std::string(keys::kOnSendHeadersEvent
) + "/3");
964 void TestInitFromValue(const std::string
& values
, bool expected_return_code
,
965 int expected_extra_info_spec
) {
966 int actual_info_spec
;
967 bool actual_return_code
= GenerateInfoSpec(values
, &actual_info_spec
);
968 EXPECT_EQ(expected_return_code
, actual_return_code
);
969 if (expected_return_code
)
970 EXPECT_EQ(expected_extra_info_spec
, actual_info_spec
);
975 TEST_F(ExtensionWebRequestTest
, InitFromValue
) {
976 TestInitFromValue(std::string(), true, 0);
978 // Single valid values.
982 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS
);
986 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS
);
990 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
);
994 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING
);
998 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_BODY
);
1000 // Multiple valid values are bitwise-or'ed.
1002 "requestHeaders,blocking",
1004 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS
|
1005 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
);
1007 // Any invalid values lead to a bad parse.
1008 TestInitFromValue("invalidValue", false, 0);
1009 TestInitFromValue("blocking,invalidValue", false, 0);
1010 TestInitFromValue("invalidValue1,invalidValue2", false, 0);
1012 // BLOCKING and ASYNC_BLOCKING are mutually exclusive.
1013 TestInitFromValue("blocking,asyncBlocking", false, 0);
1018 const HeaderModificationTest_Modification::Type SET
=
1019 HeaderModificationTest_Modification::SET
;
1020 const HeaderModificationTest_Modification::Type REMOVE
=
1021 HeaderModificationTest_Modification::REMOVE
;
1023 HeaderModificationTest kTests
[] = {
1024 // Check that extension 2 always wins when settings the same header.
1026 // Headers before test.
1027 2, { {"header1", "value1"},
1028 {"header2", "value2"} },
1029 // Modifications in test.
1030 2, { {1, SET
, "header1", "foo"},
1031 {2, SET
, "header1", "bar"} },
1032 // Headers after test.
1033 2, { {"header1", "bar"},
1034 {"header2", "value2"} }
1036 // Same as before in reverse execution order.
1038 // Headers before test.
1039 2, { {"header1", "value1"},
1040 {"header2", "value2"} },
1041 // Modifications in test.
1042 2, { {2, SET
, "header1", "bar"},
1043 {1, SET
, "header1", "foo"} },
1044 // Headers after test.
1045 2, { {"header1", "bar"},
1046 {"header2", "value2"} }
1048 // Check that two extensions can modify different headers that do not
1051 // Headers before test.
1052 2, { {"header1", "value1"},
1053 {"header2", "value2"} },
1054 // Modifications in test.
1055 2, { {1, SET
, "header1", "foo"},
1056 {2, SET
, "header2", "bar"} },
1057 // Headers after test.
1058 2, { {"header1", "foo"},
1059 {"header2", "bar"} }
1061 // Check insert/delete conflict.
1063 // Headers before test.
1064 1, { {"header1", "value1"} },
1065 // Modifications in test.
1066 2, { {1, SET
, "header1", "foo"},
1067 {2, REMOVE
, "header1", NULL
} },
1068 // Headers after test.
1072 // Headers before test.
1073 1, { {"header1", "value1"} },
1074 // Modifications in test.
1075 2, { {2, REMOVE
, "header1", NULL
},
1076 {1, SET
, "header1", "foo"} },
1077 // Headers after test.
1081 // Headers before test.
1082 1, { {"header1", "value1"} },
1083 // Modifications in test.
1084 2, { {1, REMOVE
, "header1", NULL
},
1085 {2, SET
, "header1", "foo"} },
1086 // Headers after test.
1087 1, { {"header1", "foo"} }
1090 // Headers before test.
1091 1, { {"header1", "value1"} },
1092 // Modifications in test.
1093 2, { {2, SET
, "header1", "foo"},
1094 {1, REMOVE
, "header1", NULL
} },
1095 // Headers after test.
1096 1, { {"header1", "foo"} }
1098 // Check that edits are atomic (i.e. either all edit requests of an
1099 // extension are executed or none).
1101 // Headers before test.
1103 // Modifications in test.
1104 3, { {1, SET
, "header1", "value1"},
1105 {1, SET
, "header2", "value2"},
1106 {2, SET
, "header1", "foo"} },
1107 // Headers after test.
1108 1, { {"header1", "foo"} } // set(header2) is ignored
1110 // Check that identical edits do not conflict (set(header2) would be ignored
1111 // if set(header1) were considered a conflict).
1113 // Headers before test.
1115 // Modifications in test.
1116 3, { {1, SET
, "header1", "value2"},
1117 {1, SET
, "header2", "foo"},
1118 {2, SET
, "header1", "value2"} },
1119 // Headers after test.
1120 2, { {"header1", "value2"},
1121 {"header2", "foo"} }
1123 // Check that identical deletes do not conflict (set(header2) would be ignored
1124 // if delete(header1) were considered a conflict).
1126 // Headers before test.
1127 1, { {"header1", "value1"} },
1128 // Modifications in test.
1129 3, { {1, REMOVE
, "header1", NULL
},
1130 {1, SET
, "header2", "foo"},
1131 {2, REMOVE
, "header1", NULL
} },
1132 // Headers after test.
1133 1, { {"header2", "foo"} }
1135 // Check that setting a value to an identical value is not considered an
1136 // edit operation that can conflict.
1138 // Headers before test.
1139 1, { {"header1", "value1"} },
1140 // Modifications in test.
1141 3, { {1, SET
, "header1", "foo"},
1142 {1, SET
, "header2", "bar"},
1143 {2, SET
, "header1", "value1"} },
1144 // Headers after test.
1145 2, { {"header1", "foo"},
1146 {"header2", "bar"} }
1150 INSTANTIATE_TEST_CASE_P(
1151 ExtensionWebRequest
,
1152 ExtensionWebRequestHeaderModificationTest
,
1153 ::testing::ValuesIn(kTests
));
1158 TEST(ExtensionWebRequestHelpersTest
,
1159 TestInDecreasingExtensionInstallationTimeOrder
) {
1160 linked_ptr
<EventResponseDelta
> a(
1161 new EventResponseDelta("ext_1", base::Time::FromInternalValue(0)));
1162 linked_ptr
<EventResponseDelta
> b(
1163 new EventResponseDelta("ext_2", base::Time::FromInternalValue(1000)));
1164 EXPECT_FALSE(InDecreasingExtensionInstallationTimeOrder(a
, a
));
1165 EXPECT_FALSE(InDecreasingExtensionInstallationTimeOrder(a
, b
));
1166 EXPECT_TRUE(InDecreasingExtensionInstallationTimeOrder(b
, a
));
1169 TEST(ExtensionWebRequestHelpersTest
, TestStringToCharList
) {
1170 base::ListValue list_value
;
1171 list_value
.Append(new base::FundamentalValue('1'));
1172 list_value
.Append(new base::FundamentalValue('2'));
1173 list_value
.Append(new base::FundamentalValue('3'));
1174 list_value
.Append(new base::FundamentalValue(0xFE));
1175 list_value
.Append(new base::FundamentalValue(0xD1));
1177 unsigned char char_value
[] = {'1', '2', '3', 0xFE, 0xD1};
1178 std::string
string_value(reinterpret_cast<char *>(char_value
), 5);
1180 scoped_ptr
<base::ListValue
> converted_list(StringToCharList(string_value
));
1181 EXPECT_TRUE(list_value
.Equals(converted_list
.get()));
1183 std::string converted_string
;
1184 EXPECT_TRUE(CharListToString(&list_value
, &converted_string
));
1185 EXPECT_EQ(string_value
, converted_string
);
1188 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnBeforeRequestDelta
) {
1189 const bool cancel
= true;
1190 const GURL
localhost("http://localhost");
1191 scoped_ptr
<EventResponseDelta
> delta(
1192 CalculateOnBeforeRequestDelta("extid", base::Time::Now(),
1193 cancel
, localhost
));
1194 ASSERT_TRUE(delta
.get());
1195 EXPECT_TRUE(delta
->cancel
);
1196 EXPECT_EQ(localhost
, delta
->new_url
);
1199 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnBeforeSendHeadersDelta
) {
1200 const bool cancel
= true;
1202 net::HttpRequestHeaders old_headers
;
1203 old_headers
.AddHeadersFromString("key1: value1\r\n"
1204 "key2: value2\r\n");
1206 // Test adding a header.
1207 net::HttpRequestHeaders new_headers_added
;
1208 new_headers_added
.AddHeadersFromString("key1: value1\r\n"
1210 "key2: value2\r\n");
1211 scoped_ptr
<EventResponseDelta
> delta_added(
1212 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1213 &old_headers
, &new_headers_added
));
1214 ASSERT_TRUE(delta_added
.get());
1215 EXPECT_TRUE(delta_added
->cancel
);
1216 ASSERT_TRUE(delta_added
->modified_request_headers
.GetHeader("key3", &value
));
1217 EXPECT_EQ("value3", value
);
1219 // Test deleting a header.
1220 net::HttpRequestHeaders new_headers_deleted
;
1221 new_headers_deleted
.AddHeadersFromString("key1: value1\r\n");
1222 scoped_ptr
<EventResponseDelta
> delta_deleted(
1223 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1224 &old_headers
, &new_headers_deleted
));
1225 ASSERT_TRUE(delta_deleted
.get());
1226 ASSERT_EQ(1u, delta_deleted
->deleted_request_headers
.size());
1227 ASSERT_EQ("key2", delta_deleted
->deleted_request_headers
.front());
1229 // Test modifying a header.
1230 net::HttpRequestHeaders new_headers_modified
;
1231 new_headers_modified
.AddHeadersFromString("key1: value1\r\n"
1232 "key2: value3\r\n");
1233 scoped_ptr
<EventResponseDelta
> delta_modified(
1234 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1235 &old_headers
, &new_headers_modified
));
1236 ASSERT_TRUE(delta_modified
.get());
1237 EXPECT_TRUE(delta_modified
->deleted_request_headers
.empty());
1239 delta_modified
->modified_request_headers
.GetHeader("key2", &value
));
1240 EXPECT_EQ("value3", value
);
1242 // Test modifying a header if extension author just appended a new (key,
1243 // value) pair with a key that existed before. This is incorrect
1244 // usage of the API that shall be handled gracefully.
1245 net::HttpRequestHeaders new_headers_modified2
;
1246 new_headers_modified2
.AddHeadersFromString("key1: value1\r\n"
1248 "key2: value3\r\n");
1249 scoped_ptr
<EventResponseDelta
> delta_modified2(
1250 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1251 &old_headers
, &new_headers_modified
));
1252 ASSERT_TRUE(delta_modified2
.get());
1253 EXPECT_TRUE(delta_modified2
->deleted_request_headers
.empty());
1255 delta_modified2
->modified_request_headers
.GetHeader("key2", &value
));
1256 EXPECT_EQ("value3", value
);
1259 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnHeadersReceivedDelta
) {
1260 const bool cancel
= true;
1261 char base_headers_string
[] =
1262 "HTTP/1.0 200 OK\r\n"
1264 "Key2: Value2, Bar\r\n"
1267 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
1268 new net::HttpResponseHeaders(
1269 net::HttpUtil::AssembleRawHeaders(
1270 base_headers_string
, sizeof(base_headers_string
))));
1272 ResponseHeaders new_headers
;
1273 new_headers
.push_back(ResponseHeader("kEy1", "Value1")); // Unchanged
1274 new_headers
.push_back(ResponseHeader("Key2", "Value1")); // Modified
1276 new_headers
.push_back(ResponseHeader("Key4", "Value4")); // Added
1277 GURL effective_new_url
;
1279 scoped_ptr
<EventResponseDelta
> delta(
1280 CalculateOnHeadersReceivedDelta("extid",
1286 ASSERT_TRUE(delta
.get());
1287 EXPECT_TRUE(delta
->cancel
);
1288 EXPECT_EQ(2u, delta
->added_response_headers
.size());
1289 EXPECT_TRUE(Contains(delta
->added_response_headers
,
1290 ResponseHeader("Key2", "Value1")));
1291 EXPECT_TRUE(Contains(delta
->added_response_headers
,
1292 ResponseHeader("Key4", "Value4")));
1293 EXPECT_EQ(2u, delta
->deleted_response_headers
.size());
1294 EXPECT_TRUE(Contains(delta
->deleted_response_headers
,
1295 ResponseHeader("Key2", "Value2, Bar")));
1296 EXPECT_TRUE(Contains(delta
->deleted_response_headers
,
1297 ResponseHeader("Key3", "Value3")));
1300 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnAuthRequiredDelta
) {
1301 const bool cancel
= true;
1303 base::string16 username
= base::ASCIIToUTF16("foo");
1304 base::string16 password
= base::ASCIIToUTF16("bar");
1305 scoped_ptr
<net::AuthCredentials
> credentials(
1306 new net::AuthCredentials(username
, password
));
1308 scoped_ptr
<EventResponseDelta
> delta(
1309 CalculateOnAuthRequiredDelta("extid", base::Time::Now(), cancel
,
1311 ASSERT_TRUE(delta
.get());
1312 EXPECT_TRUE(delta
->cancel
);
1313 ASSERT_TRUE(delta
->auth_credentials
.get());
1314 EXPECT_EQ(username
, delta
->auth_credentials
->username());
1315 EXPECT_EQ(password
, delta
->auth_credentials
->password());
1318 TEST(ExtensionWebRequestHelpersTest
, TestMergeCancelOfResponses
) {
1319 EventResponseDeltas deltas
;
1320 net::CapturingBoundNetLog capturing_net_log
;
1321 net::BoundNetLog net_log
= capturing_net_log
.bound();
1322 bool canceled
= false;
1324 // Single event that does not cancel.
1325 linked_ptr
<EventResponseDelta
> d1(
1326 new EventResponseDelta("extid1", base::Time::FromInternalValue(1000)));
1328 deltas
.push_back(d1
);
1329 MergeCancelOfResponses(deltas
, &canceled
, &net_log
);
1330 EXPECT_FALSE(canceled
);
1331 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1333 // Second event that cancels the request
1334 linked_ptr
<EventResponseDelta
> d2(
1335 new EventResponseDelta("extid2", base::Time::FromInternalValue(500)));
1337 deltas
.push_back(d2
);
1338 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1339 MergeCancelOfResponses(deltas
, &canceled
, &net_log
);
1340 EXPECT_TRUE(canceled
);
1341 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1344 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeRequestResponses
) {
1345 EventResponseDeltas deltas
;
1346 net::CapturingBoundNetLog capturing_net_log
;
1347 net::BoundNetLog net_log
= capturing_net_log
.bound();
1348 ExtensionWarningSet warning_set
;
1349 GURL effective_new_url
;
1352 linked_ptr
<EventResponseDelta
> d0(
1353 new EventResponseDelta("extid0", base::Time::FromInternalValue(0)));
1354 deltas
.push_back(d0
);
1355 MergeOnBeforeRequestResponses(
1356 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1357 EXPECT_TRUE(effective_new_url
.is_empty());
1360 GURL
new_url_1("http://foo.com");
1361 linked_ptr
<EventResponseDelta
> d1(
1362 new EventResponseDelta("extid1", base::Time::FromInternalValue(1000)));
1363 d1
->new_url
= GURL(new_url_1
);
1364 deltas
.push_back(d1
);
1365 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1366 capturing_net_log
.Clear();
1367 MergeOnBeforeRequestResponses(
1368 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1369 EXPECT_EQ(new_url_1
, effective_new_url
);
1370 EXPECT_TRUE(warning_set
.empty());
1371 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1373 // Ignored redirect (due to precedence).
1374 GURL
new_url_2("http://bar.com");
1375 linked_ptr
<EventResponseDelta
> d2(
1376 new EventResponseDelta("extid2", base::Time::FromInternalValue(500)));
1377 d2
->new_url
= GURL(new_url_2
);
1378 deltas
.push_back(d2
);
1379 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1380 warning_set
.clear();
1381 capturing_net_log
.Clear();
1382 MergeOnBeforeRequestResponses(
1383 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1384 EXPECT_EQ(new_url_1
, effective_new_url
);
1385 EXPECT_EQ(1u, warning_set
.size());
1386 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1387 EXPECT_EQ(2u, capturing_net_log
.GetSize());
1389 // Overriding redirect.
1390 GURL
new_url_3("http://baz.com");
1391 linked_ptr
<EventResponseDelta
> d3(
1392 new EventResponseDelta("extid3", base::Time::FromInternalValue(1500)));
1393 d3
->new_url
= GURL(new_url_3
);
1394 deltas
.push_back(d3
);
1395 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1396 warning_set
.clear();
1397 capturing_net_log
.Clear();
1398 MergeOnBeforeRequestResponses(
1399 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1400 EXPECT_EQ(new_url_3
, effective_new_url
);
1401 EXPECT_EQ(2u, warning_set
.size());
1402 EXPECT_TRUE(HasWarning(warning_set
, "extid1"));
1403 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1404 EXPECT_EQ(3u, capturing_net_log
.GetSize());
1406 // Check that identical redirects don't cause a conflict.
1407 linked_ptr
<EventResponseDelta
> d4(
1408 new EventResponseDelta("extid4", base::Time::FromInternalValue(2000)));
1409 d4
->new_url
= GURL(new_url_3
);
1410 deltas
.push_back(d4
);
1411 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1412 warning_set
.clear();
1413 capturing_net_log
.Clear();
1414 MergeOnBeforeRequestResponses(
1415 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1416 EXPECT_EQ(new_url_3
, effective_new_url
);
1417 EXPECT_EQ(2u, warning_set
.size());
1418 EXPECT_TRUE(HasWarning(warning_set
, "extid1"));
1419 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1420 EXPECT_EQ(4u, capturing_net_log
.GetSize());
1423 // This tests that we can redirect to data:// urls, which is considered
1424 // a kind of cancelling requests.
1425 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeRequestResponses2
) {
1426 EventResponseDeltas deltas
;
1427 net::CapturingBoundNetLog capturing_net_log
;
1428 net::BoundNetLog net_log
= capturing_net_log
.bound();
1429 ExtensionWarningSet warning_set
;
1430 GURL effective_new_url
;
1433 GURL
new_url_0("http://foo.com");
1434 linked_ptr
<EventResponseDelta
> d0(
1435 new EventResponseDelta("extid0", base::Time::FromInternalValue(2000)));
1436 d0
->new_url
= GURL(new_url_0
);
1437 deltas
.push_back(d0
);
1438 MergeOnBeforeRequestResponses(
1439 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1440 EXPECT_EQ(new_url_0
, effective_new_url
);
1442 // Cancel request by redirecting to a data:// URL. This shall override
1443 // the other redirect but not cause any conflict warnings.
1444 GURL
new_url_1("data://foo");
1445 linked_ptr
<EventResponseDelta
> d1(
1446 new EventResponseDelta("extid1", base::Time::FromInternalValue(1500)));
1447 d1
->new_url
= GURL(new_url_1
);
1448 deltas
.push_back(d1
);
1449 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1450 warning_set
.clear();
1451 capturing_net_log
.Clear();
1452 MergeOnBeforeRequestResponses(
1453 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1454 EXPECT_EQ(new_url_1
, effective_new_url
);
1455 EXPECT_TRUE(warning_set
.empty());
1456 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1458 // Cancel request by redirecting to the same data:// URL. This shall
1459 // not create any conflicts as it is in line with d1.
1460 GURL
new_url_2("data://foo");
1461 linked_ptr
<EventResponseDelta
> d2(
1462 new EventResponseDelta("extid2", base::Time::FromInternalValue(1000)));
1463 d2
->new_url
= GURL(new_url_2
);
1464 deltas
.push_back(d2
);
1465 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1466 warning_set
.clear();
1467 capturing_net_log
.Clear();
1468 MergeOnBeforeRequestResponses(
1469 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1470 EXPECT_EQ(new_url_1
, effective_new_url
);
1471 EXPECT_TRUE(warning_set
.empty());
1472 EXPECT_EQ(2u, capturing_net_log
.GetSize());
1474 // Cancel redirect by redirecting to a different data:// URL. This needs
1475 // to create a conflict.
1476 GURL
new_url_3("data://something_totally_different");
1477 linked_ptr
<EventResponseDelta
> d3(
1478 new EventResponseDelta("extid3", base::Time::FromInternalValue(500)));
1479 d3
->new_url
= GURL(new_url_3
);
1480 deltas
.push_back(d3
);
1481 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1482 warning_set
.clear();
1483 capturing_net_log
.Clear();
1484 MergeOnBeforeRequestResponses(
1485 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1486 EXPECT_EQ(new_url_1
, effective_new_url
);
1487 EXPECT_EQ(1u, warning_set
.size());
1488 EXPECT_TRUE(HasWarning(warning_set
, "extid3"));
1489 EXPECT_EQ(3u, capturing_net_log
.GetSize());
1492 // This tests that we can redirect to about:blank, which is considered
1493 // a kind of cancelling requests.
1494 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeRequestResponses3
) {
1495 EventResponseDeltas deltas
;
1496 net::CapturingBoundNetLog capturing_net_log
;
1497 net::BoundNetLog net_log
= capturing_net_log
.bound();
1498 ExtensionWarningSet warning_set
;
1499 GURL effective_new_url
;
1502 GURL
new_url_0("http://foo.com");
1503 linked_ptr
<EventResponseDelta
> d0(
1504 new EventResponseDelta("extid0", base::Time::FromInternalValue(2000)));
1505 d0
->new_url
= GURL(new_url_0
);
1506 deltas
.push_back(d0
);
1507 MergeOnBeforeRequestResponses(
1508 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1509 EXPECT_EQ(new_url_0
, effective_new_url
);
1511 // Cancel request by redirecting to about:blank. This shall override
1512 // the other redirect but not cause any conflict warnings.
1513 GURL
new_url_1("about:blank");
1514 linked_ptr
<EventResponseDelta
> d1(
1515 new EventResponseDelta("extid1", base::Time::FromInternalValue(1500)));
1516 d1
->new_url
= GURL(new_url_1
);
1517 deltas
.push_back(d1
);
1518 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1519 warning_set
.clear();
1520 capturing_net_log
.Clear();
1521 MergeOnBeforeRequestResponses(
1522 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1523 EXPECT_EQ(new_url_1
, effective_new_url
);
1524 EXPECT_TRUE(warning_set
.empty());
1525 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1528 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeSendHeadersResponses
) {
1529 net::HttpRequestHeaders base_headers
;
1530 base_headers
.AddHeaderFromString("key1: value 1");
1531 base_headers
.AddHeaderFromString("key2: value 2");
1532 net::CapturingBoundNetLog capturing_net_log
;
1533 net::BoundNetLog net_log
= capturing_net_log
.bound();
1534 ExtensionWarningSet warning_set
;
1535 std::string header_value
;
1536 EventResponseDeltas deltas
;
1538 // Check that we can handle not changing the headers.
1539 linked_ptr
<EventResponseDelta
> d0(
1540 new EventResponseDelta("extid0", base::Time::FromInternalValue(2500)));
1541 deltas
.push_back(d0
);
1542 net::HttpRequestHeaders headers0
;
1543 headers0
.MergeFrom(base_headers
);
1544 MergeOnBeforeSendHeadersResponses(deltas
, &headers0
, &warning_set
, &net_log
);
1545 ASSERT_TRUE(headers0
.GetHeader("key1", &header_value
));
1546 EXPECT_EQ("value 1", header_value
);
1547 ASSERT_TRUE(headers0
.GetHeader("key2", &header_value
));
1548 EXPECT_EQ("value 2", header_value
);
1549 EXPECT_EQ(0u, warning_set
.size());
1550 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1552 // Delete, modify and add a header.
1553 linked_ptr
<EventResponseDelta
> d1(
1554 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
1555 d1
->deleted_request_headers
.push_back("key1");
1556 d1
->modified_request_headers
.AddHeaderFromString("key2: value 3");
1557 d1
->modified_request_headers
.AddHeaderFromString("key3: value 3");
1558 deltas
.push_back(d1
);
1559 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1560 warning_set
.clear();
1561 capturing_net_log
.Clear();
1562 net::HttpRequestHeaders headers1
;
1563 headers1
.MergeFrom(base_headers
);
1564 MergeOnBeforeSendHeadersResponses(deltas
, &headers1
, &warning_set
, &net_log
);
1565 EXPECT_FALSE(headers1
.HasHeader("key1"));
1566 ASSERT_TRUE(headers1
.GetHeader("key2", &header_value
));
1567 EXPECT_EQ("value 3", header_value
);
1568 ASSERT_TRUE(headers1
.GetHeader("key3", &header_value
));
1569 EXPECT_EQ("value 3", header_value
);
1570 EXPECT_EQ(0u, warning_set
.size());
1571 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1573 // Check that conflicts are atomic, i.e. if one header modification
1574 // collides all other conflicts of the same extension are declined as well.
1575 linked_ptr
<EventResponseDelta
> d2(
1576 new EventResponseDelta("extid2", base::Time::FromInternalValue(1500)));
1577 // This one conflicts:
1578 d2
->modified_request_headers
.AddHeaderFromString("key3: value 0");
1579 d2
->modified_request_headers
.AddHeaderFromString("key4: value 4");
1580 deltas
.push_back(d2
);
1581 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1582 warning_set
.clear();
1583 capturing_net_log
.Clear();
1584 net::HttpRequestHeaders headers2
;
1585 headers2
.MergeFrom(base_headers
);
1586 MergeOnBeforeSendHeadersResponses(deltas
, &headers2
, &warning_set
, &net_log
);
1587 EXPECT_FALSE(headers2
.HasHeader("key1"));
1588 ASSERT_TRUE(headers2
.GetHeader("key2", &header_value
));
1589 EXPECT_EQ("value 3", header_value
);
1590 ASSERT_TRUE(headers2
.GetHeader("key3", &header_value
));
1591 EXPECT_EQ("value 3", header_value
);
1592 EXPECT_FALSE(headers2
.HasHeader("key4"));
1593 EXPECT_EQ(1u, warning_set
.size());
1594 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1595 EXPECT_EQ(2u, capturing_net_log
.GetSize());
1597 // Check that identical modifications don't conflict and operations
1599 linked_ptr
<EventResponseDelta
> d3(
1600 new EventResponseDelta("extid3", base::Time::FromInternalValue(1000)));
1601 d3
->deleted_request_headers
.push_back("key1");
1602 d3
->modified_request_headers
.AddHeaderFromString("key2: value 3");
1603 d3
->modified_request_headers
.AddHeaderFromString("key5: value 5");
1604 deltas
.push_back(d3
);
1605 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1606 warning_set
.clear();
1607 capturing_net_log
.Clear();
1608 net::HttpRequestHeaders headers3
;
1609 headers3
.MergeFrom(base_headers
);
1610 MergeOnBeforeSendHeadersResponses(deltas
, &headers3
, &warning_set
, &net_log
);
1611 EXPECT_FALSE(headers3
.HasHeader("key1"));
1612 ASSERT_TRUE(headers3
.GetHeader("key2", &header_value
));
1613 EXPECT_EQ("value 3", header_value
);
1614 ASSERT_TRUE(headers3
.GetHeader("key3", &header_value
));
1615 EXPECT_EQ("value 3", header_value
);
1616 ASSERT_TRUE(headers3
.GetHeader("key5", &header_value
));
1617 EXPECT_EQ("value 5", header_value
);
1618 EXPECT_EQ(1u, warning_set
.size());
1619 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1620 EXPECT_EQ(3u, capturing_net_log
.GetSize());
1623 TEST(ExtensionWebRequestHelpersTest
,
1624 TestMergeOnBeforeSendHeadersResponses_Cookies
) {
1625 net::HttpRequestHeaders base_headers
;
1626 base_headers
.AddHeaderFromString(
1627 "Cookie: name=value; name2=value2; name3=\"value3\"");
1628 net::CapturingBoundNetLog capturing_net_log
;
1629 net::BoundNetLog net_log
= capturing_net_log
.bound();
1630 ExtensionWarningSet warning_set
;
1631 std::string header_value
;
1632 EventResponseDeltas deltas
;
1634 linked_ptr
<RequestCookieModification
> add_cookie
=
1635 make_linked_ptr(new RequestCookieModification
);
1636 add_cookie
->type
= helpers::ADD
;
1637 add_cookie
->modification
.reset(new helpers::RequestCookie
);
1638 add_cookie
->modification
->name
.reset(new std::string("name4"));
1639 add_cookie
->modification
->value
.reset(new std::string("\"value 4\""));
1641 linked_ptr
<RequestCookieModification
> add_cookie_2
=
1642 make_linked_ptr(new RequestCookieModification
);
1643 add_cookie_2
->type
= helpers::ADD
;
1644 add_cookie_2
->modification
.reset(new helpers::RequestCookie
);
1645 add_cookie_2
->modification
->name
.reset(new std::string("name"));
1646 add_cookie_2
->modification
->value
.reset(new std::string("new value"));
1648 linked_ptr
<RequestCookieModification
> edit_cookie
=
1649 make_linked_ptr(new RequestCookieModification
);
1650 edit_cookie
->type
= helpers::EDIT
;
1651 edit_cookie
->filter
.reset(new helpers::RequestCookie
);
1652 edit_cookie
->filter
->name
.reset(new std::string("name2"));
1653 edit_cookie
->modification
.reset(new helpers::RequestCookie
);
1654 edit_cookie
->modification
->value
.reset(new std::string("new value"));
1656 linked_ptr
<RequestCookieModification
> remove_cookie
=
1657 make_linked_ptr(new RequestCookieModification
);
1658 remove_cookie
->type
= helpers::REMOVE
;
1659 remove_cookie
->filter
.reset(new helpers::RequestCookie
);
1660 remove_cookie
->filter
->name
.reset(new std::string("name3"));
1662 linked_ptr
<RequestCookieModification
> operations
[] = {
1663 add_cookie
, add_cookie_2
, edit_cookie
, remove_cookie
1666 for (size_t i
= 0; i
< arraysize(operations
); ++i
) {
1667 linked_ptr
<EventResponseDelta
> delta(
1668 new EventResponseDelta("extid0", base::Time::FromInternalValue(i
* 5)));
1669 delta
->request_cookie_modifications
.push_back(operations
[i
]);
1670 deltas
.push_back(delta
);
1672 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1673 net::HttpRequestHeaders headers1
;
1674 headers1
.MergeFrom(base_headers
);
1675 warning_set
.clear();
1676 MergeOnBeforeSendHeadersResponses(deltas
, &headers1
, &warning_set
, &net_log
);
1677 EXPECT_TRUE(headers1
.HasHeader("Cookie"));
1678 ASSERT_TRUE(headers1
.GetHeader("Cookie", &header_value
));
1679 EXPECT_EQ("name=new value; name2=new value; name4=\"value 4\"", header_value
);
1680 EXPECT_EQ(0u, warning_set
.size());
1681 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1686 std::string
GetCookieExpirationDate(int delta_secs
) {
1687 const char* const kWeekDays
[] = {
1688 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1690 const char* const kMonthNames
[] = {
1691 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1692 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1695 Time::Exploded exploded_time
;
1696 (Time::Now() + TimeDelta::FromSeconds(delta_secs
)).UTCExplode(&exploded_time
);
1698 return base::StringPrintf("%s, %d %s %d %.2d:%.2d:%.2d GMT",
1699 kWeekDays
[exploded_time
.day_of_week
],
1700 exploded_time
.day_of_month
,
1701 kMonthNames
[exploded_time
.month
- 1],
1704 exploded_time
.minute
,
1705 exploded_time
.second
);
1710 TEST(ExtensionWebRequestHelpersTest
,
1711 TestMergeCookiesInOnHeadersReceivedResponses
) {
1712 net::CapturingBoundNetLog capturing_net_log
;
1713 net::BoundNetLog net_log
= capturing_net_log
.bound();
1714 ExtensionWarningSet warning_set
;
1715 std::string header_value
;
1716 EventResponseDeltas deltas
;
1718 std::string cookie_expiration
= GetCookieExpirationDate(1200);
1719 std::string base_headers_string
=
1720 "HTTP/1.0 200 OK\r\n"
1722 "Set-Cookie: name=value; DOMAIN=google.com; Secure\r\n"
1723 "Set-Cookie: name2=value2\r\n"
1724 "Set-Cookie: name3=value3\r\n"
1725 "Set-Cookie: lBound1=value5; Expires=" + cookie_expiration
+ "\r\n"
1726 "Set-Cookie: lBound2=value6; Max-Age=1200\r\n"
1727 "Set-Cookie: lBound3=value7; Max-Age=2000\r\n"
1728 "Set-Cookie: uBound1=value8; Expires=" + cookie_expiration
+ "\r\n"
1729 "Set-Cookie: uBound2=value9; Max-Age=1200\r\n"
1730 "Set-Cookie: uBound3=value10; Max-Age=2000\r\n"
1731 "Set-Cookie: uBound4=value11; Max-Age=2500\r\n"
1732 "Set-Cookie: uBound5=value12; Max-Age=600; Expires=" +
1733 cookie_expiration
+ "\r\n"
1734 "Set-Cookie: uBound6=removed; Max-Age=600\r\n"
1735 "Set-Cookie: sessionCookie=removed; Max-Age=INVALID\r\n"
1736 "Set-Cookie: sessionCookie2=removed\r\n"
1738 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
1739 new net::HttpResponseHeaders(
1740 net::HttpUtil::AssembleRawHeaders(
1741 base_headers_string
.c_str(), base_headers_string
.size())));
1743 // Check that we can handle if not touching the response headers.
1744 linked_ptr
<EventResponseDelta
> d0(
1745 new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
1746 deltas
.push_back(d0
);
1747 scoped_refptr
<net::HttpResponseHeaders
> new_headers0
;
1748 MergeCookiesInOnHeadersReceivedResponses(
1749 deltas
, base_headers
.get(), &new_headers0
, &warning_set
, &net_log
);
1750 EXPECT_FALSE(new_headers0
.get());
1751 EXPECT_EQ(0u, warning_set
.size());
1752 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1754 linked_ptr
<ResponseCookieModification
> add_cookie
=
1755 make_linked_ptr(new ResponseCookieModification
);
1756 add_cookie
->type
= helpers::ADD
;
1757 add_cookie
->modification
.reset(new helpers::ResponseCookie
);
1758 add_cookie
->modification
->name
.reset(new std::string("name4"));
1759 add_cookie
->modification
->value
.reset(new std::string("\"value4\""));
1761 linked_ptr
<ResponseCookieModification
> edit_cookie
=
1762 make_linked_ptr(new ResponseCookieModification
);
1763 edit_cookie
->type
= helpers::EDIT
;
1764 edit_cookie
->filter
.reset(new helpers::FilterResponseCookie
);
1765 edit_cookie
->filter
->name
.reset(new std::string("name2"));
1766 edit_cookie
->modification
.reset(new helpers::ResponseCookie
);
1767 edit_cookie
->modification
->value
.reset(new std::string("new value"));
1769 linked_ptr
<ResponseCookieModification
> edit_cookie_2
=
1770 make_linked_ptr(new ResponseCookieModification
);
1771 edit_cookie_2
->type
= helpers::EDIT
;
1772 edit_cookie_2
->filter
.reset(new helpers::FilterResponseCookie
);
1773 edit_cookie_2
->filter
->secure
.reset(new bool(false));
1774 edit_cookie_2
->modification
.reset(new helpers::ResponseCookie
);
1775 edit_cookie_2
->modification
->secure
.reset(new bool(true));
1777 // Tests 'ageLowerBound' filter when cookie lifetime is set
1778 // in cookie's 'max-age' attribute and its value is greater than
1779 // the filter's value.
1780 linked_ptr
<ResponseCookieModification
> edit_cookie_3
=
1781 make_linked_ptr(new ResponseCookieModification
);
1782 edit_cookie_3
->type
= helpers::EDIT
;
1783 edit_cookie_3
->filter
.reset(new helpers::FilterResponseCookie
);
1784 edit_cookie_3
->filter
->name
.reset(new std::string("lBound1"));
1785 edit_cookie_3
->filter
->age_lower_bound
.reset(new int(600));
1786 edit_cookie_3
->modification
.reset(new helpers::ResponseCookie
);
1787 edit_cookie_3
->modification
->value
.reset(new std::string("greater_1"));
1789 // Cookie lifetime is set in the cookie's 'expires' attribute.
1790 linked_ptr
<ResponseCookieModification
> edit_cookie_4
=
1791 make_linked_ptr(new ResponseCookieModification
);
1792 edit_cookie_4
->type
= helpers::EDIT
;
1793 edit_cookie_4
->filter
.reset(new helpers::FilterResponseCookie
);
1794 edit_cookie_4
->filter
->name
.reset(new std::string("lBound2"));
1795 edit_cookie_4
->filter
->age_lower_bound
.reset(new int(600));
1796 edit_cookie_4
->modification
.reset(new helpers::ResponseCookie
);
1797 edit_cookie_4
->modification
->value
.reset(new std::string("greater_2"));
1799 // Tests equality of the cookie lifetime with the filter value when
1800 // lifetime is set in the cookie's 'max-age' attribute.
1801 // Note: we don't test the equality when the lifetime is set in the 'expires'
1802 // attribute because the tests will be flaky. The reason is calculations will
1803 // depend on fetching the current time.
1804 linked_ptr
<ResponseCookieModification
> edit_cookie_5
=
1805 make_linked_ptr(new ResponseCookieModification
);
1806 edit_cookie_5
->type
= helpers::EDIT
;
1807 edit_cookie_5
->filter
.reset(new helpers::FilterResponseCookie
);
1808 edit_cookie_5
->filter
->name
.reset(new std::string("lBound3"));
1809 edit_cookie_5
->filter
->age_lower_bound
.reset(new int(2000));
1810 edit_cookie_5
->modification
.reset(new helpers::ResponseCookie
);
1811 edit_cookie_5
->modification
->value
.reset(new std::string("equal_2"));
1813 // Tests 'ageUpperBound' filter when cookie lifetime is set
1814 // in cookie's 'max-age' attribute and its value is lower than
1815 // the filter's value.
1816 linked_ptr
<ResponseCookieModification
> edit_cookie_6
=
1817 make_linked_ptr(new ResponseCookieModification
);
1818 edit_cookie_6
->type
= helpers::EDIT
;
1819 edit_cookie_6
->filter
.reset(new helpers::FilterResponseCookie
);
1820 edit_cookie_6
->filter
->name
.reset(new std::string("uBound1"));
1821 edit_cookie_6
->filter
->age_upper_bound
.reset(new int(2000));
1822 edit_cookie_6
->modification
.reset(new helpers::ResponseCookie
);
1823 edit_cookie_6
->modification
->value
.reset(new std::string("smaller_1"));
1825 // Cookie lifetime is set in the cookie's 'expires' attribute.
1826 linked_ptr
<ResponseCookieModification
> edit_cookie_7
=
1827 make_linked_ptr(new ResponseCookieModification
);
1828 edit_cookie_7
->type
= helpers::EDIT
;
1829 edit_cookie_7
->filter
.reset(new helpers::FilterResponseCookie
);
1830 edit_cookie_7
->filter
->name
.reset(new std::string("uBound2"));
1831 edit_cookie_7
->filter
->age_upper_bound
.reset(new int(2000));
1832 edit_cookie_7
->modification
.reset(new helpers::ResponseCookie
);
1833 edit_cookie_7
->modification
->value
.reset(new std::string("smaller_2"));
1835 // Tests equality of the cookie lifetime with the filter value when
1836 // lifetime is set in the cookie's 'max-age' attribute.
1837 linked_ptr
<ResponseCookieModification
> edit_cookie_8
=
1838 make_linked_ptr(new ResponseCookieModification
);
1839 edit_cookie_8
->type
= helpers::EDIT
;
1840 edit_cookie_8
->filter
.reset(new helpers::FilterResponseCookie
);
1841 edit_cookie_8
->filter
->name
.reset(new std::string("uBound3"));
1842 edit_cookie_8
->filter
->age_upper_bound
.reset(new int(2000));
1843 edit_cookie_8
->modification
.reset(new helpers::ResponseCookie
);
1844 edit_cookie_8
->modification
->value
.reset(new std::string("equal_4"));
1846 // Tests 'ageUpperBound' filter when cookie lifetime is greater
1847 // than the filter value. No modification is expected to be applied.
1848 linked_ptr
<ResponseCookieModification
> edit_cookie_9
=
1849 make_linked_ptr(new ResponseCookieModification
);
1850 edit_cookie_9
->type
= helpers::EDIT
;
1851 edit_cookie_9
->filter
.reset(new helpers::FilterResponseCookie
);
1852 edit_cookie_9
->filter
->name
.reset(new std::string("uBound4"));
1853 edit_cookie_9
->filter
->age_upper_bound
.reset(new int(2501));
1854 edit_cookie_9
->modification
.reset(new helpers::ResponseCookie
);
1855 edit_cookie_9
->modification
->value
.reset(new std::string("Will not change"));
1857 // Tests 'ageUpperBound' filter when both 'max-age' and 'expires' cookie
1858 // attributes are provided. 'expires' value matches the filter, however
1859 // no modification to the cookie is expected because 'max-age' overrides
1860 // 'expires' and it does not match the filter.
1861 linked_ptr
<ResponseCookieModification
> edit_cookie_10
=
1862 make_linked_ptr(new ResponseCookieModification
);
1863 edit_cookie_10
->type
= helpers::EDIT
;
1864 edit_cookie_10
->filter
.reset(new helpers::FilterResponseCookie
);
1865 edit_cookie_10
->filter
->name
.reset(new std::string("uBound5"));
1866 edit_cookie_10
->filter
->age_upper_bound
.reset(new int(800));
1867 edit_cookie_10
->modification
.reset(new helpers::ResponseCookie
);
1868 edit_cookie_10
->modification
->value
.reset(new std::string("Will not change"));
1870 linked_ptr
<ResponseCookieModification
> remove_cookie
=
1871 make_linked_ptr(new ResponseCookieModification
);
1872 remove_cookie
->type
= helpers::REMOVE
;
1873 remove_cookie
->filter
.reset(new helpers::FilterResponseCookie
);
1874 remove_cookie
->filter
->name
.reset(new std::string("name3"));
1876 linked_ptr
<ResponseCookieModification
> remove_cookie_2
=
1877 make_linked_ptr(new ResponseCookieModification
);
1878 remove_cookie_2
->type
= helpers::REMOVE
;
1879 remove_cookie_2
->filter
.reset(new helpers::FilterResponseCookie
);
1880 remove_cookie_2
->filter
->name
.reset(new std::string("uBound6"));
1881 remove_cookie_2
->filter
->age_upper_bound
.reset(new int(700));
1883 linked_ptr
<ResponseCookieModification
> remove_cookie_3
=
1884 make_linked_ptr(new ResponseCookieModification
);
1885 remove_cookie_3
->type
= helpers::REMOVE
;
1886 remove_cookie_3
->filter
.reset(new helpers::FilterResponseCookie
);
1887 remove_cookie_3
->filter
->name
.reset(new std::string("sessionCookie"));
1888 remove_cookie_3
->filter
->session_cookie
.reset(new bool(true));
1890 linked_ptr
<ResponseCookieModification
> remove_cookie_4
=
1891 make_linked_ptr(new ResponseCookieModification
);
1892 remove_cookie_4
->type
= helpers::REMOVE
;
1893 remove_cookie_4
->filter
.reset(new helpers::FilterResponseCookie
);
1894 remove_cookie_4
->filter
->name
.reset(new std::string("sessionCookie2"));
1895 remove_cookie_4
->filter
->session_cookie
.reset(new bool(true));
1897 linked_ptr
<ResponseCookieModification
> operations
[] = {
1898 add_cookie
, edit_cookie
, edit_cookie_2
, edit_cookie_3
, edit_cookie_4
,
1899 edit_cookie_5
, edit_cookie_6
, edit_cookie_7
, edit_cookie_8
,
1900 edit_cookie_9
, edit_cookie_10
, remove_cookie
, remove_cookie_2
,
1901 remove_cookie_3
, remove_cookie_4
1904 for (size_t i
= 0; i
< arraysize(operations
); ++i
) {
1905 linked_ptr
<EventResponseDelta
> delta(
1906 new EventResponseDelta("extid0", base::Time::FromInternalValue(i
* 5)));
1907 delta
->response_cookie_modifications
.push_back(operations
[i
]);
1908 deltas
.push_back(delta
);
1910 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1911 scoped_refptr
<net::HttpResponseHeaders
> headers1(
1912 new net::HttpResponseHeaders(
1913 net::HttpUtil::AssembleRawHeaders(
1914 base_headers_string
.c_str(), base_headers_string
.size())));
1915 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
1916 warning_set
.clear();
1917 MergeCookiesInOnHeadersReceivedResponses(
1918 deltas
, headers1
.get(), &new_headers1
, &warning_set
, &net_log
);
1920 EXPECT_TRUE(new_headers1
->HasHeader("Foo"));
1922 std::string cookie_string
;
1923 std::set
<std::string
> expected_cookies
;
1924 expected_cookies
.insert("name=value; domain=google.com; secure");
1925 expected_cookies
.insert("name2=value2; secure");
1926 expected_cookies
.insert("name4=\"value4\"; secure");
1927 expected_cookies
.insert(
1928 "lBound1=greater_1; expires=" + cookie_expiration
+ "; secure");
1929 expected_cookies
.insert("lBound2=greater_2; max-age=1200; secure");
1930 expected_cookies
.insert("lBound3=equal_2; max-age=2000; secure");
1931 expected_cookies
.insert(
1932 "uBound1=smaller_1; expires=" + cookie_expiration
+ "; secure");
1933 expected_cookies
.insert("uBound2=smaller_2; max-age=1200; secure");
1934 expected_cookies
.insert("uBound3=equal_4; max-age=2000; secure");
1935 expected_cookies
.insert("uBound4=value11; max-age=2500; secure");
1936 expected_cookies
.insert(
1937 "uBound5=value12; max-age=600; expires=" + cookie_expiration
+ "; secure");
1938 std::set
<std::string
> actual_cookies
;
1939 while (new_headers1
->EnumerateHeader(&iter
, "Set-Cookie", &cookie_string
))
1940 actual_cookies
.insert(cookie_string
);
1941 EXPECT_EQ(expected_cookies
, actual_cookies
);
1942 EXPECT_EQ(0u, warning_set
.size());
1943 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1946 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnHeadersReceivedResponses
) {
1947 net::CapturingBoundNetLog capturing_net_log
;
1948 net::BoundNetLog net_log
= capturing_net_log
.bound();
1949 ExtensionWarningSet warning_set
;
1950 std::string header_value
;
1951 EventResponseDeltas deltas
;
1953 char base_headers_string
[] =
1954 "HTTP/1.0 200 OK\r\n"
1956 "Key2: Value2, Foo\r\n"
1958 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
1959 new net::HttpResponseHeaders(
1960 net::HttpUtil::AssembleRawHeaders(
1961 base_headers_string
, sizeof(base_headers_string
))));
1963 // Check that we can handle if not touching the response headers.
1964 linked_ptr
<EventResponseDelta
> d0(
1965 new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
1966 deltas
.push_back(d0
);
1967 scoped_refptr
<net::HttpResponseHeaders
> new_headers0
;
1968 GURL allowed_unsafe_redirect_url0
;
1969 MergeOnHeadersReceivedResponses(deltas
,
1972 &allowed_unsafe_redirect_url0
,
1975 EXPECT_FALSE(new_headers0
.get());
1976 EXPECT_TRUE(allowed_unsafe_redirect_url0
.is_empty());
1977 EXPECT_EQ(0u, warning_set
.size());
1978 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1980 linked_ptr
<EventResponseDelta
> d1(
1981 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
1982 d1
->deleted_response_headers
.push_back(ResponseHeader("KEY1", "Value1"));
1983 d1
->deleted_response_headers
.push_back(ResponseHeader("KEY2", "Value2, Foo"));
1984 d1
->added_response_headers
.push_back(ResponseHeader("Key2", "Value3"));
1985 deltas
.push_back(d1
);
1986 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1987 warning_set
.clear();
1988 capturing_net_log
.Clear();
1989 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
1990 GURL allowed_unsafe_redirect_url1
;
1991 MergeOnHeadersReceivedResponses(deltas
,
1994 &allowed_unsafe_redirect_url1
,
1997 ASSERT_TRUE(new_headers1
.get());
1998 EXPECT_TRUE(allowed_unsafe_redirect_url1
.is_empty());
1999 std::multimap
<std::string
, std::string
> expected1
;
2000 expected1
.insert(std::pair
<std::string
, std::string
>("Key2", "Value3"));
2004 std::multimap
<std::string
, std::string
> actual1
;
2005 while (new_headers1
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
2006 actual1
.insert(std::pair
<std::string
, std::string
>(name
, value
));
2008 EXPECT_EQ(expected1
, actual1
);
2009 EXPECT_EQ(0u, warning_set
.size());
2010 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2012 // Check that we replace response headers only once.
2013 linked_ptr
<EventResponseDelta
> d2(
2014 new EventResponseDelta("extid2", base::Time::FromInternalValue(1500)));
2015 // Note that we use a different capitalization of KeY2. This should not
2017 d2
->deleted_response_headers
.push_back(ResponseHeader("KeY2", "Value2, Foo"));
2018 d2
->added_response_headers
.push_back(ResponseHeader("Key2", "Value4"));
2019 deltas
.push_back(d2
);
2020 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2021 warning_set
.clear();
2022 capturing_net_log
.Clear();
2023 scoped_refptr
<net::HttpResponseHeaders
> new_headers2
;
2024 GURL allowed_unsafe_redirect_url2
;
2025 MergeOnHeadersReceivedResponses(deltas
,
2028 &allowed_unsafe_redirect_url2
,
2031 ASSERT_TRUE(new_headers2
.get());
2032 EXPECT_TRUE(allowed_unsafe_redirect_url2
.is_empty());
2034 std::multimap
<std::string
, std::string
> actual2
;
2035 while (new_headers2
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
2036 actual2
.insert(std::pair
<std::string
, std::string
>(name
, value
));
2038 EXPECT_EQ(expected1
, actual2
);
2039 EXPECT_EQ(1u, warning_set
.size());
2040 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
2041 EXPECT_EQ(2u, capturing_net_log
.GetSize());
2044 // Check that we do not delete too much
2045 TEST(ExtensionWebRequestHelpersTest
,
2046 TestMergeOnHeadersReceivedResponsesDeletion
) {
2047 net::CapturingBoundNetLog capturing_net_log
;
2048 net::BoundNetLog net_log
= capturing_net_log
.bound();
2049 ExtensionWarningSet warning_set
;
2050 std::string header_value
;
2051 EventResponseDeltas deltas
;
2053 char base_headers_string
[] =
2054 "HTTP/1.0 200 OK\r\n"
2060 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
2061 new net::HttpResponseHeaders(
2062 net::HttpUtil::AssembleRawHeaders(
2063 base_headers_string
, sizeof(base_headers_string
))));
2065 linked_ptr
<EventResponseDelta
> d1(
2066 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
2067 d1
->deleted_response_headers
.push_back(ResponseHeader("KEY1", "Value2"));
2068 deltas
.push_back(d1
);
2069 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
2070 GURL allowed_unsafe_redirect_url1
;
2071 MergeOnHeadersReceivedResponses(deltas
,
2074 &allowed_unsafe_redirect_url1
,
2077 ASSERT_TRUE(new_headers1
.get());
2078 EXPECT_TRUE(allowed_unsafe_redirect_url1
.is_empty());
2079 std::multimap
<std::string
, std::string
> expected1
;
2080 expected1
.insert(std::pair
<std::string
, std::string
>("Key1", "Value1"));
2081 expected1
.insert(std::pair
<std::string
, std::string
>("Key1", "Value3"));
2082 expected1
.insert(std::pair
<std::string
, std::string
>("Key2", "Value4"));
2086 std::multimap
<std::string
, std::string
> actual1
;
2087 while (new_headers1
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
2088 actual1
.insert(std::pair
<std::string
, std::string
>(name
, value
));
2090 EXPECT_EQ(expected1
, actual1
);
2091 EXPECT_EQ(0u, warning_set
.size());
2092 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2095 // Tests whether onHeadersReceived can initiate a redirect.
2096 // The URL merge logic is shared with onBeforeRequest, so we only need to test
2097 // whether the URLs are merged at all.
2098 TEST(ExtensionWebRequestHelpersTest
,
2099 TestMergeOnHeadersReceivedResponsesRedirect
) {
2100 EventResponseDeltas deltas
;
2101 net::CapturingBoundNetLog capturing_net_log
;
2102 net::BoundNetLog net_log
= capturing_net_log
.bound();
2103 ExtensionWarningSet warning_set
;
2105 char base_headers_string
[] =
2106 "HTTP/1.0 200 OK\r\n"
2108 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
2109 new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
2110 base_headers_string
, sizeof(base_headers_string
))));
2113 linked_ptr
<EventResponseDelta
> d0(
2114 new EventResponseDelta("extid0", base::Time::FromInternalValue(0)));
2115 deltas
.push_back(d0
);
2116 scoped_refptr
<net::HttpResponseHeaders
> new_headers0
;
2117 GURL allowed_unsafe_redirect_url0
;
2118 MergeOnHeadersReceivedResponses(deltas
,
2121 &allowed_unsafe_redirect_url0
,
2124 EXPECT_FALSE(new_headers0
.get());
2125 EXPECT_TRUE(allowed_unsafe_redirect_url0
.is_empty());
2126 EXPECT_EQ(0u, warning_set
.size());
2127 EXPECT_EQ(0u, capturing_net_log
.GetSize());
2130 GURL
new_url_1("http://foo.com");
2131 linked_ptr
<EventResponseDelta
> d1(
2132 new EventResponseDelta("extid1", base::Time::FromInternalValue(1000)));
2133 d1
->new_url
= GURL(new_url_1
);
2134 deltas
.push_back(d1
);
2135 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2136 capturing_net_log
.Clear();
2137 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
2138 GURL allowed_unsafe_redirect_url1
;
2139 MergeOnHeadersReceivedResponses(deltas
,
2142 &allowed_unsafe_redirect_url1
,
2146 EXPECT_TRUE(new_headers1
.get());
2147 EXPECT_TRUE(new_headers1
->HasHeaderValue("Location", new_url_1
.spec()));
2148 EXPECT_EQ(new_url_1
, allowed_unsafe_redirect_url1
);
2149 EXPECT_TRUE(warning_set
.empty());
2150 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2153 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnAuthRequiredResponses
) {
2154 net::CapturingBoundNetLog capturing_net_log
;
2155 net::BoundNetLog net_log
= capturing_net_log
.bound();
2156 ExtensionWarningSet warning_set
;
2157 EventResponseDeltas deltas
;
2158 base::string16 username
= base::ASCIIToUTF16("foo");
2159 base::string16 password
= base::ASCIIToUTF16("bar");
2160 base::string16 password2
= base::ASCIIToUTF16("baz");
2162 // Check that we can handle if not returning credentials.
2163 linked_ptr
<EventResponseDelta
> d0(
2164 new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
2165 deltas
.push_back(d0
);
2166 net::AuthCredentials auth0
;
2167 bool credentials_set
= MergeOnAuthRequiredResponses(
2168 deltas
, &auth0
, &warning_set
, &net_log
);
2169 EXPECT_FALSE(credentials_set
);
2170 EXPECT_TRUE(auth0
.Empty());
2171 EXPECT_EQ(0u, warning_set
.size());
2172 EXPECT_EQ(0u, capturing_net_log
.GetSize());
2174 // Check that we can set AuthCredentials.
2175 linked_ptr
<EventResponseDelta
> d1(
2176 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
2177 d1
->auth_credentials
.reset(new net::AuthCredentials(username
, password
));
2178 deltas
.push_back(d1
);
2179 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2180 warning_set
.clear();
2181 capturing_net_log
.Clear();
2182 net::AuthCredentials auth1
;
2183 credentials_set
= MergeOnAuthRequiredResponses(
2184 deltas
, &auth1
, &warning_set
, &net_log
);
2185 EXPECT_TRUE(credentials_set
);
2186 EXPECT_FALSE(auth1
.Empty());
2187 EXPECT_EQ(username
, auth1
.username());
2188 EXPECT_EQ(password
, auth1
.password());
2189 EXPECT_EQ(0u, warning_set
.size());
2190 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2192 // Check that we set AuthCredentials only once.
2193 linked_ptr
<EventResponseDelta
> d2(
2194 new EventResponseDelta("extid2", base::Time::FromInternalValue(1500)));
2195 d2
->auth_credentials
.reset(new net::AuthCredentials(username
, password2
));
2196 deltas
.push_back(d2
);
2197 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2198 warning_set
.clear();
2199 capturing_net_log
.Clear();
2200 net::AuthCredentials auth2
;
2201 credentials_set
= MergeOnAuthRequiredResponses(
2202 deltas
, &auth2
, &warning_set
, &net_log
);
2203 EXPECT_TRUE(credentials_set
);
2204 EXPECT_FALSE(auth2
.Empty());
2205 EXPECT_EQ(username
, auth1
.username());
2206 EXPECT_EQ(password
, auth1
.password());
2207 EXPECT_EQ(1u, warning_set
.size());
2208 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
2209 EXPECT_EQ(2u, capturing_net_log
.GetSize());
2211 // Check that we can set identical AuthCredentials twice without causing
2213 linked_ptr
<EventResponseDelta
> d3(
2214 new EventResponseDelta("extid3", base::Time::FromInternalValue(1000)));
2215 d3
->auth_credentials
.reset(new net::AuthCredentials(username
, password
));
2216 deltas
.push_back(d3
);
2217 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2218 warning_set
.clear();
2219 capturing_net_log
.Clear();
2220 net::AuthCredentials auth3
;
2221 credentials_set
= MergeOnAuthRequiredResponses(
2222 deltas
, &auth3
, &warning_set
, &net_log
);
2223 EXPECT_TRUE(credentials_set
);
2224 EXPECT_FALSE(auth3
.Empty());
2225 EXPECT_EQ(username
, auth1
.username());
2226 EXPECT_EQ(password
, auth1
.password());
2227 EXPECT_EQ(1u, warning_set
.size());
2228 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
2229 EXPECT_EQ(3u, capturing_net_log
.GetSize());
2232 } // namespace extensions