Home | History | Annotate | Download | only in web_request
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "extensions/browser/api/web_request/web_request_permissions.h"
      6 
      7 #include "base/strings/string_util.h"
      8 #include "base/strings/stringprintf.h"
      9 #include "content/public/browser/resource_request_info.h"
     10 #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
     11 #include "extensions/browser/info_map.h"
     12 #include "extensions/common/constants.h"
     13 #include "extensions/common/extension.h"
     14 #include "extensions/common/extension_urls.h"
     15 #include "extensions/common/permissions/permissions_data.h"
     16 #include "net/url_request/url_request.h"
     17 #include "url/gurl.h"
     18 
     19 using content::ResourceRequestInfo;
     20 
     21 namespace {
     22 
     23 // Returns true if the URL is sensitive and requests to this URL must not be
     24 // modified/canceled by extensions, e.g. because it is targeted to the webstore
     25 // to check for updates, extension blacklisting, etc.
     26 bool IsSensitiveURL(const GURL& url) {
     27   // TODO(battre) Merge this, CanExtensionAccessURL and
     28   // PermissionsData::CanAccessPage into one function.
     29   bool sensitive_chrome_url = false;
     30   const std::string host = url.host();
     31   const char kGoogleCom[] = ".google.com";
     32   const char kClient[] = "clients";
     33   if (EndsWith(host, kGoogleCom, true)) {
     34     // Check for "clients[0-9]*.google.com" hosts.
     35     // This protects requests to several internal services such as sync,
     36     // extension update pings, captive portal detection, fraudulent certificate
     37     // reporting, autofill and others.
     38     if (StartsWithASCII(host, kClient, true)) {
     39       bool match = true;
     40       for (std::string::const_iterator i = host.begin() + strlen(kClient),
     41                end = host.end() - strlen(kGoogleCom); i != end; ++i) {
     42         if (!isdigit(*i)) {
     43           match = false;
     44           break;
     45         }
     46       }
     47       sensitive_chrome_url = sensitive_chrome_url || match;
     48     }
     49     // This protects requests to safe browsing, link doctor, and possibly
     50     // others.
     51     sensitive_chrome_url = sensitive_chrome_url ||
     52         EndsWith(url.host(), ".clients.google.com", true) ||
     53         url.host() == "sb-ssl.google.com" ||
     54         (url.host() ==  "chrome.google.com" &&
     55              StartsWithASCII(url.path(), "/webstore", true));
     56   }
     57   GURL::Replacements replacements;
     58   replacements.ClearQuery();
     59   replacements.ClearRef();
     60   GURL url_without_query = url.ReplaceComponents(replacements);
     61   return sensitive_chrome_url ||
     62       extension_urls::IsWebstoreUpdateUrl(url_without_query) ||
     63       extension_urls::IsBlacklistUpdateUrl(url);
     64 }
     65 
     66 // Returns true if the scheme is one we want to allow extensions to have access
     67 // to. Extensions still need specific permissions for a given URL, which is
     68 // covered by CanExtensionAccessURL.
     69 bool HasWebRequestScheme(const GURL& url) {
     70   return (url.SchemeIs(url::kAboutScheme) || url.SchemeIs(url::kFileScheme) ||
     71           url.SchemeIs(url::kFileSystemScheme) ||
     72           url.SchemeIs(url::kFtpScheme) || url.SchemeIs(url::kHttpScheme) ||
     73           url.SchemeIs(url::kHttpsScheme) ||
     74           url.SchemeIs(extensions::kExtensionScheme));
     75 }
     76 
     77 }  // namespace
     78 
     79 // static
     80 bool WebRequestPermissions::HideRequest(
     81     const extensions::InfoMap* extension_info_map,
     82     const net::URLRequest* request) {
     83   // Hide requests from the Chrome WebStore App or signin process.
     84   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
     85   if (info) {
     86     int process_id = info->GetChildID();
     87     // Never hide requests from guest processes.
     88     if (extensions::WebViewRendererState::GetInstance()->IsGuest(process_id))
     89       return false;
     90 
     91     if (extension_info_map && (
     92         extension_info_map->IsSigninProcess(process_id) ||
     93         extension_info_map->process_map().Contains(
     94             extensions::kWebStoreAppId, process_id))) {
     95       return true;
     96     }
     97   }
     98 
     99   const GURL& url = request->url();
    100   return IsSensitiveURL(url) || !HasWebRequestScheme(url);
    101 }
    102 
    103 // static
    104 bool WebRequestPermissions::CanExtensionAccessURL(
    105     const extensions::InfoMap* extension_info_map,
    106     const std::string& extension_id,
    107     const GURL& url,
    108     bool crosses_incognito,
    109     HostPermissionsCheck host_permissions_check) {
    110   // extension_info_map can be NULL in testing.
    111   if (!extension_info_map)
    112     return true;
    113 
    114   const extensions::Extension* extension =
    115       extension_info_map->extensions().GetByID(extension_id);
    116   if (!extension)
    117     return false;
    118 
    119   // Check if this event crosses incognito boundaries when it shouldn't.
    120   if (crosses_incognito && !extension_info_map->CanCrossIncognito(extension))
    121     return false;
    122 
    123   switch (host_permissions_check) {
    124     case DO_NOT_CHECK_HOST:
    125       break;
    126     case REQUIRE_HOST_PERMISSION:
    127       // about: URLs are not covered in host permissions, but are allowed
    128       // anyway.
    129       if (!((url.SchemeIs(url::kAboutScheme) ||
    130              extension->permissions_data()->HasHostPermission(url) ||
    131              url.GetOrigin() == extension->url()))) {
    132         return false;
    133       }
    134       break;
    135     case REQUIRE_ALL_URLS:
    136       if (!extension->permissions_data()->HasEffectiveAccessToAllHosts())
    137         return false;
    138       break;
    139   }
    140 
    141   return true;
    142 }
    143