| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/file_util.h" | 5 #include "base/file_util.h" |
| 6 #include "base/memory/ref_counted.h" | 6 #include "base/memory/ref_counted.h" |
| 7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 #include "base/scoped_temp_dir.h" | |
| 9 #include "chrome/test/testing_browser_process.h" | 8 #include "chrome/test/testing_browser_process.h" |
| 10 #include "chrome/test/testing_browser_process_test.h" | 9 #include "chrome/test/testing_browser_process_test.h" |
| 11 #include "content/browser/appcache/chrome_appcache_service.h" | 10 #include "content/browser/appcache/chrome_appcache_service.h" |
| 12 #include "content/browser/browser_thread.h" | 11 #include "content/browser/browser_thread.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 13 #include "webkit/appcache/appcache_database.h" |
| 14 #include "webkit/appcache/appcache_storage_impl.h" | 14 #include "webkit/appcache/appcache_storage_impl.h" |
| 15 #include "webkit/quota/mock_special_storage_policy.h" |
| 16 |
| 17 #include <set> |
| 15 | 18 |
| 16 namespace { | 19 namespace { |
| 17 const FilePath::CharType kTestingAppCacheDirname[] = | 20 const FilePath::CharType kTestingAppCacheDirname[] = |
| 18 FILE_PATH_LITERAL("Application Cache"); | 21 FILE_PATH_LITERAL("Application Cache"); |
| 22 |
| 23 // Examples of a protected and an unprotected origin, to be used througout the |
| 24 // test. |
| 25 const GURL kProtectedOrigin("http://www.protected.com/"); |
| 26 const GURL kNormalOrigin("http://www.normal.com/"); |
| 27 |
| 28 } // unnamed namespace |
| 29 |
| 30 namespace appcache { |
| 31 |
| 32 // This subclass overwrites 2 functions (GetAllAppCacheInfo and |
| 33 // DeleteAppcachesForOrigin). It enables unit testing the internal logic of |
| 34 // ChromeAppCacheInfo (deleting only non-protected origins from the app cache). |
| 35 class TestableChromeAppCacheService : public ChromeAppCacheService |
| 36 { |
| 37 public: |
| 38 explicit TestableChromeAppCacheService(quota::QuotaManagerProxy* proxy); |
| 39 |
| 40 // Mock implementations |
| 41 virtual void GetAllAppCacheInfo(AppCacheInfoCollection* collection, |
| 42 net::CompletionCallback* callback); |
| 43 |
| 44 virtual void DeleteAppCachesForOrigin(const GURL& origin, |
| 45 net::CompletionCallback* callback); |
| 46 |
| 47 // public so that the test program can read it |
| 48 std::set<GURL> deleted_origins_; |
| 49 bool callback_called_; |
| 50 private: |
| 51 // Helper function for the mock implementation |
| 52 static void DeferredCallCallback(net::CompletionCallback* callback, int rv); |
| 53 }; |
| 54 |
| 55 TestableChromeAppCacheService::TestableChromeAppCacheService( |
| 56 quota::QuotaManagerProxy* proxy) |
| 57 : ChromeAppCacheService(proxy), callback_called_(false) |
| 58 { |
| 19 } | 59 } |
| 20 | 60 |
| 21 namespace appcache { | 61 void TestableChromeAppCacheService::GetAllAppCacheInfo( |
| 62 AppCacheInfoCollection* collection, |
| 63 net::CompletionCallback* callback) |
| 64 { |
| 65 AppCacheInfoVector info_vector; |
| 66 collection->infos_by_origin[kProtectedOrigin]; |
| 67 collection->infos_by_origin[kNormalOrigin]; |
| 68 callback->Run(0); |
| 69 } |
| 70 |
| 71 void TestableChromeAppCacheService::DeleteAppCachesForOrigin( |
| 72 const GURL& origin, |
| 73 net::CompletionCallback* callback) |
| 74 { |
| 75 deleted_origins_.insert(origin); |
| 76 // The callback must be called asynchronously, otherwise the code breaks. |
| 77 // Defer to guarentee async completion. |
| 78 MessageLoop::current()->PostTask( |
| 79 FROM_HERE, |
| 80 NewRunnableFunction(&DeferredCallCallback, callback, 0)); |
| 81 } |
| 82 |
| 83 void TestableChromeAppCacheService::DeferredCallCallback( |
| 84 net::CompletionCallback* callback, int rv){ |
| 85 callback->Run(rv); |
| 86 } |
| 22 | 87 |
| 23 class ChromeAppCacheServiceTest : public TestingBrowserProcessTest { | 88 class ChromeAppCacheServiceTest : public TestingBrowserProcessTest { |
| 24 public: | 89 public: |
| 25 ChromeAppCacheServiceTest() | 90 ChromeAppCacheServiceTest() |
| 26 : message_loop_(MessageLoop::TYPE_IO), | 91 : message_loop_(MessageLoop::TYPE_IO), |
| 92 ALLOW_THIS_IN_INITIALIZER_LIST(appcache_cleared_callback_( |
| 93 this, &ChromeAppCacheServiceTest::OnAppCacheCleared)), |
| 94 callback_called_(false), |
| 27 db_thread_(BrowserThread::DB, &message_loop_), | 95 db_thread_(BrowserThread::DB, &message_loop_), |
| 28 file_thread_(BrowserThread::FILE, &message_loop_), | 96 file_thread_(BrowserThread::FILE, &message_loop_), |
| 29 cache_thread_(BrowserThread::CACHE, &message_loop_), | 97 cache_thread_(BrowserThread::CACHE, &message_loop_), |
| 30 io_thread_(BrowserThread::IO, &message_loop_) { | 98 io_thread_(BrowserThread::IO, &message_loop_) { |
| 31 } | 99 } |
| 32 | 100 |
| 33 protected: | 101 protected: |
| 34 MessageLoop message_loop_; | 102 MessageLoop message_loop_; |
| 35 ScopedTempDir temp_dir_; | 103 net::CompletionCallbackImpl<ChromeAppCacheServiceTest> |
| 104 appcache_cleared_callback_; |
| 105 bool callback_called_; |
| 36 | 106 |
| 37 private: | 107 private: |
| 108 void OnAppCacheCleared(int rv); |
| 109 |
| 38 BrowserThread db_thread_; | 110 BrowserThread db_thread_; |
| 39 BrowserThread file_thread_; | 111 BrowserThread file_thread_; |
| 40 BrowserThread cache_thread_; | 112 BrowserThread cache_thread_; |
| 41 BrowserThread io_thread_; | 113 BrowserThread io_thread_; |
| 42 }; | 114 }; |
| 43 | 115 |
| 44 TEST_F(ChromeAppCacheServiceTest, KeepOnDestruction) { | 116 void ChromeAppCacheServiceTest::OnAppCacheCleared(int rv) |
| 45 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 117 { |
| 46 FilePath appcache_path = temp_dir_.path().Append(kTestingAppCacheDirname); | 118 callback_called_ = true; |
| 47 scoped_refptr<ChromeAppCacheService> appcache_service = | 119 } |
| 48 new ChromeAppCacheService(NULL); | 120 |
| 121 TEST_F(ChromeAppCacheServiceTest, ClearAppCache) { |
| 122 // Tests ChromeAppCacheService::ClearAppCache(): nonprotected origins should |
| 123 // be deleted an protected origins should not. |
| 124 scoped_refptr<TestableChromeAppCacheService> appcache_service = |
| 125 new TestableChromeAppCacheService(NULL); |
| 49 const content::ResourceContext* resource_context = NULL; | 126 const content::ResourceContext* resource_context = NULL; |
| 127 scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy = |
| 128 new quota::MockSpecialStoragePolicy; |
| 129 mock_policy->AddProtected(kProtectedOrigin); |
| 130 // Passing an empty FilePath is ok; nothing will be saved on the disk during |
| 131 // the test. |
| 50 BrowserThread::PostTask( | 132 BrowserThread::PostTask( |
| 51 BrowserThread::IO, FROM_HERE, | 133 BrowserThread::IO, FROM_HERE, |
| 52 NewRunnableMethod(appcache_service.get(), | 134 NewRunnableMethod(appcache_service.get(), |
| 53 &ChromeAppCacheService::InitializeOnIOThread, | 135 &ChromeAppCacheService::InitializeOnIOThread, |
| 54 appcache_path, | 136 FilePath(""), |
| 55 resource_context, | 137 resource_context, |
| 56 scoped_refptr<quota::SpecialStoragePolicy>(NULL), | 138 mock_policy)); |
| 57 false)); | 139 // Spin the message loop so that the initialization really happens. |
| 58 // Make the steps needed to initialize the storage of AppCache data. | |
| 59 message_loop_.RunAllPending(); | |
| 60 appcache::AppCacheStorageImpl* storage = | |
| 61 static_cast<appcache::AppCacheStorageImpl*>(appcache_service->storage()); | |
| 62 ASSERT_TRUE(storage->database_->db_connection()); | |
| 63 ASSERT_EQ(1, storage->NewCacheId()); | |
| 64 storage->disk_cache(); | |
| 65 message_loop_.RunAllPending(); | 140 message_loop_.RunAllPending(); |
| 66 | 141 |
| 67 ASSERT_TRUE(file_util::PathExists(appcache_path)); | 142 appcache_service->ClearAppCache(&appcache_cleared_callback_); |
| 68 ASSERT_TRUE(file_util::PathExists(appcache_path.AppendASCII("Index"))); | |
| 69 | 143 |
| 70 appcache_service = NULL; | 144 // Spin the message loop so that the asynchronous operations (mainly, calling |
| 145 // the callback) happen. |
| 71 message_loop_.RunAllPending(); | 146 message_loop_.RunAllPending(); |
| 72 | 147 |
| 73 ASSERT_TRUE(file_util::PathExists(appcache_path)); | 148 // The appcache of the protected origin wasn't deleted, but the appcache of |
| 149 // the normal origin was. |
| 150 ASSERT_EQ(appcache_service->deleted_origins_.find(kProtectedOrigin), |
| 151 appcache_service->deleted_origins_.end()); |
| 152 ASSERT_NE(appcache_service->deleted_origins_.find(kNormalOrigin), |
| 153 appcache_service->deleted_origins_.end()); |
| 154 ASSERT_TRUE(callback_called_); |
| 74 } | 155 } |
| 75 | 156 |
| 76 TEST_F(ChromeAppCacheServiceTest, RemoveOnDestruction) { | 157 TEST_F(ChromeAppCacheServiceTest, ClearEmptyAppCache) { |
| 77 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 158 // Tests ChromeAppCacheService::ClearAppCache(): the callback function should |
| 78 FilePath appcache_path = temp_dir_.path().Append(kTestingAppCacheDirname); | 159 // be called even if there are no appcaches to clear. |
| 79 scoped_refptr<ChromeAppCacheService> appcache_service = | 160 scoped_refptr<TestableChromeAppCacheService> appcache_service = |
| 80 new ChromeAppCacheService(NULL); | 161 new TestableChromeAppCacheService(NULL); |
| 81 const content::ResourceContext* resource_context = NULL; | 162 const content::ResourceContext* resource_context = NULL; |
| 163 scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy = |
| 164 new quota::MockSpecialStoragePolicy; |
| 165 // Passing an empty FilePath is ok; nothing will be saved on the disk during |
| 166 // the test. |
| 82 BrowserThread::PostTask( | 167 BrowserThread::PostTask( |
| 83 BrowserThread::IO, FROM_HERE, | 168 BrowserThread::IO, FROM_HERE, |
| 84 NewRunnableMethod(appcache_service.get(), | 169 NewRunnableMethod(appcache_service.get(), |
| 85 &ChromeAppCacheService::InitializeOnIOThread, | 170 &ChromeAppCacheService::InitializeOnIOThread, |
| 86 appcache_path, | 171 FilePath(""), |
| 87 resource_context, | 172 resource_context, |
| 88 scoped_refptr<quota::SpecialStoragePolicy>(NULL), | 173 mock_policy)); |
| 89 true)); | 174 // Spin the message loop so that the initialization really happens. |
| 90 // Make the steps needed to initialize the storage of AppCache data. | |
| 91 message_loop_.RunAllPending(); | |
| 92 appcache::AppCacheStorageImpl* storage = | |
| 93 static_cast<appcache::AppCacheStorageImpl*>(appcache_service->storage()); | |
| 94 ASSERT_TRUE(storage->database_->db_connection()); | |
| 95 ASSERT_EQ(1, storage->NewCacheId()); | |
| 96 storage->disk_cache(); | |
| 97 message_loop_.RunAllPending(); | 175 message_loop_.RunAllPending(); |
| 98 | 176 |
| 99 ASSERT_TRUE(file_util::PathExists(appcache_path)); | 177 appcache_service->ClearAppCache(&appcache_cleared_callback_); |
| 100 ASSERT_TRUE(file_util::PathExists(appcache_path.AppendASCII("Index"))); | |
| 101 | 178 |
| 102 appcache_service = NULL; | 179 // Spin the message loop so that the asynchronous operations (mainly, calling |
| 180 // the callback) happen. |
| 103 message_loop_.RunAllPending(); | 181 message_loop_.RunAllPending(); |
| 104 | 182 |
| 105 ASSERT_FALSE(file_util::PathExists(appcache_path)); | 183 ASSERT_TRUE(callback_called_); |
| 184 } |
| 185 |
| 186 TEST_F(ChromeAppCacheServiceTest, ClearAppCacheWithoutCallback) { |
| 187 // Tests ChromeAppCacheService::ClearAppCache(): passing NULL as callback |
| 188 // should be ok and the functionality should be the same as in the case with |
| 189 // the callback. |
| 190 scoped_refptr<TestableChromeAppCacheService> appcache_service = |
| 191 new TestableChromeAppCacheService(NULL); |
| 192 const content::ResourceContext* resource_context = NULL; |
| 193 scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy = |
| 194 new quota::MockSpecialStoragePolicy; |
| 195 mock_policy->AddProtected(kProtectedOrigin); |
| 196 // Passing an empty FilePath is ok; nothing will be saved on the disk during |
| 197 // the test. |
| 198 BrowserThread::PostTask( |
| 199 BrowserThread::IO, FROM_HERE, |
| 200 NewRunnableMethod(appcache_service.get(), |
| 201 &ChromeAppCacheService::InitializeOnIOThread, |
| 202 FilePath(""), |
| 203 resource_context, |
| 204 mock_policy)); |
| 205 // Spin the message loop so that the initialization really happens. |
| 206 message_loop_.RunAllPending(); |
| 207 |
| 208 appcache_service->ClearAppCache(NULL); |
| 209 |
| 210 // Spin the message loop so that the asynchronous operations have a chance to |
| 211 // happen. |
| 212 message_loop_.RunAllPending(); |
| 213 |
| 214 // The appcache of the protected origin wasn't deleted, but the appcache of |
| 215 // the normal origin was. |
| 216 ASSERT_EQ(appcache_service->deleted_origins_.find(kProtectedOrigin), |
| 217 appcache_service->deleted_origins_.end()); |
| 218 ASSERT_NE(appcache_service->deleted_origins_.find(kNormalOrigin), |
| 219 appcache_service->deleted_origins_.end()); |
| 220 ASSERT_FALSE(callback_called_); |
| 106 } | 221 } |
| 107 | 222 |
| 108 } // namespace appcache | 223 } // namespace appcache |
| OLD | NEW |