| OLD | NEW |
| 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/file_path.h" | 10 #include "base/file_path.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "net/http/http_response_info.h" | 31 #include "net/http/http_response_info.h" |
| 32 #include "net/http/http_response_headers.h" | 32 #include "net/http/http_response_headers.h" |
| 33 #include "net/url_request/url_request_error_job.h" | 33 #include "net/url_request/url_request_error_job.h" |
| 34 #include "net/url_request/url_request_file_job.h" | 34 #include "net/url_request/url_request_file_job.h" |
| 35 #include "net/url_request/url_request_simple_job.h" | 35 #include "net/url_request/url_request_simple_job.h" |
| 36 #include "ui/base/resource/resource_bundle.h" | 36 #include "ui/base/resource/resource_bundle.h" |
| 37 | 37 |
| 38 namespace { | 38 namespace { |
| 39 | 39 |
| 40 net::HttpResponseHeaders* BuildHttpHeaders( | 40 net::HttpResponseHeaders* BuildHttpHeaders( |
| 41 const std::string& content_security_policy) { | 41 const std::string& content_security_policy, bool send_cors_header) { |
| 42 std::string raw_headers; | 42 std::string raw_headers; |
| 43 raw_headers.append("HTTP/1.1 200 OK"); | 43 raw_headers.append("HTTP/1.1 200 OK"); |
| 44 if (!content_security_policy.empty()) { | 44 if (!content_security_policy.empty()) { |
| 45 raw_headers.append(1, '\0'); | 45 raw_headers.append(1, '\0'); |
| 46 raw_headers.append("X-WebKit-CSP: "); | 46 raw_headers.append("X-WebKit-CSP: "); |
| 47 raw_headers.append(content_security_policy); | 47 raw_headers.append(content_security_policy); |
| 48 } | 48 } |
| 49 |
| 50 if (send_cors_header) { |
| 51 raw_headers.append(1, '\0'); |
| 52 raw_headers.append("Access-Control-Allow-Origin: *"); |
| 53 } |
| 49 raw_headers.append(2, '\0'); | 54 raw_headers.append(2, '\0'); |
| 50 return new net::HttpResponseHeaders(raw_headers); | 55 return new net::HttpResponseHeaders(raw_headers); |
| 51 } | 56 } |
| 52 | 57 |
| 53 class URLRequestResourceBundleJob : public net::URLRequestSimpleJob { | 58 class URLRequestResourceBundleJob : public net::URLRequestSimpleJob { |
| 54 public: | 59 public: |
| 55 URLRequestResourceBundleJob( | 60 URLRequestResourceBundleJob( |
| 56 net::URLRequest* request, const FilePath& filename, int resource_id, | 61 net::URLRequest* request, const FilePath& filename, int resource_id, |
| 57 const std::string& content_security_policy) | 62 const std::string& content_security_policy, bool send_cors_header) |
| 58 : net::URLRequestSimpleJob(request), | 63 : net::URLRequestSimpleJob(request), |
| 59 filename_(filename), | 64 filename_(filename), |
| 60 resource_id_(resource_id) { | 65 resource_id_(resource_id) { |
| 61 response_info_.headers = BuildHttpHeaders(content_security_policy); | 66 response_info_.headers = BuildHttpHeaders(content_security_policy, |
| 67 send_cors_header); |
| 62 } | 68 } |
| 63 | 69 |
| 64 // Overridden from URLRequestSimpleJob: | 70 // Overridden from URLRequestSimpleJob: |
| 65 virtual bool GetData(std::string* mime_type, | 71 virtual bool GetData(std::string* mime_type, |
| 66 std::string* charset, | 72 std::string* charset, |
| 67 std::string* data) const OVERRIDE { | 73 std::string* data) const OVERRIDE { |
| 68 const ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 74 const ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 69 *data = rb.GetRawDataResource(resource_id_).as_string(); | 75 *data = rb.GetRawDataResource(resource_id_).as_string(); |
| 70 | 76 |
| 71 // Requests should not block on the disk! On Windows this goes to the | 77 // Requests should not block on the disk! On Windows this goes to the |
| (...skipping 30 matching lines...) Expand all Loading... |
| 102 net::HttpResponseInfo response_info_; | 108 net::HttpResponseInfo response_info_; |
| 103 }; | 109 }; |
| 104 | 110 |
| 105 class GeneratedBackgroundPageJob : public net::URLRequestSimpleJob { | 111 class GeneratedBackgroundPageJob : public net::URLRequestSimpleJob { |
| 106 public: | 112 public: |
| 107 GeneratedBackgroundPageJob(net::URLRequest* request, | 113 GeneratedBackgroundPageJob(net::URLRequest* request, |
| 108 const scoped_refptr<const Extension> extension, | 114 const scoped_refptr<const Extension> extension, |
| 109 const std::string& content_security_policy) | 115 const std::string& content_security_policy) |
| 110 : net::URLRequestSimpleJob(request), | 116 : net::URLRequestSimpleJob(request), |
| 111 extension_(extension) { | 117 extension_(extension) { |
| 112 response_info_.headers = BuildHttpHeaders(content_security_policy); | 118 const bool send_cors_headers = false; |
| 119 response_info_.headers = BuildHttpHeaders(content_security_policy, |
| 120 send_cors_headers); |
| 113 } | 121 } |
| 114 | 122 |
| 115 // Overridden from URLRequestSimpleJob: | 123 // Overridden from URLRequestSimpleJob: |
| 116 virtual bool GetData(std::string* mime_type, | 124 virtual bool GetData(std::string* mime_type, |
| 117 std::string* charset, | 125 std::string* charset, |
| 118 std::string* data) const OVERRIDE { | 126 std::string* data) const OVERRIDE { |
| 119 *mime_type = "text/html"; | 127 *mime_type = "text/html"; |
| 120 *charset = "utf-8"; | 128 *charset = "utf-8"; |
| 121 | 129 |
| 122 *data = "<!DOCTYPE html>\n<body>\n"; | 130 *data = "<!DOCTYPE html>\n<body>\n"; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 135 | 143 |
| 136 private: | 144 private: |
| 137 scoped_refptr<const Extension> extension_; | 145 scoped_refptr<const Extension> extension_; |
| 138 net::HttpResponseInfo response_info_; | 146 net::HttpResponseInfo response_info_; |
| 139 }; | 147 }; |
| 140 | 148 |
| 141 class URLRequestExtensionJob : public net::URLRequestFileJob { | 149 class URLRequestExtensionJob : public net::URLRequestFileJob { |
| 142 public: | 150 public: |
| 143 URLRequestExtensionJob(net::URLRequest* request, | 151 URLRequestExtensionJob(net::URLRequest* request, |
| 144 const FilePath& filename, | 152 const FilePath& filename, |
| 145 const std::string& content_security_policy) | 153 const std::string& content_security_policy, |
| 154 bool send_cors_header) |
| 146 : net::URLRequestFileJob(request, filename) { | 155 : net::URLRequestFileJob(request, filename) { |
| 147 response_info_.headers = BuildHttpHeaders(content_security_policy); | 156 response_info_.headers = BuildHttpHeaders(content_security_policy, |
| 157 send_cors_header); |
| 148 } | 158 } |
| 149 | 159 |
| 150 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE { | 160 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE { |
| 151 *info = response_info_; | 161 *info = response_info_; |
| 152 } | 162 } |
| 153 | 163 |
| 154 net::HttpResponseInfo response_info_; | 164 net::HttpResponseInfo response_info_; |
| 155 }; | 165 }; |
| 156 | 166 |
| 157 bool ExtensionCanLoadInIncognito(const std::string& extension_id, | 167 bool ExtensionCanLoadInIncognito(const std::string& extension_id, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 248 extension_info_map_->disabled_extensions().GetByID(extension_id); | 258 extension_info_map_->disabled_extensions().GetByID(extension_id); |
| 249 if (URLIsForExtensionIcon(request->url(), disabled_extension)) | 259 if (URLIsForExtensionIcon(request->url(), disabled_extension)) |
| 250 directory_path = disabled_extension->path(); | 260 directory_path = disabled_extension->path(); |
| 251 if (directory_path.value().empty()) { | 261 if (directory_path.value().empty()) { |
| 252 LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id; | 262 LOG(WARNING) << "Failed to GetPathForExtension: " << extension_id; |
| 253 return NULL; | 263 return NULL; |
| 254 } | 264 } |
| 255 } | 265 } |
| 256 | 266 |
| 257 std::string content_security_policy; | 267 std::string content_security_policy; |
| 258 if (extension) | 268 bool send_cors_header = false; |
| 269 if (extension) { |
| 259 content_security_policy = extension->content_security_policy(); | 270 content_security_policy = extension->content_security_policy(); |
| 271 if ((extension->manifest_version() >= 2 || |
| 272 extension->HasWebAccessibleResources()) && |
| 273 extension->IsResourceWebAccessible(request->url().path())) |
| 274 send_cors_header = true; |
| 275 } |
| 260 | 276 |
| 261 std::string path = request->url().path(); | 277 std::string path = request->url().path(); |
| 262 if (path.size() > 1 && | 278 if (path.size() > 1 && |
| 263 path.substr(1) == extension_filenames::kGeneratedBackgroundPageFilename) { | 279 path.substr(1) == extension_filenames::kGeneratedBackgroundPageFilename) { |
| 264 return new GeneratedBackgroundPageJob( | 280 return new GeneratedBackgroundPageJob( |
| 265 request, extension, content_security_policy); | 281 request, extension, content_security_policy); |
| 266 } | 282 } |
| 267 | 283 |
| 268 FilePath resources_path; | 284 FilePath resources_path; |
| 269 if (PathService::Get(chrome::DIR_RESOURCES, &resources_path) && | 285 if (PathService::Get(chrome::DIR_RESOURCES, &resources_path) && |
| 270 directory_path.DirName() == resources_path) { | 286 directory_path.DirName() == resources_path) { |
| 271 FilePath relative_path = directory_path.BaseName().Append( | 287 FilePath relative_path = directory_path.BaseName().Append( |
| 272 extension_file_util::ExtensionURLToRelativeFilePath(request->url())); | 288 extension_file_util::ExtensionURLToRelativeFilePath(request->url())); |
| 273 #if defined(OS_WIN) | 289 #if defined(OS_WIN) |
| 274 relative_path = relative_path.NormalizeWindowsPathSeparators(); | 290 relative_path = relative_path.NormalizeWindowsPathSeparators(); |
| 275 #endif | 291 #endif |
| 276 | 292 |
| 277 // TODO(tc): Make a map of FilePath -> resource ids so we don't have to | 293 // TODO(tc): Make a map of FilePath -> resource ids so we don't have to |
| 278 // covert to FilePaths all the time. This will be more useful as we add | 294 // covert to FilePaths all the time. This will be more useful as we add |
| 279 // more resources. | 295 // more resources. |
| 280 for (size_t i = 0; i < kComponentExtensionResourcesSize; ++i) { | 296 for (size_t i = 0; i < kComponentExtensionResourcesSize; ++i) { |
| 281 FilePath bm_resource_path = | 297 FilePath bm_resource_path = |
| 282 FilePath().AppendASCII(kComponentExtensionResources[i].name); | 298 FilePath().AppendASCII(kComponentExtensionResources[i].name); |
| 283 #if defined(OS_WIN) | 299 #if defined(OS_WIN) |
| 284 bm_resource_path = bm_resource_path.NormalizeWindowsPathSeparators(); | 300 bm_resource_path = bm_resource_path.NormalizeWindowsPathSeparators(); |
| 285 #endif | 301 #endif |
| 286 if (relative_path == bm_resource_path) { | 302 if (relative_path == bm_resource_path) { |
| 287 return new URLRequestResourceBundleJob(request, relative_path, | 303 return new URLRequestResourceBundleJob(request, relative_path, |
| 288 kComponentExtensionResources[i].value, content_security_policy); | 304 kComponentExtensionResources[i].value, content_security_policy, |
| 305 send_cors_header); |
| 289 } | 306 } |
| 290 } | 307 } |
| 291 } | 308 } |
| 292 // TODO(tc): Move all of these files into resources.pak so we don't break | 309 // TODO(tc): Move all of these files into resources.pak so we don't break |
| 293 // when updating on Linux. | 310 // when updating on Linux. |
| 294 ExtensionResource resource(extension_id, directory_path, | 311 ExtensionResource resource(extension_id, directory_path, |
| 295 extension_file_util::ExtensionURLToRelativeFilePath(request->url())); | 312 extension_file_util::ExtensionURLToRelativeFilePath(request->url())); |
| 296 | 313 |
| 297 FilePath resource_file_path; | 314 FilePath resource_file_path; |
| 298 { | 315 { |
| 299 // Getting the file path will touch the file system. Fixing | 316 // Getting the file path will touch the file system. Fixing |
| 300 // crbug.com/59849 would also fix this. Suppress the error for now. | 317 // crbug.com/59849 would also fix this. Suppress the error for now. |
| 301 base::ThreadRestrictions::ScopedAllowIO allow_io; | 318 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 302 resource_file_path = resource.GetFilePath(); | 319 resource_file_path = resource.GetFilePath(); |
| 303 } | 320 } |
| 304 | 321 |
| 305 return new URLRequestExtensionJob(request, resource_file_path, | 322 return new URLRequestExtensionJob(request, resource_file_path, |
| 306 content_security_policy); | 323 content_security_policy, send_cors_header); |
| 307 } | 324 } |
| 308 | 325 |
| 309 } // namespace | 326 } // namespace |
| 310 | 327 |
| 311 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( | 328 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( |
| 312 bool is_incognito, | 329 bool is_incognito, |
| 313 ExtensionInfoMap* extension_info_map) { | 330 ExtensionInfoMap* extension_info_map) { |
| 314 return new ExtensionProtocolHandler(is_incognito, extension_info_map); | 331 return new ExtensionProtocolHandler(is_incognito, extension_info_map); |
| 315 } | 332 } |
| OLD | NEW |