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 |