| 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 there is no sql database, ensure there is no disk cache either. | 
 |   288   if (!db_file_path_.empty() && | 
 |   289       !base::PathExists(db_file_path_) && | 
 |   290       base::DirectoryExists(disk_cache_directory_)) { | 
 |   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  | 
|   272   database_->FindLastStorageIds( |   298   database_->FindLastStorageIds( | 
|   273       &last_group_id_, &last_cache_id_, &last_response_id_, |   299       &last_group_id_, &last_cache_id_, &last_response_id_, | 
|   274       &last_deletable_response_rowid_); |   300       &last_deletable_response_rowid_); | 
|   275   database_->GetAllOriginUsage(&usage_map_); |   301   database_->GetAllOriginUsage(&usage_map_); | 
|   276 } |   302 } | 
|   277  |   303  | 
|   278 void AppCacheStorageImpl::InitTask::RunCompleted() { |   304 void AppCacheStorageImpl::InitTask::RunCompleted() { | 
|   279   storage_->last_group_id_ = last_group_id_; |   305   storage_->last_group_id_ = last_group_id_; | 
|   280   storage_->last_cache_id_ = last_cache_id_; |   306   storage_->last_cache_id_ = last_cache_id_; | 
|   281   storage_->last_response_id_ = last_response_id_; |   307   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_; |   932   GURL preferred_manifest_url_; | 
|   907   std::set<int64> cache_ids_in_use_; |   933   std::set<int64> cache_ids_in_use_; | 
|   908   AppCacheEntry entry_; |   934   AppCacheEntry entry_; | 
|   909   AppCacheEntry fallback_entry_; |   935   AppCacheEntry fallback_entry_; | 
|   910   GURL namespace_entry_url_; |   936   GURL namespace_entry_url_; | 
|   911   int64 cache_id_; |   937   int64 cache_id_; | 
|   912   int64 group_id_; |   938   int64 group_id_; | 
|   913   GURL manifest_url_; |   939   GURL manifest_url_; | 
|   914 }; |   940 }; | 
|   915  |   941  | 
|   916  |  | 
|   917  |  | 
|   918 void AppCacheStorageImpl::FindMainResponseTask::Run() { |   942 void AppCacheStorageImpl::FindMainResponseTask::Run() { | 
|   919   // NOTE: The heuristics around choosing amoungst multiple candidates |   943   // NOTE: The heuristics around choosing amoungst multiple candidates | 
|   920   // is underspecified, and just plain not fully understood. This needs |   944   // is underspecified, and just plain not fully understood. This needs | 
|   921   // to be refined. |   945   // to be refined. | 
|   922  |   946  | 
|   923   // The 'preferred_manifest_url' is the url of the manifest associated |   947   // The 'preferred_manifest_url' is the url of the manifest associated | 
|   924   // with the page that opened or embedded the page being loaded now. |   948   // with the page that opened or embedded the page being loaded now. | 
|   925   // We have a strong preference to use resources from that cache. |   949   // 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 |   950   // We also have a lesser bias to use resources from caches that are currently | 
|   927   // being used by other unrelated pages. |   951   // being used by other unrelated pages. | 
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1786     } else { |  1810     } else { | 
|  1787       rv = disk_cache_->InitWithDiskBackend( |  1811       rv = disk_cache_->InitWithDiskBackend( | 
|  1788           cache_directory_.Append(kDiskCacheDirectoryName), |  1812           cache_directory_.Append(kDiskCacheDirectoryName), | 
|  1789           kMaxDiskCacheSize, |  1813           kMaxDiskCacheSize, | 
|  1790           false, |  1814           false, | 
|  1791           cache_thread_.get(), |  1815           cache_thread_.get(), | 
|  1792           base::Bind(&AppCacheStorageImpl::OnDiskCacheInitialized, |  1816           base::Bind(&AppCacheStorageImpl::OnDiskCacheInitialized, | 
|  1793                      base::Unretained(this))); |  1817                      base::Unretained(this))); | 
|  1794     } |  1818     } | 
|  1795  |  1819  | 
|  1796     // We should not keep this reference around. |  | 
|  1797     cache_thread_ = NULL; |  | 
|  1798  |  | 
|  1799     if (rv != net::ERR_IO_PENDING) |  1820     if (rv != net::ERR_IO_PENDING) | 
|  1800       OnDiskCacheInitialized(rv); |  1821       OnDiskCacheInitialized(rv); | 
|  1801   } |  1822   } | 
|  1802   return disk_cache_.get(); |  1823   return disk_cache_.get(); | 
|  1803 } |  1824 } | 
|  1804  |  1825  | 
|  1805 void AppCacheStorageImpl::OnDiskCacheInitialized(int rv) { |  1826 void AppCacheStorageImpl::OnDiskCacheInitialized(int rv) { | 
|  1806   if (rv != net::OK) { |  1827   if (rv != net::OK) { | 
|  1807     LOG(ERROR) << "Failed to open the appcache diskcache."; |  1828     LOG(ERROR) << "Failed to open the appcache diskcache."; | 
|  1808     AppCacheHistograms::CountInitResult(AppCacheHistograms::DISK_CACHE_ERROR); |  1829     AppCacheHistograms::CountInitResult(AppCacheHistograms::DISK_CACHE_ERROR); | 
|  1809  |  1830  | 
|  1810     // We're unable to open the disk cache, this is a fatal error that we can't |  1831     // 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 |  1832     // really recover from. We handle it by temporarily disabling the appcache | 
|  1812     // deleting the directory on disk and reinitializing the appcache system. |  1833     // deleting the directory on disk and reinitializing the appcache system. | 
|  1813     Disable(); |  1834     Disable(); | 
|  1814     if (!is_incognito_ && rv != net::ERR_ABORTED) { |  1835     if (rv != net::ERR_ABORTED) | 
|  1815       VLOG(1) << "Deleting existing appcache data and starting over."; |  1836       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   } |  1837   } | 
|  1824 } |  1838 } | 
|  1825  |  1839  | 
|  1826 void AppCacheStorageImpl::CallReinitialize() { |  1840 void AppCacheStorageImpl::DeleteAndStartOver() { | 
|  1827   service_->Reinitialize(); |  1841   DCHECK(is_disabled_); | 
|  1828   // note: 'this' may be deleted during reinit. |  1842   if (!is_incognito_) { | 
 |  1843     VLOG(1) << "Deleting existing appcache data and starting over."; | 
 |  1844     // We can have tasks in flight to close file handles on both the db | 
 |  1845     // and cache threads, we need to allow those tasks to cycle thru | 
 |  1846     // prior to deleting the files and calling reinit. | 
 |  1847     cache_thread_->PostTaskAndReply( | 
 |  1848         FROM_HERE, | 
 |  1849         base::Bind(&base::DoNothing), | 
 |  1850         base::Bind(&AppCacheStorageImpl::DeleteAndStartOverPart2, | 
 |  1851                    weak_factory_.GetWeakPtr())); | 
 |  1852   } | 
 |  1853 } | 
 |  1854  | 
 |  1855 void AppCacheStorageImpl::DeleteAndStartOverPart2() { | 
 |  1856   db_thread_->PostTaskAndReply( | 
 |  1857       FROM_HERE, | 
 |  1858       base::Bind(base::IgnoreResult(&base::DeleteFile), | 
 |  1859                  cache_directory_, true), | 
 |  1860       base::Bind(&AppCacheStorageImpl::CallScheduleReinitialize, | 
 |  1861                   weak_factory_.GetWeakPtr())); | 
 |  1862 } | 
 |  1863  | 
 |  1864 void AppCacheStorageImpl::CallScheduleReinitialize() { | 
 |  1865   service_->ScheduleReinitialize(); | 
 |  1866   // note: 'this' may be deleted at this point. | 
|  1829 } |  1867 } | 
|  1830  |  1868  | 
|  1831 }  // namespace appcache |  1869 }  // namespace appcache | 
| OLD | NEW |