diff options
-rw-r--r-- | chrome/common/appcache/chrome_appcache_service.cc | 22 | ||||
-rw-r--r-- | chrome/common/appcache/chrome_appcache_service.h | 7 | ||||
-rw-r--r-- | webkit/appcache/appcache_policy.h | 38 | ||||
-rw-r--r-- | webkit/appcache/appcache_service.cc | 2 | ||||
-rw-r--r-- | webkit/appcache/appcache_service.h | 11 | ||||
-rw-r--r-- | webkit/appcache/appcache_storage_impl.cc | 35 | ||||
-rw-r--r-- | webkit/appcache/appcache_storage_impl.h | 5 | ||||
-rw-r--r-- | webkit/appcache/appcache_storage_impl_unittest.cc | 72 | ||||
-rw-r--r-- | webkit/appcache/appcache_update_job.cc | 51 | ||||
-rw-r--r-- | webkit/appcache/appcache_update_job.h | 9 | ||||
-rw-r--r-- | webkit/appcache/appcache_update_job_unittest.cc | 105 | ||||
-rw-r--r-- | webkit/webkit.gyp | 1 |
12 files changed, 337 insertions, 21 deletions
diff --git a/chrome/common/appcache/chrome_appcache_service.cc b/chrome/common/appcache/chrome_appcache_service.cc index 68e30c7..5fdb17f 100644 --- a/chrome/common/appcache/chrome_appcache_service.cc +++ b/chrome/common/appcache/chrome_appcache_service.cc @@ -10,6 +10,7 @@ #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/notification_service.h" +#include "net/base/net_errors.h" #include "webkit/appcache/appcache_thread.h" static bool has_initialized_thread_ids; @@ -33,6 +34,7 @@ ChromeAppCacheService::ChromeAppCacheService( Initialize(request_context->is_off_the_record() ? FilePath() : profile_path.Append(chrome::kAppCacheDirname)); set_request_context(request_context); + set_appcache_policy(this); } ChromeAppCacheService::~ChromeAppCacheService() { @@ -44,6 +46,26 @@ void ChromeAppCacheService::ClearLocalState(const FilePath& profile_path) { file_util::Delete(profile_path.Append(chrome::kAppCacheDirname), true); } +bool ChromeAppCacheService::CanLoadAppCache(const GURL& manifest_url) { + ContentSetting setting = host_contents_settings_map_->GetContentSetting( + manifest_url, CONTENT_SETTINGS_TYPE_COOKIES); + DCHECK(setting != CONTENT_SETTING_DEFAULT); + return setting == CONTENT_SETTING_ALLOW || + setting == CONTENT_SETTING_ASK; // we don't prompt for read access +} + +int ChromeAppCacheService::CanCreateAppCache( + const GURL& manifest_url, net::CompletionCallback* callback) { + ContentSetting setting = host_contents_settings_map_->GetContentSetting( + manifest_url, CONTENT_SETTINGS_TYPE_COOKIES); + DCHECK(setting != CONTENT_SETTING_DEFAULT); + if (setting == CONTENT_SETTING_ASK) { + // TODO(michaeln): prompt the user, for now we block + setting = CONTENT_SETTING_BLOCK; + } + return (setting != CONTENT_SETTING_BLOCK) ? net::OK : net::ERR_ACCESS_DENIED; +} + void ChromeAppCacheService::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { diff --git a/chrome/common/appcache/chrome_appcache_service.h b/chrome/common/appcache/chrome_appcache_service.h index ec7b0bd..fd36a05 100644 --- a/chrome/common/appcache/chrome_appcache_service.h +++ b/chrome/common/appcache/chrome_appcache_service.h @@ -8,6 +8,7 @@ #include "base/ref_counted.h" #include "chrome/browser/host_content_settings_map.h" #include "chrome/common/notification_registrar.h" +#include "webkit/appcache/appcache_policy.h" #include "webkit/appcache/appcache_service.h" class ChromeURLRequestContext; @@ -24,6 +25,7 @@ class FilePath; class ChromeAppCacheService : public base::RefCounted<ChromeAppCacheService>, public appcache::AppCacheService, + public appcache::AppCachePolicy, public NotificationObserver { public: ChromeAppCacheService(const FilePath& profile_path, @@ -35,6 +37,11 @@ class ChromeAppCacheService friend class base::RefCounted<ChromeAppCacheService>; virtual ~ChromeAppCacheService(); + // AppCachePolicy overrides + virtual bool CanLoadAppCache(const GURL& manifest_url); + virtual int CanCreateAppCache(const GURL& manifest_url, + net::CompletionCallback* callback); + // NotificationObserver override virtual void Observe(NotificationType type, const NotificationSource& source, diff --git a/webkit/appcache/appcache_policy.h b/webkit/appcache/appcache_policy.h new file mode 100644 index 0000000..7d3e844 --- /dev/null +++ b/webkit/appcache/appcache_policy.h @@ -0,0 +1,38 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_APPCACHE_APPCACHE_POLICY_H_ +#define WEBKIT_APPCACHE_APPCACHE_POLICY_H_ + +#include "net/base/completion_callback.h" + +class GURL; + +namespace appcache { + +class AppCachePolicy { + public: + AppCachePolicy() {} + + // Called prior to loading a main resource from the appache. + // Returns true if allowed. This is expected to return immediately + // without any user prompt. + virtual bool CanLoadAppCache(const GURL& manifest_url) = 0; + + // Called prior to creating a new appcache. + // Returns net::OK if allowed, net::ERR_ACCESS_DENIED if not allowed. + // May also return net::ERR_IO_PENDING to indicate + // that the completion callback will be notified (asynchronously and on + // the current thread) of the final result. Note: The completion callback + // must remain valid until notified. + virtual int CanCreateAppCache(const GURL& manifest_url, + net::CompletionCallback* callback) = 0; + + protected: + ~AppCachePolicy() {} +}; + +} // namespace appcache + +#endif // WEBKIT_APPCACHE_APPCACHE_POLICY_H_ diff --git a/webkit/appcache/appcache_service.cc b/webkit/appcache/appcache_service.cc index f0c8784..65cc457 100644 --- a/webkit/appcache/appcache_service.cc +++ b/webkit/appcache/appcache_service.cc @@ -11,7 +11,7 @@ namespace appcache { AppCacheService::AppCacheService() - : request_context_(NULL) { + : appcache_policy_(NULL), request_context_(NULL) { } AppCacheService::~AppCacheService() { diff --git a/webkit/appcache/appcache_service.h b/webkit/appcache/appcache_service.h index 986e620..70a0953 100644 --- a/webkit/appcache/appcache_service.h +++ b/webkit/appcache/appcache_service.h @@ -15,6 +15,7 @@ class URLRequestContext; namespace appcache { class AppCacheBackendImpl; +class AppCachePolicy; // Class that manages the application cache service. Sends notifications // to many frontends. One instance per user-profile. Each instance has @@ -40,6 +41,14 @@ class AppCacheService { request_context_ = context; } + // The appcache policy, may be null, in which case access is always allowed. + // The service does NOT assume ownership of the policy, it is the callers + // responsibility to ensure that the pointer remains valid while set. + AppCachePolicy* appcache_policy() const { return appcache_policy_; } + void set_appcache_policy(AppCachePolicy* policy) { + appcache_policy_ = policy; + } + // Track which processes are using this appcache service. void RegisterBackend(AppCacheBackendImpl* backend_impl); void UnregisterBackend(AppCacheBackendImpl* backend_impl); @@ -51,6 +60,8 @@ class AppCacheService { AppCacheStorage* storage() const { return storage_.get(); } protected: + AppCachePolicy* appcache_policy_; + // Deals with persistence. scoped_ptr<AppCacheStorage> storage_; diff --git a/webkit/appcache/appcache_storage_impl.cc b/webkit/appcache/appcache_storage_impl.cc index ed893c1..0d908aa 100644 --- a/webkit/appcache/appcache_storage_impl.cc +++ b/webkit/appcache/appcache_storage_impl.cc @@ -12,11 +12,14 @@ #include "base/stl_util-inl.h" #include "base/string_util.h" #include "net/base/cache_type.h" +#include "net/base/net_errors.h" #include "webkit/appcache/appcache.h" #include "webkit/appcache/appcache_database.h" #include "webkit/appcache/appcache_entry.h" #include "webkit/appcache/appcache_group.h" +#include "webkit/appcache/appcache_policy.h" #include "webkit/appcache/appcache_response.h" +#include "webkit/appcache/appcache_service.h" #include "webkit/appcache/appcache_thread.h" namespace appcache { @@ -562,9 +565,8 @@ void AppCacheStorageImpl::FindMainResponseTask::Run() { } void AppCacheStorageImpl::FindMainResponseTask::RunCompleted() { - FOR_EACH_DELEGATE(delegates_, - OnMainResponseFound(url_, entry_, fallback_entry_, - cache_id_, manifest_url_)); + storage_->CheckPolicyAndCallOnMainResponseFound( + &delegates_, url_, entry_, fallback_entry_, cache_id_, manifest_url_); } // MarkEntryAsForeignTask ------- @@ -902,13 +904,36 @@ void AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse( scoped_refptr<AppCacheGroup> group, scoped_refptr<AppCache> cache, scoped_refptr<DelegateReference> delegate_ref) { if (delegate_ref->delegate) { - delegate_ref->delegate->OnMainResponseFound( - url, found_entry, AppCacheEntry(), + DelegateReferenceVector delegates(1, delegate_ref); + CheckPolicyAndCallOnMainResponseFound( + &delegates, url, found_entry, AppCacheEntry(), cache.get() ? cache->cache_id() : kNoCacheId, group.get() ? group->manifest_url() : GURL()); } } +void AppCacheStorageImpl::CheckPolicyAndCallOnMainResponseFound( + DelegateReferenceVector* delegates, const GURL& url, + const AppCacheEntry& entry, const AppCacheEntry& fallback_entry, + int64 cache_id, const GURL& manifest_url) { + if (!manifest_url.is_empty()) { + // Check the policy prior to returning a main resource from the appcache. + AppCachePolicy* policy = service()->appcache_policy(); + if (policy && !policy->CanLoadAppCache(manifest_url)) { + FOR_EACH_DELEGATE( + (*delegates), + OnMainResponseFound(url, AppCacheEntry(), AppCacheEntry(), + kNoCacheId, GURL())); + return; + } + } + + FOR_EACH_DELEGATE( + (*delegates), + OnMainResponseFound(url, entry, fallback_entry, + cache_id, manifest_url)); +} + void AppCacheStorageImpl::FindResponseForSubRequest( AppCache* cache, const GURL& url, AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry, diff --git a/webkit/appcache/appcache_storage_impl.h b/webkit/appcache/appcache_storage_impl.h index 96fc876..93391e9 100644 --- a/webkit/appcache/appcache_storage_impl.h +++ b/webkit/appcache/appcache_storage_impl.h @@ -97,6 +97,11 @@ class AppCacheStorageImpl : public AppCacheStorage { scoped_refptr<AppCacheGroup> group, scoped_refptr<AppCache> newest_cache, scoped_refptr<DelegateReference> delegate_ref); + void CheckPolicyAndCallOnMainResponseFound( + DelegateReferenceVector* delegates, const GURL& url, + const AppCacheEntry& entry, const AppCacheEntry& fallback_entry, + int64 cache_id, const GURL& manifest_url); + disk_cache::Backend* disk_cache(); // The directory in which we place files in the file system. diff --git a/webkit/appcache/appcache_storage_impl_unittest.cc b/webkit/appcache/appcache_storage_impl_unittest.cc index 9e207f8..ad6a8310 100644 --- a/webkit/appcache/appcache_storage_impl_unittest.cc +++ b/webkit/appcache/appcache_storage_impl_unittest.cc @@ -7,11 +7,13 @@ #include "base/message_loop.h" #include "base/thread.h" #include "base/waitable_event.h" +#include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/appcache/appcache.h" #include "webkit/appcache/appcache_database.h" #include "webkit/appcache/appcache_entry.h" #include "webkit/appcache/appcache_group.h" +#include "webkit/appcache/appcache_policy.h" #include "webkit/appcache/appcache_service.h" #include "webkit/appcache/appcache_storage_impl.h" #include "webkit/tools/test_shell/simple_appcache_system.h" @@ -130,6 +132,34 @@ class AppCacheStorageImplTest : public testing::Test { AppCacheStorageImplTest* test_; }; + class MockAppCachePolicy : public AppCachePolicy { + public: + explicit MockAppCachePolicy(AppCacheStorageImplTest* test) + : can_load_return_value_(true), can_create_return_value_(0), + callback_(NULL), test_(test) { + } + + virtual bool CanLoadAppCache(const GURL& manifest_url) { + requested_manifest_url_ = manifest_url; + return can_load_return_value_; + } + + virtual int CanCreateAppCache(const GURL& manifest_url, + net::CompletionCallback* callback) { + requested_manifest_url_ = manifest_url; + callback_ = callback; + if (can_create_return_value_ == net::ERR_IO_PENDING) + test_->ScheduleNextTask(); + return can_create_return_value_; + } + + bool can_load_return_value_; + int can_create_return_value_; + GURL requested_manifest_url_; + net::CompletionCallback* callback_; + AppCacheStorageImplTest* test_; + }; + // Helper class run a test on our io_thread. The io_thread // is spun up once and reused for all tests. template <class Method> @@ -182,7 +212,8 @@ class AppCacheStorageImplTest : public testing::Test { // Test harness -------------------------------------------------- AppCacheStorageImplTest() - : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { + : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), + ALLOW_THIS_IN_INITIALIZER_LIST(policy_(this)) { } template <class Method> @@ -664,17 +695,25 @@ class AppCacheStorageImplTest : public testing::Test { // BasicFindMainResponse ------------------------------- void BasicFindMainResponseInDatabase() { - BasicFindMainResponse(true); + BasicFindMainResponse(true, false); } void BasicFindMainResponseInWorkingSet() { - BasicFindMainResponse(false); + BasicFindMainResponse(false, false); + } + + void BlockFindMainResponseWithPolicyCheck() { + BasicFindMainResponse(true, true); } - void BasicFindMainResponse(bool drop_from_working_set) { + void BasicFindMainResponse(bool drop_from_working_set, + bool block_with_policy_check) { PushNextTask(method_factory_.NewRunnableMethod( &AppCacheStorageImplTest::Verify_BasicFindMainResponse)); + policy_.can_load_return_value_ = !block_with_policy_check; + service()->set_appcache_policy(&policy_); + // Setup some preconditions. Create a complete cache with an entry // in storage. MakeCacheAndGroup(kManifestUrl, 1, 1, true); @@ -700,13 +739,18 @@ class AppCacheStorageImplTest : public testing::Test { } void Verify_BasicFindMainResponse() { - EXPECT_EQ(kEntryUrl, delegate()->found_url_); - EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_); - EXPECT_EQ(1, delegate()->found_cache_id_); - EXPECT_EQ(1, delegate()->found_entry_.response_id()); - EXPECT_TRUE(delegate()->found_entry_.IsExplicit()); - EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id()); - TestFinished(); + EXPECT_EQ(kManifestUrl, policy_.requested_manifest_url_); + if (policy_.can_load_return_value_) { + EXPECT_EQ(kEntryUrl, delegate()->found_url_); + EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_); + EXPECT_EQ(1, delegate()->found_cache_id_); + EXPECT_EQ(1, delegate()->found_entry_.response_id()); + EXPECT_TRUE(delegate()->found_entry_.IsExplicit()); + EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id()); + TestFinished(); + } else { + Verify_FindNoMainResponse(); + } } // BasicFindMainFallbackResponse ------------------------------- @@ -914,6 +958,7 @@ class AppCacheStorageImplTest : public testing::Test { ScopedRunnableMethodFactory<AppCacheStorageImplTest> method_factory_; scoped_ptr<base::WaitableEvent> test_finished_event_; std::stack<Task*> task_stack_; + MockAppCachePolicy policy_; scoped_ptr<AppCacheService> service_; scoped_ptr<MockStorageDelegate> delegate_; scoped_refptr<AppCacheGroup> group_; @@ -981,6 +1026,11 @@ TEST_F(AppCacheStorageImplTest, BasicFindMainResponseInWorkingSet) { &AppCacheStorageImplTest::BasicFindMainResponseInWorkingSet); } +TEST_F(AppCacheStorageImplTest, BlockFindMainResponseWithPolicyCheck) { + RunTestOnIOThread( + &AppCacheStorageImplTest::BlockFindMainResponseWithPolicyCheck); +} + TEST_F(AppCacheStorageImplTest, BasicFindMainFallbackResponseInDatabase) { RunTestOnIOThread( &AppCacheStorageImplTest::BasicFindMainFallbackResponseInDatabase); diff --git a/webkit/appcache/appcache_update_job.cc b/webkit/appcache/appcache_update_job.cc index dcf77b0..a022ed3 100644 --- a/webkit/appcache/appcache_update_job.cc +++ b/webkit/appcache/appcache_update_job.cc @@ -9,7 +9,9 @@ #include "base/string_util.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" +#include "net/base/net_errors.h" #include "webkit/appcache/appcache_group.h" +#include "webkit/appcache/appcache_policy.h" #include "webkit/appcache/appcache_response.h" namespace appcache { @@ -113,7 +115,10 @@ AppCacheUpdateJob::AppCacheUpdateJob(AppCacheService* service, ALLOW_THIS_IN_INITIALIZER_LIST(manifest_data_write_callback_( this, &AppCacheUpdateJob::OnManifestDataWriteComplete)), ALLOW_THIS_IN_INITIALIZER_LIST(manifest_data_read_callback_( - this, &AppCacheUpdateJob::OnManifestDataReadComplete)) { + this, &AppCacheUpdateJob::OnManifestDataReadComplete)), + ALLOW_THIS_IN_INITIALIZER_LIST(policy_callback_( + new net::CancelableCompletionCallback<AppCacheUpdateJob>( + this, &AppCacheUpdateJob::OnPolicyCheckComplete))) { DCHECK(group_); manifest_url_ = group_->manifest_url(); } @@ -130,6 +135,8 @@ AppCacheUpdateJob::~AppCacheUpdateJob() { if (group_) group_->SetUpdateStatus(AppCacheGroup::IDLE); + + policy_callback_->Cancel(); } void AppCacheUpdateJob::StartUpdate(AppCacheHost* host, @@ -191,7 +198,45 @@ void AppCacheUpdateJob::StartUpdate(AppCacheHost* host, is_new_pending_master_entry); } - FetchManifest(true); + if (update_type_ == CACHE_ATTEMPT) + CheckPolicy(); + else + FetchManifest(true); +} + +void AppCacheUpdateJob::CheckPolicy() { + int rv = net::OK; + policy_callback_->AddRef(); // Balanced in OnPolicyCheckComplete. + AppCachePolicy* policy = service_->appcache_policy(); + if (policy) { + rv = policy->CanCreateAppCache(manifest_url_, policy_callback_); + if (rv == net::ERR_IO_PENDING) + return; + } + OnPolicyCheckComplete(rv); +} + +void AppCacheUpdateJob::OnPolicyCheckComplete(int rv) { + policy_callback_->Release(); // Balanced in CheckPolicy. + if (rv == net::OK) { + FetchManifest(true); + return; + } + + MessageLoop::current()->PostTask(FROM_HERE, + method_factory_.NewRunnableMethod( + &AppCacheUpdateJob::HandleCacheFailure)); +} + +void AppCacheUpdateJob::HandleCacheFailure() { + // TODO(michaeln): For now this is only invoked from one point + // of failure. Overtime, attempt the migrate the various places + // where we can detect a failure condition to use this same + // method to enter the cache_failure state. + internal_state_ = CACHE_FAILURE; + CancelAllUrlFetches(); + CancelAllMasterEntryFetches(); + MaybeCompleteUpdate(); } void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) { @@ -1227,6 +1272,8 @@ void AppCacheUpdateJob::Cancel() { manifest_response_writer_.reset(); service_->storage()->CancelDelegateCallbacks(this); + + policy_callback_->Cancel(); } void AppCacheUpdateJob::ClearPendingMasterEntries() { diff --git a/webkit/appcache/appcache_update_job.h b/webkit/appcache/appcache_update_job.h index 2580ff8..c50f202 100644 --- a/webkit/appcache/appcache_update_job.h +++ b/webkit/appcache/appcache_update_job.h @@ -14,6 +14,7 @@ #include "base/ref_counted.h" #include "base/task.h" #include "googleurl/src/gurl.h" +#include "net/base/completion_callback.h" #include "net/url_request/url_request.h" #include "testing/gtest/include/gtest/gtest_prod.h" #include "webkit/appcache/appcache.h" @@ -99,6 +100,11 @@ class AppCacheUpdateJob : public URLRequest::Delegate, void OnCacheSelectionComplete(AppCacheHost* host) {} // N/A void OnDestructionImminent(AppCacheHost* host); + void CheckPolicy(); + void OnPolicyCheckComplete(int rv); + + void HandleCacheFailure(); + void FetchManifest(bool is_first_fetch); // Add extra HTTP headers to the request based on the response info and @@ -260,6 +266,9 @@ class AppCacheUpdateJob : public URLRequest::Delegate, net::CompletionCallbackImpl<AppCacheUpdateJob> manifest_data_write_callback_; net::CompletionCallbackImpl<AppCacheUpdateJob> manifest_data_read_callback_; + scoped_refptr<net::CancelableCompletionCallback<AppCacheUpdateJob> > + policy_callback_; + FRIEND_TEST(AppCacheGroupTest, QueueUpdate); DISALLOW_COPY_AND_ASSIGN(AppCacheUpdateJob); }; diff --git a/webkit/appcache/appcache_update_job_unittest.cc b/webkit/appcache/appcache_update_job_unittest.cc index d41e486..42efbff 100644 --- a/webkit/appcache/appcache_update_job_unittest.cc +++ b/webkit/appcache/appcache_update_job_unittest.cc @@ -7,10 +7,12 @@ #include "base/stl_util-inl.h" #include "base/thread.h" #include "base/waitable_event.h" +#include "net/base/net_errors.h" #include "net/url_request/url_request_test_job.h" #include "net/url_request/url_request_unittest.h" #include "webkit/appcache/appcache_group.h" #include "webkit/appcache/appcache_host.h" +#include "webkit/appcache/appcache_policy.h" #include "webkit/appcache/appcache_response.h" #include "webkit/appcache/appcache_update_job.h" #include "webkit/appcache/mock_appcache_service.h" @@ -276,6 +278,43 @@ bool HttpHeadersRequestTestJob::already_checked_ = false; class AppCacheUpdateJobTest : public testing::Test, public AppCacheGroup::UpdateObserver { public: + class MockAppCachePolicy : public AppCachePolicy { + public: + MockAppCachePolicy() + : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), + can_create_return_value_(net::OK), return_immediately_(true), + callback_(NULL) { + } + + virtual bool CanLoadAppCache(const GURL& manifest_url) { + return true; + } + + virtual int CanCreateAppCache(const GURL& manifest_url, + net::CompletionCallback* callback) { + requested_manifest_url_ = manifest_url; + callback_ = callback; + if (return_immediately_) + return can_create_return_value_; + + MessageLoop::current()->PostTask(FROM_HERE, + method_factory_.NewRunnableMethod( + &MockAppCachePolicy::CompleteCanCreateAppCache)); + return net::ERR_IO_PENDING; + } + + void CompleteCanCreateAppCache() { + callback_->Run(can_create_return_value_); + } + + ScopedRunnableMethodFactory<MockAppCachePolicy> method_factory_; + int can_create_return_value_; + bool return_immediately_; + GURL requested_manifest_url_; + net::CompletionCallback* callback_; + }; + + AppCacheUpdateJobTest() : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), do_checks_after_update_finished_(false), @@ -355,6 +394,52 @@ class AppCacheUpdateJobTest : public testing::Test, UpdateFinished(); } + void ImmediatelyBlockCacheAttemptTest() { + BlockCacheAttemptTest(true); + } + + void DelayedBlockCacheAttemptTest() { + BlockCacheAttemptTest(false); + } + + void BlockCacheAttemptTest(bool immediately) { + ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + + GURL manifest_url = GURL("http://failme"); + + // Setup to block the cache attempt immediately. + policy_.return_immediately_ = immediately; + policy_.can_create_return_value_ = net::ERR_ACCESS_DENIED; + + MakeService(); + group_ = new AppCacheGroup(service_.get(), manifest_url, + service_->storage()->NewGroupId()); + + AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); + group_->update_job_ = update; + + MockFrontend mock_frontend; + AppCacheHost host(1, &mock_frontend, service_.get()); + + update->StartUpdate(&host, GURL()); + EXPECT_EQ(manifest_url, policy_.requested_manifest_url_); + + // Verify state. + EXPECT_EQ(AppCacheUpdateJob::CACHE_ATTEMPT, update->update_type_); + EXPECT_EQ(AppCacheUpdateJob::FETCH_MANIFEST, update->internal_state_); + EXPECT_EQ(AppCacheGroup::CHECKING, group_->update_status()); + + // Verify notifications. + MockFrontend::RaisedEvents& events = mock_frontend.raised_events_; + size_t expected = 1; + EXPECT_EQ(expected, events.size()); + EXPECT_EQ(1U, events[0].first.size()); + EXPECT_EQ(host.host_id(), events[0].first[0]); + EXPECT_EQ(CHECKING_EVENT, events[0].second); + + WaitForUpdateToFinish(); + } + void StartUpgradeAttemptTest() { ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); @@ -727,9 +812,15 @@ class AppCacheUpdateJobTest : public testing::Test, void BasicCacheAttemptSuccessTest() { ASSERT_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type()); + GURL manifest_url = http_server_->TestServerPage("files/manifest1"); + + // We also test the async AppCachePolicy return path in this test case. + policy_.return_immediately_ = false; + policy_.can_create_return_value_ = net::OK; + MakeService(); group_ = new AppCacheGroup( - service_.get(), http_server_->TestServerPage("files/manifest1"), + service_.get(), manifest_url, service_->storage()->NewGroupId()); AppCacheUpdateJob* update = new AppCacheUpdateJob(service_.get(), group_); group_->update_job_ = update; @@ -737,7 +828,7 @@ class AppCacheUpdateJobTest : public testing::Test, MockFrontend* frontend = MakeMockFrontend(); AppCacheHost* host = MakeHost(1, frontend); update->StartUpdate(host, GURL()); - EXPECT_TRUE(update->manifest_url_request_ != NULL); + EXPECT_EQ(manifest_url, policy_.requested_manifest_url_);; // Set up checks for when update job finishes. do_checks_after_update_finished_ = true; @@ -2485,6 +2576,7 @@ class AppCacheUpdateJobTest : public testing::Test, void MakeService() { service_.reset(new MockAppCacheService()); service_->set_request_context(request_context_); + service_->set_appcache_policy(&policy_); } AppCache* MakeCacheForGroup(int64 cache_id, int64 manifest_response_id) { @@ -2777,6 +2869,7 @@ class AppCacheUpdateJobTest : public testing::Test, scoped_refptr<AppCacheGroup> group_; scoped_refptr<AppCache> protect_newest_cache_; scoped_ptr<base::WaitableEvent> event_; + MockAppCachePolicy policy_; scoped_ptr<AppCacheResponseWriter> response_writer_; scoped_ptr<net::CompletionCallbackImpl<AppCacheUpdateJobTest> > @@ -2873,6 +2966,14 @@ TEST_F(AppCacheUpdateJobTest, StartCacheAttempt) { RunTestOnIOThread(&AppCacheUpdateJobTest::StartCacheAttemptTest); } +TEST_F(AppCacheUpdateJobTest, ImmediatelyBlockCacheAttemptTest) { + RunTestOnIOThread(&AppCacheUpdateJobTest::ImmediatelyBlockCacheAttemptTest); +} + +TEST_F(AppCacheUpdateJobTest, DelayedBlockCacheAttemptTest) { + RunTestOnIOThread(&AppCacheUpdateJobTest::DelayedBlockCacheAttemptTest); +} + TEST_F(AppCacheUpdateJobTest, StartUpgradeAttempt) { RunTestOnIOThread(&AppCacheUpdateJobTest::StartUpgradeAttemptTest); } diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp index 4784106..483c1a6 100644 --- a/webkit/webkit.gyp +++ b/webkit/webkit.gyp @@ -145,6 +145,7 @@ 'appcache/appcache_interceptor.h', 'appcache/appcache_interfaces.cc', 'appcache/appcache_interfaces.h', + 'appcache/appcache_policy.h', 'appcache/appcache_request_handler.cc', 'appcache/appcache_request_handler.h', 'appcache/appcache_response.cc', |