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/about_protocol_handler.h"
29 #include "chrome/browser/net/chrome_network_delegate.h"
30 #include "chrome/test/base/testing_browser_process.h"
31 #include "chrome/test/base/testing_pref_service_syncable.h"
32 #include "chrome/test/base/testing_profile.h"
33 #include "chrome/test/base/testing_profile_manager.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
, kEventName
, kEventName
+ "/1",
231 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
232 ipc_sender_factory
.GetWeakPtr());
233 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
234 &profile_
, extension2_id
, extension2_id
, kEventName
, kEventName
+ "/2",
235 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
236 ipc_sender_factory
.GetWeakPtr());
238 net::URLRequestJobFactoryImpl job_factory
;
239 job_factory
.SetProtocolHandler(
240 url::kAboutScheme
, new chrome_browser_net::AboutProtocolHandler());
241 context_
->set_job_factory(&job_factory
);
243 GURL
redirect_url("about:redirected");
244 GURL
not_chosen_redirect_url("about:not_chosen");
246 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
247 GURL("about:blank"), net::DEFAULT_PRIORITY
, &delegate_
));
249 // onBeforeRequest will be dispatched twice initially. The second response -
250 // the redirect - should win, since it has a later |install_time|. The
251 // redirect will dispatch another pair of onBeforeRequest. There, the first
252 // response should win (later |install_time|).
253 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
255 // Extension1 response. Arrives first, but ignored due to install_time.
256 response
= new ExtensionWebRequestEventRouter::EventResponse(
257 extension1_id
, base::Time::FromDoubleT(1));
258 response
->new_url
= not_chosen_redirect_url
;
259 ipc_sender_
.PushTask(
260 base::Bind(&EventHandledOnIOThread
,
261 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
262 request
->identifier(), response
));
264 // Extension2 response. Arrives second, and chosen because of install_time.
265 response
= new ExtensionWebRequestEventRouter::EventResponse(
266 extension2_id
, base::Time::FromDoubleT(2));
267 response
->new_url
= redirect_url
;
268 ipc_sender_
.PushTask(
269 base::Bind(&EventHandledOnIOThread
,
270 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
271 request
->identifier(), response
));
273 // Extension2 response to the redirected URL. Arrives first, and chosen.
274 response
= new ExtensionWebRequestEventRouter::EventResponse(
275 extension2_id
, base::Time::FromDoubleT(2));
276 ipc_sender_
.PushTask(
277 base::Bind(&EventHandledOnIOThread
,
278 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
279 request
->identifier(), response
));
281 // Extension1 response to the redirected URL. Arrives second, and ignored.
282 response
= new ExtensionWebRequestEventRouter::EventResponse(
283 extension1_id
, base::Time::FromDoubleT(1));
284 ipc_sender_
.PushTask(
285 base::Bind(&EventHandledOnIOThread
,
286 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
287 request
->identifier(), response
));
290 base::MessageLoop::current()->Run();
292 EXPECT_TRUE(!request
->is_pending());
293 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, request
->status().status());
294 EXPECT_EQ(0, request
->status().error());
295 EXPECT_EQ(redirect_url
, request
->url());
296 EXPECT_EQ(2U, request
->url_chain().size());
297 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
300 // Now test the same thing but the extensions answer in reverse order.
301 scoped_ptr
<net::URLRequest
> request2(context_
->CreateRequest(
302 GURL("about:blank"), net::DEFAULT_PRIORITY
, &delegate_
));
304 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
306 // Extension2 response. Arrives first, and chosen because of install_time.
307 response
= new ExtensionWebRequestEventRouter::EventResponse(
308 extension2_id
, base::Time::FromDoubleT(2));
309 response
->new_url
= redirect_url
;
310 ipc_sender_
.PushTask(
311 base::Bind(&EventHandledOnIOThread
,
312 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
313 request2
->identifier(), response
));
315 // Extension1 response. Arrives second, but ignored due to install_time.
316 response
= new ExtensionWebRequestEventRouter::EventResponse(
317 extension1_id
, base::Time::FromDoubleT(1));
318 response
->new_url
= not_chosen_redirect_url
;
319 ipc_sender_
.PushTask(
320 base::Bind(&EventHandledOnIOThread
,
321 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
322 request2
->identifier(), response
));
324 // Extension2 response to the redirected URL. Arrives first, and chosen.
325 response
= new ExtensionWebRequestEventRouter::EventResponse(
326 extension2_id
, base::Time::FromDoubleT(2));
327 ipc_sender_
.PushTask(
328 base::Bind(&EventHandledOnIOThread
,
329 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
330 request2
->identifier(), response
));
332 // Extension1 response to the redirected URL. Arrives second, and ignored.
333 response
= new ExtensionWebRequestEventRouter::EventResponse(
334 extension1_id
, base::Time::FromDoubleT(1));
335 ipc_sender_
.PushTask(
336 base::Bind(&EventHandledOnIOThread
,
337 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
338 request2
->identifier(), response
));
341 base::MessageLoop::current()->Run();
343 EXPECT_TRUE(!request2
->is_pending());
344 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, request2
->status().status());
345 EXPECT_EQ(0, request2
->status().error());
346 EXPECT_EQ(redirect_url
, request2
->url());
347 EXPECT_EQ(2U, request2
->url_chain().size());
348 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
351 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
352 &profile_
, extension1_id
, kEventName
+ "/1", 0, 0);
353 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
354 &profile_
, extension2_id
, kEventName
+ "/2", 0, 0);
357 // Test that a request is canceled if this is requested by any extension
358 // regardless whether it is the extension with the highest precedence.
359 TEST_F(ExtensionWebRequestTest
, BlockingEventPrecedenceCancel
) {
360 std::string
extension1_id("1");
361 std::string
extension2_id("2");
362 ExtensionWebRequestEventRouter::RequestFilter filter
;
363 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
364 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
365 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
366 &profile_
, extension1_id
, extension1_id
, kEventName
, kEventName
+ "/1",
367 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
368 ipc_sender_factory
.GetWeakPtr());
369 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
370 &profile_
, extension2_id
, extension2_id
, kEventName
, kEventName
+ "/2",
371 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
372 ipc_sender_factory
.GetWeakPtr());
374 GURL
request_url("about:blank");
375 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
376 request_url
, net::DEFAULT_PRIORITY
, &delegate_
));
378 // onBeforeRequest will be dispatched twice. The second response -
379 // the redirect - would win, since it has a later |install_time|, but
380 // the first response takes precedence because cancel >> redirect.
381 GURL
redirect_url("about:redirected");
382 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
384 // Extension1 response. Arrives first, would be ignored in principle due to
385 // install_time but "cancel" always wins.
386 response
= new ExtensionWebRequestEventRouter::EventResponse(
387 extension1_id
, base::Time::FromDoubleT(1));
388 response
->cancel
= true;
389 ipc_sender_
.PushTask(
390 base::Bind(&EventHandledOnIOThread
,
391 &profile_
, extension1_id
, kEventName
, kEventName
+ "/1",
392 request
->identifier(), response
));
394 // Extension2 response. Arrives second, but has higher precedence
395 // due to its later install_time.
396 response
= new ExtensionWebRequestEventRouter::EventResponse(
397 extension2_id
, base::Time::FromDoubleT(2));
398 response
->new_url
= redirect_url
;
399 ipc_sender_
.PushTask(
400 base::Bind(&EventHandledOnIOThread
,
401 &profile_
, extension2_id
, kEventName
, kEventName
+ "/2",
402 request
->identifier(), response
));
406 base::MessageLoop::current()->Run();
408 EXPECT_TRUE(!request
->is_pending());
409 EXPECT_EQ(net::URLRequestStatus::FAILED
, request
->status().status());
410 EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT
, request
->status().error());
411 EXPECT_EQ(request_url
, request
->url());
412 EXPECT_EQ(1U, request
->url_chain().size());
413 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
415 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
416 &profile_
, extension1_id
, kEventName
+ "/1", 0, 0);
417 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
418 &profile_
, extension2_id
, kEventName
+ "/2", 0, 0);
421 TEST_F(ExtensionWebRequestTest
, SimulateChancelWhileBlocked
) {
422 // We subscribe to OnBeforeRequest and OnErrorOccurred.
423 // While the OnBeforeRequest handler is blocked, we cancel the request.
424 // We verify that the response of the blocked OnBeforeRequest handler
427 std::string
extension_id("1");
428 ExtensionWebRequestEventRouter::RequestFilter filter
;
430 // Subscribe to OnBeforeRequest and OnErrorOccurred.
431 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
432 const std::string
kEventName2(web_request::OnErrorOccurred::kEventName
);
433 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
434 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
435 &profile_
, extension_id
, extension_id
, kEventName
, kEventName
+ "/1",
436 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
437 ipc_sender_factory
.GetWeakPtr());
438 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
439 &profile_
, extension_id
, extension_id
, kEventName2
, kEventName2
+ "/1",
440 filter
, 0, 0, 0, ipc_sender_factory
.GetWeakPtr());
442 GURL
request_url("about:blank");
443 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
444 request_url
, net::DEFAULT_PRIORITY
, &delegate_
));
446 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
448 // Extension response for the OnBeforeRequest handler. This should not be
449 // processed because request is canceled before the handler responds.
450 response
= new ExtensionWebRequestEventRouter::EventResponse(
451 extension_id
, base::Time::FromDoubleT(1));
452 GURL
redirect_url("about:redirected");
453 response
->new_url
= redirect_url
;
454 ipc_sender_
.PushTask(
455 base::Bind(&EventHandledOnIOThread
,
456 &profile_
, extension_id
, kEventName
, kEventName
+ "/1",
457 request
->identifier(), response
));
459 // Extension response for OnErrorOccurred: Terminate the message loop.
460 ipc_sender_
.PushTask(
461 base::Bind(&base::MessageLoop::PostTask
,
462 base::Unretained(base::MessageLoop::current()),
463 FROM_HERE
, base::MessageLoop::QuitClosure()));
466 // request->Start() will have submitted OnBeforeRequest by the time we cancel.
468 base::MessageLoop::current()->Run();
470 EXPECT_TRUE(!request
->is_pending());
471 EXPECT_EQ(net::URLRequestStatus::CANCELED
, request
->status().status());
472 EXPECT_EQ(net::ERR_ABORTED
, request
->status().error());
473 EXPECT_EQ(request_url
, request
->url());
474 EXPECT_EQ(1U, request
->url_chain().size());
475 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
477 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
478 &profile_
, extension_id
, kEventName
+ "/1", 0, 0);
479 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
480 &profile_
, extension_id
, kEventName2
+ "/1", 0, 0);
485 // Create the numerical representation of |values|, strings passed as
486 // extraInfoSpec by the event handler. Returns true on success, otherwise false.
487 bool GenerateInfoSpec(const std::string
& values
, int* result
) {
488 // Create a base::ListValue of strings.
489 base::ListValue list_value
;
490 for (const std::string
& cur
:
491 base::SplitString(values
, ",", base::KEEP_WHITESPACE
,
492 base::SPLIT_WANT_NONEMPTY
))
493 list_value
.Append(new base::StringValue(cur
));
494 return ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
500 void ExtensionWebRequestTest::FireURLRequestWithData(
501 const std::string
& method
,
502 const char* content_type
,
503 const std::vector
<char>& bytes_1
,
504 const std::vector
<char>& bytes_2
) {
505 // The request URL can be arbitrary but must have an HTTP or HTTPS scheme.
506 GURL
request_url("http://www.example.com");
507 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
508 request_url
, net::DEFAULT_PRIORITY
, &delegate_
));
509 request
->set_method(method
);
510 if (content_type
!= NULL
) {
511 request
->SetExtraRequestHeaderByName(net::HttpRequestHeaders::kContentType
,
513 true /* overwrite */);
515 ScopedVector
<net::UploadElementReader
> element_readers
;
516 element_readers
.push_back(new net::UploadBytesElementReader(
517 &(bytes_1
[0]), bytes_1
.size()));
518 element_readers
.push_back(
519 new net::UploadFileElementReader(
520 base::ThreadTaskRunnerHandle::Get()
526 element_readers
.push_back(
527 new net::UploadBytesElementReader(&(bytes_2
[0]), bytes_2
.size()));
528 request
->set_upload(make_scoped_ptr(
529 new net::ElementsUploadDataStream(element_readers
.Pass(), 0)));
530 ipc_sender_
.PushTask(base::Bind(&base::DoNothing
));
534 TEST_F(ExtensionWebRequestTest
, AccessRequestBodyData
) {
535 // We verify that URLRequest body is accessible to OnBeforeRequest listeners.
536 // These testing steps are repeated twice in a row:
537 // 1. Register an extension requesting "requestBody" in ExtraInfoSpec and
538 // file a POST URLRequest with a multipart-encoded form. See it getting
540 // 2. Do the same, but without requesting "requestBody". Nothing should be
542 // 3. With "requestBody", fire a POST URLRequest which is not a parseable
543 // HTML form. Raw data should be returned.
544 // 4. Do the same, but with a PUT method. Result should be the same.
545 const std::string
kMethodPost("POST");
546 const std::string
kMethodPut("PUT");
549 const char kPlainBlock1
[] = "abcd\n";
550 const size_t kPlainBlock1Length
= sizeof(kPlainBlock1
) - 1;
551 std::vector
<char> plain_1(kPlainBlock1
, kPlainBlock1
+ kPlainBlock1Length
);
552 const char kPlainBlock2
[] = "1234\n";
553 const size_t kPlainBlock2Length
= sizeof(kPlainBlock2
) - 1;
554 std::vector
<char> plain_2(kPlainBlock2
, kPlainBlock2
+ kPlainBlock2Length
);
555 #define kBoundary "THIS_IS_A_BOUNDARY"
556 const char kFormBlock1
[] = "--" kBoundary
"\r\n"
557 "Content-Disposition: form-data; name=\"A\"\r\n"
560 "--" kBoundary
"\r\n"
561 "Content-Disposition: form-data; name=\"B\"; filename=\"\"\r\n"
562 "Content-Type: application/octet-stream\r\n"
564 std::vector
<char> form_1(kFormBlock1
, kFormBlock1
+ sizeof(kFormBlock1
) - 1);
565 const char kFormBlock2
[] = "\r\n"
566 "--" kBoundary
"\r\n"
567 "Content-Disposition: form-data; name=\"C\"\r\n"
571 std::vector
<char> form_2(kFormBlock2
, kFormBlock2
+ sizeof(kFormBlock2
) - 1);
574 // Paths to look for in returned dictionaries.
575 const std::string
kBodyPath(keys::kRequestBodyKey
);
576 const std::string
kFormDataPath(
577 kBodyPath
+ "." + keys::kRequestBodyFormDataKey
);
578 const std::string
kRawPath(kBodyPath
+ "." + keys::kRequestBodyRawKey
);
579 const std::string
kErrorPath(kBodyPath
+ "." + keys::kRequestBodyErrorKey
);
580 const std::string
* const kPath
[] = {
586 // Contents of formData.
587 const char kFormData
[] =
588 "{\"A\":[\"test text\"],\"B\":[\"\"],\"C\":[\"test password\"]}";
589 scoped_ptr
<const base::Value
> form_data(
590 base::JSONReader::DeprecatedRead(kFormData
));
591 ASSERT_TRUE(form_data
.get() != NULL
);
592 ASSERT_TRUE(form_data
->GetType() == base::Value::TYPE_DICTIONARY
);
595 extensions::subtle::AppendKeyValuePair(
596 keys::kRequestBodyRawBytesKey
,
597 BinaryValue::CreateWithCopiedBuffer(kPlainBlock1
, kPlainBlock1Length
),
599 extensions::subtle::AppendKeyValuePair(
600 keys::kRequestBodyRawFileKey
,
601 new base::StringValue(std::string()),
603 extensions::subtle::AppendKeyValuePair(
604 keys::kRequestBodyRawBytesKey
,
605 BinaryValue::CreateWithCopiedBuffer(kPlainBlock2
, kPlainBlock2Length
),
608 const base::Value
* const kExpected
[] = {
614 static_assert(arraysize(kPath
) == arraysize(kExpected
),
615 "kPath and kExpected arrays should have the same number "
618 const char kMultipart
[] = "multipart/form-data; boundary=" kBoundary
;
621 // Set up a dummy extension name.
622 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
623 ExtensionWebRequestEventRouter::RequestFilter filter
;
624 std::string
extension_id("1");
625 const std::string
string_spec_post("blocking,requestBody");
626 const std::string
string_spec_no_post("blocking");
627 int extra_info_spec_empty
= 0;
628 int extra_info_spec_body
= 0;
629 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
632 // Subscribe to OnBeforeRequest with requestBody requirement.
633 ASSERT_TRUE(GenerateInfoSpec(string_spec_post
, &extra_info_spec_body
));
634 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
635 &profile_
, extension_id
, extension_id
, kEventName
, kEventName
+ "/1",
636 filter
, extra_info_spec_body
, 0, 0, ipc_sender_factory
.GetWeakPtr());
638 FireURLRequestWithData(kMethodPost
, kMultipart
, form_1
, form_2
);
640 // We inspect the result in the message list of |ipc_sender_| later.
641 base::MessageLoop::current()->RunUntilIdle();
643 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
644 &profile_
, extension_id
, kEventName
+ "/1", 0, 0);
647 // Now subscribe to OnBeforeRequest *without* the requestBody requirement.
649 GenerateInfoSpec(string_spec_no_post
, &extra_info_spec_empty
));
650 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
651 &profile_
, extension_id
, extension_id
, kEventName
, kEventName
+ "/1",
652 filter
, extra_info_spec_empty
, 0, 0, ipc_sender_factory
.GetWeakPtr());
654 FireURLRequestWithData(kMethodPost
, kMultipart
, form_1
, form_2
);
656 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
657 &profile_
, extension_id
, kEventName
+ "/1", 0, 0);
659 // Subscribe to OnBeforeRequest with requestBody requirement.
660 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
661 &profile_
, extension_id
, extension_id
, kEventName
, kEventName
+ "/1",
662 filter
, extra_info_spec_body
, 0, 0, ipc_sender_factory
.GetWeakPtr());
665 // Now send a POST request with body which is not parseable as a form.
666 FireURLRequestWithData(kMethodPost
, NULL
/*no header*/, plain_1
, plain_2
);
669 // Now send a PUT request with the same body as above.
670 FireURLRequestWithData(kMethodPut
, NULL
/*no header*/, plain_1
, plain_2
);
672 base::MessageLoop::current()->RunUntilIdle();
675 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
676 &profile_
, extension_id
, kEventName
+ "/1", 0, 0);
678 IPC::Message
* message
= NULL
;
679 TestIPCSender::SentMessages::const_iterator i
= ipc_sender_
.sent_begin();
680 for (size_t test
= 0; test
< arraysize(kExpected
); ++test
) {
681 SCOPED_TRACE(testing::Message("iteration number ") << test
);
682 EXPECT_NE(i
, ipc_sender_
.sent_end());
683 message
= (i
++)->get();
684 const base::DictionaryValue
* details
;
685 ExtensionMsg_MessageInvoke::Param param
;
686 GetPartOfMessageArguments(message
, &details
, ¶m
);
687 ASSERT_TRUE(details
!= NULL
);
688 const base::Value
* result
= NULL
;
689 if (kExpected
[test
]) {
690 EXPECT_TRUE(details
->Get(*(kPath
[test
]), &result
));
691 EXPECT_TRUE(kExpected
[test
]->Equals(result
));
693 EXPECT_FALSE(details
->Get(*(kPath
[test
]), &result
));
697 EXPECT_EQ(i
, ipc_sender_
.sent_end());
700 TEST_F(ExtensionWebRequestTest
, NoAccessRequestBodyData
) {
701 // We verify that URLRequest body is NOT accessible to OnBeforeRequest
702 // listeners when the type of the request is different from POST or PUT, or
703 // when the request body is empty. 3 requests are fired, without upload data,
704 // a POST, PUT and GET request. For none of them the "requestBody" object
705 // property should be present in the details passed to the onBeforeRequest
707 const char* const kMethods
[] = { "POST", "PUT", "GET" };
709 // Set up a dummy extension name.
710 const std::string
kEventName(web_request::OnBeforeRequest::kEventName
);
711 ExtensionWebRequestEventRouter::RequestFilter filter
;
712 const std::string
extension_id("1");
713 int extra_info_spec
= 0;
714 ASSERT_TRUE(GenerateInfoSpec("blocking,requestBody", &extra_info_spec
));
715 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
717 // Subscribe to OnBeforeRequest with requestBody requirement.
718 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
719 &profile_
, extension_id
, extension_id
, kEventName
, kEventName
+ "/1",
720 filter
, extra_info_spec
, 0, 0, ipc_sender_factory
.GetWeakPtr());
722 // The request URL can be arbitrary but must have an HTTP or HTTPS scheme.
723 const GURL
request_url("http://www.example.com");
725 for (size_t i
= 0; i
< arraysize(kMethods
); ++i
) {
726 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
727 request_url
, net::DEFAULT_PRIORITY
, &delegate_
));
728 request
->set_method(kMethods
[i
]);
729 ipc_sender_
.PushTask(base::Bind(&base::DoNothing
));
733 // We inspect the result in the message list of |ipc_sender_| later.
734 base::MessageLoop::current()->RunUntilIdle();
736 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
737 &profile_
, extension_id
, kEventName
+ "/1", 0, 0);
739 TestIPCSender::SentMessages::const_iterator i
= ipc_sender_
.sent_begin();
740 for (size_t test
= 0; test
< arraysize(kMethods
); ++test
, ++i
) {
741 SCOPED_TRACE(testing::Message("iteration number ") << test
);
742 EXPECT_NE(i
, ipc_sender_
.sent_end());
743 IPC::Message
* message
= i
->get();
744 const base::DictionaryValue
* details
= NULL
;
745 ExtensionMsg_MessageInvoke::Param param
;
746 GetPartOfMessageArguments(message
, &details
, ¶m
);
747 ASSERT_TRUE(details
!= NULL
);
748 EXPECT_FALSE(details
->HasKey(keys::kRequestBodyKey
));
751 EXPECT_EQ(i
, ipc_sender_
.sent_end());
754 struct HeaderModificationTest_Header
{
759 struct HeaderModificationTest_Modification
{
771 struct HeaderModificationTest
{
773 HeaderModificationTest_Header before
[10];
774 int modification_size
;
775 HeaderModificationTest_Modification modification
[10];
777 HeaderModificationTest_Header after
[10];
780 class ExtensionWebRequestHeaderModificationTest
781 : public testing::TestWithParam
<HeaderModificationTest
> {
783 ExtensionWebRequestHeaderModificationTest()
784 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
785 profile_manager_(TestingBrowserProcess::GetGlobal()),
786 event_router_(new EventRouterForwarder
) {}
789 void SetUp() override
{
790 ASSERT_TRUE(profile_manager_
.SetUp());
791 ChromeNetworkDelegate::InitializePrefsOnUIThread(
792 &enable_referrers_
, NULL
, NULL
, NULL
,
793 profile_
.GetTestingPrefService());
794 network_delegate_
.reset(
795 new ChromeNetworkDelegate(event_router_
.get(), &enable_referrers_
));
796 network_delegate_
->set_profile(&profile_
);
797 network_delegate_
->set_cookie_settings(
798 CookieSettingsFactory::GetForProfile(&profile_
).get());
799 context_
.reset(new net::TestURLRequestContext(true));
800 host_resolver_
.reset(new net::MockHostResolver());
801 host_resolver_
->rules()->AddSimulatedFailure("doesnotexist");
802 context_
->set_host_resolver(host_resolver_
.get());
803 context_
->set_network_delegate(network_delegate_
.get());
807 content::TestBrowserThreadBundle thread_bundle_
;
808 TestingProfile profile_
;
809 TestingProfileManager profile_manager_
;
810 net::TestDelegate delegate_
;
811 BooleanPrefMember enable_referrers_
;
812 TestIPCSender ipc_sender_
;
813 scoped_refptr
<EventRouterForwarder
> event_router_
;
814 scoped_refptr
<InfoMap
> extension_info_map_
;
815 scoped_ptr
<ChromeNetworkDelegate
> network_delegate_
;
816 scoped_ptr
<net::MockHostResolver
> host_resolver_
;
817 scoped_ptr
<net::TestURLRequestContext
> context_
;
820 TEST_P(ExtensionWebRequestHeaderModificationTest
, TestModifications
) {
821 std::string
extension1_id("1");
822 std::string
extension2_id("2");
823 std::string
extension3_id("3");
824 ExtensionWebRequestEventRouter::RequestFilter filter
;
825 const std::string
kEventName(keys::kOnBeforeSendHeadersEvent
);
826 base::WeakPtrFactory
<TestIPCSender
> ipc_sender_factory(&ipc_sender_
);
828 // Install two extensions that can modify headers. Extension 2 has
829 // higher precedence than extension 1.
830 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
831 &profile_
, extension1_id
, extension1_id
, kEventName
, kEventName
+ "/1",
832 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
833 ipc_sender_factory
.GetWeakPtr());
834 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
835 &profile_
, extension2_id
, extension2_id
, kEventName
, kEventName
+ "/2",
836 filter
, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
, 0, 0,
837 ipc_sender_factory
.GetWeakPtr());
839 // Install one extension that observes the final headers.
840 ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
841 &profile_
, extension3_id
, extension3_id
, keys::kOnSendHeadersEvent
,
842 std::string(keys::kOnSendHeadersEvent
) + "/3", filter
,
843 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS
, 0, 0,
844 ipc_sender_factory
.GetWeakPtr());
846 GURL
request_url("http://doesnotexist/does_not_exist.html");
847 scoped_ptr
<net::URLRequest
> request(context_
->CreateRequest(
848 request_url
, net::DEFAULT_PRIORITY
, &delegate_
));
850 // Initialize headers available before extensions are notified of the
851 // onBeforeSendHeaders event.
852 HeaderModificationTest test
= GetParam();
853 net::HttpRequestHeaders before_headers
;
854 for (int i
= 0; i
< test
.before_size
; ++i
)
855 before_headers
.SetHeader(test
.before
[i
].name
, test
.before
[i
].value
);
856 request
->SetExtraRequestHeaders(before_headers
);
858 // Gather the modifications to the headers for the respective extensions.
859 // We assume here that all modifications of one extension are listed
860 // in a continuous block of |test.modifications_|.
861 ExtensionWebRequestEventRouter::EventResponse
* response
= NULL
;
862 for (int i
= 0; i
< test
.modification_size
; ++i
) {
863 const HeaderModificationTest_Modification
& mod
= test
.modification
[i
];
864 if (response
== NULL
) {
865 response
= new ExtensionWebRequestEventRouter::EventResponse(
866 mod
.extension_id
== 1 ? extension1_id
: extension2_id
,
867 base::Time::FromDoubleT(mod
.extension_id
));
868 response
->request_headers
.reset(new net::HttpRequestHeaders());
869 response
->request_headers
->MergeFrom(request
->extra_request_headers());
873 case HeaderModificationTest_Modification::SET
:
874 response
->request_headers
->SetHeader(mod
.key
, mod
.value
);
876 case HeaderModificationTest_Modification::REMOVE
:
877 response
->request_headers
->RemoveHeader(mod
.key
);
881 // Trigger the result when this is the last modification statement or
882 // the block of modifications for the next extension starts.
883 if (i
+1 == test
.modification_size
||
884 mod
.extension_id
!= test
.modification
[i
+1].extension_id
) {
885 ipc_sender_
.PushTask(
886 base::Bind(&EventHandledOnIOThread
,
887 &profile_
, mod
.extension_id
== 1 ? extension1_id
: extension2_id
,
888 kEventName
, kEventName
+ (mod
.extension_id
== 1 ? "/1" : "/2"),
889 request
->identifier(), response
));
894 // Don't do anything for the onSendHeaders message.
895 ipc_sender_
.PushTask(base::Bind(&base::DoNothing
));
897 // Note that we mess up the headers slightly:
898 // request->Start() will first add additional headers (e.g. the User-Agent)
899 // and then send an event to the extension. When we have prepared our
900 // answers to the onBeforeSendHeaders events above, these headers did not
901 // exists and are therefore not listed in the responses. This makes
902 // them seem deleted.
904 base::MessageLoop::current()->Run();
906 EXPECT_TRUE(!request
->is_pending());
907 // This cannot succeed as we send the request to a server that does not exist.
908 EXPECT_EQ(net::URLRequestStatus::FAILED
, request
->status().status());
909 EXPECT_EQ(request_url
, request
->url());
910 EXPECT_EQ(1U, request
->url_chain().size());
911 EXPECT_EQ(0U, ipc_sender_
.GetNumTasks());
913 // Calculate the expected headers.
914 net::HttpRequestHeaders expected_headers
;
915 for (int i
= 0; i
< test
.after_size
; ++i
) {
916 expected_headers
.SetHeader(test
.after
[i
].name
,
917 test
.after
[i
].value
);
920 // Counter for the number of observed onSendHeaders events.
921 int num_headers_observed
= 0;
923 // Search the onSendHeaders signal in the IPC messages and check that
924 // it contained the correct headers.
925 TestIPCSender::SentMessages::const_iterator i
;
926 for (i
= ipc_sender_
.sent_begin(); i
!= ipc_sender_
.sent_end(); ++i
) {
927 IPC::Message
* message
= i
->get();
928 if (ExtensionMsg_MessageInvoke::ID
!= message
->type())
930 ExtensionMsg_MessageInvoke::Param message_tuple
;
931 ExtensionMsg_MessageInvoke::Read(message
, &message_tuple
);
932 base::ListValue
& args
= base::get
<3>(message_tuple
);
934 std::string event_name
;
935 if (!args
.GetString(0, &event_name
) ||
936 event_name
!= std::string(keys::kOnSendHeadersEvent
) + "/3") {
940 base::ListValue
* event_arg
= NULL
;
941 ASSERT_TRUE(args
.GetList(1, &event_arg
));
943 base::DictionaryValue
* event_arg_dict
= NULL
;
944 ASSERT_TRUE(event_arg
->GetDictionary(0, &event_arg_dict
));
946 base::ListValue
* request_headers
= NULL
;
947 ASSERT_TRUE(event_arg_dict
->GetList(keys::kRequestHeadersKey
,
950 net::HttpRequestHeaders observed_headers
;
951 for (size_t j
= 0; j
< request_headers
->GetSize(); ++j
) {
952 base::DictionaryValue
* header
= NULL
;
953 ASSERT_TRUE(request_headers
->GetDictionary(j
, &header
));
956 ASSERT_TRUE(header
->GetString(keys::kHeaderNameKey
, &key
));
957 ASSERT_TRUE(header
->GetString(keys::kHeaderValueKey
, &value
));
958 observed_headers
.SetHeader(key
, value
);
961 EXPECT_EQ(expected_headers
.ToString(), observed_headers
.ToString());
962 ++num_headers_observed
;
964 EXPECT_EQ(1, num_headers_observed
);
965 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
966 &profile_
, extension1_id
, kEventName
+ "/1", 0, 0);
967 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
968 &profile_
, extension2_id
, kEventName
+ "/2", 0, 0);
969 ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
970 &profile_
, extension3_id
,
971 std::string(keys::kOnSendHeadersEvent
) + "/3", 0, 0);
976 void TestInitFromValue(const std::string
& values
, bool expected_return_code
,
977 int expected_extra_info_spec
) {
978 int actual_info_spec
;
979 bool actual_return_code
= GenerateInfoSpec(values
, &actual_info_spec
);
980 EXPECT_EQ(expected_return_code
, actual_return_code
);
981 if (expected_return_code
)
982 EXPECT_EQ(expected_extra_info_spec
, actual_info_spec
);
987 TEST_F(ExtensionWebRequestTest
, InitFromValue
) {
988 TestInitFromValue(std::string(), true, 0);
990 // Single valid values.
994 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS
);
998 ExtensionWebRequestEventRouter::ExtraInfoSpec::RESPONSE_HEADERS
);
1002 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
);
1006 ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING
);
1010 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_BODY
);
1012 // Multiple valid values are bitwise-or'ed.
1014 "requestHeaders,blocking",
1016 ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS
|
1017 ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING
);
1019 // Any invalid values lead to a bad parse.
1020 TestInitFromValue("invalidValue", false, 0);
1021 TestInitFromValue("blocking,invalidValue", false, 0);
1022 TestInitFromValue("invalidValue1,invalidValue2", false, 0);
1024 // BLOCKING and ASYNC_BLOCKING are mutually exclusive.
1025 TestInitFromValue("blocking,asyncBlocking", false, 0);
1030 const HeaderModificationTest_Modification::Type SET
=
1031 HeaderModificationTest_Modification::SET
;
1032 const HeaderModificationTest_Modification::Type REMOVE
=
1033 HeaderModificationTest_Modification::REMOVE
;
1035 HeaderModificationTest kTests
[] = {
1036 // Check that extension 2 always wins when settings the same header.
1038 // Headers before test.
1039 2, { {"header1", "value1"},
1040 {"header2", "value2"} },
1041 // Modifications in test.
1042 2, { {1, SET
, "header1", "foo"},
1043 {2, SET
, "header1", "bar"} },
1044 // Headers after test.
1045 2, { {"header1", "bar"},
1046 {"header2", "value2"} }
1048 // Same as before in reverse execution order.
1050 // Headers before test.
1051 2, { {"header1", "value1"},
1052 {"header2", "value2"} },
1053 // Modifications in test.
1054 2, { {2, SET
, "header1", "bar"},
1055 {1, SET
, "header1", "foo"} },
1056 // Headers after test.
1057 2, { {"header1", "bar"},
1058 {"header2", "value2"} }
1060 // Check that two extensions can modify different headers that do not
1063 // Headers before test.
1064 2, { {"header1", "value1"},
1065 {"header2", "value2"} },
1066 // Modifications in test.
1067 2, { {1, SET
, "header1", "foo"},
1068 {2, SET
, "header2", "bar"} },
1069 // Headers after test.
1070 2, { {"header1", "foo"},
1071 {"header2", "bar"} }
1073 // Check insert/delete conflict.
1075 // Headers before test.
1076 1, { {"header1", "value1"} },
1077 // Modifications in test.
1078 2, { {1, SET
, "header1", "foo"},
1079 {2, REMOVE
, "header1", NULL
} },
1080 // Headers after test.
1084 // Headers before test.
1085 1, { {"header1", "value1"} },
1086 // Modifications in test.
1087 2, { {2, REMOVE
, "header1", NULL
},
1088 {1, SET
, "header1", "foo"} },
1089 // Headers after test.
1093 // Headers before test.
1094 1, { {"header1", "value1"} },
1095 // Modifications in test.
1096 2, { {1, REMOVE
, "header1", NULL
},
1097 {2, SET
, "header1", "foo"} },
1098 // Headers after test.
1099 1, { {"header1", "foo"} }
1102 // Headers before test.
1103 1, { {"header1", "value1"} },
1104 // Modifications in test.
1105 2, { {2, SET
, "header1", "foo"},
1106 {1, REMOVE
, "header1", NULL
} },
1107 // Headers after test.
1108 1, { {"header1", "foo"} }
1110 // Check that edits are atomic (i.e. either all edit requests of an
1111 // extension are executed or none).
1113 // Headers before test.
1115 // Modifications in test.
1116 3, { {1, SET
, "header1", "value1"},
1117 {1, SET
, "header2", "value2"},
1118 {2, SET
, "header1", "foo"} },
1119 // Headers after test.
1120 1, { {"header1", "foo"} } // set(header2) is ignored
1122 // Check that identical edits do not conflict (set(header2) would be ignored
1123 // if set(header1) were considered a conflict).
1125 // Headers before test.
1127 // Modifications in test.
1128 3, { {1, SET
, "header1", "value2"},
1129 {1, SET
, "header2", "foo"},
1130 {2, SET
, "header1", "value2"} },
1131 // Headers after test.
1132 2, { {"header1", "value2"},
1133 {"header2", "foo"} }
1135 // Check that identical deletes do not conflict (set(header2) would be ignored
1136 // if delete(header1) were considered a conflict).
1138 // Headers before test.
1139 1, { {"header1", "value1"} },
1140 // Modifications in test.
1141 3, { {1, REMOVE
, "header1", NULL
},
1142 {1, SET
, "header2", "foo"},
1143 {2, REMOVE
, "header1", NULL
} },
1144 // Headers after test.
1145 1, { {"header2", "foo"} }
1147 // Check that setting a value to an identical value is not considered an
1148 // edit operation that can conflict.
1150 // Headers before test.
1151 1, { {"header1", "value1"} },
1152 // Modifications in test.
1153 3, { {1, SET
, "header1", "foo"},
1154 {1, SET
, "header2", "bar"},
1155 {2, SET
, "header1", "value1"} },
1156 // Headers after test.
1157 2, { {"header1", "foo"},
1158 {"header2", "bar"} }
1162 INSTANTIATE_TEST_CASE_P(
1163 ExtensionWebRequest
,
1164 ExtensionWebRequestHeaderModificationTest
,
1165 ::testing::ValuesIn(kTests
));
1170 TEST(ExtensionWebRequestHelpersTest
,
1171 TestInDecreasingExtensionInstallationTimeOrder
) {
1172 linked_ptr
<EventResponseDelta
> a(
1173 new EventResponseDelta("ext_1", base::Time::FromInternalValue(0)));
1174 linked_ptr
<EventResponseDelta
> b(
1175 new EventResponseDelta("ext_2", base::Time::FromInternalValue(1000)));
1176 EXPECT_FALSE(InDecreasingExtensionInstallationTimeOrder(a
, a
));
1177 EXPECT_FALSE(InDecreasingExtensionInstallationTimeOrder(a
, b
));
1178 EXPECT_TRUE(InDecreasingExtensionInstallationTimeOrder(b
, a
));
1181 TEST(ExtensionWebRequestHelpersTest
, TestStringToCharList
) {
1182 base::ListValue list_value
;
1183 list_value
.Append(new base::FundamentalValue('1'));
1184 list_value
.Append(new base::FundamentalValue('2'));
1185 list_value
.Append(new base::FundamentalValue('3'));
1186 list_value
.Append(new base::FundamentalValue(0xFE));
1187 list_value
.Append(new base::FundamentalValue(0xD1));
1189 unsigned char char_value
[] = {'1', '2', '3', 0xFE, 0xD1};
1190 std::string
string_value(reinterpret_cast<char *>(char_value
), 5);
1192 scoped_ptr
<base::ListValue
> converted_list(StringToCharList(string_value
));
1193 EXPECT_TRUE(list_value
.Equals(converted_list
.get()));
1195 std::string converted_string
;
1196 EXPECT_TRUE(CharListToString(&list_value
, &converted_string
));
1197 EXPECT_EQ(string_value
, converted_string
);
1200 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnBeforeRequestDelta
) {
1201 const bool cancel
= true;
1202 const GURL
localhost("http://localhost");
1203 scoped_ptr
<EventResponseDelta
> delta(
1204 CalculateOnBeforeRequestDelta("extid", base::Time::Now(),
1205 cancel
, localhost
));
1206 ASSERT_TRUE(delta
.get());
1207 EXPECT_TRUE(delta
->cancel
);
1208 EXPECT_EQ(localhost
, delta
->new_url
);
1211 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnBeforeSendHeadersDelta
) {
1212 const bool cancel
= true;
1214 net::HttpRequestHeaders old_headers
;
1215 old_headers
.AddHeadersFromString("key1: value1\r\n"
1216 "key2: value2\r\n");
1218 // Test adding a header.
1219 net::HttpRequestHeaders new_headers_added
;
1220 new_headers_added
.AddHeadersFromString("key1: value1\r\n"
1222 "key2: value2\r\n");
1223 scoped_ptr
<EventResponseDelta
> delta_added(
1224 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1225 &old_headers
, &new_headers_added
));
1226 ASSERT_TRUE(delta_added
.get());
1227 EXPECT_TRUE(delta_added
->cancel
);
1228 ASSERT_TRUE(delta_added
->modified_request_headers
.GetHeader("key3", &value
));
1229 EXPECT_EQ("value3", value
);
1231 // Test deleting a header.
1232 net::HttpRequestHeaders new_headers_deleted
;
1233 new_headers_deleted
.AddHeadersFromString("key1: value1\r\n");
1234 scoped_ptr
<EventResponseDelta
> delta_deleted(
1235 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1236 &old_headers
, &new_headers_deleted
));
1237 ASSERT_TRUE(delta_deleted
.get());
1238 ASSERT_EQ(1u, delta_deleted
->deleted_request_headers
.size());
1239 ASSERT_EQ("key2", delta_deleted
->deleted_request_headers
.front());
1241 // Test modifying a header.
1242 net::HttpRequestHeaders new_headers_modified
;
1243 new_headers_modified
.AddHeadersFromString("key1: value1\r\n"
1244 "key2: value3\r\n");
1245 scoped_ptr
<EventResponseDelta
> delta_modified(
1246 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1247 &old_headers
, &new_headers_modified
));
1248 ASSERT_TRUE(delta_modified
.get());
1249 EXPECT_TRUE(delta_modified
->deleted_request_headers
.empty());
1251 delta_modified
->modified_request_headers
.GetHeader("key2", &value
));
1252 EXPECT_EQ("value3", value
);
1254 // Test modifying a header if extension author just appended a new (key,
1255 // value) pair with a key that existed before. This is incorrect
1256 // usage of the API that shall be handled gracefully.
1257 net::HttpRequestHeaders new_headers_modified2
;
1258 new_headers_modified2
.AddHeadersFromString("key1: value1\r\n"
1260 "key2: value3\r\n");
1261 scoped_ptr
<EventResponseDelta
> delta_modified2(
1262 CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel
,
1263 &old_headers
, &new_headers_modified
));
1264 ASSERT_TRUE(delta_modified2
.get());
1265 EXPECT_TRUE(delta_modified2
->deleted_request_headers
.empty());
1267 delta_modified2
->modified_request_headers
.GetHeader("key2", &value
));
1268 EXPECT_EQ("value3", value
);
1271 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnHeadersReceivedDelta
) {
1272 const bool cancel
= true;
1273 char base_headers_string
[] =
1274 "HTTP/1.0 200 OK\r\n"
1276 "Key2: Value2, Bar\r\n"
1279 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
1280 new net::HttpResponseHeaders(
1281 net::HttpUtil::AssembleRawHeaders(
1282 base_headers_string
, sizeof(base_headers_string
))));
1284 ResponseHeaders new_headers
;
1285 new_headers
.push_back(ResponseHeader("kEy1", "Value1")); // Unchanged
1286 new_headers
.push_back(ResponseHeader("Key2", "Value1")); // Modified
1288 new_headers
.push_back(ResponseHeader("Key4", "Value4")); // Added
1289 GURL effective_new_url
;
1291 scoped_ptr
<EventResponseDelta
> delta(
1292 CalculateOnHeadersReceivedDelta("extid",
1298 ASSERT_TRUE(delta
.get());
1299 EXPECT_TRUE(delta
->cancel
);
1300 EXPECT_EQ(2u, delta
->added_response_headers
.size());
1301 EXPECT_TRUE(Contains(delta
->added_response_headers
,
1302 ResponseHeader("Key2", "Value1")));
1303 EXPECT_TRUE(Contains(delta
->added_response_headers
,
1304 ResponseHeader("Key4", "Value4")));
1305 EXPECT_EQ(2u, delta
->deleted_response_headers
.size());
1306 EXPECT_TRUE(Contains(delta
->deleted_response_headers
,
1307 ResponseHeader("Key2", "Value2, Bar")));
1308 EXPECT_TRUE(Contains(delta
->deleted_response_headers
,
1309 ResponseHeader("Key3", "Value3")));
1312 TEST(ExtensionWebRequestHelpersTest
, TestCalculateOnAuthRequiredDelta
) {
1313 const bool cancel
= true;
1315 base::string16 username
= base::ASCIIToUTF16("foo");
1316 base::string16 password
= base::ASCIIToUTF16("bar");
1317 scoped_ptr
<net::AuthCredentials
> credentials(
1318 new net::AuthCredentials(username
, password
));
1320 scoped_ptr
<EventResponseDelta
> delta(
1321 CalculateOnAuthRequiredDelta("extid", base::Time::Now(), cancel
,
1323 ASSERT_TRUE(delta
.get());
1324 EXPECT_TRUE(delta
->cancel
);
1325 ASSERT_TRUE(delta
->auth_credentials
.get());
1326 EXPECT_EQ(username
, delta
->auth_credentials
->username());
1327 EXPECT_EQ(password
, delta
->auth_credentials
->password());
1330 TEST(ExtensionWebRequestHelpersTest
, TestMergeCancelOfResponses
) {
1331 EventResponseDeltas deltas
;
1332 net::BoundTestNetLog capturing_net_log
;
1333 net::BoundNetLog net_log
= capturing_net_log
.bound();
1334 bool canceled
= false;
1336 // Single event that does not cancel.
1337 linked_ptr
<EventResponseDelta
> d1(
1338 new EventResponseDelta("extid1", base::Time::FromInternalValue(1000)));
1340 deltas
.push_back(d1
);
1341 MergeCancelOfResponses(deltas
, &canceled
, &net_log
);
1342 EXPECT_FALSE(canceled
);
1343 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1345 // Second event that cancels the request
1346 linked_ptr
<EventResponseDelta
> d2(
1347 new EventResponseDelta("extid2", base::Time::FromInternalValue(500)));
1349 deltas
.push_back(d2
);
1350 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1351 MergeCancelOfResponses(deltas
, &canceled
, &net_log
);
1352 EXPECT_TRUE(canceled
);
1353 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1356 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeRequestResponses
) {
1357 EventResponseDeltas deltas
;
1358 net::BoundTestNetLog capturing_net_log
;
1359 net::BoundNetLog net_log
= capturing_net_log
.bound();
1360 WarningSet warning_set
;
1361 GURL effective_new_url
;
1364 linked_ptr
<EventResponseDelta
> d0(
1365 new EventResponseDelta("extid0", base::Time::FromInternalValue(0)));
1366 deltas
.push_back(d0
);
1367 MergeOnBeforeRequestResponses(
1368 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1369 EXPECT_TRUE(effective_new_url
.is_empty());
1372 GURL
new_url_1("http://foo.com");
1373 linked_ptr
<EventResponseDelta
> d1(
1374 new EventResponseDelta("extid1", base::Time::FromInternalValue(1000)));
1375 d1
->new_url
= GURL(new_url_1
);
1376 deltas
.push_back(d1
);
1377 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1378 capturing_net_log
.Clear();
1379 MergeOnBeforeRequestResponses(
1380 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1381 EXPECT_EQ(new_url_1
, effective_new_url
);
1382 EXPECT_TRUE(warning_set
.empty());
1383 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1385 // Ignored redirect (due to precedence).
1386 GURL
new_url_2("http://bar.com");
1387 linked_ptr
<EventResponseDelta
> d2(
1388 new EventResponseDelta("extid2", base::Time::FromInternalValue(500)));
1389 d2
->new_url
= GURL(new_url_2
);
1390 deltas
.push_back(d2
);
1391 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1392 warning_set
.clear();
1393 capturing_net_log
.Clear();
1394 MergeOnBeforeRequestResponses(
1395 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1396 EXPECT_EQ(new_url_1
, effective_new_url
);
1397 EXPECT_EQ(1u, warning_set
.size());
1398 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1399 EXPECT_EQ(2u, capturing_net_log
.GetSize());
1401 // Overriding redirect.
1402 GURL
new_url_3("http://baz.com");
1403 linked_ptr
<EventResponseDelta
> d3(
1404 new EventResponseDelta("extid3", base::Time::FromInternalValue(1500)));
1405 d3
->new_url
= GURL(new_url_3
);
1406 deltas
.push_back(d3
);
1407 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1408 warning_set
.clear();
1409 capturing_net_log
.Clear();
1410 MergeOnBeforeRequestResponses(
1411 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1412 EXPECT_EQ(new_url_3
, effective_new_url
);
1413 EXPECT_EQ(2u, warning_set
.size());
1414 EXPECT_TRUE(HasWarning(warning_set
, "extid1"));
1415 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1416 EXPECT_EQ(3u, capturing_net_log
.GetSize());
1418 // Check that identical redirects don't cause a conflict.
1419 linked_ptr
<EventResponseDelta
> d4(
1420 new EventResponseDelta("extid4", base::Time::FromInternalValue(2000)));
1421 d4
->new_url
= GURL(new_url_3
);
1422 deltas
.push_back(d4
);
1423 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1424 warning_set
.clear();
1425 capturing_net_log
.Clear();
1426 MergeOnBeforeRequestResponses(
1427 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1428 EXPECT_EQ(new_url_3
, effective_new_url
);
1429 EXPECT_EQ(2u, warning_set
.size());
1430 EXPECT_TRUE(HasWarning(warning_set
, "extid1"));
1431 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1432 EXPECT_EQ(4u, capturing_net_log
.GetSize());
1435 // This tests that we can redirect to data:// urls, which is considered
1436 // a kind of cancelling requests.
1437 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeRequestResponses2
) {
1438 EventResponseDeltas deltas
;
1439 net::BoundTestNetLog capturing_net_log
;
1440 net::BoundNetLog net_log
= capturing_net_log
.bound();
1441 WarningSet warning_set
;
1442 GURL effective_new_url
;
1445 GURL
new_url_0("http://foo.com");
1446 linked_ptr
<EventResponseDelta
> d0(
1447 new EventResponseDelta("extid0", base::Time::FromInternalValue(2000)));
1448 d0
->new_url
= GURL(new_url_0
);
1449 deltas
.push_back(d0
);
1450 MergeOnBeforeRequestResponses(
1451 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1452 EXPECT_EQ(new_url_0
, effective_new_url
);
1454 // Cancel request by redirecting to a data:// URL. This shall override
1455 // the other redirect but not cause any conflict warnings.
1456 GURL
new_url_1("data://foo");
1457 linked_ptr
<EventResponseDelta
> d1(
1458 new EventResponseDelta("extid1", base::Time::FromInternalValue(1500)));
1459 d1
->new_url
= GURL(new_url_1
);
1460 deltas
.push_back(d1
);
1461 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1462 warning_set
.clear();
1463 capturing_net_log
.Clear();
1464 MergeOnBeforeRequestResponses(
1465 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1466 EXPECT_EQ(new_url_1
, effective_new_url
);
1467 EXPECT_TRUE(warning_set
.empty());
1468 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1470 // Cancel request by redirecting to the same data:// URL. This shall
1471 // not create any conflicts as it is in line with d1.
1472 GURL
new_url_2("data://foo");
1473 linked_ptr
<EventResponseDelta
> d2(
1474 new EventResponseDelta("extid2", base::Time::FromInternalValue(1000)));
1475 d2
->new_url
= GURL(new_url_2
);
1476 deltas
.push_back(d2
);
1477 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1478 warning_set
.clear();
1479 capturing_net_log
.Clear();
1480 MergeOnBeforeRequestResponses(
1481 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1482 EXPECT_EQ(new_url_1
, effective_new_url
);
1483 EXPECT_TRUE(warning_set
.empty());
1484 EXPECT_EQ(2u, capturing_net_log
.GetSize());
1486 // Cancel redirect by redirecting to a different data:// URL. This needs
1487 // to create a conflict.
1488 GURL
new_url_3("data://something_totally_different");
1489 linked_ptr
<EventResponseDelta
> d3(
1490 new EventResponseDelta("extid3", base::Time::FromInternalValue(500)));
1491 d3
->new_url
= GURL(new_url_3
);
1492 deltas
.push_back(d3
);
1493 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1494 warning_set
.clear();
1495 capturing_net_log
.Clear();
1496 MergeOnBeforeRequestResponses(
1497 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1498 EXPECT_EQ(new_url_1
, effective_new_url
);
1499 EXPECT_EQ(1u, warning_set
.size());
1500 EXPECT_TRUE(HasWarning(warning_set
, "extid3"));
1501 EXPECT_EQ(3u, capturing_net_log
.GetSize());
1504 // This tests that we can redirect to about:blank, which is considered
1505 // a kind of cancelling requests.
1506 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeRequestResponses3
) {
1507 EventResponseDeltas deltas
;
1508 net::BoundTestNetLog capturing_net_log
;
1509 net::BoundNetLog net_log
= capturing_net_log
.bound();
1510 WarningSet warning_set
;
1511 GURL effective_new_url
;
1514 GURL
new_url_0("http://foo.com");
1515 linked_ptr
<EventResponseDelta
> d0(
1516 new EventResponseDelta("extid0", base::Time::FromInternalValue(2000)));
1517 d0
->new_url
= GURL(new_url_0
);
1518 deltas
.push_back(d0
);
1519 MergeOnBeforeRequestResponses(
1520 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1521 EXPECT_EQ(new_url_0
, effective_new_url
);
1523 // Cancel request by redirecting to about:blank. This shall override
1524 // the other redirect but not cause any conflict warnings.
1525 GURL
new_url_1("about:blank");
1526 linked_ptr
<EventResponseDelta
> d1(
1527 new EventResponseDelta("extid1", base::Time::FromInternalValue(1500)));
1528 d1
->new_url
= GURL(new_url_1
);
1529 deltas
.push_back(d1
);
1530 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1531 warning_set
.clear();
1532 capturing_net_log
.Clear();
1533 MergeOnBeforeRequestResponses(
1534 deltas
, &effective_new_url
, &warning_set
, &net_log
);
1535 EXPECT_EQ(new_url_1
, effective_new_url
);
1536 EXPECT_TRUE(warning_set
.empty());
1537 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1540 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnBeforeSendHeadersResponses
) {
1541 net::HttpRequestHeaders base_headers
;
1542 base_headers
.AddHeaderFromString("key1: value 1");
1543 base_headers
.AddHeaderFromString("key2: value 2");
1544 net::BoundTestNetLog capturing_net_log
;
1545 net::BoundNetLog net_log
= capturing_net_log
.bound();
1546 WarningSet warning_set
;
1547 std::string header_value
;
1548 EventResponseDeltas deltas
;
1550 // Check that we can handle not changing the headers.
1551 linked_ptr
<EventResponseDelta
> d0(
1552 new EventResponseDelta("extid0", base::Time::FromInternalValue(2500)));
1553 deltas
.push_back(d0
);
1554 net::HttpRequestHeaders headers0
;
1555 headers0
.MergeFrom(base_headers
);
1556 MergeOnBeforeSendHeadersResponses(deltas
, &headers0
, &warning_set
, &net_log
);
1557 ASSERT_TRUE(headers0
.GetHeader("key1", &header_value
));
1558 EXPECT_EQ("value 1", header_value
);
1559 ASSERT_TRUE(headers0
.GetHeader("key2", &header_value
));
1560 EXPECT_EQ("value 2", header_value
);
1561 EXPECT_EQ(0u, warning_set
.size());
1562 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1564 // Delete, modify and add a header.
1565 linked_ptr
<EventResponseDelta
> d1(
1566 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
1567 d1
->deleted_request_headers
.push_back("key1");
1568 d1
->modified_request_headers
.AddHeaderFromString("key2: value 3");
1569 d1
->modified_request_headers
.AddHeaderFromString("key3: value 3");
1570 deltas
.push_back(d1
);
1571 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1572 warning_set
.clear();
1573 capturing_net_log
.Clear();
1574 net::HttpRequestHeaders headers1
;
1575 headers1
.MergeFrom(base_headers
);
1576 MergeOnBeforeSendHeadersResponses(deltas
, &headers1
, &warning_set
, &net_log
);
1577 EXPECT_FALSE(headers1
.HasHeader("key1"));
1578 ASSERT_TRUE(headers1
.GetHeader("key2", &header_value
));
1579 EXPECT_EQ("value 3", header_value
);
1580 ASSERT_TRUE(headers1
.GetHeader("key3", &header_value
));
1581 EXPECT_EQ("value 3", header_value
);
1582 EXPECT_EQ(0u, warning_set
.size());
1583 EXPECT_EQ(1u, capturing_net_log
.GetSize());
1585 // Check that conflicts are atomic, i.e. if one header modification
1586 // collides all other conflicts of the same extension are declined as well.
1587 linked_ptr
<EventResponseDelta
> d2(
1588 new EventResponseDelta("extid2", base::Time::FromInternalValue(1500)));
1589 // This one conflicts:
1590 d2
->modified_request_headers
.AddHeaderFromString("key3: value 0");
1591 d2
->modified_request_headers
.AddHeaderFromString("key4: value 4");
1592 deltas
.push_back(d2
);
1593 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1594 warning_set
.clear();
1595 capturing_net_log
.Clear();
1596 net::HttpRequestHeaders headers2
;
1597 headers2
.MergeFrom(base_headers
);
1598 MergeOnBeforeSendHeadersResponses(deltas
, &headers2
, &warning_set
, &net_log
);
1599 EXPECT_FALSE(headers2
.HasHeader("key1"));
1600 ASSERT_TRUE(headers2
.GetHeader("key2", &header_value
));
1601 EXPECT_EQ("value 3", header_value
);
1602 ASSERT_TRUE(headers2
.GetHeader("key3", &header_value
));
1603 EXPECT_EQ("value 3", header_value
);
1604 EXPECT_FALSE(headers2
.HasHeader("key4"));
1605 EXPECT_EQ(1u, warning_set
.size());
1606 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1607 EXPECT_EQ(2u, capturing_net_log
.GetSize());
1609 // Check that identical modifications don't conflict and operations
1611 linked_ptr
<EventResponseDelta
> d3(
1612 new EventResponseDelta("extid3", base::Time::FromInternalValue(1000)));
1613 d3
->deleted_request_headers
.push_back("key1");
1614 d3
->modified_request_headers
.AddHeaderFromString("key2: value 3");
1615 d3
->modified_request_headers
.AddHeaderFromString("key5: value 5");
1616 deltas
.push_back(d3
);
1617 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1618 warning_set
.clear();
1619 capturing_net_log
.Clear();
1620 net::HttpRequestHeaders headers3
;
1621 headers3
.MergeFrom(base_headers
);
1622 MergeOnBeforeSendHeadersResponses(deltas
, &headers3
, &warning_set
, &net_log
);
1623 EXPECT_FALSE(headers3
.HasHeader("key1"));
1624 ASSERT_TRUE(headers3
.GetHeader("key2", &header_value
));
1625 EXPECT_EQ("value 3", header_value
);
1626 ASSERT_TRUE(headers3
.GetHeader("key3", &header_value
));
1627 EXPECT_EQ("value 3", header_value
);
1628 ASSERT_TRUE(headers3
.GetHeader("key5", &header_value
));
1629 EXPECT_EQ("value 5", header_value
);
1630 EXPECT_EQ(1u, warning_set
.size());
1631 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
1632 EXPECT_EQ(3u, capturing_net_log
.GetSize());
1635 TEST(ExtensionWebRequestHelpersTest
,
1636 TestMergeOnBeforeSendHeadersResponses_Cookies
) {
1637 net::HttpRequestHeaders base_headers
;
1638 base_headers
.AddHeaderFromString(
1639 "Cookie: name=value; name2=value2; name3=\"value3\"");
1640 net::BoundTestNetLog capturing_net_log
;
1641 net::BoundNetLog net_log
= capturing_net_log
.bound();
1642 WarningSet warning_set
;
1643 std::string header_value
;
1644 EventResponseDeltas deltas
;
1646 linked_ptr
<RequestCookieModification
> add_cookie
=
1647 make_linked_ptr(new RequestCookieModification
);
1648 add_cookie
->type
= helpers::ADD
;
1649 add_cookie
->modification
.reset(new helpers::RequestCookie
);
1650 add_cookie
->modification
->name
.reset(new std::string("name4"));
1651 add_cookie
->modification
->value
.reset(new std::string("\"value 4\""));
1653 linked_ptr
<RequestCookieModification
> add_cookie_2
=
1654 make_linked_ptr(new RequestCookieModification
);
1655 add_cookie_2
->type
= helpers::ADD
;
1656 add_cookie_2
->modification
.reset(new helpers::RequestCookie
);
1657 add_cookie_2
->modification
->name
.reset(new std::string("name"));
1658 add_cookie_2
->modification
->value
.reset(new std::string("new value"));
1660 linked_ptr
<RequestCookieModification
> edit_cookie
=
1661 make_linked_ptr(new RequestCookieModification
);
1662 edit_cookie
->type
= helpers::EDIT
;
1663 edit_cookie
->filter
.reset(new helpers::RequestCookie
);
1664 edit_cookie
->filter
->name
.reset(new std::string("name2"));
1665 edit_cookie
->modification
.reset(new helpers::RequestCookie
);
1666 edit_cookie
->modification
->value
.reset(new std::string("new value"));
1668 linked_ptr
<RequestCookieModification
> remove_cookie
=
1669 make_linked_ptr(new RequestCookieModification
);
1670 remove_cookie
->type
= helpers::REMOVE
;
1671 remove_cookie
->filter
.reset(new helpers::RequestCookie
);
1672 remove_cookie
->filter
->name
.reset(new std::string("name3"));
1674 linked_ptr
<RequestCookieModification
> operations
[] = {
1675 add_cookie
, add_cookie_2
, edit_cookie
, remove_cookie
1678 for (size_t i
= 0; i
< arraysize(operations
); ++i
) {
1679 linked_ptr
<EventResponseDelta
> delta(
1680 new EventResponseDelta("extid0", base::Time::FromInternalValue(i
* 5)));
1681 delta
->request_cookie_modifications
.push_back(operations
[i
]);
1682 deltas
.push_back(delta
);
1684 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1685 net::HttpRequestHeaders headers1
;
1686 headers1
.MergeFrom(base_headers
);
1687 warning_set
.clear();
1688 MergeOnBeforeSendHeadersResponses(deltas
, &headers1
, &warning_set
, &net_log
);
1689 EXPECT_TRUE(headers1
.HasHeader("Cookie"));
1690 ASSERT_TRUE(headers1
.GetHeader("Cookie", &header_value
));
1691 EXPECT_EQ("name=new value; name2=new value; name4=\"value 4\"", header_value
);
1692 EXPECT_EQ(0u, warning_set
.size());
1693 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1698 std::string
GetCookieExpirationDate(int delta_secs
) {
1699 const char* const kWeekDays
[] = {
1700 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1702 const char* const kMonthNames
[] = {
1703 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1704 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1707 Time::Exploded exploded_time
;
1708 (Time::Now() + TimeDelta::FromSeconds(delta_secs
)).UTCExplode(&exploded_time
);
1710 return base::StringPrintf("%s, %d %s %d %.2d:%.2d:%.2d GMT",
1711 kWeekDays
[exploded_time
.day_of_week
],
1712 exploded_time
.day_of_month
,
1713 kMonthNames
[exploded_time
.month
- 1],
1716 exploded_time
.minute
,
1717 exploded_time
.second
);
1722 TEST(ExtensionWebRequestHelpersTest
,
1723 TestMergeCookiesInOnHeadersReceivedResponses
) {
1724 net::BoundTestNetLog capturing_net_log
;
1725 net::BoundNetLog net_log
= capturing_net_log
.bound();
1726 WarningSet warning_set
;
1727 std::string header_value
;
1728 EventResponseDeltas deltas
;
1730 std::string cookie_expiration
= GetCookieExpirationDate(1200);
1731 std::string base_headers_string
=
1732 "HTTP/1.0 200 OK\r\n"
1734 "Set-Cookie: name=value; DOMAIN=google.com; Secure\r\n"
1735 "Set-Cookie: name2=value2\r\n"
1736 "Set-Cookie: name3=value3\r\n"
1737 "Set-Cookie: lBound1=value5; Expires=" + cookie_expiration
+ "\r\n"
1738 "Set-Cookie: lBound2=value6; Max-Age=1200\r\n"
1739 "Set-Cookie: lBound3=value7; Max-Age=2000\r\n"
1740 "Set-Cookie: uBound1=value8; Expires=" + cookie_expiration
+ "\r\n"
1741 "Set-Cookie: uBound2=value9; Max-Age=1200\r\n"
1742 "Set-Cookie: uBound3=value10; Max-Age=2000\r\n"
1743 "Set-Cookie: uBound4=value11; Max-Age=2500\r\n"
1744 "Set-Cookie: uBound5=value12; Max-Age=600; Expires=" +
1745 cookie_expiration
+ "\r\n"
1746 "Set-Cookie: uBound6=removed; Max-Age=600\r\n"
1747 "Set-Cookie: sessionCookie=removed; Max-Age=INVALID\r\n"
1748 "Set-Cookie: sessionCookie2=removed\r\n"
1750 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
1751 new net::HttpResponseHeaders(
1752 net::HttpUtil::AssembleRawHeaders(
1753 base_headers_string
.c_str(), base_headers_string
.size())));
1755 // Check that we can handle if not touching the response headers.
1756 linked_ptr
<EventResponseDelta
> d0(
1757 new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
1758 deltas
.push_back(d0
);
1759 scoped_refptr
<net::HttpResponseHeaders
> new_headers0
;
1760 MergeCookiesInOnHeadersReceivedResponses(
1761 deltas
, base_headers
.get(), &new_headers0
, &warning_set
, &net_log
);
1762 EXPECT_FALSE(new_headers0
.get());
1763 EXPECT_EQ(0u, warning_set
.size());
1764 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1766 linked_ptr
<ResponseCookieModification
> add_cookie
=
1767 make_linked_ptr(new ResponseCookieModification
);
1768 add_cookie
->type
= helpers::ADD
;
1769 add_cookie
->modification
.reset(new helpers::ResponseCookie
);
1770 add_cookie
->modification
->name
.reset(new std::string("name4"));
1771 add_cookie
->modification
->value
.reset(new std::string("\"value4\""));
1773 linked_ptr
<ResponseCookieModification
> edit_cookie
=
1774 make_linked_ptr(new ResponseCookieModification
);
1775 edit_cookie
->type
= helpers::EDIT
;
1776 edit_cookie
->filter
.reset(new helpers::FilterResponseCookie
);
1777 edit_cookie
->filter
->name
.reset(new std::string("name2"));
1778 edit_cookie
->modification
.reset(new helpers::ResponseCookie
);
1779 edit_cookie
->modification
->value
.reset(new std::string("new value"));
1781 linked_ptr
<ResponseCookieModification
> edit_cookie_2
=
1782 make_linked_ptr(new ResponseCookieModification
);
1783 edit_cookie_2
->type
= helpers::EDIT
;
1784 edit_cookie_2
->filter
.reset(new helpers::FilterResponseCookie
);
1785 edit_cookie_2
->filter
->secure
.reset(new bool(false));
1786 edit_cookie_2
->modification
.reset(new helpers::ResponseCookie
);
1787 edit_cookie_2
->modification
->secure
.reset(new bool(true));
1789 // Tests 'ageLowerBound' filter when cookie lifetime is set
1790 // in cookie's 'max-age' attribute and its value is greater than
1791 // the filter's value.
1792 linked_ptr
<ResponseCookieModification
> edit_cookie_3
=
1793 make_linked_ptr(new ResponseCookieModification
);
1794 edit_cookie_3
->type
= helpers::EDIT
;
1795 edit_cookie_3
->filter
.reset(new helpers::FilterResponseCookie
);
1796 edit_cookie_3
->filter
->name
.reset(new std::string("lBound1"));
1797 edit_cookie_3
->filter
->age_lower_bound
.reset(new int(600));
1798 edit_cookie_3
->modification
.reset(new helpers::ResponseCookie
);
1799 edit_cookie_3
->modification
->value
.reset(new std::string("greater_1"));
1801 // Cookie lifetime is set in the cookie's 'expires' attribute.
1802 linked_ptr
<ResponseCookieModification
> edit_cookie_4
=
1803 make_linked_ptr(new ResponseCookieModification
);
1804 edit_cookie_4
->type
= helpers::EDIT
;
1805 edit_cookie_4
->filter
.reset(new helpers::FilterResponseCookie
);
1806 edit_cookie_4
->filter
->name
.reset(new std::string("lBound2"));
1807 edit_cookie_4
->filter
->age_lower_bound
.reset(new int(600));
1808 edit_cookie_4
->modification
.reset(new helpers::ResponseCookie
);
1809 edit_cookie_4
->modification
->value
.reset(new std::string("greater_2"));
1811 // Tests equality of the cookie lifetime with the filter value when
1812 // lifetime is set in the cookie's 'max-age' attribute.
1813 // Note: we don't test the equality when the lifetime is set in the 'expires'
1814 // attribute because the tests will be flaky. The reason is calculations will
1815 // depend on fetching the current time.
1816 linked_ptr
<ResponseCookieModification
> edit_cookie_5
=
1817 make_linked_ptr(new ResponseCookieModification
);
1818 edit_cookie_5
->type
= helpers::EDIT
;
1819 edit_cookie_5
->filter
.reset(new helpers::FilterResponseCookie
);
1820 edit_cookie_5
->filter
->name
.reset(new std::string("lBound3"));
1821 edit_cookie_5
->filter
->age_lower_bound
.reset(new int(2000));
1822 edit_cookie_5
->modification
.reset(new helpers::ResponseCookie
);
1823 edit_cookie_5
->modification
->value
.reset(new std::string("equal_2"));
1825 // Tests 'ageUpperBound' filter when cookie lifetime is set
1826 // in cookie's 'max-age' attribute and its value is lower than
1827 // the filter's value.
1828 linked_ptr
<ResponseCookieModification
> edit_cookie_6
=
1829 make_linked_ptr(new ResponseCookieModification
);
1830 edit_cookie_6
->type
= helpers::EDIT
;
1831 edit_cookie_6
->filter
.reset(new helpers::FilterResponseCookie
);
1832 edit_cookie_6
->filter
->name
.reset(new std::string("uBound1"));
1833 edit_cookie_6
->filter
->age_upper_bound
.reset(new int(2000));
1834 edit_cookie_6
->modification
.reset(new helpers::ResponseCookie
);
1835 edit_cookie_6
->modification
->value
.reset(new std::string("smaller_1"));
1837 // Cookie lifetime is set in the cookie's 'expires' attribute.
1838 linked_ptr
<ResponseCookieModification
> edit_cookie_7
=
1839 make_linked_ptr(new ResponseCookieModification
);
1840 edit_cookie_7
->type
= helpers::EDIT
;
1841 edit_cookie_7
->filter
.reset(new helpers::FilterResponseCookie
);
1842 edit_cookie_7
->filter
->name
.reset(new std::string("uBound2"));
1843 edit_cookie_7
->filter
->age_upper_bound
.reset(new int(2000));
1844 edit_cookie_7
->modification
.reset(new helpers::ResponseCookie
);
1845 edit_cookie_7
->modification
->value
.reset(new std::string("smaller_2"));
1847 // Tests equality of the cookie lifetime with the filter value when
1848 // lifetime is set in the cookie's 'max-age' attribute.
1849 linked_ptr
<ResponseCookieModification
> edit_cookie_8
=
1850 make_linked_ptr(new ResponseCookieModification
);
1851 edit_cookie_8
->type
= helpers::EDIT
;
1852 edit_cookie_8
->filter
.reset(new helpers::FilterResponseCookie
);
1853 edit_cookie_8
->filter
->name
.reset(new std::string("uBound3"));
1854 edit_cookie_8
->filter
->age_upper_bound
.reset(new int(2000));
1855 edit_cookie_8
->modification
.reset(new helpers::ResponseCookie
);
1856 edit_cookie_8
->modification
->value
.reset(new std::string("equal_4"));
1858 // Tests 'ageUpperBound' filter when cookie lifetime is greater
1859 // than the filter value. No modification is expected to be applied.
1860 linked_ptr
<ResponseCookieModification
> edit_cookie_9
=
1861 make_linked_ptr(new ResponseCookieModification
);
1862 edit_cookie_9
->type
= helpers::EDIT
;
1863 edit_cookie_9
->filter
.reset(new helpers::FilterResponseCookie
);
1864 edit_cookie_9
->filter
->name
.reset(new std::string("uBound4"));
1865 edit_cookie_9
->filter
->age_upper_bound
.reset(new int(2501));
1866 edit_cookie_9
->modification
.reset(new helpers::ResponseCookie
);
1867 edit_cookie_9
->modification
->value
.reset(new std::string("Will not change"));
1869 // Tests 'ageUpperBound' filter when both 'max-age' and 'expires' cookie
1870 // attributes are provided. 'expires' value matches the filter, however
1871 // no modification to the cookie is expected because 'max-age' overrides
1872 // 'expires' and it does not match the filter.
1873 linked_ptr
<ResponseCookieModification
> edit_cookie_10
=
1874 make_linked_ptr(new ResponseCookieModification
);
1875 edit_cookie_10
->type
= helpers::EDIT
;
1876 edit_cookie_10
->filter
.reset(new helpers::FilterResponseCookie
);
1877 edit_cookie_10
->filter
->name
.reset(new std::string("uBound5"));
1878 edit_cookie_10
->filter
->age_upper_bound
.reset(new int(800));
1879 edit_cookie_10
->modification
.reset(new helpers::ResponseCookie
);
1880 edit_cookie_10
->modification
->value
.reset(new std::string("Will not change"));
1882 linked_ptr
<ResponseCookieModification
> remove_cookie
=
1883 make_linked_ptr(new ResponseCookieModification
);
1884 remove_cookie
->type
= helpers::REMOVE
;
1885 remove_cookie
->filter
.reset(new helpers::FilterResponseCookie
);
1886 remove_cookie
->filter
->name
.reset(new std::string("name3"));
1888 linked_ptr
<ResponseCookieModification
> remove_cookie_2
=
1889 make_linked_ptr(new ResponseCookieModification
);
1890 remove_cookie_2
->type
= helpers::REMOVE
;
1891 remove_cookie_2
->filter
.reset(new helpers::FilterResponseCookie
);
1892 remove_cookie_2
->filter
->name
.reset(new std::string("uBound6"));
1893 remove_cookie_2
->filter
->age_upper_bound
.reset(new int(700));
1895 linked_ptr
<ResponseCookieModification
> remove_cookie_3
=
1896 make_linked_ptr(new ResponseCookieModification
);
1897 remove_cookie_3
->type
= helpers::REMOVE
;
1898 remove_cookie_3
->filter
.reset(new helpers::FilterResponseCookie
);
1899 remove_cookie_3
->filter
->name
.reset(new std::string("sessionCookie"));
1900 remove_cookie_3
->filter
->session_cookie
.reset(new bool(true));
1902 linked_ptr
<ResponseCookieModification
> remove_cookie_4
=
1903 make_linked_ptr(new ResponseCookieModification
);
1904 remove_cookie_4
->type
= helpers::REMOVE
;
1905 remove_cookie_4
->filter
.reset(new helpers::FilterResponseCookie
);
1906 remove_cookie_4
->filter
->name
.reset(new std::string("sessionCookie2"));
1907 remove_cookie_4
->filter
->session_cookie
.reset(new bool(true));
1909 linked_ptr
<ResponseCookieModification
> operations
[] = {
1910 add_cookie
, edit_cookie
, edit_cookie_2
, edit_cookie_3
, edit_cookie_4
,
1911 edit_cookie_5
, edit_cookie_6
, edit_cookie_7
, edit_cookie_8
,
1912 edit_cookie_9
, edit_cookie_10
, remove_cookie
, remove_cookie_2
,
1913 remove_cookie_3
, remove_cookie_4
1916 for (size_t i
= 0; i
< arraysize(operations
); ++i
) {
1917 linked_ptr
<EventResponseDelta
> delta(
1918 new EventResponseDelta("extid0", base::Time::FromInternalValue(i
* 5)));
1919 delta
->response_cookie_modifications
.push_back(operations
[i
]);
1920 deltas
.push_back(delta
);
1922 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1923 scoped_refptr
<net::HttpResponseHeaders
> headers1(
1924 new net::HttpResponseHeaders(
1925 net::HttpUtil::AssembleRawHeaders(
1926 base_headers_string
.c_str(), base_headers_string
.size())));
1927 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
1928 warning_set
.clear();
1929 MergeCookiesInOnHeadersReceivedResponses(
1930 deltas
, headers1
.get(), &new_headers1
, &warning_set
, &net_log
);
1932 EXPECT_TRUE(new_headers1
->HasHeader("Foo"));
1934 std::string cookie_string
;
1935 std::set
<std::string
> expected_cookies
;
1936 expected_cookies
.insert("name=value; domain=google.com; secure");
1937 expected_cookies
.insert("name2=value2; secure");
1938 expected_cookies
.insert("name4=\"value4\"; secure");
1939 expected_cookies
.insert(
1940 "lBound1=greater_1; expires=" + cookie_expiration
+ "; secure");
1941 expected_cookies
.insert("lBound2=greater_2; max-age=1200; secure");
1942 expected_cookies
.insert("lBound3=equal_2; max-age=2000; secure");
1943 expected_cookies
.insert(
1944 "uBound1=smaller_1; expires=" + cookie_expiration
+ "; secure");
1945 expected_cookies
.insert("uBound2=smaller_2; max-age=1200; secure");
1946 expected_cookies
.insert("uBound3=equal_4; max-age=2000; secure");
1947 expected_cookies
.insert("uBound4=value11; max-age=2500; secure");
1948 expected_cookies
.insert(
1949 "uBound5=value12; max-age=600; expires=" + cookie_expiration
+ "; secure");
1950 std::set
<std::string
> actual_cookies
;
1951 while (new_headers1
->EnumerateHeader(&iter
, "Set-Cookie", &cookie_string
))
1952 actual_cookies
.insert(cookie_string
);
1953 EXPECT_EQ(expected_cookies
, actual_cookies
);
1954 EXPECT_EQ(0u, warning_set
.size());
1955 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1958 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnHeadersReceivedResponses
) {
1959 net::BoundTestNetLog capturing_net_log
;
1960 net::BoundNetLog net_log
= capturing_net_log
.bound();
1961 WarningSet warning_set
;
1962 std::string header_value
;
1963 EventResponseDeltas deltas
;
1965 char base_headers_string
[] =
1966 "HTTP/1.0 200 OK\r\n"
1968 "Key2: Value2, Foo\r\n"
1970 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
1971 new net::HttpResponseHeaders(
1972 net::HttpUtil::AssembleRawHeaders(
1973 base_headers_string
, sizeof(base_headers_string
))));
1975 // Check that we can handle if not touching the response headers.
1976 linked_ptr
<EventResponseDelta
> d0(
1977 new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
1978 deltas
.push_back(d0
);
1979 scoped_refptr
<net::HttpResponseHeaders
> new_headers0
;
1980 GURL allowed_unsafe_redirect_url0
;
1981 MergeOnHeadersReceivedResponses(deltas
,
1984 &allowed_unsafe_redirect_url0
,
1987 EXPECT_FALSE(new_headers0
.get());
1988 EXPECT_TRUE(allowed_unsafe_redirect_url0
.is_empty());
1989 EXPECT_EQ(0u, warning_set
.size());
1990 EXPECT_EQ(0u, capturing_net_log
.GetSize());
1992 linked_ptr
<EventResponseDelta
> d1(
1993 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
1994 d1
->deleted_response_headers
.push_back(ResponseHeader("KEY1", "Value1"));
1995 d1
->deleted_response_headers
.push_back(ResponseHeader("KEY2", "Value2, Foo"));
1996 d1
->added_response_headers
.push_back(ResponseHeader("Key2", "Value3"));
1997 deltas
.push_back(d1
);
1998 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
1999 warning_set
.clear();
2000 capturing_net_log
.Clear();
2001 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
2002 GURL allowed_unsafe_redirect_url1
;
2003 MergeOnHeadersReceivedResponses(deltas
,
2006 &allowed_unsafe_redirect_url1
,
2009 ASSERT_TRUE(new_headers1
.get());
2010 EXPECT_TRUE(allowed_unsafe_redirect_url1
.is_empty());
2011 std::multimap
<std::string
, std::string
> expected1
;
2012 expected1
.insert(std::pair
<std::string
, std::string
>("Key2", "Value3"));
2016 std::multimap
<std::string
, std::string
> actual1
;
2017 while (new_headers1
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
2018 actual1
.insert(std::pair
<std::string
, std::string
>(name
, value
));
2020 EXPECT_EQ(expected1
, actual1
);
2021 EXPECT_EQ(0u, warning_set
.size());
2022 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2024 // Check that we replace response headers only once.
2025 linked_ptr
<EventResponseDelta
> d2(
2026 new EventResponseDelta("extid2", base::Time::FromInternalValue(1500)));
2027 // Note that we use a different capitalization of KeY2. This should not
2029 d2
->deleted_response_headers
.push_back(ResponseHeader("KeY2", "Value2, Foo"));
2030 d2
->added_response_headers
.push_back(ResponseHeader("Key2", "Value4"));
2031 deltas
.push_back(d2
);
2032 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2033 warning_set
.clear();
2034 capturing_net_log
.Clear();
2035 scoped_refptr
<net::HttpResponseHeaders
> new_headers2
;
2036 GURL allowed_unsafe_redirect_url2
;
2037 MergeOnHeadersReceivedResponses(deltas
,
2040 &allowed_unsafe_redirect_url2
,
2043 ASSERT_TRUE(new_headers2
.get());
2044 EXPECT_TRUE(allowed_unsafe_redirect_url2
.is_empty());
2046 std::multimap
<std::string
, std::string
> actual2
;
2047 while (new_headers2
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
2048 actual2
.insert(std::pair
<std::string
, std::string
>(name
, value
));
2050 EXPECT_EQ(expected1
, actual2
);
2051 EXPECT_EQ(1u, warning_set
.size());
2052 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
2053 EXPECT_EQ(2u, capturing_net_log
.GetSize());
2056 // Check that we do not delete too much
2057 TEST(ExtensionWebRequestHelpersTest
,
2058 TestMergeOnHeadersReceivedResponsesDeletion
) {
2059 net::BoundTestNetLog capturing_net_log
;
2060 net::BoundNetLog net_log
= capturing_net_log
.bound();
2061 WarningSet warning_set
;
2062 std::string header_value
;
2063 EventResponseDeltas deltas
;
2065 char base_headers_string
[] =
2066 "HTTP/1.0 200 OK\r\n"
2072 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
2073 new net::HttpResponseHeaders(
2074 net::HttpUtil::AssembleRawHeaders(
2075 base_headers_string
, sizeof(base_headers_string
))));
2077 linked_ptr
<EventResponseDelta
> d1(
2078 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
2079 d1
->deleted_response_headers
.push_back(ResponseHeader("KEY1", "Value2"));
2080 deltas
.push_back(d1
);
2081 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
2082 GURL allowed_unsafe_redirect_url1
;
2083 MergeOnHeadersReceivedResponses(deltas
,
2086 &allowed_unsafe_redirect_url1
,
2089 ASSERT_TRUE(new_headers1
.get());
2090 EXPECT_TRUE(allowed_unsafe_redirect_url1
.is_empty());
2091 std::multimap
<std::string
, std::string
> expected1
;
2092 expected1
.insert(std::pair
<std::string
, std::string
>("Key1", "Value1"));
2093 expected1
.insert(std::pair
<std::string
, std::string
>("Key1", "Value3"));
2094 expected1
.insert(std::pair
<std::string
, std::string
>("Key2", "Value4"));
2098 std::multimap
<std::string
, std::string
> actual1
;
2099 while (new_headers1
->EnumerateHeaderLines(&iter
, &name
, &value
)) {
2100 actual1
.insert(std::pair
<std::string
, std::string
>(name
, value
));
2102 EXPECT_EQ(expected1
, actual1
);
2103 EXPECT_EQ(0u, warning_set
.size());
2104 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2107 // Tests whether onHeadersReceived can initiate a redirect.
2108 // The URL merge logic is shared with onBeforeRequest, so we only need to test
2109 // whether the URLs are merged at all.
2110 TEST(ExtensionWebRequestHelpersTest
,
2111 TestMergeOnHeadersReceivedResponsesRedirect
) {
2112 EventResponseDeltas deltas
;
2113 net::BoundTestNetLog capturing_net_log
;
2114 net::BoundNetLog net_log
= capturing_net_log
.bound();
2115 WarningSet warning_set
;
2117 char base_headers_string
[] =
2118 "HTTP/1.0 200 OK\r\n"
2120 scoped_refptr
<net::HttpResponseHeaders
> base_headers(
2121 new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
2122 base_headers_string
, sizeof(base_headers_string
))));
2125 linked_ptr
<EventResponseDelta
> d0(
2126 new EventResponseDelta("extid0", base::Time::FromInternalValue(0)));
2127 deltas
.push_back(d0
);
2128 scoped_refptr
<net::HttpResponseHeaders
> new_headers0
;
2129 GURL allowed_unsafe_redirect_url0
;
2130 MergeOnHeadersReceivedResponses(deltas
,
2133 &allowed_unsafe_redirect_url0
,
2136 EXPECT_FALSE(new_headers0
.get());
2137 EXPECT_TRUE(allowed_unsafe_redirect_url0
.is_empty());
2138 EXPECT_EQ(0u, warning_set
.size());
2139 EXPECT_EQ(0u, capturing_net_log
.GetSize());
2142 GURL
new_url_1("http://foo.com");
2143 linked_ptr
<EventResponseDelta
> d1(
2144 new EventResponseDelta("extid1", base::Time::FromInternalValue(1000)));
2145 d1
->new_url
= GURL(new_url_1
);
2146 deltas
.push_back(d1
);
2147 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2148 capturing_net_log
.Clear();
2149 scoped_refptr
<net::HttpResponseHeaders
> new_headers1
;
2150 GURL allowed_unsafe_redirect_url1
;
2151 MergeOnHeadersReceivedResponses(deltas
,
2154 &allowed_unsafe_redirect_url1
,
2158 EXPECT_TRUE(new_headers1
.get());
2159 EXPECT_TRUE(new_headers1
->HasHeaderValue("Location", new_url_1
.spec()));
2160 EXPECT_EQ(new_url_1
, allowed_unsafe_redirect_url1
);
2161 EXPECT_TRUE(warning_set
.empty());
2162 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2165 TEST(ExtensionWebRequestHelpersTest
, TestMergeOnAuthRequiredResponses
) {
2166 net::BoundTestNetLog capturing_net_log
;
2167 net::BoundNetLog net_log
= capturing_net_log
.bound();
2168 WarningSet warning_set
;
2169 EventResponseDeltas deltas
;
2170 base::string16 username
= base::ASCIIToUTF16("foo");
2171 base::string16 password
= base::ASCIIToUTF16("bar");
2172 base::string16 password2
= base::ASCIIToUTF16("baz");
2174 // Check that we can handle if not returning credentials.
2175 linked_ptr
<EventResponseDelta
> d0(
2176 new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
2177 deltas
.push_back(d0
);
2178 net::AuthCredentials auth0
;
2179 bool credentials_set
= MergeOnAuthRequiredResponses(
2180 deltas
, &auth0
, &warning_set
, &net_log
);
2181 EXPECT_FALSE(credentials_set
);
2182 EXPECT_TRUE(auth0
.Empty());
2183 EXPECT_EQ(0u, warning_set
.size());
2184 EXPECT_EQ(0u, capturing_net_log
.GetSize());
2186 // Check that we can set AuthCredentials.
2187 linked_ptr
<EventResponseDelta
> d1(
2188 new EventResponseDelta("extid1", base::Time::FromInternalValue(2000)));
2189 d1
->auth_credentials
.reset(new net::AuthCredentials(username
, password
));
2190 deltas
.push_back(d1
);
2191 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2192 warning_set
.clear();
2193 capturing_net_log
.Clear();
2194 net::AuthCredentials auth1
;
2195 credentials_set
= MergeOnAuthRequiredResponses(
2196 deltas
, &auth1
, &warning_set
, &net_log
);
2197 EXPECT_TRUE(credentials_set
);
2198 EXPECT_FALSE(auth1
.Empty());
2199 EXPECT_EQ(username
, auth1
.username());
2200 EXPECT_EQ(password
, auth1
.password());
2201 EXPECT_EQ(0u, warning_set
.size());
2202 EXPECT_EQ(1u, capturing_net_log
.GetSize());
2204 // Check that we set AuthCredentials only once.
2205 linked_ptr
<EventResponseDelta
> d2(
2206 new EventResponseDelta("extid2", base::Time::FromInternalValue(1500)));
2207 d2
->auth_credentials
.reset(new net::AuthCredentials(username
, password2
));
2208 deltas
.push_back(d2
);
2209 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2210 warning_set
.clear();
2211 capturing_net_log
.Clear();
2212 net::AuthCredentials auth2
;
2213 credentials_set
= MergeOnAuthRequiredResponses(
2214 deltas
, &auth2
, &warning_set
, &net_log
);
2215 EXPECT_TRUE(credentials_set
);
2216 EXPECT_FALSE(auth2
.Empty());
2217 EXPECT_EQ(username
, auth1
.username());
2218 EXPECT_EQ(password
, auth1
.password());
2219 EXPECT_EQ(1u, warning_set
.size());
2220 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
2221 EXPECT_EQ(2u, capturing_net_log
.GetSize());
2223 // Check that we can set identical AuthCredentials twice without causing
2225 linked_ptr
<EventResponseDelta
> d3(
2226 new EventResponseDelta("extid3", base::Time::FromInternalValue(1000)));
2227 d3
->auth_credentials
.reset(new net::AuthCredentials(username
, password
));
2228 deltas
.push_back(d3
);
2229 deltas
.sort(&InDecreasingExtensionInstallationTimeOrder
);
2230 warning_set
.clear();
2231 capturing_net_log
.Clear();
2232 net::AuthCredentials auth3
;
2233 credentials_set
= MergeOnAuthRequiredResponses(
2234 deltas
, &auth3
, &warning_set
, &net_log
);
2235 EXPECT_TRUE(credentials_set
);
2236 EXPECT_FALSE(auth3
.Empty());
2237 EXPECT_EQ(username
, auth1
.username());
2238 EXPECT_EQ(password
, auth1
.password());
2239 EXPECT_EQ(1u, warning_set
.size());
2240 EXPECT_TRUE(HasWarning(warning_set
, "extid2"));
2241 EXPECT_EQ(3u, capturing_net_log
.GetSize());
2244 } // namespace extensions