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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/web_request/web_request_permissions.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/resource_request_info.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/info_map.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/extension_urls.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::ResourceRequestInfo;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the URL is sensitive and requests to this URL must not be
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modified/canceled by extensions, e.g. because it is targeted to the webstore
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to check for updates, extension blacklisting, etc.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsSensitiveURL(const GURL& url) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(battre) Merge this, CanExtensionAccessURL and
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // PermissionsData::CanAccessPage into one function.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sensitive_chrome_url = false;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string host = url.host();
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kGoogleCom[] = ".google.com";
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kClient[] = "clients";
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (EndsWith(host, kGoogleCom, true)) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check for "clients[0-9]*.google.com" hosts.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This protects requests to several internal services such as sync,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // extension update pings, captive portal detection, fraudulent certificate
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // reporting, autofill and others.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (StartsWithASCII(host, kClient, true)) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool match = true;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (std::string::const_iterator i = host.begin() + strlen(kClient),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               end = host.end() - strlen(kGoogleCom); i != end; ++i) {
422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        if (!isdigit(*i)) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          match = false;
442385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch          break;
452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch        }
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sensitive_chrome_url = sensitive_chrome_url || match;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This protects requests to safe browsing, link doctor, and possibly
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // others.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sensitive_chrome_url = sensitive_chrome_url ||
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EndsWith(url.host(), ".clients.google.com", true) ||
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        url.host() == "sb-ssl.google.com" ||
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        (url.host() ==  "chrome.google.com" &&
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             StartsWithASCII(url.path(), "/webstore", true));
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.ClearQuery();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.ClearRef();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url_without_query = url.ReplaceComponents(replacements);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sensitive_chrome_url ||
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_urls::IsWebstoreUpdateUrl(url_without_query) ||
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_urls::IsBlacklistUpdateUrl(url);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the scheme is one we want to allow extensions to have access
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to. Extensions still need specific permissions for a given URL, which is
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// covered by CanExtensionAccessURL.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasWebRequestScheme(const GURL& url) {
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return (url.SchemeIs(url::kAboutScheme) || url.SchemeIs(url::kFileScheme) ||
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          url.SchemeIs(url::kFileSystemScheme) ||
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          url.SchemeIs(url::kFtpScheme) || url.SchemeIs(url::kHttpScheme) ||
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          url.SchemeIs(url::kHttpsScheme) ||
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          url.SchemeIs(extensions::kExtensionScheme));
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRequestPermissions::HideRequest(
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const extensions::InfoMap* extension_info_map,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLRequest* request) {
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Hide requests from the Chrome WebStore App or signin process.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (info) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int process_id = info->GetChildID();
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Never hide requests from guest processes.
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (extensions::WebViewRendererState::GetInstance()->IsGuest(process_id))
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return false;
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (extension_info_map && (
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        extension_info_map->IsSigninProcess(process_id) ||
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        extension_info_map->process_map().Contains(
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            extensions::kWebStoreAppId, process_id))) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& url = request->url();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IsSensitiveURL(url) || !HasWebRequestScheme(url);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRequestPermissions::CanExtensionAccessURL(
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const extensions::InfoMap* extension_info_map,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool crosses_incognito,
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    HostPermissionsCheck host_permissions_check) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension_info_map can be NULL in testing.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_info_map)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const extensions::Extension* extension =
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_info_map->extensions().GetByID(extension_id);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if this event crosses incognito boundaries when it shouldn't.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (crosses_incognito && !extension_info_map->CanCrossIncognito(extension))
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (host_permissions_check) {
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case DO_NOT_CHECK_HOST:
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case REQUIRE_HOST_PERMISSION:
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // about: URLs are not covered in host permissions, but are allowed
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // anyway.
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (!((url.SchemeIs(url::kAboutScheme) ||
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)             extension->permissions_data()->HasHostPermission(url) ||
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)             url.GetOrigin() == extension->url()))) {
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return false;
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case REQUIRE_ALL_URLS:
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (!extension->permissions_data()->HasEffectiveAccessToAllHosts())
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return false;
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
143