blob: fc13cb4ac620ddb7339149886e103c215e2ed695 [file] [log] [blame]
// Copyright 2014 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.
#include "content/browser/appcache/appcache_host.h"
#include <stdint.h>
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/test/scoped_task_environment.h"
#include "content/browser/appcache/appcache.h"
#include "content/browser/appcache/appcache_backend_impl.h"
#include "content/browser/appcache/appcache_group.h"
#include "content/browser/appcache/appcache_request_handler.h"
#include "content/browser/appcache/mock_appcache_policy.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_renderer_host.h"
#include "content/test/test_web_contents.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "net/url_request/url_request.h"
#include "storage/browser/quota/quota_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "url/origin.h"
namespace content {
namespace {
constexpr int kHostIdForTest = 123;
} // namespace
class AppCacheHostTest : public testing::Test {
public:
AppCacheHostTest()
: web_contents_(TestWebContents::Create(&browser_context_, nullptr)),
kProcessIdForTest(web_contents_->GetMainFrame()->GetProcess()->GetID()),
kRenderFrameIdForTest(web_contents_->GetMainFrame()->GetRoutingID()),
mock_frontend_(web_contents_.get()) {
get_status_callback_ = base::BindRepeating(
&AppCacheHostTest::GetStatusCallback, base::Unretained(this));
AppCacheRequestHandler::SetRunningInTests(true);
}
~AppCacheHostTest() override {
AppCacheRequestHandler::SetRunningInTests(false);
}
class MockFrontend : public blink::mojom::AppCacheFrontend,
public WebContentsObserver {
public:
MockFrontend(WebContents* web_contents)
: WebContentsObserver(web_contents),
last_cache_id_(-222),
last_status_(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE),
last_event_id_(
blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT),
content_blocked_(false) {}
void CacheSelected(blink::mojom::AppCacheInfoPtr info) override {
last_cache_id_ = info->cache_id;
last_status_ = info->status;
}
void EventRaised(blink::mojom::AppCacheEventID event_id) override {
last_event_id_ = event_id;
}
void ErrorEventRaised(
blink::mojom::AppCacheErrorDetailsPtr details) override {
last_event_id_ = blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT;
}
void ProgressEventRaised(const GURL& url,
int32_t num_total,
int32_t num_complete) override {
last_event_id_ = blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT;
}
void LogMessage(blink::mojom::ConsoleMessageLevel log_level,
const std::string& message) override {}
void SetSubresourceFactory(
network::mojom::URLLoaderFactoryPtr url_loader_factory) override {}
// WebContentsObserver:
void AppCacheAccessed(const GURL& manifest_url,
bool blocked_by_policy) override {
appcache_accessed_ = true;
if (blocked_by_policy)
content_blocked_ = true;
}
int64_t last_cache_id_;
blink::mojom::AppCacheStatus last_status_;
blink::mojom::AppCacheEventID last_event_id_;
bool content_blocked_;
bool appcache_accessed_ = false;
};
class MockQuotaManagerProxy : public storage::QuotaManagerProxy {
public:
MockQuotaManagerProxy() : QuotaManagerProxy(nullptr, nullptr) {}
// Not needed for our tests.
void RegisterClient(storage::QuotaClient* client) override {}
void NotifyStorageAccessed(storage::QuotaClient::ID client_id,
const url::Origin& origin,
blink::mojom::StorageType type) override {}
void NotifyStorageModified(storage::QuotaClient::ID client_id,
const url::Origin& origin,
blink::mojom::StorageType type,
int64_t delta) override {}
void SetUsageCacheEnabled(storage::QuotaClient::ID client_id,
const url::Origin& origin,
blink::mojom::StorageType type,
bool enabled) override {}
void GetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
const url::Origin& origin,
blink::mojom::StorageType type,
UsageAndQuotaCallback callback) override {}
void NotifyOriginInUse(const url::Origin& origin) override {
inuse_[origin] += 1;
}
void NotifyOriginNoLongerInUse(const url::Origin& origin) override {
inuse_[origin] -= 1;
}
int GetInUseCount(const url::Origin& origin) { return inuse_[origin]; }
void reset() { inuse_.clear(); }
// Map from origin to count of inuse notifications.
std::map<url::Origin, int> inuse_;
protected:
~MockQuotaManagerProxy() override {}
};
void GetStatusCallback(blink::mojom::AppCacheStatus status) {
last_status_result_ = status;
}
void StartUpdateCallback(bool result) { last_start_result_ = result; }
void SwapCacheCallback(bool result) { last_swap_result_ = result; }
TestBrowserThreadBundle scoped_task_environment_;
RenderViewHostTestEnabler rvh_enabler_;
TestBrowserContext browser_context_;
std::unique_ptr<TestWebContents> web_contents_;
const int kProcessIdForTest;
const int kRenderFrameIdForTest;
// Mock classes for the 'host' to work with
MockAppCacheService service_;
MockFrontend mock_frontend_;
// Mock callbacks we expect to receive from the 'host'
blink::mojom::AppCacheHost::GetStatusCallback get_status_callback_;
blink::mojom::AppCacheStatus last_status_result_;
bool last_swap_result_;
bool last_start_result_;
};
TEST_F(AppCacheHostTest, Basic) {
// Construct a host and test what state it appears to be in.
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
EXPECT_EQ(kHostIdForTest, host.host_id());
EXPECT_EQ(kProcessIdForTest, host.process_id());
EXPECT_EQ(&service_, host.service());
EXPECT_EQ(nullptr, host.associated_cache());
EXPECT_FALSE(host.is_selection_pending());
// See that the callbacks are delivered immediately
// and respond as if there is no cache selected.
last_status_result_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
host.GetStatus(std::move(get_status_callback_));
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
last_status_result_);
last_start_result_ = true;
host.StartUpdate(base::BindOnce(&AppCacheHostTest::StartUpdateCallback,
base::Unretained(this)));
EXPECT_FALSE(last_start_result_);
last_swap_result_ = true;
host.SwapCache(base::BindOnce(&AppCacheHostTest::SwapCacheCallback,
base::Unretained(this)));
EXPECT_FALSE(last_swap_result_);
}
TEST_F(AppCacheHostTest, SelectNoCache) {
scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy =
base::MakeRefCounted<MockQuotaManagerProxy>();
service_.set_quota_manager_proxy(mock_quota_proxy.get());
// Reset our mock frontend
mock_frontend_.last_cache_id_ = -333;
mock_frontend_.last_status_ =
blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
const url::Origin kOrigin(url::Origin::Create(kDocAndOriginUrl));
{
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
host.SelectCache(kDocAndOriginUrl, blink::mojom::kAppCacheNoCacheId,
GURL());
EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kOrigin));
// We should have received an OnCacheSelected msg
EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
mock_frontend_.last_status_);
// Otherwise, see that it respond as if there is no cache selected.
EXPECT_EQ(kHostIdForTest, host.host_id());
EXPECT_EQ(&service_, host.service());
EXPECT_EQ(nullptr, host.associated_cache());
EXPECT_FALSE(host.is_selection_pending());
EXPECT_TRUE(host.preferred_manifest_url().is_empty());
}
EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kOrigin));
service_.set_quota_manager_proxy(nullptr);
}
TEST_F(AppCacheHostTest, ForeignEntry) {
// Reset our mock frontend
mock_frontend_.last_cache_id_ = -333;
mock_frontend_.last_status_ =
blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
// Precondition, a cache with an entry that is not marked as foreign.
const int kCacheId = 22;
const GURL kDocumentURL("http://origin/document");
scoped_refptr<AppCache> cache = new AppCache(service_.storage(), kCacheId);
cache->AddEntry(kDocumentURL, AppCacheEntry(AppCacheEntry::EXPLICIT));
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
host.MarkAsForeignEntry(kDocumentURL, kCacheId);
// We should have received an OnCacheSelected msg for kAppCacheNoCacheId.
EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
mock_frontend_.last_status_);
// See that it respond as if there is no cache selected.
EXPECT_EQ(kHostIdForTest, host.host_id());
EXPECT_EQ(&service_, host.service());
EXPECT_EQ(nullptr, host.associated_cache());
EXPECT_FALSE(host.is_selection_pending());
// See that the entry was marked as foreign.
EXPECT_TRUE(cache->GetEntry(kDocumentURL)->IsForeign());
}
TEST_F(AppCacheHostTest, ForeignFallbackEntry) {
// Reset our mock frontend
mock_frontend_.last_cache_id_ = -333;
mock_frontend_.last_status_ =
blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
// Precondition, a cache with a fallback entry that is not marked as foreign.
const int kCacheId = 22;
const GURL kFallbackURL("http://origin/fallback_resource");
scoped_refptr<AppCache> cache =
base::MakeRefCounted<AppCache>(service_.storage(), kCacheId);
cache->AddEntry(kFallbackURL, AppCacheEntry(AppCacheEntry::FALLBACK));
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
host.NotifyMainResourceIsNamespaceEntry(kFallbackURL);
host.MarkAsForeignEntry(GURL("http://origin/missing_document"), kCacheId);
// We should have received an OnCacheSelected msg for kAppCacheNoCacheId.
EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
mock_frontend_.last_status_);
// See that the fallback entry was marked as foreign.
EXPECT_TRUE(cache->GetEntry(kFallbackURL)->IsForeign());
}
TEST_F(AppCacheHostTest, FailedCacheLoad) {
// Reset our mock frontend
mock_frontend_.last_cache_id_ = -333;
mock_frontend_.last_status_ =
blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
EXPECT_FALSE(host.is_selection_pending());
const int kMockCacheId = 333;
// Put it in a state where we're waiting on a cache
// load prior to finishing cache selection.
host.pending_selected_cache_id_ = kMockCacheId;
EXPECT_TRUE(host.is_selection_pending());
// The callback should not occur until we finish cache selection.
last_status_result_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
host.GetStatus(std::move(get_status_callback_));
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE,
last_status_result_);
// Satisfy the load with NULL, a failure.
host.OnCacheLoaded(nullptr, kMockCacheId);
// Cache selection should have finished
EXPECT_FALSE(host.is_selection_pending());
EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
mock_frontend_.last_status_);
// Callback should have fired upon completing the cache load too.
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
last_status_result_);
}
TEST_F(AppCacheHostTest, FailedGroupLoad) {
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
const GURL kMockManifestUrl("http://foo.bar/baz");
// Put it in a state where we're waiting on a cache
// load prior to finishing cache selection.
host.pending_selected_manifest_url_ = kMockManifestUrl;
EXPECT_TRUE(host.is_selection_pending());
// The callback should not occur until we finish cache selection.
last_status_result_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
host.GetStatus(std::move(get_status_callback_));
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE,
last_status_result_);
// Satisfy the load will NULL, a failure.
host.OnGroupLoaded(nullptr, kMockManifestUrl);
// Cache selection should have finished
EXPECT_FALSE(host.is_selection_pending());
EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
mock_frontend_.last_status_);
// Callback should have fired upon completing the group load.
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
last_status_result_);
}
TEST_F(AppCacheHostTest, SetSwappableCache) {
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
host.SetSwappableCache(nullptr);
EXPECT_FALSE(host.swappable_cache_.get());
const GURL kGroup1ManifestUrl("http://bar.com");
scoped_refptr<AppCacheGroup> group1 = base::MakeRefCounted<AppCacheGroup>(
service_.storage(), kGroup1ManifestUrl, service_.storage()->NewGroupId());
host.SetSwappableCache(group1.get());
EXPECT_FALSE(host.swappable_cache_.get());
scoped_refptr<AppCache> cache1 =
base::MakeRefCounted<AppCache>(service_.storage(), 111);
cache1->set_complete(true);
group1->AddCache(cache1.get());
host.SetSwappableCache(group1.get());
EXPECT_EQ(cache1, host.swappable_cache_.get());
mock_frontend_.last_cache_id_ =
-222; // to verify we received OnCacheSelected
host.AssociateCompleteCache(cache1.get());
EXPECT_FALSE(host.swappable_cache_.get()); // was same as associated cache
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_IDLE,
host.GetStatusSync());
// verify OnCacheSelected was called
EXPECT_EQ(cache1->cache_id(), mock_frontend_.last_cache_id_);
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_IDLE,
mock_frontend_.last_status_);
scoped_refptr<AppCache> cache2 =
base::MakeRefCounted<AppCache>(service_.storage(), 222);
cache2->set_complete(true);
group1->AddCache(cache2.get());
EXPECT_EQ(cache2.get(), host.swappable_cache_.get()); // updated to newest
const GURL kGroup2ManifestUrl("http://foo.com/");
scoped_refptr<AppCacheGroup> group2 = base::MakeRefCounted<AppCacheGroup>(
service_.storage(), kGroup2ManifestUrl, service_.storage()->NewGroupId());
scoped_refptr<AppCache> cache3 =
base::MakeRefCounted<AppCache>(service_.storage(), 333);
cache3->set_complete(true);
group2->AddCache(cache3.get());
scoped_refptr<AppCache> cache4 =
base::MakeRefCounted<AppCache>(service_.storage(), 444);
cache4->set_complete(true);
group2->AddCache(cache4.get());
EXPECT_EQ(cache2.get(), host.swappable_cache_.get()); // unchanged
cache1.reset();
cache2.reset();
host.AssociateCompleteCache(cache3.get());
EXPECT_EQ(cache4.get(),
host.swappable_cache_.get()); // newest cache in group2
EXPECT_FALSE(group1->HasCache()); // both caches in group1 have refcount 0
cache3.reset();
cache4.reset();
host.AssociateNoCache(kGroup1ManifestUrl);
EXPECT_FALSE(host.swappable_cache_.get());
EXPECT_FALSE(group2->HasCache()); // both caches in group2 have refcount 0
// Host adds reference to newest cache when an update is complete.
scoped_refptr<AppCache> cache5 =
base::MakeRefCounted<AppCache>(service_.storage(), 555);
cache5->set_complete(true);
group2->AddCache(cache5.get());
host.group_being_updated_ = group2;
host.OnUpdateComplete(group2.get());
EXPECT_FALSE(host.group_being_updated_.get());
EXPECT_EQ(cache5.get(), host.swappable_cache_.get());
group2->RemoveCache(cache5.get());
EXPECT_FALSE(group2->HasCache());
host.group_being_updated_ = group2;
host.OnUpdateComplete(group2.get());
EXPECT_FALSE(host.group_being_updated_.get());
EXPECT_FALSE(host.swappable_cache_.get()); // group2 had no newest cache
}
TEST_F(AppCacheHostTest, SelectCacheAllowed) {
scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy =
base::MakeRefCounted<MockQuotaManagerProxy>();
MockAppCachePolicy mock_appcache_policy;
mock_appcache_policy.can_create_return_value_ = true;
service_.set_quota_manager_proxy(mock_quota_proxy.get());
service_.set_appcache_policy(&mock_appcache_policy);
// Reset our mock frontend
mock_frontend_.last_cache_id_ = -333;
mock_frontend_.last_status_ =
blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
mock_frontend_.last_event_id_ =
blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT;
mock_frontend_.content_blocked_ = false;
mock_frontend_.appcache_accessed_ = false;
const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
const url::Origin kOrigin(url::Origin::Create(kDocAndOriginUrl));
const GURL kManifestUrl(GURL("http://whatever/cache.manifest"));
{
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
host.SetFirstPartyUrlForTesting(kDocAndOriginUrl);
host.SelectCache(kDocAndOriginUrl, blink::mojom::kAppCacheNoCacheId,
kManifestUrl);
EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kOrigin));
// MockAppCacheService::LoadOrCreateGroup is asynchronous, so we shouldn't
// have received an OnCacheSelected msg yet.
EXPECT_EQ(-333, mock_frontend_.last_cache_id_);
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE,
mock_frontend_.last_status_);
// No error events either
EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT,
mock_frontend_.last_event_id_);
EXPECT_FALSE(mock_frontend_.content_blocked_);
EXPECT_TRUE(host.is_selection_pending());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(mock_frontend_.content_blocked_);
EXPECT_TRUE(mock_frontend_.appcache_accessed_);
}
EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kOrigin));
service_.set_quota_manager_proxy(nullptr);
}
TEST_F(AppCacheHostTest, SelectCacheBlocked) {
scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy =
base::MakeRefCounted<MockQuotaManagerProxy>();
MockAppCachePolicy mock_appcache_policy;
mock_appcache_policy.can_create_return_value_ = false;
service_.set_quota_manager_proxy(mock_quota_proxy.get());
service_.set_appcache_policy(&mock_appcache_policy);
// Reset our mock frontend
mock_frontend_.last_cache_id_ = -333;
mock_frontend_.last_status_ =
blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
mock_frontend_.last_event_id_ =
blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT;
mock_frontend_.content_blocked_ = false;
mock_frontend_.appcache_accessed_ = false;
const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
const url::Origin kOrigin(url::Origin::Create(kDocAndOriginUrl));
const GURL kManifestUrl(GURL("http://whatever/cache.manifest"));
{
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
host.SetFirstPartyUrlForTesting(kDocAndOriginUrl);
host.SelectCache(kDocAndOriginUrl, blink::mojom::kAppCacheNoCacheId,
kManifestUrl);
EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kOrigin));
// We should have received an OnCacheSelected msg
EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
mock_frontend_.last_status_);
// Also, an error event was raised
EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT,
mock_frontend_.last_event_id_);
// Otherwise, see that it respond as if there is no cache selected.
EXPECT_EQ(kHostIdForTest, host.host_id());
EXPECT_EQ(&service_, host.service());
EXPECT_EQ(nullptr, host.associated_cache());
EXPECT_FALSE(host.is_selection_pending());
EXPECT_TRUE(host.preferred_manifest_url().is_empty());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(mock_frontend_.content_blocked_);
EXPECT_TRUE(mock_frontend_.appcache_accessed_);
}
EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kOrigin));
service_.set_quota_manager_proxy(nullptr);
}
TEST_F(AppCacheHostTest, SelectCacheTwice) {
const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
blink::mojom::AppCacheHostPtr host_ptr;
host.BindRequest(mojo::MakeRequest(&host_ptr));
{
mojo::test::BadMessageObserver bad_message_observer;
host_ptr->SelectCache(kDocAndOriginUrl, blink::mojom::kAppCacheNoCacheId,
GURL());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(bad_message_observer.got_bad_message());
}
// Select methods should bail if cache has already been selected.
{
mojo::test::BadMessageObserver bad_message_observer;
host_ptr->SelectCache(kDocAndOriginUrl, blink::mojom::kAppCacheNoCacheId,
GURL());
EXPECT_EQ("ACH_SELECT_CACHE", bad_message_observer.WaitForBadMessage());
}
{
mojo::test::BadMessageObserver bad_message_observer;
host_ptr->SelectCacheForSharedWorker(blink::mojom::kAppCacheNoCacheId);
EXPECT_EQ("ACH_SELECT_CACHE_FOR_SHARED_WORKER",
bad_message_observer.WaitForBadMessage());
}
{
mojo::test::BadMessageObserver bad_message_observer;
host_ptr->MarkAsForeignEntry(kDocAndOriginUrl,
blink::mojom::kAppCacheNoCacheId);
EXPECT_EQ("ACH_MARK_AS_FOREIGN_ENTRY",
bad_message_observer.WaitForBadMessage());
}
}
TEST_F(AppCacheHostTest, SelectCacheInvalidCacheId) {
const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
// A cache that the document wasn't actually loaded from. Trying to select it
// should cause a BadMessage.
const int kCacheId = 22;
const GURL kDocumentURL("http://origin/document");
scoped_refptr<AppCache> cache = new AppCache(service_.storage(), kCacheId);
AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
nullptr, &service_);
host.set_frontend_for_testing(&mock_frontend_);
blink::mojom::AppCacheHostPtr host_ptr;
host.BindRequest(mojo::MakeRequest(&host_ptr));
{
mojo::test::BadMessageObserver bad_message_observer;
host_ptr->SelectCache(kDocAndOriginUrl, kCacheId, GURL());
EXPECT_EQ("ACH_SELECT_CACHE_ID_NOT_OWNED",
bad_message_observer.WaitForBadMessage());
}
}
} // namespace content