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" |
14 #include "webkit/appcache/appcache_storage_impl.h" | 13 #include "webkit/appcache/appcache_storage_impl.h" |
| 14 #include "webkit/quota/mock_special_storage_policy.h" |
| 15 |
| 16 #include <set> |
15 | 17 |
16 namespace { | 18 namespace { |
17 const FilePath::CharType kTestingAppCacheDirname[] = | 19 |
18 FILE_PATH_LITERAL("Application Cache"); | 20 // Examples of a protected and an unprotected origin, to be used througout the |
| 21 // test. |
| 22 const GURL kProtectedOrigin("http://www.protected.com/"); |
| 23 const GURL kProtectedManifest1("http://www.protected.com/1/cache.manifest"); |
| 24 const GURL kProtectedManifest2("http://www.protected.com/2/cache.manifest"); |
| 25 const GURL kNormalOrigin("http://www.normal.com/"); |
| 26 const GURL kNormalManifest1("http://www.normal.com/1/cache.manifest"); |
| 27 const GURL kNormalManifest2("http://www.normal.com/2/cache.manifest"); |
| 28 |
| 29 } // namespace |
| 30 |
| 31 namespace appcache { |
| 32 |
| 33 // This subclass overwrites 2 functions (GetAllAppCacheInfo and |
| 34 // DeleteAppcachesForOrigin). It enables unit testing the internal logic of |
| 35 // ChromeAppCacheInfo (deleting only non-protected origins from the app cache). |
| 36 class TestableChromeAppCacheService : public ChromeAppCacheService { |
| 37 public: |
| 38 explicit TestableChromeAppCacheService(quota::QuotaManagerProxy* proxy); |
| 39 |
| 40 // Mock implementations. |
| 41 virtual void GetAllAppCacheInfo(AppCacheInfoCollection* collection, |
| 42 net::CompletionCallback* callback); |
| 43 virtual void SyncGetAllAppCacheInfo(AppCacheInfoCollection* collection); |
| 44 virtual void DeleteAppCacheGroup(const GURL& origin, |
| 45 net::CompletionCallback* callback); |
| 46 virtual void SyncDeleteAppCacheGroup(const GURL& origin); |
| 47 |
| 48 // Functions for controlling the mock implementations. |
| 49 void set_empty(bool empty); |
| 50 bool GroupDeleted(const GURL& manifest_url); |
| 51 |
| 52 private: |
| 53 // Helper function for the mock implementation |
| 54 static void DeferredCallCallback(net::CompletionCallback* callback, int rv); |
| 55 |
| 56 std::set<GURL> deleted_groups_; |
| 57 bool empty_; |
| 58 }; |
| 59 |
| 60 TestableChromeAppCacheService::TestableChromeAppCacheService( |
| 61 quota::QuotaManagerProxy* proxy) |
| 62 : ChromeAppCacheService(proxy), empty_(false) { |
19 } | 63 } |
20 | 64 |
21 namespace appcache { | 65 void TestableChromeAppCacheService::GetAllAppCacheInfo( |
| 66 AppCacheInfoCollection* collection, |
| 67 net::CompletionCallback* callback) { |
| 68 if (!empty_) { |
| 69 AppCacheInfo info1; |
| 70 info1.manifest_url = kProtectedManifest1; |
| 71 AppCacheInfo info2; |
| 72 info2.manifest_url = kProtectedManifest2; |
| 73 AppCacheInfoVector& info_vector1 = |
| 74 collection->infos_by_origin[kProtectedOrigin]; |
| 75 info_vector1.push_back(info1); |
| 76 info_vector1.push_back(info2); |
| 77 |
| 78 AppCacheInfo info3; |
| 79 info3.manifest_url = kNormalManifest1; |
| 80 AppCacheInfo info4; |
| 81 info4.manifest_url = kNormalManifest2; |
| 82 AppCacheInfoVector& info_vector2 = |
| 83 collection->infos_by_origin[kNormalOrigin]; |
| 84 info_vector2.push_back(info3); |
| 85 info_vector2.push_back(info4); |
| 86 } |
| 87 if (callback) |
| 88 callback->Run(0); |
| 89 } |
| 90 |
| 91 void TestableChromeAppCacheService::SyncGetAllAppCacheInfo( |
| 92 AppCacheInfoCollection* collection) { |
| 93 GetAllAppCacheInfo(collection, NULL); |
| 94 } |
| 95 |
| 96 void TestableChromeAppCacheService::DeleteAppCacheGroup( |
| 97 const GURL& manifest_url, |
| 98 net::CompletionCallback* callback) { |
| 99 deleted_groups_.insert(manifest_url); |
| 100 // The callback must be called asynchronously, otherwise the code breaks. |
| 101 // Defer to guarentee async completion. |
| 102 MessageLoop::current()->PostTask( |
| 103 FROM_HERE, |
| 104 NewRunnableFunction(&DeferredCallCallback, callback, 0)); |
| 105 } |
| 106 |
| 107 void TestableChromeAppCacheService::SyncDeleteAppCacheGroup( |
| 108 const GURL& manifest_url) { |
| 109 deleted_groups_.insert(manifest_url); |
| 110 } |
| 111 |
| 112 void TestableChromeAppCacheService::set_empty(bool empty) { |
| 113 empty_ = empty; |
| 114 } |
| 115 |
| 116 bool TestableChromeAppCacheService::GroupDeleted(const GURL& manifest_url) { |
| 117 return (deleted_groups_.find(manifest_url) != deleted_groups_.end()); |
| 118 } |
| 119 |
| 120 void TestableChromeAppCacheService::DeferredCallCallback( |
| 121 net::CompletionCallback* callback, int rv){ |
| 122 callback->Run(rv); |
| 123 } |
22 | 124 |
23 class ChromeAppCacheServiceTest : public TestingBrowserProcessTest { | 125 class ChromeAppCacheServiceTest : public TestingBrowserProcessTest { |
24 public: | 126 public: |
25 ChromeAppCacheServiceTest() | 127 ChromeAppCacheServiceTest() |
26 : message_loop_(MessageLoop::TYPE_IO), | 128 : message_loop_(MessageLoop::TYPE_IO), |
| 129 ALLOW_THIS_IN_INITIALIZER_LIST(appcache_cleared_callback_( |
| 130 this, &ChromeAppCacheServiceTest::OnAppCacheCleared)), |
| 131 callback_called_(false), |
27 db_thread_(BrowserThread::DB, &message_loop_), | 132 db_thread_(BrowserThread::DB, &message_loop_), |
28 file_thread_(BrowserThread::FILE, &message_loop_), | 133 file_thread_(BrowserThread::FILE, &message_loop_), |
29 cache_thread_(BrowserThread::CACHE, &message_loop_), | 134 cache_thread_(BrowserThread::CACHE, &message_loop_), |
30 io_thread_(BrowserThread::IO, &message_loop_) { | 135 io_thread_(BrowserThread::IO, &message_loop_) { |
31 } | 136 } |
32 | 137 |
33 protected: | 138 protected: |
34 MessageLoop message_loop_; | 139 MessageLoop message_loop_; |
35 ScopedTempDir temp_dir_; | 140 net::CompletionCallbackImpl<ChromeAppCacheServiceTest> |
| 141 appcache_cleared_callback_; |
| 142 bool callback_called_; |
36 | 143 |
37 private: | 144 private: |
| 145 void OnAppCacheCleared(int rv); |
| 146 |
38 BrowserThread db_thread_; | 147 BrowserThread db_thread_; |
39 BrowserThread file_thread_; | 148 BrowserThread file_thread_; |
40 BrowserThread cache_thread_; | 149 BrowserThread cache_thread_; |
41 BrowserThread io_thread_; | 150 BrowserThread io_thread_; |
42 }; | 151 }; |
43 | 152 |
44 TEST_F(ChromeAppCacheServiceTest, KeepOnDestruction) { | 153 void ChromeAppCacheServiceTest::OnAppCacheCleared(int rv) { |
45 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 154 callback_called_ = true; |
46 FilePath appcache_path = temp_dir_.path().Append(kTestingAppCacheDirname); | 155 } |
47 scoped_refptr<ChromeAppCacheService> appcache_service = | 156 |
48 new ChromeAppCacheService(NULL); | 157 TEST_F(ChromeAppCacheServiceTest, ClearAppCache) { |
| 158 // Tests ChromeAppCacheService::ClearAppCache(): nonprotected origins should |
| 159 // be deleted an protected origins should not. |
| 160 scoped_refptr<TestableChromeAppCacheService> appcache_service = |
| 161 new TestableChromeAppCacheService(NULL); |
49 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 mock_policy->AddProtected(kProtectedOrigin); |
| 166 // Passing an empty FilePath is ok; nothing will be saved on the disk during |
| 167 // the test. |
50 BrowserThread::PostTask( | 168 BrowserThread::PostTask( |
51 BrowserThread::IO, FROM_HERE, | 169 BrowserThread::IO, FROM_HERE, |
52 NewRunnableMethod(appcache_service.get(), | 170 NewRunnableMethod(appcache_service.get(), |
53 &ChromeAppCacheService::InitializeOnIOThread, | 171 &ChromeAppCacheService::InitializeOnIOThread, |
54 appcache_path, | 172 FilePath(), |
55 resource_context, | 173 resource_context, |
56 scoped_refptr<quota::SpecialStoragePolicy>(NULL), | 174 mock_policy)); |
57 false)); | 175 // 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(); | 176 message_loop_.RunAllPending(); |
66 | 177 |
67 ASSERT_TRUE(file_util::PathExists(appcache_path)); | 178 appcache_service->ClearAppCache(&appcache_cleared_callback_); |
68 ASSERT_TRUE(file_util::PathExists(appcache_path.AppendASCII("Index"))); | |
69 | 179 |
70 appcache_service = NULL; | 180 // Spin the message loop so that the asynchronous operations (mainly, calling |
| 181 // the callback) happen. |
71 message_loop_.RunAllPending(); | 182 message_loop_.RunAllPending(); |
72 | 183 |
73 ASSERT_TRUE(file_util::PathExists(appcache_path)); | 184 // The appcaches of the protected origin weren't deleted, but the appcache of |
| 185 // the normal origin were. |
| 186 EXPECT_FALSE(appcache_service->GroupDeleted(kProtectedManifest1)); |
| 187 EXPECT_FALSE(appcache_service->GroupDeleted(kProtectedManifest2)); |
| 188 EXPECT_TRUE(appcache_service->GroupDeleted(kNormalManifest1)); |
| 189 EXPECT_TRUE(appcache_service->GroupDeleted(kNormalManifest2)); |
| 190 EXPECT_TRUE(callback_called_); |
74 } | 191 } |
75 | 192 |
76 TEST_F(ChromeAppCacheServiceTest, RemoveOnDestruction) { | 193 TEST_F(ChromeAppCacheServiceTest, ClearEmptyAppCache) { |
77 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 194 // Tests ChromeAppCacheService::ClearAppCache(): the callback function should |
78 FilePath appcache_path = temp_dir_.path().Append(kTestingAppCacheDirname); | 195 // be called even if there are no appcaches to clear. |
79 scoped_refptr<ChromeAppCacheService> appcache_service = | 196 scoped_refptr<TestableChromeAppCacheService> appcache_service = |
80 new ChromeAppCacheService(NULL); | 197 new TestableChromeAppCacheService(NULL); |
| 198 appcache_service->set_empty(true); |
81 const content::ResourceContext* resource_context = NULL; | 199 const content::ResourceContext* resource_context = NULL; |
| 200 scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy = |
| 201 new quota::MockSpecialStoragePolicy; |
| 202 // Passing an empty FilePath is ok; nothing will be saved on the disk during |
| 203 // the test. |
82 BrowserThread::PostTask( | 204 BrowserThread::PostTask( |
83 BrowserThread::IO, FROM_HERE, | 205 BrowserThread::IO, FROM_HERE, |
84 NewRunnableMethod(appcache_service.get(), | 206 NewRunnableMethod(appcache_service.get(), |
85 &ChromeAppCacheService::InitializeOnIOThread, | 207 &ChromeAppCacheService::InitializeOnIOThread, |
86 appcache_path, | 208 FilePath(), |
87 resource_context, | 209 resource_context, |
88 scoped_refptr<quota::SpecialStoragePolicy>(NULL), | 210 mock_policy)); |
89 true)); | 211 // 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(); | 212 message_loop_.RunAllPending(); |
98 | 213 |
99 ASSERT_TRUE(file_util::PathExists(appcache_path)); | 214 appcache_service->ClearAppCache(&appcache_cleared_callback_); |
100 ASSERT_TRUE(file_util::PathExists(appcache_path.AppendASCII("Index"))); | |
101 | 215 |
102 appcache_service = NULL; | 216 // Spin the message loop so that the asynchronous operations (mainly, calling |
| 217 // the callback) happen. |
103 message_loop_.RunAllPending(); | 218 message_loop_.RunAllPending(); |
104 | 219 |
105 ASSERT_FALSE(file_util::PathExists(appcache_path)); | 220 EXPECT_TRUE(callback_called_); |
| 221 } |
| 222 |
| 223 TEST_F(ChromeAppCacheServiceTest, ClearAppCacheWithoutCallback) { |
| 224 // Tests ChromeAppCacheService::ClearAppCache(): passing NULL as callback |
| 225 // should be ok and the functionality should be the same as in the case with |
| 226 // the callback. |
| 227 scoped_refptr<TestableChromeAppCacheService> appcache_service = |
| 228 new TestableChromeAppCacheService(NULL); |
| 229 const content::ResourceContext* resource_context = NULL; |
| 230 scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy = |
| 231 new quota::MockSpecialStoragePolicy; |
| 232 mock_policy->AddProtected(kProtectedOrigin); |
| 233 // Passing an empty FilePath is ok; nothing will be saved on the disk during |
| 234 // the test. |
| 235 BrowserThread::PostTask( |
| 236 BrowserThread::IO, FROM_HERE, |
| 237 NewRunnableMethod(appcache_service.get(), |
| 238 &ChromeAppCacheService::InitializeOnIOThread, |
| 239 FilePath(), |
| 240 resource_context, |
| 241 mock_policy)); |
| 242 // Spin the message loop so that the initialization really happens. |
| 243 message_loop_.RunAllPending(); |
| 244 |
| 245 appcache_service->ClearAppCache(NULL); |
| 246 |
| 247 // Spin the message loop so that the asynchronous operations have a chance to |
| 248 // happen. |
| 249 message_loop_.RunAllPending(); |
| 250 |
| 251 // The appcaches of the protected origin weren't deleted, but the appcache of |
| 252 // the normal origin were. |
| 253 EXPECT_FALSE(appcache_service->GroupDeleted(kProtectedManifest1)); |
| 254 EXPECT_FALSE(appcache_service->GroupDeleted(kProtectedManifest2)); |
| 255 EXPECT_TRUE(appcache_service->GroupDeleted(kNormalManifest1)); |
| 256 EXPECT_TRUE(appcache_service->GroupDeleted(kNormalManifest2)); |
| 257 } |
| 258 |
| 259 TEST_F(ChromeAppCacheServiceTest, SyncClearAppCache) { |
| 260 // Tests ChromeAppCacheService::SyncClearAppCacheOnIOThread(): nonprotected |
| 261 // origins should be deleted an protected origins should not. |
| 262 scoped_refptr<TestableChromeAppCacheService> appcache_service = |
| 263 new TestableChromeAppCacheService(NULL); |
| 264 const content::ResourceContext* resource_context = NULL; |
| 265 scoped_refptr<quota::MockSpecialStoragePolicy> mock_policy = |
| 266 new quota::MockSpecialStoragePolicy; |
| 267 mock_policy->AddProtected(kProtectedOrigin); |
| 268 // Passing an empty FilePath is ok; nothing will be saved on the disk during |
| 269 // the test. |
| 270 BrowserThread::PostTask( |
| 271 BrowserThread::IO, FROM_HERE, |
| 272 NewRunnableMethod(appcache_service.get(), |
| 273 &ChromeAppCacheService::InitializeOnIOThread, |
| 274 FilePath(), |
| 275 resource_context, |
| 276 mock_policy)); |
| 277 // Spin the message loop so that the initialization really happens. |
| 278 message_loop_.RunAllPending(); |
| 279 |
| 280 appcache_service->SyncClearAppCacheOnIOThread(); |
| 281 // The task that completes the appcache clearing synchronously is posted to |
| 282 // the IO thread. Run it, but don't run anything else. |
| 283 message_loop_.PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| 284 message_loop_.Run(); |
| 285 |
| 286 // The appcaches of the protected origin weren't deleted, but the appcache of |
| 287 // the normal origin were. |
| 288 EXPECT_FALSE(appcache_service->GroupDeleted(kProtectedManifest1)); |
| 289 EXPECT_FALSE(appcache_service->GroupDeleted(kProtectedManifest2)); |
| 290 EXPECT_TRUE(appcache_service->GroupDeleted(kNormalManifest1)); |
| 291 EXPECT_TRUE(appcache_service->GroupDeleted(kNormalManifest2)); |
106 } | 292 } |
107 | 293 |
108 } // namespace appcache | 294 } // namespace appcache |
OLD | NEW |