Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/chrome_content_browser_client_extensions_par t.h" | 5 #include "chrome/browser/extensions/chrome_content_browser_client_extensions_par t.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 // should not be changed, and new values should only be added before | 99 // should not be changed, and new values should only be added before |
| 100 // FAILURE_LAST. | 100 // FAILURE_LAST. |
| 101 enum ShouldAllowOpenURLFailureReason { | 101 enum ShouldAllowOpenURLFailureReason { |
| 102 FAILURE_FILE_SYSTEM_URL = 0, | 102 FAILURE_FILE_SYSTEM_URL = 0, |
| 103 FAILURE_BLOB_URL, | 103 FAILURE_BLOB_URL, |
| 104 FAILURE_SCHEME_NOT_HTTP_OR_HTTPS_OR_EXTENSION, | 104 FAILURE_SCHEME_NOT_HTTP_OR_HTTPS_OR_EXTENSION, |
| 105 FAILURE_RESOURCE_NOT_WEB_ACCESSIBLE, | 105 FAILURE_RESOURCE_NOT_WEB_ACCESSIBLE, |
| 106 FAILURE_LAST, | 106 FAILURE_LAST, |
| 107 }; | 107 }; |
| 108 | 108 |
| 109 // Specifies the scheme of the SiteInstance responsible for a failed | |
| 110 // web-accessible resource check in ShouldAllowOpenURL. | |
| 111 // | |
| 112 // This enum backs an UMA histogram. The order of existing values | |
| 113 // should not be changed, and new values should only be added before | |
| 114 // SCHEME_LAST. It must also be synchronized to kSchemeNames in | |
| 115 // RecordShowAllowOpenURLFailure. | |
|
ncarter (slow)
2017/03/29 22:59:21
It's possible to add a presubmit that will fail if
alexmos
2017/03/31 01:11:04
Done. This is awesome, thanks for the pointers!
| |
| 116 enum ShouldAllowOpenURLFailureScheme { | |
| 117 SCHEME_UNKNOWN, | |
| 118 SCHEME_EMPTY, | |
| 119 SCHEME_HTTP, | |
| 120 SCHEME_HTTPS, | |
| 121 SCHEME_FILE, | |
| 122 SCHEME_FTP, | |
| 123 SCHEME_DATA, | |
| 124 SCHEME_JAVASCRIPT, | |
| 125 SCHEME_ABOUT, | |
| 126 SCHEME_CHROME, | |
| 127 SCHEME_DEVTOOLS, | |
| 128 SCHEME_GUEST, | |
| 129 SCHEME_VIEWSOURCE, | |
| 130 SCHEME_CHROME_SEARCH, | |
| 131 SCHEME_CHROME_EXTENSION, | |
| 132 SCHEME_BLOB, | |
| 133 SCHEME_FILESYSTEM, | |
|
ncarter (slow)
2017/03/29 22:59:21
content:// (that's the android-only file:// like
alexmos
2017/03/31 01:11:04
Done. content:// should never show up for this um
| |
| 134 SCHEME_LAST, | |
|
ncarter (slow)
2017/03/29 22:59:21
I recommend adding a unittest here that: grab a se
alexmos
2017/03/31 01:11:04
Done. Had to move some things around to let the t
| |
| 135 }; | |
| 136 | |
| 109 RenderProcessHostPrivilege GetPrivilegeRequiredByUrl( | 137 RenderProcessHostPrivilege GetPrivilegeRequiredByUrl( |
| 110 const GURL& url, | 138 const GURL& url, |
| 111 ExtensionRegistry* registry) { | 139 ExtensionRegistry* registry) { |
| 112 // Default to a normal renderer cause it is lower privileged. This should only | 140 // Default to a normal renderer cause it is lower privileged. This should only |
| 113 // occur if the URL on a site instance is either malformed, or uninitialized. | 141 // occur if the URL on a site instance is either malformed, or uninitialized. |
| 114 // If it is malformed, then there is no need for better privileges anyways. | 142 // If it is malformed, then there is no need for better privileges anyways. |
| 115 // If it is uninitialized, but eventually settles on being an a scheme other | 143 // If it is uninitialized, but eventually settles on being an a scheme other |
| 116 // than normal webrenderer, the navigation logic will correct us out of band | 144 // than normal webrenderer, the navigation logic will correct us out of band |
| 117 // anyways. | 145 // anyways. |
| 118 if (!url.is_valid()) | 146 if (!url.is_valid()) |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 content::ResourceContext* resource_context, | 249 content::ResourceContext* resource_context, |
| 222 content::OnHeaderProcessedCallback callback) { | 250 content::OnHeaderProcessedCallback callback) { |
| 223 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 251 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 224 | 252 |
| 225 GURL origin(value); | 253 GURL origin(value); |
| 226 DCHECK(origin.SchemeIs(extensions::kExtensionScheme)); | 254 DCHECK(origin.SchemeIs(extensions::kExtensionScheme)); |
| 227 | 255 |
| 228 callback.Run(CheckOriginHeader(resource_context, child_id, origin)); | 256 callback.Run(CheckOriginHeader(resource_context, child_id, origin)); |
| 229 } | 257 } |
| 230 | 258 |
| 231 void RecordShowAllowOpenURLFailure(ShouldAllowOpenURLFailureReason reason) { | 259 // Helper to record metrics when ShouldAllowOpenURL blocks a load. |site_url| |
| 260 // corresponds to the SiteInstance that initiated the blocked load. | |
| 261 void RecordShowAllowOpenURLFailure(ShouldAllowOpenURLFailureReason reason, | |
| 262 GURL site_url) { | |
| 232 UMA_HISTOGRAM_ENUMERATION("Extensions.ShouldAllowOpenURL.Failure", reason, | 263 UMA_HISTOGRAM_ENUMERATION("Extensions.ShouldAllowOpenURL.Failure", reason, |
| 233 FAILURE_LAST); | 264 FAILURE_LAST); |
| 265 | |
| 266 const char* const kSchemeNames[] = { | |
| 267 "unknown", | |
| 268 "", | |
| 269 url::kHttpScheme, | |
| 270 url::kHttpsScheme, | |
| 271 url::kFileScheme, | |
| 272 url::kFtpScheme, | |
| 273 url::kDataScheme, | |
| 274 url::kJavaScriptScheme, | |
| 275 url::kAboutScheme, | |
| 276 content::kChromeUIScheme, | |
| 277 content::kChromeDevToolsScheme, | |
| 278 content::kGuestScheme, | |
| 279 content::kViewSourceScheme, | |
| 280 chrome::kChromeSearchScheme, | |
| 281 extensions::kExtensionScheme, | |
| 282 url::kBlobScheme, | |
| 283 url::kFileSystemScheme, | |
| 284 "last", | |
| 285 }; | |
| 286 | |
| 287 static_assert(arraysize(kSchemeNames) == SCHEME_LAST + 1, | |
| 288 "kSchemeNames should have SCHEME_LAST + 1 elements"); | |
| 289 | |
| 290 ShouldAllowOpenURLFailureScheme scheme = SCHEME_UNKNOWN; | |
| 291 for (int i = 1; i < SCHEME_LAST; i++) { | |
| 292 if (site_url.SchemeIs(kSchemeNames[i])) { | |
| 293 scheme = static_cast<ShouldAllowOpenURLFailureScheme>(i); | |
| 294 break; | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 UMA_HISTOGRAM_ENUMERATION("Extensions.ShouldAllowOpenURL.Failure.Scheme", | |
| 299 scheme, SCHEME_LAST); | |
| 234 } | 300 } |
| 235 | 301 |
| 236 } // namespace | 302 } // namespace |
| 237 | 303 |
| 238 ChromeContentBrowserClientExtensionsPart:: | 304 ChromeContentBrowserClientExtensionsPart:: |
| 239 ChromeContentBrowserClientExtensionsPart() { | 305 ChromeContentBrowserClientExtensionsPart() { |
| 240 } | 306 } |
| 241 | 307 |
| 242 ChromeContentBrowserClientExtensionsPart:: | 308 ChromeContentBrowserClientExtensionsPart:: |
| 243 ~ChromeContentBrowserClientExtensionsPart() { | 309 ~ChromeContentBrowserClientExtensionsPart() { |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 580 registry->enabled_extensions().GetExtensionOrAppByURL(site_url); | 646 registry->enabled_extensions().GetExtensionOrAppByURL(site_url); |
| 581 if (from_extension && from_extension == to_extension) { | 647 if (from_extension && from_extension == to_extension) { |
| 582 *result = true; | 648 *result = true; |
| 583 return true; | 649 return true; |
| 584 } | 650 } |
| 585 | 651 |
| 586 // Blob and filesystem URLs are never considered web-accessible. See | 652 // Blob and filesystem URLs are never considered web-accessible. See |
| 587 // https://crbug.com/656752. | 653 // https://crbug.com/656752. |
| 588 if (to_url.SchemeIsFileSystem() || to_url.SchemeIsBlob()) { | 654 if (to_url.SchemeIsFileSystem() || to_url.SchemeIsBlob()) { |
| 589 if (to_url.SchemeIsFileSystem()) | 655 if (to_url.SchemeIsFileSystem()) |
| 590 RecordShowAllowOpenURLFailure(FAILURE_FILE_SYSTEM_URL); | 656 RecordShowAllowOpenURLFailure(FAILURE_FILE_SYSTEM_URL, site_url); |
| 591 else | 657 else |
| 592 RecordShowAllowOpenURLFailure(FAILURE_BLOB_URL); | 658 RecordShowAllowOpenURLFailure(FAILURE_BLOB_URL, site_url); |
| 593 | 659 |
| 594 // TODO(alexmos): Temporary instrumentation to find any regressions for | 660 // TODO(alexmos): Temporary instrumentation to find any regressions for |
| 595 // this blocking. Remove after verifying that this is not breaking any | 661 // this blocking. Remove after verifying that this is not breaking any |
| 596 // legitimate use cases. | 662 // legitimate use cases. |
| 597 char site_url_copy[256]; | 663 char site_url_copy[256]; |
| 598 base::strlcpy(site_url_copy, site_url.spec().c_str(), | 664 base::strlcpy(site_url_copy, site_url.spec().c_str(), |
| 599 arraysize(site_url_copy)); | 665 arraysize(site_url_copy)); |
| 600 base::debug::Alias(&site_url_copy); | 666 base::debug::Alias(&site_url_copy); |
| 601 char to_origin_copy[256]; | 667 char to_origin_copy[256]; |
| 602 base::strlcpy(to_origin_copy, to_origin.Serialize().c_str(), | 668 base::strlcpy(to_origin_copy, to_origin.Serialize().c_str(), |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 630 return true; | 696 return true; |
| 631 } | 697 } |
| 632 | 698 |
| 633 if (WebAccessibleResourcesInfo::IsResourceWebAccessible(to_extension, | 699 if (WebAccessibleResourcesInfo::IsResourceWebAccessible(to_extension, |
| 634 to_url.path())) { | 700 to_url.path())) { |
| 635 *result = true; | 701 *result = true; |
| 636 return true; | 702 return true; |
| 637 } | 703 } |
| 638 | 704 |
| 639 if (!site_url.SchemeIsHTTPOrHTTPS() && !site_url.SchemeIs(kExtensionScheme)) { | 705 if (!site_url.SchemeIsHTTPOrHTTPS() && !site_url.SchemeIs(kExtensionScheme)) { |
| 640 RecordShowAllowOpenURLFailure( | 706 // This function used to incorrectly skip the web-accessible resource |
| 641 FAILURE_SCHEME_NOT_HTTP_OR_HTTPS_OR_EXTENSION); | 707 // checks in this case. Measure how often this happens. See also |
| 642 | 708 // https://crbug.com/696034. |
| 643 // TODO(alexmos): Previous version of this function skipped the | 709 RecordShowAllowOpenURLFailure(FAILURE_SCHEME_NOT_HTTP_OR_HTTPS_OR_EXTENSION, |
| 644 // web-accessible resource checks in this case. Collect data to catch | 710 site_url); |
| 645 // any regressions, and then remove this. | |
| 646 char site_url_copy[256]; | |
| 647 base::strlcpy(site_url_copy, site_url.spec().c_str(), | |
| 648 arraysize(site_url_copy)); | |
| 649 base::debug::Alias(&site_url_copy); | |
| 650 char to_origin_copy[256]; | |
| 651 base::strlcpy(to_origin_copy, to_origin.Serialize().c_str(), | |
| 652 arraysize(to_origin_copy)); | |
| 653 base::debug::Alias(&to_origin_copy); | |
| 654 base::debug::DumpWithoutCrashing(); | |
| 655 } else { | 711 } else { |
| 656 RecordShowAllowOpenURLFailure(FAILURE_RESOURCE_NOT_WEB_ACCESSIBLE); | 712 RecordShowAllowOpenURLFailure(FAILURE_RESOURCE_NOT_WEB_ACCESSIBLE, |
| 713 site_url); | |
| 657 } | 714 } |
| 658 | 715 |
| 659 *result = false; | 716 *result = false; |
| 660 return true; | 717 return true; |
| 661 } | 718 } |
| 662 | 719 |
| 663 // static | 720 // static |
| 664 std::unique_ptr<content::VpnServiceProxy> | 721 std::unique_ptr<content::VpnServiceProxy> |
| 665 ChromeContentBrowserClientExtensionsPart::GetVpnServiceProxy( | 722 ChromeContentBrowserClientExtensionsPart::GetVpnServiceProxy( |
| 666 content::BrowserContext* browser_context) { | 723 content::BrowserContext* browser_context) { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 command_line->AppendSwitch(switches::kExtensionProcess); | 870 command_line->AppendSwitch(switches::kExtensionProcess); |
| 814 } | 871 } |
| 815 } | 872 } |
| 816 | 873 |
| 817 void ChromeContentBrowserClientExtensionsPart::ResourceDispatcherHostCreated() { | 874 void ChromeContentBrowserClientExtensionsPart::ResourceDispatcherHostCreated() { |
| 818 content::ResourceDispatcherHost::Get()->RegisterInterceptor( | 875 content::ResourceDispatcherHost::Get()->RegisterInterceptor( |
| 819 "Origin", kExtensionScheme, base::Bind(&OnHttpHeaderReceived)); | 876 "Origin", kExtensionScheme, base::Bind(&OnHttpHeaderReceived)); |
| 820 } | 877 } |
| 821 | 878 |
| 822 } // namespace extensions | 879 } // namespace extensions |
| OLD | NEW |