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/location.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/prefs/pref_member.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/stl_util.h"
20 #include "base/strings/string_piece.h"
21 #include "base/strings/string_split.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/thread_task_runner_handle.h"
25 #include "base/time/time.h"
26 #include "chrome/browser/content_settings/cookie_settings_factory.h"
27 #include "chrome/browser/extensions/event_router_forwarder.h"
28 #include "chrome/browser/net/chrome_network_delegate.h"
29 #include "chrome/test/base/testing_browser_process.h"
30 #include "chrome/test/base/testing_pref_service_syncable.h"
31 #include "chrome/test/base/testing_profile.h"
32 #include "chrome/test/base/testing_profile_manager.h"
33 #include "components/about_handler/about_protocol_handler.h"
34 #include "components/content_settings/core/browser/cookie_settings.h"
35 #include "content/public/common/url_constants.h"
36 #include "content/public/test/test_browser_thread_bundle.h"
37 #include "extensions/browser/api/web_request/upload_data_presenter.h"
38 #include "extensions/browser/api/web_request/web_request_api.h"
39 #include "extensions/browser/api/web_request/web_request_api_constants.h"
40 #include "extensions/browser/api/web_request/web_request_api_helpers.h"
41 #include "extensions/browser/warning_set.h"
42 #include "extensions/common/api/web_request.h"
43 #include "extensions/common/extension_messages.h"
44 #include "extensions/common/features/feature.h"
45 #include "net/base/auth.h"
46 #include "net/base/elements_upload_data_stream.h"
47 #include "net/base/net_util.h"
48 #include "net/base/request_priority.h"
49 #include "net/base/upload_bytes_element_reader.h"
50 #include "net/base/upload_file_element_reader.h"
51 #include "net/dns/mock_host_resolver.h"
52 #include "net/log/test_net_log.h"
53 #include "net/url_request/url_request_job_factory_impl.h"
54 #include "net/url_request/url_request_test_util.h"
55 #include "testing/gtest/include/gtest/gtest-message.h"
56 #include "testing/gtest/include/gtest/gtest.h"
58 namespace helpers
= extension_web_request_api_helpers
;
59 namespace keys
= extension_web_request_api_constants
;
60 namespace web_request
= extensions::api::web_request
;
62 using base::BinaryValue
;
63 using base::DictionaryValue
;
64 using base::ListValue
;
65 using base::StringValue
;
67 using base::TimeDelta
;
69 using helpers::CalculateOnAuthRequiredDelta
;
70 using helpers::CalculateOnBeforeRequestDelta
;
71 using helpers::CalculateOnBeforeSendHeadersDelta
;
72 using helpers::CalculateOnHeadersReceivedDelta
;
73 using helpers::CharListToString
;
74 using helpers::EventResponseDelta
;
75 using helpers::EventResponseDeltas
;
76 using helpers::EventResponseDeltas
;
77 using helpers::InDecreasingExtensionInstallationTimeOrder
;
78 using helpers::MergeCancelOfResponses
;
79 using helpers::MergeOnBeforeRequestResponses
;
80 using helpers::RequestCookieModification
;
81 using helpers::ResponseCookieModification
;
82 using helpers::ResponseHeader
;
83 using helpers::ResponseHeaders
;
84 using helpers::StringToCharList
;
86 namespace extensions
{
89 static void EventHandledOnIOThread(
91 const std::string
& extension_id
,
92 const std::string
& event_name
,
93 const std::string
& sub_event_name
,
95 ExtensionWebRequestEventRouter::EventResponse
* response
) {
96 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
97 profile
, extension_id
, event_name
, sub_event_name
, request_id
,
101 // Searches |key| in |collection| by iterating over its elements and returns
103 template <typename Collection
, typename Key
>
104 bool Contains(const Collection
& collection
, const Key
& key
) {
105 return std::find(collection
.begin(), collection
.end(), key
) !=
109 // Returns whether |warnings| contains an extension for |extension_id|.
110 bool HasWarning(const WarningSet
& warnings
,
111 const std::string
& extension_id
) {
112 for (WarningSet::const_iterator i
= warnings
.begin();
113 i
!= warnings
.end(); ++i
) {
114 if (i
->extension_id() == extension_id
)
120 // Parses the JSON data attached to the |message| and tries to return it.
121 // |param| must outlive |out|. Returns NULL on failure.
122 void GetPartOfMessageArguments(IPC::Message
* message
,
123 const base::DictionaryValue
** out
,
124 ExtensionMsg_MessageInvoke::Param
* param
) {
125 ASSERT_EQ(ExtensionMsg_MessageInvoke::ID
, message
->type());
126 ASSERT_TRUE(ExtensionMsg_MessageInvoke::Read(message
, param
));
127 ASSERT_GE(base::get
<3>(*param
).GetSize(), 2u);
128 const base::Value
* value
= NULL
;
129 ASSERT_TRUE(base::get
<3>(*param
).Get(1, &value
));
130 const base::ListValue
* list
= NULL
;
131 ASSERT_TRUE(value
->GetAsList(&list
));
132 ASSERT_EQ(1u, list
->GetSize());
133 ASSERT_TRUE(list
->GetDictionary(0, out
));
138 // A mock event router that responds to events with a pre-arranged queue of
140 class TestIPCSender
: public IPC::Sender
{
142 typedef std::list
<linked_ptr
<IPC::Message
> > SentMessages
;
144 // Adds a Task to the queue. We will fire these in order as events are
146 void PushTask(const base::Closure
& task
) {
147 task_queue_
.push(task
);
150 size_t GetNumTasks() { return task_queue_
.size(); }
152 SentMessages::const_iterator
sent_begin() const {
153 return sent_messages_
.begin();
156 SentMessages::const_iterator
sent_end() const {
157 return sent_messages_
.end();
162 bool Send(IPC::Message
* message
) override
{
163 EXPECT_EQ(ExtensionMsg_MessageInvoke::ID
, message
->type());
165 EXPECT_FALSE(task_queue_
.empty());
166 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
167 task_queue_
.front());
170 sent_messages_
.push_back(linked_ptr
<IPC::Message
>(message
));
174 std::queue
<base::Closure
> task_queue_
;
175 SentMessages sent_messages_
;
178 class ExtensionWebRequestTest
: public testing::Test
{
180 ExtensionWebRequestTest()
181 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
182 profile_manager_(TestingBrowserProcess::GetGlobal()),
183 event_router_(new EventRouterForwarder
) {}
186 void SetUp() override
{
187 ASSERT_TRUE(profile_manager_
.SetUp());
188 ChromeNetworkDelegate::InitializePrefsOnUIThread(
189 &enable_referrers_
, NULL
, NULL
, NULL
,
190 profile_
.GetTestingPrefService());
191 network_delegate_
.reset(
192 new ChromeNetworkDelegate(event_router_
.get(), &enable_referrers_
));
193 network_delegate_
->set_profile(&profile_
);
194 network_delegate_
->set_cookie_settings(
195 CookieSettingsFactory::GetForProfile(&profile_
).get());
196 context_
.reset(new net::TestURLRequestContext(true));
197 context_
->set_network_delegate(network_delegate_
.get());
201 // Fires a URLRequest with the specified |method|, |content_type| and three
202 // elements of upload data: bytes_1, a dummy empty file, bytes_2.
203 void FireURLRequestWithData(const std::string
& method
,
204 const char* content_type
,
205 const std::vector
<char>& bytes_1
,
206 const std::vector
<char>& bytes_2
);
208 content::TestBrowserThreadBundle thread_bundle_
;
209 TestingProfile profile_
;
210 TestingProfileManager profile_manager_
;
211 net::TestDelegate delegate_
;
212 BooleanPrefMember enable_referrers_
;
213 TestIPCSender ipc_sender_
;
214 scoped_refptr
<EventRouterForwarder
> event_router_
;
215 scoped_refptr
<InfoMap
> extension_info_map_
;
216 scoped_ptr
<ChromeNetworkDelegate
> network_delegate_
;
217 scoped_ptr
<net::TestURLRequestContext
> context_
;
220 // Tests that we handle disagreements among extensions about responses to
221 // blocking events (redirection) by choosing the response from the
222 // most-recently-installed extension.
223 TEST_F(ExtensionWebRequestTest
, BlockingEventPrecedenceRedirect
) {
224 std::string
extension1_id("1");
225 std::string
extension2_id("2");
226 ExtensionWebRequestEventRouter::RequestFilter filter
;
227 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
228 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
229 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
230 &profile_
, extension1_id
, extension1_id
, events::FOR_TEST
, kEventName
,
231 kEventName
+ "/1", filter
,
232 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
233 ipc_sender_factory
.GetWeakPtr());
234 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
235 &profile_
, extension2_id
, extension2_id
, events::FOR_TEST
, kEventName
,
236 kEventName
+ "/2", filter
,
237 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
238 ipc_sender_factory
.GetWeakPtr());
240 net::URLRequestJobFactoryImpl job_factory
;
241 job_factory
.SetProtocolHandler(
243 make_scoped_ptr(new about_handler::AboutProtocolHandler()));
244 context_
->set_job_factory(&job_factory
);
246 GURL
redirect_url("about:redirected");
247 GURL
not_chosen_redirect_url("about:not_chosen");
249 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
250 GURL("about:blank"), net::DEFAULT_PRIORITY
, &delegate_
));
252 // onBeforeRequest will be dispatched twice initially. The second response -
253 // the redirect - should win, since it has a later |install_time|. The
254 // redirect will dispatch another pair of onBeforeRequest. There, the first
255 // response should win (later |install_time|).
256 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
258 // Extension1 response. Arrives first, but ignored due to install_time.
259 response
= new ExtensionWebRequestEventRouter::EventResponse(
260 extension1_id
, base::Time::FromDoubleT(1));
261 response
->new_url
= not_chosen_redirect_url
;
262 ipc_sender_
.PushTask(
263 base::Bind(&EventHandledOnIOThread
,
264 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
265 request
->identifier(), response
));
267 // Extension2 response. Arrives second, and chosen because of install_time.
268 response
= new ExtensionWebRequestEventRouter::EventResponse(
269 extension2_id
, base::Time::FromDoubleT(2));
270 response
->new_url
= redirect_url
;
271 ipc_sender_
.PushTask(
272 base::Bind(&EventHandledOnIOThread
,
273 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
274 request
->identifier(), response
));
276 // Extension2 response to the redirected URL. Arrives first, and chosen.
277 response
= new ExtensionWebRequestEventRouter::EventResponse(
278 extension2_id
, base::Time::FromDoubleT(2));
279 ipc_sender_
.PushTask(
280 base::Bind(&EventHandledOnIOThread
,
281 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
282 request
->identifier(), response
));
284 // Extension1 response to the redirected URL. Arrives second, and ignored.
285 response
= new ExtensionWebRequestEventRouter::EventResponse(
286 extension1_id
, base::Time::FromDoubleT(1));
287 ipc_sender_
.PushTask(
288 base::Bind(&EventHandledOnIOThread
,
289 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
290 request
->identifier(), response
));
293 base::MessageLoop::current()->Run();
295 EXPECT_TRUE(!request
->is_pending());
296 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, request
->status().status());
297 EXPECT_EQ(0, request
->status().error());
298 EXPECT_EQ(redirect_url
, request
->url());
299 EXPECT_EQ(2U, request
->url_chain().size());
300 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
303 // Now test the same thing but the extensions answer in reverse order.
304 scoped_ptr
<net::URLRequest
> request2(context_
->CreateRequest(
305 GURL("about:blank"), net::DEFAULT_PRIORITY
, &delegate_
));
307 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
309 // Extension2 response. Arrives first, and chosen because of install_time.
310 response
= new ExtensionWebRequestEventRouter::EventResponse(
311 extension2_id
, base::Time::FromDoubleT(2));
312 response
->new_url
= redirect_url
;
313 ipc_sender_
.PushTask(
314 base::Bind(&EventHandledOnIOThread
,
315 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
316 request2
->identifier(), response
));
318 // Extension1 response. Arrives second, but ignored due to install_time.
319 response
= new ExtensionWebRequestEventRouter::EventResponse(
320 extension1_id
, base::Time::FromDoubleT(1));
321 response
->new_url
= not_chosen_redirect_url
;
322 ipc_sender_
.PushTask(
323 base::Bind(&EventHandledOnIOThread
,
324 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
325 request2
->identifier(), response
));
327 // Extension2 response to the redirected URL. Arrives first, and chosen.
328 response
= new ExtensionWebRequestEventRouter::EventResponse(
329 extension2_id
, base::Time::FromDoubleT(2));
330 ipc_sender_
.PushTask(
331 base::Bind(&EventHandledOnIOThread
,
332 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
333 request2
->identifier(), response
));
335 // Extension1 response to the redirected URL. Arrives second, and ignored.
336 response
= new ExtensionWebRequestEventRouter::EventResponse(
337 extension1_id
, base::Time::FromDoubleT(1));
338 ipc_sender_
.PushTask(
339 base::Bind(&EventHandledOnIOThread
,
340 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
341 request2
->identifier(), response
));
344 base::MessageLoop::current()->Run();
346 EXPECT_TRUE(!request2
->is_pending());
347 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, request2
->status().status());
348 EXPECT_EQ(0, request2
->status().error());
349 EXPECT_EQ(redirect_url
, request2
->url());
350 EXPECT_EQ(2U, request2
->url_chain().size());
351 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
354 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
355 &profile_
, extension1_id
, kEventName
+ "/1", 0, 0);
356 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
357 &profile_
, extension2_id
, kEventName
+ "/2", 0, 0);
360 // Test that a request is canceled if this is requested by any extension
361 // regardless whether it is the extension with the highest precedence.
362 TEST_F(ExtensionWebRequestTest
, BlockingEventPrecedenceCancel
) {
363 std::string
extension1_id("1");
364 std::string
extension2_id("2");
365 ExtensionWebRequestEventRouter::RequestFilter filter
;
366 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
367 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
368 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
369 &profile_
, extension1_id
, extension1_id
, events::FOR_TEST
, kEventName
,
370 kEventName
+ "/1", filter
,
371 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
372 ipc_sender_factory
.GetWeakPtr());
373 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
374 &profile_
, extension2_id
, extension2_id
, events::FOR_TEST
, kEventName
,
375 kEventName
+ "/2", filter
,
376 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
377 ipc_sender_factory
.GetWeakPtr());
379 GURL
request_url("about:blank");
380 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
381 request_url
, net::DEFAULT_PRIORITY
, &delegate_
));
383 // onBeforeRequest will be dispatched twice. The second response -
384 // the redirect - would win, since it has a later |install_time|, but
385 // the first response takes precedence because cancel >> redirect.
386 GURL
redirect_url("about:redirected");
387 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
389 // Extension1 response. Arrives first, would be ignored in principle due to
390 // install_time but "cancel" always wins.
391 response
= new ExtensionWebRequestEventRouter::EventResponse(
392 extension1_id
, base::Time::FromDoubleT(1));
393 response
->cancel
= true;
394 ipc_sender_
.PushTask(
395 base::Bind(&EventHandledOnIOThread
,
396 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
397 request
->identifier(), response
));
399 // Extension2 response. Arrives second, but has higher precedence
400 // due to its later install_time.
401 response
= new ExtensionWebRequestEventRouter::EventResponse(
402 extension2_id
, base::Time::FromDoubleT(2));
403 response
->new_url
= redirect_url
;
404 ipc_sender_
.PushTask(
405 base::Bind(&EventHandledOnIOThread
,
406 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
407 request
->identifier(), response
));
411 base::MessageLoop::current()->Run();
413 EXPECT_TRUE(!request
->is_pending());
414 EXPECT_EQ(net::URLRequestStatus::FAILED
, request
->status().status());
415 EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT
, request
->status().error());
416 EXPECT_EQ(request_url
, request
->url());
417 EXPECT_EQ(1U, request
->url_chain().size());
418 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
420 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
421 &profile_
, extension1_id
, kEventName
+ "/1", 0, 0);
422 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
423 &profile_
, extension2_id
, kEventName
+ "/2", 0, 0);
426 TEST_F(ExtensionWebRequestTest
, SimulateChancelWhileBlocked
) {
427 // We subscribe to OnBeforeRequest and OnErrorOccurred.
428 // While the OnBeforeRequest handler is blocked, we cancel the request.
429 // We verify that the response of the blocked OnBeforeRequest handler
432 std::string
extension_id("1");
433 ExtensionWebRequestEventRouter::RequestFilter filter
;
435 // Subscribe to OnBeforeRequest and OnErrorOccurred.
436 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
437 const std::string
kEventName2(web_request::OnErrorOccurred::kEventName
);
438 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
439 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
440 &profile_
, extension_id
, extension_id
, events::FOR_TEST
, kEventName
,
441 kEventName
+ "/1", filter
,
442 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
443 ipc_sender_factory
.GetWeakPtr());
444 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
445 &profile_
, extension_id
, extension_id
, events::FOR_TEST
, kEventName2
,
446 kEventName2
+ "/1", filter
, 0, 0, 0, ipc_sender_factory
.GetWeakPtr());
448 GURL
request_url("about:blank");
449 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
450 request_url
, net::DEFAULT_PRIORITY
, &delegate_
));
452 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
454 // Extension response for the OnBeforeRequest handler. This should not be
455 // processed because request is canceled before the handler responds.
456 response
= new ExtensionWebRequestEventRouter::EventResponse(
457 extension_id
, base::Time::FromDoubleT(1));
458 GURL
redirect_url("about:redirected");
459 response
->new_url
= redirect_url
;
460 ipc_sender_
.PushTask(
461 base::Bind(&EventHandledOnIOThread
,
462 &profile_
, extension_id
, kEventName
, kEventName
+ "/1",
463 request
->identifier(), response
));
465 // Extension response for OnErrorOccurred: Terminate the message loop.
466 ipc_sender_
.PushTask(
467 base::Bind(&base::MessageLoop::PostTask
,
468 base::Unretained(base::MessageLoop::current()),
469 FROM_HERE
, base::MessageLoop::QuitClosure()));
472 // request->Start() will have submitted OnBeforeRequest by the time we cancel.
474 base::MessageLoop::current()->Run();
476 EXPECT_TRUE(!request
->is_pending());
477 EXPECT_EQ(net::URLRequestStatus::CANCELED
, request
->status().status());
478 EXPECT_EQ(net::ERR_ABORTED
, request
->status().error());
479 EXPECT_EQ(request_url
, request
->url());
480 EXPECT_EQ(1U, request
->url_chain().size());
481 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
483 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
484 &profile_
, extension_id
, kEventName
+ "/1", 0, 0);
485 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
486 &profile_
, extension_id
, kEventName2
+ "/1", 0, 0);
491 // Create the numerical representation of |values|, strings passed as
492 // extraInfoSpec by the event handler. Returns true on success, otherwise false.
493 bool GenerateInfoSpec(const std::string
& values
, int* result
) {
494 // Create a base::ListValue of strings.
495 base::ListValue list_value
;
496 for (const std::string
& cur
:
497 base::SplitString(values
, ",", base::KEEP_WHITESPACE
,
498 base::SPLIT_WANT_NONEMPTY
))
499 list_value
.Append(new base::StringValue(cur
));
500 return ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
506 void ExtensionWebRequestTest::FireURLRequestWithData(
507 const std::string
& method
,
508 const char* content_type
,
509 const std::vector
<char>& bytes_1
,
510 const std::vector
<char>& bytes_2
) {
511 // The request URL can be arbitrary but must have an HTTP or HTTPS scheme.
512 GURL
request_url("http://www.example.com");
513 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
514 request_url
, net::DEFAULT_PRIORITY
, &delegate_
));
515 request
->set_method(method
);
516 if (content_type
!= NULL
) {
517 request
->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kContentType
,
519 true /* overwrite */);
521 ScopedVector
<net::UploadElementReader
> element_readers
;
522 element_readers
.push_back(new net::UploadBytesElementReader(
523 &(bytes_1
[0]), bytes_1
.size()));
524 element_readers
.push_back(
525 new net::UploadFileElementReader(
526 base::ThreadTaskRunnerHandle::Get()
532 element_readers
.push_back(
533 new net::UploadBytesElementReader(&(bytes_2
[0]), bytes_2
.size()));
534 request
->set_upload(make_scoped_ptr(
535 new net::ElementsUploadDataStream(element_readers
.Pass(), 0)));
536 ipc_sender_
.PushTask(base::Bind(&base::DoNothing
));
540 TEST_F(ExtensionWebRequestTest
, AccessRequestBodyData
) {
541 // We verify that URLRequest body is accessible to OnBeforeRequest listeners.
542 // These testing steps are repeated twice in a row:
543 // 1. Register an extension requesting "requestBody" in ExtraInfoSpec and
544 // file a POST URLRequest with a multipart-encoded form. See it getting
546 // 2. Do the same, but without requesting "requestBody". Nothing should be
548 // 3. With "requestBody", fire a POST URLRequest which is not a parseable
549 // HTML form. Raw data should be returned.
550 // 4. Do the same, but with a PUT method. Result should be the same.
551 const std::string
kMethodPost("POST");
552 const std::string
kMethodPut("PUT");
555 const char kPlainBlock1
[] = "abcd\n";
556 const size_t kPlainBlock1Length
= sizeof(kPlainBlock1
) - 1;
557 std::vector
<char> plain_1(kPlainBlock1
, kPlainBlock1
+ kPlainBlock1Length
);
558 const char kPlainBlock2
[] = "1234\n";
559 const size_t kPlainBlock2Length
= sizeof(kPlainBlock2
) - 1;
560 std::vector
<char> plain_2(kPlainBlock2
, kPlainBlock2
+ kPlainBlock2Length
);
561 #define kBoundary "THIS_IS_A_BOUNDARY"
562 const char kFormBlock1
[] = "--" kBoundary
"\r\n"
563 "Content-Disposition: form-data; name=\"A\"\r\n"
566 "--" kBoundary
"\r\n"
567 "Content-Disposition: form-data; name=\"B\"; filename=\"\"\r\n"
568 "Content-Type: application/octet-stream\r\n"
570 std::vector
<char> form_1(kFormBlock1
, kFormBlock1
+ sizeof(kFormBlock1
) - 1);
571 const char kFormBlock2
[] = "\r\n"
572 "--" kBoundary
"\r\n"
573 "Content-Disposition: form-data; name=\"C\"\r\n"
577 std::vector
<char> form_2(kFormBlock2
, kFormBlock2
+ sizeof(kFormBlock2
) - 1);
580 // Paths to look for in returned dictionaries.
581 const std::string
kBodyPath(keys::kRequestBodyKey
);
582 const std::string
kFormDataPath(
583 kBodyPath
+ "." + keys::kRequestBodyFormDataKey
);
584 const std::string
kRawPath(kBodyPath
+ "." + keys::kRequestBodyRawKey
);
585 const std::string
kErrorPath(kBodyPath
+ "." + keys::kRequestBodyErrorKey
);
586 const std::string
* const kPath
[] = {
592 // Contents of formData.
593 const char kFormData
[] =
594 "{\"A\":[\"test text\"],\"B\":[\"\"],\"C\":[\"test password\"]}";
595 scoped_ptr
<const base::Value
> form_data(
596 base::JSONReader::DeprecatedRead(kFormData
));
597 ASSERT_TRUE(form_data
.get() != NULL
);
598 ASSERT_TRUE(form_data
->GetType() == base::Value::TYPE_DICTIONARY
);
601 extensions::subtle::AppendKeyValuePair(
602 keys::kRequestBodyRawBytesKey
,
603 BinaryValue::CreateWithCopiedBuffer(kPlainBlock1
, kPlainBlock1Length
),
605 extensions::subtle::AppendKeyValuePair(
606 keys::kRequestBodyRawFileKey
,
607 new base::StringValue(std::string()),
609 extensions::subtle::AppendKeyValuePair(
610 keys::kRequestBodyRawBytesKey
,
611 BinaryValue::CreateWithCopiedBuffer(kPlainBlock2
, kPlainBlock2Length
),
614 const base::Value
* const kExpected
[] = {
620 static_assert(arraysize(kPath
) == arraysize(kExpected
),
621 "kPath and kExpected arrays should have the same number "
624 const char kMultipart
[] = "multipart/form-data; boundary=" kBoundary
;
627 // Set up a dummy extension name.
628 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
629 ExtensionWebRequestEventRouter::RequestFilter filter
;
630 std::string
extension_id("1");
631 const std::string
string_spec_post("blocking,requestBody");
632 const std::string
string_spec_no_post("blocking");
633 int extra_info_spec_empty
= 0;
634 int extra_info_spec_body
= 0;
635 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
638 // Subscribe to OnBeforeRequest with requestBody requirement.
639 ASSERT_TRUE(GenerateInfoSpec(string_spec_post
, &extra_info_spec_body
));
640 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
641 &profile_
, extension_id
, extension_id
, events::FOR_TEST
, kEventName
,
642 kEventName
+ "/1", filter
, extra_info_spec_body
, 0, 0,
643 ipc_sender_factory
.GetWeakPtr());
645 FireURLRequestWithData(kMethodPost
, kMultipart
, form_1
, form_2
);
647 // We inspect the result in the message list of |ipc_sender_| later.
648 base::MessageLoop::current()->RunUntilIdle();
650 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
651 &profile_
, extension_id
, kEventName
+ "/1", 0, 0);
654 // Now subscribe to OnBeforeRequest *without* the requestBody requirement.
656 GenerateInfoSpec(string_spec_no_post
, &extra_info_spec_empty
));
657 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
658 &profile_
, extension_id
, extension_id
, events::FOR_TEST
, kEventName
,
659 kEventName
+ "/1", filter
, extra_info_spec_empty
, 0, 0,
660 ipc_sender_factory
.GetWeakPtr());
662 FireURLRequestWithData(kMethodPost
, kMultipart
, form_1
, form_2
);
664 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
665 &profile_
, extension_id
, kEventName
+ "/1", 0, 0);
667 // Subscribe to OnBeforeRequest with requestBody requirement.
668 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
669 &profile_
, extension_id
, extension_id
, events::FOR_TEST
, kEventName
,
670 kEventName
+ "/1", filter
, extra_info_spec_body
, 0, 0,
671 ipc_sender_factory
.GetWeakPtr());
674 // Now send a POST request with body which is not parseable as a form.
675 FireURLRequestWithData(kMethodPost
, NULL
/*no header*/, plain_1
, plain_2
);
678 // Now send a PUT request with the same body as above.
679 FireURLRequestWithData(kMethodPut
, NULL
/*no header*/, plain_1
, plain_2
);
681 base::MessageLoop::current()->RunUntilIdle();
684 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
685 &profile_
, extension_id
, kEventName
+ "/1", 0, 0);
687 IPC::Message
* message
= NULL
;
688 TestIPCSender::SentMessages::const_iterator i
= ipc_sender_
.sent_begin();
689 for (size_t test
= 0; test
< arraysize(kExpected
); ++test
) {
690 SCOPED_TRACE(testing::Message("iteration number ") << test
);
691 EXPECT_NE(i
, ipc_sender_
.sent_end());
692 message
= (i
++)->get();
693 const base::DictionaryValue
* details
;
694 ExtensionMsg_MessageInvoke::Param param
;
695 GetPartOfMessageArguments(message
, &details
, ¶m
);
696 ASSERT_TRUE(details
!= NULL
);
697 const base::Value
* result
= NULL
;
698 if (kExpected
[test
]) {
699 EXPECT_TRUE(details
->Get(*(kPath
[test
]), &result
));
700 EXPECT_TRUE(kExpected
[test
]->Equals(result
));
702 EXPECT_FALSE(details
->Get(*(kPath
[test
]), &result
));
706 EXPECT_EQ(i
, ipc_sender_
.sent_end());
709 TEST_F(ExtensionWebRequestTest
, NoAccessRequestBodyData
) {
710 // We verify that URLRequest body is NOT accessible to OnBeforeRequest
711 // listeners when the type of the request is different from POST or PUT, or
712 // when the request body is empty. 3 requests are fired, without upload data,
713 // a POST, PUT and GET request. For none of them the "requestBody" object
714 // property should be present in the details passed to the onBeforeRequest
716 const char* const kMethods
[] = { "POST", "PUT", "GET" };
718 // Set up a dummy extension name.
719 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
720 ExtensionWebRequestEventRouter::RequestFilter filter
;
721 const std::string
extension_id("1");
722 int extra_info_spec
= 0;
723 ASSERT_TRUE(GenerateInfoSpec("blocking,requestBody", &extra_info_spec
));
724 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
726 // Subscribe to OnBeforeRequest with requestBody requirement.
727 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
728 &profile_
, extension_id
, extension_id
, events::FOR_TEST
, kEventName
,
729 kEventName
+ "/1", filter
, extra_info_spec
, 0, 0,
730 ipc_sender_factory
.GetWeakPtr());
732 // The request URL can be arbitrary but must have an HTTP or HTTPS scheme.
733 const GURL
request_url("http://www.example.com");
735 for (size_t i
= 0; i
< arraysize(kMethods
); ++i
) {
736 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
737 request_url
, net::DEFAULT_PRIORITY
, &delegate_
));
738 request
->set_method(kMethods
[i
]);
739 ipc_sender_
.PushTask(base::Bind(&base::DoNothing
));
743 // We inspect the result in the message list of |ipc_sender_| later.
744 base::MessageLoop::current()->RunUntilIdle();
746 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
747 &profile_
, extension_id
, kEventName
+ "/1", 0, 0);
749 TestIPCSender::SentMessages::const_iterator i
= ipc_sender_
.sent_begin();
750 for (size_t test
= 0; test
< arraysize(kMethods
); ++test
, ++i
) {
751 SCOPED_TRACE(testing::Message("iteration number ") << test
);
752 EXPECT_NE(i
, ipc_sender_
.sent_end());
753 IPC::Message
* message
= i
->get();
754 const base::DictionaryValue
* details
= NULL
;
755 ExtensionMsg_MessageInvoke::Param param
;
756 GetPartOfMessageArguments(message
, &details
, ¶m
);
757 ASSERT_TRUE(details
!= NULL
);
758 EXPECT_FALSE(details
->HasKey(keys::kRequestBodyKey
));
761 EXPECT_EQ(i
, ipc_sender_
.sent_end());
764 struct HeaderModificationTest_Header
{
769 struct HeaderModificationTest_Modification
{
781 struct HeaderModificationTest
{
783 HeaderModificationTest_Header before
[10];
784 int modification_size
;
785 HeaderModificationTest_Modification modification
[10];
787 HeaderModificationTest_Header after
[10];
790 class ExtensionWebRequestHeaderModificationTest
791 : public testing::TestWithParam
<HeaderModificationTest
> {
793 ExtensionWebRequestHeaderModificationTest()
794 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
795 profile_manager_(TestingBrowserProcess::GetGlobal()),
796 event_router_(new EventRouterForwarder
) {}
799 void SetUp() override
{
800 ASSERT_TRUE(profile_manager_
.SetUp());
801 ChromeNetworkDelegate::InitializePrefsOnUIThread(
802 &enable_referrers_
, NULL
, NULL
, NULL
,
803 profile_
.GetTestingPrefService());
804 network_delegate_
.reset(
805 new ChromeNetworkDelegate(event_router_
.get(), &enable_referrers_
));
806 network_delegate_
->set_profile(&profile_
);
807 network_delegate_
->set_cookie_settings(
808 CookieSettingsFactory::GetForProfile(&profile_
).get());
809 context_
.reset(new net::TestURLRequestContext(true));
810 host_resolver_
.reset(new net::MockHostResolver());
811 host_resolver_
->rules()->AddSimulatedFailure("doesnotexist");
812 context_
->set_host_resolver(host_resolver_
.get());
813 context_
->set_network_delegate(network_delegate_
.get());
817 content::TestBrowserThreadBundle thread_bundle_
;
818 TestingProfile profile_
;
819 TestingProfileManager profile_manager_
;
820 net::TestDelegate delegate_
;
821 BooleanPrefMember enable_referrers_
;
822 TestIPCSender ipc_sender_
;
823 scoped_refptr
<EventRouterForwarder
> event_router_
;
824 scoped_refptr
<InfoMap
> extension_info_map_
;
825 scoped_ptr
<ChromeNetworkDelegate
> network_delegate_
;
826 scoped_ptr
<net::MockHostResolver
> host_resolver_
;
827 scoped_ptr
<net::TestURLRequestContext
> context_
;
830 TEST_P(ExtensionWebRequestHeaderModificationTest
, TestModifications
) {
831 std::string
extension1_id("1");
832 std::string
extension2_id("2");
833 std::string
extension3_id("3");
834 ExtensionWebRequestEventRouter::RequestFilter filter
;
835 const std::string
kEventName(keys::kOnBeforeSendHeadersEvent
);
836 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
838 // Install two extensions that can modify headers. Extension 2 has
839 // higher precedence than extension 1.
840 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
841 &profile_
, extension1_id
, extension1_id
, events::FOR_TEST
, kEventName
,
842 kEventName
+ "/1", filter
,
843 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
844 ipc_sender_factory
.GetWeakPtr());
845 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
846 &profile_
, extension2_id
, extension2_id
, events::FOR_TEST
, kEventName
,
847 kEventName
+ "/2", filter
,
848 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
849 ipc_sender_factory
.GetWeakPtr());
851 // Install one extension that observes the final headers.
852 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
853 &profile_
, extension3_id
, extension3_id
, events::FOR_TEST
,
854 keys::kOnSendHeadersEvent
, std::string(keys::kOnSendHeadersEvent
) + "/3",
855 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS
, 0,
856 0, ipc_sender_factory
.GetWeakPtr());
858 GURL
request_url("http://doesnotexist/does_not_exist.html");
859 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
860 request_url
, net::DEFAULT_PRIORITY
, &delegate_
));
862 // Initialize headers available before extensions are notified of the
863 // onBeforeSendHeaders event.
864 HeaderModificationTest test
= GetParam();
865 net::HttpRequestHeaders before_headers
;
866 for (int i
= 0; i
< test
.before_size
; ++i
)
867 before_headers
.SetHeader(test
.before
[i
].name
, test
.before
[i
].value
);
868 request
->SetExtraRequestHeaders(before_headers
);
870 // Gather the modifications to the headers for the respective extensions.
871 // We assume here that all modifications of one extension are listed
872 // in a continuous block of |test.modifications_|.
873 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
874 for (int i
= 0; i
< test
.modification_size
; ++i
) {
875 const HeaderModificationTest_Modification
& mod
= test
.modification
[i
];
876 if (response
== NULL
) {
877 response
= new ExtensionWebRequestEventRouter::EventResponse(
878 mod
.extension_id
== 1 ? extension1_id
: extension2_id
,
879 base::Time::FromDoubleT(mod
.extension_id
));
880 response
->request_headers
.reset(new net::HttpRequestHeaders());
881 response
->request_headers
->MergeFrom(request
->extra_request_headers());
885 case HeaderModificationTest_Modification::SET
:
886 response
->request_headers
->SetHeader(mod
.key
, mod
.value
);
888 case HeaderModificationTest_Modification::REMOVE
:
889 response
->request_headers
->RemoveHeader(mod
.key
);
893 // Trigger the result when this is the last modification statement or
894 // the block of modifications for the next extension starts.
895 if (i
+1 == test
.modification_size
||
896 mod
.extension_id
!= test
.modification
[i
+1].extension_id
) {
897 ipc_sender_
.PushTask(
898 base::Bind(&EventHandledOnIOThread
,
899 &profile_
, mod
.extension_id
== 1 ? extension1_id
: extension2_id
,
900 kEventName
, kEventName
+ (mod
.extension_id
== 1 ? "/1" : "/2"),
901 request
->identifier(), response
));
906 // Don't do anything for the onSendHeaders message.
907 ipc_sender_
.PushTask(base::Bind(&base::DoNothing
));
909 // Note that we mess up the headers slightly:
910 // request->Start() will first add additional headers (e.g. the User-Agent)
911 // and then send an event to the extension. When we have prepared our
912 // answers to the onBeforeSendHeaders events above, these headers did not
913 // exists and are therefore not listed in the responses. This makes
914 // them seem deleted.
916 base::MessageLoop::current()->Run();
918 EXPECT_TRUE(!request
->is_pending());
919 // This cannot succeed as we send the request to a server that does not exist.
920 EXPECT_EQ(net::URLRequestStatus::FAILED
, request
->status().status());
921 EXPECT_EQ(request_url
, request
->url());
922 EXPECT_EQ(1U, request
->url_chain().size());
923 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
925 // Calculate the expected headers.
926 net::HttpRequestHeaders expected_headers
;
927 for (int i
= 0; i
< test
.after_size
; ++i
) {
928 expected_headers
.SetHeader(test
.after
[i
].name
,
929 test
.after
[i
].value
);
932 // Counter for the number of observed onSendHeaders events.
933 int num_headers_observed
= 0;
935 // Search the onSendHeaders signal in the IPC messages and check that
936 // it contained the correct headers.
937 TestIPCSender::SentMessages::const_iterator i
;
938 for (i
= ipc_sender_
.sent_begin(); i
!= ipc_sender_
.sent_end(); ++i
) {
939 IPC::Message
* message
= i
->get();
940 if (ExtensionMsg_MessageInvoke::ID
!= message
->type())
942 ExtensionMsg_MessageInvoke::Param message_tuple
;
943 ExtensionMsg_MessageInvoke::Read(message
, &message_tuple
);
944 base::ListValue
& args
= base::get
<3>(message_tuple
);
946 std::string event_name
;
947 if (!args
.GetString(0, &event_name
) ||
948 event_name
!= std::string(keys::kOnSendHeadersEvent
) + "/3") {
952 base::ListValue
* event_arg
= NULL
;
953 ASSERT_TRUE(args
.GetList(1, &event_arg
));
955 base::DictionaryValue
* event_arg_dict
= NULL
;
956 ASSERT_TRUE(event_arg
->GetDictionary(0, &event_arg_dict
));
958 base::ListValue
* request_headers
= NULL
;
959 ASSERT_TRUE(event_arg_dict
->GetList(keys::kRequestHeadersKey
,
962 net::HttpRequestHeaders observed_headers
;
963 for (size_t j
= 0; j
< request_headers
->GetSize(); ++j
) {
964 base::DictionaryValue
* header
= NULL
;
965 ASSERT_TRUE(request_headers
->GetDictionary(j
, &header
));
968 ASSERT_TRUE(header
->GetString(keys::kHeaderNameKey
, &key
));
969 ASSERT_TRUE(header
->GetString(keys::kHeaderValueKey
, &value
));
970 observed_headers
.SetHeader(key
, value
);
973 EXPECT_EQ(expected_headers
.ToString(), observed_headers
.ToString());
974 ++num_headers_observed
;
976 EXPECT_EQ(1, num_headers_observed
);
977 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
978 &profile_
, extension1_id
, kEventName
+ "/1", 0, 0);
979 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
980 &profile_
, extension2_id
, kEventName
+ "/2", 0, 0);
981 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
982 &profile_
, extension3_id
,
983 std::string(keys::kOnSendHeadersEvent
) + "/3", 0, 0);
988 void TestInitFromValue(const std::string
& values
, bool expected_return_code
,
989 int expected_extra_info_spec
) {
990 int actual_info_spec
;
991 bool actual_return_code
= GenerateInfoSpec(values
, &actual_info_spec
);
992 EXPECT_EQ(expected_return_code
, actual_return_code
);
993 if (expected_return_code
)
994 EXPECT_EQ(expected_extra_info_spec
, actual_info_spec
);
999 TEST_F(ExtensionWebRequestTest
, InitFromValue
) {
1000 TestInitFromValue(std::string(), true, 0);
1002 // Single valid values.
1006 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS
);
1010 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS
);
1014 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
);
1018 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING
);
1022 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_BODY
);
1024 // Multiple valid values are bitwise-or'ed.
1026 "requestHeaders,blocking",
1028 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS
|
1029 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
);
1031 // Any invalid values lead to a bad parse.
1032 TestInitFromValue("invalidValue", false, 0);
1033 TestInitFromValue("blocking,invalidValue", false, 0);
1034 TestInitFromValue("invalidValue1,invalidValue2", false, 0);
1036 // BLOCKING and ASYNC_BLOCKING are mutually exclusive.
1037 TestInitFromValue("blocking,asyncBlocking", false, 0);
1042 const HeaderModificationTest_Modification::Type SET
=
1043 HeaderModificationTest_Modification::SET
;
1044 const HeaderModificationTest_Modification::Type REMOVE
=
1045 HeaderModificationTest_Modification::REMOVE
;
1047 HeaderModificationTest kTests
[] = {
1048 // Check that extension 2 always wins when settings the same header.
1050 // Headers before test.
1051 2, { {"header1", "value1"},
1052 {"header2", "value2"} },
1053 // Modifications in test.
1054 2, { {1, SET
, "header1", "foo"},
1055 {2, SET
, "header1", "bar"} },
1056 // Headers after test.
1057 2, { {"header1", "bar"},
1058 {"header2", "value2"} }
1060 // Same as before in reverse execution order.
1062 // Headers before test.
1063 2, { {"header1", "value1"},
1064 {"header2", "value2"} },
1065 // Modifications in test.
1066 2, { {2, SET
, "header1", "bar"},
1067 {1, SET
, "header1", "foo"} },
1068 // Headers after test.
1069 2, { {"header1", "bar"},
1070 {"header2", "value2"} }
1072 // Check that two extensions can modify different headers that do not
1075 // Headers before test.
1076 2, { {"header1", "value1"},
1077 {"header2", "value2"} },
1078 // Modifications in test.
1079 2, { {1, SET
, "header1", "foo"},
1080 {2, SET
, "header2", "bar"} },
1081 // Headers after test.
1082 2, { {"header1", "foo"},
1083 {"header2", "bar"} }
1085 // Check insert/delete conflict.
1087 // Headers before test.
1088 1, { {"header1", "value1"} },
1089 // Modifications in test.
1090 2, { {1, SET
, "header1", "foo"},
1091 {2, REMOVE
, "header1", NULL
} },
1092 // Headers after test.
1096 // Headers before test.
1097 1, { {"header1", "value1"} },
1098 // Modifications in test.
1099 2, { {2, REMOVE
, "header1", NULL
},
1100 {1, SET
, "header1", "foo"} },
1101 // Headers after test.
1105 // Headers before test.
1106 1, { {"header1", "value1"} },
1107 // Modifications in test.
1108 2, { {1, REMOVE
, "header1", NULL
},
1109 {2, SET
, "header1", "foo"} },
1110 // Headers after test.
1111 1, { {"header1", "foo"} }
1114 // Headers before test.
1115 1, { {"header1", "value1"} },
1116 // Modifications in test.
1117 2, { {2, SET
, "header1", "foo"},
1118 {1, REMOVE
, "header1", NULL
} },
1119 // Headers after test.
1120 1, { {"header1", "foo"} }
1122 // Check that edits are atomic (i.e. either all edit requests of an
1123 // extension are executed or none).
1125 // Headers before test.
1127 // Modifications in test.
1128 3, { {1, SET
, "header1", "value1"},
1129 {1, SET
, "header2", "value2"},
1130 {2, SET
, "header1", "foo"} },
1131 // Headers after test.
1132 1, { {"header1", "foo"} } // set(header2) is ignored
1134 // Check that identical edits do not conflict (set(header2) would be ignored
1135 // if set(header1) were considered a conflict).
1137 // Headers before test.
1139 // Modifications in test.
1140 3, { {1, SET
, "header1", "value2"},
1141 {1, SET
, "header2", "foo"},
1142 {2, SET
, "header1", "value2"} },
1143 // Headers after test.
1144 2, { {"header1", "value2"},
1145 {"header2", "foo"} }
1147 // Check that identical deletes do not conflict (set(header2) would be ignored
1148 // if delete(header1) were considered a conflict).
1150 // Headers before test.
1151 1, { {"header1", "value1"} },
1152 // Modifications in test.
1153 3, { {1, REMOVE
, "header1", NULL
},
1154 {1, SET
, "header2", "foo"},
1155 {2, REMOVE
, "header1", NULL
} },
1156 // Headers after test.
1157 1, { {"header2", "foo"} }
1159 // Check that setting a value to an identical value is not considered an
1160 // edit operation that can conflict.
1162 // Headers before test.
1163 1, { {"header1", "value1"} },
1164 // Modifications in test.
1165 3, { {1, SET
, "header1", "foo"},
1166 {1, SET
, "header2", "bar"},
1167 {2, SET
, "header1", "value1"} },
1168 // Headers after test.
1169 2, { {"header1", "foo"},
1170 {"header2", "bar"} }
1174 INSTANTIATE_TEST_CASE_P(
1175 ExtensionWebRequest
,
1176 ExtensionWebRequestHeaderModificationTest
,
1177 ::testing::ValuesIn(kTests
));
1182 TEST(ExtensionWebRequestHelpersTest
,
1183 TestInDecreasingExtensionInstallationTimeOrder
) {
1184 linked_ptr
<EventResponseDelta
> a(
1185 new EventResponseDelta("ext_1", base::Time::FromInternalValue(0)));
1186 linked_ptr
<EventResponseDelta
> b(
1187 new EventResponseDelta("ext_2", base::Time::FromInternalValue(1000)));
1188 EXPECT_FALSE(InDecreasingExtensionInstallationTimeOrder(a
, a
));
1189 EXPECT_FALSE(InDecreasingExtensionInstallationTimeOrder(a
, b
));
1190 EXPECT_TRUE(InDecreasingExtensionInstallationTimeOrder(b
, a
));
1193 TEST(ExtensionWebRequestHelpersTest
, TestStringToCharList
) {
1194 base::ListValue list_value
;
1195 list_value
.Append(new base::FundamentalValue('1'));
1196 list_value
.Append(new base::FundamentalValue('2'));
1197 list_value
.Append(new base::FundamentalValue('3'));
1198 list_value
.Append(new base::FundamentalValue(0xFE));
1199 list_value
.Append(new base::FundamentalValue(0xD1));
1201 unsigned char char_value
[] = {'1', '2', '3', 0xFE, 0xD1};
1202 std::string
string_value(reinterpret_cast<char *>(char_value
), 5);
1204 scoped_ptr
<base::ListValue
> converted_list(StringToCharList(string_value
));
1205 EXPECT_TRUE(list_value
.Equals(converted_list
.get()));
1207 std::string converted_string
;
1208 EXPECT_TRUE(CharListToString(&list_value
, &converted_string
));
1209 EXPECT_EQ(string_value
, converted_string
);
1212 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnBeforeRequestDelta
) {
1213 const bool cancel
= true;
1214 const GURL
localhost("http://localhost");
1215 scoped_ptr
<EventResponseDelta
> delta(
1216 CalculateOnBeforeRequestDelta("extid", base::Time::Now(),
1217 cancel
, localhost
));
1218 ASSERT_TRUE(delta
.get());
1219 EXPECT_TRUE(delta
->cancel
);
1220 EXPECT_EQ(localhost
, delta
->new_url
);
1223 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnBeforeSendHeadersDelta
) {
1224 const bool cancel
= true;
1226 net::HttpRequestHeaders old_headers
;
1227 old_headers
.AddHeadersFromString("key1: value1\r\n"
1228 "key2: value2\r\n");
1230 // Test adding a header.
1231 net::HttpRequestHeaders new_headers_added
;
1232 new_headers_added
.AddHeadersFromString("key1: value1\r\n"
1234 "key2: value2\r\n");
1235 scoped_ptr
<EventResponseDelta
> delta_added(
1236 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1237 &old_headers
, &new_headers_added
));
1238 ASSERT_TRUE(delta_added
.get());
1239 EXPECT_TRUE(delta_added
->cancel
);
1240 ASSERT_TRUE(delta_added
->modified_request_headers
.GetHeader("key3", &value
));
1241 EXPECT_EQ("value3", value
);
1243 // Test deleting a header.
1244 net::HttpRequestHeaders new_headers_deleted
;
1245 new_headers_deleted
.AddHeadersFromString("key1: value1\r\n");
1246 scoped_ptr
<EventResponseDelta
> delta_deleted(
1247 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1248 &old_headers
, &new_headers_deleted
));
1249 ASSERT_TRUE(delta_deleted
.get());
1250 ASSERT_EQ(1u, delta_deleted
->deleted_request_headers
.size());
1251 ASSERT_EQ("key2", delta_deleted
->deleted_request_headers
.front());
1253 // Test modifying a header.
1254 net::HttpRequestHeaders new_headers_modified
;
1255 new_headers_modified
.AddHeadersFromString("key1: value1\r\n"
1256 "key2: value3\r\n");
1257 scoped_ptr
<EventResponseDelta
> delta_modified(
1258 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1259 &old_headers
, &new_headers_modified
));
1260 ASSERT_TRUE(delta_modified
.get());
1261 EXPECT_TRUE(delta_modified
->deleted_request_headers
.empty());
1263 delta_modified
->modified_request_headers
.GetHeader("key2", &value
));
1264 EXPECT_EQ("value3", value
);
1266 // Test modifying a header if extension author just appended a new (key,
1267 // value) pair with a key that existed before. This is incorrect
1268 // usage of the API that shall be handled gracefully.
1269 net::HttpRequestHeaders new_headers_modified2
;
1270 new_headers_modified2
.AddHeadersFromString("key1: value1\r\n"
1272 "key2: value3\r\n");
1273 scoped_ptr
<EventResponseDelta
> delta_modified2(
1274 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1275 &old_headers
, &new_headers_modified
));
1276 ASSERT_TRUE(delta_modified2
.get());
1277 EXPECT_TRUE(delta_modified2
->deleted_request_headers
.empty());
1279 delta_modified2
->modified_request_headers
.GetHeader("key2", &value
));
1280 EXPECT_EQ("value3", value
);
1283 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnHeadersReceivedDelta
) {
1284 const bool cancel
= true;
1285 char base_headers_string
[] =
1286 "HTTP/1.0 200 OK\r\n"
1288 "Key2: Value2, Bar\r\n"
1290 "Key5: Value5, end5\r\n"
1292 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
1293 new net::HttpResponseHeaders(
1294 net::HttpUtil::AssembleRawHeaders(
1295 base_headers_string
, sizeof(base_headers_string
))));
1297 ResponseHeaders new_headers
;
1298 new_headers
.push_back(ResponseHeader("kEy1", "Value1")); // Unchanged
1299 new_headers
.push_back(ResponseHeader("Key2", "Value1")); // Modified
1301 new_headers
.push_back(ResponseHeader("Key4", "Value4")); // Added
1302 new_headers
.push_back(ResponseHeader("Key5", "Value5, end5")); // Unchanged
1303 GURL effective_new_url
;
1305 scoped_ptr
<EventResponseDelta
> delta(
1306 CalculateOnHeadersReceivedDelta("extid",
1312 ASSERT_TRUE(delta
.get());
1313 EXPECT_TRUE(delta
->cancel
);
1314 EXPECT_EQ(2u, delta
->added_response_headers
.size());
1315 EXPECT_TRUE(Contains(delta
->added_response_headers
,
1316 ResponseHeader("Key2", "Value1")));
1317 EXPECT_TRUE(Contains(delta
->added_response_headers
,
1318 ResponseHeader("Key4", "Value4")));
1319 EXPECT_EQ(2u, delta
->deleted_response_headers
.size());
1320 EXPECT_TRUE(Contains(delta
->deleted_response_headers
,
1321 ResponseHeader("Key2", "Value2, Bar")));
1322 EXPECT_TRUE(Contains(delta
->deleted_response_headers
,
1323 ResponseHeader("Key3", "Value3")));
1326 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnAuthRequiredDelta
) {
1327 const bool cancel
= true;
1329 base::string16 username
= base::ASCIIToUTF16("foo");
1330 base::string16 password
= base::ASCIIToUTF16("bar");
1331 scoped_ptr
<net::AuthCredentials
> credentials(
1332 new net::AuthCredentials(username
, password
));
1334 scoped_ptr
<EventResponseDelta
> delta(
1335 CalculateOnAuthRequiredDelta("extid", base::Time::Now(), cancel
,
1337 ASSERT_TRUE(delta
.get());
1338 EXPECT_TRUE(delta
->cancel
);
1339 ASSERT_TRUE(delta
->auth_credentials
.get());
1340 EXPECT_EQ(username
, delta
->auth_credentials
->username());
1341 EXPECT_EQ(password
, delta
->auth_credentials
->password());
1344 TEST(ExtensionWebRequestHelpersTest
, TestMergeCancelOfResponses
) {
1345 EventResponseDeltas deltas
;
1346 net::BoundTestNetLog capturing_net_log
;
1347 net::BoundNetLog net_log
= capturing_net_log
.bound();
1348 bool canceled
= false;
1350 // Single event that does not cancel.
1351 linked_ptr
<EventResponseDelta
> d1(
1352 new EventResponseDelta("extid1", base::Time::FromInternalValue(1000)));
1354 deltas
.push_back(d1
);
1355 MergeCancelOfResponses(deltas
, &canceled
, &net_log
);
1356 EXPECT_FALSE(canceled
);
1357 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1359 // Second event that cancels the request
1360 linked_ptr
<EventResponseDelta
> d2(
1361 new EventResponseDelta("extid2", base::Time::FromInternalValue(500)));
1363 deltas
.push_back(d2
);
1364 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1365 MergeCancelOfResponses(deltas
, &canceled
, &net_log
);
1366 EXPECT_TRUE(canceled
);
1367 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1370 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeRequestResponses
) {
1371 EventResponseDeltas deltas
;
1372 net::BoundTestNetLog capturing_net_log
;
1373 net::BoundNetLog net_log
= capturing_net_log
.bound();
1374 WarningSet warning_set
;
1375 GURL effective_new_url
;
1378 linked_ptr
<EventResponseDelta
> d0(
1379 new EventResponseDelta("extid0", base::Time::FromInternalValue(0)));
1380 deltas
.push_back(d0
);
1381 MergeOnBeforeRequestResponses(
1382 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1383 EXPECT_TRUE(effective_new_url
.is_empty());
1386 GURL
new_url_1("http://foo.com");
1387 linked_ptr
<EventResponseDelta
> d1(
1388 new EventResponseDelta("extid1", base::Time::FromInternalValue(1000)));
1389 d1
->new_url
= GURL(new_url_1
);
1390 deltas
.push_back(d1
);
1391 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1392 capturing_net_log
.Clear();
1393 MergeOnBeforeRequestResponses(
1394 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1395 EXPECT_EQ(new_url_1
, effective_new_url
);
1396 EXPECT_TRUE(warning_set
.empty());
1397 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1399 // Ignored redirect (due to precedence).
1400 GURL
new_url_2("http://bar.com");
1401 linked_ptr
<EventResponseDelta
> d2(
1402 new EventResponseDelta("extid2", base::Time::FromInternalValue(500)));
1403 d2
->new_url
= GURL(new_url_2
);
1404 deltas
.push_back(d2
);
1405 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1406 warning_set
.clear();
1407 capturing_net_log
.Clear();
1408 MergeOnBeforeRequestResponses(
1409 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1410 EXPECT_EQ(new_url_1
, effective_new_url
);
1411 EXPECT_EQ(1u, warning_set
.size());
1412 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1413 EXPECT_EQ(2u, capturing_net_log
.GetSize());
1415 // Overriding redirect.
1416 GURL
new_url_3("http://baz.com");
1417 linked_ptr
<EventResponseDelta
> d3(
1418 new EventResponseDelta("extid3", base::Time::FromInternalValue(1500)));
1419 d3
->new_url
= GURL(new_url_3
);
1420 deltas
.push_back(d3
);
1421 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1422 warning_set
.clear();
1423 capturing_net_log
.Clear();
1424 MergeOnBeforeRequestResponses(
1425 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1426 EXPECT_EQ(new_url_3
, effective_new_url
);
1427 EXPECT_EQ(2u, warning_set
.size());
1428 EXPECT_TRUE(HasWarning(warning_set
, "extid1"));
1429 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1430 EXPECT_EQ(3u, capturing_net_log
.GetSize());
1432 // Check that identical redirects don't cause a conflict.
1433 linked_ptr
<EventResponseDelta
> d4(
1434 new EventResponseDelta("extid4", base::Time::FromInternalValue(2000)));
1435 d4
->new_url
= GURL(new_url_3
);
1436 deltas
.push_back(d4
);
1437 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1438 warning_set
.clear();
1439 capturing_net_log
.Clear();
1440 MergeOnBeforeRequestResponses(
1441 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1442 EXPECT_EQ(new_url_3
, effective_new_url
);
1443 EXPECT_EQ(2u, warning_set
.size());
1444 EXPECT_TRUE(HasWarning(warning_set
, "extid1"));
1445 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1446 EXPECT_EQ(4u, capturing_net_log
.GetSize());
1449 // This tests that we can redirect to data:// urls, which is considered
1450 // a kind of cancelling requests.
1451 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeRequestResponses2
) {
1452 EventResponseDeltas deltas
;
1453 net::BoundTestNetLog capturing_net_log
;
1454 net::BoundNetLog net_log
= capturing_net_log
.bound();
1455 WarningSet warning_set
;
1456 GURL effective_new_url
;
1459 GURL
new_url_0("http://foo.com");
1460 linked_ptr
<EventResponseDelta
> d0(
1461 new EventResponseDelta("extid0", base::Time::FromInternalValue(2000)));
1462 d0
->new_url
= GURL(new_url_0
);
1463 deltas
.push_back(d0
);
1464 MergeOnBeforeRequestResponses(
1465 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1466 EXPECT_EQ(new_url_0
, effective_new_url
);
1468 // Cancel request by redirecting to a data:// URL. This shall override
1469 // the other redirect but not cause any conflict warnings.
1470 GURL
new_url_1("data://foo");
1471 linked_ptr
<EventResponseDelta
> d1(
1472 new EventResponseDelta("extid1", base::Time::FromInternalValue(1500)));
1473 d1
->new_url
= GURL(new_url_1
);
1474 deltas
.push_back(d1
);
1475 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1476 warning_set
.clear();
1477 capturing_net_log
.Clear();
1478 MergeOnBeforeRequestResponses(
1479 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1480 EXPECT_EQ(new_url_1
, effective_new_url
);
1481 EXPECT_TRUE(warning_set
.empty());
1482 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1484 // Cancel request by redirecting to the same data:// URL. This shall
1485 // not create any conflicts as it is in line with d1.
1486 GURL
new_url_2("data://foo");
1487 linked_ptr
<EventResponseDelta
> d2(
1488 new EventResponseDelta("extid2", base::Time::FromInternalValue(1000)));
1489 d2
->new_url
= GURL(new_url_2
);
1490 deltas
.push_back(d2
);
1491 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1492 warning_set
.clear();
1493 capturing_net_log
.Clear();
1494 MergeOnBeforeRequestResponses(
1495 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1496 EXPECT_EQ(new_url_1
, effective_new_url
);
1497 EXPECT_TRUE(warning_set
.empty());
1498 EXPECT_EQ(2u, capturing_net_log
.GetSize());
1500 // Cancel redirect by redirecting to a different data:// URL. This needs
1501 // to create a conflict.
1502 GURL
new_url_3("data://something_totally_different");
1503 linked_ptr
<EventResponseDelta
> d3(
1504 new EventResponseDelta("extid3", base::Time::FromInternalValue(500)));
1505 d3
->new_url
= GURL(new_url_3
);
1506 deltas
.push_back(d3
);
1507 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1508 warning_set
.clear();
1509 capturing_net_log
.Clear();
1510 MergeOnBeforeRequestResponses(
1511 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1512 EXPECT_EQ(new_url_1
, effective_new_url
);
1513 EXPECT_EQ(1u, warning_set
.size());
1514 EXPECT_TRUE(HasWarning(warning_set
, "extid3"));
1515 EXPECT_EQ(3u, capturing_net_log
.GetSize());
1518 // This tests that we can redirect to about:blank, which is considered
1519 // a kind of cancelling requests.
1520 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeRequestResponses3
) {
1521 EventResponseDeltas deltas
;
1522 net::BoundTestNetLog capturing_net_log
;
1523 net::BoundNetLog net_log
= capturing_net_log
.bound();
1524 WarningSet warning_set
;
1525 GURL effective_new_url
;
1528 GURL
new_url_0("http://foo.com");
1529 linked_ptr
<EventResponseDelta
> d0(
1530 new EventResponseDelta("extid0", base::Time::FromInternalValue(2000)));
1531 d0
->new_url
= GURL(new_url_0
);
1532 deltas
.push_back(d0
);
1533 MergeOnBeforeRequestResponses(
1534 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1535 EXPECT_EQ(new_url_0
, effective_new_url
);
1537 // Cancel request by redirecting to about:blank. This shall override
1538 // the other redirect but not cause any conflict warnings.
1539 GURL
new_url_1("about:blank");
1540 linked_ptr
<EventResponseDelta
> d1(
1541 new EventResponseDelta("extid1", base::Time::FromInternalValue(1500)));
1542 d1
->new_url
= GURL(new_url_1
);
1543 deltas
.push_back(d1
);
1544 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1545 warning_set
.clear();
1546 capturing_net_log
.Clear();
1547 MergeOnBeforeRequestResponses(
1548 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1549 EXPECT_EQ(new_url_1
, effective_new_url
);
1550 EXPECT_TRUE(warning_set
.empty());
1551 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1554 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeSendHeadersResponses
) {
1555 net::HttpRequestHeaders base_headers
;
1556 base_headers
.AddHeaderFromString("key1: value 1");
1557 base_headers
.AddHeaderFromString("key2: value 2");
1558 net::BoundTestNetLog capturing_net_log
;
1559 net::BoundNetLog net_log
= capturing_net_log
.bound();
1560 WarningSet warning_set
;
1561 std::string header_value
;
1562 EventResponseDeltas deltas
;
1564 // Check that we can handle not changing the headers.
1565 linked_ptr
<EventResponseDelta
> d0(
1566 new EventResponseDelta("extid0", base::Time::FromInternalValue(2500)));
1567 deltas
.push_back(d0
);
1568 net::HttpRequestHeaders headers0
;
1569 headers0
.MergeFrom(base_headers
);
1570 MergeOnBeforeSendHeadersResponses(deltas
, &headers0
, &warning_set
, &net_log
);
1571 ASSERT_TRUE(headers0
.GetHeader("key1", &header_value
));
1572 EXPECT_EQ("value 1", header_value
);
1573 ASSERT_TRUE(headers0
.GetHeader("key2", &header_value
));
1574 EXPECT_EQ("value 2", header_value
);
1575 EXPECT_EQ(0u, warning_set
.size());
1576 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1578 // Delete, modify and add a header.
1579 linked_ptr
<EventResponseDelta
> d1(
1580 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
1581 d1
->deleted_request_headers
.push_back("key1");
1582 d1
->modified_request_headers
.AddHeaderFromString("key2: value 3");
1583 d1
->modified_request_headers
.AddHeaderFromString("key3: value 3");
1584 deltas
.push_back(d1
);
1585 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1586 warning_set
.clear();
1587 capturing_net_log
.Clear();
1588 net::HttpRequestHeaders headers1
;
1589 headers1
.MergeFrom(base_headers
);
1590 MergeOnBeforeSendHeadersResponses(deltas
, &headers1
, &warning_set
, &net_log
);
1591 EXPECT_FALSE(headers1
.HasHeader("key1"));
1592 ASSERT_TRUE(headers1
.GetHeader("key2", &header_value
));
1593 EXPECT_EQ("value 3", header_value
);
1594 ASSERT_TRUE(headers1
.GetHeader("key3", &header_value
));
1595 EXPECT_EQ("value 3", header_value
);
1596 EXPECT_EQ(0u, warning_set
.size());
1597 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1599 // Check that conflicts are atomic, i.e. if one header modification
1600 // collides all other conflicts of the same extension are declined as well.
1601 linked_ptr
<EventResponseDelta
> d2(
1602 new EventResponseDelta("extid2", base::Time::FromInternalValue(1500)));
1603 // This one conflicts:
1604 d2
->modified_request_headers
.AddHeaderFromString("key3: value 0");
1605 d2
->modified_request_headers
.AddHeaderFromString("key4: value 4");
1606 deltas
.push_back(d2
);
1607 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1608 warning_set
.clear();
1609 capturing_net_log
.Clear();
1610 net::HttpRequestHeaders headers2
;
1611 headers2
.MergeFrom(base_headers
);
1612 MergeOnBeforeSendHeadersResponses(deltas
, &headers2
, &warning_set
, &net_log
);
1613 EXPECT_FALSE(headers2
.HasHeader("key1"));
1614 ASSERT_TRUE(headers2
.GetHeader("key2", &header_value
));
1615 EXPECT_EQ("value 3", header_value
);
1616 ASSERT_TRUE(headers2
.GetHeader("key3", &header_value
));
1617 EXPECT_EQ("value 3", header_value
);
1618 EXPECT_FALSE(headers2
.HasHeader("key4"));
1619 EXPECT_EQ(1u, warning_set
.size());
1620 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1621 EXPECT_EQ(2u, capturing_net_log
.GetSize());
1623 // Check that identical modifications don't conflict and operations
1625 linked_ptr
<EventResponseDelta
> d3(
1626 new EventResponseDelta("extid3", base::Time::FromInternalValue(1000)));
1627 d3
->deleted_request_headers
.push_back("key1");
1628 d3
->modified_request_headers
.AddHeaderFromString("key2: value 3");
1629 d3
->modified_request_headers
.AddHeaderFromString("key5: value 5");
1630 deltas
.push_back(d3
);
1631 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1632 warning_set
.clear();
1633 capturing_net_log
.Clear();
1634 net::HttpRequestHeaders headers3
;
1635 headers3
.MergeFrom(base_headers
);
1636 MergeOnBeforeSendHeadersResponses(deltas
, &headers3
, &warning_set
, &net_log
);
1637 EXPECT_FALSE(headers3
.HasHeader("key1"));
1638 ASSERT_TRUE(headers3
.GetHeader("key2", &header_value
));
1639 EXPECT_EQ("value 3", header_value
);
1640 ASSERT_TRUE(headers3
.GetHeader("key3", &header_value
));
1641 EXPECT_EQ("value 3", header_value
);
1642 ASSERT_TRUE(headers3
.GetHeader("key5", &header_value
));
1643 EXPECT_EQ("value 5", header_value
);
1644 EXPECT_EQ(1u, warning_set
.size());
1645 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1646 EXPECT_EQ(3u, capturing_net_log
.GetSize());
1649 TEST(ExtensionWebRequestHelpersTest
,
1650 TestMergeOnBeforeSendHeadersResponses_Cookies
) {
1651 net::HttpRequestHeaders base_headers
;
1652 base_headers
.AddHeaderFromString(
1653 "Cookie: name=value; name2=value2; name3=\"value3\"");
1654 net::BoundTestNetLog capturing_net_log
;
1655 net::BoundNetLog net_log
= capturing_net_log
.bound();
1656 WarningSet warning_set
;
1657 std::string header_value
;
1658 EventResponseDeltas deltas
;
1660 linked_ptr
<RequestCookieModification
> add_cookie
=
1661 make_linked_ptr(new RequestCookieModification
);
1662 add_cookie
->type
= helpers::ADD
;
1663 add_cookie
->modification
.reset(new helpers::RequestCookie
);
1664 add_cookie
->modification
->name
.reset(new std::string("name4"));
1665 add_cookie
->modification
->value
.reset(new std::string("\"value 4\""));
1667 linked_ptr
<RequestCookieModification
> add_cookie_2
=
1668 make_linked_ptr(new RequestCookieModification
);
1669 add_cookie_2
->type
= helpers::ADD
;
1670 add_cookie_2
->modification
.reset(new helpers::RequestCookie
);
1671 add_cookie_2
->modification
->name
.reset(new std::string("name"));
1672 add_cookie_2
->modification
->value
.reset(new std::string("new value"));
1674 linked_ptr
<RequestCookieModification
> edit_cookie
=
1675 make_linked_ptr(new RequestCookieModification
);
1676 edit_cookie
->type
= helpers::EDIT
;
1677 edit_cookie
->filter
.reset(new helpers::RequestCookie
);
1678 edit_cookie
->filter
->name
.reset(new std::string("name2"));
1679 edit_cookie
->modification
.reset(new helpers::RequestCookie
);
1680 edit_cookie
->modification
->value
.reset(new std::string("new value"));
1682 linked_ptr
<RequestCookieModification
> remove_cookie
=
1683 make_linked_ptr(new RequestCookieModification
);
1684 remove_cookie
->type
= helpers::REMOVE
;
1685 remove_cookie
->filter
.reset(new helpers::RequestCookie
);
1686 remove_cookie
->filter
->name
.reset(new std::string("name3"));
1688 linked_ptr
<RequestCookieModification
> operations
[] = {
1689 add_cookie
, add_cookie_2
, edit_cookie
, remove_cookie
1692 for (size_t i
= 0; i
< arraysize(operations
); ++i
) {
1693 linked_ptr
<EventResponseDelta
> delta(
1694 new EventResponseDelta("extid0", base::Time::FromInternalValue(i
* 5)));
1695 delta
->request_cookie_modifications
.push_back(operations
[i
]);
1696 deltas
.push_back(delta
);
1698 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1699 net::HttpRequestHeaders headers1
;
1700 headers1
.MergeFrom(base_headers
);
1701 warning_set
.clear();
1702 MergeOnBeforeSendHeadersResponses(deltas
, &headers1
, &warning_set
, &net_log
);
1703 EXPECT_TRUE(headers1
.HasHeader("Cookie"));
1704 ASSERT_TRUE(headers1
.GetHeader("Cookie", &header_value
));
1705 EXPECT_EQ("name=new value; name2=new value; name4=\"value 4\"", header_value
);
1706 EXPECT_EQ(0u, warning_set
.size());
1707 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1712 std::string
GetCookieExpirationDate(int delta_secs
) {
1713 const char* const kWeekDays
[] = {
1714 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1716 const char* const kMonthNames
[] = {
1717 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1718 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1721 Time::Exploded exploded_time
;
1722 (Time::Now() + TimeDelta::FromSeconds(delta_secs
)).UTCExplode(&exploded_time
);
1724 return base::StringPrintf("%s, %d %s %d %.2d:%.2d:%.2d GMT",
1725 kWeekDays
[exploded_time
.day_of_week
],
1726 exploded_time
.day_of_month
,
1727 kMonthNames
[exploded_time
.month
- 1],
1730 exploded_time
.minute
,
1731 exploded_time
.second
);
1736 TEST(ExtensionWebRequestHelpersTest
,
1737 TestMergeCookiesInOnHeadersReceivedResponses
) {
1738 net::BoundTestNetLog capturing_net_log
;
1739 net::BoundNetLog net_log
= capturing_net_log
.bound();
1740 WarningSet warning_set
;
1741 std::string header_value
;
1742 EventResponseDeltas deltas
;
1744 std::string cookie_expiration
= GetCookieExpirationDate(1200);
1745 std::string base_headers_string
=
1746 "HTTP/1.0 200 OK\r\n"
1748 "Set-Cookie: name=value; DOMAIN=google.com; Secure\r\n"
1749 "Set-Cookie: name2=value2\r\n"
1750 "Set-Cookie: name3=value3\r\n"
1751 "Set-Cookie: lBound1=value5; Expires=" + cookie_expiration
+ "\r\n"
1752 "Set-Cookie: lBound2=value6; Max-Age=1200\r\n"
1753 "Set-Cookie: lBound3=value7; Max-Age=2000\r\n"
1754 "Set-Cookie: uBound1=value8; Expires=" + cookie_expiration
+ "\r\n"
1755 "Set-Cookie: uBound2=value9; Max-Age=1200\r\n"
1756 "Set-Cookie: uBound3=value10; Max-Age=2000\r\n"
1757 "Set-Cookie: uBound4=value11; Max-Age=2500\r\n"
1758 "Set-Cookie: uBound5=value12; Max-Age=600; Expires=" +
1759 cookie_expiration
+ "\r\n"
1760 "Set-Cookie: uBound6=removed; Max-Age=600\r\n"
1761 "Set-Cookie: sessionCookie=removed; Max-Age=INVALID\r\n"
1762 "Set-Cookie: sessionCookie2=removed\r\n"
1764 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
1765 new net::HttpResponseHeaders(
1766 net::HttpUtil::AssembleRawHeaders(
1767 base_headers_string
.c_str(), base_headers_string
.size())));
1769 // Check that we can handle if not touching the response headers.
1770 linked_ptr
<EventResponseDelta
> d0(
1771 new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
1772 deltas
.push_back(d0
);
1773 scoped_refptr
<net::HttpResponseHeaders
> new_headers0
;
1774 MergeCookiesInOnHeadersReceivedResponses(
1775 deltas
, base_headers
.get(), &new_headers0
, &warning_set
, &net_log
);
1776 EXPECT_FALSE(new_headers0
.get());
1777 EXPECT_EQ(0u, warning_set
.size());
1778 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1780 linked_ptr
<ResponseCookieModification
> add_cookie
=
1781 make_linked_ptr(new ResponseCookieModification
);
1782 add_cookie
->type
= helpers::ADD
;
1783 add_cookie
->modification
.reset(new helpers::ResponseCookie
);
1784 add_cookie
->modification
->name
.reset(new std::string("name4"));
1785 add_cookie
->modification
->value
.reset(new std::string("\"value4\""));
1787 linked_ptr
<ResponseCookieModification
> edit_cookie
=
1788 make_linked_ptr(new ResponseCookieModification
);
1789 edit_cookie
->type
= helpers::EDIT
;
1790 edit_cookie
->filter
.reset(new helpers::FilterResponseCookie
);
1791 edit_cookie
->filter
->name
.reset(new std::string("name2"));
1792 edit_cookie
->modification
.reset(new helpers::ResponseCookie
);
1793 edit_cookie
->modification
->value
.reset(new std::string("new value"));
1795 linked_ptr
<ResponseCookieModification
> edit_cookie_2
=
1796 make_linked_ptr(new ResponseCookieModification
);
1797 edit_cookie_2
->type
= helpers::EDIT
;
1798 edit_cookie_2
->filter
.reset(new helpers::FilterResponseCookie
);
1799 edit_cookie_2
->filter
->secure
.reset(new bool(false));
1800 edit_cookie_2
->modification
.reset(new helpers::ResponseCookie
);
1801 edit_cookie_2
->modification
->secure
.reset(new bool(true));
1803 // Tests 'ageLowerBound' filter when cookie lifetime is set
1804 // in cookie's 'max-age' attribute and its value is greater than
1805 // the filter's value.
1806 linked_ptr
<ResponseCookieModification
> edit_cookie_3
=
1807 make_linked_ptr(new ResponseCookieModification
);
1808 edit_cookie_3
->type
= helpers::EDIT
;
1809 edit_cookie_3
->filter
.reset(new helpers::FilterResponseCookie
);
1810 edit_cookie_3
->filter
->name
.reset(new std::string("lBound1"));
1811 edit_cookie_3
->filter
->age_lower_bound
.reset(new int(600));
1812 edit_cookie_3
->modification
.reset(new helpers::ResponseCookie
);
1813 edit_cookie_3
->modification
->value
.reset(new std::string("greater_1"));
1815 // Cookie lifetime is set in the cookie's 'expires' attribute.
1816 linked_ptr
<ResponseCookieModification
> edit_cookie_4
=
1817 make_linked_ptr(new ResponseCookieModification
);
1818 edit_cookie_4
->type
= helpers::EDIT
;
1819 edit_cookie_4
->filter
.reset(new helpers::FilterResponseCookie
);
1820 edit_cookie_4
->filter
->name
.reset(new std::string("lBound2"));
1821 edit_cookie_4
->filter
->age_lower_bound
.reset(new int(600));
1822 edit_cookie_4
->modification
.reset(new helpers::ResponseCookie
);
1823 edit_cookie_4
->modification
->value
.reset(new std::string("greater_2"));
1825 // Tests equality of the cookie lifetime with the filter value when
1826 // lifetime is set in the cookie's 'max-age' attribute.
1827 // Note: we don't test the equality when the lifetime is set in the 'expires'
1828 // attribute because the tests will be flaky. The reason is calculations will
1829 // depend on fetching the current time.
1830 linked_ptr
<ResponseCookieModification
> edit_cookie_5
=
1831 make_linked_ptr(new ResponseCookieModification
);
1832 edit_cookie_5
->type
= helpers::EDIT
;
1833 edit_cookie_5
->filter
.reset(new helpers::FilterResponseCookie
);
1834 edit_cookie_5
->filter
->name
.reset(new std::string("lBound3"));
1835 edit_cookie_5
->filter
->age_lower_bound
.reset(new int(2000));
1836 edit_cookie_5
->modification
.reset(new helpers::ResponseCookie
);
1837 edit_cookie_5
->modification
->value
.reset(new std::string("equal_2"));
1839 // Tests 'ageUpperBound' filter when cookie lifetime is set
1840 // in cookie's 'max-age' attribute and its value is lower than
1841 // the filter's value.
1842 linked_ptr
<ResponseCookieModification
> edit_cookie_6
=
1843 make_linked_ptr(new ResponseCookieModification
);
1844 edit_cookie_6
->type
= helpers::EDIT
;
1845 edit_cookie_6
->filter
.reset(new helpers::FilterResponseCookie
);
1846 edit_cookie_6
->filter
->name
.reset(new std::string("uBound1"));
1847 edit_cookie_6
->filter
->age_upper_bound
.reset(new int(2000));
1848 edit_cookie_6
->modification
.reset(new helpers::ResponseCookie
);
1849 edit_cookie_6
->modification
->value
.reset(new std::string("smaller_1"));
1851 // Cookie lifetime is set in the cookie's 'expires' attribute.
1852 linked_ptr
<ResponseCookieModification
> edit_cookie_7
=
1853 make_linked_ptr(new ResponseCookieModification
);
1854 edit_cookie_7
->type
= helpers::EDIT
;
1855 edit_cookie_7
->filter
.reset(new helpers::FilterResponseCookie
);
1856 edit_cookie_7
->filter
->name
.reset(new std::string("uBound2"));
1857 edit_cookie_7
->filter
->age_upper_bound
.reset(new int(2000));
1858 edit_cookie_7
->modification
.reset(new helpers::ResponseCookie
);
1859 edit_cookie_7
->modification
->value
.reset(new std::string("smaller_2"));
1861 // Tests equality of the cookie lifetime with the filter value when
1862 // lifetime is set in the cookie's 'max-age' attribute.
1863 linked_ptr
<ResponseCookieModification
> edit_cookie_8
=
1864 make_linked_ptr(new ResponseCookieModification
);
1865 edit_cookie_8
->type
= helpers::EDIT
;
1866 edit_cookie_8
->filter
.reset(new helpers::FilterResponseCookie
);
1867 edit_cookie_8
->filter
->name
.reset(new std::string("uBound3"));
1868 edit_cookie_8
->filter
->age_upper_bound
.reset(new int(2000));
1869 edit_cookie_8
->modification
.reset(new helpers::ResponseCookie
);
1870 edit_cookie_8
->modification
->value
.reset(new std::string("equal_4"));
1872 // Tests 'ageUpperBound' filter when cookie lifetime is greater
1873 // than the filter value. No modification is expected to be applied.
1874 linked_ptr
<ResponseCookieModification
> edit_cookie_9
=
1875 make_linked_ptr(new ResponseCookieModification
);
1876 edit_cookie_9
->type
= helpers::EDIT
;
1877 edit_cookie_9
->filter
.reset(new helpers::FilterResponseCookie
);
1878 edit_cookie_9
->filter
->name
.reset(new std::string("uBound4"));
1879 edit_cookie_9
->filter
->age_upper_bound
.reset(new int(2501));
1880 edit_cookie_9
->modification
.reset(new helpers::ResponseCookie
);
1881 edit_cookie_9
->modification
->value
.reset(new std::string("Will not change"));
1883 // Tests 'ageUpperBound' filter when both 'max-age' and 'expires' cookie
1884 // attributes are provided. 'expires' value matches the filter, however
1885 // no modification to the cookie is expected because 'max-age' overrides
1886 // 'expires' and it does not match the filter.
1887 linked_ptr
<ResponseCookieModification
> edit_cookie_10
=
1888 make_linked_ptr(new ResponseCookieModification
);
1889 edit_cookie_10
->type
= helpers::EDIT
;
1890 edit_cookie_10
->filter
.reset(new helpers::FilterResponseCookie
);
1891 edit_cookie_10
->filter
->name
.reset(new std::string("uBound5"));
1892 edit_cookie_10
->filter
->age_upper_bound
.reset(new int(800));
1893 edit_cookie_10
->modification
.reset(new helpers::ResponseCookie
);
1894 edit_cookie_10
->modification
->value
.reset(new std::string("Will not change"));
1896 linked_ptr
<ResponseCookieModification
> remove_cookie
=
1897 make_linked_ptr(new ResponseCookieModification
);
1898 remove_cookie
->type
= helpers::REMOVE
;
1899 remove_cookie
->filter
.reset(new helpers::FilterResponseCookie
);
1900 remove_cookie
->filter
->name
.reset(new std::string("name3"));
1902 linked_ptr
<ResponseCookieModification
> remove_cookie_2
=
1903 make_linked_ptr(new ResponseCookieModification
);
1904 remove_cookie_2
->type
= helpers::REMOVE
;
1905 remove_cookie_2
->filter
.reset(new helpers::FilterResponseCookie
);
1906 remove_cookie_2
->filter
->name
.reset(new std::string("uBound6"));
1907 remove_cookie_2
->filter
->age_upper_bound
.reset(new int(700));
1909 linked_ptr
<ResponseCookieModification
> remove_cookie_3
=
1910 make_linked_ptr(new ResponseCookieModification
);
1911 remove_cookie_3
->type
= helpers::REMOVE
;
1912 remove_cookie_3
->filter
.reset(new helpers::FilterResponseCookie
);
1913 remove_cookie_3
->filter
->name
.reset(new std::string("sessionCookie"));
1914 remove_cookie_3
->filter
->session_cookie
.reset(new bool(true));
1916 linked_ptr
<ResponseCookieModification
> remove_cookie_4
=
1917 make_linked_ptr(new ResponseCookieModification
);
1918 remove_cookie_4
->type
= helpers::REMOVE
;
1919 remove_cookie_4
->filter
.reset(new helpers::FilterResponseCookie
);
1920 remove_cookie_4
->filter
->name
.reset(new std::string("sessionCookie2"));
1921 remove_cookie_4
->filter
->session_cookie
.reset(new bool(true));
1923 linked_ptr
<ResponseCookieModification
> operations
[] = {
1924 add_cookie
, edit_cookie
, edit_cookie_2
, edit_cookie_3
, edit_cookie_4
,
1925 edit_cookie_5
, edit_cookie_6
, edit_cookie_7
, edit_cookie_8
,
1926 edit_cookie_9
, edit_cookie_10
, remove_cookie
, remove_cookie_2
,
1927 remove_cookie_3
, remove_cookie_4
1930 for (size_t i
= 0; i
< arraysize(operations
); ++i
) {
1931 linked_ptr
<EventResponseDelta
> delta(
1932 new EventResponseDelta("extid0", base::Time::FromInternalValue(i
* 5)));
1933 delta
->response_cookie_modifications
.push_back(operations
[i
]);
1934 deltas
.push_back(delta
);
1936 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1937 scoped_refptr
<net::HttpResponseHeaders
> headers1(
1938 new net::HttpResponseHeaders(
1939 net::HttpUtil::AssembleRawHeaders(
1940 base_headers_string
.c_str(), base_headers_string
.size())));
1941 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
1942 warning_set
.clear();
1943 MergeCookiesInOnHeadersReceivedResponses(
1944 deltas
, headers1
.get(), &new_headers1
, &warning_set
, &net_log
);
1946 EXPECT_TRUE(new_headers1
->HasHeader("Foo"));
1948 std::string cookie_string
;
1949 std::set
<std::string
> expected_cookies
;
1950 expected_cookies
.insert("name=value; domain=google.com; secure");
1951 expected_cookies
.insert("name2=value2; secure");
1952 expected_cookies
.insert("name4=\"value4\"; secure");
1953 expected_cookies
.insert(
1954 "lBound1=greater_1; expires=" + cookie_expiration
+ "; secure");
1955 expected_cookies
.insert("lBound2=greater_2; max-age=1200; secure");
1956 expected_cookies
.insert("lBound3=equal_2; max-age=2000; secure");
1957 expected_cookies
.insert(
1958 "uBound1=smaller_1; expires=" + cookie_expiration
+ "; secure");
1959 expected_cookies
.insert("uBound2=smaller_2; max-age=1200; secure");
1960 expected_cookies
.insert("uBound3=equal_4; max-age=2000; secure");
1961 expected_cookies
.insert("uBound4=value11; max-age=2500; secure");
1962 expected_cookies
.insert(
1963 "uBound5=value12; max-age=600; expires=" + cookie_expiration
+ "; secure");
1964 std::set
<std::string
> actual_cookies
;
1965 while (new_headers1
->EnumerateHeader(&iter
, "Set-Cookie", &cookie_string
))
1966 actual_cookies
.insert(cookie_string
);
1967 EXPECT_EQ(expected_cookies
, actual_cookies
);
1968 EXPECT_EQ(0u, warning_set
.size());
1969 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1972 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnHeadersReceivedResponses
) {
1973 net::BoundTestNetLog capturing_net_log
;
1974 net::BoundNetLog net_log
= capturing_net_log
.bound();
1975 WarningSet warning_set
;
1976 std::string header_value
;
1977 EventResponseDeltas deltas
;
1979 char base_headers_string
[] =
1980 "HTTP/1.0 200 OK\r\n"
1982 "Key2: Value2, Foo\r\n"
1984 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
1985 new net::HttpResponseHeaders(
1986 net::HttpUtil::AssembleRawHeaders(
1987 base_headers_string
, sizeof(base_headers_string
))));
1989 // Check that we can handle if not touching the response headers.
1990 linked_ptr
<EventResponseDelta
> d0(
1991 new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
1992 deltas
.push_back(d0
);
1993 scoped_refptr
<net::HttpResponseHeaders
> new_headers0
;
1994 GURL allowed_unsafe_redirect_url0
;
1995 MergeOnHeadersReceivedResponses(deltas
,
1998 &allowed_unsafe_redirect_url0
,
2001 EXPECT_FALSE(new_headers0
.get());
2002 EXPECT_TRUE(allowed_unsafe_redirect_url0
.is_empty());
2003 EXPECT_EQ(0u, warning_set
.size());
2004 EXPECT_EQ(0u, capturing_net_log
.GetSize());
2006 linked_ptr
<EventResponseDelta
> d1(
2007 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
2008 d1
->deleted_response_headers
.push_back(ResponseHeader("KEY1", "Value1"));
2009 d1
->deleted_response_headers
.push_back(ResponseHeader("KEY2", "Value2, Foo"));
2010 d1
->added_response_headers
.push_back(ResponseHeader("Key2", "Value3"));
2011 deltas
.push_back(d1
);
2012 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2013 warning_set
.clear();
2014 capturing_net_log
.Clear();
2015 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
2016 GURL allowed_unsafe_redirect_url1
;
2017 MergeOnHeadersReceivedResponses(deltas
,
2020 &allowed_unsafe_redirect_url1
,
2023 ASSERT_TRUE(new_headers1
.get());
2024 EXPECT_TRUE(allowed_unsafe_redirect_url1
.is_empty());
2025 std::multimap
<std::string
, std::string
> expected1
;
2026 expected1
.insert(std::pair
<std::string
, std::string
>("Key2", "Value3"));
2030 std::multimap
<std::string
, std::string
> actual1
;
2031 while (new_headers1
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
2032 actual1
.insert(std::pair
<std::string
, std::string
>(name
, value
));
2034 EXPECT_EQ(expected1
, actual1
);
2035 EXPECT_EQ(0u, warning_set
.size());
2036 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2038 // Check that we replace response headers only once.
2039 linked_ptr
<EventResponseDelta
> d2(
2040 new EventResponseDelta("extid2", base::Time::FromInternalValue(1500)));
2041 // Note that we use a different capitalization of KeY2. This should not
2043 d2
->deleted_response_headers
.push_back(ResponseHeader("KeY2", "Value2, Foo"));
2044 d2
->added_response_headers
.push_back(ResponseHeader("Key2", "Value4"));
2045 deltas
.push_back(d2
);
2046 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2047 warning_set
.clear();
2048 capturing_net_log
.Clear();
2049 scoped_refptr
<net::HttpResponseHeaders
> new_headers2
;
2050 GURL allowed_unsafe_redirect_url2
;
2051 MergeOnHeadersReceivedResponses(deltas
,
2054 &allowed_unsafe_redirect_url2
,
2057 ASSERT_TRUE(new_headers2
.get());
2058 EXPECT_TRUE(allowed_unsafe_redirect_url2
.is_empty());
2060 std::multimap
<std::string
, std::string
> actual2
;
2061 while (new_headers2
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
2062 actual2
.insert(std::pair
<std::string
, std::string
>(name
, value
));
2064 EXPECT_EQ(expected1
, actual2
);
2065 EXPECT_EQ(1u, warning_set
.size());
2066 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
2067 EXPECT_EQ(2u, capturing_net_log
.GetSize());
2070 // Check that we do not delete too much
2071 TEST(ExtensionWebRequestHelpersTest
,
2072 TestMergeOnHeadersReceivedResponsesDeletion
) {
2073 net::BoundTestNetLog capturing_net_log
;
2074 net::BoundNetLog net_log
= capturing_net_log
.bound();
2075 WarningSet warning_set
;
2076 std::string header_value
;
2077 EventResponseDeltas deltas
;
2079 char base_headers_string
[] =
2080 "HTTP/1.0 200 OK\r\n"
2086 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
2087 new net::HttpResponseHeaders(
2088 net::HttpUtil::AssembleRawHeaders(
2089 base_headers_string
, sizeof(base_headers_string
))));
2091 linked_ptr
<EventResponseDelta
> d1(
2092 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
2093 d1
->deleted_response_headers
.push_back(ResponseHeader("KEY1", "Value2"));
2094 deltas
.push_back(d1
);
2095 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
2096 GURL allowed_unsafe_redirect_url1
;
2097 MergeOnHeadersReceivedResponses(deltas
,
2100 &allowed_unsafe_redirect_url1
,
2103 ASSERT_TRUE(new_headers1
.get());
2104 EXPECT_TRUE(allowed_unsafe_redirect_url1
.is_empty());
2105 std::multimap
<std::string
, std::string
> expected1
;
2106 expected1
.insert(std::pair
<std::string
, std::string
>("Key1", "Value1"));
2107 expected1
.insert(std::pair
<std::string
, std::string
>("Key1", "Value3"));
2108 expected1
.insert(std::pair
<std::string
, std::string
>("Key2", "Value4"));
2112 std::multimap
<std::string
, std::string
> actual1
;
2113 while (new_headers1
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
2114 actual1
.insert(std::pair
<std::string
, std::string
>(name
, value
));
2116 EXPECT_EQ(expected1
, actual1
);
2117 EXPECT_EQ(0u, warning_set
.size());
2118 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2121 // Tests whether onHeadersReceived can initiate a redirect.
2122 // The URL merge logic is shared with onBeforeRequest, so we only need to test
2123 // whether the URLs are merged at all.
2124 TEST(ExtensionWebRequestHelpersTest
,
2125 TestMergeOnHeadersReceivedResponsesRedirect
) {
2126 EventResponseDeltas deltas
;
2127 net::BoundTestNetLog capturing_net_log
;
2128 net::BoundNetLog net_log
= capturing_net_log
.bound();
2129 WarningSet warning_set
;
2131 char base_headers_string
[] =
2132 "HTTP/1.0 200 OK\r\n"
2134 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
2135 new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
2136 base_headers_string
, sizeof(base_headers_string
))));
2139 linked_ptr
<EventResponseDelta
> d0(
2140 new EventResponseDelta("extid0", base::Time::FromInternalValue(0)));
2141 deltas
.push_back(d0
);
2142 scoped_refptr
<net::HttpResponseHeaders
> new_headers0
;
2143 GURL allowed_unsafe_redirect_url0
;
2144 MergeOnHeadersReceivedResponses(deltas
,
2147 &allowed_unsafe_redirect_url0
,
2150 EXPECT_FALSE(new_headers0
.get());
2151 EXPECT_TRUE(allowed_unsafe_redirect_url0
.is_empty());
2152 EXPECT_EQ(0u, warning_set
.size());
2153 EXPECT_EQ(0u, capturing_net_log
.GetSize());
2156 GURL
new_url_1("http://foo.com");
2157 linked_ptr
<EventResponseDelta
> d1(
2158 new EventResponseDelta("extid1", base::Time::FromInternalValue(1000)));
2159 d1
->new_url
= GURL(new_url_1
);
2160 deltas
.push_back(d1
);
2161 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2162 capturing_net_log
.Clear();
2163 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
2164 GURL allowed_unsafe_redirect_url1
;
2165 MergeOnHeadersReceivedResponses(deltas
,
2168 &allowed_unsafe_redirect_url1
,
2172 EXPECT_TRUE(new_headers1
.get());
2173 EXPECT_TRUE(new_headers1
->HasHeaderValue("Location", new_url_1
.spec()));
2174 EXPECT_EQ(new_url_1
, allowed_unsafe_redirect_url1
);
2175 EXPECT_TRUE(warning_set
.empty());
2176 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2179 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnAuthRequiredResponses
) {
2180 net::BoundTestNetLog capturing_net_log
;
2181 net::BoundNetLog net_log
= capturing_net_log
.bound();
2182 WarningSet warning_set
;
2183 EventResponseDeltas deltas
;
2184 base::string16 username
= base::ASCIIToUTF16("foo");
2185 base::string16 password
= base::ASCIIToUTF16("bar");
2186 base::string16 password2
= base::ASCIIToUTF16("baz");
2188 // Check that we can handle if not returning credentials.
2189 linked_ptr
<EventResponseDelta
> d0(
2190 new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
2191 deltas
.push_back(d0
);
2192 net::AuthCredentials auth0
;
2193 bool credentials_set
= MergeOnAuthRequiredResponses(
2194 deltas
, &auth0
, &warning_set
, &net_log
);
2195 EXPECT_FALSE(credentials_set
);
2196 EXPECT_TRUE(auth0
.Empty());
2197 EXPECT_EQ(0u, warning_set
.size());
2198 EXPECT_EQ(0u, capturing_net_log
.GetSize());
2200 // Check that we can set AuthCredentials.
2201 linked_ptr
<EventResponseDelta
> d1(
2202 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
2203 d1
->auth_credentials
.reset(new net::AuthCredentials(username
, password
));
2204 deltas
.push_back(d1
);
2205 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2206 warning_set
.clear();
2207 capturing_net_log
.Clear();
2208 net::AuthCredentials auth1
;
2209 credentials_set
= MergeOnAuthRequiredResponses(
2210 deltas
, &auth1
, &warning_set
, &net_log
);
2211 EXPECT_TRUE(credentials_set
);
2212 EXPECT_FALSE(auth1
.Empty());
2213 EXPECT_EQ(username
, auth1
.username());
2214 EXPECT_EQ(password
, auth1
.password());
2215 EXPECT_EQ(0u, warning_set
.size());
2216 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2218 // Check that we set AuthCredentials only once.
2219 linked_ptr
<EventResponseDelta
> d2(
2220 new EventResponseDelta("extid2", base::Time::FromInternalValue(1500)));
2221 d2
->auth_credentials
.reset(new net::AuthCredentials(username
, password2
));
2222 deltas
.push_back(d2
);
2223 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2224 warning_set
.clear();
2225 capturing_net_log
.Clear();
2226 net::AuthCredentials auth2
;
2227 credentials_set
= MergeOnAuthRequiredResponses(
2228 deltas
, &auth2
, &warning_set
, &net_log
);
2229 EXPECT_TRUE(credentials_set
);
2230 EXPECT_FALSE(auth2
.Empty());
2231 EXPECT_EQ(username
, auth1
.username());
2232 EXPECT_EQ(password
, auth1
.password());
2233 EXPECT_EQ(1u, warning_set
.size());
2234 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
2235 EXPECT_EQ(2u, capturing_net_log
.GetSize());
2237 // Check that we can set identical AuthCredentials twice without causing
2239 linked_ptr
<EventResponseDelta
> d3(
2240 new EventResponseDelta("extid3", base::Time::FromInternalValue(1000)));
2241 d3
->auth_credentials
.reset(new net::AuthCredentials(username
, password
));
2242 deltas
.push_back(d3
);
2243 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2244 warning_set
.clear();
2245 capturing_net_log
.Clear();
2246 net::AuthCredentials auth3
;
2247 credentials_set
= MergeOnAuthRequiredResponses(
2248 deltas
, &auth3
, &warning_set
, &net_log
);
2249 EXPECT_TRUE(credentials_set
);
2250 EXPECT_FALSE(auth3
.Empty());
2251 EXPECT_EQ(username
, auth1
.username());
2252 EXPECT_EQ(password
, auth1
.password());
2253 EXPECT_EQ(1u, warning_set
.size());
2254 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
2255 EXPECT_EQ(3u, capturing_net_log
.GetSize());
2258 } // namespace extensions