| 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 |