Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1271)

Side by Side Diff: webkit/browser/appcache/appcache_storage_impl.cc

Issue 137493003: Appcache::OnCorruptionDetected handling (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "webkit/browser/appcache/appcache_storage_impl.h" 5 #include "webkit/browser/appcache/appcache_storage_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 #include <set> 9 #include <set>
10 #include <vector> 10 #include <vector>
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 friend class base::RefCountedThreadSafe<DatabaseTask>; 166 friend class base::RefCountedThreadSafe<DatabaseTask>;
167 virtual ~DatabaseTask() {} 167 virtual ~DatabaseTask() {}
168 168
169 AppCacheStorageImpl* storage_; 169 AppCacheStorageImpl* storage_;
170 AppCacheDatabase* database_; 170 AppCacheDatabase* database_;
171 DelegateReferenceVector delegates_; 171 DelegateReferenceVector delegates_;
172 172
173 private: 173 private:
174 void CallRun(base::TimeTicks schedule_time); 174 void CallRun(base::TimeTicks schedule_time);
175 void CallRunCompleted(base::TimeTicks schedule_time); 175 void CallRunCompleted(base::TimeTicks schedule_time);
176 void CallDisableStorage(); 176 void OnDisableStorage();
177 void OnCorruptionDetected();
177 178
178 scoped_refptr<base::MessageLoopProxy> io_thread_; 179 scoped_refptr<base::MessageLoopProxy> io_thread_;
179 }; 180 };
180 181
181 void AppCacheStorageImpl::DatabaseTask::Schedule() { 182 void AppCacheStorageImpl::DatabaseTask::Schedule() {
182 DCHECK(storage_); 183 DCHECK(storage_);
183 DCHECK(io_thread_->BelongsToCurrentThread()); 184 DCHECK(io_thread_->BelongsToCurrentThread());
184 if (!storage_->database_) 185 if (!storage_->database_)
185 return; 186 return;
186 187
(...skipping 17 matching lines...) Expand all
204 AppCacheHistograms::AddTaskQueueTimeSample( 205 AppCacheHistograms::AddTaskQueueTimeSample(
205 base::TimeTicks::Now() - schedule_time); 206 base::TimeTicks::Now() - schedule_time);
206 if (!database_->is_disabled()) { 207 if (!database_->is_disabled()) {
207 base::TimeTicks run_time = base::TimeTicks::Now(); 208 base::TimeTicks run_time = base::TimeTicks::Now();
208 Run(); 209 Run();
209 AppCacheHistograms::AddTaskRunTimeSample( 210 AppCacheHistograms::AddTaskRunTimeSample(
210 base::TimeTicks::Now() - run_time); 211 base::TimeTicks::Now() - run_time);
211 if (database_->is_disabled()) { 212 if (database_->is_disabled()) {
212 io_thread_->PostTask( 213 io_thread_->PostTask(
213 FROM_HERE, 214 FROM_HERE,
214 base::Bind(&DatabaseTask::CallDisableStorage, this)); 215 base::Bind(&DatabaseTask::OnDisableStorage, this));
216 } else if (database_->was_corruption_dectected()) {
217 database_->Disable();
218 io_thread_->PostTask(
219 FROM_HERE,
220 base::Bind(&DatabaseTask::OnCorruptionDetected, this));
215 } 221 }
216 } 222 }
217 io_thread_->PostTask( 223 io_thread_->PostTask(
218 FROM_HERE, 224 FROM_HERE,
219 base::Bind(&DatabaseTask::CallRunCompleted, this, 225 base::Bind(&DatabaseTask::CallRunCompleted, this,
220 base::TimeTicks::Now())); 226 base::TimeTicks::Now()));
221 } 227 }
222 228
223 void AppCacheStorageImpl::DatabaseTask::CallRunCompleted( 229 void AppCacheStorageImpl::DatabaseTask::CallRunCompleted(
224 base::TimeTicks schedule_time) { 230 base::TimeTicks schedule_time) {
225 AppCacheHistograms::AddCompletionQueueTimeSample( 231 AppCacheHistograms::AddCompletionQueueTimeSample(
226 base::TimeTicks::Now() - schedule_time); 232 base::TimeTicks::Now() - schedule_time);
227 if (storage_) { 233 if (storage_) {
228 DCHECK(io_thread_->BelongsToCurrentThread()); 234 DCHECK(io_thread_->BelongsToCurrentThread());
229 DCHECK(storage_->scheduled_database_tasks_.front() == this); 235 DCHECK(storage_->scheduled_database_tasks_.front() == this);
230 storage_->scheduled_database_tasks_.pop_front(); 236 storage_->scheduled_database_tasks_.pop_front();
231 base::TimeTicks run_time = base::TimeTicks::Now(); 237 base::TimeTicks run_time = base::TimeTicks::Now();
232 RunCompleted(); 238 RunCompleted();
233 AppCacheHistograms::AddCompletionRunTimeSample( 239 AppCacheHistograms::AddCompletionRunTimeSample(
234 base::TimeTicks::Now() - run_time); 240 base::TimeTicks::Now() - run_time);
235 delegates_.clear(); 241 delegates_.clear();
236 } 242 }
237 } 243 }
238 244
239 void AppCacheStorageImpl::DatabaseTask::CallDisableStorage() { 245 void AppCacheStorageImpl::DatabaseTask::OnDisableStorage() {
240 if (storage_) { 246 if (storage_) {
241 DCHECK(io_thread_->BelongsToCurrentThread()); 247 DCHECK(io_thread_->BelongsToCurrentThread());
242 storage_->Disable(); 248 storage_->Disable();
243 } 249 }
244 } 250 }
245 251
252 void AppCacheStorageImpl::DatabaseTask::OnCorruptionDetected() {
253 if (storage_) {
254 DCHECK(io_thread_->BelongsToCurrentThread());
255 AppCacheHistograms::CountCorruptionDetected();
256 storage_->Disable();
257 storage_->DeleteAndStartOver();
258 }
259 }
260
246 // InitTask ------- 261 // InitTask -------
247 262
248 class AppCacheStorageImpl::InitTask : public DatabaseTask { 263 class AppCacheStorageImpl::InitTask : public DatabaseTask {
249 public: 264 public:
250 explicit InitTask(AppCacheStorageImpl* storage) 265 explicit InitTask(AppCacheStorageImpl* storage)
251 : DatabaseTask(storage), last_group_id_(0), 266 : DatabaseTask(storage), last_group_id_(0),
252 last_cache_id_(0), last_response_id_(0), 267 last_cache_id_(0), last_response_id_(0),
253 last_deletable_response_rowid_(0) {} 268 last_deletable_response_rowid_(0) {
269 if (!storage->is_incognito_) {
270 db_file_path_ =
271 storage->cache_directory_.Append(kAppCacheDatabaseName);
272 disk_cache_directory_ =
273 storage->cache_directory_.Append(kDiskCacheDirectoryName);
274 }
275 }
254 276
255 // DatabaseTask: 277 // DatabaseTask:
256 virtual void Run() OVERRIDE; 278 virtual void Run() OVERRIDE;
257 virtual void RunCompleted() OVERRIDE; 279 virtual void RunCompleted() OVERRIDE;
258 280
259 protected: 281 protected:
260 virtual ~InitTask() {} 282 virtual ~InitTask() {}
261 283
262 private: 284 private:
285 base::FilePath db_file_path_;
286 base::FilePath disk_cache_directory_;
263 int64 last_group_id_; 287 int64 last_group_id_;
264 int64 last_cache_id_; 288 int64 last_cache_id_;
265 int64 last_response_id_; 289 int64 last_response_id_;
266 int64 last_deletable_response_rowid_; 290 int64 last_deletable_response_rowid_;
267 std::map<GURL, int64> usage_map_; 291 std::map<GURL, int64> usage_map_;
268 }; 292 };
269 293
270 void AppCacheStorageImpl::InitTask::Run() { 294 void AppCacheStorageImpl::InitTask::Run() {
295 if (!db_file_path_.empty()) {
296 // If there is no sql database, ensure there is no disk cache either.
297 if (!base::PathExists(db_file_path_)) {
298 if (base::DirectoryExists(disk_cache_directory_)) {
299 base::DeleteFile(disk_cache_directory_, true);
300 DCHECK(!base::DirectoryExists(disk_cache_directory_));
301 }
302 }
303 }
304
271 database_->FindLastStorageIds( 305 database_->FindLastStorageIds(
272 &last_group_id_, &last_cache_id_, &last_response_id_, 306 &last_group_id_, &last_cache_id_, &last_response_id_,
273 &last_deletable_response_rowid_); 307 &last_deletable_response_rowid_);
274 database_->GetAllOriginUsage(&usage_map_); 308 database_->GetAllOriginUsage(&usage_map_);
275 } 309 }
276 310
277 void AppCacheStorageImpl::InitTask::RunCompleted() { 311 void AppCacheStorageImpl::InitTask::RunCompleted() {
278 storage_->last_group_id_ = last_group_id_; 312 storage_->last_group_id_ = last_group_id_;
279 storage_->last_cache_id_ = last_cache_id_; 313 storage_->last_cache_id_ = last_cache_id_;
280 storage_->last_response_id_ = last_response_id_; 314 storage_->last_response_id_ = last_response_id_;
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 GURL preferred_manifest_url_; 939 GURL preferred_manifest_url_;
906 std::set<int64> cache_ids_in_use_; 940 std::set<int64> cache_ids_in_use_;
907 AppCacheEntry entry_; 941 AppCacheEntry entry_;
908 AppCacheEntry fallback_entry_; 942 AppCacheEntry fallback_entry_;
909 GURL namespace_entry_url_; 943 GURL namespace_entry_url_;
910 int64 cache_id_; 944 int64 cache_id_;
911 int64 group_id_; 945 int64 group_id_;
912 GURL manifest_url_; 946 GURL manifest_url_;
913 }; 947 };
914 948
915
916
917 void AppCacheStorageImpl::FindMainResponseTask::Run() { 949 void AppCacheStorageImpl::FindMainResponseTask::Run() {
918 // NOTE: The heuristics around choosing amoungst multiple candidates 950 // NOTE: The heuristics around choosing amoungst multiple candidates
919 // is underspecified, and just plain not fully understood. This needs 951 // is underspecified, and just plain not fully understood. This needs
920 // to be refined. 952 // to be refined.
921 953
922 // The 'preferred_manifest_url' is the url of the manifest associated 954 // The 'preferred_manifest_url' is the url of the manifest associated
923 // with the page that opened or embedded the page being loaded now. 955 // with the page that opened or embedded the page being loaded now.
924 // We have a strong preference to use resources from that cache. 956 // We have a strong preference to use resources from that cache.
925 // We also have a lesser bias to use resources from caches that are currently 957 // We also have a lesser bias to use resources from caches that are currently
926 // being used by other unrelated pages. 958 // being used by other unrelated pages.
(...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after
1785 } else { 1817 } else {
1786 rv = disk_cache_->InitWithDiskBackend( 1818 rv = disk_cache_->InitWithDiskBackend(
1787 cache_directory_.Append(kDiskCacheDirectoryName), 1819 cache_directory_.Append(kDiskCacheDirectoryName),
1788 kMaxDiskCacheSize, 1820 kMaxDiskCacheSize,
1789 false, 1821 false,
1790 cache_thread_.get(), 1822 cache_thread_.get(),
1791 base::Bind(&AppCacheStorageImpl::OnDiskCacheInitialized, 1823 base::Bind(&AppCacheStorageImpl::OnDiskCacheInitialized,
1792 base::Unretained(this))); 1824 base::Unretained(this)));
1793 } 1825 }
1794 1826
1795 // We should not keep this reference around.
1796 cache_thread_ = NULL;
1797
1798 if (rv != net::ERR_IO_PENDING) 1827 if (rv != net::ERR_IO_PENDING)
1799 OnDiskCacheInitialized(rv); 1828 OnDiskCacheInitialized(rv);
1800 } 1829 }
1801 return disk_cache_.get(); 1830 return disk_cache_.get();
1802 } 1831 }
1803 1832
1804 void AppCacheStorageImpl::OnDiskCacheInitialized(int rv) { 1833 void AppCacheStorageImpl::OnDiskCacheInitialized(int rv) {
1805 if (rv != net::OK) { 1834 if (rv != net::OK) {
1806 LOG(ERROR) << "Failed to open the appcache diskcache."; 1835 LOG(ERROR) << "Failed to open the appcache diskcache.";
1807 AppCacheHistograms::CountInitResult(AppCacheHistograms::DISK_CACHE_ERROR); 1836 AppCacheHistograms::CountInitResult(AppCacheHistograms::DISK_CACHE_ERROR);
1808 1837
1809 // We're unable to open the disk cache, this is a fatal error that we can't 1838 // We're unable to open the disk cache, this is a fatal error that we can't
1810 // really recover from. We handle it by temporarily disabling the appcache 1839 // really recover from. We handle it by temporarily disabling the appcache
1811 // deleting the directory on disk and reinitializing the appcache system. 1840 // deleting the directory on disk and reinitializing the appcache system.
1812 Disable(); 1841 Disable();
1813 if (!is_incognito_ && rv != net::ERR_ABORTED) { 1842 if (rv != net::ERR_ABORTED)
1814 VLOG(1) << "Deleting existing appcache data and starting over."; 1843 DeleteAndStartOver();
1815 db_thread_->PostTaskAndReply(
1816 FROM_HERE,
1817 base::Bind(base::IgnoreResult(&base::DeleteFile),
1818 cache_directory_, true),
1819 base::Bind(&AppCacheStorageImpl::CallReinitialize,
1820 weak_factory_.GetWeakPtr()));
1821 }
1822 } 1844 }
1823 } 1845 }
1824 1846
1825 void AppCacheStorageImpl::CallReinitialize() { 1847 namespace {
1826 service_->Reinitialize(); 1848
1827 // note: 'this' may be deleted during reinit. 1849 void HopThruCacheThread() {
1850 // Function body is intentionally empty,
1851 // all diskcache file handles should be closed by the
1852 // time this function runs.
1853 }
1854
1855 void DeleteDirectoryHelper(const base::FilePath& dir) {
1856 base::DeleteFile(dir, true);
1857 DCHECK(!base::DirectoryExists(dir));
1858 }
1859
1860 }
1861
1862 void AppCacheStorageImpl::DeleteAndStartOver() {
1863 DCHECK(is_disabled_);
1864 if (!is_incognito_) {
1865 VLOG(1) << "Deleting existing appcache data and starting over.";
1866 // We can have tasks in flight to close file handles on both the db
1867 // and cache threads, we need to allow those tasks to cycle thru
1868 // prior to deleting the files and calling reinit.
1869 cache_thread_->PostTaskAndReply(
1870 FROM_HERE,
1871 base::Bind(&HopThruCacheThread),
1872 base::Bind(&AppCacheStorageImpl::DeleteAndStartOverPart2,
1873 weak_factory_.GetWeakPtr()));
1874 }
1875 }
1876
1877 void AppCacheStorageImpl::DeleteAndStartOverPart2() {
1878 db_thread_->PostTaskAndReply(
1879 FROM_HERE,
1880 base::Bind(&DeleteDirectoryHelper, cache_directory_),
1881 base::Bind(&AppCacheStorageImpl::CallScheduleReinitialize,
1882 weak_factory_.GetWeakPtr()));
1883 }
1884
1885 void AppCacheStorageImpl::CallScheduleReinitialize() {
1886 service_->ScheduleReinitialize();
1887 // note: 'this' may be deleted at this point.
1828 } 1888 }
1829 1889
1830 } // namespace appcache 1890 } // namespace appcache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698