summaryrefslogtreecommitdiffstats
path: root/webkit/appcache/appcache_update_job.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/appcache/appcache_update_job.cc')
-rw-r--r--webkit/appcache/appcache_update_job.cc112
1 files changed, 66 insertions, 46 deletions
diff --git a/webkit/appcache/appcache_update_job.cc b/webkit/appcache/appcache_update_job.cc
index d9cf729..46048b5 100644
--- a/webkit/appcache/appcache_update_job.cc
+++ b/webkit/appcache/appcache_update_job.cc
@@ -88,12 +88,15 @@ AppCacheUpdateJob::AppCacheUpdateJob(AppCacheService* service,
}
AppCacheUpdateJob::~AppCacheUpdateJob() {
- Cancel();
+ if (internal_state_ != COMPLETED)
+ Cancel();
DCHECK(!manifest_url_request_);
DCHECK(pending_url_fetches_.empty());
+ DCHECK(!inprogress_cache_);
- group_->SetUpdateStatus(AppCacheGroup::IDLE);
+ if (group_)
+ group_->SetUpdateStatus(AppCacheGroup::IDLE);
}
void AppCacheUpdateJob::StartUpdate(AppCacheHost* host,
@@ -156,7 +159,7 @@ void AppCacheUpdateJob::OnResponseStarted(URLRequest *request) {
}
void AppCacheUpdateJob::ReadResponseData(URLRequest* request) {
- if (internal_state_ == CACHE_FAILURE)
+ if (internal_state_ == CACHE_FAILURE || internal_state_ == CANCELLED)
return;
int bytes_read = 0;
@@ -311,14 +314,16 @@ void AppCacheUpdateJob::HandleManifestFetchCompleted(URLRequest* request) {
ContinueHandleManifestFetchCompleted(true);
} else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) {
ContinueHandleManifestFetchCompleted(false);
- } else if (response_code == 404 || response_code == 410) {
- group_->set_obsolete(true);
- NotifyAllAssociatedHosts(OBSOLETE_EVENT);
- NotifyAllPendingMasterHosts(ERROR_EVENT);
- DeleteSoon();
} else {
- LOG(INFO) << "Cache failure, response code: " << response_code;
- internal_state_ = CACHE_FAILURE;
+ if (response_code == 404 || response_code == 410) {
+ group_->set_obsolete(true);
+ NotifyAllAssociatedHosts(OBSOLETE_EVENT);
+ NotifyAllPendingMasterHosts(ERROR_EVENT);
+ internal_state_ = COMPLETED;
+ } else {
+ LOG(INFO) << "Cache failure, response code: " << response_code;
+ internal_state_ = CACHE_FAILURE;
+ }
MaybeCompleteUpdate(); // if not done, run async cache failure steps
}
}
@@ -346,7 +351,6 @@ void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) {
internal_state_ = DOWNLOADING;
inprogress_cache_ = new AppCache(service_,
service_->storage()->NewCacheId());
- inprogress_cache_->set_owning_group(group_);
BuildUrlFileList(manifest);
inprogress_cache_->InitializeWithManifest(&manifest);
@@ -398,7 +402,6 @@ void AppCacheUpdateJob::HandleUrlFetchCompleted(URLRequest* request) {
// Cancel any pending URL requests.
for (PendingUrlFetches::iterator it = pending_url_fetches_.begin();
it != pending_url_fetches_.end(); ++it) {
- it->second->Cancel();
delete it->second;
}
@@ -436,21 +439,19 @@ void AppCacheUpdateJob::HandleManifestRefetchCompleted(URLRequest* request) {
inprogress_cache_->AddOrModifyEntry(manifest_url_, entry);
inprogress_cache_->set_update_time(base::TimeTicks::Now());
- // TODO(jennb): start of part to make async (cache storage may fail;
- // group storage may fail)
+ // TODO(jennb): start of part to make async (cache/group storage may fail)
inprogress_cache_->set_complete(true);
-
- // TODO(jennb): write new cache to storage here
group_->AddCache(inprogress_cache_);
- // TODO(jennb): write new group to storage here
- inprogress_cache_ = NULL;
+ protect_new_cache_.swap(inprogress_cache_);
+
+ // TODO(jennb): write new group and cache to storage here
if (update_type_ == CACHE_ATTEMPT) {
NotifyAllAssociatedHosts(CACHED_EVENT);
} else {
NotifyAllAssociatedHosts(UPDATE_READY_EVENT);
}
- DeleteSoon();
+ internal_state_ = COMPLETED;
// TODO(jennb): end of part that needs to be made async.
} else {
LOG(INFO) << "Request status: " << request->status().status()
@@ -458,8 +459,9 @@ void AppCacheUpdateJob::HandleManifestRefetchCompleted(URLRequest* request) {
<< " response code: " << response_code;
ScheduleUpdateRetry(kRerunDelayMs);
internal_state_ = CACHE_FAILURE;
- HandleCacheFailure();
}
+
+ MaybeCompleteUpdate(); // will definitely complete
}
void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host,
@@ -655,10 +657,12 @@ void AppCacheUpdateJob::CopyEntryToCache(const GURL& url,
inprogress_cache_->AddEntry(url, *dest);
}
-bool AppCacheUpdateJob::MaybeCompleteUpdate() {
+void AppCacheUpdateJob::MaybeCompleteUpdate() {
+ // Must wait for any pending master entries or url fetches to complete.
if (master_entries_completed_ != pending_master_entries_.size() ||
url_fetches_completed_ != url_file_list_.size() ) {
- return false;
+ DCHECK(internal_state_ != COMPLETED);
+ return;
}
switch (internal_state_) {
@@ -666,37 +670,30 @@ bool AppCacheUpdateJob::MaybeCompleteUpdate() {
// 6.9.4 steps 7.3-7.7.
NotifyAllAssociatedHosts(NO_UPDATE_EVENT);
pending_master_entries_.clear();
- DeleteSoon();
+ internal_state_ = COMPLETED;
break;
case DOWNLOADING:
internal_state_ = REFETCH_MANIFEST;
FetchManifest(false);
- return false;
+ break;
case CACHE_FAILURE:
- HandleCacheFailure();
+ // 6.9.4 cache failure steps 2-8.
+ NotifyAllAssociatedHosts(ERROR_EVENT);
+ pending_master_entries_.clear();
+ DiscardInprogressCache();
+ // For a CACHE_ATTEMPT, group will be discarded when the host(s) that
+ // started this update removes its reference to the group. Nothing more
+ // to do here.
+ internal_state_ = COMPLETED;
break;
default:
- NOTREACHED();
- }
- return true;
-}
-
-void AppCacheUpdateJob::HandleCacheFailure() {
- // 6.9.4 cache failure steps 2-8.
- NotifyAllAssociatedHosts(ERROR_EVENT);
- pending_master_entries_.clear();
-
- // Discard the inprogress cache.
- // TODO(jennb): cleanup possible storage for entries in the cache
- if (inprogress_cache_) {
- inprogress_cache_->set_owning_group(NULL);
- inprogress_cache_ = NULL;
+ break;
}
- // For a CACHE_ATTEMPT, group will be discarded when this update
- // job removes its reference to the group. Nothing more to do here.
-
- DeleteSoon();
+ // Let the stack unwind before deletion to make it less risky as this
+ // method is called from multiple places in this file.
+ if (internal_state_ == COMPLETED)
+ DeleteSoon();
}
void AppCacheUpdateJob::ScheduleUpdateRetry(int delay_ms) {
@@ -706,16 +703,39 @@ void AppCacheUpdateJob::ScheduleUpdateRetry(int delay_ms) {
}
void AppCacheUpdateJob::Cancel() {
+ internal_state_ = CANCELLED;
+
if (manifest_url_request_) {
delete manifest_url_request_;
manifest_url_request_ = NULL;
}
- // TODO(jennb): code other cancel cleanup (pending url requests, storage)
+ for (PendingUrlFetches::iterator it = pending_url_fetches_.begin();
+ it != pending_url_fetches_.end(); ++it) {
+ delete it->second;
+ }
+
+ pending_master_entries_.clear();
+ DiscardInprogressCache();
+ // TODO(jennb): cancel any storage callbacks
+}
+
+void AppCacheUpdateJob::DiscardInprogressCache() {
+ if (!inprogress_cache_)
+ return;
+
+ // TODO(jennb): cleanup stored responses for entries in the cache
+ inprogress_cache_ = NULL;
}
void AppCacheUpdateJob::DeleteSoon() {
- // TODO(jennb): revisit if update should be deleting itself
+ // Break the connection with the group so the group cannot call delete
+ // on this object after we've posted a task to delete ourselves.
+ group_->SetUpdateStatus(AppCacheGroup::IDLE);
+ protect_new_cache_ = NULL;
+ group_ = NULL;
+
MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
+
} // namespace appcache