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