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