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

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

Powered by Google App Engine
This is Rietveld 408576698