Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: content/browser/appcache/chrome_appcache_service_unittest.cc

Issue 7210006: AppCaches which belong to hosted apps are not protected from deletion (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Test beautification. Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698