blob: 239c78b44b3e1709454bf60e862edf19c5bf7825 [file] [log] [blame]
// Copyright 2016 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 "chrome/browser/offline_pages/prerender_adapter.h"
#include "base/sys_info.h"
#include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/prerender/prerender_test_utils.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
using prerender::FinalStatus;
using prerender::Origin;
using prerender::PrerenderContents;
using prerender::PrerenderManager;
using prerender::PrerenderManagerFactory;
namespace offline_pages {
namespace {
class StubPrerenderContents : public PrerenderContents {
public:
StubPrerenderContents(PrerenderManager* prerender_manager,
const GURL& url,
Origin origin);
~StubPrerenderContents() override;
void StartPrerendering(
const gfx::Rect& bounds,
content::SessionStorageNamespace* session_storage_namespace) override;
void ReportStartEvent() { NotifyPrerenderStart(); }
void ReportOnLoadEvent() { NotifyPrerenderStopLoading(); }
void ReportDomContentEvent() { NotifyPrerenderDomContentLoaded(); }
void StopWithStatus(FinalStatus final_status) { Destroy(final_status); }
};
StubPrerenderContents::StubPrerenderContents(
PrerenderManager* prerender_manager,
const GURL& url,
Origin origin)
: PrerenderContents(prerender_manager,
NULL,
url,
content::Referrer(),
origin) {}
StubPrerenderContents::~StubPrerenderContents() {}
void StubPrerenderContents::StartPrerendering(
const gfx::Rect& bounds,
content::SessionStorageNamespace* session_storage_namespace) {
prerendering_has_started_ = true;
}
class StubPrerenderContentsFactory : public PrerenderContents::Factory {
public:
StubPrerenderContentsFactory()
: create_prerender_contents_called_(false),
last_prerender_contents_(nullptr) {}
~StubPrerenderContentsFactory() override {}
PrerenderContents* CreatePrerenderContents(
PrerenderManager* prerender_manager,
Profile* profile,
const GURL& url,
const content::Referrer& referrer,
Origin origin) override;
bool create_prerender_contents_called() const {
return create_prerender_contents_called_;
}
StubPrerenderContents* last_prerender_contents() const {
return last_prerender_contents_;
}
private:
bool create_prerender_contents_called_;
StubPrerenderContents* last_prerender_contents_;
DISALLOW_COPY_AND_ASSIGN(StubPrerenderContentsFactory);
};
PrerenderContents* StubPrerenderContentsFactory::CreatePrerenderContents(
PrerenderManager* prerender_manager,
Profile* profile,
const GURL& url,
const content::Referrer& referrer,
Origin origin) {
create_prerender_contents_called_ = true;
last_prerender_contents_ = new StubPrerenderContents(
prerender_manager, url, prerender::ORIGIN_OFFLINE);
return last_prerender_contents_;
}
} // namespace
// Test class.
class PrerenderAdapterTest : public testing::Test,
public PrerenderAdapter::Observer {
public:
PrerenderAdapterTest();
~PrerenderAdapterTest() override;
// PrerenderAdapter::Observer implementation:
void OnPrerenderStopLoading() override;
void OnPrerenderDomContentLoaded() override;
void OnPrerenderStop() override;
void OnPrerenderNetworkBytesChanged(int64_t bytes) override;
void SetUp() override;
void TearDown() override;
// Returns the PrerenderLoader to test.
PrerenderAdapter* adapter() const { return adapter_.get(); }
StubPrerenderContentsFactory* prerender_contents_factory() {
return prerender_contents_factory_;
}
Profile* profile() { return &profile_; }
PrerenderManager* prerender_manager() { return prerender_manager_; }
bool observer_stop_loading_called() const {
return observer_stop_loading_called_;
}
bool observer_dom_content_loaded_called() const {
return observer_dom_content_loaded_called_;
}
bool observer_stop_called() const { return observer_stop_called_; }
int64_t observer_network_bytes_changed() const {
return observer_network_bytes_changed_;
}
private:
using RestorePrerenderMode = prerender::test_utils::RestorePrerenderMode;
content::TestBrowserThreadBundle thread_bundle_;
TestingProfile profile_;
std::unique_ptr<PrerenderAdapter> adapter_;
StubPrerenderContentsFactory* prerender_contents_factory_;
PrerenderManager* prerender_manager_;
bool observer_stop_loading_called_;
bool observer_dom_content_loaded_called_;
bool observer_stop_called_;
int64_t observer_network_bytes_changed_;
std::unique_ptr<RestorePrerenderMode> restore_prerender_mode_;
DISALLOW_COPY_AND_ASSIGN(PrerenderAdapterTest);
};
PrerenderAdapterTest::PrerenderAdapterTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
prerender_manager_(nullptr),
observer_stop_loading_called_(false),
observer_dom_content_loaded_called_(false),
observer_stop_called_(false),
observer_network_bytes_changed_(0) {}
PrerenderAdapterTest::~PrerenderAdapterTest() {
if (prerender_manager_)
prerender_manager_->Shutdown();
}
void PrerenderAdapterTest::OnPrerenderStopLoading() {
observer_stop_loading_called_ = true;
}
void PrerenderAdapterTest::OnPrerenderDomContentLoaded() {
observer_dom_content_loaded_called_ = true;
}
void PrerenderAdapterTest::OnPrerenderStop() {
observer_stop_called_ = true;
}
void PrerenderAdapterTest::OnPrerenderNetworkBytesChanged(int64_t bytes) {
observer_network_bytes_changed_ = bytes;
}
void PrerenderAdapterTest::SetUp() {
if (base::SysInfo::IsLowEndDevice())
return;
// Prerender mode is stored in a few static variables. Remember the default
// mode to restore it later in TearDown() to avoid affecting other tests.
restore_prerender_mode_ = base::MakeUnique<RestorePrerenderMode>();
PrerenderManager::SetMode(PrerenderManager::PRERENDER_MODE_ENABLED);
adapter_.reset(new PrerenderAdapter(this));
prerender_contents_factory_ = new StubPrerenderContentsFactory();
prerender_manager_ = PrerenderManagerFactory::GetForBrowserContext(profile());
if (prerender_manager_) {
prerender_manager_->SetPrerenderContentsFactoryForTest(
prerender_contents_factory_);
}
observer_stop_loading_called_ = false;
observer_dom_content_loaded_called_ = false;
observer_stop_called_ = false;
ASSERT_TRUE(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
}
void PrerenderAdapterTest::TearDown() {
restore_prerender_mode_.reset();
}
TEST_F(PrerenderAdapterTest, StartPrerenderFailsForUnsupportedScheme) {
// Skip test on low end device until supported.
if (base::SysInfo::IsLowEndDevice())
return;
std::unique_ptr<content::WebContents> session_contents(
content::WebContents::Create(
content::WebContents::CreateParams(profile())));
content::SessionStorageNamespace* sessionStorageNamespace =
session_contents->GetController().GetDefaultSessionStorageNamespace();
gfx::Size renderWindowSize = session_contents->GetContainerBounds().size();
GURL url("file://file.test");
EXPECT_FALSE(adapter()->StartPrerender(
profile(), url, sessionStorageNamespace, renderWindowSize));
EXPECT_TRUE(prerender_contents_factory()->create_prerender_contents_called());
EXPECT_FALSE(adapter()->IsActive());
}
TEST_F(PrerenderAdapterTest, StartPrerenderSucceeds) {
// Skip test on low end device until supported.
if (base::SysInfo::IsLowEndDevice())
return;
std::unique_ptr<content::WebContents> session_contents(
content::WebContents::Create(
content::WebContents::CreateParams(profile())));
content::SessionStorageNamespace* sessionStorageNamespace =
session_contents->GetController().GetDefaultSessionStorageNamespace();
gfx::Size renderWindowSize = session_contents->GetContainerBounds().size();
GURL url("https://url.test");
EXPECT_TRUE(adapter()->StartPrerender(profile(), url, sessionStorageNamespace,
renderWindowSize));
EXPECT_TRUE(prerender_contents_factory()->create_prerender_contents_called());
EXPECT_NE(nullptr, prerender_contents_factory()->last_prerender_contents());
EXPECT_TRUE(adapter()->IsActive());
EXPECT_FALSE(observer_stop_loading_called());
EXPECT_FALSE(observer_dom_content_loaded_called());
EXPECT_FALSE(observer_stop_called());
// Exercise observer event call paths.
prerender_contents_factory()
->last_prerender_contents()
->ReportDomContentEvent();
EXPECT_TRUE(observer_dom_content_loaded_called());
// Expect byte count reported to Observer.
prerender_contents_factory()->last_prerender_contents()->AddNetworkBytes(153);
EXPECT_EQ(153LL, observer_network_bytes_changed());
prerender_contents_factory()->last_prerender_contents()->ReportOnLoadEvent();
EXPECT_TRUE(observer_stop_loading_called());
prerender_contents_factory()->last_prerender_contents()->StopWithStatus(
FinalStatus::FINAL_STATUS_CANCELLED);
EXPECT_TRUE(observer_stop_called());
EXPECT_EQ(FinalStatus::FINAL_STATUS_CANCELLED, adapter()->GetFinalStatus());
// Exercise access methods even though no interesting values set beneath.
EXPECT_EQ(nullptr, adapter()->GetWebContents());
adapter()->DestroyActive();
EXPECT_FALSE(adapter()->IsActive());
}
} // namespace offline_pages