| Index: chrome/browser/android/offline_pages/prerendering_loader.cc
|
| diff --git a/chrome/browser/android/offline_pages/prerendering_loader.cc b/chrome/browser/android/offline_pages/prerendering_loader.cc
|
| index c29e1fd56fcd486c3fd34a38b2a6a02cb17bd696..bf194568c0820bbaf60bad25d87ae6d3abc4387a 100644
|
| --- a/chrome/browser/android/offline_pages/prerendering_loader.cc
|
| +++ b/chrome/browser/android/offline_pages/prerendering_loader.cc
|
| @@ -4,26 +4,203 @@
|
|
|
| #include "chrome/browser/android/offline_pages/prerendering_loader.h"
|
|
|
| +#include "base/location.h"
|
| +#include "chrome/browser/prerender/prerender_manager.h"
|
| +#include "chrome/browser/prerender/prerender_manager_factory.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "content/public/browser/browser_context.h"
|
| #include "content/public/browser/web_contents.h"
|
| #include "ui/gfx/geometry/size.h"
|
|
|
| namespace offline_pages {
|
|
|
| -PrerenderingLoader::PrerenderingLoader(PrerenderManager* prerender_manager) {}
|
| +using PrerenderingAdapter = PrerenderingLoader::PrerenderingAdapter;
|
|
|
| -PrerenderingLoader::~PrerenderingLoader() {}
|
| +PrerenderingLoader::PrerenderingLoader(content::BrowserContext* browser_context)
|
| + : browser_context_(browser_context) {
|
| + adapter_.reset(new PrerenderingAdapter());
|
| +}
|
| +
|
| +PrerenderingLoader::~PrerenderingLoader() {
|
| + CancelPrerender();
|
| +}
|
| +
|
| +bool PrerenderingLoader::LoadPage(const GURL& url,
|
| + const LoadPageCallback& callback) {
|
| + if (state_ != State::kIdle) {
|
| + LOG(WARNING) << "Existing request pending";
|
| + return false;
|
| + }
|
| + if (!CanPrerender())
|
| + return false;
|
| +
|
| + adapter_->AddPrerenderForOffline(browser_context_, url,
|
| + GetSessionStorageNamespace(), GetSize());
|
| + if (!adapter_->IsActive())
|
| + return false;
|
| +
|
| + callback_ = callback;
|
| + adapter_->SetObserver(this);
|
| + state_ = State::kLoading;
|
| + return true;
|
| +}
|
| +
|
| +void PrerenderingLoader::StopLoading() {
|
| + CancelPrerender();
|
| + state_ = State::kIdle;
|
| +}
|
| +
|
| +bool PrerenderingLoader::CanPrerender() {
|
| + // First check if prerendering is enabled.
|
| + return adapter_->CanPrerender();
|
| +}
|
| +
|
| +bool PrerenderingLoader::IsIdle() {
|
| + return state_ == State::kIdle;
|
| +}
|
| +
|
| +content::SessionStorageNamespace*
|
| +PrerenderingLoader::GetSessionStorageNamespace() {
|
| + // TODO(dougarnett): Create separate namespace from default (to better
|
| + // isolate background loading artifacts from direct user browsing).
|
| + return content::WebContents::Create(
|
| + content::WebContents::CreateParams(browser_context_))
|
| + ->GetController()
|
| + .GetDefaultSessionStorageNamespace();
|
| +}
|
| +
|
| +const gfx::Size PrerenderingLoader::GetSize() {
|
| + return content::WebContents::Create(
|
| + content::WebContents::CreateParams(browser_context_))
|
| + ->GetContainerBounds()
|
| + .size();
|
| +}
|
| +
|
| +void PrerenderingLoader::ReportLoaded() {
|
| + if (state_ == State::kLoading) {
|
| + content::WebContents* contents = adapter_->GetPrerenderContents();
|
| + if (contents) {
|
| + state_ = State::kLoaded;
|
| + callback_.Run(true, contents);
|
| + } else {
|
| + ReportLoadFailed();
|
| + }
|
| + }
|
| +}
|
| +
|
| +void PrerenderingLoader::ReportLoadFailed() {
|
| + if (state_ != State::kLoaded && state_ != State::kIdle) {
|
| + if (adapter_->IsActive())
|
| + DVLOG(1) << "Load failed: " << adapter_->GetFinalStatus();
|
| + state_ = State::kIdle;
|
| + callback_.Run(false, nullptr);
|
| + }
|
| +}
|
| +
|
| +void PrerenderingLoader::CancelPrerender() {
|
| + if (adapter_->IsPrerendering())
|
| + adapter_->OnCancel();
|
| + adapter_->DestroyActive();
|
| +}
|
| +
|
| +void PrerenderingLoader::OnPrerenderStart(prerender::PrerenderHandle* handle) {
|
| + if (adapter_->IsActive(handle) && state_ == State::kPending) {
|
| + state_ = State::kLoading;
|
| + }
|
| +}
|
| +
|
| +void PrerenderingLoader::OnPrerenderStopLoading(
|
| + prerender::PrerenderHandle* handle) {
|
| + if (adapter_->IsActive(handle)) {
|
| + // TODO(dougarnett): Implement/integrate to delay policy here.
|
| + ReportLoaded();
|
| + }
|
| +}
|
| +
|
| +void PrerenderingLoader::OnPrerenderDomContentLoaded(
|
| + prerender::PrerenderHandle* handle) {
|
| + if (adapter_->IsActive(handle)) {
|
| + // TODO(dougarnett): Implement/integrate to delay policy here.
|
| + ReportLoaded();
|
| + }
|
| +}
|
| +
|
| +void PrerenderingLoader::OnPrerenderStop(prerender::PrerenderHandle* handle) {
|
| + if (adapter_->IsActive(handle)) {
|
| + ReportLoadFailed();
|
| + }
|
| +}
|
| +
|
| +void PrerenderingLoader::OnPrerenderCreatedMatchCompleteReplacement(
|
| + prerender::PrerenderHandle* handle) {
|
| + LOG(WARNING) << "Offlining prerender should never do replacement";
|
| +}
|
|
|
| -bool PrerenderingLoader::LoadPage(
|
| +void PrerenderingLoader::SetAdapterForTesting(
|
| + PrerenderingAdapter* prerendering_adapter) {
|
| + adapter_.reset(prerendering_adapter);
|
| +}
|
| +
|
| +// Adapter implementation to prerender stack:
|
| +
|
| +bool PrerenderingAdapter::CanPrerender() const {
|
| + return prerender::PrerenderManager::ActuallyPrerendering();
|
| +}
|
| +
|
| +bool PrerenderingAdapter::AddPrerenderForOffline(
|
| + content::BrowserContext* browser_context,
|
| const GURL& url,
|
| content::SessionStorageNamespace* session_storage_namespace,
|
| - const gfx::Size& size,
|
| - const LoadPageCallback& callback) {
|
| - // TODO(dougarnett): implement.
|
| - return false;
|
| + const gfx::Size& size) {
|
| + DCHECK(!IsActive());
|
| + Profile* profile = Profile::FromBrowserContext(browser_context);
|
| + prerender::PrerenderManager* manager =
|
| + prerender::PrerenderManagerFactory::GetForProfile(profile);
|
| + DCHECK(manager);
|
| + // Start prerendering the url and capture the handle for the prerendering.
|
| + active_handle_.reset(
|
| + manager->AddPrerenderForOffline(url, session_storage_namespace, size));
|
| + return active_handle_.get();
|
| }
|
|
|
| -void PrerenderingLoader::StopLoading() {
|
| - // TODO(dougarnett): implement.
|
| +void PrerenderingAdapter::SetObserver(
|
| + prerender::PrerenderHandle::Observer* observer) {
|
| + active_handle_->SetObserver(observer);
|
| +}
|
| +
|
| +bool PrerenderingAdapter::IsPrerendering() const {
|
| + return active_handle_->IsPrerendering();
|
| +}
|
| +
|
| +void PrerenderingAdapter::OnCancel() {
|
| + active_handle_->OnCancel();
|
| +}
|
| +
|
| +content::WebContents* PrerenderingAdapter::GetPrerenderContents() const {
|
| + if (active_handle_->contents()) {
|
| + // Note: the prerender stack maintains ownership of these contents
|
| + // and PrerenderingLoader::StopLoading() must be called to report
|
| + // the Loader is done with the contents.
|
| + return active_handle_->contents()->prerender_contents();
|
| + }
|
| + return nullptr;
|
| +}
|
| +
|
| +prerender::FinalStatus PrerenderingAdapter::GetFinalStatus() const {
|
| + DCHECK(active_handle_->contents());
|
| + return active_handle_->contents()->final_status();
|
| +}
|
| +
|
| +bool PrerenderingAdapter::IsActive() const {
|
| + return active_handle_ ? true : false;
|
| +}
|
| +
|
| +bool PrerenderingAdapter::IsActive(prerender::PrerenderHandle* handle) const {
|
| + return active_handle_.get() == handle;
|
| +}
|
| +
|
| +void PrerenderingAdapter::DestroyActive() {
|
| + active_handle_.reset(nullptr);
|
| }
|
|
|
| } // namespace offline_pages
|
|
|