Home | History | Annotate | Download | only in web_request
      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, &param);
    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, &param);
    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