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

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

Issue 2830893002: Refactor of ExtensionNavigationThrottle (Closed)
Patch Set: Nasko's fix 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/extensions/process_manager_browsertest.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()); 37 const GURL& url = navigation_handle()->GetURL();
38 bool url_has_extension_scheme = url.SchemeIs(kExtensionScheme);
Devlin 2017/04/28 22:13:02 Is it worth a brief comment explaining the signifi
ncarter (slow) 2017/05/01 21:50:37 Done. I eliminated the is_nested_url variable and
38 content::WebContents* web_contents = navigation_handle()->GetWebContents(); 39 content::WebContents* web_contents = navigation_handle()->GetWebContents();
39 ExtensionRegistry* registry = 40 ExtensionRegistry* registry =
40 ExtensionRegistry::Get(web_contents->GetBrowserContext()); 41 ExtensionRegistry::Get(web_contents->GetBrowserContext());
41 42
43 // Is this navigation targeting an extension resource?
44 bool is_nested_url = url.SchemeIsFileSystem() || url.SchemeIsBlob();
45 url::Origin target_origin(url);
46 const Extension* target_extension = nullptr;
47 if (url_has_extension_scheme) {
48 target_extension =
49 registry->enabled_extensions().GetExtensionOrAppByURL(url);
50 } else if (is_nested_url && target_origin.scheme() == kExtensionScheme) {
51 target_extension =
52 registry->enabled_extensions().GetByID(target_origin.host());
53 } else {
54 // If the navigation is not to a chrome-extension resource, no need to
55 // perform any more checks; it's outside of the purview of this throttle.
56 return content::NavigationThrottle::PROCEED;
57 }
58
59 // If the navigation is to an unknown or disabled extension, block it.
60 if (!target_extension)
61 return content::NavigationThrottle::BLOCK_REQUEST;
62
42 if (navigation_handle()->IsInMainFrame()) { 63 if (navigation_handle()->IsInMainFrame()) {
43 // Block top-level navigations to blob: or filesystem: URLs with extension 64 // Block top-level navigations to blob: or filesystem: URLs with extension
44 // origin from non-extension processes. See https://crbug.com/645028. 65 // origin from non-extension processes. See https://crbug.com/645028.
45 bool is_nested_url = url.SchemeIsFileSystem() || url.SchemeIsBlob(); 66 bool current_frame_is_extension_process =
46 bool is_extension = false; 67 !!registry->enabled_extensions().GetExtensionOrAppByURL(
47 if (registry) { 68 navigation_handle()->GetStartingSiteInstance()->GetSiteURL());
48 is_extension = !!registry->enabled_extensions().GetExtensionOrAppByURL(
49 navigation_handle()->GetStartingSiteInstance()->GetSiteURL());
50 }
51 69
52 url::Origin origin(url); 70 if (is_nested_url && !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 71 // Relax this restriction for apps that use <webview>. See
56 // https://crbug.com/652077. 72 // https://crbug.com/652077.
57 const extensions::Extension* extension =
58 registry->enabled_extensions().GetByID(origin.host());
59 bool has_webview_permission = 73 bool has_webview_permission =
60 extension && 74 target_extension->permissions_data()->HasAPIPermission(
61 extension->permissions_data()->HasAPIPermission( 75 APIPermission::kWebView);
62 extensions::APIPermission::kWebView);
63 if (!has_webview_permission) 76 if (!has_webview_permission)
64 return content::NavigationThrottle::CANCEL; 77 return content::NavigationThrottle::CANCEL;
65 } 78 }
66 79
67 if (content::IsBrowserSideNavigationEnabled() && 80 guest_view::GuestViewBase* guest =
68 url.scheme() == extensions::kExtensionScheme) { 81 guest_view::GuestViewBase::FromWebContents(web_contents);
69 // This logic is performed for PlzNavigate sub-resources and for 82 if (content::IsBrowserSideNavigationEnabled() && url_has_extension_scheme &&
70 // non-PlzNavigate in 83 guest) {
71 // extensions::url_request_util::AllowCrossRendererResourceLoad. 84 // This logic is performed for PlzNavigate sub-resources and for non-
72 const Extension* extension = 85 // PlzNavigate in url_request_util::AllowCrossRendererResourceLoad.
Devlin 2017/04/28 22:13:02 "and for non-PlzNavigate" - non-PlzNavigate what?
ncarter (slow) 2017/05/01 21:50:37 Done.
73 registry->enabled_extensions().GetExtensionOrAppByURL(url); 86 std::string owner_extension_id = guest->owner_host();
Devlin 2017/04/28 22:13:02 Can this be a const std::string&? (Or even just i
ncarter (slow) 2017/05/01 21:50:37 Done.
74 guest_view::GuestViewBase* guest = 87 const Extension* owner_extension =
75 guest_view::GuestViewBase::FromWebContents(web_contents); 88 registry->enabled_extensions().GetByID(owner_extension_id);
76 if (guest) {
77 std::string owner_extension_id = guest->owner_host();
78 const Extension* owner_extension =
79 registry->enabled_extensions().GetByID(owner_extension_id);
80 89
81 std::string partition_domain, partition_id; 90 std::string partition_domain, partition_id;
Devlin 2017/04/28 22:13:02 one variable per line
ncarter (slow) 2017/05/01 21:50:37 Done.
82 bool in_memory; 91 bool in_memory;
Devlin 2017/04/28 22:13:02 initialize
ncarter (slow) 2017/05/01 21:50:37 Done.
83 std::string resource_path = url.path(); 92 bool is_guest = WebViewGuest::GetGuestPartitionConfigForSite(
84 bool is_guest = WebViewGuest::GetGuestPartitionConfigForSite( 93 navigation_handle()->GetStartingSiteInstance()->GetSiteURL(),
85 navigation_handle()->GetStartingSiteInstance()->GetSiteURL(), 94 &partition_domain, &partition_id, &in_memory);
86 &partition_domain, &partition_id, &in_memory);
87 95
88 bool allowed = true; 96 bool allowed = true;
89 url_request_util::AllowCrossRendererResourceLoadHelper( 97 url_request_util::AllowCrossRendererResourceLoadHelper(
90 is_guest, extension, owner_extension, partition_id, resource_path, 98 is_guest, target_extension, owner_extension, partition_id, url.path(),
91 navigation_handle()->GetPageTransition(), &allowed); 99 navigation_handle()->GetPageTransition(), &allowed);
92 if (!allowed) 100 if (!allowed)
93 return content::NavigationThrottle::BLOCK_REQUEST; 101 return content::NavigationThrottle::BLOCK_REQUEST;
94 }
95 } 102 }
96 103
97 return content::NavigationThrottle::PROCEED; 104 return content::NavigationThrottle::PROCEED;
98 } 105 }
99 106
100 // Now enforce web_accessible_resources for navigations. Top-level navigations 107 // This is a subframe navigation to a |target_extension| resource.
101 // should always be allowed. 108 // Enforce the web_accessible_resources restriction.
109 content::RenderFrameHost* parent = web_contents->FindFrameByFrameTreeNodeId(
110 navigation_handle()->GetParentFrameTreeNodeId());
102 111
103 // If the navigation is not to a chrome-extension:// URL, no need to perform 112 // Look to see if all ancestors belong to |target_extension|. If not,
104 // any more checks. 113 // then the web_accessible_resource restriction applies.
105 if (!url.SchemeIs(extensions::kExtensionScheme)) 114 bool external_ancestor = false;
106 return content::NavigationThrottle::PROCEED; 115 for (auto* ancestor = parent; ancestor; ancestor = ancestor->GetParent()) {
116 // Look for a match on the last committed origin. This handles the
117 // common case, and the about:blank case.
118 if (ancestor->GetLastCommittedOrigin().IsSameOriginWith(target_origin))
119 continue;
120 // Look for an origin match with the last committed URL. This handles the
121 // case of sandboxed extension resources.
Devlin 2017/04/28 22:13:02 Can you expand on this a bit to include briefly wh
ncarter (slow) 2017/05/01 21:50:37 Done.
122 if (url::Origin(ancestor->GetLastCommittedURL()) == target_origin)
123 continue;
124 // Ignore DevTools, as it is allowed to embed extension pages.
125 if (ancestor->GetLastCommittedURL().SchemeIs(
126 content::kChromeDevToolsScheme))
127 continue;
107 128
108 // The subframe which is navigated needs to have all of its ancestors be 129 // Otherwise, we have an external ancestor.
109 // at the same origin, otherwise the resource needs to be explicitly listed 130 external_ancestor = true;
110 // in web_accessible_resources. 131 break;
111 // Since the RenderFrameHost is not known until navigation has committed,
112 // we can't get it from NavigationHandle. However, this code only cares about
113 // the ancestor chain, so find the current RenderFrameHost and use it to
114 // traverse up to the main frame.
115 content::RenderFrameHost* navigating_frame = nullptr;
116 for (auto* frame : web_contents->GetAllFrames()) {
117 if (frame->GetFrameTreeNodeId() ==
118 navigation_handle()->GetFrameTreeNodeId()) {
119 navigating_frame = frame;
120 break;
121 }
122 }
123 DCHECK(navigating_frame);
124
125 // Traverse the chain of parent frames, checking if they are the same origin
126 // as the URL of this navigation.
127 content::RenderFrameHost* ancestor = navigating_frame->GetParent();
128 bool external_ancestor = false;
129 while (ancestor) {
130 if (ancestor->GetLastCommittedURL().GetOrigin() != url.GetOrigin()) {
131 // Ignore DevTools, as it is allowed to embed extension pages.
132 if (!ancestor->GetLastCommittedURL().SchemeIs(
133 content::kChromeDevToolsScheme)) {
134 external_ancestor = true;
135 break;
136 }
137 }
138 ancestor = ancestor->GetParent();
139 } 132 }
140 133
141 if (!external_ancestor) 134 if (external_ancestor) {
142 return content::NavigationThrottle::PROCEED; 135 // Cancel navigations to nested URLs, to match the main frame behavior.
136 if (!url_has_extension_scheme)
137 return content::NavigationThrottle::CANCEL;
143 138
144 // Since there was at least one origin different than the navigation URL, 139 // |url| must be in the manifest's "web_accessible_resources" section.
145 // explicitly check for the resource in web_accessible_resources. 140 if (!WebAccessibleResourcesInfo::IsResourceWebAccessible(target_extension,
146 std::string resource_path = url.path(); 141 url.path()))
147 if (!registry) 142 return content::NavigationThrottle::BLOCK_REQUEST;
148 return content::NavigationThrottle::BLOCK_REQUEST;
149
150 const extensions::Extension* extension =
151 registry->enabled_extensions().GetByID(url.host());
152 if (!extension)
153 return content::NavigationThrottle::BLOCK_REQUEST;
154
155 if (WebAccessibleResourcesInfo::IsResourceWebAccessible(extension,
156 resource_path)) {
157 return content::NavigationThrottle::PROCEED;
158 } 143 }
159 144
160 return content::NavigationThrottle::BLOCK_REQUEST; 145 return content::NavigationThrottle::PROCEED;
161 } 146 }
162 147
163 } // namespace extensions 148 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/process_manager_browsertest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698