15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/web_request/web_request_api_helpers.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/macros.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/web_cache/browser/web_cache_manager.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/render_process_host.h"
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/web_request/web_request_api_constants.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/extension_registry.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/extensions_browser_client.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/runtime_data.h"
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/warning_set.h"
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/extension_messages.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/cookies/cookie_util.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/cookies/parsed_cookie.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "url/url_constants.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(battre): move all static functions into an anonymous namespace at the
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// top of this file.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing content::ResourceType;
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using net::cookie_util::ParsedRequestCookie;
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using net::cookie_util::ParsedRequestCookies;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace keys = extension_web_request_api_constants;
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extension_web_request_api_helpers {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* kResourceTypeStrings[] = {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "main_frame",
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "sub_frame",
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "stylesheet",
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "script",
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "image",
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "object",
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "xmlhttprequest",
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "other",
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "other",
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst size_t kResourceTypeStringsLength = arraysize(kResourceTypeStrings);
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static ResourceType kResourceTypeValues[] = {
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::RESOURCE_TYPE_MAIN_FRAME,
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::RESOURCE_TYPE_SUB_FRAME,
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::RESOURCE_TYPE_STYLESHEET,
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::RESOURCE_TYPE_SCRIPT,
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::RESOURCE_TYPE_IMAGE,
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::RESOURCE_TYPE_OBJECT,
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::RESOURCE_TYPE_XHR,
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::RESOURCE_TYPE_LAST_TYPE,  // represents "other"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jochen): We duplicate the last entry, so the array's size is not a
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // power of two. If it is, this triggers a bug in gcc 4.4 in Release builds
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949). Once we use a version
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of gcc with this bug fixed, or the array is changed so this duplicate
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // entry is no longer required, this should be removed.
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::RESOURCE_TYPE_LAST_TYPE,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst size_t kResourceTypeValuesLength = arraysize(kResourceTypeValues);
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef std::vector<linked_ptr<net::ParsedCookie> > ParsedResponseCookies;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearCacheOnNavigationOnUI() {
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  web_cache::WebCacheManager::GetInstance()->ClearCacheOnNavigation();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseCookieLifetime(net::ParsedCookie* cookie,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int64* seconds_till_expiry) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 'Max-Age' is processed first because according to:
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://tools.ietf.org/html/rfc6265#section-5.3 'Max-Age' attribute
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // overrides 'Expires' attribute.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cookie->HasMaxAge() &&
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringToInt64(cookie->MaxAge(), seconds_till_expiry)) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time parsed_expiry_time;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cookie->HasExpires())
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parsed_expiry_time = net::cookie_util::ParseCookieTime(cookie->Expires());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!parsed_expiry_time.is_null()) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *seconds_till_expiry =
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ceil((parsed_expiry_time - Time::Now()).InSecondsF());
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *seconds_till_expiry >= 0;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool NullableEquals(const int* a, const int* b) {
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((a && !b) || (!a && b))
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (!a) || (*a == *b);
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool NullableEquals(const bool* a, const bool* b) {
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((a && !b) || (!a && b))
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (!a) || (*a == *b);
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool NullableEquals(const std::string* a, const std::string* b) {
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((a && !b) || (!a && b))
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (!a) || (*a == *b);
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RequestCookie::RequestCookie() {}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RequestCookie::~RequestCookie() {}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool NullableEquals(const RequestCookie* a, const RequestCookie* b) {
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((a && !b) || (!a && b))
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!a)
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return NullableEquals(a->name.get(), b->name.get()) &&
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->value.get(), b->value.get());
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResponseCookie::ResponseCookie() {}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResponseCookie::~ResponseCookie() {}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool NullableEquals(const ResponseCookie* a, const ResponseCookie* b) {
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((a && !b) || (!a && b))
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!a)
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return NullableEquals(a->name.get(), b->name.get()) &&
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->value.get(), b->value.get()) &&
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->expires.get(), b->expires.get()) &&
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->max_age.get(), b->max_age.get()) &&
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->domain.get(), b->domain.get()) &&
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->path.get(), b->path.get()) &&
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->secure.get(), b->secure.get()) &&
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->http_only.get(), b->http_only.get());
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilterResponseCookie::FilterResponseCookie() {}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilterResponseCookie::~FilterResponseCookie() {}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool NullableEquals(const FilterResponseCookie* a,
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    const FilterResponseCookie* b) {
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((a && !b) || (!a && b))
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!a)
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return NullableEquals(a->age_lower_bound.get(), b->age_lower_bound.get()) &&
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->age_upper_bound.get(), b->age_upper_bound.get()) &&
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->session_cookie.get(), b->session_cookie.get());
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RequestCookieModification::RequestCookieModification() {}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RequestCookieModification::~RequestCookieModification() {}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool NullableEquals(const RequestCookieModification* a,
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    const RequestCookieModification* b) {
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((a && !b) || (!a && b))
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!a)
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return NullableEquals(a->filter.get(), b->filter.get()) &&
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->modification.get(), b->modification.get());
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResponseCookieModification::ResponseCookieModification() : type(ADD) {}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResponseCookieModification::~ResponseCookieModification() {}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool NullableEquals(const ResponseCookieModification* a,
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                    const ResponseCookieModification* b) {
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((a && !b) || (!a && b))
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!a)
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return a->type == b->type &&
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->filter.get(), b->filter.get()) &&
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         NullableEquals(a->modification.get(), b->modification.get());
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EventResponseDelta::EventResponseDelta(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id, const base::Time& extension_install_time)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : extension_id(extension_id),
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_install_time(extension_install_time),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cancel(false) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EventResponseDelta::~EventResponseDelta() {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a NetLog callback the returns a Value with the ID of the extension
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that caused an event.  |delta| must remain valid for the lifetime of the
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callback.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::NetLog::ParametersCallback CreateNetLogExtensionIdCallback(
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDelta* delta) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net::NetLog::StringCallback("extension_id", &delta->extension_id);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates NetLog parameters to indicate that an extension modified a request.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Caller takes ownership of returned value.
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::Value* NetLogModificationCallback(
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDelta* delta,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetLog::LogLevel log_level) {
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::DictionaryValue* dict = new base::DictionaryValue();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetString("extension_id", delta->extension_id);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ListValue* modified_headers = new base::ListValue();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpRequestHeaders::Iterator modification(
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta->modified_request_headers);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (modification.GetNext()) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string line = modification.name() + ": " + modification.value();
2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    modified_headers->Append(new base::StringValue(line));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set("modified_headers", modified_headers);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ListValue* deleted_headers = new base::ListValue();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<std::string>::const_iterator key =
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           delta->deleted_request_headers.begin();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       key != delta->deleted_request_headers.end();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++key) {
2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    deleted_headers->Append(new base::StringValue(*key));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set("deleted_headers", deleted_headers);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InDecreasingExtensionInstallationTimeOrder(
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const linked_ptr<EventResponseDelta>& a,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const linked_ptr<EventResponseDelta>& b) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return a->extension_install_time > b->extension_install_time;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::ListValue* StringToCharList(const std::string& s) {
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::ListValue* result = new base::ListValue;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0, n = s.size(); i < n; ++i) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->Append(
2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        new base::FundamentalValue(
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *reinterpret_cast<const unsigned char*>(&s[i])));
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool CharListToString(const base::ListValue* list, std::string* out) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!list)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t list_length = list->GetSize();
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->resize(list_length);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int value = 0;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < list_length; ++i) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!list->GetInteger(i, &value) || value < 0 || value > 255)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char tmp = static_cast<unsigned char>(value);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*out)[i] = *reinterpret_cast<char*>(&tmp);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EventResponseDelta* CalculateOnBeforeRequestDelta(
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Time& extension_install_time,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool cancel,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& new_url) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDelta* result =
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new EventResponseDelta(extension_id, extension_install_time);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->cancel = cancel;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->new_url = new_url;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EventResponseDelta* CalculateOnBeforeSendHeadersDelta(
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Time& extension_install_time,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool cancel,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::HttpRequestHeaders* old_headers,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::HttpRequestHeaders* new_headers) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDelta* result =
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new EventResponseDelta(extension_id, extension_install_time);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->cancel = cancel;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The event listener might not have passed any new headers if he
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // just wanted to cancel the request.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_headers) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Find deleted headers.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::HttpRequestHeaders::Iterator i(*old_headers);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (i.GetNext()) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!new_headers->HasHeader(i.name())) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->deleted_request_headers.push_back(i.name());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Find modified headers.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::HttpRequestHeaders::Iterator i(*new_headers);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (i.GetNext()) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string value;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!old_headers->GetHeader(i.name(), &value) || i.value() != value) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result->modified_request_headers.SetHeader(i.name(), i.value());
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EventResponseDelta* CalculateOnHeadersReceivedDelta(
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Time& extension_install_time,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool cancel,
331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const GURL& new_url,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpResponseHeaders* old_response_headers,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseHeaders* new_response_headers) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDelta* result =
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new EventResponseDelta(extension_id, extension_install_time);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->cancel = cancel;
337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  result->new_url = new_url;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!new_response_headers)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find deleted headers (header keys are treated case insensitively).
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* iter = NULL;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (old_response_headers->EnumerateHeaderLines(&iter, &name, &value)) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string name_lowercase(name);
3496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::StringToLowerASCII(&name_lowercase);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool header_found = false;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (ResponseHeaders::const_iterator i = new_response_headers->begin();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           i != new_response_headers->end(); ++i) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (LowerCaseEqualsASCII(i->first, name_lowercase.c_str()) &&
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            value == i->second) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          header_found = true;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!header_found)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result->deleted_response_headers.push_back(ResponseHeader(name, value));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find added headers (header keys are treated case insensitively).
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ResponseHeaders::const_iterator i = new_response_headers->begin();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         i != new_response_headers->end(); ++i) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void* iter = NULL;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string value;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool header_found = false;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (old_response_headers->EnumerateHeader(&iter, i->first, &value) &&
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             !header_found) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        header_found = (value == i->second);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!header_found)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result->added_response_headers.push_back(*i);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EventResponseDelta* CalculateOnAuthRequiredDelta(
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Time& extension_install_time,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool cancel,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<net::AuthCredentials>* auth_credentials) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDelta* result =
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new EventResponseDelta(extension_id, extension_install_time);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->cancel = cancel;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->auth_credentials.swap(*auth_credentials);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MergeCancelOfResponses(
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* canceled,
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog* net_log) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (EventResponseDeltas::const_iterator i = deltas.begin();
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != deltas.end(); ++i) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*i)->cancel) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *canceled = true;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log->AddEvent(
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_CHROME_EXTENSION_ABORTED_REQUEST,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogExtensionIdCallback(i->get()));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
412effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Helper function for MergeRedirectUrlOfResponses() that allows ignoring
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all redirects but those to data:// urls and about:blank. This is important
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to treat these URLs as "cancel urls", i.e. URLs that extensions redirect
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to if they want to express that they want to cancel a request. This reduces
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the number of conflicts that we need to flag, as canceling is considered
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a higher precedence operation that redirects.
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns whether a redirect occurred.
419effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic bool MergeRedirectUrlOfResponsesHelper(
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL* new_url,
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    extensions::WarningSet* conflicting_extensions,
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog* net_log,
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool consider_only_cancel_scheme_urls) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool redirected = false;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Extension that determines the |new_url|.
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string winning_extension_id;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_iterator delta;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*delta)->new_url.is_empty())
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (consider_only_cancel_scheme_urls &&
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        !(*delta)->new_url.SchemeIs(url::kDataScheme) &&
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*delta)->new_url.spec() != "about:blank") {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!redirected || *new_url == (*delta)->new_url) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *new_url = (*delta)->new_url;
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      winning_extension_id = (*delta)->extension_id;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      redirected = true;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log->AddEvent(
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_CHROME_EXTENSION_REDIRECTED_REQUEST,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogExtensionIdCallback(delta->get()));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      conflicting_extensions->insert(
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          extensions::Warning::CreateRedirectConflictWarning(
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (*delta)->extension_id,
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              winning_extension_id,
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (*delta)->new_url,
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              *new_url));
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log->AddEvent(
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogExtensionIdCallback(delta->get()));
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return redirected;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
461effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid MergeRedirectUrlOfResponses(
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL* new_url,
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    extensions::WarningSet* conflicting_extensions,
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog* net_log) {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First handle only redirects to data:// URLs and about:blank. These are a
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // special case as they represent a way of cancelling a request.
469effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (MergeRedirectUrlOfResponsesHelper(
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          deltas, new_url, conflicting_extensions, net_log, true)) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If any extension cancelled a request by redirecting to a data:// URL or
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // about:blank, we don't consider the other redirects.
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle all other redirects.
477effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  MergeRedirectUrlOfResponsesHelper(
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deltas, new_url, conflicting_extensions, net_log, false);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
481effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid MergeOnBeforeRequestResponses(
482effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const EventResponseDeltas& deltas,
483effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    GURL* new_url,
4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    extensions::WarningSet* conflicting_extensions,
485effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const net::BoundNetLog* net_log) {
486effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  MergeRedirectUrlOfResponses(deltas, new_url, conflicting_extensions, net_log);
487effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
488effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool DoesRequestCookieMatchFilter(
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ParsedRequestCookie& cookie,
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RequestCookie* filter) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!filter) return true;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (filter->name.get() && cookie.first != *filter->name) return false;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (filter->value.get() && cookie.second != *filter->value) return false;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Applies all CookieModificationType::ADD operations for request cookies of
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |deltas| to |cookies|. Returns whether any cookie was added.
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool MergeAddRequestCookieModifications(
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParsedRequestCookies* cookies) {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool modified = false;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume here that the deltas are sorted in decreasing extension
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // precedence (i.e. decreasing extension installation time).
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_reverse_iterator delta;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RequestCookieModifications& modifications =
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*delta)->request_cookie_modifications;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (RequestCookieModifications::const_iterator mod = modifications.begin();
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         mod != modifications.end(); ++mod) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*mod)->type != ADD || !(*mod)->modification.get())
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string* new_name = (*mod)->modification->name.get();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string* new_value = (*mod)->modification->value.get();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!new_name || !new_value)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool cookie_with_same_name_found = false;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (ParsedRequestCookies::iterator cookie = cookies->begin();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           cookie != cookies->end() && !cookie_with_same_name_found; ++cookie) {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (cookie->first == *new_name) {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (cookie->second != *new_value) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            cookie->second = *new_value;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            modified = true;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie_with_same_name_found = true;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!cookie_with_same_name_found) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cookies->push_back(std::make_pair(base::StringPiece(*new_name),
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          base::StringPiece(*new_value)));
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        modified = true;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return modified;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Applies all CookieModificationType::EDIT operations for request cookies of
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |deltas| to |cookies|. Returns whether any cookie was modified.
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool MergeEditRequestCookieModifications(
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParsedRequestCookies* cookies) {
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool modified = false;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume here that the deltas are sorted in decreasing extension
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // precedence (i.e. decreasing extension installation time).
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_reverse_iterator delta;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RequestCookieModifications& modifications =
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*delta)->request_cookie_modifications;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (RequestCookieModifications::const_iterator mod = modifications.begin();
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         mod != modifications.end(); ++mod) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*mod)->type != EDIT || !(*mod)->modification.get())
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string* new_value = (*mod)->modification->value.get();
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RequestCookie* filter = (*mod)->filter.get();
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (ParsedRequestCookies::iterator cookie = cookies->begin();
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           cookie != cookies->end(); ++cookie) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!DoesRequestCookieMatchFilter(*cookie, filter))
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If the edit operation tries to modify the cookie name, we just ignore
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // this. We only modify the cookie value.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (new_value && cookie->second != *new_value) {
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cookie->second = *new_value;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          modified = true;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return modified;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Applies all CookieModificationType::REMOVE operations for request cookies of
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |deltas| to |cookies|. Returns whether any cookie was deleted.
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool MergeRemoveRequestCookieModifications(
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParsedRequestCookies* cookies) {
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool modified = false;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume here that the deltas are sorted in decreasing extension
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // precedence (i.e. decreasing extension installation time).
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_reverse_iterator delta;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RequestCookieModifications& modifications =
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*delta)->request_cookie_modifications;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (RequestCookieModifications::const_iterator mod = modifications.begin();
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         mod != modifications.end(); ++mod) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*mod)->type != REMOVE)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RequestCookie* filter = (*mod)->filter.get();
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ParsedRequestCookies::iterator i = cookies->begin();
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (i != cookies->end()) {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (DoesRequestCookieMatchFilter(*i, filter)) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          i = cookies->erase(i);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          modified = true;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++i;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return modified;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MergeCookiesInOnBeforeSendHeadersResponses(
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::HttpRequestHeaders* request_headers,
6101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    extensions::WarningSet* conflicting_extensions,
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog* net_log) {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip all work if there are no registered cookie modifications.
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool cookie_modifications_exist = false;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_iterator delta;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cookie_modifications_exist |=
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !(*delta)->request_cookie_modifications.empty();
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cookie_modifications_exist)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse old cookie line.
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cookie_header;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_headers->GetHeader(net::HttpRequestHeaders::kCookie, &cookie_header);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParsedRequestCookies cookies;
6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  net::cookie_util::ParseRequestCookieLine(cookie_header, &cookies);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Modify cookies.
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool modified = false;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  modified |= MergeAddRequestCookieModifications(deltas, &cookies);
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  modified |= MergeEditRequestCookieModifications(deltas, &cookies);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  modified |= MergeRemoveRequestCookieModifications(deltas, &cookies);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reassemble and store new cookie line.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modified) {
6365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::string new_cookie_header =
6375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        net::cookie_util::SerializeRequestCookieLine(cookies);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_headers->SetHeader(net::HttpRequestHeaders::kCookie,
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               new_cookie_header);
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the extension ID of the first extension in |deltas| that sets the
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// request header identified by |key| to |value|.
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static std::string FindSetRequestHeader(
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const EventResponseDeltas& deltas,
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& key,
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& value) {
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventResponseDeltas::const_iterator delta;
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::HttpRequestHeaders::Iterator modification(
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (*delta)->modified_request_headers);
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (modification.GetNext()) {
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (key == modification.name() && value == modification.value())
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return (*delta)->extension_id;
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::string();
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the extension ID of the first extension in |deltas| that removes the
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// request header identified by |key|.
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static std::string FindRemoveRequestHeader(
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const EventResponseDeltas& deltas,
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& key) {
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventResponseDeltas::const_iterator delta;
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<std::string>::iterator i;
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (i = (*delta)->deleted_request_headers.begin();
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         i != (*delta)->deleted_request_headers.end();
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         ++i) {
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (*i == key)
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return (*delta)->extension_id;
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::string();
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MergeOnBeforeSendHeadersResponses(
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::HttpRequestHeaders* request_headers,
6821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    extensions::WarningSet* conflicting_extensions,
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog* net_log) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_iterator delta;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Here we collect which headers we have removed or set to new values
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so far due to extensions of higher precedence.
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> removed_headers;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<std::string> set_headers;
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume here that the deltas are sorted in decreasing extension
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // precedence (i.e. decreasing extension installation time).
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*delta)->modified_request_headers.IsEmpty() &&
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*delta)->deleted_request_headers.empty()) {
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check whether any modification affects a request header that
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // has been modified differently before. As deltas is sorted by decreasing
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // extension installation order, this takes care of precedence.
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool extension_conflicts = false;
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string winning_extension_id;
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string conflicting_header;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::HttpRequestHeaders::Iterator modification(
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*delta)->modified_request_headers);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (modification.GetNext() && !extension_conflicts) {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This modification sets |key| to |value|.
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const std::string& key = modification.name();
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const std::string& value = modification.value();
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We must not delete anything that has been modified before.
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (removed_headers.find(key) != removed_headers.end() &&
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            !extension_conflicts) {
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          winning_extension_id = FindRemoveRequestHeader(deltas, key);
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          conflicting_header = key;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_conflicts = true;
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We must not modify anything that has been set to a *different*
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // value before.
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (set_headers.find(key) != set_headers.end() &&
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            !extension_conflicts) {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          std::string current_value;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!request_headers->GetHeader(key, &current_value) ||
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              current_value != value) {
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            winning_extension_id =
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                FindSetRequestHeader(deltas, key, current_value);
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            conflicting_header = key;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            extension_conflicts = true;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check whether any deletion affects a request header that has been
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // modified before.
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<std::string>::iterator key;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (key = (*delta)->deleted_request_headers.begin();
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           key != (*delta)->deleted_request_headers.end() &&
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               !extension_conflicts;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ++key) {
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (set_headers.find(*key) != set_headers.end()) {
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          std::string current_value;
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          request_headers->GetHeader(*key, &current_value);
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          winning_extension_id =
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              FindSetRequestHeader(deltas, *key, current_value);
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          conflicting_header = *key;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_conflicts = true;
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now execute the modifications if there were no conflicts.
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!extension_conflicts) {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Copy all modifications into the original headers.
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_headers->MergeFrom((*delta)->modified_request_headers);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Record which keys were changed.
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::HttpRequestHeaders::Iterator modification(
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (*delta)->modified_request_headers);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (modification.GetNext())
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          set_headers.insert(modification.name());
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Perform all deletions and record which keys were deleted.
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::vector<std::string>::iterator key;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (key = (*delta)->deleted_request_headers.begin();
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             key != (*delta)->deleted_request_headers.end();
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             ++key) {
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          request_headers->RemoveHeader(*key);
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          removed_headers.insert(*key);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log->AddEvent(
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS,
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&NetLogModificationCallback, delta->get()));
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      conflicting_extensions->insert(
7831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          extensions::Warning::CreateRequestHeaderConflictWarning(
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (*delta)->extension_id, winning_extension_id,
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              conflicting_header));
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log->AddEvent(
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogExtensionIdCallback(delta->get()));
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MergeCookiesInOnBeforeSendHeadersResponses(deltas, request_headers,
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      conflicting_extensions, net_log);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Retrives all cookies from |override_response_headers|.
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static ParsedResponseCookies GetResponseCookies(
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::HttpResponseHeaders> override_response_headers) {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParsedResponseCookies result;
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = NULL;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (override_response_headers->EnumerateHeader(&iter, "Set-Cookie",
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    &value)) {
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.push_back(make_linked_ptr(new net::ParsedCookie(value)));
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stores all |cookies| in |override_response_headers| deleting previously
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// existing cookie definitions.
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void StoreResponseCookies(
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ParsedResponseCookies& cookies,
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::HttpResponseHeaders> override_response_headers) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  override_response_headers->RemoveHeader("Set-Cookie");
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ParsedResponseCookies::const_iterator i = cookies.begin();
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != cookies.end(); ++i) {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    override_response_headers->AddHeader("Set-Cookie: " + (*i)->ToCookieLine());
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Modifies |cookie| according to |modification|. Each value that is set in
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |modification| is applied to |cookie|.
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool ApplyResponseCookieModification(ResponseCookie* modification,
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            net::ParsedCookie* cookie) {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool modified = false;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modification->name.get())
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modified |= cookie->SetName(*modification->name);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modification->value.get())
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modified |= cookie->SetValue(*modification->value);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modification->expires.get())
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modified |= cookie->SetExpires(*modification->expires);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modification->max_age.get())
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modified |= cookie->SetMaxAge(base::IntToString(*modification->max_age));
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modification->domain.get())
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modified |= cookie->SetDomain(*modification->domain);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modification->path.get())
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modified |= cookie->SetPath(*modification->path);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modification->secure.get())
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modified |= cookie->SetIsSecure(*modification->secure);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modification->http_only.get())
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    modified |= cookie->SetIsHttpOnly(*modification->http_only);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return modified;
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool DoesResponseCookieMatchFilter(net::ParsedCookie* cookie,
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          FilterResponseCookie* filter) {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cookie->IsValid()) return false;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!filter) return true;
850116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (filter->name && cookie->Name() != *filter->name)
851116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
852116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (filter->value && cookie->Value() != *filter->value)
853116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
854116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (filter->expires) {
855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string actual_value =
856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        cookie->HasExpires() ? cookie->Expires() : std::string();
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (actual_value != *filter->expires)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
860116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (filter->max_age) {
861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string actual_value =
862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        cookie->HasMaxAge() ? cookie->MaxAge() : std::string();
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (actual_value != base::IntToString(*filter->max_age))
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
866116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (filter->domain) {
867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string actual_value =
868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        cookie->HasDomain() ? cookie->Domain() : std::string();
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (actual_value != *filter->domain)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
872116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (filter->path) {
873c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string actual_value =
874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        cookie->HasPath() ? cookie->Path() : std::string();
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (actual_value != *filter->path)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
878116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (filter->secure && cookie->IsSecure() != *filter->secure)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
880116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (filter->http_only && cookie->IsHttpOnly() != *filter->http_only)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
882116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (filter->age_upper_bound || filter->age_lower_bound ||
883116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (filter->session_cookie && *filter->session_cookie)) {
884116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int64 seconds_to_expiry;
885116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool lifetime_parsed = ParseCookieLifetime(cookie, &seconds_to_expiry);
886116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (filter->age_upper_bound && seconds_to_expiry > *filter->age_upper_bound)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
888116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (filter->age_lower_bound && seconds_to_expiry < *filter->age_lower_bound)
889116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return false;
890116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (filter->session_cookie && *filter->session_cookie && lifetime_parsed)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Applies all CookieModificationType::ADD operations for response cookies of
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |deltas| to |cookies|. Returns whether any cookie was added.
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool MergeAddResponseCookieModifications(
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParsedResponseCookies* cookies) {
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool modified = false;
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume here that the deltas are sorted in decreasing extension
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // precedence (i.e. decreasing extension installation time).
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_reverse_iterator delta;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ResponseCookieModifications& modifications =
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*delta)->response_cookie_modifications;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ResponseCookieModifications::const_iterator mod =
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             modifications.begin(); mod != modifications.end(); ++mod) {
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*mod)->type != ADD || !(*mod)->modification.get())
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Cookie names are not unique in response cookies so we always append
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // and never override.
914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      linked_ptr<net::ParsedCookie> cookie(
915c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          new net::ParsedCookie(std::string()));
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ApplyResponseCookieModification((*mod)->modification.get(), cookie.get());
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cookies->push_back(cookie);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      modified = true;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return modified;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Applies all CookieModificationType::EDIT operations for response cookies of
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |deltas| to |cookies|. Returns whether any cookie was modified.
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool MergeEditResponseCookieModifications(
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParsedResponseCookies* cookies) {
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool modified = false;
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume here that the deltas are sorted in decreasing extension
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // precedence (i.e. decreasing extension installation time).
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_reverse_iterator delta;
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) {
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ResponseCookieModifications& modifications =
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*delta)->response_cookie_modifications;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ResponseCookieModifications::const_iterator mod =
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             modifications.begin(); mod != modifications.end(); ++mod) {
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*mod)->type != EDIT || !(*mod)->modification.get())
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (ParsedResponseCookies::iterator cookie = cookies->begin();
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           cookie != cookies->end(); ++cookie) {
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (DoesResponseCookieMatchFilter(cookie->get(),
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          (*mod)->filter.get())) {
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          modified |= ApplyResponseCookieModification(
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (*mod)->modification.get(), cookie->get());
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return modified;
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Applies all CookieModificationType::REMOVE operations for response cookies of
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |deltas| to |cookies|. Returns whether any cookie was deleted.
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool MergeRemoveResponseCookieModifications(
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParsedResponseCookies* cookies) {
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool modified = false;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume here that the deltas are sorted in decreasing extension
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // precedence (i.e. decreasing extension installation time).
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_reverse_iterator delta;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) {
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ResponseCookieModifications& modifications =
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*delta)->response_cookie_modifications;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ResponseCookieModifications::const_iterator mod =
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             modifications.begin(); mod != modifications.end(); ++mod) {
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*mod)->type != REMOVE)
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ParsedResponseCookies::iterator i = cookies->begin();
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (i != cookies->end()) {
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (DoesResponseCookieMatchFilter(i->get(),
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          (*mod)->filter.get())) {
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          i = cookies->erase(i);
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          modified = true;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++i;
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return modified;
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MergeCookiesInOnHeadersReceivedResponses(
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpResponseHeaders* original_response_headers,
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
9901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    extensions::WarningSet* conflicting_extensions,
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog* net_log) {
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip all work if there are no registered cookie modifications.
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool cookie_modifications_exist = false;
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_reverse_iterator delta;
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.rbegin(); delta != deltas.rend(); ++delta) {
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cookie_modifications_exist |=
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !(*delta)->response_cookie_modifications.empty();
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cookie_modifications_exist)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only create a copy if we really want to modify the response headers.
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (override_response_headers->get() == NULL) {
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *override_response_headers = new net::HttpResponseHeaders(
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        original_response_headers->raw_headers());
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParsedResponseCookies cookies =
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetResponseCookies(*override_response_headers);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool modified = false;
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  modified |= MergeAddResponseCookieModifications(deltas, &cookies);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  modified |= MergeEditResponseCookieModifications(deltas, &cookies);
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  modified |= MergeRemoveResponseCookieModifications(deltas, &cookies);
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store new value.
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modified)
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StoreResponseCookies(cookies, *override_response_headers);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts the key of the (key, value) pair to lower case.
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static ResponseHeader ToLowerCase(const ResponseHeader& header) {
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string lower_key(header.first);
10246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::StringToLowerASCII(&lower_key);
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ResponseHeader(lower_key, header.second);
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the extension ID of the first extension in |deltas| that removes the
10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// request header identified by |key|.
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static std::string FindRemoveResponseHeader(
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const EventResponseDeltas& deltas,
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& key) {
10336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string lower_key = base::StringToLowerASCII(key);
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EventResponseDeltas::const_iterator delta;
10352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
10362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ResponseHeaders::const_iterator i;
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (i = (*delta)->deleted_response_headers.begin();
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         i != (*delta)->deleted_response_headers.end(); ++i) {
10396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (base::StringToLowerASCII(i->first) == lower_key)
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return (*delta)->extension_id;
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1043c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::string();
10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MergeOnHeadersReceivedResponses(
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpResponseHeaders* original_response_headers,
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
1050effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    GURL* allowed_unsafe_redirect_url,
10511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    extensions::WarningSet* conflicting_extensions,
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog* net_log) {
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventResponseDeltas::const_iterator delta;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Here we collect which headers we have removed or added so far due to
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extensions of higher precedence. Header keys are always stored as
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lower case.
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<ResponseHeader> removed_headers;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<ResponseHeader> added_headers;
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume here that the deltas are sorted in decreasing extension
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // precedence (i.e. decreasing extension installation time).
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (delta = deltas.begin(); delta != deltas.end(); ++delta) {
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*delta)->added_response_headers.empty() &&
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*delta)->deleted_response_headers.empty()) {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only create a copy if we really want to modify the response headers.
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (override_response_headers->get() == NULL) {
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *override_response_headers = new net::HttpResponseHeaders(
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          original_response_headers->raw_headers());
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We consider modifications as pairs of (delete, add) operations.
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If a header is deleted twice by different extensions we assume that the
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // intention was to modify it to different values and consider this a
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // conflict. As deltas is sorted by decreasing extension installation order,
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this takes care of precedence.
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool extension_conflicts = false;
10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string conflicting_header;
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string winning_extension_id;
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseHeaders::const_iterator i;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = (*delta)->deleted_response_headers.begin();
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         i != (*delta)->deleted_response_headers.end(); ++i) {
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (removed_headers.find(ToLowerCase(*i)) != removed_headers.end()) {
10872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        winning_extension_id = FindRemoveResponseHeader(deltas, i->first);
10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        conflicting_header = i->first;
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension_conflicts = true;
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now execute the modifications if there were no conflicts.
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!extension_conflicts) {
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Delete headers
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = (*delta)->deleted_response_headers.begin();
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             i != (*delta)->deleted_response_headers.end(); ++i) {
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*override_response_headers)->RemoveHeaderLine(i->first, i->second);
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          removed_headers.insert(ToLowerCase(*i));
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Add headers.
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (i = (*delta)->added_response_headers.begin();
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             i != (*delta)->added_response_headers.end(); ++i) {
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ResponseHeader lowercase_header(ToLowerCase(*i));
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (added_headers.find(lowercase_header) != added_headers.end())
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            continue;
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          added_headers.insert(lowercase_header);
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*override_response_headers)->AddHeader(i->first + ": " + i->second);
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log->AddEvent(
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_CHROME_EXTENSION_MODIFIED_HEADERS,
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogExtensionIdCallback(delta->get()));
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      conflicting_extensions->insert(
11211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          extensions::Warning::CreateResponseHeaderConflictWarning(
11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (*delta)->extension_id, winning_extension_id,
11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              conflicting_header));
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log->AddEvent(
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogExtensionIdCallback(delta->get()));
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MergeCookiesInOnHeadersReceivedResponses(deltas, original_response_headers,
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      override_response_headers, conflicting_extensions, net_log);
1132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  GURL new_url;
1134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  MergeRedirectUrlOfResponses(
1135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      deltas, &new_url, conflicting_extensions, net_log);
1136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (new_url.is_valid()) {
1137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Only create a copy if we really want to modify the response headers.
1138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (override_response_headers->get() == NULL) {
1139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      *override_response_headers = new net::HttpResponseHeaders(
1140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          original_response_headers->raw_headers());
1141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
1142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    (*override_response_headers)->ReplaceStatusLine("HTTP/1.1 302 Found");
1143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    (*override_response_headers)->RemoveHeader("location");
1144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    (*override_response_headers)->AddHeader("Location: " + new_url.spec());
1145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // Explicitly mark the URL as safe for redirection, to prevent the request
1146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // from being blocked because of net::ERR_UNSAFE_REDIRECT.
1147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    *allowed_unsafe_redirect_url = new_url;
1148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MergeOnAuthRequiredResponses(
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const EventResponseDeltas& deltas,
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::AuthCredentials* auth_credentials,
11541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    extensions::WarningSet* conflicting_extensions,
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog* net_log) {
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(auth_credentials);
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool credentials_set = false;
11582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string winning_extension_id;
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (EventResponseDeltas::const_iterator delta = deltas.begin();
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       delta != deltas.end();
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++delta) {
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(*delta)->auth_credentials.get())
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool different =
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        auth_credentials->username() !=
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (*delta)->auth_credentials->username() ||
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        auth_credentials->password() != (*delta)->auth_credentials->password();
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (credentials_set && different) {
11702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      conflicting_extensions->insert(
11711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          extensions::Warning::CreateCredentialsConflictWarning(
11722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (*delta)->extension_id, winning_extension_id));
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log->AddEvent(
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_CHROME_EXTENSION_IGNORED_DUE_TO_CONFLICT,
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogExtensionIdCallback(delta->get()));
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log->AddEvent(
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_CHROME_EXTENSION_PROVIDE_AUTH_CREDENTIALS,
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogExtensionIdCallback(delta->get()));
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *auth_credentials = *(*delta)->auth_credentials;
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      credentials_set = true;
11822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      winning_extension_id = (*delta)->extension_id;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return credentials_set;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearCacheOnNavigation() {
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearCacheOnNavigationOnUI();
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::Bind(&ClearCacheOnNavigationOnUI));
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void NotifyWebRequestAPIUsed(
11981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context_id,
1199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_refptr<const extensions::Extension> extension) {
1200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
12011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  content::BrowserContext* browser_context =
12021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      reinterpret_cast<content::BrowserContext*>(browser_context_id);
12031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(
12041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      browser_context))
1205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
1206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  extensions::RuntimeData* runtime_data =
12081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extensions::ExtensionSystem::Get(browser_context)->runtime_data();
12095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (runtime_data->HasUsedWebRequest(extension.get()))
1210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
12115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  runtime_data->SetHasUsedWebRequest(extension.get(), true);
1212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (content::RenderProcessHost::iterator it =
1214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           content::RenderProcessHost::AllHostsIterator();
1215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       !it.IsAtEnd(); it.Advance()) {
1216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    content::RenderProcessHost* host = it.GetCurrentValue();
1217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (host->GetBrowserContext() == browser_context)
1218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SendExtensionWebRequestStatusToHost(host);
1219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid SendExtensionWebRequestStatusToHost(content::RenderProcessHost* host) {
12231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  content::BrowserContext* browser_context = host->GetBrowserContext();
12241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_context)
12251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
12261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool webrequest_used = false;
12281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const extensions::ExtensionSet& extensions =
12291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extensions::ExtensionRegistry::Get(browser_context)->enabled_extensions();
12301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  extensions::RuntimeData* runtime_data =
12311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extensions::ExtensionSystem::Get(browser_context)->runtime_data();
12321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (extensions::ExtensionSet::const_iterator it = extensions.begin();
12331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       !webrequest_used && it != extensions.end();
12341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++it) {
12351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    webrequest_used |= runtime_data->HasUsedWebRequest(it->get());
12361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
12371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  host->Send(new ExtensionMsg_UsingWebRequestAPI(webrequest_used));
12391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
12401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Converts the |name|, |value| pair of a http header to a HttpHeaders
12421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// dictionary. Ownership is passed to the caller.
12431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibase::DictionaryValue* CreateHeaderDictionary(
12441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& name, const std::string& value) {
12451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::DictionaryValue* header = new base::DictionaryValue();
12461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  header->SetString(keys::kHeaderNameKey, name);
12471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (base::IsStringUTF8(value)) {
12481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    header->SetString(keys::kHeaderValueKey, value);
12491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
12501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    header->Set(keys::kHeaderBinaryValueKey,
12511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                StringToCharList(value));
12521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
12531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return header;
12541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
12551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define ARRAYEND(array) (array + arraysize(array))
12571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool IsRelevantResourceType(ResourceType type) {
12591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResourceType* iter =
12601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      std::find(kResourceTypeValues,
12611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                kResourceTypeValues + kResourceTypeValuesLength,
12621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                type);
12631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return iter != (kResourceTypeValues + kResourceTypeValuesLength);
12641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
12651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char* ResourceTypeToString(ResourceType type) {
12671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResourceType* iter =
12681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      std::find(kResourceTypeValues,
12691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                kResourceTypeValues + kResourceTypeValuesLength,
12701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                type);
12711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (iter == (kResourceTypeValues + kResourceTypeValuesLength))
12721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return "other";
12731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return kResourceTypeStrings[iter - kResourceTypeValues];
1275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
1276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
12771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ParseResourceType(const std::string& type_str,
12781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       ResourceType* type) {
12791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const char** iter =
12801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      std::find(kResourceTypeStrings,
12811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                kResourceTypeStrings + kResourceTypeStringsLength,
12821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                type_str);
12831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (iter == (kResourceTypeStrings + kResourceTypeStringsLength))
12841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
12851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  *type = kResourceTypeValues[iter - kResourceTypeStrings];
12861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
1287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
1288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extension_web_request_api_helpers
1290