| 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_database.h" | 5 #include "content/browser/service_worker/service_worker_database.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 GURL url(record.url()); | 204 GURL url(record.url()); |
| 205 if (!url.is_valid()) | 205 if (!url.is_valid()) |
| 206 return false; | 206 return false; |
| 207 | 207 |
| 208 // Convert ServiceWorkerResourceRecord to ResourceRecord. | 208 // Convert ServiceWorkerResourceRecord to ResourceRecord. |
| 209 out->resource_id = record.resource_id(); | 209 out->resource_id = record.resource_id(); |
| 210 out->url = url; | 210 out->url = url; |
| 211 return true; | 211 return true; |
| 212 } | 212 } |
| 213 | 213 |
| 214 ServiceWorkerStatusCode LevelDBStatusToServiceWorkerStatusCode( | 214 ServiceWorkerDatabase::Status LevelDBStatusToStatus( |
| 215 const leveldb::Status& status) { | 215 const leveldb::Status& status) { |
| 216 if (status.ok()) | 216 if (status.ok()) |
| 217 return SERVICE_WORKER_OK; | 217 return ServiceWorkerDatabase::STATUS_OK; |
| 218 else if (status.IsNotFound()) | 218 else if (status.IsNotFound()) |
| 219 return SERVICE_WORKER_ERROR_NOT_FOUND; | 219 return ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND; |
| 220 else if (status.IsCorruption()) | 220 else if (status.IsCorruption()) |
| 221 return SERVICE_WORKER_ERROR_DB_CORRUPTED; | 221 return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED; |
| 222 else | 222 else |
| 223 return SERVICE_WORKER_ERROR_FAILED; | 223 return ServiceWorkerDatabase::STATUS_ERROR_FAILED; |
| 224 } | 224 } |
| 225 | 225 |
| 226 } // namespace | 226 } // namespace |
| 227 | 227 |
| 228 ServiceWorkerDatabase::RegistrationData::RegistrationData() | 228 ServiceWorkerDatabase::RegistrationData::RegistrationData() |
| 229 : registration_id(-1), | 229 : registration_id(-1), |
| 230 version_id(-1), | 230 version_id(-1), |
| 231 is_active(false), | 231 is_active(false), |
| 232 has_fetch_handler(false) { | 232 has_fetch_handler(false) { |
| 233 } | 233 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 244 was_corruption_detected_(false), | 244 was_corruption_detected_(false), |
| 245 is_initialized_(false) { | 245 is_initialized_(false) { |
| 246 sequence_checker_.DetachFromSequence(); | 246 sequence_checker_.DetachFromSequence(); |
| 247 } | 247 } |
| 248 | 248 |
| 249 ServiceWorkerDatabase::~ServiceWorkerDatabase() { | 249 ServiceWorkerDatabase::~ServiceWorkerDatabase() { |
| 250 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 250 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 251 db_.reset(); | 251 db_.reset(); |
| 252 } | 252 } |
| 253 | 253 |
| 254 ServiceWorkerStatusCode ServiceWorkerDatabase::GetNextAvailableIds( | 254 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetNextAvailableIds( |
| 255 int64* next_avail_registration_id, | 255 int64* next_avail_registration_id, |
| 256 int64* next_avail_version_id, | 256 int64* next_avail_version_id, |
| 257 int64* next_avail_resource_id) { | 257 int64* next_avail_resource_id) { |
| 258 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 258 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 259 DCHECK(next_avail_registration_id); | 259 DCHECK(next_avail_registration_id); |
| 260 DCHECK(next_avail_version_id); | 260 DCHECK(next_avail_version_id); |
| 261 DCHECK(next_avail_resource_id); | 261 DCHECK(next_avail_resource_id); |
| 262 | 262 |
| 263 if (!LazyOpen(false)) { | 263 Status status = LazyOpen(false); |
| 264 if (is_disabled_) | 264 if (IsNewOrNonexistentDatabase(status)) { |
| 265 return SERVICE_WORKER_ERROR_FAILED; | |
| 266 // Database has never been used. | |
| 267 *next_avail_registration_id = 0; | 265 *next_avail_registration_id = 0; |
| 268 *next_avail_version_id = 0; | 266 *next_avail_version_id = 0; |
| 269 *next_avail_resource_id = 0; | 267 *next_avail_resource_id = 0; |
| 270 return SERVICE_WORKER_OK; | 268 return STATUS_OK; |
| 271 } | 269 } |
| 270 if (status != STATUS_OK) |
| 271 return status; |
| 272 | 272 |
| 273 ServiceWorkerStatusCode status = | 273 status = ReadNextAvailableId(kNextRegIdKey, &next_avail_registration_id_); |
| 274 ReadNextAvailableId(kNextRegIdKey, &next_avail_registration_id_); | 274 if (status != STATUS_OK) |
| 275 if (status != SERVICE_WORKER_OK) | |
| 276 return status; | 275 return status; |
| 277 status = ReadNextAvailableId(kNextVerIdKey, &next_avail_version_id_); | 276 status = ReadNextAvailableId(kNextVerIdKey, &next_avail_version_id_); |
| 278 if (status != SERVICE_WORKER_OK) | 277 if (status != STATUS_OK) |
| 279 return status; | 278 return status; |
| 280 status = ReadNextAvailableId(kNextResIdKey, &next_avail_resource_id_); | 279 status = ReadNextAvailableId(kNextResIdKey, &next_avail_resource_id_); |
| 281 if (status != SERVICE_WORKER_OK) | 280 if (status != STATUS_OK) |
| 282 return status; | 281 return status; |
| 283 | 282 |
| 284 *next_avail_registration_id = next_avail_registration_id_; | 283 *next_avail_registration_id = next_avail_registration_id_; |
| 285 *next_avail_version_id = next_avail_version_id_; | 284 *next_avail_version_id = next_avail_version_id_; |
| 286 *next_avail_resource_id = next_avail_resource_id_; | 285 *next_avail_resource_id = next_avail_resource_id_; |
| 287 return SERVICE_WORKER_OK; | 286 return STATUS_OK; |
| 288 } | 287 } |
| 289 | 288 |
| 290 ServiceWorkerStatusCode ServiceWorkerDatabase::GetOriginsWithRegistrations( | 289 ServiceWorkerDatabase::Status |
| 291 std::set<GURL>* origins) { | 290 ServiceWorkerDatabase::GetOriginsWithRegistrations(std::set<GURL>* origins) { |
| 292 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 291 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 293 DCHECK(origins); | 292 DCHECK(origins->empty()); |
| 294 | 293 |
| 295 if (!LazyOpen(false)) { | 294 Status status = LazyOpen(false); |
| 296 if (is_disabled_) | 295 if (IsNewOrNonexistentDatabase(status)) |
| 297 return SERVICE_WORKER_ERROR_FAILED; | 296 return STATUS_OK; |
| 298 // Database has never been used. | 297 if (status != STATUS_OK) |
| 299 origins->clear(); | 298 return status; |
| 300 return SERVICE_WORKER_OK; | |
| 301 } | |
| 302 | 299 |
| 303 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); | 300 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
| 304 for (itr->Seek(kUniqueOriginKey); itr->Valid(); itr->Next()) { | 301 for (itr->Seek(kUniqueOriginKey); itr->Valid(); itr->Next()) { |
| 305 if (!itr->status().ok()) { | 302 if (!itr->status().ok()) { |
| 306 HandleError(FROM_HERE, itr->status()); | 303 HandleError(FROM_HERE, itr->status()); |
| 307 origins->clear(); | 304 origins->clear(); |
| 308 return LevelDBStatusToServiceWorkerStatusCode(itr->status()); | 305 return LevelDBStatusToStatus(itr->status()); |
| 309 } | 306 } |
| 310 | 307 |
| 311 std::string origin; | 308 std::string origin; |
| 312 if (!RemovePrefix(itr->key().ToString(), kUniqueOriginKey, &origin)) | 309 if (!RemovePrefix(itr->key().ToString(), kUniqueOriginKey, &origin)) |
| 313 break; | 310 break; |
| 314 origins->insert(GURL(origin)); | 311 origins->insert(GURL(origin)); |
| 315 } | 312 } |
| 316 return SERVICE_WORKER_OK; | 313 return STATUS_OK; |
| 317 } | 314 } |
| 318 | 315 |
| 319 bool ServiceWorkerDatabase::GetRegistrationsForOrigin( | 316 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetRegistrationsForOrigin( |
| 320 const GURL& origin, | 317 const GURL& origin, |
| 321 std::vector<RegistrationData>* registrations) { | 318 std::vector<RegistrationData>* registrations) { |
| 322 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 319 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 323 DCHECK(registrations); | 320 DCHECK(registrations->empty()); |
| 324 | 321 |
| 325 if (!LazyOpen(false)) { | 322 Status status = LazyOpen(false); |
| 326 if (is_disabled_) | 323 if (IsNewOrNonexistentDatabase(status)) |
| 327 return false; | 324 return STATUS_OK; |
| 328 // Database has never been used. | 325 if (status != STATUS_OK) |
| 329 registrations->clear(); | 326 return status; |
| 330 return true; | |
| 331 } | |
| 332 | 327 |
| 333 // Create a key prefix for registrations. | 328 // Create a key prefix for registrations. |
| 334 std::string prefix = base::StringPrintf( | 329 std::string prefix = base::StringPrintf( |
| 335 "%s%s%c", kRegKeyPrefix, origin.spec().c_str(), kKeySeparator); | 330 "%s%s%c", kRegKeyPrefix, origin.spec().c_str(), kKeySeparator); |
| 336 | 331 |
| 337 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); | 332 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
| 338 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { | 333 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { |
| 339 if (!itr->status().ok()) { | 334 if (!itr->status().ok()) { |
| 340 HandleError(FROM_HERE, itr->status()); | 335 HandleError(FROM_HERE, itr->status()); |
| 341 registrations->clear(); | 336 registrations->clear(); |
| 342 return false; | 337 return LevelDBStatusToStatus(itr->status()); |
| 343 } | 338 } |
| 344 | 339 |
| 345 if (!RemovePrefix(itr->key().ToString(), prefix, NULL)) | 340 if (!RemovePrefix(itr->key().ToString(), prefix, NULL)) |
| 346 break; | 341 break; |
| 347 | 342 |
| 348 RegistrationData registration; | 343 RegistrationData registration; |
| 349 if (!ParseRegistrationData(itr->value().ToString(), ®istration)) { | 344 if (!ParseRegistrationData(itr->value().ToString(), ®istration)) { |
| 350 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 345 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 351 registrations->clear(); | 346 registrations->clear(); |
| 352 return false; | 347 return STATUS_ERROR_CORRUPTED; |
| 353 } | 348 } |
| 354 registrations->push_back(registration); | 349 registrations->push_back(registration); |
| 355 } | 350 } |
| 356 return true; | 351 return STATUS_OK; |
| 357 } | 352 } |
| 358 | 353 |
| 359 bool ServiceWorkerDatabase::GetAllRegistrations( | 354 ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetAllRegistrations( |
| 360 std::vector<RegistrationData>* registrations) { | 355 std::vector<RegistrationData>* registrations) { |
| 361 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 356 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 362 DCHECK(registrations); | 357 DCHECK(registrations->empty()); |
| 363 | 358 |
| 364 if (!LazyOpen(false)) { | 359 Status status = LazyOpen(false); |
| 365 if (is_disabled_) | 360 if (IsNewOrNonexistentDatabase(status)) |
| 366 return false; | 361 return STATUS_OK; |
| 367 // Database has never been used. | 362 if (status != STATUS_OK) |
| 368 registrations->clear(); | 363 return status; |
| 369 return true; | |
| 370 } | |
| 371 | 364 |
| 372 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); | 365 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
| 373 for (itr->Seek(kRegKeyPrefix); itr->Valid(); itr->Next()) { | 366 for (itr->Seek(kRegKeyPrefix); itr->Valid(); itr->Next()) { |
| 374 if (!itr->status().ok()) { | 367 if (!itr->status().ok()) { |
| 375 HandleError(FROM_HERE, itr->status()); | 368 HandleError(FROM_HERE, itr->status()); |
| 376 registrations->clear(); | 369 registrations->clear(); |
| 377 return false; | 370 return LevelDBStatusToStatus(itr->status()); |
| 378 } | 371 } |
| 379 | 372 |
| 380 if (!RemovePrefix(itr->key().ToString(), kRegKeyPrefix, NULL)) | 373 if (!RemovePrefix(itr->key().ToString(), kRegKeyPrefix, NULL)) |
| 381 break; | 374 break; |
| 382 | 375 |
| 383 RegistrationData registration; | 376 RegistrationData registration; |
| 384 if (!ParseRegistrationData(itr->value().ToString(), ®istration)) { | 377 if (!ParseRegistrationData(itr->value().ToString(), ®istration)) { |
| 385 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 378 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 386 registrations->clear(); | 379 registrations->clear(); |
| 387 return false; | 380 return STATUS_ERROR_CORRUPTED; |
| 388 } | 381 } |
| 389 registrations->push_back(registration); | 382 registrations->push_back(registration); |
| 390 } | 383 } |
| 391 return true; | 384 return STATUS_OK; |
| 392 } | 385 } |
| 393 | 386 |
| 394 bool ServiceWorkerDatabase::ReadRegistration( | 387 bool ServiceWorkerDatabase::ReadRegistration( |
| 395 int64 registration_id, | 388 int64 registration_id, |
| 396 const GURL& origin, | 389 const GURL& origin, |
| 397 RegistrationData* registration, | 390 RegistrationData* registration, |
| 398 std::vector<ResourceRecord>* resources) { | 391 std::vector<ResourceRecord>* resources) { |
| 399 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 392 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 400 DCHECK(registration); | 393 DCHECK(registration); |
| 401 DCHECK(resources); | 394 DCHECK(resources); |
| 402 | 395 |
| 403 if (!LazyOpen(false) || is_disabled_) | 396 Status status = LazyOpen(false); |
| 397 if (IsNewOrNonexistentDatabase(status) || status != STATUS_OK) |
| 404 return false; | 398 return false; |
| 405 | 399 |
| 406 RegistrationData value; | 400 RegistrationData value; |
| 407 if (!ReadRegistrationData(registration_id, origin, &value)) | 401 if (!ReadRegistrationData(registration_id, origin, &value)) |
| 408 return false; | 402 return false; |
| 409 | 403 |
| 410 if (!ReadResourceRecords(value.version_id, resources)) | 404 if (!ReadResourceRecords(value.version_id, resources)) |
| 411 return false; | 405 return false; |
| 412 | 406 |
| 413 *registration = value; | 407 *registration = value; |
| 414 return true; | 408 return true; |
| 415 } | 409 } |
| 416 | 410 |
| 417 bool ServiceWorkerDatabase::WriteRegistration( | 411 bool ServiceWorkerDatabase::WriteRegistration( |
| 418 const RegistrationData& registration, | 412 const RegistrationData& registration, |
| 419 const std::vector<ResourceRecord>& resources) { | 413 const std::vector<ResourceRecord>& resources) { |
| 420 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 414 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 421 if (!LazyOpen(true) || is_disabled_) | 415 if (LazyOpen(true) != STATUS_OK) |
| 422 return false; | 416 return false; |
| 423 | 417 |
| 424 leveldb::WriteBatch batch; | 418 leveldb::WriteBatch batch; |
| 425 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch); | 419 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch); |
| 426 BumpNextVersionIdIfNeeded(registration.version_id, &batch); | 420 BumpNextVersionIdIfNeeded(registration.version_id, &batch); |
| 427 | 421 |
| 428 // TODO(nhiroki): Skip to add the origin into the unique origin list if it | 422 // TODO(nhiroki): Skip to add the origin into the unique origin list if it |
| 429 // has already been added. | 423 // has already been added. |
| 430 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch); | 424 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch); |
| 431 | 425 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 batch.Delete(CreateResourceIdKey( | 461 batch.Delete(CreateResourceIdKey( |
| 468 kUncommittedResIdKeyPrefix, itr->resource_id)); | 462 kUncommittedResIdKeyPrefix, itr->resource_id)); |
| 469 } | 463 } |
| 470 | 464 |
| 471 return WriteBatch(&batch); | 465 return WriteBatch(&batch); |
| 472 } | 466 } |
| 473 | 467 |
| 474 bool ServiceWorkerDatabase::UpdateVersionToActive(int64 registration_id, | 468 bool ServiceWorkerDatabase::UpdateVersionToActive(int64 registration_id, |
| 475 const GURL& origin) { | 469 const GURL& origin) { |
| 476 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 470 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 477 if (!LazyOpen(false) || is_disabled_) | 471 ServiceWorkerDatabase::Status status = LazyOpen(false); |
| 472 if (IsNewOrNonexistentDatabase(status) || status != STATUS_OK) |
| 478 return false; | 473 return false; |
| 479 | 474 |
| 480 RegistrationData registration; | 475 RegistrationData registration; |
| 481 if (!ReadRegistrationData(registration_id, origin, ®istration)) | 476 if (!ReadRegistrationData(registration_id, origin, ®istration)) |
| 482 return false; | 477 return false; |
| 483 | 478 |
| 484 registration.is_active = true; | 479 registration.is_active = true; |
| 485 | 480 |
| 486 leveldb::WriteBatch batch; | 481 leveldb::WriteBatch batch; |
| 487 PutRegistrationDataToBatch(registration, &batch); | 482 PutRegistrationDataToBatch(registration, &batch); |
| 488 return WriteBatch(&batch); | 483 return WriteBatch(&batch); |
| 489 } | 484 } |
| 490 | 485 |
| 491 bool ServiceWorkerDatabase::UpdateLastCheckTime(int64 registration_id, | 486 bool ServiceWorkerDatabase::UpdateLastCheckTime(int64 registration_id, |
| 492 const GURL& origin, | 487 const GURL& origin, |
| 493 const base::Time& time) { | 488 const base::Time& time) { |
| 494 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 489 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 495 if (!LazyOpen(false) || is_disabled_) | 490 ServiceWorkerDatabase::Status status = LazyOpen(false); |
| 491 if (IsNewOrNonexistentDatabase(status) || status != STATUS_OK) |
| 496 return false; | 492 return false; |
| 497 | 493 |
| 498 RegistrationData registration; | 494 RegistrationData registration; |
| 499 if (!ReadRegistrationData(registration_id, origin, ®istration)) | 495 if (!ReadRegistrationData(registration_id, origin, ®istration)) |
| 500 return false; | 496 return false; |
| 501 | 497 |
| 502 registration.last_update_check = time; | 498 registration.last_update_check = time; |
| 503 | 499 |
| 504 leveldb::WriteBatch batch; | 500 leveldb::WriteBatch batch; |
| 505 PutRegistrationDataToBatch(registration, &batch); | 501 PutRegistrationDataToBatch(registration, &batch); |
| 506 return WriteBatch(&batch); | 502 return WriteBatch(&batch); |
| 507 } | 503 } |
| 508 | 504 |
| 509 bool ServiceWorkerDatabase::DeleteRegistration(int64 registration_id, | 505 bool ServiceWorkerDatabase::DeleteRegistration(int64 registration_id, |
| 510 const GURL& origin) { | 506 const GURL& origin) { |
| 511 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 507 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 512 if (!LazyOpen(false) || is_disabled_) | 508 Status status = LazyOpen(false); |
| 509 if (IsNewOrNonexistentDatabase(status)) |
| 510 return STATUS_OK; |
| 511 if (status != STATUS_OK || !origin.is_valid()) |
| 513 return false; | 512 return false; |
| 514 | 513 |
| 515 leveldb::WriteBatch batch; | 514 leveldb::WriteBatch batch; |
| 516 | 515 |
| 517 // Remove |origin| from unique origins if a registration specified by | 516 // Remove |origin| from unique origins if a registration specified by |
| 518 // |registration_id| is the only one for |origin|. | 517 // |registration_id| is the only one for |origin|. |
| 519 // TODO(nhiroki): Check the uniqueness by more efficient way. | 518 // TODO(nhiroki): Check the uniqueness by more efficient way. |
| 520 std::vector<RegistrationData> registrations; | 519 std::vector<RegistrationData> registrations; |
| 521 if (!GetRegistrationsForOrigin(origin, ®istrations)) | 520 if (GetRegistrationsForOrigin(origin, ®istrations) != STATUS_OK) |
| 522 return false; | 521 return false; |
| 523 if (registrations.size() == 1 && | 522 if (registrations.size() == 1 && |
| 524 registrations[0].registration_id == registration_id) { | 523 registrations[0].registration_id == registration_id) { |
| 525 batch.Delete(CreateUniqueOriginKey(origin)); | 524 batch.Delete(CreateUniqueOriginKey(origin)); |
| 526 } | 525 } |
| 527 | 526 |
| 528 // Delete a registration specified by |registration_id|. | 527 // Delete a registration specified by |registration_id|. |
| 529 batch.Delete(CreateRegistrationKey(registration_id, origin)); | 528 batch.Delete(CreateRegistrationKey(registration_id, origin)); |
| 530 | 529 |
| 531 // Delete resource records associated with the registration. | 530 // Delete resource records associated with the registration. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids); | 563 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids); |
| 565 } | 564 } |
| 566 | 565 |
| 567 bool ServiceWorkerDatabase::ClearPurgeableResourceIds( | 566 bool ServiceWorkerDatabase::ClearPurgeableResourceIds( |
| 568 const std::set<int64>& ids) { | 567 const std::set<int64>& ids) { |
| 569 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids); | 568 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids); |
| 570 } | 569 } |
| 571 | 570 |
| 572 bool ServiceWorkerDatabase::DeleteAllDataForOrigin(const GURL& origin) { | 571 bool ServiceWorkerDatabase::DeleteAllDataForOrigin(const GURL& origin) { |
| 573 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 572 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 574 if (!LazyOpen(true) || is_disabled_ || !origin.is_valid()) | 573 Status status = LazyOpen(false); |
| 574 if (IsNewOrNonexistentDatabase(status)) |
| 575 return STATUS_OK; |
| 576 if (status != STATUS_OK || !origin.is_valid()) |
| 575 return false; | 577 return false; |
| 576 | 578 |
| 577 leveldb::WriteBatch batch; | 579 leveldb::WriteBatch batch; |
| 578 | 580 |
| 579 // Delete from the unique origin list. | 581 // Delete from the unique origin list. |
| 580 batch.Delete(CreateUniqueOriginKey(origin)); | 582 batch.Delete(CreateUniqueOriginKey(origin)); |
| 581 | 583 |
| 582 std::vector<RegistrationData> registrations; | 584 std::vector<RegistrationData> registrations; |
| 583 if (!GetRegistrationsForOrigin(origin, ®istrations)) | 585 if (GetRegistrationsForOrigin(origin, ®istrations) != STATUS_OK) |
| 584 return false; | 586 return false; |
| 585 | 587 |
| 586 // Delete registrations and resource records. | 588 // Delete registrations and resource records. |
| 587 for (std::vector<RegistrationData>::const_iterator itr = | 589 for (std::vector<RegistrationData>::const_iterator itr = |
| 588 registrations.begin(); itr != registrations.end(); ++itr) { | 590 registrations.begin(); itr != registrations.end(); ++itr) { |
| 589 batch.Delete(CreateRegistrationKey(itr->registration_id, origin)); | 591 batch.Delete(CreateRegistrationKey(itr->registration_id, origin)); |
| 590 if (!DeleteResourceRecords(itr->version_id, &batch)) | 592 if (!DeleteResourceRecords(itr->version_id, &batch)) |
| 591 return false; | 593 return false; |
| 592 } | 594 } |
| 593 | 595 |
| 594 return WriteBatch(&batch); | 596 return WriteBatch(&batch); |
| 595 } | 597 } |
| 596 | 598 |
| 597 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) { | 599 ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen( |
| 600 bool create_if_missing) { |
| 598 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 601 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 599 if (IsOpen()) | |
| 600 return true; | |
| 601 | 602 |
| 602 // Do not try to open a database if we tried and failed once. | 603 // Do not try to open a database if we tried and failed once. |
| 603 if (is_disabled_) | 604 if (is_disabled_) |
| 604 return false; | 605 return STATUS_ERROR_FAILED; |
| 606 if (IsOpen()) |
| 607 return STATUS_OK; |
| 605 | 608 |
| 606 // When |path_| is empty, open a database in-memory. | 609 // When |path_| is empty, open a database in-memory. |
| 607 bool use_in_memory_db = path_.empty(); | 610 bool use_in_memory_db = path_.empty(); |
| 608 | 611 |
| 609 if (!create_if_needed) { | 612 if (!create_if_missing) { |
| 610 // Avoid opening a database if it does not exist at the |path_|. | 613 // Avoid opening a database if it does not exist at the |path_|. |
| 611 if (use_in_memory_db || | 614 if (use_in_memory_db || |
| 612 !base::PathExists(path_) || | 615 !base::PathExists(path_) || |
| 613 base::IsDirectoryEmpty(path_)) { | 616 base::IsDirectoryEmpty(path_)) { |
| 614 return false; | 617 return STATUS_ERROR_NOT_FOUND; |
| 615 } | 618 } |
| 616 } | 619 } |
| 617 | 620 |
| 618 leveldb::Options options; | 621 leveldb::Options options; |
| 619 options.create_if_missing = create_if_needed; | 622 options.create_if_missing = create_if_missing; |
| 620 if (use_in_memory_db) { | 623 if (use_in_memory_db) { |
| 621 env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); | 624 env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); |
| 622 options.env = env_.get(); | 625 options.env = env_.get(); |
| 623 } | 626 } |
| 624 | 627 |
| 625 leveldb::DB* db = NULL; | 628 leveldb::DB* db = NULL; |
| 626 leveldb::Status status = | 629 leveldb::Status db_status = |
| 627 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); | 630 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); |
| 628 if (!status.ok()) { | 631 if (!db_status.ok()) { |
| 629 DCHECK(!db); | 632 DCHECK(!db); |
| 630 // TODO(nhiroki): Should we retry to open the database? | 633 // TODO(nhiroki): Should we retry to open the database? |
| 631 HandleError(FROM_HERE, status); | 634 HandleError(FROM_HERE, db_status); |
| 632 return false; | 635 return LevelDBStatusToStatus(db_status); |
| 633 } | 636 } |
| 634 db_.reset(db); | 637 db_.reset(db); |
| 635 | 638 |
| 636 int64 db_version; | 639 int64 db_version; |
| 637 if (!ReadDatabaseVersion(&db_version)) | 640 Status status = ReadDatabaseVersion(&db_version); |
| 638 return false; | 641 if (status != STATUS_OK) |
| 642 return status; |
| 643 DCHECK_LE(0, db_version); |
| 639 if (db_version > 0) | 644 if (db_version > 0) |
| 640 is_initialized_ = true; | 645 is_initialized_ = true; |
| 641 return true; | 646 return STATUS_OK; |
| 642 } | 647 } |
| 643 | 648 |
| 644 ServiceWorkerStatusCode ServiceWorkerDatabase::ReadNextAvailableId( | 649 bool ServiceWorkerDatabase::IsNewOrNonexistentDatabase( |
| 650 ServiceWorkerDatabase::Status status) { |
| 651 if (status == STATUS_ERROR_NOT_FOUND) |
| 652 return true; |
| 653 if (status == STATUS_OK && !is_initialized_) |
| 654 return true; |
| 655 return false; |
| 656 } |
| 657 |
| 658 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadNextAvailableId( |
| 645 const char* id_key, | 659 const char* id_key, |
| 646 int64* next_avail_id) { | 660 int64* next_avail_id) { |
| 647 DCHECK(id_key); | 661 DCHECK(id_key); |
| 648 DCHECK(next_avail_id); | 662 DCHECK(next_avail_id); |
| 649 | 663 |
| 650 std::string value; | 664 std::string value; |
| 651 leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value); | 665 leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value); |
| 652 if (status.IsNotFound()) { | 666 if (status.IsNotFound()) { |
| 653 // Nobody has gotten the next resource id for |id_key|. | 667 // Nobody has gotten the next resource id for |id_key|. |
| 654 *next_avail_id = 0; | 668 *next_avail_id = 0; |
| 655 return SERVICE_WORKER_OK; | 669 return STATUS_OK; |
| 656 } | 670 } |
| 657 | 671 |
| 658 if (!status.ok()) { | 672 if (!status.ok()) { |
| 659 HandleError(FROM_HERE, status); | 673 HandleError(FROM_HERE, status); |
| 660 return LevelDBStatusToServiceWorkerStatusCode(status); | 674 return LevelDBStatusToStatus(status); |
| 661 } | 675 } |
| 662 | 676 |
| 663 int64 parsed; | 677 int64 parsed; |
| 664 if (!base::StringToInt64(value, &parsed)) { | 678 if (!base::StringToInt64(value, &parsed)) { |
| 665 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 679 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 666 return SERVICE_WORKER_ERROR_DB_CORRUPTED; | 680 return STATUS_ERROR_CORRUPTED; |
| 667 } | 681 } |
| 668 | 682 |
| 669 *next_avail_id = parsed; | 683 *next_avail_id = parsed; |
| 670 return SERVICE_WORKER_OK; | 684 return STATUS_OK; |
| 671 } | 685 } |
| 672 | 686 |
| 673 bool ServiceWorkerDatabase::ReadRegistrationData( | 687 bool ServiceWorkerDatabase::ReadRegistrationData( |
| 674 int64 registration_id, | 688 int64 registration_id, |
| 675 const GURL& origin, | 689 const GURL& origin, |
| 676 RegistrationData* registration) { | 690 RegistrationData* registration) { |
| 677 DCHECK(registration); | 691 DCHECK(registration); |
| 678 | 692 |
| 679 std::string key = CreateRegistrationKey(registration_id, origin); | 693 std::string key = CreateRegistrationKey(registration_id, origin); |
| 680 | 694 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 // supported, so we can purge this without caring about it. | 769 // supported, so we can purge this without caring about it. |
| 756 PutPurgeableResourceIdToBatch(resource_id, batch); | 770 PutPurgeableResourceIdToBatch(resource_id, batch); |
| 757 } | 771 } |
| 758 return true; | 772 return true; |
| 759 } | 773 } |
| 760 | 774 |
| 761 bool ServiceWorkerDatabase::ReadResourceIds(const char* id_key_prefix, | 775 bool ServiceWorkerDatabase::ReadResourceIds(const char* id_key_prefix, |
| 762 std::set<int64>* ids) { | 776 std::set<int64>* ids) { |
| 763 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 777 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 764 DCHECK(id_key_prefix); | 778 DCHECK(id_key_prefix); |
| 765 DCHECK(ids); | 779 DCHECK(ids->empty()); |
| 766 | 780 |
| 767 if (!LazyOpen(false) || is_disabled_) | 781 Status status = LazyOpen(false); |
| 782 if (IsNewOrNonexistentDatabase(status)) |
| 783 return true; |
| 784 if (status != STATUS_OK) |
| 768 return false; | 785 return false; |
| 769 | 786 |
| 770 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); | 787 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
| 771 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) { | 788 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) { |
| 772 if (!itr->status().ok()) { | 789 if (!itr->status().ok()) { |
| 773 HandleError(FROM_HERE, itr->status()); | 790 HandleError(FROM_HERE, itr->status()); |
| 774 ids->clear(); | 791 ids->clear(); |
| 775 return false; | 792 return false; |
| 776 } | 793 } |
| 777 | 794 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 788 ids->insert(resource_id); | 805 ids->insert(resource_id); |
| 789 } | 806 } |
| 790 return true; | 807 return true; |
| 791 } | 808 } |
| 792 | 809 |
| 793 bool ServiceWorkerDatabase::WriteResourceIds(const char* id_key_prefix, | 810 bool ServiceWorkerDatabase::WriteResourceIds(const char* id_key_prefix, |
| 794 const std::set<int64>& ids) { | 811 const std::set<int64>& ids) { |
| 795 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 812 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 796 DCHECK(id_key_prefix); | 813 DCHECK(id_key_prefix); |
| 797 | 814 |
| 798 if (!LazyOpen(true) || is_disabled_) | 815 if (LazyOpen(true) != STATUS_OK) |
| 799 return false; | 816 return false; |
| 800 if (ids.empty()) | 817 if (ids.empty()) |
| 801 return true; | 818 return true; |
| 802 | 819 |
| 803 leveldb::WriteBatch batch; | 820 leveldb::WriteBatch batch; |
| 804 for (std::set<int64>::const_iterator itr = ids.begin(); | 821 for (std::set<int64>::const_iterator itr = ids.begin(); |
| 805 itr != ids.end(); ++itr) { | 822 itr != ids.end(); ++itr) { |
| 806 // Value should be empty. | 823 // Value should be empty. |
| 807 batch.Put(CreateResourceIdKey(id_key_prefix, *itr), ""); | 824 batch.Put(CreateResourceIdKey(id_key_prefix, *itr), ""); |
| 808 } | 825 } |
| 809 return WriteBatch(&batch); | 826 return WriteBatch(&batch); |
| 810 } | 827 } |
| 811 | 828 |
| 812 bool ServiceWorkerDatabase::DeleteResourceIds(const char* id_key_prefix, | 829 bool ServiceWorkerDatabase::DeleteResourceIds(const char* id_key_prefix, |
| 813 const std::set<int64>& ids) { | 830 const std::set<int64>& ids) { |
| 814 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 831 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 815 DCHECK(id_key_prefix); | 832 DCHECK(id_key_prefix); |
| 816 | 833 |
| 817 if (!LazyOpen(true) || is_disabled_) | 834 Status status = LazyOpen(false); |
| 835 if (IsNewOrNonexistentDatabase(status)) |
| 836 return true; |
| 837 if (status != STATUS_OK) |
| 818 return false; | 838 return false; |
| 839 |
| 819 if (ids.empty()) | 840 if (ids.empty()) |
| 820 return true; | 841 return true; |
| 821 | 842 |
| 822 leveldb::WriteBatch batch; | 843 leveldb::WriteBatch batch; |
| 823 for (std::set<int64>::const_iterator itr = ids.begin(); | 844 for (std::set<int64>::const_iterator itr = ids.begin(); |
| 824 itr != ids.end(); ++itr) { | 845 itr != ids.end(); ++itr) { |
| 825 batch.Delete(CreateResourceIdKey(id_key_prefix, *itr)); | 846 batch.Delete(CreateResourceIdKey(id_key_prefix, *itr)); |
| 826 } | 847 } |
| 827 return WriteBatch(&batch); | 848 return WriteBatch(&batch); |
| 828 } | 849 } |
| 829 | 850 |
| 830 bool ServiceWorkerDatabase::ReadDatabaseVersion(int64* db_version) { | 851 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadDatabaseVersion( |
| 852 int64* db_version) { |
| 831 std::string value; | 853 std::string value; |
| 832 leveldb::Status status = | 854 leveldb::Status status = |
| 833 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value); | 855 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value); |
| 834 if (status.IsNotFound()) { | 856 if (status.IsNotFound()) { |
| 835 // The database hasn't been initialized yet. | 857 // The database hasn't been initialized yet. |
| 836 *db_version = 0; | 858 *db_version = 0; |
| 837 return true; | 859 return STATUS_OK; |
| 838 } | 860 } |
| 839 if (!status.ok()) { | 861 if (!status.ok()) { |
| 840 HandleError(FROM_HERE, status); | 862 HandleError(FROM_HERE, status); |
| 841 return false; | 863 return LevelDBStatusToStatus(status); |
| 842 } | 864 } |
| 843 | 865 |
| 844 int64 parsed; | 866 int64 parsed; |
| 845 if (!base::StringToInt64(value, &parsed)) { | 867 if (!base::StringToInt64(value, &parsed)) { |
| 846 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 868 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 847 return false; | 869 return STATUS_ERROR_CORRUPTED; |
| 848 } | 870 } |
| 849 | 871 |
| 850 const int kFirstValidVersion = 1; | 872 const int kFirstValidVersion = 1; |
| 851 if (parsed < kFirstValidVersion || kCurrentSchemaVersion < parsed) { | 873 if (parsed < kFirstValidVersion || kCurrentSchemaVersion < parsed) { |
| 852 HandleError(FROM_HERE, leveldb::Status::Corruption("invalid DB version")); | 874 HandleError(FROM_HERE, leveldb::Status::Corruption("invalid DB version")); |
| 853 return false; | 875 return STATUS_ERROR_CORRUPTED; |
| 854 } | 876 } |
| 855 | 877 |
| 856 *db_version = parsed; | 878 *db_version = parsed; |
| 857 return true; | 879 return STATUS_OK; |
| 858 } | 880 } |
| 859 | 881 |
| 860 bool ServiceWorkerDatabase::WriteBatch(leveldb::WriteBatch* batch) { | 882 bool ServiceWorkerDatabase::WriteBatch(leveldb::WriteBatch* batch) { |
| 861 DCHECK(batch); | 883 DCHECK(batch); |
| 862 DCHECK(!is_disabled_); | 884 DCHECK(!is_disabled_); |
| 863 | 885 |
| 864 if (!is_initialized_) { | 886 if (!is_initialized_) { |
| 865 // Write the database schema version. | 887 // Write the database schema version. |
| 866 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion)); | 888 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion)); |
| 867 is_initialized_ = true; | 889 is_initialized_ = true; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 // TODO(nhiroki): Add an UMA histogram. | 925 // TODO(nhiroki): Add an UMA histogram. |
| 904 DLOG(ERROR) << "Failed at: " << from_here.ToString() | 926 DLOG(ERROR) << "Failed at: " << from_here.ToString() |
| 905 << " with error: " << status.ToString(); | 927 << " with error: " << status.ToString(); |
| 906 is_disabled_ = true; | 928 is_disabled_ = true; |
| 907 if (status.IsCorruption()) | 929 if (status.IsCorruption()) |
| 908 was_corruption_detected_ = true; | 930 was_corruption_detected_ = true; |
| 909 db_.reset(); | 931 db_.reset(); |
| 910 } | 932 } |
| 911 | 933 |
| 912 } // namespace content | 934 } // namespace content |
| OLD | NEW |