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

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

Issue 229733002: Toro: Move ExtensionProtocolHandler to //extensions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: move file, cleanup (extension-protocols) Created 6 years, 8 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 "extensions/browser/extension_protocols.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
13 #include "base/format_macros.h" 13 #include "base/format_macros.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/weak_ptr.h" 15 #include "base/memory/weak_ptr.h"
16 #include "base/message_loop/message_loop.h" 16 #include "base/message_loop/message_loop.h"
17 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
18 #include "base/path_service.h" 18 #include "base/path_service.h"
19 #include "base/sha1.h" 19 #include "base/sha1.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h" 20 #include "base/strings/stringprintf.h"
23 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
24 #include "base/threading/sequenced_worker_pool.h" 22 #include "base/threading/sequenced_worker_pool.h"
25 #include "base/threading/thread_restrictions.h" 23 #include "base/threading/thread_restrictions.h"
26 #include "base/timer/elapsed_timer.h" 24 #include "base/timer/elapsed_timer.h"
27 #include "build/build_config.h" 25 #include "build/build_config.h"
28 #include "chrome/browser/extensions/extension_renderer_state.h"
29 #include "chrome/browser/extensions/image_loader.h"
30 #include "chrome/common/chrome_paths.h"
31 #include "chrome/common/extensions/manifest_url_handler.h"
32 #include "chrome/common/url_constants.h"
33 #include "content/public/browser/browser_thread.h" 26 #include "content/public/browser/browser_thread.h"
34 #include "content/public/browser/resource_request_info.h" 27 #include "content/public/browser/resource_request_info.h"
28 #include "extensions/browser/extensions_browser_client.h"
35 #include "extensions/browser/info_map.h" 29 #include "extensions/browser/info_map.h"
36 #include "extensions/common/constants.h" 30 #include "extensions/common/constants.h"
37 #include "extensions/common/extension.h" 31 #include "extensions/common/extension.h"
38 #include "extensions/common/extension_resource.h" 32 #include "extensions/common/extension_resource.h"
39 #include "extensions/common/file_util.h" 33 #include "extensions/common/file_util.h"
40 #include "extensions/common/manifest_handlers/background_info.h" 34 #include "extensions/common/manifest_handlers/background_info.h"
41 #include "extensions/common/manifest_handlers/csp_info.h" 35 #include "extensions/common/manifest_handlers/csp_info.h"
42 #include "extensions/common/manifest_handlers/icons_handler.h" 36 #include "extensions/common/manifest_handlers/icons_handler.h"
43 #include "extensions/common/manifest_handlers/incognito_info.h" 37 #include "extensions/common/manifest_handlers/incognito_info.h"
44 #include "extensions/common/manifest_handlers/shared_module_info.h" 38 #include "extensions/common/manifest_handlers/shared_module_info.h"
45 #include "extensions/common/manifest_handlers/web_accessible_resources_info.h" 39 #include "extensions/common/manifest_handlers/web_accessible_resources_info.h"
46 #include "extensions/common/manifest_handlers/webview_info.h"
47 #include "grit/component_extension_resources_map.h"
48 #include "net/base/mime_util.h"
49 #include "net/base/net_errors.h" 40 #include "net/base/net_errors.h"
50 #include "net/http/http_request_headers.h" 41 #include "net/http/http_request_headers.h"
51 #include "net/http/http_response_headers.h" 42 #include "net/http/http_response_headers.h"
52 #include "net/http/http_response_info.h" 43 #include "net/http/http_response_info.h"
53 #include "net/url_request/url_request_error_job.h" 44 #include "net/url_request/url_request_error_job.h"
54 #include "net/url_request/url_request_file_job.h" 45 #include "net/url_request/url_request_file_job.h"
55 #include "net/url_request/url_request_simple_job.h" 46 #include "net/url_request/url_request_simple_job.h"
56 #include "ui/base/resource/resource_bundle.h"
57 #include "url/url_util.h" 47 #include "url/url_util.h"
58 48
59 using content::BrowserThread; 49 using content::BrowserThread;
60 using content::ResourceRequestInfo; 50 using content::ResourceRequestInfo;
61 using extensions::Extension; 51 using extensions::Extension;
62 using extensions::SharedModuleInfo; 52 using extensions::SharedModuleInfo;
63 53
54 namespace extensions {
64 namespace { 55 namespace {
65 56
66 net::HttpResponseHeaders* BuildHttpHeaders(
67 const std::string& content_security_policy, bool send_cors_header,
68 const base::Time& last_modified_time) {
69 std::string raw_headers;
70 raw_headers.append("HTTP/1.1 200 OK");
71 if (!content_security_policy.empty()) {
72 raw_headers.append(1, '\0');
73 raw_headers.append("Content-Security-Policy: ");
74 raw_headers.append(content_security_policy);
75 }
76
77 if (send_cors_header) {
78 raw_headers.append(1, '\0');
79 raw_headers.append("Access-Control-Allow-Origin: *");
80 }
81
82 if (!last_modified_time.is_null()) {
83 // Hash the time and make an etag to avoid exposing the exact
84 // user installation time of the extension.
85 std::string hash = base::StringPrintf("%" PRId64,
86 last_modified_time.ToInternalValue());
87 hash = base::SHA1HashString(hash);
88 std::string etag;
89 base::Base64Encode(hash, &etag);
90 raw_headers.append(1, '\0');
91 raw_headers.append("ETag: \"");
92 raw_headers.append(etag);
93 raw_headers.append("\"");
94 // Also force revalidation.
95 raw_headers.append(1, '\0');
96 raw_headers.append("cache-control: no-cache");
97 }
98
99 raw_headers.append(2, '\0');
100 return new net::HttpResponseHeaders(raw_headers);
101 }
102
103 class URLRequestResourceBundleJob : public net::URLRequestSimpleJob {
104 public:
105 URLRequestResourceBundleJob(net::URLRequest* request,
106 net::NetworkDelegate* network_delegate,
107 const base::FilePath& filename,
108 int resource_id,
109 const std::string& content_security_policy,
110 bool send_cors_header)
111 : net::URLRequestSimpleJob(request, network_delegate),
112 filename_(filename),
113 resource_id_(resource_id),
114 weak_factory_(this) {
115 // Leave cache headers out of resource bundle requests.
116 response_info_.headers = BuildHttpHeaders(content_security_policy,
117 send_cors_header,
118 base::Time());
119 }
120
121 // Overridden from URLRequestSimpleJob:
122 virtual int GetData(std::string* mime_type,
123 std::string* charset,
124 std::string* data,
125 const net::CompletionCallback& callback) const OVERRIDE {
126 const ResourceBundle& rb = ResourceBundle::GetSharedInstance();
127 *data = rb.GetRawDataResource(resource_id_).as_string();
128
129 // Add the Content-Length header now that we know the resource length.
130 response_info_.headers->AddHeader(base::StringPrintf(
131 "%s: %s", net::HttpRequestHeaders::kContentLength,
132 base::UintToString(data->size()).c_str()));
133
134 std::string* read_mime_type = new std::string;
135 bool posted = base::PostTaskAndReplyWithResult(
136 BrowserThread::GetBlockingPool(),
137 FROM_HERE,
138 base::Bind(&net::GetMimeTypeFromFile, filename_,
139 base::Unretained(read_mime_type)),
140 base::Bind(&URLRequestResourceBundleJob::OnMimeTypeRead,
141 weak_factory_.GetWeakPtr(),
142 mime_type, charset, data,
143 base::Owned(read_mime_type),
144 callback));
145 DCHECK(posted);
146
147 return net::ERR_IO_PENDING;
148 }
149
150 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE {
151 *info = response_info_;
152 }
153
154 private:
155 virtual ~URLRequestResourceBundleJob() { }
156
157 void OnMimeTypeRead(std::string* out_mime_type,
158 std::string* charset,
159 std::string* data,
160 std::string* read_mime_type,
161 const net::CompletionCallback& callback,
162 bool read_result) {
163 *out_mime_type = *read_mime_type;
164 if (StartsWithASCII(*read_mime_type, "text/", false)) {
165 // All of our HTML files should be UTF-8 and for other resource types
166 // (like images), charset doesn't matter.
167 DCHECK(IsStringUTF8(*data));
168 *charset = "utf-8";
169 }
170 int result = read_result ? net::OK : net::ERR_INVALID_URL;
171 callback.Run(result);
172 }
173
174 // We need the filename of the resource to determine the mime type.
175 base::FilePath filename_;
176
177 // The resource bundle id to load.
178 int resource_id_;
179
180 net::HttpResponseInfo response_info_;
181
182 mutable base::WeakPtrFactory<URLRequestResourceBundleJob> weak_factory_;
183 };
184
185 class GeneratedBackgroundPageJob : public net::URLRequestSimpleJob { 57 class GeneratedBackgroundPageJob : public net::URLRequestSimpleJob {
186 public: 58 public:
187 GeneratedBackgroundPageJob(net::URLRequest* request, 59 GeneratedBackgroundPageJob(net::URLRequest* request,
188 net::NetworkDelegate* network_delegate, 60 net::NetworkDelegate* network_delegate,
189 const scoped_refptr<const Extension> extension, 61 const scoped_refptr<const Extension> extension,
190 const std::string& content_security_policy) 62 const std::string& content_security_policy)
191 : net::URLRequestSimpleJob(request, network_delegate), 63 : net::URLRequestSimpleJob(request, network_delegate),
192 extension_(extension) { 64 extension_(extension) {
193 const bool send_cors_headers = false; 65 const bool send_cors_headers = false;
194 // Leave cache headers out of generated background page jobs. 66 // Leave cache headers out of generated background page jobs.
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 if (info->GetResourceType() == ResourceType::MAIN_FRAME) { 226 if (info->GetResourceType() == ResourceType::MAIN_FRAME) {
355 const Extension* extension = 227 const Extension* extension =
356 extension_info_map->extensions().GetByID(extension_id); 228 extension_info_map->extensions().GetByID(extension_id);
357 return extension && extensions::IncognitoInfo::IsSplitMode(extension); 229 return extension && extensions::IncognitoInfo::IsSplitMode(extension);
358 } 230 }
359 231
360 return true; 232 return true;
361 } 233 }
362 234
363 // Returns true if an chrome-extension:// resource should be allowed to load. 235 // Returns true if an chrome-extension:// resource should be allowed to load.
236 // Pass true for |is_incognito| only for incognito profiles and not Chrome OS
237 // guest mode profiles.
364 // TODO(aa): This should be moved into ExtensionResourceRequestPolicy, but we 238 // TODO(aa): This should be moved into ExtensionResourceRequestPolicy, but we
365 // first need to find a way to get CanLoadInIncognito state into the renderers. 239 // first need to find a way to get CanLoadInIncognito state into the renderers.
366 bool AllowExtensionResourceLoad(net::URLRequest* request, 240 bool AllowExtensionResourceLoad(net::URLRequest* request,
367 Profile::ProfileType profile_type, 241 bool is_incognito,
368 const Extension* extension, 242 const Extension* extension,
369 extensions::InfoMap* extension_info_map) { 243 extensions::InfoMap* extension_info_map) {
370 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); 244 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
371 245
372 // We have seen crashes where info is NULL: crbug.com/52374. 246 // We have seen crashes where info is NULL: crbug.com/52374.
373 if (!info) { 247 if (!info) {
374 LOG(ERROR) << "Allowing load of " << request->url().spec() 248 LOG(ERROR) << "Allowing load of " << request->url().spec()
375 << "from unknown origin. Could not find user data for " 249 << "from unknown origin. Could not find user data for "
376 << "request."; 250 << "request.";
377 return true; 251 return true;
378 } 252 }
379 253
380 if (profile_type == Profile::INCOGNITO_PROFILE && 254 if (is_incognito && !ExtensionCanLoadInIncognito(
381 !ExtensionCanLoadInIncognito(info, request->url().host(), 255 info, request->url().host(), extension_info_map)) {
382 extension_info_map)) {
383 return false; 256 return false;
384 } 257 }
385 258
386 // The following checks are meant to replicate similar set of checks in the 259 // The following checks are meant to replicate similar set of checks in the
387 // renderer process, performed by ResourceRequestPolicy::CanRequestResource. 260 // renderer process, performed by ResourceRequestPolicy::CanRequestResource.
388 // These are not exactly equivalent, because we don't have the same bits of 261 // These are not exactly equivalent, because we don't have the same bits of
389 // information. The two checks need to be kept in sync as much as possible, as 262 // information. The two checks need to be kept in sync as much as possible, as
390 // an exploited renderer can bypass the checks in ResourceRequestPolicy. 263 // an exploited renderer can bypass the checks in ResourceRequestPolicy.
391 264
392 // Check if the extension for which this request is made is indeed loaded in 265 // Check if the extension for which this request is made is indeed loaded in
393 // the process sending the request. If not, we need to explicitly check if 266 // the process sending the request. If not, we need to explicitly check if
394 // the resource is explicitly accessible or fits in a set of exception cases. 267 // the resource is explicitly accessible or fits in a set of exception cases.
395 // Note: This allows a case where two extensions execute in the same renderer 268 // Note: This allows a case where two extensions execute in the same renderer
396 // process to request each other's resources. We can't do a more precise 269 // process to request each other's resources. We can't do a more precise
397 // check, since the renderer can lie about which extension has made the 270 // check, since the renderer can lie about which extension has made the
398 // request. 271 // request.
399 if (extension_info_map->process_map().Contains( 272 if (extension_info_map->process_map().Contains(
400 request->url().host(), info->GetChildID())) { 273 request->url().host(), info->GetChildID())) {
401 return true; 274 return true;
402 } 275 }
403 276
404 // Check workers so that importScripts works from extension workers. 277 // Allow the extension module embedder to grant permission for loads.
405 if (extension_info_map->worker_process_map().Contains( 278 if (ExtensionsBrowserClient::Get()->AllowCrossRendererResourceLoad(
406 request->url().host(), info->GetChildID())) { 279 request, is_incognito, extension, extension_info_map)) {
407 return true; 280 return true;
408 } 281 }
409 282
410 // Extensions with webview: allow loading certain resources by guest renderers 283 // No special exceptions for cross-process loading. Block the load.
411 // with privileged partition IDs as specified in the manifest file. 284 return false;
412 ExtensionRendererState* renderer_state =
413 ExtensionRendererState::GetInstance();
414 ExtensionRendererState::WebViewInfo webview_info;
415 bool is_guest = renderer_state->GetWebViewInfo(info->GetChildID(),
416 info->GetRouteID(),
417 &webview_info);
418 std::string resource_path = request->url().path();
419 if (is_guest && extensions::WebviewInfo::IsResourceWebviewAccessible(
420 extension, webview_info.partition_id, resource_path)) {
421 return true;
422 }
423
424 // If the request is for navigations outside of webviews, then it should be
425 // allowed. The navigation logic in CrossSiteResourceHandler will properly
426 // transfer the navigation to a privileged process before it commits.
427 if (ResourceType::IsFrame(info->GetResourceType()) && !is_guest)
428 return true;
429
430 if (!content::PageTransitionIsWebTriggerable(info->GetPageTransition()))
431 return false;
432
433 // The following checks require that we have an actual extension object. If we
434 // don't have it, allow the request handling to continue with the rest of the
435 // checks.
436 if (!extension)
437 return true;
438
439 // Disallow loading of packaged resources for hosted apps. We don't allow
440 // hybrid hosted/packaged apps. The one exception is access to icons, since
441 // some extensions want to be able to do things like create their own
442 // launchers.
443 std::string resource_root_relative_path =
444 request->url().path().empty() ? std::string()
445 : request->url().path().substr(1);
446 if (extension->is_hosted_app() &&
447 !extensions::IconsInfo::GetIcons(extension)
448 .ContainsPath(resource_root_relative_path)) {
449 LOG(ERROR) << "Denying load of " << request->url().spec() << " from "
450 << "hosted app.";
451 return false;
452 }
453
454 // Extensions with web_accessible_resources: allow loading by regular
455 // renderers. Since not all subresources are required to be listed in a v2
456 // manifest, we must allow all loads if there are any web accessible
457 // resources. See http://crbug.com/179127.
458 if (extension->manifest_version() < 2 ||
459 extensions::WebAccessibleResourcesInfo::HasWebAccessibleResources(
460 extension)) {
461 return true;
462 }
463
464 // If there aren't any explicitly marked web accessible resources, the
465 // load should be allowed only if it is by DevTools. A close approximation is
466 // checking if the extension contains a DevTools page.
467 if (extensions::ManifestURL::GetDevToolsPage(extension).is_empty())
468 return false;
469
470 return true;
471 } 285 }
472 286
473 // Returns true if the given URL references an icon in the given extension. 287 // Returns true if the given URL references an icon in the given extension.
474 bool URLIsForExtensionIcon(const GURL& url, const Extension* extension) { 288 bool URLIsForExtensionIcon(const GURL& url, const Extension* extension) {
475 DCHECK(url.SchemeIs(extensions::kExtensionScheme)); 289 DCHECK(url.SchemeIs(extensions::kExtensionScheme));
476 290
477 if (!extension) 291 if (!extension)
478 return false; 292 return false;
479 293
480 std::string path = url.path(); 294 std::string path = url.path();
481 DCHECK_EQ(url.host(), extension->id()); 295 DCHECK_EQ(url.host(), extension->id());
482 DCHECK(path.length() > 0 && path[0] == '/'); 296 DCHECK(path.length() > 0 && path[0] == '/');
483 path = path.substr(1); 297 path = path.substr(1);
484 return extensions::IconsInfo::GetIcons(extension).ContainsPath(path); 298 return extensions::IconsInfo::GetIcons(extension).ContainsPath(path);
485 } 299 }
486 300
487 class ExtensionProtocolHandler 301 class ExtensionProtocolHandler
488 : public net::URLRequestJobFactory::ProtocolHandler { 302 : public net::URLRequestJobFactory::ProtocolHandler {
489 public: 303 public:
490 ExtensionProtocolHandler(Profile::ProfileType profile_type, 304 ExtensionProtocolHandler(bool is_incognito,
491 extensions::InfoMap* extension_info_map) 305 extensions::InfoMap* extension_info_map)
492 : profile_type_(profile_type), extension_info_map_(extension_info_map) {} 306 : is_incognito_(is_incognito), extension_info_map_(extension_info_map) {}
493 307
494 virtual ~ExtensionProtocolHandler() {} 308 virtual ~ExtensionProtocolHandler() {}
495 309
496 virtual net::URLRequestJob* MaybeCreateJob( 310 virtual net::URLRequestJob* MaybeCreateJob(
497 net::URLRequest* request, 311 net::URLRequest* request,
498 net::NetworkDelegate* network_delegate) const OVERRIDE; 312 net::NetworkDelegate* network_delegate) const OVERRIDE;
499 313
500 private: 314 private:
501 const Profile::ProfileType profile_type_; 315 const bool is_incognito_;
502 extensions::InfoMap* const extension_info_map_; 316 extensions::InfoMap* const extension_info_map_;
503 DISALLOW_COPY_AND_ASSIGN(ExtensionProtocolHandler); 317 DISALLOW_COPY_AND_ASSIGN(ExtensionProtocolHandler);
504 }; 318 };
505 319
506 // Creates URLRequestJobs for extension:// URLs. 320 // Creates URLRequestJobs for extension:// URLs.
507 net::URLRequestJob* 321 net::URLRequestJob*
508 ExtensionProtocolHandler::MaybeCreateJob( 322 ExtensionProtocolHandler::MaybeCreateJob(
509 net::URLRequest* request, net::NetworkDelegate* network_delegate) const { 323 net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
510 // chrome-extension://extension-id/resource/path.js 324 // chrome-extension://extension-id/resource/path.js
511 std::string extension_id = request->url().host(); 325 std::string extension_id = request->url().host();
512 const Extension* extension = 326 const Extension* extension =
513 extension_info_map_->extensions().GetByID(extension_id); 327 extension_info_map_->extensions().GetByID(extension_id);
514 328
515 // TODO(mpcomplete): better error code. 329 // TODO(mpcomplete): better error code.
516 if (!AllowExtensionResourceLoad( 330 if (!AllowExtensionResourceLoad(
517 request, profile_type_, extension, extension_info_map_)) { 331 request, is_incognito_, extension, extension_info_map_)) {
518 return new net::URLRequestErrorJob( 332 return new net::URLRequestErrorJob(
519 request, network_delegate, net::ERR_ADDRESS_UNREACHABLE); 333 request, network_delegate, net::ERR_ADDRESS_UNREACHABLE);
520 } 334 }
521 335
336 // If this is a disabled extension only allow the icon to load.
522 base::FilePath directory_path; 337 base::FilePath directory_path;
523 if (extension) 338 if (extension)
524 directory_path = extension->path(); 339 directory_path = extension->path();
525 if (directory_path.value().empty()) { 340 if (directory_path.value().empty()) {
526 const Extension* disabled_extension = 341 const Extension* disabled_extension =
527 extension_info_map_->disabled_extensions().GetByID(extension_id); 342 extension_info_map_->disabled_extensions().GetByID(extension_id);
528 if (URLIsForExtensionIcon(request->url(), disabled_extension)) 343 if (URLIsForExtensionIcon(request->url(), disabled_extension))
529 directory_path = disabled_extension->path(); 344 directory_path = disabled_extension->path();
530 if (directory_path.value().empty()) { 345 if (directory_path.value().empty()) {
531 LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id; 346 LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id;
532 return NULL; 347 return NULL;
533 } 348 }
534 } 349 }
535 350
351 // Set up content security policy.
536 std::string content_security_policy; 352 std::string content_security_policy;
537 bool send_cors_header = false; 353 bool send_cors_header = false;
538 bool follow_symlinks_anywhere = false; 354 bool follow_symlinks_anywhere = false;
539 if (extension) { 355 if (extension) {
540 std::string resource_path = request->url().path(); 356 std::string resource_path = request->url().path();
541 content_security_policy = 357 content_security_policy =
542 extensions::CSPInfo::GetResourceContentSecurityPolicy(extension, 358 extensions::CSPInfo::GetResourceContentSecurityPolicy(extension,
543 resource_path); 359 resource_path);
544 if ((extension->manifest_version() >= 2 || 360 if ((extension->manifest_version() >= 2 ||
545 extensions::WebAccessibleResourcesInfo::HasWebAccessibleResources( 361 extensions::WebAccessibleResourcesInfo::HasWebAccessibleResources(
546 extension)) && 362 extension)) &&
547 extensions::WebAccessibleResourcesInfo::IsResourceWebAccessible( 363 extensions::WebAccessibleResourcesInfo::IsResourceWebAccessible(
548 extension, resource_path)) 364 extension, resource_path))
549 send_cors_header = true; 365 send_cors_header = true;
550 366
551 follow_symlinks_anywhere = 367 follow_symlinks_anywhere =
552 (extension->creation_flags() & Extension::FOLLOW_SYMLINKS_ANYWHERE) 368 (extension->creation_flags() & Extension::FOLLOW_SYMLINKS_ANYWHERE)
553 != 0; 369 != 0;
554 } 370 }
555 371
372 // Create a job for a generated background page.
556 std::string path = request->url().path(); 373 std::string path = request->url().path();
557 if (path.size() > 1 && 374 if (path.size() > 1 &&
558 path.substr(1) == extensions::kGeneratedBackgroundPageFilename) { 375 path.substr(1) == extensions::kGeneratedBackgroundPageFilename) {
559 return new GeneratedBackgroundPageJob( 376 return new GeneratedBackgroundPageJob(
560 request, network_delegate, extension, content_security_policy); 377 request, network_delegate, extension, content_security_policy);
561 } 378 }
562 379
563 base::FilePath resources_path; 380 // Component extension resources may be part of the embedder's resource files,
564 base::FilePath relative_path; 381 // for example component_extension_resources.pak in Chrome.
565 // Try to load extension resources from chrome resource file if 382 net::URLRequestJob* resource_bundle_job =
566 // directory_path is a descendant of resources_path. resources_path 383 extensions::ExtensionsBrowserClient::Get()
567 // corresponds to src/chrome/browser/resources in source tree. 384 ->MaybeCreateResourceBundleRequestJob(request,
568 if (PathService::Get(chrome::DIR_RESOURCES, &resources_path) && 385 network_delegate,
569 // Since component extension resources are included in 386 directory_path,
570 // component_extension_resources.pak file in resources_path, calculate 387 content_security_policy,
571 // extension relative path against resources_path. 388 send_cors_header);
572 resources_path.AppendRelativePath(directory_path, &relative_path)) { 389 if (resource_bundle_job)
573 base::FilePath request_path = 390 return resource_bundle_job;
574 extensions::file_util::ExtensionURLToRelativeFilePath(request->url());
575 int resource_id;
576 if (extensions::ImageLoader::IsComponentExtensionResource(
577 directory_path, request_path, &resource_id)) {
578 relative_path = relative_path.Append(request_path);
579 relative_path = relative_path.NormalizePathSeparators();
580 return new URLRequestResourceBundleJob(
581 request,
582 network_delegate,
583 relative_path,
584 resource_id,
585 content_security_policy,
586 send_cors_header);
587 }
588 }
589 391
590 relative_path = 392 base::FilePath relative_path =
591 extensions::file_util::ExtensionURLToRelativeFilePath(request->url()); 393 extensions::file_util::ExtensionURLToRelativeFilePath(request->url());
592 394
395 // Handle shared resources (extension A loading resources out of extension B).
593 if (SharedModuleInfo::IsImportedPath(path)) { 396 if (SharedModuleInfo::IsImportedPath(path)) {
594 std::string new_extension_id; 397 std::string new_extension_id;
595 std::string new_relative_path; 398 std::string new_relative_path;
596 SharedModuleInfo::ParseImportedPath(path, &new_extension_id, 399 SharedModuleInfo::ParseImportedPath(path, &new_extension_id,
597 &new_relative_path); 400 &new_relative_path);
598 const Extension* new_extension = 401 const Extension* new_extension =
599 extension_info_map_->extensions().GetByID(new_extension_id); 402 extension_info_map_->extensions().GetByID(new_extension_id);
600 403
601 bool first_party_in_import = false; 404 bool first_party_in_import = false;
602 // NB: This first_party_for_cookies call is not for security, it is only 405 // NB: This first_party_for_cookies call is not for security, it is only
(...skipping 28 matching lines...) Expand all
631 extension_id, 434 extension_id,
632 directory_path, 435 directory_path,
633 relative_path, 436 relative_path,
634 content_security_policy, 437 content_security_policy,
635 send_cors_header, 438 send_cors_header,
636 follow_symlinks_anywhere); 439 follow_symlinks_anywhere);
637 } 440 }
638 441
639 } // namespace 442 } // namespace
640 443
444 net::HttpResponseHeaders* BuildHttpHeaders(
James Cook 2014/04/09 22:54:41 Moved unchanged from above to let the Chrome code
445 const std::string& content_security_policy,
446 bool send_cors_header,
447 const base::Time& last_modified_time) {
448 std::string raw_headers;
449 raw_headers.append("HTTP/1.1 200 OK");
450 if (!content_security_policy.empty()) {
451 raw_headers.append(1, '\0');
452 raw_headers.append("Content-Security-Policy: ");
453 raw_headers.append(content_security_policy);
454 }
455
456 if (send_cors_header) {
457 raw_headers.append(1, '\0');
458 raw_headers.append("Access-Control-Allow-Origin: *");
459 }
460
461 if (!last_modified_time.is_null()) {
462 // Hash the time and make an etag to avoid exposing the exact
463 // user installation time of the extension.
464 std::string hash =
465 base::StringPrintf("%" PRId64, last_modified_time.ToInternalValue());
466 hash = base::SHA1HashString(hash);
467 std::string etag;
468 base::Base64Encode(hash, &etag);
469 raw_headers.append(1, '\0');
470 raw_headers.append("ETag: \"");
471 raw_headers.append(etag);
472 raw_headers.append("\"");
473 // Also force revalidation.
474 raw_headers.append(1, '\0');
475 raw_headers.append("cache-control: no-cache");
476 }
477
478 raw_headers.append(2, '\0');
479 return new net::HttpResponseHeaders(raw_headers);
480 }
481
641 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( 482 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler(
642 Profile::ProfileType profile_type, 483 bool is_incognito,
643 extensions::InfoMap* extension_info_map) { 484 extensions::InfoMap* extension_info_map) {
644 return new ExtensionProtocolHandler(profile_type, extension_info_map); 485 return new ExtensionProtocolHandler(is_incognito, extension_info_map);
645 } 486 }
487
488 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698