 Chromium Code Reviews
 Chromium Code Reviews Issue 137493003:
  Appcache::OnCorruptionDetected handling  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 137493003:
  Appcache::OnCorruptionDetected handling  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| OLD | NEW | 
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 | 
| OLD | NEW |