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 "content/browser/service_worker/service_worker_cache.h" | 5 #include "content/browser/service_worker/service_worker_cache.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/guid.h" | 10 #include "base/guid.h" |
11 #include "base/message_loop/message_loop_proxy.h" | 11 #include "base/message_loop/message_loop_proxy.h" |
12 #include "base/profiler/scoped_tracker.h" | 12 #include "base/profiler/scoped_tracker.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #include "content/browser/service_worker/service_worker_cache.pb.h" | 14 #include "content/browser/service_worker/service_worker_cache.pb.h" |
| 15 #include "content/browser/service_worker/service_worker_cache_scheduler.h" |
15 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
16 #include "content/public/common/referrer.h" | 17 #include "content/public/common/referrer.h" |
17 #include "net/base/io_buffer.h" | 18 #include "net/base/io_buffer.h" |
18 #include "net/base/net_errors.h" | 19 #include "net/base/net_errors.h" |
19 #include "net/disk_cache/disk_cache.h" | 20 #include "net/disk_cache/disk_cache.h" |
20 #include "net/url_request/url_request_context.h" | 21 #include "net/url_request/url_request_context.h" |
21 #include "storage/browser/blob/blob_data_builder.h" | 22 #include "storage/browser/blob/blob_data_builder.h" |
22 #include "storage/browser/blob/blob_data_handle.h" | 23 #include "storage/browser/blob/blob_data_handle.h" |
23 #include "storage/browser/blob/blob_storage_context.h" | 24 #include "storage/browser/blob/blob_storage_context.h" |
24 #include "storage/browser/blob/blob_url_request_job_factory.h" | 25 #include "storage/browser/blob/blob_url_request_job_factory.h" |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
455 origin_, request.Pass(), response.Pass(), blob_data_handle.Pass(), | 456 origin_, request.Pass(), response.Pass(), blob_data_handle.Pass(), |
456 pending_callback, request_context_, quota_manager_proxy_)); | 457 pending_callback, request_context_, quota_manager_proxy_)); |
457 | 458 |
458 if (put_context->blob_data_handle) { | 459 if (put_context->blob_data_handle) { |
459 // Grab another handle to the blob for the callback response. | 460 // Grab another handle to the blob for the callback response. |
460 put_context->out_blob_data_handle = | 461 put_context->out_blob_data_handle = |
461 blob_storage_context_->GetBlobDataFromUUID( | 462 blob_storage_context_->GetBlobDataFromUUID( |
462 put_context->response->blob_uuid); | 463 put_context->response->blob_uuid); |
463 } | 464 } |
464 | 465 |
465 pending_operations_.push_back(base::Bind(&ServiceWorkerCache::PutImpl, | 466 if (backend_state_ == BACKEND_UNINITIALIZED) |
| 467 InitBackend(); |
| 468 |
| 469 scheduler_->ScheduleOperation(base::Bind(&ServiceWorkerCache::PutImpl, |
466 weak_ptr_factory_.GetWeakPtr(), | 470 weak_ptr_factory_.GetWeakPtr(), |
467 base::Passed(put_context.Pass()))); | 471 base::Passed(put_context.Pass()))); |
468 | |
469 if (backend_state_ == BACKEND_UNINITIALIZED) { | |
470 InitBackend(); | |
471 return; | |
472 } | |
473 | |
474 RunOperationIfIdle(); | |
475 } | 472 } |
476 | 473 |
477 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, | 474 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, |
478 const ResponseCallback& callback) { | 475 const ResponseCallback& callback) { |
| 476 switch (backend_state_) { |
| 477 case BACKEND_UNINITIALIZED: |
| 478 InitBackend(); |
| 479 break; |
| 480 case BACKEND_CLOSED: |
| 481 callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), |
| 482 scoped_ptr<storage::BlobDataHandle>()); |
| 483 return; |
| 484 case BACKEND_OPEN: |
| 485 DCHECK(backend_); |
| 486 break; |
| 487 } |
| 488 |
479 ResponseCallback pending_callback = | 489 ResponseCallback pending_callback = |
480 base::Bind(&ServiceWorkerCache::PendingResponseCallback, | 490 base::Bind(&ServiceWorkerCache::PendingResponseCallback, |
481 weak_ptr_factory_.GetWeakPtr(), callback); | 491 weak_ptr_factory_.GetWeakPtr(), callback); |
482 pending_operations_.push_back( | 492 scheduler_->ScheduleOperation( |
483 base::Bind(&ServiceWorkerCache::MatchImpl, weak_ptr_factory_.GetWeakPtr(), | 493 base::Bind(&ServiceWorkerCache::MatchImpl, weak_ptr_factory_.GetWeakPtr(), |
484 base::Passed(request.Pass()), pending_callback)); | 494 base::Passed(request.Pass()), pending_callback)); |
485 | |
486 switch (backend_state_) { | |
487 case BACKEND_UNINITIALIZED: | |
488 InitBackend(); | |
489 return; | |
490 case BACKEND_CLOSED: | |
491 pending_callback.Run(ErrorTypeStorage, | |
492 scoped_ptr<ServiceWorkerResponse>(), | |
493 scoped_ptr<storage::BlobDataHandle>()); | |
494 return; | |
495 case BACKEND_OPEN: | |
496 DCHECK(backend_); | |
497 RunOperationIfIdle(); | |
498 return; | |
499 } | |
500 NOTREACHED(); | |
501 } | 495 } |
502 | 496 |
503 void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, | 497 void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, |
504 const ErrorCallback& callback) { | 498 const ErrorCallback& callback) { |
| 499 switch (backend_state_) { |
| 500 case BACKEND_UNINITIALIZED: |
| 501 InitBackend(); |
| 502 break; |
| 503 case BACKEND_CLOSED: |
| 504 callback.Run(ErrorTypeStorage); |
| 505 return; |
| 506 case BACKEND_OPEN: |
| 507 DCHECK(backend_); |
| 508 break; |
| 509 } |
505 ErrorCallback pending_callback = | 510 ErrorCallback pending_callback = |
506 base::Bind(&ServiceWorkerCache::PendingErrorCallback, | 511 base::Bind(&ServiceWorkerCache::PendingErrorCallback, |
507 weak_ptr_factory_.GetWeakPtr(), callback); | 512 weak_ptr_factory_.GetWeakPtr(), callback); |
508 pending_operations_.push_back(base::Bind( | 513 scheduler_->ScheduleOperation(base::Bind( |
509 &ServiceWorkerCache::DeleteImpl, weak_ptr_factory_.GetWeakPtr(), | 514 &ServiceWorkerCache::DeleteImpl, weak_ptr_factory_.GetWeakPtr(), |
510 base::Passed(request.Pass()), pending_callback)); | 515 base::Passed(request.Pass()), pending_callback)); |
| 516 } |
511 | 517 |
| 518 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { |
512 switch (backend_state_) { | 519 switch (backend_state_) { |
513 case BACKEND_UNINITIALIZED: | 520 case BACKEND_UNINITIALIZED: |
514 InitBackend(); | 521 InitBackend(); |
515 return; | 522 break; |
516 case BACKEND_CLOSED: | 523 case BACKEND_CLOSED: |
517 pending_callback.Run(ErrorTypeStorage); | 524 callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); |
518 return; | 525 return; |
519 case BACKEND_OPEN: | 526 case BACKEND_OPEN: |
520 DCHECK(backend_); | 527 DCHECK(backend_); |
521 RunOperationIfIdle(); | 528 break; |
522 return; | |
523 } | 529 } |
524 NOTREACHED(); | |
525 } | |
526 | 530 |
527 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { | |
528 RequestsCallback pending_callback = | 531 RequestsCallback pending_callback = |
529 base::Bind(&ServiceWorkerCache::PendingRequestsCallback, | 532 base::Bind(&ServiceWorkerCache::PendingRequestsCallback, |
530 weak_ptr_factory_.GetWeakPtr(), callback); | 533 weak_ptr_factory_.GetWeakPtr(), callback); |
531 pending_operations_.push_back(base::Bind(&ServiceWorkerCache::KeysImpl, | 534 scheduler_->ScheduleOperation(base::Bind(&ServiceWorkerCache::KeysImpl, |
532 weak_ptr_factory_.GetWeakPtr(), | 535 weak_ptr_factory_.GetWeakPtr(), |
533 pending_callback)); | 536 pending_callback)); |
534 | |
535 switch (backend_state_) { | |
536 case BACKEND_UNINITIALIZED: | |
537 InitBackend(); | |
538 return; | |
539 case BACKEND_CLOSED: | |
540 pending_callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); | |
541 return; | |
542 case BACKEND_OPEN: | |
543 DCHECK(backend_); | |
544 RunOperationIfIdle(); | |
545 return; | |
546 } | |
547 NOTREACHED(); | |
548 } | 537 } |
549 | 538 |
550 void ServiceWorkerCache::Close(const base::Closure& callback) { | 539 void ServiceWorkerCache::Close(const base::Closure& callback) { |
551 DCHECK(backend_state_ != BACKEND_CLOSED) | 540 DCHECK(backend_state_ != BACKEND_CLOSED) |
552 << "Don't call ServiceWorkerCache::Close() twice."; | 541 << "Don't call ServiceWorkerCache::Close() twice."; |
553 | 542 |
554 base::Closure pending_callback = | 543 base::Closure pending_callback = |
555 base::Bind(&ServiceWorkerCache::PendingClosure, | 544 base::Bind(&ServiceWorkerCache::PendingClosure, |
556 weak_ptr_factory_.GetWeakPtr(), callback); | 545 weak_ptr_factory_.GetWeakPtr(), callback); |
557 | 546 |
558 pending_operations_.push_back(base::Bind(&ServiceWorkerCache::CloseImpl, | 547 scheduler_->ScheduleOperation(base::Bind(&ServiceWorkerCache::CloseImpl, |
559 weak_ptr_factory_.GetWeakPtr(), | 548 weak_ptr_factory_.GetWeakPtr(), |
560 pending_callback)); | 549 pending_callback)); |
561 RunOperationIfIdle(); | |
562 } | 550 } |
563 | 551 |
564 int64 ServiceWorkerCache::MemoryBackedSize() const { | 552 int64 ServiceWorkerCache::MemoryBackedSize() const { |
565 if (backend_state_ != BACKEND_OPEN || !memory_only_) | 553 if (backend_state_ != BACKEND_OPEN || !memory_only_) |
566 return 0; | 554 return 0; |
567 | 555 |
568 scoped_ptr<disk_cache::Backend::Iterator> backend_iter = | 556 scoped_ptr<disk_cache::Backend::Iterator> backend_iter = |
569 backend_->CreateIterator(); | 557 backend_->CreateIterator(); |
570 disk_cache::Entry* entry = nullptr; | 558 disk_cache::Entry* entry = nullptr; |
571 | 559 |
(...skipping 22 matching lines...) Expand all Loading... |
594 const base::FilePath& path, | 582 const base::FilePath& path, |
595 net::URLRequestContext* request_context, | 583 net::URLRequestContext* request_context, |
596 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, | 584 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, |
597 base::WeakPtr<storage::BlobStorageContext> blob_context) | 585 base::WeakPtr<storage::BlobStorageContext> blob_context) |
598 : origin_(origin), | 586 : origin_(origin), |
599 path_(path), | 587 path_(path), |
600 request_context_(request_context), | 588 request_context_(request_context), |
601 quota_manager_proxy_(quota_manager_proxy), | 589 quota_manager_proxy_(quota_manager_proxy), |
602 blob_storage_context_(blob_context), | 590 blob_storage_context_(blob_context), |
603 backend_state_(BACKEND_UNINITIALIZED), | 591 backend_state_(BACKEND_UNINITIALIZED), |
604 operation_running_(false), | 592 scheduler_(new ServiceWorkerCacheScheduler()), |
605 initializing_(false), | 593 initializing_(false), |
606 memory_only_(path.empty()), | 594 memory_only_(path.empty()), |
607 weak_ptr_factory_(this) { | 595 weak_ptr_factory_(this) { |
608 } | 596 } |
609 | 597 |
610 void ServiceWorkerCache::MatchImpl( | 598 void ServiceWorkerCache::MatchImpl( |
611 scoped_ptr<ServiceWorkerFetchRequest> request, | 599 scoped_ptr<ServiceWorkerFetchRequest> request, |
612 const ResponseCallback& callback) { | 600 const ResponseCallback& callback) { |
613 DCHECK(backend_state_ != BACKEND_UNINITIALIZED); | 601 DCHECK(backend_state_ != BACKEND_UNINITIALIZED); |
614 if (backend_state_ != BACKEND_OPEN) { | 602 if (backend_state_ != BACKEND_OPEN) { |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 return; | 1186 return; |
1199 } | 1187 } |
1200 | 1188 |
1201 backend_ = backend_ptr->Pass(); | 1189 backend_ = backend_ptr->Pass(); |
1202 callback.Run(ServiceWorkerCache::ErrorTypeOK); | 1190 callback.Run(ServiceWorkerCache::ErrorTypeOK); |
1203 } | 1191 } |
1204 | 1192 |
1205 void ServiceWorkerCache::InitBackend() { | 1193 void ServiceWorkerCache::InitBackend() { |
1206 DCHECK(backend_state_ == BACKEND_UNINITIALIZED); | 1194 DCHECK(backend_state_ == BACKEND_UNINITIALIZED); |
1207 | 1195 |
1208 if (initializing_) { | 1196 if (initializing_) |
1209 DCHECK(operation_running_); | |
1210 return; | 1197 return; |
1211 } | |
1212 | 1198 |
1213 DCHECK(!operation_running_); // All ops should wait for backend init. | 1199 DCHECK(scheduler_->Empty()); |
1214 initializing_ = true; | 1200 initializing_ = true; |
1215 // Note that this operation pushes to the front of the queue. | 1201 |
1216 pending_operations_.push_front(base::Bind( | 1202 scheduler_->ScheduleOperation(base::Bind( |
1217 &ServiceWorkerCache::CreateBackend, weak_ptr_factory_.GetWeakPtr(), | 1203 &ServiceWorkerCache::CreateBackend, weak_ptr_factory_.GetWeakPtr(), |
1218 base::Bind(&ServiceWorkerCache::InitDone, | 1204 base::Bind(&ServiceWorkerCache::InitDone, |
1219 weak_ptr_factory_.GetWeakPtr()))); | 1205 weak_ptr_factory_.GetWeakPtr()))); |
1220 RunOperationIfIdle(); | |
1221 } | 1206 } |
1222 | 1207 |
1223 void ServiceWorkerCache::InitDone(ErrorType error) { | 1208 void ServiceWorkerCache::InitDone(ErrorType error) { |
1224 initializing_ = false; | 1209 initializing_ = false; |
1225 backend_state_ = (error == ErrorTypeOK && backend_ && | 1210 backend_state_ = (error == ErrorTypeOK && backend_ && |
1226 backend_state_ == BACKEND_UNINITIALIZED) | 1211 backend_state_ == BACKEND_UNINITIALIZED) |
1227 ? BACKEND_OPEN | 1212 ? BACKEND_OPEN |
1228 : BACKEND_CLOSED; | 1213 : BACKEND_CLOSED; |
1229 CompleteOperationAndRunNext(); | 1214 scheduler_->CompleteOperationAndRunNext(); |
1230 } | |
1231 | |
1232 void ServiceWorkerCache::CompleteOperationAndRunNext() { | |
1233 DCHECK(!pending_operations_.empty()); | |
1234 operation_running_ = false; | |
1235 pending_operations_.pop_front(); | |
1236 RunOperationIfIdle(); | |
1237 } | |
1238 | |
1239 void ServiceWorkerCache::RunOperationIfIdle() { | |
1240 DCHECK(!operation_running_ || !pending_operations_.empty()); | |
1241 | |
1242 if (!operation_running_ && !pending_operations_.empty()) { | |
1243 operation_running_ = true; | |
1244 // TODO(jkarlin): Run multiple operations in parallel where allowed (e.g., | |
1245 // if they're for different keys then they won't interfere). See | |
1246 // https://crbug.com/451174. | |
1247 pending_operations_.front().Run(); | |
1248 } | |
1249 } | 1215 } |
1250 | 1216 |
1251 void ServiceWorkerCache::PendingClosure(const base::Closure& callback) { | 1217 void ServiceWorkerCache::PendingClosure(const base::Closure& callback) { |
| 1218 base::WeakPtr<ServiceWorkerCache> cache = weak_ptr_factory_.GetWeakPtr(); |
| 1219 |
1252 callback.Run(); | 1220 callback.Run(); |
1253 CompleteOperationAndRunNext(); | 1221 if (cache) |
| 1222 scheduler_->CompleteOperationAndRunNext(); |
1254 } | 1223 } |
1255 | 1224 |
1256 void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback, | 1225 void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback, |
1257 ErrorType error) { | 1226 ErrorType error) { |
| 1227 base::WeakPtr<ServiceWorkerCache> cache = weak_ptr_factory_.GetWeakPtr(); |
| 1228 |
1258 callback.Run(error); | 1229 callback.Run(error); |
1259 CompleteOperationAndRunNext(); | 1230 if (cache) |
| 1231 scheduler_->CompleteOperationAndRunNext(); |
1260 } | 1232 } |
1261 | 1233 |
1262 void ServiceWorkerCache::PendingResponseCallback( | 1234 void ServiceWorkerCache::PendingResponseCallback( |
1263 const ResponseCallback& callback, | 1235 const ResponseCallback& callback, |
1264 ErrorType error, | 1236 ErrorType error, |
1265 scoped_ptr<ServiceWorkerResponse> response, | 1237 scoped_ptr<ServiceWorkerResponse> response, |
1266 scoped_ptr<storage::BlobDataHandle> blob_data_handle) { | 1238 scoped_ptr<storage::BlobDataHandle> blob_data_handle) { |
| 1239 base::WeakPtr<ServiceWorkerCache> cache = weak_ptr_factory_.GetWeakPtr(); |
| 1240 |
1267 callback.Run(error, response.Pass(), blob_data_handle.Pass()); | 1241 callback.Run(error, response.Pass(), blob_data_handle.Pass()); |
1268 CompleteOperationAndRunNext(); | 1242 if (cache) |
| 1243 scheduler_->CompleteOperationAndRunNext(); |
1269 } | 1244 } |
1270 | 1245 |
1271 void ServiceWorkerCache::PendingRequestsCallback( | 1246 void ServiceWorkerCache::PendingRequestsCallback( |
1272 const RequestsCallback& callback, | 1247 const RequestsCallback& callback, |
1273 ErrorType error, | 1248 ErrorType error, |
1274 scoped_ptr<Requests> requests) { | 1249 scoped_ptr<Requests> requests) { |
| 1250 base::WeakPtr<ServiceWorkerCache> cache = weak_ptr_factory_.GetWeakPtr(); |
| 1251 |
1275 callback.Run(error, requests.Pass()); | 1252 callback.Run(error, requests.Pass()); |
1276 CompleteOperationAndRunNext(); | 1253 if (cache) |
| 1254 scheduler_->CompleteOperationAndRunNext(); |
1277 } | 1255 } |
1278 | 1256 |
1279 } // namespace content | 1257 } // namespace content |
OLD | NEW |