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