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 20 using content::ResourceRequestInfo; 21 22 namespace { 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. 27 bool 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 } 56 GURL::Replacements replacements; 57 replacements.ClearQuery(); 58 replacements.ClearRef(); 59 GURL url_without_query = url.ReplaceComponents(replacements); 60 return sensitive_chrome_url || 61 extension_urls::IsWebstoreUpdateUrl(url_without_query) || 62 extension_urls::IsBlacklistUpdateUrl(url); 63 } 64 65 // Returns true if the scheme is one we want to allow extensions to have access 66 // to. Extensions still need specific permissions for a given URL, which is 67 // covered by CanExtensionAccessURL. 68 bool HasWebRequestScheme(const GURL& url) { 69 return (url.SchemeIs(chrome::kAboutScheme) || 70 url.SchemeIs(chrome::kFileScheme) || 71 url.SchemeIs(chrome::kFileSystemScheme) || 72 url.SchemeIs(content::kFtpScheme) || 73 url.SchemeIs(content::kHttpScheme) || 74 url.SchemeIs(content::kHttpsScheme) || 75 url.SchemeIs(extensions::kExtensionScheme)); 76 } 77 78 } // namespace 79 80 // static 81 bool WebRequestPermissions::HideRequest( 82 const extensions::InfoMap* extension_info_map, 83 const net::URLRequest* request) { 84 // Hide requests from the Chrome WebStore App or signin process. 85 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); 86 if (info) { 87 int process_id = info->GetChildID(); 88 int route_id = info->GetRouteID(); 89 ExtensionRendererState::WebViewInfo webview_info; 90 // Never hide requests from guest processes. 91 if (ExtensionRendererState::GetInstance()->GetWebViewInfo( 92 process_id, route_id, &webview_info)) { 93 return false; 94 } 95 if (extension_info_map && ( 96 extension_info_map->IsSigninProcess(process_id) || 97 extension_info_map->process_map().Contains( 98 extension_misc::kWebStoreAppId, process_id))) { 99 return true; 100 } 101 } 102 103 const GURL& url = request->url(); 104 return IsSensitiveURL(url) || !HasWebRequestScheme(url); 105 } 106 107 // static 108 bool WebRequestPermissions::CanExtensionAccessURL( 109 const extensions::InfoMap* extension_info_map, 110 const std::string& extension_id, 111 const GURL& url, 112 bool crosses_incognito, 113 HostPermissionsCheck host_permissions_check) { 114 // extension_info_map can be NULL in testing. 115 if (!extension_info_map) 116 return true; 117 118 const extensions::Extension* extension = 119 extension_info_map->extensions().GetByID(extension_id); 120 if (!extension) 121 return false; 122 123 // Check if this event crosses incognito boundaries when it shouldn't. 124 if (crosses_incognito && !extension_info_map->CanCrossIncognito(extension)) 125 return false; 126 127 switch (host_permissions_check) { 128 case DO_NOT_CHECK_HOST: 129 break; 130 case REQUIRE_HOST_PERMISSION: 131 // about: URLs are not covered in host permissions, but are allowed 132 // anyway. 133 if (!((url.SchemeIs(chrome::kAboutScheme) || 134 extensions::PermissionsData::HasHostPermission(extension, url) || 135 url.GetOrigin() == extension->url()))) { 136 return false; 137 } 138 break; 139 case REQUIRE_ALL_URLS: 140 if (!extensions::PermissionsData::HasEffectiveAccessToAllHosts(extension)) 141 return false; 142 break; 143 } 144 145 return true; 146 } 147