| 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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |