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