OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_storage.h" | 5 #include "content/browser/service_worker/service_worker_storage.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 base::Owned(registrations))); | 264 base::Owned(registrations))); |
265 } | 265 } |
266 | 266 |
267 void ServiceWorkerStorage::StoreRegistration( | 267 void ServiceWorkerStorage::StoreRegistration( |
268 ServiceWorkerRegistration* registration, | 268 ServiceWorkerRegistration* registration, |
269 ServiceWorkerVersion* version, | 269 ServiceWorkerVersion* version, |
270 const StatusCallback& callback) { | 270 const StatusCallback& callback) { |
271 DCHECK(registration); | 271 DCHECK(registration); |
272 DCHECK(version); | 272 DCHECK(version); |
273 | 273 |
274 DCHECK(state_ == INITIALIZED || state_ == DISABLED); | 274 DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_; |
275 if (state_ != INITIALIZED || !context_) { | 275 if (IsDisabled() || !context_) { |
276 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); | 276 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); |
277 return; | 277 return; |
278 } | 278 } |
279 | 279 |
280 ServiceWorkerDatabase::RegistrationData data; | 280 ServiceWorkerDatabase::RegistrationData data; |
281 data.registration_id = registration->id(); | 281 data.registration_id = registration->id(); |
282 data.scope = registration->pattern(); | 282 data.scope = registration->pattern(); |
283 data.script = registration->script_url(); | 283 data.script = registration->script_url(); |
284 data.has_fetch_handler = true; | 284 data.has_fetch_handler = true; |
285 data.version_id = version->version_id(); | 285 data.version_id = version->version_id(); |
286 data.last_update_check = base::Time::Now(); | 286 data.last_update_check = base::Time::Now(); |
287 data.is_active = false; // initially stored in the waiting state | 287 data.is_active = false; // initially stored in the waiting state |
288 | 288 |
289 ResourceList resources; | 289 ResourceList resources; |
290 version->script_cache_map()->GetResources(&resources); | 290 version->script_cache_map()->GetResources(&resources); |
291 | 291 |
| 292 if (!has_checked_for_stale_resources_) |
| 293 DeleteStaleResources(); |
| 294 |
292 database_task_runner_->PostTask( | 295 database_task_runner_->PostTask( |
293 FROM_HERE, | 296 FROM_HERE, |
294 base::Bind(&WriteRegistrationInDB, | 297 base::Bind(&WriteRegistrationInDB, |
295 database_.get(), | 298 database_.get(), |
296 base::MessageLoopProxy::current(), | 299 base::MessageLoopProxy::current(), |
297 data, resources, | 300 data, resources, |
298 base::Bind(&ServiceWorkerStorage::DidStoreRegistration, | 301 base::Bind(&ServiceWorkerStorage::DidStoreRegistration, |
299 weak_factory_.GetWeakPtr(), | 302 weak_factory_.GetWeakPtr(), |
300 callback))); | 303 callback))); |
301 } | 304 } |
302 | 305 |
303 void ServiceWorkerStorage::UpdateToActiveState( | 306 void ServiceWorkerStorage::UpdateToActiveState( |
304 ServiceWorkerRegistration* registration, | 307 ServiceWorkerRegistration* registration, |
305 const StatusCallback& callback) { | 308 const StatusCallback& callback) { |
306 DCHECK(registration); | 309 DCHECK(registration); |
307 | 310 |
308 DCHECK(state_ == INITIALIZED || state_ == DISABLED); | 311 DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_; |
309 if (state_ != INITIALIZED || !context_) { | 312 if (IsDisabled() || !context_) { |
310 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); | 313 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); |
311 return; | 314 return; |
312 } | 315 } |
313 | 316 |
314 PostTaskAndReplyWithResult( | 317 PostTaskAndReplyWithResult( |
315 database_task_runner_, | 318 database_task_runner_, |
316 FROM_HERE, | 319 FROM_HERE, |
317 base::Bind(&ServiceWorkerDatabase::UpdateVersionToActive, | 320 base::Bind(&ServiceWorkerDatabase::UpdateVersionToActive, |
318 base::Unretained(database_.get()), | 321 base::Unretained(database_.get()), |
319 registration->id(), | 322 registration->id(), |
320 registration->script_url().GetOrigin()), | 323 registration->script_url().GetOrigin()), |
321 base::Bind(&ServiceWorkerStorage::DidUpdateToActiveState, | 324 base::Bind(&ServiceWorkerStorage::DidUpdateToActiveState, |
322 weak_factory_.GetWeakPtr(), | 325 weak_factory_.GetWeakPtr(), |
323 callback)); | 326 callback)); |
324 } | 327 } |
325 | 328 |
326 void ServiceWorkerStorage::DeleteRegistration( | 329 void ServiceWorkerStorage::DeleteRegistration( |
327 int64 registration_id, | 330 int64 registration_id, |
328 const GURL& origin, | 331 const GURL& origin, |
329 const StatusCallback& callback) { | 332 const StatusCallback& callback) { |
330 DCHECK(state_ == INITIALIZED || state_ == DISABLED); | 333 DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_; |
331 if (state_ != INITIALIZED || !context_) { | 334 if (IsDisabled() || !context_) { |
332 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); | 335 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); |
333 return; | 336 return; |
334 } | 337 } |
335 | 338 |
| 339 if (!has_checked_for_stale_resources_) |
| 340 DeleteStaleResources(); |
| 341 |
336 database_task_runner_->PostTask( | 342 database_task_runner_->PostTask( |
337 FROM_HERE, | 343 FROM_HERE, |
338 base::Bind(&DeleteRegistrationFromDB, | 344 base::Bind(&DeleteRegistrationFromDB, |
339 database_.get(), | 345 database_.get(), |
340 base::MessageLoopProxy::current(), | 346 base::MessageLoopProxy::current(), |
341 registration_id, origin, | 347 registration_id, origin, |
342 base::Bind(&ServiceWorkerStorage::DidDeleteRegistration, | 348 base::Bind(&ServiceWorkerStorage::DidDeleteRegistration, |
343 weak_factory_.GetWeakPtr(), origin, callback))); | 349 weak_factory_.GetWeakPtr(), origin, callback))); |
344 | 350 |
345 // TODO(michaeln): Either its instance should also be | 351 // TODO(michaeln): Either its instance should also be |
346 // removed from liveregistrations map or the live object | 352 // removed from liveregistrations map or the live object |
347 // should marked as deleted in some way and not 'findable' | 353 // should marked as deleted in some way and not 'findable' |
348 // thereafter. | 354 // thereafter. |
349 } | 355 } |
350 | 356 |
351 scoped_ptr<ServiceWorkerResponseReader> | 357 scoped_ptr<ServiceWorkerResponseReader> |
352 ServiceWorkerStorage::CreateResponseReader(int64 response_id) { | 358 ServiceWorkerStorage::CreateResponseReader(int64 response_id) { |
353 return make_scoped_ptr( | 359 return make_scoped_ptr( |
354 new ServiceWorkerResponseReader(response_id, disk_cache())); | 360 new ServiceWorkerResponseReader(response_id, disk_cache())); |
355 } | 361 } |
356 | 362 |
357 scoped_ptr<ServiceWorkerResponseWriter> | 363 scoped_ptr<ServiceWorkerResponseWriter> |
358 ServiceWorkerStorage::CreateResponseWriter(int64 response_id) { | 364 ServiceWorkerStorage::CreateResponseWriter(int64 response_id) { |
359 return make_scoped_ptr( | 365 return make_scoped_ptr( |
360 new ServiceWorkerResponseWriter(response_id, disk_cache())); | 366 new ServiceWorkerResponseWriter(response_id, disk_cache())); |
361 } | 367 } |
362 | 368 |
363 void ServiceWorkerStorage::StoreUncommittedReponseId(int64 id) { | 369 void ServiceWorkerStorage::StoreUncommittedResponseId(int64 id) { |
364 DCHECK_NE(kInvalidServiceWorkerResponseId, id); | 370 DCHECK_NE(kInvalidServiceWorkerResponseId, id); |
| 371 DCHECK_EQ(INITIALIZED, state_); |
| 372 |
| 373 if (!has_checked_for_stale_resources_) |
| 374 DeleteStaleResources(); |
| 375 |
365 database_task_runner_->PostTask( | 376 database_task_runner_->PostTask( |
366 FROM_HERE, | 377 FROM_HERE, |
367 base::Bind(base::IgnoreResult( | 378 base::Bind(base::IgnoreResult( |
368 &ServiceWorkerDatabase::WriteUncommittedResourceIds), | 379 &ServiceWorkerDatabase::WriteUncommittedResourceIds), |
369 base::Unretained(database_.get()), | 380 base::Unretained(database_.get()), |
370 std::set<int64>(&id, &id + 1))); | 381 std::set<int64>(&id, &id + 1))); |
371 } | 382 } |
372 | 383 |
373 void ServiceWorkerStorage::DoomUncommittedResponse(int64 id) { | 384 void ServiceWorkerStorage::DoomUncommittedResponse(int64 id) { |
374 DCHECK_NE(kInvalidServiceWorkerResponseId, id); | 385 DCHECK_NE(kInvalidServiceWorkerResponseId, id); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 : next_registration_id_(kInvalidServiceWorkerRegistrationId), | 474 : next_registration_id_(kInvalidServiceWorkerRegistrationId), |
464 next_version_id_(kInvalidServiceWorkerVersionId), | 475 next_version_id_(kInvalidServiceWorkerVersionId), |
465 next_resource_id_(kInvalidServiceWorkerResourceId), | 476 next_resource_id_(kInvalidServiceWorkerResourceId), |
466 state_(UNINITIALIZED), | 477 state_(UNINITIALIZED), |
467 path_(path), | 478 path_(path), |
468 context_(context), | 479 context_(context), |
469 database_task_runner_(database_task_runner), | 480 database_task_runner_(database_task_runner), |
470 disk_cache_thread_(disk_cache_thread), | 481 disk_cache_thread_(disk_cache_thread), |
471 quota_manager_proxy_(quota_manager_proxy), | 482 quota_manager_proxy_(quota_manager_proxy), |
472 is_purge_pending_(false), | 483 is_purge_pending_(false), |
| 484 has_checked_for_stale_resources_(false), |
473 weak_factory_(this) { | 485 weak_factory_(this) { |
474 database_.reset(new ServiceWorkerDatabase(GetDatabasePath())); | 486 database_.reset(new ServiceWorkerDatabase(GetDatabasePath())); |
475 } | 487 } |
476 | 488 |
477 base::FilePath ServiceWorkerStorage::GetDatabasePath() { | 489 base::FilePath ServiceWorkerStorage::GetDatabasePath() { |
478 if (path_.empty()) | 490 if (path_.empty()) |
479 return base::FilePath(); | 491 return base::FilePath(); |
480 return path_.Append(kServiceWorkerDirectory).Append(kDatabaseName); | 492 return path_.Append(kServiceWorkerDirectory).Append(kDatabaseName); |
481 } | 493 } |
482 | 494 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 ServiceWorkerDatabase::Status status) { | 531 ServiceWorkerDatabase::Status status) { |
520 DCHECK(data); | 532 DCHECK(data); |
521 DCHECK_EQ(INITIALIZING, state_); | 533 DCHECK_EQ(INITIALIZING, state_); |
522 | 534 |
523 if (status == ServiceWorkerDatabase::STATUS_OK) { | 535 if (status == ServiceWorkerDatabase::STATUS_OK) { |
524 next_registration_id_ = data->next_registration_id; | 536 next_registration_id_ = data->next_registration_id; |
525 next_version_id_ = data->next_version_id; | 537 next_version_id_ = data->next_version_id; |
526 next_resource_id_ = data->next_resource_id; | 538 next_resource_id_ = data->next_resource_id; |
527 registered_origins_.swap(data->origins); | 539 registered_origins_.swap(data->origins); |
528 state_ = INITIALIZED; | 540 state_ = INITIALIZED; |
529 StartPurgingResources( | |
530 std::vector<int64>(data->purgeable_resource_ids.begin(), | |
531 data->purgeable_resource_ids.end())); | |
532 } else { | 541 } else { |
533 // TODO(nhiroki): Stringify |status| using StatusToString() defined in | 542 // TODO(nhiroki): Stringify |status| using StatusToString() defined in |
534 // service_worker_database.cc. | 543 // service_worker_database.cc. |
535 DVLOG(2) << "Failed to initialize: " << status; | 544 DVLOG(2) << "Failed to initialize: " << status; |
536 ScheduleDeleteAndStartOver(); | 545 ScheduleDeleteAndStartOver(); |
537 } | 546 } |
538 | 547 |
539 for (std::vector<base::Closure>::const_iterator it = pending_tasks_.begin(); | 548 for (std::vector<base::Closure>::const_iterator it = pending_tasks_.begin(); |
540 it != pending_tasks_.end(); ++it) { | 549 it != pending_tasks_.end(); ++it) { |
541 RunSoon(FROM_HERE, *it); | 550 RunSoon(FROM_HERE, *it); |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 if (version && version->HasControllee()) { | 865 if (version && version->HasControllee()) { |
857 deleted_version_resource_ids_[version_id] = resources; | 866 deleted_version_resource_ids_[version_id] = resources; |
858 version->AddListener(this); | 867 version->AddListener(this); |
859 } else { | 868 } else { |
860 StartPurgingResources(resources); | 869 StartPurgingResources(resources); |
861 } | 870 } |
862 } | 871 } |
863 | 872 |
864 void ServiceWorkerStorage::StartPurgingResources( | 873 void ServiceWorkerStorage::StartPurgingResources( |
865 const std::vector<int64>& ids) { | 874 const std::vector<int64>& ids) { |
| 875 DCHECK(has_checked_for_stale_resources_); |
866 for (size_t i = 0; i < ids.size(); ++i) | 876 for (size_t i = 0; i < ids.size(); ++i) |
867 purgeable_resource_ids_.push_back(ids[i]); | 877 purgeable_resource_ids_.push_back(ids[i]); |
868 ContinuePurgingResources(); | 878 ContinuePurgingResources(); |
869 } | 879 } |
870 | 880 |
871 void ServiceWorkerStorage::StartPurgingResources( | 881 void ServiceWorkerStorage::StartPurgingResources( |
872 const ResourceList& resources) { | 882 const ResourceList& resources) { |
| 883 DCHECK(has_checked_for_stale_resources_); |
873 for (size_t i = 0; i < resources.size(); ++i) | 884 for (size_t i = 0; i < resources.size(); ++i) |
874 purgeable_resource_ids_.push_back(resources[i].resource_id); | 885 purgeable_resource_ids_.push_back(resources[i].resource_id); |
875 ContinuePurgingResources(); | 886 ContinuePurgingResources(); |
876 } | 887 } |
877 | 888 |
878 void ServiceWorkerStorage::ContinuePurgingResources() { | 889 void ServiceWorkerStorage::ContinuePurgingResources() { |
879 if (purgeable_resource_ids_.empty() || is_purge_pending_) | 890 if (purgeable_resource_ids_.empty() || is_purge_pending_) |
880 return; | 891 return; |
881 | 892 |
882 // Do one at a time until we're done, use RunSoon to avoid recursion when | 893 // Do one at a time until we're done, use RunSoon to avoid recursion when |
(...skipping 22 matching lines...) Expand all Loading... |
905 database_task_runner_->PostTask( | 916 database_task_runner_->PostTask( |
906 FROM_HERE, | 917 FROM_HERE, |
907 base::Bind(base::IgnoreResult( | 918 base::Bind(base::IgnoreResult( |
908 &ServiceWorkerDatabase::ClearPurgeableResourceIds), | 919 &ServiceWorkerDatabase::ClearPurgeableResourceIds), |
909 base::Unretained(database_.get()), | 920 base::Unretained(database_.get()), |
910 std::set<int64>(&id, &id + 1))); | 921 std::set<int64>(&id, &id + 1))); |
911 | 922 |
912 ContinuePurgingResources(); | 923 ContinuePurgingResources(); |
913 } | 924 } |
914 | 925 |
| 926 void ServiceWorkerStorage::DeleteStaleResources() { |
| 927 DCHECK(!has_checked_for_stale_resources_); |
| 928 has_checked_for_stale_resources_ = true; |
| 929 database_task_runner_->PostTask( |
| 930 FROM_HERE, |
| 931 base::Bind(&ServiceWorkerStorage::CollectStaleResourcesFromDB, |
| 932 database_.get(), |
| 933 base::MessageLoopProxy::current(), |
| 934 base::Bind(&ServiceWorkerStorage::DidCollectStaleResources, |
| 935 weak_factory_.GetWeakPtr()))); |
| 936 } |
| 937 |
| 938 void ServiceWorkerStorage::DidCollectStaleResources( |
| 939 const std::vector<int64>& stale_resource_ids, |
| 940 ServiceWorkerDatabase::Status status) { |
| 941 DCHECK_EQ(ServiceWorkerDatabase::STATUS_OK, status); |
| 942 if (status != ServiceWorkerDatabase::STATUS_OK) |
| 943 return; |
| 944 StartPurgingResources(stale_resource_ids); |
| 945 } |
| 946 |
| 947 void ServiceWorkerStorage::CollectStaleResourcesFromDB( |
| 948 ServiceWorkerDatabase* database, |
| 949 scoped_refptr<base::SequencedTaskRunner> original_task_runner, |
| 950 const GetResourcesCallback& callback) { |
| 951 std::set<int64> ids; |
| 952 ServiceWorkerDatabase::Status status = |
| 953 database->GetUncommittedResourceIds(&ids); |
| 954 if (status != ServiceWorkerDatabase::STATUS_OK) { |
| 955 original_task_runner->PostTask( |
| 956 FROM_HERE, |
| 957 base::Bind( |
| 958 callback, std::vector<int64>(ids.begin(), ids.end()), status)); |
| 959 return; |
| 960 } |
| 961 |
| 962 status = database->PurgeUncommittedResourceIds(ids); |
| 963 if (status != ServiceWorkerDatabase::STATUS_OK) { |
| 964 original_task_runner->PostTask( |
| 965 FROM_HERE, |
| 966 base::Bind( |
| 967 callback, std::vector<int64>(ids.begin(), ids.end()), status)); |
| 968 return; |
| 969 } |
| 970 |
| 971 ids.clear(); |
| 972 status = database->GetPurgeableResourceIds(&ids); |
| 973 original_task_runner->PostTask( |
| 974 FROM_HERE, |
| 975 base::Bind(callback, std::vector<int64>(ids.begin(), ids.end()), status)); |
| 976 } |
| 977 |
915 void ServiceWorkerStorage::ReadInitialDataFromDB( | 978 void ServiceWorkerStorage::ReadInitialDataFromDB( |
916 ServiceWorkerDatabase* database, | 979 ServiceWorkerDatabase* database, |
917 scoped_refptr<base::SequencedTaskRunner> original_task_runner, | 980 scoped_refptr<base::SequencedTaskRunner> original_task_runner, |
918 const InitializeCallback& callback) { | 981 const InitializeCallback& callback) { |
919 DCHECK(database); | 982 DCHECK(database); |
920 scoped_ptr<ServiceWorkerStorage::InitialData> data( | 983 scoped_ptr<ServiceWorkerStorage::InitialData> data( |
921 new ServiceWorkerStorage::InitialData()); | 984 new ServiceWorkerStorage::InitialData()); |
922 | 985 |
923 ServiceWorkerDatabase::Status status = | 986 ServiceWorkerDatabase::Status status = |
924 database->GetNextAvailableIds(&data->next_registration_id, | 987 database->GetNextAvailableIds(&data->next_registration_id, |
925 &data->next_version_id, | 988 &data->next_version_id, |
926 &data->next_resource_id); | 989 &data->next_resource_id); |
927 if (status != ServiceWorkerDatabase::STATUS_OK) { | 990 if (status != ServiceWorkerDatabase::STATUS_OK) { |
928 original_task_runner->PostTask( | 991 original_task_runner->PostTask( |
929 FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); | 992 FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); |
930 return; | 993 return; |
931 } | 994 } |
932 | 995 |
933 status = database->GetOriginsWithRegistrations(&data->origins); | 996 status = database->GetOriginsWithRegistrations(&data->origins); |
934 if (status != ServiceWorkerDatabase::STATUS_OK) { | |
935 original_task_runner->PostTask( | |
936 FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); | |
937 return; | |
938 } | |
939 | |
940 // TODO: Also purge uncommitted resources. | |
941 status = database->GetPurgeableResourceIds(&data->purgeable_resource_ids); | |
942 original_task_runner->PostTask( | 997 original_task_runner->PostTask( |
943 FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); | 998 FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); |
944 } | 999 } |
945 | 1000 |
946 void ServiceWorkerStorage::DeleteRegistrationFromDB( | 1001 void ServiceWorkerStorage::DeleteRegistrationFromDB( |
947 ServiceWorkerDatabase* database, | 1002 ServiceWorkerDatabase* database, |
948 scoped_refptr<base::SequencedTaskRunner> original_task_runner, | 1003 scoped_refptr<base::SequencedTaskRunner> original_task_runner, |
949 int64 registration_id, | 1004 int64 registration_id, |
950 const GURL& origin, | 1005 const GURL& origin, |
951 const DeleteRegistrationCallback& callback) { | 1006 const DeleteRegistrationCallback& callback) { |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 // Give up the corruption recovery until the browser restarts. | 1196 // Give up the corruption recovery until the browser restarts. |
1142 LOG(ERROR) << "Failed to delete the diskcache."; | 1197 LOG(ERROR) << "Failed to delete the diskcache."; |
1143 callback.Run(SERVICE_WORKER_ERROR_FAILED); | 1198 callback.Run(SERVICE_WORKER_ERROR_FAILED); |
1144 return; | 1199 return; |
1145 } | 1200 } |
1146 DVLOG(1) << "Deleted ServiceWorkerDiskCache successfully."; | 1201 DVLOG(1) << "Deleted ServiceWorkerDiskCache successfully."; |
1147 callback.Run(SERVICE_WORKER_OK); | 1202 callback.Run(SERVICE_WORKER_OK); |
1148 } | 1203 } |
1149 | 1204 |
1150 } // namespace content | 1205 } // namespace content |
OLD | NEW |