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