Chromium Code Reviews| 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 08576826a92db9984c60bbbfe2baf32711a173b8..e789093513da1b393ea652b832e7e5202ebfd5cf 100644 |
| --- a/chrome/browser/android/offline_pages/prerendering_loader.cc |
| +++ b/chrome/browser/android/offline_pages/prerendering_loader.cc |
| @@ -4,26 +4,161 @@ |
| #include "chrome/browser/android/offline_pages/prerendering_loader.h" |
| +#include "base/location.h" |
| +#include "base/logging.h" |
| +#include "base/threading/thread_task_runner_handle.h" |
| +#include "chrome/browser/profiles/profile.h" |
| #include "content/public/browser/browser_context.h" |
| +#include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/web_contents.h" |
| #include "ui/gfx/geometry/size.h" |
| namespace offline_pages { |
| -PrerenderingLoader::PrerenderingLoader( |
| - content::BrowserContext* browser_context) {} |
| +PrerenderingLoader::PrerenderingLoader(content::BrowserContext* browser_context) |
| + : state_(State::IDLE), browser_context_(browser_context) { |
| + adapter_.reset(new PrerenderAdapter(this)); |
| +} |
| + |
| +PrerenderingLoader::~PrerenderingLoader() { |
| + CancelPrerender(); |
| +} |
| + |
| +bool PrerenderingLoader::LoadPage(const GURL& url, |
| + const LoadPageCallback& callback) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + if (!IsIdle()) { |
| + DVLOG(1) << "WARNING: Existing request pending"; |
|
pasko
2016/05/20 19:04:53
it might be LOADED and LOADING, not just pending
dougarnett
2016/05/20 22:21:12
Done.
|
| + return false; |
| + } |
| + if (!CanPrerender()) |
| + return false; |
| -PrerenderingLoader::~PrerenderingLoader() {} |
| + // Create a WebContents instance to define and hold a SessionStorageNamespace |
| + // for this load request. |
| + DCHECK(!session_contents_.get()); |
| + session_contents_.reset(content::WebContents::Create( |
| + content::WebContents::CreateParams(browser_context_))); |
| + bool accepted = adapter_->StartPrerender( |
| + browser_context_, url, GetSessionStorageNamespace(), GetSize()); |
| + if (!accepted) |
| + return false; |
| -bool PrerenderingLoader::LoadPage( |
| - const GURL& url, |
| - const LoadPageCallback& callback) { |
| - // TODO(dougarnett): implement. |
| - return false; |
| + DCHECK(adapter_->IsActive()); |
| + callback_ = callback; |
| + state_ = State::PENDING; |
| + return true; |
| } |
| void PrerenderingLoader::StopLoading() { |
| - // TODO(dougarnett): implement. |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + CancelPrerender(); |
| +} |
| + |
| +bool PrerenderingLoader::CanPrerender() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + return adapter_->CanPrerender(); |
| +} |
| + |
| +bool PrerenderingLoader::IsIdle() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + return state_ == State::IDLE; |
| +} |
| + |
| +bool PrerenderingLoader::IsLoaded() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + return state_ == State::LOADED; |
| +} |
| + |
| +void PrerenderingLoader::SetAdapterForTesting( |
| + std::unique_ptr<PrerenderAdapter> prerender_adapter) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + adapter_ = std::move(prerender_adapter); |
| +} |
| + |
| +void PrerenderingLoader::OnPrerenderStart() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + DCHECK(state_ == State::PENDING); |
| + state_ = State::LOADING; |
| +} |
| + |
| +void PrerenderingLoader::OnPrerenderStopLoading() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + // TODO(dougarnett): Implement/integrate to delay policy here. |
| + ReportLoaded(); |
| +} |
| + |
| +void PrerenderingLoader::OnPrerenderDomContentLoaded() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + // TODO(dougarnett): Implement/integrate to delay policy here. |
| + ReportLoaded(); |
| +} |
| + |
| +void PrerenderingLoader::OnPrerenderStop() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + ReportLoadingStopped(); |
| +} |
| + |
| +content::SessionStorageNamespace* |
| +PrerenderingLoader::GetSessionStorageNamespace() { |
|
pasko
2016/05/20 19:04:53
called only once, does this really need to be a se
dougarnett
2016/05/20 22:21:12
Done.
|
| + DCHECK(session_contents_); |
| + return session_contents_->GetController().GetDefaultSessionStorageNamespace(); |
| +} |
| + |
| +const gfx::Size PrerenderingLoader::GetSize() { |
|
pasko
2016/05/20 19:04:53
this method is used only once, and the implementat
dougarnett
2016/05/20 22:21:12
Done.
|
| + DCHECK(session_contents_); |
| + return session_contents_->GetContainerBounds().size(); |
| +} |
| + |
| +void PrerenderingLoader::ReportLoaded() { |
|
pasko
2016/05/20 19:04:53
it does not only Report, but also performs state t
dougarnett
2016/05/20 22:21:12
Tried improved names and comments for these method
pasko
2016/05/23 20:05:41
I still find the state transitions here to be comp
dougarnett
2016/05/23 21:43:54
Will keep this feedback in mind going forward as I
|
| + // Check if load is still active to see if reporting is applicable (i.e., |
| + // no other load detection or canceling has already occurred). |
| + if (!IsLoaded() && !IsIdle()) { |
|
pasko
2016/05/20 19:04:53
We are not supposed to call ReportLoaded with stat
dougarnett
2016/05/20 22:21:12
see preceding comment
|
| + content::WebContents* contents = adapter_->GetWebContents(); |
| + if (contents) { |
| + state_ = State::LOADED; |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
|
pasko
2016/05/20 19:04:53
I still do not understand the ThreadTaskRunnerHand
dougarnett
2016/05/20 22:21:12
I don't know which type of PostTask is preferred.
pasko
2016/05/23 20:05:41
OK, using ThreadTaskRunnerHandle to post to the sa
dougarnett
2016/05/23 21:43:54
I don't have a strong opinion here. I agree does n
|
| + FROM_HERE, |
| + base::Bind(callback_, Offliner::RequestStatus::LOADED, contents)); |
| + } else { |
| + // No WebContents means that the load failed. |
| + ReportLoadingStopped(); |
| + } |
| + } |
| +} |
| + |
| +void PrerenderingLoader::ReportLoadingStopped() { |
| + // Check if request is still active to see if reporting is applicable. |
|
pasko
2016/05/20 19:04:53
"Applicable" is not concrete. It would be clearer
dougarnett
2016/05/20 22:21:12
reworded
|
| + if (!IsIdle()) { |
| + if (adapter_->IsActive()) { |
| + DVLOG(1) << "Load failed: " << adapter_->GetFinalStatus(); |
| + adapter_->DestroyActive(); |
| + } |
| + // Request status depends on whether we are still loading (failed) or |
| + // did load and then loading was stopped (cancel - from prerender stack). |
| + Offliner::RequestStatus request_status = |
| + IsLoaded() ? Offliner::RequestStatus::CANCELED |
| + : Offliner::RequestStatus::FAILED; |
| + // TODO(dougarnett): For failure, determine from final status if retry-able |
| + // and report different failure statuses if retry-able or not. |
| + session_contents_.reset(nullptr); |
| + state_ = State::IDLE; |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::Bind(callback_, request_status, nullptr)); |
| + } |
| +} |
| + |
| +void PrerenderingLoader::CancelPrerender() { |
| + if (adapter_->IsActive()) { |
| + adapter_->DestroyActive(); |
| + } |
| + session_contents_.reset(nullptr); |
| + if (!IsLoaded() && !IsIdle()) { |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, |
| + base::Bind(callback_, Offliner::RequestStatus::CANCELED, nullptr)); |
| + } |
| + state_ = State::IDLE; |
| } |
| } // namespace offline_pages |