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

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

Issue 2958343002: [Extensions] Change renderer-side web accessible resource determination (Closed)
Patch Set: . 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::OnExtensionAdded(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 (extension.is_hosted_app() && !IconsInfo::GetIcons(&extension).empty())) {
nasko 2017/06/30 18:08:10 I see this call scattered a few places already. Sh
Devlin 2017/07/06 00:40:39 Most places check a specific path to see if it's r
47 web_accessible_ids_.insert(extension.id());
48 }
49 }
50
51 void ResourceRequestPolicy::OnExtensionRemoved(
52 const ExtensionId& extension_id) {
53 web_accessible_ids_.erase(extension_id);
54 }
33 55
34 // This method does a security check whether chrome-extension:// URLs can be 56 // 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 57 // 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. 58 // 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 59 // If you are changing this function, ensure equivalent checks are added to
38 // extension_protocols.cc's AllowExtensionResourceLoad. 60 // extension_protocols.cc's AllowExtensionResourceLoad.
39 bool ResourceRequestPolicy::CanRequestResource( 61 bool ResourceRequestPolicy::CanRequestResource(
40 const GURL& resource_url, 62 const GURL& resource_url,
41 blink::WebLocalFrame* frame, 63 blink::WebLocalFrame* frame,
42 ui::PageTransition transition_type) { 64 ui::PageTransition transition_type) {
43 CHECK(resource_url.SchemeIs(kExtensionScheme)); 65 CHECK(resource_url.SchemeIs(kExtensionScheme));
44 66
45 const Extension* extension = 67 GURL frame_url = frame->GetDocument().Url();
46 RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(resource_url); 68
47 if (!extension) { 69 // 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 70 // but this is ok for the checks below. We only care if it matches the
49 // 404 from the browser process. 71 // current extension or has a devtools scheme.
72 GURL page_origin = url::Origin(frame->Top()->GetSecurityOrigin()).GetURL();
nasko 2017/06/30 18:08:09 Ok, I realize this is move only operation here. Ho
Devlin 2017/07/06 00:40:38 Yes, we probably should. I tried this (see PS4),
alexmos 2017/07/06 18:20:06 (Pitching in here since Nasko's OOO for a while)
Devlin 2017/07/06 19:14:56 Acknowledged; will leave the TODO and submit as-is
73
74 GURL extension_origin = resource_url.GetOrigin();
75
76 // We always allow loads in the following cases, regardless of web accessible
77 // resources:
78
79 // Empty origin (needed for some edge cases when we have empty origins).
nasko 2017/06/30 18:08:09 Empty origins or empty URLs?
Devlin 2017/07/06 00:40:39 This was copy-pasted, but code implies url, so cha
80 if (frame_url.is_empty())
81 return true;
nasko 2017/06/30 18:08:09 In general, if you want timing neutral code, early
Devlin 2017/07/06 00:40:38 Except if we return true, it's because the navigat
82
83 // Extensions requesting their own resources (frame_url check is for images,
84 // page_url check is for iframes)
85 if (frame_url.GetOrigin() == extension_origin ||
alexmos 2017/06/30 21:10:17 I know you're not changing this logic... but why d
Devlin 2017/07/06 00:40:38 Sorry, you lost me at the sandboxed frame part - c
alexmos 2017/07/06 18:20:06 If a frame is sandboxed via <iframe sandbox>, the
Devlin 2017/07/06 19:14:56 Thanks for the explanation! I've expanded the TOD
86 page_origin == extension_origin) {
50 return true; 87 return true;
51 } 88 }
52 89
90 if (!ui::PageTransitionIsWebTriggerable(transition_type))
91 return true;
92
93 // Unreachable web page error page (to allow showing the icon of the
94 // unreachable app on this page).
95 if (frame_url == content::kUnreachableWebDataURL)
96 return true;
97
98 bool is_dev_tools = page_origin.SchemeIs(content::kChromeDevToolsScheme);
99 if (!is_dev_tools && !web_accessible_ids_.count(extension_origin.host())) {
alexmos 2017/06/30 21:10:17 nit: no { needed
alexmos 2017/06/30 21:10:18 Maybe add a comment about why you needed to add th
Devlin 2017/07/06 00:40:38 Done.
Devlin 2017/07/06 00:40:39 Done.
alexmos 2017/07/06 18:20:06 Was it added somewhere where I missed it? :) I wa
Devlin 2017/07/06 19:14:56 Whoops - it *was* added (https://codereview.chromi
100 return false;
alexmos 2017/06/30 21:10:18 Just to clarify: does this help for an extension t
Devlin 2017/07/06 00:40:39 If an extension has a web accessible resource, it
alexmos 2017/07/06 18:20:06 Acknowledged.
101 }
102
103 const Extension* extension =
104 RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(resource_url);
105 DCHECK(extension);
alexmos 2017/06/30 21:10:17 I'm curious if it's possible to hit this when |is_
Devlin 2017/07/06 00:40:38 Umm... I'd hope not, but I'm not 100% sure. I've
alexmos 2017/07/06 18:20:06 Acknowledged.
106
107 // Devtools (chrome-extension:// URLs are loaded into frames of devtools to
108 // support the devtools extension APIs).
109 if (is_dev_tools &&
110 !chrome_manifest_urls::GetDevToolsPage(extension).is_empty()) {
111 return true;
112 }
113
53 // Disallow loading of packaged resources for hosted apps. We don't allow 114 // 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 115 // 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 116 // some extensions want to be able to do things like create their own
56 // launchers. 117 // launchers.
57 base::StringPiece resource_root_relative_path = 118 base::StringPiece resource_root_relative_path =
58 resource_url.path_piece().empty() ? base::StringPiece() 119 resource_url.path_piece().empty() ? base::StringPiece()
59 : resource_url.path_piece().substr(1); 120 : resource_url.path_piece().substr(1);
60 if (extension->is_hosted_app() && 121 if (extension->is_hosted_app() &&
61 !IconsInfo::GetIcons(extension) 122 !IconsInfo::GetIcons(extension)
62 .ContainsPath(resource_root_relative_path)) { 123 .ContainsPath(resource_root_relative_path)) {
63 LOG(ERROR) << "Denying load of " << resource_url.spec() << " from " 124 LOG(ERROR) << "Denying load of " << resource_url.spec() << " from "
64 << "hosted app."; 125 << "hosted app.";
65 return false; 126 return false;
66 } 127 }
67 128
68 // Disallow loading of extension resources which are not explicitly listed 129 // Disallow loading of extension resources which are not explicitly listed
69 // as web or WebView accessible if the manifest version is 2 or greater. 130 // as web or WebView accessible if the manifest version is 2 or greater.
70 if (!WebAccessibleResourcesInfo::IsResourceWebAccessible( 131 if (!WebAccessibleResourcesInfo::IsResourceWebAccessible(
71 extension, resource_url.path()) && 132 extension, resource_url.path()) &&
72 !WebviewInfo::IsResourceWebviewAccessible( 133 !WebviewInfo::IsResourceWebviewAccessible(
73 extension, dispatcher_->webview_partition_id(), 134 extension, dispatcher_->webview_partition_id(),
74 resource_url.path())) { 135 resource_url.path())) {
75 GURL frame_url = frame->GetDocument().Url(); 136 std::string message = base::StringPrintf(
76 137 "Denying load of %s. Resources must be listed in the "
77 // The page_origin may be GURL("null") for unique origins like data URLs, 138 "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 139 "pages outside the extension.",
79 // current extension or has a devtools scheme. 140 resource_url.spec().c_str());
80 GURL page_origin = url::Origin(frame->Top()->GetSecurityOrigin()).GetURL(); 141 frame->AddMessageToConsole(
81 142 blink::WebConsoleMessage(blink::WebConsoleMessage::kLevelError,
82 // Exceptions are: 143 blink::WebString::FromUTF8(message)));
83 // - empty origin (needed for some edge cases when we have empty origins) 144 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 } 145 }
113 146
114 return true; 147 return true;
115 } 148 }
116 149
117 } // namespace extensions 150 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698