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 |