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

Side by Side Diff: chrome/browser/extensions/extension_protocols.cc

Issue 12457042: Non-web-accessible extension URLs should not load in non-extension processes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 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 | Annotate | Revision Log
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/browser/extensions/extension_protocols.h" 5 #include "chrome/browser/extensions/extension_protocols.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/weak_ptr.h" 12 #include "base/memory/weak_ptr.h"
13 #include "base/message_loop.h" 13 #include "base/message_loop.h"
14 #include "base/path_service.h" 14 #include "base/path_service.h"
15 #include "base/string_util.h" 15 #include "base/string_util.h"
16 #include "base/stringprintf.h" 16 #include "base/stringprintf.h"
17 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
18 #include "base/threading/worker_pool.h" 18 #include "base/threading/worker_pool.h"
19 #include "build/build_config.h" 19 #include "build/build_config.h"
20 #include "chrome/browser/extensions/extension_info_map.h" 20 #include "chrome/browser/extensions/extension_info_map.h"
21 #include "chrome/browser/extensions/image_loader.h" 21 #include "chrome/browser/extensions/image_loader.h"
22 #include "chrome/common/chrome_paths.h" 22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/extensions/api/icons/icons_handler.h" 23 #include "chrome/common/extensions/api/icons/icons_handler.h"
24 #include "chrome/common/extensions/background_info.h" 24 #include "chrome/common/extensions/background_info.h"
25 #include "chrome/common/extensions/extension.h" 25 #include "chrome/common/extensions/extension.h"
26 #include "chrome/common/extensions/extension_file_util.h" 26 #include "chrome/common/extensions/extension_file_util.h"
27 #include "chrome/common/extensions/incognito_handler.h" 27 #include "chrome/common/extensions/incognito_handler.h"
28 #include "chrome/common/extensions/manifest_url_handler.h"
28 #include "chrome/common/extensions/web_accessible_resources_handler.h" 29 #include "chrome/common/extensions/web_accessible_resources_handler.h"
29 #include "chrome/common/url_constants.h" 30 #include "chrome/common/url_constants.h"
30 #include "content/public/browser/resource_request_info.h" 31 #include "content/public/browser/resource_request_info.h"
31 #include "extensions/common/constants.h" 32 #include "extensions/common/constants.h"
32 #include "extensions/common/extension_resource.h" 33 #include "extensions/common/extension_resource.h"
33 #include "googleurl/src/url_util.h" 34 #include "googleurl/src/url_util.h"
34 #include "grit/component_extension_resources_map.h" 35 #include "grit/component_extension_resources_map.h"
35 #include "net/base/mime_util.h" 36 #include "net/base/mime_util.h"
36 #include "net/base/net_errors.h" 37 #include "net/base/net_errors.h"
37 #include "net/http/http_response_headers.h" 38 #include "net/http/http_response_headers.h"
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 } 263 }
263 264
264 return true; 265 return true;
265 } 266 }
266 267
267 // Returns true if an chrome-extension:// resource should be allowed to load. 268 // Returns true if an chrome-extension:// resource should be allowed to load.
268 // TODO(aa): This should be moved into ExtensionResourceRequestPolicy, but we 269 // TODO(aa): This should be moved into ExtensionResourceRequestPolicy, but we
269 // first need to find a way to get CanLoadInIncognito state into the renderers. 270 // first need to find a way to get CanLoadInIncognito state into the renderers.
270 bool AllowExtensionResourceLoad(net::URLRequest* request, 271 bool AllowExtensionResourceLoad(net::URLRequest* request,
271 bool is_incognito, 272 bool is_incognito,
273 const Extension* extension,
272 ExtensionInfoMap* extension_info_map) { 274 ExtensionInfoMap* extension_info_map) {
273 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); 275 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
274 276
275 // We have seen crashes where info is NULL: crbug.com/52374. 277 // We have seen crashes where info is NULL: crbug.com/52374.
276 if (!info) { 278 if (!info) {
277 LOG(ERROR) << "Allowing load of " << request->url().spec() 279 LOG(ERROR) << "Allowing load of " << request->url().spec()
278 << "from unknown origin. Could not find user data for " 280 << "from unknown origin. Could not find user data for "
279 << "request."; 281 << "request.";
280 return true; 282 return true;
281 } 283 }
282 284
283 if (is_incognito && !ExtensionCanLoadInIncognito(info, request->url().host(), 285 if (is_incognito && !ExtensionCanLoadInIncognito(info, request->url().host(),
284 extension_info_map)) { 286 extension_info_map)) {
285 return false; 287 return false;
286 } 288 }
287 289
290 // The following checks are meant to replicate similar set of checks in the
291 // renderer process, performed by ResourceRequestPolicy::CanRequestResource.
292 // These are not exactly equivalent, because we don't have the same bits of
293 // information. The two checks need to be kept in sync as much as possible, as
294 // an exploited renderer can bypass the checks in ResourceRequestPolicy.
295
296 // Check if the extension for which this request is made is indeed loaded in
297 // the process sending the request. If not, we need to explicitly check if
298 // the resource is explicitly accessible or fits in a set of exception cases.
299 // Note: This allows a case where two extensions execute in the same renderer
300 // process to request each other's resources. We can't do more precise check,
301 // since the renderer can lie which extension has made the request.
302 if (extension_info_map->process_map().Contains(
303 request->url().host(), info->GetChildID())) {
304 return true;
305 }
306
307 if (!content::PageTransitionIsWebTriggerable(info->GetPageTransition()))
308 return false;
309
310 // The following checks require that we have an actual extension object. If we
311 // don't have it, allow the request handling to continue with the rest of the
312 // checks.
313 if (!extension)
314 return true;
315
316 // Disallow loading of packaged resources for hosted apps. We don't allow
317 // hybrid hosted/packaged apps. The one exception is access to icons, since
318 // some extensions want to be able to do things like create their own
319 // launchers.
320 std::string resource_root_relative_path =
321 request->url().path().empty() ? "" : request->url().path().substr(1);
322 if (extension->is_hosted_app() &&
323 !extensions::IconsInfo::GetIcons(extension)
324 .ContainsPath(resource_root_relative_path)) {
325 LOG(ERROR) << "Denying load of " << request->url().spec() << " from "
326 << "hosted app.";
327 return false;
328 }
329
330 // Extensions with web_accessible_resources, allow loading by regular
331 // renderers. Since not all subresources are required to be listed in a v2
332 // manifest, we must allow all loads if there are any web accessible
333 // resources. See http://crbug.com/179127.
334 if (extensions::WebAccessibleResourcesInfo::HasWebAccessibleResources(
Matt Perry 2013/03/27 23:53:00 This will break extensions written before web_acce
nasko 2013/04/02 18:25:16 Done.
335 extension)) {
336 return true;
337 }
338
339 // If there aren't any explicitly marked web accessible resources, the
340 // load should be allowed only if it is by DevTools. A close approximation is
341 // checking if the extension contains DevTools page.
342 if (extensions::ManifestURL::GetDevToolsPage(extension).is_empty()) {
343 return false;
344 }
345
288 return true; 346 return true;
289 } 347 }
290 348
291 // Returns true if the given URL references an icon in the given extension. 349 // Returns true if the given URL references an icon in the given extension.
292 bool URLIsForExtensionIcon(const GURL& url, const Extension* extension) { 350 bool URLIsForExtensionIcon(const GURL& url, const Extension* extension) {
293 DCHECK(url.SchemeIs(extensions::kExtensionScheme)); 351 DCHECK(url.SchemeIs(extensions::kExtensionScheme));
294 352
295 if (!extension) 353 if (!extension)
296 return false; 354 return false;
297 355
(...skipping 21 matching lines...) Expand all
319 private: 377 private:
320 const bool is_incognito_; 378 const bool is_incognito_;
321 ExtensionInfoMap* const extension_info_map_; 379 ExtensionInfoMap* const extension_info_map_;
322 DISALLOW_COPY_AND_ASSIGN(ExtensionProtocolHandler); 380 DISALLOW_COPY_AND_ASSIGN(ExtensionProtocolHandler);
323 }; 381 };
324 382
325 // Creates URLRequestJobs for extension:// URLs. 383 // Creates URLRequestJobs for extension:// URLs.
326 net::URLRequestJob* 384 net::URLRequestJob*
327 ExtensionProtocolHandler::MaybeCreateJob( 385 ExtensionProtocolHandler::MaybeCreateJob(
328 net::URLRequest* request, net::NetworkDelegate* network_delegate) const { 386 net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
387 // chrome-extension://extension-id/resource/path.js
388 const std::string& extension_id = request->url().host();
389 const Extension* extension =
390 extension_info_map_->extensions().GetByID(extension_id);
391
329 // TODO(mpcomplete): better error code. 392 // TODO(mpcomplete): better error code.
330 if (!AllowExtensionResourceLoad( 393 if (!AllowExtensionResourceLoad(
331 request, is_incognito_, extension_info_map_)) { 394 request, is_incognito_, extension, extension_info_map_)) {
332 return new net::URLRequestErrorJob( 395 return new net::URLRequestErrorJob(
333 request, network_delegate, net::ERR_ADDRESS_UNREACHABLE); 396 request, network_delegate, net::ERR_ADDRESS_UNREACHABLE);
334 } 397 }
335 398
336 // chrome-extension://extension-id/resource/path.js
337 const std::string& extension_id = request->url().host();
338 const Extension* extension =
339 extension_info_map_->extensions().GetByID(extension_id);
340 base::FilePath directory_path; 399 base::FilePath directory_path;
341 if (extension) 400 if (extension)
342 directory_path = extension->path(); 401 directory_path = extension->path();
343 if (directory_path.value().empty()) { 402 if (directory_path.value().empty()) {
344 const Extension* disabled_extension = 403 const Extension* disabled_extension =
345 extension_info_map_->disabled_extensions().GetByID(extension_id); 404 extension_info_map_->disabled_extensions().GetByID(extension_id);
346 if (URLIsForExtensionIcon(request->url(), disabled_extension)) 405 if (URLIsForExtensionIcon(request->url(), disabled_extension))
347 directory_path = disabled_extension->path(); 406 directory_path = disabled_extension->path();
348 if (directory_path.value().empty()) { 407 if (directory_path.value().empty()) {
349 LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id; 408 LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 send_cors_header); 466 send_cors_header);
408 } 467 }
409 468
410 } // namespace 469 } // namespace
411 470
412 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( 471 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler(
413 bool is_incognito, 472 bool is_incognito,
414 ExtensionInfoMap* extension_info_map) { 473 ExtensionInfoMap* extension_info_map) {
415 return new ExtensionProtocolHandler(is_incognito, extension_info_map); 474 return new ExtensionProtocolHandler(is_incognito, extension_info_map);
416 } 475 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698