Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: extensions/browser/extension_navigation_throttle.cc

Issue 2830893002: Refactor of ExtensionNavigationThrottle (Closed)
Patch Set: \ Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/ui/toolbar/toolbar_model_unittest.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "extensions/browser/extension_navigation_throttle.h" 5 #include "extensions/browser/extension_navigation_throttle.h"
6 6
7 #include "components/guest_view/browser/guest_view_base.h" 7 #include "components/guest_view/browser/guest_view_base.h"
8 #include "content/public/browser/browser_thread.h" 8 #include "content/public/browser/browser_thread.h"
9 #include "content/public/browser/navigation_handle.h" 9 #include "content/public/browser/navigation_handle.h"
10 #include "content/public/browser/render_frame_host.h" 10 #include "content/public/browser/render_frame_host.h"
(...skipping 16 matching lines...) Expand all
27 27
28 ExtensionNavigationThrottle::ExtensionNavigationThrottle( 28 ExtensionNavigationThrottle::ExtensionNavigationThrottle(
29 content::NavigationHandle* navigation_handle) 29 content::NavigationHandle* navigation_handle)
30 : content::NavigationThrottle(navigation_handle) {} 30 : content::NavigationThrottle(navigation_handle) {}
31 31
32 ExtensionNavigationThrottle::~ExtensionNavigationThrottle() {} 32 ExtensionNavigationThrottle::~ExtensionNavigationThrottle() {}
33 33
34 content::NavigationThrottle::ThrottleCheckResult 34 content::NavigationThrottle::ThrottleCheckResult
35 ExtensionNavigationThrottle::WillStartRequest() { 35 ExtensionNavigationThrottle::WillStartRequest() {
36 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 36 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
37 GURL url(navigation_handle()->GetURL());
38 content::WebContents* web_contents = navigation_handle()->GetWebContents(); 37 content::WebContents* web_contents = navigation_handle()->GetWebContents();
39 ExtensionRegistry* registry = 38 ExtensionRegistry* registry =
40 ExtensionRegistry::Get(web_contents->GetBrowserContext()); 39 ExtensionRegistry::Get(web_contents->GetBrowserContext());
41 40
41 // Is this navigation targeting an extension resource?
42 const GURL& url = navigation_handle()->GetURL();
43 bool url_has_extension_scheme = url.SchemeIs(kExtensionScheme);
44 url::Origin target_origin(url);
45 const Extension* target_extension = nullptr;
46 if (url_has_extension_scheme) {
47 // "chrome-extension://" URL.
48 target_extension =
49 registry->enabled_extensions().GetExtensionOrAppByURL(url);
50 } else if (target_origin.scheme() == kExtensionScheme) {
51 // "blob:chrome-extension://" or "filesystem:chrome-extension://" URL.
52 DCHECK(url.SchemeIsFileSystem() || url.SchemeIsBlob());
53 target_extension =
54 registry->enabled_extensions().GetByID(target_origin.host());
55 } else {
56 // If the navigation is not to a chrome-extension resource, no need to
57 // perform any more checks; it's outside of the purview of this throttle.
58 return content::NavigationThrottle::PROCEED;
59 }
60
61 // If the navigation is to an unknown or disabled extension, block it.
62 if (!target_extension) {
63 // TODO(nick): This yields an unsatisfying error page; use a different error
64 // code once that's supported. https://crbug.com/649869
65 return content::NavigationThrottle::BLOCK_REQUEST;
66 }
67
42 if (navigation_handle()->IsInMainFrame()) { 68 if (navigation_handle()->IsInMainFrame()) {
43 // Block top-level navigations to blob: or filesystem: URLs with extension 69 // Block top-level navigations to blob: or filesystem: URLs with extension
44 // origin from non-extension processes. See https://crbug.com/645028. 70 // origin from non-extension processes. See https://crbug.com/645028.
45 bool is_nested_url = url.SchemeIsFileSystem() || url.SchemeIsBlob(); 71 bool current_frame_is_extension_process =
46 bool is_extension = false; 72 !!registry->enabled_extensions().GetExtensionOrAppByURL(
47 if (registry) { 73 navigation_handle()->GetStartingSiteInstance()->GetSiteURL());
48 is_extension = !!registry->enabled_extensions().GetExtensionOrAppByURL(
49 navigation_handle()->GetStartingSiteInstance()->GetSiteURL());
50 }
51 74
52 url::Origin origin(url); 75 if (!url_has_extension_scheme && !current_frame_is_extension_process) {
53 if (is_nested_url && origin.scheme() == extensions::kExtensionScheme &&
54 !is_extension) {
55 // Relax this restriction for apps that use <webview>. See 76 // Relax this restriction for apps that use <webview>. See
56 // https://crbug.com/652077. 77 // https://crbug.com/652077.
57 const extensions::Extension* extension =
58 registry->enabled_extensions().GetByID(origin.host());
59 bool has_webview_permission = 78 bool has_webview_permission =
60 extension && 79 target_extension->permissions_data()->HasAPIPermission(
61 extension->permissions_data()->HasAPIPermission( 80 APIPermission::kWebView);
62 extensions::APIPermission::kWebView);
63 if (!has_webview_permission) 81 if (!has_webview_permission)
64 return content::NavigationThrottle::CANCEL; 82 return content::NavigationThrottle::CANCEL;
65 } 83 }
66 84
67 if (content::IsBrowserSideNavigationEnabled() && 85 guest_view::GuestViewBase* guest =
68 url.scheme() == extensions::kExtensionScheme) { 86 guest_view::GuestViewBase::FromWebContents(web_contents);
69 // This logic is performed for PlzNavigate sub-resources and for 87 if (content::IsBrowserSideNavigationEnabled() && url_has_extension_scheme &&
70 // non-PlzNavigate in 88 guest) {
71 // extensions::url_request_util::AllowCrossRendererResourceLoad. 89 // This variant of this logic applies to PlzNavigate top-level
72 const Extension* extension = 90 // navigations. It is performed for subresources, and for non-PlzNavigate
73 registry->enabled_extensions().GetExtensionOrAppByURL(url); 91 // top navigations, in url_request_util::AllowCrossRendererResourceLoad.
74 guest_view::GuestViewBase* guest = 92 const std::string& owner_extension_id = guest->owner_host();
75 guest_view::GuestViewBase::FromWebContents(web_contents); 93 const Extension* owner_extension =
76 if (guest) { 94 registry->enabled_extensions().GetByID(owner_extension_id);
77 std::string owner_extension_id = guest->owner_host();
78 const Extension* owner_extension =
79 registry->enabled_extensions().GetByID(owner_extension_id);
80 95
81 std::string partition_domain, partition_id; 96 std::string partition_domain;
82 bool in_memory; 97 std::string partition_id;
83 std::string resource_path = url.path(); 98 bool in_memory = false;
84 bool is_guest = WebViewGuest::GetGuestPartitionConfigForSite( 99 bool is_guest = WebViewGuest::GetGuestPartitionConfigForSite(
85 navigation_handle()->GetStartingSiteInstance()->GetSiteURL(), 100 navigation_handle()->GetStartingSiteInstance()->GetSiteURL(),
86 &partition_domain, &partition_id, &in_memory); 101 &partition_domain, &partition_id, &in_memory);
87 102
88 bool allowed = true; 103 bool allowed = true;
89 url_request_util::AllowCrossRendererResourceLoadHelper( 104 url_request_util::AllowCrossRendererResourceLoadHelper(
90 is_guest, extension, owner_extension, partition_id, resource_path, 105 is_guest, target_extension, owner_extension, partition_id, url.path(),
91 navigation_handle()->GetPageTransition(), &allowed); 106 navigation_handle()->GetPageTransition(), &allowed);
92 if (!allowed) 107 if (!allowed)
93 return content::NavigationThrottle::BLOCK_REQUEST; 108 return content::NavigationThrottle::BLOCK_REQUEST;
94 }
95 } 109 }
96 110
97 return content::NavigationThrottle::PROCEED; 111 return content::NavigationThrottle::PROCEED;
98 } 112 }
99 113
100 // Now enforce web_accessible_resources for navigations. Top-level navigations 114 // This is a subframe navigation to a |target_extension| resource.
101 // should always be allowed. 115 // Enforce the web_accessible_resources restriction.
116 content::RenderFrameHost* parent = navigation_handle()->GetParentFrame();
102 117
103 // If the navigation is not to a chrome-extension:// URL, no need to perform 118 // Look to see if all ancestors belong to |target_extension|. If not,
104 // any more checks. 119 // then the web_accessible_resource restriction applies.
105 if (!url.SchemeIs(extensions::kExtensionScheme)) 120 bool external_ancestor = false;
106 return content::NavigationThrottle::PROCEED; 121 for (auto* ancestor = parent; ancestor; ancestor = ancestor->GetParent()) {
122 // Look for a match on the last committed origin. This handles the
123 // common case, and the about:blank case.
124 if (ancestor->GetLastCommittedOrigin() == target_origin)
125 continue;
126 // Look for an origin match with the last committed URL. This handles the
127 // case of sandboxed extension resources, which commit with a null origin,
128 // but are permitted to load non-webaccessible extension resources in
129 // subframes.
130 if (url::Origin(ancestor->GetLastCommittedURL()) == target_origin)
131 continue;
132 // Ignore DevTools, as it is allowed to embed extension pages.
133 if (ancestor->GetLastCommittedURL().SchemeIs(
134 content::kChromeDevToolsScheme))
135 continue;
107 136
108 // The subframe which is navigated needs to have all of its ancestors be 137 // Otherwise, we have an external ancestor.
109 // at the same origin, otherwise the resource needs to be explicitly listed 138 external_ancestor = true;
110 // in web_accessible_resources. 139 break;
111 content::RenderFrameHost* ancestor = navigation_handle()->GetParentFrame();
112 bool external_ancestor = false;
113 while (ancestor) {
114 if (ancestor->GetLastCommittedURL().GetOrigin() != url.GetOrigin()) {
115 // Ignore DevTools, as it is allowed to embed extension pages.
116 if (!ancestor->GetLastCommittedURL().SchemeIs(
117 content::kChromeDevToolsScheme)) {
118 external_ancestor = true;
119 break;
120 }
121 }
122 ancestor = ancestor->GetParent();
123 } 140 }
124 141
125 if (!external_ancestor) 142 if (external_ancestor) {
126 return content::NavigationThrottle::PROCEED; 143 // Cancel navigations to nested URLs, to match the main frame behavior.
144 if (!url_has_extension_scheme)
145 return content::NavigationThrottle::CANCEL;
127 146
128 // Since there was at least one origin different than the navigation URL, 147 // |url| must be in the manifest's "web_accessible_resources" section.
129 // explicitly check for the resource in web_accessible_resources. 148 if (!WebAccessibleResourcesInfo::IsResourceWebAccessible(target_extension,
130 std::string resource_path = url.path(); 149 url.path()))
131 if (!registry) 150 return content::NavigationThrottle::BLOCK_REQUEST;
132 return content::NavigationThrottle::BLOCK_REQUEST;
133
134 const extensions::Extension* extension =
135 registry->enabled_extensions().GetByID(url.host());
136 if (!extension)
137 return content::NavigationThrottle::BLOCK_REQUEST;
138
139 if (WebAccessibleResourcesInfo::IsResourceWebAccessible(extension,
140 resource_path)) {
141 return content::NavigationThrottle::PROCEED;
142 } 151 }
143 152
144 return content::NavigationThrottle::BLOCK_REQUEST; 153 return content::NavigationThrottle::PROCEED;
145 } 154 }
146 155
147 const char* ExtensionNavigationThrottle::GetNameForLogging() { 156 const char* ExtensionNavigationThrottle::GetNameForLogging() {
148 return "ExtensionNavigationThrottle"; 157 return "ExtensionNavigationThrottle";
149 } 158 }
150 159
151 } // namespace extensions 160 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/ui/toolbar/toolbar_model_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698