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