Dismiss autofill popup on screen orientation change.
[chromium-blink-merge.git] / webkit / browser / appcache / appcache_host_unittest.cc
blob69f1f3a3870fa77e12d0984e1066153c32a731b1
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.
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"
19 namespace appcache {
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));
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) {
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;
52 virtual void OnStatusChanged(const std::vector<int>& host_ids,
53 appcache::Status status) OVERRIDE {
54 last_status_changed_ = status;
57 virtual void OnEventRaised(const std::vector<int>& host_ids,
58 appcache::EventID event_id) OVERRIDE {
59 last_event_id_ = event_id;
62 virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
63 const std::string& message) OVERRIDE {
64 last_event_id_ = ERROR_EVENT;
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;
74 virtual void OnLogMessage(int host_id,
75 appcache::LogLevel log_level,
76 const std::string& message) OVERRIDE {
79 virtual void OnContentBlocked(int host_id,
80 const GURL& manifest_url) OVERRIDE {
81 content_blocked_ = true;
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_;
92 class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
93 public:
94 MockQuotaManagerProxy() : QuotaManagerProxy(NULL, NULL) {}
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 {}
106 virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {
107 inuse_[origin] += 1;
110 virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {
111 inuse_[origin] -= 1;
114 int GetInUseCount(const GURL& origin) {
115 return inuse_[origin];
118 void reset() {
119 inuse_.clear();
122 // Map from origin to count of inuse notifications.
123 std::map<GURL, int> inuse_;
125 protected:
126 virtual ~MockQuotaManagerProxy() {}
129 void GetStatusCallback(Status status, void* param) {
130 last_status_result_ = status;
131 last_callback_param_ = param;
134 void StartUpdateCallback(bool result, void* param) {
135 last_start_result_ = result;
136 last_callback_param_ = param;
139 void SwapCacheCallback(bool result, void* param) {
140 last_swap_result_ = result;
141 last_callback_param_ = param;
144 base::MessageLoop message_loop_;
146 // Mock classes for the 'host' to work with
147 MockAppCacheService service_;
148 MockFrontend mock_frontend_;
150 // Mock callbacks we expect to receive from the 'host'
151 appcache::GetStatusCallback get_status_callback_;
152 appcache::StartUpdateCallback start_update_callback_;
153 appcache::SwapCacheCallback swap_cache_callback_;
155 Status last_status_result_;
156 bool last_swap_result_;
157 bool last_start_result_;
158 void* last_callback_param_;
161 TEST_F(AppCacheHostTest, Basic) {
162 // Construct a host and test what state it appears to be in.
163 AppCacheHost host(1, &mock_frontend_, &service_);
164 EXPECT_EQ(1, host.host_id());
165 EXPECT_EQ(&service_, host.service());
166 EXPECT_EQ(&mock_frontend_, host.frontend());
167 EXPECT_EQ(NULL, host.associated_cache());
168 EXPECT_FALSE(host.is_selection_pending());
170 // See that the callbacks are delivered immediately
171 // and respond as if there is no cache selected.
172 last_status_result_ = OBSOLETE;
173 host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1));
174 EXPECT_EQ(UNCACHED, last_status_result_);
175 EXPECT_EQ(reinterpret_cast<void*>(1), last_callback_param_);
177 last_start_result_ = true;
178 host.StartUpdateWithCallback(start_update_callback_,
179 reinterpret_cast<void*>(2));
180 EXPECT_FALSE(last_start_result_);
181 EXPECT_EQ(reinterpret_cast<void*>(2), last_callback_param_);
183 last_swap_result_ = true;
184 host.SwapCacheWithCallback(swap_cache_callback_, reinterpret_cast<void*>(3));
185 EXPECT_FALSE(last_swap_result_);
186 EXPECT_EQ(reinterpret_cast<void*>(3), last_callback_param_);
189 TEST_F(AppCacheHostTest, SelectNoCache) {
190 scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy(
191 new MockQuotaManagerProxy);
192 service_.set_quota_manager_proxy(mock_quota_proxy.get());
194 // Reset our mock frontend
195 mock_frontend_.last_cache_id_ = -333;
196 mock_frontend_.last_host_id_ = -333;
197 mock_frontend_.last_status_ = OBSOLETE;
199 const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
201 AppCacheHost host(1, &mock_frontend_, &service_);
202 host.SelectCache(kDocAndOriginUrl, kNoCacheId, GURL());
203 EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));
205 // We should have received an OnCacheSelected msg
206 EXPECT_EQ(1, mock_frontend_.last_host_id_);
207 EXPECT_EQ(kNoCacheId, mock_frontend_.last_cache_id_);
208 EXPECT_EQ(UNCACHED, mock_frontend_.last_status_);
210 // Otherwise, see that it respond as if there is no cache selected.
211 EXPECT_EQ(1, host.host_id());
212 EXPECT_EQ(&service_, host.service());
213 EXPECT_EQ(&mock_frontend_, host.frontend());
214 EXPECT_EQ(NULL, host.associated_cache());
215 EXPECT_FALSE(host.is_selection_pending());
216 EXPECT_TRUE(host.preferred_manifest_url().is_empty());
218 EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));
219 service_.set_quota_manager_proxy(NULL);
222 TEST_F(AppCacheHostTest, ForeignEntry) {
223 // Reset our mock frontend
224 mock_frontend_.last_cache_id_ = -333;
225 mock_frontend_.last_host_id_ = -333;
226 mock_frontend_.last_status_ = OBSOLETE;
228 // Precondition, a cache with an entry that is not marked as foreign.
229 const int kCacheId = 22;
230 const GURL kDocumentURL("http://origin/document");
231 scoped_refptr<AppCache> cache = new AppCache(service_.storage(), kCacheId);
232 cache->AddEntry(kDocumentURL, AppCacheEntry(AppCacheEntry::EXPLICIT));
234 AppCacheHost host(1, &mock_frontend_, &service_);
235 host.MarkAsForeignEntry(kDocumentURL, kCacheId);
237 // We should have received an OnCacheSelected msg for kNoCacheId.
238 EXPECT_EQ(1, mock_frontend_.last_host_id_);
239 EXPECT_EQ(kNoCacheId, mock_frontend_.last_cache_id_);
240 EXPECT_EQ(UNCACHED, mock_frontend_.last_status_);
242 // See that it respond as if there is no cache selected.
243 EXPECT_EQ(1, host.host_id());
244 EXPECT_EQ(&service_, host.service());
245 EXPECT_EQ(&mock_frontend_, host.frontend());
246 EXPECT_EQ(NULL, host.associated_cache());
247 EXPECT_FALSE(host.is_selection_pending());
249 // See that the entry was marked as foreign.
250 EXPECT_TRUE(cache->GetEntry(kDocumentURL)->IsForeign());
253 TEST_F(AppCacheHostTest, ForeignFallbackEntry) {
254 // Reset our mock frontend
255 mock_frontend_.last_cache_id_ = -333;
256 mock_frontend_.last_host_id_ = -333;
257 mock_frontend_.last_status_ = OBSOLETE;
259 // Precondition, a cache with a fallback entry that is not marked as foreign.
260 const int kCacheId = 22;
261 const GURL kFallbackURL("http://origin/fallback_resource");
262 scoped_refptr<AppCache> cache = new AppCache(service_.storage(), kCacheId);
263 cache->AddEntry(kFallbackURL, AppCacheEntry(AppCacheEntry::FALLBACK));
265 AppCacheHost host(1, &mock_frontend_, &service_);
266 host.NotifyMainResourceIsNamespaceEntry(kFallbackURL);
267 host.MarkAsForeignEntry(GURL("http://origin/missing_document"), kCacheId);
269 // We should have received an OnCacheSelected msg for kNoCacheId.
270 EXPECT_EQ(1, mock_frontend_.last_host_id_);
271 EXPECT_EQ(kNoCacheId, mock_frontend_.last_cache_id_);
272 EXPECT_EQ(UNCACHED, mock_frontend_.last_status_);
274 // See that the fallback entry was marked as foreign.
275 EXPECT_TRUE(cache->GetEntry(kFallbackURL)->IsForeign());
278 TEST_F(AppCacheHostTest, FailedCacheLoad) {
279 // Reset our mock frontend
280 mock_frontend_.last_cache_id_ = -333;
281 mock_frontend_.last_host_id_ = -333;
282 mock_frontend_.last_status_ = OBSOLETE;
284 AppCacheHost host(1, &mock_frontend_, &service_);
285 EXPECT_FALSE(host.is_selection_pending());
287 const int kMockCacheId = 333;
289 // Put it in a state where we're waiting on a cache
290 // load prior to finishing cache selection.
291 host.pending_selected_cache_id_ = kMockCacheId;
292 EXPECT_TRUE(host.is_selection_pending());
294 // The callback should not occur until we finish cache selection.
295 last_status_result_ = OBSOLETE;
296 last_callback_param_ = reinterpret_cast<void*>(-1);
297 host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1));
298 EXPECT_EQ(OBSOLETE, last_status_result_);
299 EXPECT_EQ(reinterpret_cast<void*>(-1), last_callback_param_);
301 // Satisfy the load with NULL, a failure.
302 host.OnCacheLoaded(NULL, kMockCacheId);
304 // Cache selection should have finished
305 EXPECT_FALSE(host.is_selection_pending());
306 EXPECT_EQ(1, mock_frontend_.last_host_id_);
307 EXPECT_EQ(kNoCacheId, mock_frontend_.last_cache_id_);
308 EXPECT_EQ(UNCACHED, mock_frontend_.last_status_);
310 // Callback should have fired upon completing the cache load too.
311 EXPECT_EQ(UNCACHED, last_status_result_);
312 EXPECT_EQ(reinterpret_cast<void*>(1), last_callback_param_);
315 TEST_F(AppCacheHostTest, FailedGroupLoad) {
316 AppCacheHost host(1, &mock_frontend_, &service_);
318 const GURL kMockManifestUrl("http://foo.bar/baz");
320 // Put it in a state where we're waiting on a cache
321 // load prior to finishing cache selection.
322 host.pending_selected_manifest_url_ = kMockManifestUrl;
323 EXPECT_TRUE(host.is_selection_pending());
325 // The callback should not occur until we finish cache selection.
326 last_status_result_ = OBSOLETE;
327 last_callback_param_ = reinterpret_cast<void*>(-1);
328 host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1));
329 EXPECT_EQ(OBSOLETE, last_status_result_);
330 EXPECT_EQ(reinterpret_cast<void*>(-1), last_callback_param_);
332 // Satisfy the load will NULL, a failure.
333 host.OnGroupLoaded(NULL, kMockManifestUrl);
335 // Cache selection should have finished
336 EXPECT_FALSE(host.is_selection_pending());
337 EXPECT_EQ(1, mock_frontend_.last_host_id_);
338 EXPECT_EQ(kNoCacheId, mock_frontend_.last_cache_id_);
339 EXPECT_EQ(UNCACHED, mock_frontend_.last_status_);
341 // Callback should have fired upon completing the group load.
342 EXPECT_EQ(UNCACHED, last_status_result_);
343 EXPECT_EQ(reinterpret_cast<void*>(1), last_callback_param_);
346 TEST_F(AppCacheHostTest, SetSwappableCache) {
347 AppCacheHost host(1, &mock_frontend_, &service_);
348 host.SetSwappableCache(NULL);
349 EXPECT_FALSE(host.swappable_cache_.get());
351 scoped_refptr<AppCacheGroup> group1(new AppCacheGroup(
352 service_.storage(), GURL(), service_.storage()->NewGroupId()));
353 host.SetSwappableCache(group1.get());
354 EXPECT_FALSE(host.swappable_cache_.get());
356 AppCache* cache1 = new AppCache(service_.storage(), 111);
357 cache1->set_complete(true);
358 group1->AddCache(cache1);
359 host.SetSwappableCache(group1.get());
360 EXPECT_EQ(cache1, host.swappable_cache_.get());
362 mock_frontend_.last_host_id_ = -222; // to verify we received OnCacheSelected
364 host.AssociateCompleteCache(cache1);
365 EXPECT_FALSE(host.swappable_cache_.get()); // was same as associated cache
366 EXPECT_EQ(appcache::IDLE, host.GetStatus());
367 // verify OnCacheSelected was called
368 EXPECT_EQ(host.host_id(), mock_frontend_.last_host_id_);
369 EXPECT_EQ(cache1->cache_id(), mock_frontend_.last_cache_id_);
370 EXPECT_EQ(appcache::IDLE, mock_frontend_.last_status_);
372 AppCache* cache2 = new AppCache(service_.storage(), 222);
373 cache2->set_complete(true);
374 group1->AddCache(cache2);
375 EXPECT_EQ(cache2, host.swappable_cache_.get()); // updated to newest
377 scoped_refptr<AppCacheGroup> group2(
378 new AppCacheGroup(service_.storage(), GURL("http://foo.com"),
379 service_.storage()->NewGroupId()));
380 AppCache* cache3 = new AppCache(service_.storage(), 333);
381 cache3->set_complete(true);
382 group2->AddCache(cache3);
384 AppCache* cache4 = new AppCache(service_.storage(), 444);
385 cache4->set_complete(true);
386 group2->AddCache(cache4);
387 EXPECT_EQ(cache2, host.swappable_cache_.get()); // unchanged
389 host.AssociateCompleteCache(cache3);
390 EXPECT_EQ(cache4, host.swappable_cache_.get()); // newest cache in group2
391 EXPECT_FALSE(group1->HasCache()); // both caches in group1 have refcount 0
393 host.AssociateNoCache(GURL());
394 EXPECT_FALSE(host.swappable_cache_.get());
395 EXPECT_FALSE(group2->HasCache()); // both caches in group2 have refcount 0
397 // Host adds reference to newest cache when an update is complete.
398 AppCache* cache5 = new AppCache(service_.storage(), 555);
399 cache5->set_complete(true);
400 group2->AddCache(cache5);
401 host.group_being_updated_ = group2;
402 host.OnUpdateComplete(group2.get());
403 EXPECT_FALSE(host.group_being_updated_.get());
404 EXPECT_EQ(cache5, host.swappable_cache_.get());
406 group2->RemoveCache(cache5);
407 EXPECT_FALSE(group2->HasCache());
408 host.group_being_updated_ = group2;
409 host.OnUpdateComplete(group2.get());
410 EXPECT_FALSE(host.group_being_updated_.get());
411 EXPECT_FALSE(host.swappable_cache_.get()); // group2 had no newest cache
414 TEST_F(AppCacheHostTest, ForDedicatedWorker) {
415 const int kMockProcessId = 1;
416 const int kParentHostId = 1;
417 const int kWorkerHostId = 2;
419 AppCacheBackendImpl backend_impl;
420 backend_impl.Initialize(&service_, &mock_frontend_, kMockProcessId);
421 backend_impl.RegisterHost(kParentHostId);
422 backend_impl.RegisterHost(kWorkerHostId);
424 AppCacheHost* parent_host = backend_impl.GetHost(kParentHostId);
425 EXPECT_FALSE(parent_host->is_for_dedicated_worker());
427 AppCacheHost* worker_host = backend_impl.GetHost(kWorkerHostId);
428 worker_host->SelectCacheForWorker(kParentHostId, kMockProcessId);
429 EXPECT_TRUE(worker_host->is_for_dedicated_worker());
430 EXPECT_EQ(parent_host, worker_host->GetParentAppCacheHost());
432 // We should have received an OnCacheSelected msg for the worker_host.
433 // The host for workers always indicates 'no cache selected' regardless
434 // of its parent's state. This is OK because the worker cannot access
435 // the scriptable interface, the only function available is resource
436 // loading (see appcache_request_handler_unittests those tests).
437 EXPECT_EQ(kWorkerHostId, mock_frontend_.last_host_id_);
438 EXPECT_EQ(kNoCacheId, mock_frontend_.last_cache_id_);
439 EXPECT_EQ(UNCACHED, mock_frontend_.last_status_);
441 // Simulate the parent being torn down.
442 backend_impl.UnregisterHost(kParentHostId);
443 parent_host = NULL;
444 EXPECT_EQ(NULL, backend_impl.GetHost(kParentHostId));
445 EXPECT_EQ(NULL, worker_host->GetParentAppCacheHost());
448 TEST_F(AppCacheHostTest, SelectCacheAllowed) {
449 scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy(
450 new MockQuotaManagerProxy);
451 MockAppCachePolicy mock_appcache_policy;
452 mock_appcache_policy.can_create_return_value_ = true;
453 service_.set_quota_manager_proxy(mock_quota_proxy.get());
454 service_.set_appcache_policy(&mock_appcache_policy);
456 // Reset our mock frontend
457 mock_frontend_.last_cache_id_ = -333;
458 mock_frontend_.last_host_id_ = -333;
459 mock_frontend_.last_status_ = OBSOLETE;
460 mock_frontend_.last_event_id_ = OBSOLETE_EVENT;
461 mock_frontend_.content_blocked_ = false;
463 const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
464 const GURL kManifestUrl(GURL("http://whatever/cache.manifest"));
466 AppCacheHost host(1, &mock_frontend_, &service_);
467 host.first_party_url_ = kDocAndOriginUrl;
468 host.SelectCache(kDocAndOriginUrl, kNoCacheId, kManifestUrl);
469 EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));
471 // MockAppCacheService::LoadOrCreateGroup is asynchronous, so we shouldn't
472 // have received an OnCacheSelected msg yet.
473 EXPECT_EQ(-333, mock_frontend_.last_host_id_);
474 EXPECT_EQ(-333, mock_frontend_.last_cache_id_);
475 EXPECT_EQ(OBSOLETE, mock_frontend_.last_status_);
476 // No error events either
477 EXPECT_EQ(OBSOLETE_EVENT, mock_frontend_.last_event_id_);
478 EXPECT_FALSE(mock_frontend_.content_blocked_);
480 EXPECT_TRUE(host.is_selection_pending());
482 EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));
483 service_.set_quota_manager_proxy(NULL);
486 TEST_F(AppCacheHostTest, SelectCacheBlocked) {
487 scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy(
488 new MockQuotaManagerProxy);
489 MockAppCachePolicy mock_appcache_policy;
490 mock_appcache_policy.can_create_return_value_ = false;
491 service_.set_quota_manager_proxy(mock_quota_proxy.get());
492 service_.set_appcache_policy(&mock_appcache_policy);
494 // Reset our mock frontend
495 mock_frontend_.last_cache_id_ = -333;
496 mock_frontend_.last_host_id_ = -333;
497 mock_frontend_.last_status_ = OBSOLETE;
498 mock_frontend_.last_event_id_ = OBSOLETE_EVENT;
499 mock_frontend_.content_blocked_ = false;
501 const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
502 const GURL kManifestUrl(GURL("http://whatever/cache.manifest"));
504 AppCacheHost host(1, &mock_frontend_, &service_);
505 host.first_party_url_ = kDocAndOriginUrl;
506 host.SelectCache(kDocAndOriginUrl, kNoCacheId, kManifestUrl);
507 EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));
509 // We should have received an OnCacheSelected msg
510 EXPECT_EQ(1, mock_frontend_.last_host_id_);
511 EXPECT_EQ(kNoCacheId, mock_frontend_.last_cache_id_);
512 EXPECT_EQ(UNCACHED, mock_frontend_.last_status_);
514 // Also, an error event was raised
515 EXPECT_EQ(ERROR_EVENT, mock_frontend_.last_event_id_);
516 EXPECT_TRUE(mock_frontend_.content_blocked_);
518 // Otherwise, see that it respond as if there is no cache selected.
519 EXPECT_EQ(1, host.host_id());
520 EXPECT_EQ(&service_, host.service());
521 EXPECT_EQ(&mock_frontend_, host.frontend());
522 EXPECT_EQ(NULL, host.associated_cache());
523 EXPECT_FALSE(host.is_selection_pending());
524 EXPECT_TRUE(host.preferred_manifest_url().is_empty());
526 EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));
527 service_.set_quota_manager_proxy(NULL);
530 } // namespace appcache