distiller_page_web_contents.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "components/dom_distiller/content/distiller_page_web_contents.h" 6 7#include "base/callback.h" 8#include "base/memory/scoped_ptr.h" 9#include "base/strings/utf_string_conversions.h" 10#include "components/dom_distiller/content/web_contents_main_frame_observer.h" 11#include "components/dom_distiller/core/distiller_page.h" 12#include "components/dom_distiller/core/dom_distiller_service.h" 13#include "content/public/browser/browser_context.h" 14#include "content/public/browser/navigation_controller.h" 15#include "content/public/browser/render_frame_host.h" 16#include "content/public/browser/render_view_host.h" 17#include "content/public/browser/web_contents.h" 18#include "content/public/browser/web_contents_observer.h" 19#include "url/gurl.h" 20 21namespace dom_distiller { 22 23SourcePageHandleWebContents::SourcePageHandleWebContents( 24 scoped_ptr<content::WebContents> web_contents) 25 : web_contents_(web_contents.Pass()) { 26 DCHECK(web_contents_); 27} 28 29SourcePageHandleWebContents::~SourcePageHandleWebContents() { 30} 31 32scoped_ptr<content::WebContents> SourcePageHandleWebContents::GetWebContents() { 33 return web_contents_.Pass(); 34} 35 36scoped_ptr<DistillerPage> DistillerPageWebContentsFactory::CreateDistillerPage() 37 const { 38 DCHECK(browser_context_); 39 return scoped_ptr<DistillerPage>(new DistillerPageWebContents( 40 browser_context_, scoped_ptr<SourcePageHandleWebContents>())); 41} 42 43scoped_ptr<DistillerPage> 44DistillerPageWebContentsFactory::CreateDistillerPageWithHandle( 45 scoped_ptr<SourcePageHandle> handle) const { 46 DCHECK(browser_context_); 47 scoped_ptr<SourcePageHandleWebContents> web_contents_handle = 48 scoped_ptr<SourcePageHandleWebContents>( 49 static_cast<SourcePageHandleWebContents*>(handle.release())); 50 return scoped_ptr<DistillerPage>(new DistillerPageWebContents( 51 browser_context_, web_contents_handle.Pass())); 52} 53 54DistillerPageWebContents::DistillerPageWebContents( 55 content::BrowserContext* browser_context, 56 scoped_ptr<SourcePageHandleWebContents> optional_web_contents_handle) 57 : state_(IDLE), browser_context_(browser_context) { 58 if (optional_web_contents_handle) { 59 web_contents_ = optional_web_contents_handle->GetWebContents().Pass(); 60 } 61} 62 63DistillerPageWebContents::~DistillerPageWebContents() { 64} 65 66void DistillerPageWebContents::DistillPageImpl(const GURL& url, 67 const std::string& script) { 68 DCHECK(browser_context_); 69 DCHECK(state_ == IDLE); 70 state_ = LOADING_PAGE; 71 script_ = script; 72 73 if (web_contents_ && web_contents_->GetLastCommittedURL() == url) { 74 WebContentsMainFrameObserver* main_frame_observer = 75 WebContentsMainFrameObserver::FromWebContents(web_contents_.get()); 76 if (main_frame_observer && main_frame_observer->is_initialized()) { 77 if (main_frame_observer->is_document_loaded_in_main_frame()) { 78 // Main frame has already loaded for the current WebContents, so execute 79 // JavaScript immediately. 80 ExecuteJavaScript(); 81 } else { 82 // Main frame document has not loaded yet, so wait until it has before 83 // executing JavaScript. It will trigger after DocumentLoadedInFrame is 84 // called for the main frame. 85 content::WebContentsObserver::Observe(web_contents_.get()); 86 } 87 } else { 88 // The WebContentsMainFrameObserver has not been correctly initialized, 89 // so fall back to creating a new WebContents. 90 CreateNewWebContents(url); 91 } 92 } else { 93 CreateNewWebContents(url); 94 } 95} 96 97void DistillerPageWebContents::CreateNewWebContents(const GURL& url) { 98 // Create new WebContents to use for distilling the content. 99 content::WebContents::CreateParams create_params(browser_context_); 100 create_params.initially_hidden = true; 101 web_contents_.reset(content::WebContents::Create(create_params)); 102 DCHECK(web_contents_.get()); 103 104 // Start observing WebContents and load the requested URL. 105 content::WebContentsObserver::Observe(web_contents_.get()); 106 content::NavigationController::LoadURLParams params(url); 107 web_contents_->GetController().LoadURLWithParams(params); 108} 109 110void DistillerPageWebContents::DocumentLoadedInFrame( 111 content::RenderFrameHost* render_frame_host) { 112 if (render_frame_host == web_contents_->GetMainFrame()) { 113 ExecuteJavaScript(); 114 } 115} 116 117void DistillerPageWebContents::DidFailLoad( 118 content::RenderFrameHost* render_frame_host, 119 const GURL& validated_url, 120 int error_code, 121 const base::string16& error_description) { 122 if (!render_frame_host->GetParent()) { 123 content::WebContentsObserver::Observe(NULL); 124 DCHECK(state_ == LOADING_PAGE || state_ == EXECUTING_JAVASCRIPT); 125 state_ = PAGELOAD_FAILED; 126 scoped_ptr<base::Value> empty(base::Value::CreateNullValue()); 127 OnWebContentsDistillationDone(GURL(), empty.get()); 128 } 129} 130 131void DistillerPageWebContents::ExecuteJavaScript() { 132 content::RenderFrameHost* frame = web_contents_->GetMainFrame(); 133 DCHECK(frame); 134 DCHECK_EQ(LOADING_PAGE, state_); 135 state_ = EXECUTING_JAVASCRIPT; 136 content::WebContentsObserver::Observe(NULL); 137 web_contents_->Stop(); 138 DVLOG(1) << "Beginning distillation"; 139 frame->ExecuteJavaScript( 140 base::UTF8ToUTF16(script_), 141 base::Bind(&DistillerPageWebContents::OnWebContentsDistillationDone, 142 base::Unretained(this), 143 web_contents_->GetLastCommittedURL())); 144} 145 146void DistillerPageWebContents::OnWebContentsDistillationDone( 147 const GURL& page_url, 148 const base::Value* value) { 149 DCHECK(state_ == PAGELOAD_FAILED || state_ == EXECUTING_JAVASCRIPT); 150 state_ = IDLE; 151 DistillerPage::OnDistillationDone(page_url, value); 152} 153 154} // namespace dom_distiller 155