1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <map> 6 #include <set> 7 8 #include "base/bind.h" 9 #include "base/message_loop/message_loop_proxy.h" 10 #include "base/run_loop.h" 11 #include "content/browser/appcache/appcache_quota_client.h" 12 #include "content/browser/appcache/mock_appcache_service.h" 13 #include "net/base/net_errors.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace content { 17 18 // Declared to shorten the line lengths. 19 static const storage::StorageType kTemp = storage::kStorageTypeTemporary; 20 static const storage::StorageType kPerm = storage::kStorageTypePersistent; 21 22 // Base class for our test fixtures. 23 class AppCacheQuotaClientTest : public testing::Test { 24 public: 25 const GURL kOriginA; 26 const GURL kOriginB; 27 const GURL kOriginOther; 28 29 AppCacheQuotaClientTest() 30 : kOriginA("http://host"), 31 kOriginB("http://host:8000"), 32 kOriginOther("http://other"), 33 usage_(0), 34 delete_status_(storage::kQuotaStatusUnknown), 35 num_get_origin_usage_completions_(0), 36 num_get_origins_completions_(0), 37 num_delete_origins_completions_(0), 38 weak_factory_(this) {} 39 40 int64 GetOriginUsage(storage::QuotaClient* client, 41 const GURL& origin, 42 storage::StorageType type) { 43 usage_ = -1; 44 AsyncGetOriginUsage(client, origin, type); 45 base::RunLoop().RunUntilIdle(); 46 return usage_; 47 } 48 49 const std::set<GURL>& GetOriginsForType(storage::QuotaClient* client, 50 storage::StorageType type) { 51 origins_.clear(); 52 AsyncGetOriginsForType(client, type); 53 base::RunLoop().RunUntilIdle(); 54 return origins_; 55 } 56 57 const std::set<GURL>& GetOriginsForHost(storage::QuotaClient* client, 58 storage::StorageType type, 59 const std::string& host) { 60 origins_.clear(); 61 AsyncGetOriginsForHost(client, type, host); 62 base::RunLoop().RunUntilIdle(); 63 return origins_; 64 } 65 66 storage::QuotaStatusCode DeleteOriginData(storage::QuotaClient* client, 67 storage::StorageType type, 68 const GURL& origin) { 69 delete_status_ = storage::kQuotaStatusUnknown; 70 AsyncDeleteOriginData(client, type, origin); 71 base::RunLoop().RunUntilIdle(); 72 return delete_status_; 73 } 74 75 void AsyncGetOriginUsage(storage::QuotaClient* client, 76 const GURL& origin, 77 storage::StorageType type) { 78 client->GetOriginUsage( 79 origin, type, 80 base::Bind(&AppCacheQuotaClientTest::OnGetOriginUsageComplete, 81 weak_factory_.GetWeakPtr())); 82 } 83 84 void AsyncGetOriginsForType(storage::QuotaClient* client, 85 storage::StorageType type) { 86 client->GetOriginsForType( 87 type, 88 base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete, 89 weak_factory_.GetWeakPtr())); 90 } 91 92 void AsyncGetOriginsForHost(storage::QuotaClient* client, 93 storage::StorageType type, 94 const std::string& host) { 95 client->GetOriginsForHost( 96 type, host, 97 base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete, 98 weak_factory_.GetWeakPtr())); 99 } 100 101 void AsyncDeleteOriginData(storage::QuotaClient* client, 102 storage::StorageType type, 103 const GURL& origin) { 104 client->DeleteOriginData( 105 origin, type, 106 base::Bind(&AppCacheQuotaClientTest::OnDeleteOriginDataComplete, 107 weak_factory_.GetWeakPtr())); 108 } 109 110 void SetUsageMapEntry(const GURL& origin, int64 usage) { 111 mock_service_.storage()->usage_map_[origin] = usage; 112 } 113 114 AppCacheQuotaClient* CreateClient() { 115 return new AppCacheQuotaClient(&mock_service_); 116 } 117 118 void Call_NotifyAppCacheReady(AppCacheQuotaClient* client) { 119 client->NotifyAppCacheReady(); 120 } 121 122 void Call_NotifyAppCacheDestroyed(AppCacheQuotaClient* client) { 123 client->NotifyAppCacheDestroyed(); 124 } 125 126 void Call_OnQuotaManagerDestroyed(AppCacheQuotaClient* client) { 127 client->OnQuotaManagerDestroyed(); 128 } 129 130 protected: 131 void OnGetOriginUsageComplete(int64 usage) { 132 ++num_get_origin_usage_completions_; 133 usage_ = usage; 134 } 135 136 void OnGetOriginsComplete(const std::set<GURL>& origins) { 137 ++num_get_origins_completions_; 138 origins_ = origins; 139 } 140 141 void OnDeleteOriginDataComplete(storage::QuotaStatusCode status) { 142 ++num_delete_origins_completions_; 143 delete_status_ = status; 144 } 145 146 base::MessageLoop message_loop_; 147 int64 usage_; 148 std::set<GURL> origins_; 149 storage::QuotaStatusCode delete_status_; 150 int num_get_origin_usage_completions_; 151 int num_get_origins_completions_; 152 int num_delete_origins_completions_; 153 MockAppCacheService mock_service_; 154 base::WeakPtrFactory<AppCacheQuotaClientTest> weak_factory_; 155 }; 156 157 158 TEST_F(AppCacheQuotaClientTest, BasicCreateDestroy) { 159 AppCacheQuotaClient* client = CreateClient(); 160 Call_NotifyAppCacheReady(client); 161 Call_OnQuotaManagerDestroyed(client); 162 Call_NotifyAppCacheDestroyed(client); 163 } 164 165 TEST_F(AppCacheQuotaClientTest, EmptyService) { 166 AppCacheQuotaClient* client = CreateClient(); 167 Call_NotifyAppCacheReady(client); 168 169 EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kTemp)); 170 EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm)); 171 EXPECT_TRUE(GetOriginsForType(client, kTemp).empty()); 172 EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); 173 EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginA.host()).empty()); 174 EXPECT_TRUE(GetOriginsForHost(client, kPerm, kOriginA.host()).empty()); 175 EXPECT_EQ(storage::kQuotaStatusOk, DeleteOriginData(client, kTemp, kOriginA)); 176 EXPECT_EQ(storage::kQuotaStatusOk, DeleteOriginData(client, kPerm, kOriginA)); 177 178 Call_NotifyAppCacheDestroyed(client); 179 Call_OnQuotaManagerDestroyed(client); 180 } 181 182 TEST_F(AppCacheQuotaClientTest, NoService) { 183 AppCacheQuotaClient* client = CreateClient(); 184 Call_NotifyAppCacheReady(client); 185 Call_NotifyAppCacheDestroyed(client); 186 187 EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kTemp)); 188 EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm)); 189 EXPECT_TRUE(GetOriginsForType(client, kTemp).empty()); 190 EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); 191 EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginA.host()).empty()); 192 EXPECT_TRUE(GetOriginsForHost(client, kPerm, kOriginA.host()).empty()); 193 EXPECT_EQ(storage::kQuotaErrorAbort, 194 DeleteOriginData(client, kTemp, kOriginA)); 195 EXPECT_EQ(storage::kQuotaErrorAbort, 196 DeleteOriginData(client, kPerm, kOriginA)); 197 198 Call_OnQuotaManagerDestroyed(client); 199 } 200 201 TEST_F(AppCacheQuotaClientTest, GetOriginUsage) { 202 AppCacheQuotaClient* client = CreateClient(); 203 Call_NotifyAppCacheReady(client); 204 205 SetUsageMapEntry(kOriginA, 1000); 206 EXPECT_EQ(1000, GetOriginUsage(client, kOriginA, kTemp)); 207 EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm)); 208 209 Call_NotifyAppCacheDestroyed(client); 210 Call_OnQuotaManagerDestroyed(client); 211 } 212 213 TEST_F(AppCacheQuotaClientTest, GetOriginsForHost) { 214 AppCacheQuotaClient* client = CreateClient(); 215 Call_NotifyAppCacheReady(client); 216 217 EXPECT_EQ(kOriginA.host(), kOriginB.host()); 218 EXPECT_NE(kOriginA.host(), kOriginOther.host()); 219 220 std::set<GURL> origins = GetOriginsForHost(client, kTemp, kOriginA.host()); 221 EXPECT_TRUE(origins.empty()); 222 223 SetUsageMapEntry(kOriginA, 1000); 224 SetUsageMapEntry(kOriginB, 10); 225 SetUsageMapEntry(kOriginOther, 500); 226 227 origins = GetOriginsForHost(client, kTemp, kOriginA.host()); 228 EXPECT_EQ(2ul, origins.size()); 229 EXPECT_TRUE(origins.find(kOriginA) != origins.end()); 230 EXPECT_TRUE(origins.find(kOriginB) != origins.end()); 231 232 origins = GetOriginsForHost(client, kTemp, kOriginOther.host()); 233 EXPECT_EQ(1ul, origins.size()); 234 EXPECT_TRUE(origins.find(kOriginOther) != origins.end()); 235 236 origins = GetOriginsForHost(client, kPerm, kOriginA.host()); 237 EXPECT_TRUE(origins.empty()); 238 239 Call_NotifyAppCacheDestroyed(client); 240 Call_OnQuotaManagerDestroyed(client); 241 } 242 243 TEST_F(AppCacheQuotaClientTest, GetOriginsForType) { 244 AppCacheQuotaClient* client = CreateClient(); 245 Call_NotifyAppCacheReady(client); 246 247 EXPECT_TRUE(GetOriginsForType(client, kTemp).empty()); 248 EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); 249 250 SetUsageMapEntry(kOriginA, 1000); 251 SetUsageMapEntry(kOriginB, 10); 252 253 std::set<GURL> origins = GetOriginsForType(client, kTemp); 254 EXPECT_EQ(2ul, origins.size()); 255 EXPECT_TRUE(origins.find(kOriginA) != origins.end()); 256 EXPECT_TRUE(origins.find(kOriginB) != origins.end()); 257 258 EXPECT_TRUE(GetOriginsForType(client, kPerm).empty()); 259 260 Call_NotifyAppCacheDestroyed(client); 261 Call_OnQuotaManagerDestroyed(client); 262 } 263 264 TEST_F(AppCacheQuotaClientTest, DeleteOriginData) { 265 AppCacheQuotaClient* client = CreateClient(); 266 Call_NotifyAppCacheReady(client); 267 268 // Perm deletions are short circuited in the Client and 269 // should not reach the AppCacheServiceImpl. 270 EXPECT_EQ(storage::kQuotaStatusOk, DeleteOriginData(client, kPerm, kOriginA)); 271 EXPECT_EQ(0, mock_service_.delete_called_count()); 272 273 EXPECT_EQ(storage::kQuotaStatusOk, DeleteOriginData(client, kTemp, kOriginA)); 274 EXPECT_EQ(1, mock_service_.delete_called_count()); 275 276 mock_service_.set_mock_delete_appcaches_for_origin_result( 277 net::ERR_ABORTED); 278 EXPECT_EQ(storage::kQuotaErrorAbort, 279 DeleteOriginData(client, kTemp, kOriginA)); 280 EXPECT_EQ(2, mock_service_.delete_called_count()); 281 282 Call_OnQuotaManagerDestroyed(client); 283 Call_NotifyAppCacheDestroyed(client); 284 } 285 286 TEST_F(AppCacheQuotaClientTest, PendingRequests) { 287 AppCacheQuotaClient* client = CreateClient(); 288 289 SetUsageMapEntry(kOriginA, 1000); 290 SetUsageMapEntry(kOriginB, 10); 291 SetUsageMapEntry(kOriginOther, 500); 292 293 // Queue up some reqeusts. 294 AsyncGetOriginUsage(client, kOriginA, kPerm); 295 AsyncGetOriginUsage(client, kOriginB, kTemp); 296 AsyncGetOriginsForType(client, kPerm); 297 AsyncGetOriginsForType(client, kTemp); 298 AsyncGetOriginsForHost(client, kTemp, kOriginA.host()); 299 AsyncGetOriginsForHost(client, kTemp, kOriginOther.host()); 300 AsyncDeleteOriginData(client, kTemp, kOriginA); 301 AsyncDeleteOriginData(client, kPerm, kOriginA); 302 AsyncDeleteOriginData(client, kTemp, kOriginB); 303 304 EXPECT_EQ(0, num_get_origin_usage_completions_); 305 EXPECT_EQ(0, num_get_origins_completions_); 306 EXPECT_EQ(0, num_delete_origins_completions_); 307 base::RunLoop().RunUntilIdle(); 308 EXPECT_EQ(0, num_get_origin_usage_completions_); 309 EXPECT_EQ(0, num_get_origins_completions_); 310 EXPECT_EQ(0, num_delete_origins_completions_); 311 312 // Pending requests should get serviced when the appcache is ready. 313 Call_NotifyAppCacheReady(client); 314 EXPECT_EQ(2, num_get_origin_usage_completions_); 315 EXPECT_EQ(4, num_get_origins_completions_); 316 EXPECT_EQ(0, num_delete_origins_completions_); 317 base::RunLoop().RunUntilIdle(); 318 EXPECT_EQ(3, num_delete_origins_completions_); // deletes are really async 319 320 // They should be serviced in order requested. 321 EXPECT_EQ(10, usage_); 322 EXPECT_EQ(1ul, origins_.size()); 323 EXPECT_TRUE(origins_.find(kOriginOther) != origins_.end()); 324 325 Call_NotifyAppCacheDestroyed(client); 326 Call_OnQuotaManagerDestroyed(client); 327 } 328 329 TEST_F(AppCacheQuotaClientTest, DestroyServiceWithPending) { 330 AppCacheQuotaClient* client = CreateClient(); 331 332 SetUsageMapEntry(kOriginA, 1000); 333 SetUsageMapEntry(kOriginB, 10); 334 SetUsageMapEntry(kOriginOther, 500); 335 336 // Queue up some reqeusts prior to being ready. 337 AsyncGetOriginUsage(client, kOriginA, kPerm); 338 AsyncGetOriginUsage(client, kOriginB, kTemp); 339 AsyncGetOriginsForType(client, kPerm); 340 AsyncGetOriginsForType(client, kTemp); 341 AsyncGetOriginsForHost(client, kTemp, kOriginA.host()); 342 AsyncGetOriginsForHost(client, kTemp, kOriginOther.host()); 343 AsyncDeleteOriginData(client, kTemp, kOriginA); 344 AsyncDeleteOriginData(client, kPerm, kOriginA); 345 AsyncDeleteOriginData(client, kTemp, kOriginB); 346 base::RunLoop().RunUntilIdle(); 347 EXPECT_EQ(0, num_get_origin_usage_completions_); 348 EXPECT_EQ(0, num_get_origins_completions_); 349 EXPECT_EQ(0, num_delete_origins_completions_); 350 351 // Kill the service. 352 Call_NotifyAppCacheDestroyed(client); 353 354 // All should have been aborted and called completion. 355 EXPECT_EQ(2, num_get_origin_usage_completions_); 356 EXPECT_EQ(4, num_get_origins_completions_); 357 EXPECT_EQ(3, num_delete_origins_completions_); 358 EXPECT_EQ(0, usage_); 359 EXPECT_TRUE(origins_.empty()); 360 EXPECT_EQ(storage::kQuotaErrorAbort, delete_status_); 361 362 Call_OnQuotaManagerDestroyed(client); 363 } 364 365 TEST_F(AppCacheQuotaClientTest, DestroyQuotaManagerWithPending) { 366 AppCacheQuotaClient* client = CreateClient(); 367 368 SetUsageMapEntry(kOriginA, 1000); 369 SetUsageMapEntry(kOriginB, 10); 370 SetUsageMapEntry(kOriginOther, 500); 371 372 // Queue up some reqeusts prior to being ready. 373 AsyncGetOriginUsage(client, kOriginA, kPerm); 374 AsyncGetOriginUsage(client, kOriginB, kTemp); 375 AsyncGetOriginsForType(client, kPerm); 376 AsyncGetOriginsForType(client, kTemp); 377 AsyncGetOriginsForHost(client, kTemp, kOriginA.host()); 378 AsyncGetOriginsForHost(client, kTemp, kOriginOther.host()); 379 AsyncDeleteOriginData(client, kTemp, kOriginA); 380 AsyncDeleteOriginData(client, kPerm, kOriginA); 381 AsyncDeleteOriginData(client, kTemp, kOriginB); 382 base::RunLoop().RunUntilIdle(); 383 EXPECT_EQ(0, num_get_origin_usage_completions_); 384 EXPECT_EQ(0, num_get_origins_completions_); 385 EXPECT_EQ(0, num_delete_origins_completions_); 386 387 // Kill the quota manager. 388 Call_OnQuotaManagerDestroyed(client); 389 Call_NotifyAppCacheReady(client); 390 391 // Callbacks should be deleted and not called. 392 base::RunLoop().RunUntilIdle(); 393 EXPECT_EQ(0, num_get_origin_usage_completions_); 394 EXPECT_EQ(0, num_get_origins_completions_); 395 EXPECT_EQ(0, num_delete_origins_completions_); 396 397 Call_NotifyAppCacheDestroyed(client); 398 } 399 400 TEST_F(AppCacheQuotaClientTest, DestroyWithDeleteInProgress) { 401 AppCacheQuotaClient* client = CreateClient(); 402 Call_NotifyAppCacheReady(client); 403 404 // Start an async delete. 405 AsyncDeleteOriginData(client, kTemp, kOriginB); 406 EXPECT_EQ(0, num_delete_origins_completions_); 407 408 // Kill the service. 409 Call_NotifyAppCacheDestroyed(client); 410 411 // Should have been aborted. 412 EXPECT_EQ(1, num_delete_origins_completions_); 413 EXPECT_EQ(storage::kQuotaErrorAbort, delete_status_); 414 415 // A real completion callback from the service should 416 // be dropped if it comes in after NotifyAppCacheDestroyed. 417 base::RunLoop().RunUntilIdle(); 418 EXPECT_EQ(1, num_delete_origins_completions_); 419 EXPECT_EQ(storage::kQuotaErrorAbort, delete_status_); 420 421 Call_OnQuotaManagerDestroyed(client); 422 } 423 424 } // namespace content 425