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 "base/bind.h" 6 #include "base/bind_helpers.h" 7 #include "base/memory/scoped_ptr.h" 8 #include "base/message_loop/message_loop.h" 9 #include "content/browser/appcache/appcache.h" 10 #include "content/browser/appcache/appcache_backend_impl.h" 11 #include "content/browser/appcache/appcache_group.h" 12 #include "content/browser/appcache/appcache_host.h" 13 #include "content/browser/appcache/mock_appcache_policy.h" 14 #include "content/browser/appcache/mock_appcache_service.h" 15 #include "net/url_request/url_request.h" 16 #include "storage/browser/quota/quota_manager.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 namespace content { 20 21 class AppCacheHostTest : public testing::Test { 22 public: 23 AppCacheHostTest() { 24 get_status_callback_ = 25 base::Bind(&AppCacheHostTest::GetStatusCallback, 26 base::Unretained(this)); 27 start_update_callback_ = 28 base::Bind(&AppCacheHostTest::StartUpdateCallback, 29 base::Unretained(this)); 30 swap_cache_callback_ = 31 base::Bind(&AppCacheHostTest::SwapCacheCallback, 32 base::Unretained(this)); 33 } 34 35 class MockFrontend : public AppCacheFrontend { 36 public: 37 MockFrontend() 38 : last_host_id_(-222), last_cache_id_(-222), 39 last_status_(APPCACHE_STATUS_OBSOLETE), 40 last_status_changed_(APPCACHE_STATUS_OBSOLETE), 41 last_event_id_(APPCACHE_OBSOLETE_EVENT), 42 content_blocked_(false) { 43 } 44 45 virtual void OnCacheSelected( 46 int host_id, const AppCacheInfo& info) OVERRIDE { 47 last_host_id_ = host_id; 48 last_cache_id_ = info.cache_id; 49 last_status_ = info.status; 50 } 51 52 virtual void OnStatusChanged(const std::vector<int>& host_ids, 53 AppCacheStatus status) OVERRIDE { 54 last_status_changed_ = status; 55 } 56 57 virtual void OnEventRaised(const std::vector<int>& host_ids, 58 AppCacheEventID event_id) OVERRIDE { 59 last_event_id_ = event_id; 60 } 61 62 virtual void OnErrorEventRaised( 63 const std::vector<int>& host_ids, 64 const AppCacheErrorDetails& details) OVERRIDE { 65 last_event_id_ = APPCACHE_ERROR_EVENT; 66 } 67 68 virtual void OnProgressEventRaised(const std::vector<int>& host_ids, 69 const GURL& url, 70 int num_total, 71 int num_complete) OVERRIDE { 72 last_event_id_ = APPCACHE_PROGRESS_EVENT; 73 } 74 75 virtual void OnLogMessage(int host_id, 76 AppCacheLogLevel log_level, 77 const std::string& message) OVERRIDE { 78 } 79 80 virtual void OnContentBlocked(int host_id, 81 const GURL& manifest_url) OVERRIDE { 82 content_blocked_ = true; 83 } 84 85 int last_host_id_; 86 int64 last_cache_id_; 87 AppCacheStatus last_status_; 88 AppCacheStatus last_status_changed_; 89 AppCacheEventID last_event_id_; 90 bool content_blocked_; 91 }; 92 93 class MockQuotaManagerProxy : public storage::QuotaManagerProxy { 94 public: 95 MockQuotaManagerProxy() : QuotaManagerProxy(NULL, NULL) {} 96 97 // Not needed for our tests. 98 virtual void RegisterClient(storage::QuotaClient* client) OVERRIDE {} 99 virtual void NotifyStorageAccessed(storage::QuotaClient::ID client_id, 100 const GURL& origin, 101 storage::StorageType type) OVERRIDE {} 102 virtual void NotifyStorageModified(storage::QuotaClient::ID client_id, 103 const GURL& origin, 104 storage::StorageType type, 105 int64 delta) OVERRIDE {} 106 virtual void SetUsageCacheEnabled(storage::QuotaClient::ID client_id, 107 const GURL& origin, 108 storage::StorageType type, 109 bool enabled) OVERRIDE {} 110 virtual void GetUsageAndQuota( 111 base::SequencedTaskRunner* original_task_runner, 112 const GURL& origin, 113 storage::StorageType type, 114 const GetUsageAndQuotaCallback& callback) OVERRIDE {} 115 116 virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE { 117 inuse_[origin] += 1; 118 } 119 120 virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE { 121 inuse_[origin] -= 1; 122 } 123 124 int GetInUseCount(const GURL& origin) { 125 return inuse_[origin]; 126 } 127 128 void reset() { 129 inuse_.clear(); 130 } 131 132 // Map from origin to count of inuse notifications. 133 std::map<GURL, int> inuse_; 134 135 protected: 136 virtual ~MockQuotaManagerProxy() {} 137 }; 138 139 void GetStatusCallback(AppCacheStatus status, void* param) { 140 last_status_result_ = status; 141 last_callback_param_ = param; 142 } 143 144 void StartUpdateCallback(bool result, void* param) { 145 last_start_result_ = result; 146 last_callback_param_ = param; 147 } 148 149 void SwapCacheCallback(bool result, void* param) { 150 last_swap_result_ = result; 151 last_callback_param_ = param; 152 } 153 154 base::MessageLoop message_loop_; 155 156 // Mock classes for the 'host' to work with 157 MockAppCacheService service_; 158 MockFrontend mock_frontend_; 159 160 // Mock callbacks we expect to receive from the 'host' 161 content::GetStatusCallback get_status_callback_; 162 content::StartUpdateCallback start_update_callback_; 163 content::SwapCacheCallback swap_cache_callback_; 164 165 AppCacheStatus last_status_result_; 166 bool last_swap_result_; 167 bool last_start_result_; 168 void* last_callback_param_; 169 }; 170 171 TEST_F(AppCacheHostTest, Basic) { 172 // Construct a host and test what state it appears to be in. 173 AppCacheHost host(1, &mock_frontend_, &service_); 174 EXPECT_EQ(1, host.host_id()); 175 EXPECT_EQ(&service_, host.service()); 176 EXPECT_EQ(&mock_frontend_, host.frontend()); 177 EXPECT_EQ(NULL, host.associated_cache()); 178 EXPECT_FALSE(host.is_selection_pending()); 179 180 // See that the callbacks are delivered immediately 181 // and respond as if there is no cache selected. 182 last_status_result_ = APPCACHE_STATUS_OBSOLETE; 183 host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1)); 184 EXPECT_EQ(APPCACHE_STATUS_UNCACHED, last_status_result_); 185 EXPECT_EQ(reinterpret_cast<void*>(1), last_callback_param_); 186 187 last_start_result_ = true; 188 host.StartUpdateWithCallback(start_update_callback_, 189 reinterpret_cast<void*>(2)); 190 EXPECT_FALSE(last_start_result_); 191 EXPECT_EQ(reinterpret_cast<void*>(2), last_callback_param_); 192 193 last_swap_result_ = true; 194 host.SwapCacheWithCallback(swap_cache_callback_, reinterpret_cast<void*>(3)); 195 EXPECT_FALSE(last_swap_result_); 196 EXPECT_EQ(reinterpret_cast<void*>(3), last_callback_param_); 197 } 198 199 TEST_F(AppCacheHostTest, SelectNoCache) { 200 scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy( 201 new MockQuotaManagerProxy); 202 service_.set_quota_manager_proxy(mock_quota_proxy.get()); 203 204 // Reset our mock frontend 205 mock_frontend_.last_cache_id_ = -333; 206 mock_frontend_.last_host_id_ = -333; 207 mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE; 208 209 const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin()); 210 { 211 AppCacheHost host(1, &mock_frontend_, &service_); 212 host.SelectCache(kDocAndOriginUrl, kAppCacheNoCacheId, GURL()); 213 EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl)); 214 215 // We should have received an OnCacheSelected msg 216 EXPECT_EQ(1, mock_frontend_.last_host_id_); 217 EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_); 218 EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_); 219 220 // Otherwise, see that it respond as if there is no cache selected. 221 EXPECT_EQ(1, host.host_id()); 222 EXPECT_EQ(&service_, host.service()); 223 EXPECT_EQ(&mock_frontend_, host.frontend()); 224 EXPECT_EQ(NULL, host.associated_cache()); 225 EXPECT_FALSE(host.is_selection_pending()); 226 EXPECT_TRUE(host.preferred_manifest_url().is_empty()); 227 } 228 EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl)); 229 service_.set_quota_manager_proxy(NULL); 230 } 231 232 TEST_F(AppCacheHostTest, ForeignEntry) { 233 // Reset our mock frontend 234 mock_frontend_.last_cache_id_ = -333; 235 mock_frontend_.last_host_id_ = -333; 236 mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE; 237 238 // Precondition, a cache with an entry that is not marked as foreign. 239 const int kCacheId = 22; 240 const GURL kDocumentURL("http://origin/document"); 241 scoped_refptr<AppCache> cache = new AppCache(service_.storage(), kCacheId); 242 cache->AddEntry(kDocumentURL, AppCacheEntry(AppCacheEntry::EXPLICIT)); 243 244 AppCacheHost host(1, &mock_frontend_, &service_); 245 host.MarkAsForeignEntry(kDocumentURL, kCacheId); 246 247 // We should have received an OnCacheSelected msg for kAppCacheNoCacheId. 248 EXPECT_EQ(1, mock_frontend_.last_host_id_); 249 EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_); 250 EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_); 251 252 // See that it respond as if there is no cache selected. 253 EXPECT_EQ(1, host.host_id()); 254 EXPECT_EQ(&service_, host.service()); 255 EXPECT_EQ(&mock_frontend_, host.frontend()); 256 EXPECT_EQ(NULL, host.associated_cache()); 257 EXPECT_FALSE(host.is_selection_pending()); 258 259 // See that the entry was marked as foreign. 260 EXPECT_TRUE(cache->GetEntry(kDocumentURL)->IsForeign()); 261 } 262 263 TEST_F(AppCacheHostTest, ForeignFallbackEntry) { 264 // Reset our mock frontend 265 mock_frontend_.last_cache_id_ = -333; 266 mock_frontend_.last_host_id_ = -333; 267 mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE; 268 269 // Precondition, a cache with a fallback entry that is not marked as foreign. 270 const int kCacheId = 22; 271 const GURL kFallbackURL("http://origin/fallback_resource"); 272 scoped_refptr<AppCache> cache = new AppCache(service_.storage(), kCacheId); 273 cache->AddEntry(kFallbackURL, AppCacheEntry(AppCacheEntry::FALLBACK)); 274 275 AppCacheHost host(1, &mock_frontend_, &service_); 276 host.NotifyMainResourceIsNamespaceEntry(kFallbackURL); 277 host.MarkAsForeignEntry(GURL("http://origin/missing_document"), kCacheId); 278 279 // We should have received an OnCacheSelected msg for kAppCacheNoCacheId. 280 EXPECT_EQ(1, mock_frontend_.last_host_id_); 281 EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_); 282 EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_); 283 284 // See that the fallback entry was marked as foreign. 285 EXPECT_TRUE(cache->GetEntry(kFallbackURL)->IsForeign()); 286 } 287 288 TEST_F(AppCacheHostTest, FailedCacheLoad) { 289 // Reset our mock frontend 290 mock_frontend_.last_cache_id_ = -333; 291 mock_frontend_.last_host_id_ = -333; 292 mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE; 293 294 AppCacheHost host(1, &mock_frontend_, &service_); 295 EXPECT_FALSE(host.is_selection_pending()); 296 297 const int kMockCacheId = 333; 298 299 // Put it in a state where we're waiting on a cache 300 // load prior to finishing cache selection. 301 host.pending_selected_cache_id_ = kMockCacheId; 302 EXPECT_TRUE(host.is_selection_pending()); 303 304 // The callback should not occur until we finish cache selection. 305 last_status_result_ = APPCACHE_STATUS_OBSOLETE; 306 last_callback_param_ = reinterpret_cast<void*>(-1); 307 host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1)); 308 EXPECT_EQ(APPCACHE_STATUS_OBSOLETE, last_status_result_); 309 EXPECT_EQ(reinterpret_cast<void*>(-1), last_callback_param_); 310 311 // Satisfy the load with NULL, a failure. 312 host.OnCacheLoaded(NULL, kMockCacheId); 313 314 // Cache selection should have finished 315 EXPECT_FALSE(host.is_selection_pending()); 316 EXPECT_EQ(1, mock_frontend_.last_host_id_); 317 EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_); 318 EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_); 319 320 // Callback should have fired upon completing the cache load too. 321 EXPECT_EQ(APPCACHE_STATUS_UNCACHED, last_status_result_); 322 EXPECT_EQ(reinterpret_cast<void*>(1), last_callback_param_); 323 } 324 325 TEST_F(AppCacheHostTest, FailedGroupLoad) { 326 AppCacheHost host(1, &mock_frontend_, &service_); 327 328 const GURL kMockManifestUrl("http://foo.bar/baz"); 329 330 // Put it in a state where we're waiting on a cache 331 // load prior to finishing cache selection. 332 host.pending_selected_manifest_url_ = kMockManifestUrl; 333 EXPECT_TRUE(host.is_selection_pending()); 334 335 // The callback should not occur until we finish cache selection. 336 last_status_result_ = APPCACHE_STATUS_OBSOLETE; 337 last_callback_param_ = reinterpret_cast<void*>(-1); 338 host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1)); 339 EXPECT_EQ(APPCACHE_STATUS_OBSOLETE, last_status_result_); 340 EXPECT_EQ(reinterpret_cast<void*>(-1), last_callback_param_); 341 342 // Satisfy the load will NULL, a failure. 343 host.OnGroupLoaded(NULL, kMockManifestUrl); 344 345 // Cache selection should have finished 346 EXPECT_FALSE(host.is_selection_pending()); 347 EXPECT_EQ(1, mock_frontend_.last_host_id_); 348 EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_); 349 EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_); 350 351 // Callback should have fired upon completing the group load. 352 EXPECT_EQ(APPCACHE_STATUS_UNCACHED, last_status_result_); 353 EXPECT_EQ(reinterpret_cast<void*>(1), last_callback_param_); 354 } 355 356 TEST_F(AppCacheHostTest, SetSwappableCache) { 357 AppCacheHost host(1, &mock_frontend_, &service_); 358 host.SetSwappableCache(NULL); 359 EXPECT_FALSE(host.swappable_cache_.get()); 360 361 scoped_refptr<AppCacheGroup> group1(new AppCacheGroup( 362 service_.storage(), GURL(), service_.storage()->NewGroupId())); 363 host.SetSwappableCache(group1.get()); 364 EXPECT_FALSE(host.swappable_cache_.get()); 365 366 AppCache* cache1 = new AppCache(service_.storage(), 111); 367 cache1->set_complete(true); 368 group1->AddCache(cache1); 369 host.SetSwappableCache(group1.get()); 370 EXPECT_EQ(cache1, host.swappable_cache_.get()); 371 372 mock_frontend_.last_host_id_ = -222; // to verify we received OnCacheSelected 373 374 host.AssociateCompleteCache(cache1); 375 EXPECT_FALSE(host.swappable_cache_.get()); // was same as associated cache 376 EXPECT_EQ(APPCACHE_STATUS_IDLE, host.GetStatus()); 377 // verify OnCacheSelected was called 378 EXPECT_EQ(host.host_id(), mock_frontend_.last_host_id_); 379 EXPECT_EQ(cache1->cache_id(), mock_frontend_.last_cache_id_); 380 EXPECT_EQ(APPCACHE_STATUS_IDLE, mock_frontend_.last_status_); 381 382 AppCache* cache2 = new AppCache(service_.storage(), 222); 383 cache2->set_complete(true); 384 group1->AddCache(cache2); 385 EXPECT_EQ(cache2, host.swappable_cache_.get()); // updated to newest 386 387 scoped_refptr<AppCacheGroup> group2( 388 new AppCacheGroup(service_.storage(), GURL("http://foo.com"), 389 service_.storage()->NewGroupId())); 390 AppCache* cache3 = new AppCache(service_.storage(), 333); 391 cache3->set_complete(true); 392 group2->AddCache(cache3); 393 394 AppCache* cache4 = new AppCache(service_.storage(), 444); 395 cache4->set_complete(true); 396 group2->AddCache(cache4); 397 EXPECT_EQ(cache2, host.swappable_cache_.get()); // unchanged 398 399 host.AssociateCompleteCache(cache3); 400 EXPECT_EQ(cache4, host.swappable_cache_.get()); // newest cache in group2 401 EXPECT_FALSE(group1->HasCache()); // both caches in group1 have refcount 0 402 403 host.AssociateNoCache(GURL()); 404 EXPECT_FALSE(host.swappable_cache_.get()); 405 EXPECT_FALSE(group2->HasCache()); // both caches in group2 have refcount 0 406 407 // Host adds reference to newest cache when an update is complete. 408 AppCache* cache5 = new AppCache(service_.storage(), 555); 409 cache5->set_complete(true); 410 group2->AddCache(cache5); 411 host.group_being_updated_ = group2; 412 host.OnUpdateComplete(group2.get()); 413 EXPECT_FALSE(host.group_being_updated_.get()); 414 EXPECT_EQ(cache5, host.swappable_cache_.get()); 415 416 group2->RemoveCache(cache5); 417 EXPECT_FALSE(group2->HasCache()); 418 host.group_being_updated_ = group2; 419 host.OnUpdateComplete(group2.get()); 420 EXPECT_FALSE(host.group_being_updated_.get()); 421 EXPECT_FALSE(host.swappable_cache_.get()); // group2 had no newest cache 422 } 423 424 TEST_F(AppCacheHostTest, ForDedicatedWorker) { 425 const int kMockProcessId = 1; 426 const int kParentHostId = 1; 427 const int kWorkerHostId = 2; 428 429 AppCacheBackendImpl backend_impl; 430 backend_impl.Initialize(&service_, &mock_frontend_, kMockProcessId); 431 backend_impl.RegisterHost(kParentHostId); 432 backend_impl.RegisterHost(kWorkerHostId); 433 434 AppCacheHost* parent_host = backend_impl.GetHost(kParentHostId); 435 EXPECT_FALSE(parent_host->is_for_dedicated_worker()); 436 437 AppCacheHost* worker_host = backend_impl.GetHost(kWorkerHostId); 438 worker_host->SelectCacheForWorker(kParentHostId, kMockProcessId); 439 EXPECT_TRUE(worker_host->is_for_dedicated_worker()); 440 EXPECT_EQ(parent_host, worker_host->GetParentAppCacheHost()); 441 442 // We should have received an OnCacheSelected msg for the worker_host. 443 // The host for workers always indicates 'no cache selected' regardless 444 // of its parent's state. This is OK because the worker cannot access 445 // the scriptable interface, the only function available is resource 446 // loading (see appcache_request_handler_unittests those tests). 447 EXPECT_EQ(kWorkerHostId, mock_frontend_.last_host_id_); 448 EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_); 449 EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_); 450 451 // Simulate the parent being torn down. 452 backend_impl.UnregisterHost(kParentHostId); 453 parent_host = NULL; 454 EXPECT_EQ(NULL, backend_impl.GetHost(kParentHostId)); 455 EXPECT_EQ(NULL, worker_host->GetParentAppCacheHost()); 456 } 457 458 TEST_F(AppCacheHostTest, SelectCacheAllowed) { 459 scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy( 460 new MockQuotaManagerProxy); 461 MockAppCachePolicy mock_appcache_policy; 462 mock_appcache_policy.can_create_return_value_ = true; 463 service_.set_quota_manager_proxy(mock_quota_proxy.get()); 464 service_.set_appcache_policy(&mock_appcache_policy); 465 466 // Reset our mock frontend 467 mock_frontend_.last_cache_id_ = -333; 468 mock_frontend_.last_host_id_ = -333; 469 mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE; 470 mock_frontend_.last_event_id_ = APPCACHE_OBSOLETE_EVENT; 471 mock_frontend_.content_blocked_ = false; 472 473 const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin()); 474 const GURL kManifestUrl(GURL("http://whatever/cache.manifest")); 475 { 476 AppCacheHost host(1, &mock_frontend_, &service_); 477 host.first_party_url_ = kDocAndOriginUrl; 478 host.SelectCache(kDocAndOriginUrl, kAppCacheNoCacheId, kManifestUrl); 479 EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl)); 480 481 // MockAppCacheService::LoadOrCreateGroup is asynchronous, so we shouldn't 482 // have received an OnCacheSelected msg yet. 483 EXPECT_EQ(-333, mock_frontend_.last_host_id_); 484 EXPECT_EQ(-333, mock_frontend_.last_cache_id_); 485 EXPECT_EQ(APPCACHE_STATUS_OBSOLETE, mock_frontend_.last_status_); 486 // No error events either 487 EXPECT_EQ(APPCACHE_OBSOLETE_EVENT, mock_frontend_.last_event_id_); 488 EXPECT_FALSE(mock_frontend_.content_blocked_); 489 490 EXPECT_TRUE(host.is_selection_pending()); 491 } 492 EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl)); 493 service_.set_quota_manager_proxy(NULL); 494 } 495 496 TEST_F(AppCacheHostTest, SelectCacheBlocked) { 497 scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy( 498 new MockQuotaManagerProxy); 499 MockAppCachePolicy mock_appcache_policy; 500 mock_appcache_policy.can_create_return_value_ = false; 501 service_.set_quota_manager_proxy(mock_quota_proxy.get()); 502 service_.set_appcache_policy(&mock_appcache_policy); 503 504 // Reset our mock frontend 505 mock_frontend_.last_cache_id_ = -333; 506 mock_frontend_.last_host_id_ = -333; 507 mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE; 508 mock_frontend_.last_event_id_ = APPCACHE_OBSOLETE_EVENT; 509 mock_frontend_.content_blocked_ = false; 510 511 const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin()); 512 const GURL kManifestUrl(GURL("http://whatever/cache.manifest")); 513 { 514 AppCacheHost host(1, &mock_frontend_, &service_); 515 host.first_party_url_ = kDocAndOriginUrl; 516 host.SelectCache(kDocAndOriginUrl, kAppCacheNoCacheId, kManifestUrl); 517 EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl)); 518 519 // We should have received an OnCacheSelected msg 520 EXPECT_EQ(1, mock_frontend_.last_host_id_); 521 EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_); 522 EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_); 523 524 // Also, an error event was raised 525 EXPECT_EQ(APPCACHE_ERROR_EVENT, mock_frontend_.last_event_id_); 526 EXPECT_TRUE(mock_frontend_.content_blocked_); 527 528 // Otherwise, see that it respond as if there is no cache selected. 529 EXPECT_EQ(1, host.host_id()); 530 EXPECT_EQ(&service_, host.service()); 531 EXPECT_EQ(&mock_frontend_, host.frontend()); 532 EXPECT_EQ(NULL, host.associated_cache()); 533 EXPECT_FALSE(host.is_selection_pending()); 534 EXPECT_TRUE(host.preferred_manifest_url().is_empty()); 535 } 536 EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl)); 537 service_.set_quota_manager_proxy(NULL); 538 } 539 540 } // namespace content 541