Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/browser/extension_protocols.h" | 5 #include "extensions/browser/extension_protocols.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 #include "base/strings/stringprintf.h" | 26 #include "base/strings/stringprintf.h" |
| 27 #include "base/strings/utf_string_conversions.h" | 27 #include "base/strings/utf_string_conversions.h" |
| 28 #include "base/threading/sequenced_worker_pool.h" | 28 #include "base/threading/sequenced_worker_pool.h" |
| 29 #include "base/threading/thread_restrictions.h" | 29 #include "base/threading/thread_restrictions.h" |
| 30 #include "base/timer/elapsed_timer.h" | 30 #include "base/timer/elapsed_timer.h" |
| 31 #include "build/build_config.h" | 31 #include "build/build_config.h" |
| 32 #include "content/public/browser/browser_thread.h" | 32 #include "content/public/browser/browser_thread.h" |
| 33 #include "content/public/browser/resource_request_info.h" | 33 #include "content/public/browser/resource_request_info.h" |
| 34 #include "crypto/secure_hash.h" | 34 #include "crypto/secure_hash.h" |
| 35 #include "crypto/sha2.h" | 35 #include "crypto/sha2.h" |
| 36 #include "extensions/browser/content_verifier.h" | |
| 37 #include "extensions/browser/content_verify_job.h" | |
| 36 #include "extensions/browser/extensions_browser_client.h" | 38 #include "extensions/browser/extensions_browser_client.h" |
| 37 #include "extensions/browser/info_map.h" | 39 #include "extensions/browser/info_map.h" |
| 38 #include "extensions/common/constants.h" | 40 #include "extensions/common/constants.h" |
| 39 #include "extensions/common/extension.h" | 41 #include "extensions/common/extension.h" |
| 40 #include "extensions/common/extension_resource.h" | 42 #include "extensions/common/extension_resource.h" |
| 41 #include "extensions/common/file_util.h" | 43 #include "extensions/common/file_util.h" |
| 42 #include "extensions/common/manifest_handlers/background_info.h" | 44 #include "extensions/common/manifest_handlers/background_info.h" |
| 43 #include "extensions/common/manifest_handlers/csp_info.h" | 45 #include "extensions/common/manifest_handlers/csp_info.h" |
| 44 #include "extensions/common/manifest_handlers/icons_handler.h" | 46 #include "extensions/common/manifest_handlers/icons_handler.h" |
| 45 #include "extensions/common/manifest_handlers/incognito_info.h" | 47 #include "extensions/common/manifest_handlers/incognito_info.h" |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 | 160 |
| 159 class URLRequestExtensionJob : public net::URLRequestFileJob { | 161 class URLRequestExtensionJob : public net::URLRequestFileJob { |
| 160 public: | 162 public: |
| 161 URLRequestExtensionJob(net::URLRequest* request, | 163 URLRequestExtensionJob(net::URLRequest* request, |
| 162 net::NetworkDelegate* network_delegate, | 164 net::NetworkDelegate* network_delegate, |
| 163 const std::string& extension_id, | 165 const std::string& extension_id, |
| 164 const base::FilePath& directory_path, | 166 const base::FilePath& directory_path, |
| 165 const base::FilePath& relative_path, | 167 const base::FilePath& relative_path, |
| 166 const std::string& content_security_policy, | 168 const std::string& content_security_policy, |
| 167 bool send_cors_header, | 169 bool send_cors_header, |
| 168 bool follow_symlinks_anywhere) | 170 bool follow_symlinks_anywhere, |
| 171 ContentVerifyJob* verify_job) | |
| 169 : net::URLRequestFileJob( | 172 : net::URLRequestFileJob( |
| 170 request, | 173 request, |
| 171 network_delegate, | 174 network_delegate, |
| 172 base::FilePath(), | 175 base::FilePath(), |
| 173 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( | 176 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( |
| 174 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), | 177 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)), |
| 178 verify_job_(verify_job), | |
| 175 seek_position_(0), | 179 seek_position_(0), |
| 176 bytes_read_(0), | 180 bytes_read_(0), |
| 177 directory_path_(directory_path), | 181 directory_path_(directory_path), |
| 178 // TODO(tc): Move all of these files into resources.pak so we don't | 182 // TODO(tc): Move all of these files into resources.pak so we don't |
| 179 // break when updating on Linux. | 183 // break when updating on Linux. |
| 180 resource_(extension_id, directory_path, relative_path), | 184 resource_(extension_id, directory_path, relative_path), |
| 181 content_security_policy_(content_security_policy), | 185 content_security_policy_(content_security_policy), |
| 182 send_cors_header_(send_cors_header), | 186 send_cors_header_(send_cors_header), |
| 183 weak_factory_(this) { | 187 weak_factory_(this) { |
| 184 if (follow_symlinks_anywhere) { | 188 if (follow_symlinks_anywhere) { |
| 185 resource_.set_follow_symlinks_anywhere(); | 189 resource_.set_follow_symlinks_anywhere(); |
| 186 } | 190 } |
| 187 const std::string& group = | |
| 188 base::FieldTrialList::FindFullName("ExtensionContentHashMeasurement"); | |
| 189 if (group == "Yes") { | |
| 190 base::ElapsedTimer timer; | |
| 191 hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256)); | |
| 192 hashing_time_ = timer.Elapsed(); | |
| 193 } | |
| 194 } | 191 } |
| 195 | 192 |
| 196 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE { | 193 virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE { |
| 197 *info = response_info_; | 194 *info = response_info_; |
| 198 } | 195 } |
| 199 | 196 |
| 200 virtual void Start() OVERRIDE { | 197 virtual void Start() OVERRIDE { |
| 201 base::FilePath* read_file_path = new base::FilePath; | 198 base::FilePath* read_file_path = new base::FilePath; |
| 202 base::Time* last_modified_time = new base::Time(); | 199 base::Time* last_modified_time = new base::Time(); |
| 203 bool posted = BrowserThread::PostBlockingPoolTaskAndReply( | 200 bool posted = BrowserThread::PostBlockingPoolTaskAndReply( |
| 204 FROM_HERE, | 201 FROM_HERE, |
| 205 base::Bind(&ReadResourceFilePathAndLastModifiedTime, | 202 base::Bind(&ReadResourceFilePathAndLastModifiedTime, |
| 206 resource_, | 203 resource_, |
| 207 directory_path_, | 204 directory_path_, |
| 208 base::Unretained(read_file_path), | 205 base::Unretained(read_file_path), |
| 209 base::Unretained(last_modified_time)), | 206 base::Unretained(last_modified_time)), |
| 210 base::Bind(&URLRequestExtensionJob::OnFilePathAndLastModifiedTimeRead, | 207 base::Bind(&URLRequestExtensionJob::OnFilePathAndLastModifiedTimeRead, |
| 211 weak_factory_.GetWeakPtr(), | 208 weak_factory_.GetWeakPtr(), |
| 212 base::Owned(read_file_path), | 209 base::Owned(read_file_path), |
| 213 base::Owned(last_modified_time))); | 210 base::Owned(last_modified_time))); |
| 214 DCHECK(posted); | 211 DCHECK(posted); |
| 215 } | 212 } |
| 216 | 213 |
| 214 virtual void SetExtraRequestHeaders( | |
| 215 const net::HttpRequestHeaders& headers) OVERRIDE { | |
| 216 // TODO(asargent) - we'll need to add proper support for range headers. | |
| 217 // crbug.com/369895. | |
| 218 std::string range_header; | |
| 219 if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { | |
| 220 if (verify_job_) | |
| 221 verify_job_ = NULL; | |
| 222 } | |
| 223 URLRequestFileJob::SetExtraRequestHeaders(headers); | |
| 224 } | |
| 225 | |
| 217 virtual void OnSeekComplete(int64 result) OVERRIDE { | 226 virtual void OnSeekComplete(int64 result) OVERRIDE { |
| 218 DCHECK_EQ(seek_position_, 0); | 227 DCHECK_EQ(seek_position_, 0); |
| 219 seek_position_ = result; | 228 seek_position_ = result; |
| 229 // TODO(asargent) - we'll need to add proper support for range headers. | |
| 230 // crbug.com/369895. | |
| 231 if (result > 0 && verify_job_) | |
| 232 verify_job_ = NULL; | |
| 220 } | 233 } |
| 221 | 234 |
| 222 virtual void OnReadComplete(net::IOBuffer* buffer, int result) OVERRIDE { | 235 virtual void OnReadComplete(net::IOBuffer* buffer, int result) OVERRIDE { |
| 223 if (result >= 0) | 236 if (result >= 0) |
| 224 UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.OnReadCompleteResult", result); | 237 UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.OnReadCompleteResult", result); |
| 225 else | 238 else |
| 226 UMA_HISTOGRAM_SPARSE_SLOWLY("ExtensionUrlRequest.OnReadCompleteError", | 239 UMA_HISTOGRAM_SPARSE_SLOWLY("ExtensionUrlRequest.OnReadCompleteError", |
| 227 -result); | 240 -result); |
| 228 if (result > 0) { | 241 if (result > 0) { |
| 229 bytes_read_ += result; | 242 bytes_read_ += result; |
| 230 if (hash_.get()) { | 243 if (verify_job_) { |
| 231 base::ElapsedTimer timer; | 244 verify_job_->BytesRead(result, buffer->data()); |
| 232 hash_->Update(buffer->data(), result); | 245 if (remaining_bytes() == 0) |
|
rvargas (doing something else)
2014/05/08 17:50:07
Very small nit: maybe !remaining_bytes() reads bet
asargent_no_longer_on_chrome
2014/05/08 18:02:07
Done.
| |
| 233 hashing_time_ += timer.Elapsed(); | 246 verify_job_->DoneReading(); |
| 234 } | 247 } |
| 235 } | 248 } |
| 236 } | 249 } |
| 237 | 250 |
| 238 private: | 251 private: |
| 239 virtual ~URLRequestExtensionJob() { | 252 virtual ~URLRequestExtensionJob() { |
| 240 if (hash_.get()) { | |
| 241 base::ElapsedTimer timer; | |
| 242 std::string hash_bytes(crypto::kSHA256Length, 0); | |
| 243 hash_->Finish(string_as_array(&hash_bytes), hash_bytes.size()); | |
| 244 hashing_time_ += timer.Elapsed(); | |
| 245 UMA_HISTOGRAM_TIMES("ExtensionUrlRequest.HashTimeMs", hashing_time_); | |
| 246 } | |
| 247 UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.TotalKbRead", bytes_read_ / 1024); | 253 UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.TotalKbRead", bytes_read_ / 1024); |
| 248 UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.SeekPosition", seek_position_); | 254 UMA_HISTOGRAM_COUNTS("ExtensionUrlRequest.SeekPosition", seek_position_); |
| 249 } | 255 } |
| 250 | 256 |
| 251 void OnFilePathAndLastModifiedTimeRead(base::FilePath* read_file_path, | 257 void OnFilePathAndLastModifiedTimeRead(base::FilePath* read_file_path, |
| 252 base::Time* last_modified_time) { | 258 base::Time* last_modified_time) { |
| 253 file_path_ = *read_file_path; | 259 file_path_ = *read_file_path; |
| 254 response_info_.headers = BuildHttpHeaders( | 260 response_info_.headers = BuildHttpHeaders( |
| 255 content_security_policy_, | 261 content_security_policy_, |
| 256 send_cors_header_, | 262 send_cors_header_, |
| 257 *last_modified_time); | 263 *last_modified_time); |
| 258 URLRequestFileJob::Start(); | 264 URLRequestFileJob::Start(); |
| 259 } | 265 } |
| 260 | 266 |
| 261 // A hash of the contents we've read from the file. | 267 scoped_refptr<ContentVerifyJob> verify_job_; |
| 262 scoped_ptr<crypto::SecureHash> hash_; | |
| 263 | 268 |
| 264 // The position we seeked to in the file. | 269 // The position we seeked to in the file. |
| 265 int64 seek_position_; | 270 int64 seek_position_; |
| 266 | 271 |
| 267 // The number of bytes of content we read from the file. | 272 // The number of bytes of content we read from the file. |
| 268 int bytes_read_; | 273 int bytes_read_; |
| 269 | 274 |
| 270 // Used to count the total time it takes to do hashing operations. | |
| 271 base::TimeDelta hashing_time_; | |
| 272 | |
| 273 net::HttpResponseInfo response_info_; | 275 net::HttpResponseInfo response_info_; |
| 274 base::FilePath directory_path_; | 276 base::FilePath directory_path_; |
| 275 extensions::ExtensionResource resource_; | 277 extensions::ExtensionResource resource_; |
| 276 std::string content_security_policy_; | 278 std::string content_security_policy_; |
| 277 bool send_cors_header_; | 279 bool send_cors_header_; |
| 278 base::WeakPtrFactory<URLRequestExtensionJob> weak_factory_; | 280 base::WeakPtrFactory<URLRequestExtensionJob> weak_factory_; |
| 279 }; | 281 }; |
| 280 | 282 |
| 281 bool ExtensionCanLoadInIncognito(const ResourceRequestInfo* info, | 283 bool ExtensionCanLoadInIncognito(const ResourceRequestInfo* info, |
| 282 const std::string& extension_id, | 284 const std::string& extension_id, |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 492 new_extension && | 494 new_extension && |
| 493 (first_party_in_import || | 495 (first_party_in_import || |
| 494 SharedModuleInfo::IsExportAllowed(new_extension, new_relative_path))) { | 496 SharedModuleInfo::IsExportAllowed(new_extension, new_relative_path))) { |
| 495 directory_path = new_extension->path(); | 497 directory_path = new_extension->path(); |
| 496 extension_id = new_extension_id; | 498 extension_id = new_extension_id; |
| 497 relative_path = base::FilePath::FromUTF8Unsafe(new_relative_path); | 499 relative_path = base::FilePath::FromUTF8Unsafe(new_relative_path); |
| 498 } else { | 500 } else { |
| 499 return NULL; | 501 return NULL; |
| 500 } | 502 } |
| 501 } | 503 } |
| 504 ContentVerifyJob* verify_job = NULL; | |
| 505 ContentVerifier* verifier = extension_info_map_->content_verifier(); | |
| 506 if (verifier) { | |
| 507 verify_job = | |
| 508 verifier->CreateJobFor(extension_id, directory_path, relative_path); | |
| 509 if (verify_job) | |
| 510 verify_job->Start(); | |
| 511 } | |
| 502 | 512 |
| 503 return new URLRequestExtensionJob(request, | 513 return new URLRequestExtensionJob(request, |
| 504 network_delegate, | 514 network_delegate, |
| 505 extension_id, | 515 extension_id, |
| 506 directory_path, | 516 directory_path, |
| 507 relative_path, | 517 relative_path, |
| 508 content_security_policy, | 518 content_security_policy, |
| 509 send_cors_header, | 519 send_cors_header, |
| 510 follow_symlinks_anywhere); | 520 follow_symlinks_anywhere, |
| 521 verify_job); | |
| 511 } | 522 } |
| 512 | 523 |
| 513 } // namespace | 524 } // namespace |
| 514 | 525 |
| 515 net::HttpResponseHeaders* BuildHttpHeaders( | 526 net::HttpResponseHeaders* BuildHttpHeaders( |
| 516 const std::string& content_security_policy, | 527 const std::string& content_security_policy, |
| 517 bool send_cors_header, | 528 bool send_cors_header, |
| 518 const base::Time& last_modified_time) { | 529 const base::Time& last_modified_time) { |
| 519 std::string raw_headers; | 530 std::string raw_headers; |
| 520 raw_headers.append("HTTP/1.1 200 OK"); | 531 raw_headers.append("HTTP/1.1 200 OK"); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 550 return new net::HttpResponseHeaders(raw_headers); | 561 return new net::HttpResponseHeaders(raw_headers); |
| 551 } | 562 } |
| 552 | 563 |
| 553 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( | 564 net::URLRequestJobFactory::ProtocolHandler* CreateExtensionProtocolHandler( |
| 554 bool is_incognito, | 565 bool is_incognito, |
| 555 extensions::InfoMap* extension_info_map) { | 566 extensions::InfoMap* extension_info_map) { |
| 556 return new ExtensionProtocolHandler(is_incognito, extension_info_map); | 567 return new ExtensionProtocolHandler(is_incognito, extension_info_map); |
| 557 } | 568 } |
| 558 | 569 |
| 559 } // namespace extensions | 570 } // namespace extensions |
| OLD | NEW |