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

Side by Side Diff: chrome/renderer/extensions/resource_request_policy.cc

Issue 2958343002: [Extensions] Change renderer-side web accessible resource determination (Closed)
Patch Set: Expand comments Created 3 years, 5 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/renderer/extensions/resource_request_policy.h" 5 #include "chrome/renderer/extensions/resource_request_policy.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h" 8 #include "base/strings/stringprintf.h"
9 #include "chrome/common/extensions/chrome_manifest_url_handlers.h" 9 #include "chrome/common/extensions/chrome_manifest_url_handlers.h"
10 #include "chrome/common/url_constants.h" 10 #include "chrome/common/url_constants.h"
(...skipping 12 matching lines...) Expand all
23 #include "third_party/WebKit/public/web/WebDocument.h" 23 #include "third_party/WebKit/public/web/WebDocument.h"
24 #include "third_party/WebKit/public/web/WebLocalFrame.h" 24 #include "third_party/WebKit/public/web/WebLocalFrame.h"
25 #include "ui/base/page_transition_types.h" 25 #include "ui/base/page_transition_types.h"
26 #include "url/gurl.h" 26 #include "url/gurl.h"
27 #include "url/origin.h" 27 #include "url/origin.h"
28 28
29 namespace extensions { 29 namespace extensions {
30 30
31 ResourceRequestPolicy::ResourceRequestPolicy(Dispatcher* dispatcher) 31 ResourceRequestPolicy::ResourceRequestPolicy(Dispatcher* dispatcher)
32 : dispatcher_(dispatcher) {} 32 : dispatcher_(dispatcher) {}
33 ResourceRequestPolicy::~ResourceRequestPolicy() = default;
34
35 void ResourceRequestPolicy::OnExtensionLoaded(const Extension& extension) {
36 if (WebAccessibleResourcesInfo::HasWebAccessibleResources(&extension) ||
37 // Extensions below manifest version 2 had all resources accessible by
38 // default.
39 // TODO(devlin): Two things - first, we might not have any v1 extensions
40 // anymore; second, this should maybe be included in
41 // HasWebAccessibleResources().
42 extension.manifest_version() < 2 ||
43 WebviewInfo::HasWebviewAccessibleResources(
44 extension, dispatcher_->webview_partition_id()) ||
45 // Hosted app icons are accessible.
46 // TODO(devlin): Should we incorporate this into
47 // WebAccessibleResourcesInfo?
48 (extension.is_hosted_app() && !IconsInfo::GetIcons(&extension).empty())) {
49 web_accessible_ids_.insert(extension.id());
50 }
51 }
52
53 void ResourceRequestPolicy::OnExtensionUnloaded(
54 const ExtensionId& extension_id) {
55 web_accessible_ids_.erase(extension_id);
56 }
33 57
34 // This method does a security check whether chrome-extension:// URLs can be 58 // This method does a security check whether chrome-extension:// URLs can be
35 // requested by the renderer. Since this is in an untrusted process, the browser 59 // requested by the renderer. Since this is in an untrusted process, the browser
36 // has a similar check to enforce the policy, in case this process is exploited. 60 // has a similar check to enforce the policy, in case this process is exploited.
37 // If you are changing this function, ensure equivalent checks are added to 61 // If you are changing this function, ensure equivalent checks are added to
38 // extension_protocols.cc's AllowExtensionResourceLoad. 62 // extension_protocols.cc's AllowExtensionResourceLoad.
39 bool ResourceRequestPolicy::CanRequestResource( 63 bool ResourceRequestPolicy::CanRequestResource(
40 const GURL& resource_url, 64 const GURL& resource_url,
41 blink::WebLocalFrame* frame, 65 blink::WebLocalFrame* frame,
42 ui::PageTransition transition_type) { 66 ui::PageTransition transition_type) {
43 CHECK(resource_url.SchemeIs(kExtensionScheme)); 67 CHECK(resource_url.SchemeIs(kExtensionScheme));
44 68
45 const Extension* extension = 69 GURL frame_url = frame->GetDocument().Url();
46 RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(resource_url); 70
47 if (!extension) { 71 // The page_origin may be GURL("null") for unique origins like data URLs,
48 // Allow the load in the case of a non-existent extension. We'll just get a 72 // but this is ok for the checks below. We only care if it matches the
49 // 404 from the browser process. 73 // current extension or has a devtools scheme.
74 GURL page_origin = url::Origin(frame->Top()->GetSecurityOrigin()).GetURL();
75
76 GURL extension_origin = resource_url.GetOrigin();
77
78 // We always allow loads in the following cases, regardless of web accessible
79 // resources:
80
81 // Empty urls (needed for some edge cases when we have empty urls).
82 if (frame_url.is_empty())
83 return true;
84
85 // Extensions requesting their own resources (frame_url check is for images,
86 // page_url check is for iframes).
87 // TODO(devlin): We should be checking the ancestor chain, not just the
88 // top-level frame. Additionally, we should be checking the security origin
89 // of the frame, to account for about:blank subframes being scripted by an
90 // extension parent (though we'll still need the frame origin check for
91 // sandboxed frames).
92 if (frame_url.GetOrigin() == extension_origin ||
93 page_origin == extension_origin) {
50 return true; 94 return true;
51 } 95 }
52 96
97 if (!ui::PageTransitionIsWebTriggerable(transition_type))
98 return true;
99
100 // Unreachable web page error page (to allow showing the icon of the
101 // unreachable app on this page).
102 if (frame_url == content::kUnreachableWebDataURL)
103 return true;
104
105 bool is_dev_tools = page_origin.SchemeIs(content::kChromeDevToolsScheme);
106 // Note: we check web_accessible_ids (rather than first looking up the
lazyboy 2017/07/10 22:36:39 nit: |web_accessible_ids_| I'd also expand this c
Devlin 2017/07/10 22:52:30 Done.
107 // extension in the registry and checking that) to be more resistant against
108 // timing attacks.
109 if (!is_dev_tools && !web_accessible_ids_.count(extension_origin.host()))
110 return false;
lazyboy 2017/07/10 22:36:39 This used to show "Denying load of ... " message b
Devlin 2017/07/10 22:52:30 It may have in some situations been useful, but ad
111
112 const Extension* extension =
113 RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(resource_url);
114 if (is_dev_tools && !extension) {
lazyboy 2017/07/10 22:36:39 Can you fold this and if in line 124: if (is_dev_
Devlin 2017/07/10 22:52:30 Done. That is a bit cleaner; thanks!
115 // Allow the load in the case of a non-existent extension. We'll just get a
116 // 404 from the browser process.
117 // TODO(devlin): Can this happen? Does devtools potentially make requests
118 // to non-existent extensions?
119 return true;
120 }
121
122 // Devtools (chrome-extension:// URLs are loaded into frames of devtools to
123 // support the devtools extension APIs).
124 if (is_dev_tools &&
125 !chrome_manifest_urls::GetDevToolsPage(extension).is_empty()) {
126 return true;
127 }
128
53 // Disallow loading of packaged resources for hosted apps. We don't allow 129 // Disallow loading of packaged resources for hosted apps. We don't allow
54 // hybrid hosted/packaged apps. The one exception is access to icons, since 130 // hybrid hosted/packaged apps. The one exception is access to icons, since
55 // some extensions want to be able to do things like create their own 131 // some extensions want to be able to do things like create their own
56 // launchers. 132 // launchers.
57 base::StringPiece resource_root_relative_path = 133 base::StringPiece resource_root_relative_path =
58 resource_url.path_piece().empty() ? base::StringPiece() 134 resource_url.path_piece().empty() ? base::StringPiece()
59 : resource_url.path_piece().substr(1); 135 : resource_url.path_piece().substr(1);
60 if (extension->is_hosted_app() && 136 if (extension->is_hosted_app() &&
61 !IconsInfo::GetIcons(extension) 137 !IconsInfo::GetIcons(extension)
62 .ContainsPath(resource_root_relative_path)) { 138 .ContainsPath(resource_root_relative_path)) {
63 LOG(ERROR) << "Denying load of " << resource_url.spec() << " from " 139 LOG(ERROR) << "Denying load of " << resource_url.spec() << " from "
64 << "hosted app."; 140 << "hosted app.";
65 return false; 141 return false;
66 } 142 }
67 143
68 // Disallow loading of extension resources which are not explicitly listed 144 // Disallow loading of extension resources which are not explicitly listed
69 // as web or WebView accessible if the manifest version is 2 or greater. 145 // as web or WebView accessible if the manifest version is 2 or greater.
70 if (!WebAccessibleResourcesInfo::IsResourceWebAccessible( 146 if (!WebAccessibleResourcesInfo::IsResourceWebAccessible(
71 extension, resource_url.path()) && 147 extension, resource_url.path()) &&
72 !WebviewInfo::IsResourceWebviewAccessible( 148 !WebviewInfo::IsResourceWebviewAccessible(
73 extension, dispatcher_->webview_partition_id(), 149 extension, dispatcher_->webview_partition_id(),
74 resource_url.path())) { 150 resource_url.path())) {
75 GURL frame_url = frame->GetDocument().Url(); 151 std::string message = base::StringPrintf(
76 152 "Denying load of %s. Resources must be listed in the "
77 // The page_origin may be GURL("null") for unique origins like data URLs, 153 "web_accessible_resources manifest key in order to be loaded by "
78 // but this is ok for the checks below. We only care if it matches the 154 "pages outside the extension.",
79 // current extension or has a devtools scheme. 155 resource_url.spec().c_str());
80 GURL page_origin = url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(); 156 frame->AddMessageToConsole(
81 157 blink::WebConsoleMessage(blink::WebConsoleMessage::kLevelError,
82 // Exceptions are: 158 blink::WebString::FromUTF8(message)));
83 // - empty origin (needed for some edge cases when we have empty origins) 159 return false;
84 bool is_empty_origin = frame_url.is_empty();
85 // - extensions requesting their own resources (frame_url check is for
86 // images, page_url check is for iframes)
87 bool is_own_resource = frame_url.GetOrigin() == extension->url() ||
88 page_origin == extension->url();
89 // - devtools (chrome-extension:// URLs are loaded into frames of devtools
90 // to support the devtools extension APIs)
91 bool is_dev_tools =
92 page_origin.SchemeIs(content::kChromeDevToolsScheme) &&
93 !chrome_manifest_urls::GetDevToolsPage(extension).is_empty();
94 bool transition_allowed =
95 !ui::PageTransitionIsWebTriggerable(transition_type);
96 // - unreachable web page error page (to allow showing the icon of the
97 // unreachable app on this page)
98 bool is_error_page = frame_url == content::kUnreachableWebDataURL;
99
100 if (!is_empty_origin && !is_own_resource &&
101 !is_dev_tools && !transition_allowed && !is_error_page) {
102 std::string message = base::StringPrintf(
103 "Denying load of %s. Resources must be listed in the "
104 "web_accessible_resources manifest key in order to be loaded by "
105 "pages outside the extension.",
106 resource_url.spec().c_str());
107 frame->AddMessageToConsole(
108 blink::WebConsoleMessage(blink::WebConsoleMessage::kLevelError,
109 blink::WebString::FromUTF8(message)));
110 return false;
111 }
112 } 160 }
113 161
114 return true; 162 return true;
115 } 163 }
116 164
117 } // namespace extensions 165 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/resource_request_policy.h ('k') | extensions/common/manifest_handlers/webview_info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698