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