Add support for distilling current WebContents
[chromium-blink-merge.git] / components / dom_distiller / content / distiller_page_web_contents_browsertest.cc
blobe319097bd4196c2b155d0242da97e72e93166e9e
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.
5 #include "base/memory/weak_ptr.h"
6 #include "base/path_service.h"
7 #include "base/run_loop.h"
8 #include "base/values.h"
9 #include "components/dom_distiller/content/distiller_page_web_contents.h"
10 #include "components/dom_distiller/content/web_contents_main_frame_observer.h"
11 #include "components/dom_distiller/core/distiller_page.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/navigation_controller.h"
14 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/web_contents_observer.h"
16 #include "content/public/test/content_browser_test.h"
17 #include "content/shell/browser/shell.h"
18 #include "grit/component_resources.h"
19 #include "net/test/embedded_test_server/embedded_test_server.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "ui/base/resource/resource_bundle.h"
23 using content::ContentBrowserTest;
24 using testing::ContainsRegex;
25 using testing::HasSubstr;
26 using testing::Not;
28 namespace dom_distiller {
30 const char* kSimpleArticlePath = "/simple_article.html";
32 class DistillerPageWebContentsTest : public ContentBrowserTest {
33 public:
34 // ContentBrowserTest:
35 virtual void SetUpOnMainThread() OVERRIDE {
36 AddComponentsResources();
37 SetUpTestServer();
38 ContentBrowserTest::SetUpOnMainThread();
41 void DistillPage(const base::Closure& quit_closure, const std::string& url) {
42 quit_closure_ = quit_closure;
43 distiller_page_->DistillPage(
44 embedded_test_server()->GetURL(url),
45 dom_distiller::proto::DomDistillerOptions(),
46 base::Bind(&DistillerPageWebContentsTest::OnPageDistillationFinished,
47 this));
50 void OnPageDistillationFinished(scoped_ptr<DistilledPageInfo> distilled_page,
51 bool distillation_successful) {
52 page_info_ = distilled_page.Pass();
53 quit_closure_.Run();
56 private:
57 void AddComponentsResources() {
58 base::FilePath pak_file;
59 base::FilePath pak_dir;
60 PathService::Get(base::DIR_MODULE, &pak_dir);
61 pak_file = pak_dir.Append(FILE_PATH_LITERAL("components_resources.pak"));
62 ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
63 pak_file, ui::SCALE_FACTOR_NONE);
66 void SetUpTestServer() {
67 base::FilePath path;
68 PathService::Get(base::DIR_SOURCE_ROOT, &path);
69 path = path.AppendASCII("components/test/data/dom_distiller");
70 embedded_test_server()->ServeFilesFromDirectory(path);
71 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
74 protected:
75 void RunUseCurrentWebContentsTest(const std::string& url,
76 bool expect_new_web_contents,
77 bool setup_main_frame_observer,
78 bool wait_for_document_loaded);
80 DistillerPageWebContents* distiller_page_;
81 base::Closure quit_closure_;
82 scoped_ptr<DistilledPageInfo> page_info_;
85 // Use this class to be able to leak the WebContents, which is needed for when
86 // the current WebContents is used for distillation.
87 class TestDistillerPageWebContents : public DistillerPageWebContents {
88 public:
89 TestDistillerPageWebContents(
90 content::BrowserContext* browser_context,
91 scoped_ptr<SourcePageHandleWebContents> optional_web_contents_handle,
92 bool expect_new_web_contents)
93 : DistillerPageWebContents(browser_context,
94 optional_web_contents_handle.Pass()),
95 expect_new_web_contents_(expect_new_web_contents),
96 new_web_contents_created_(false) {}
98 virtual void CreateNewWebContents(const GURL& url) OVERRIDE {
99 ASSERT_EQ(true, expect_new_web_contents_);
100 new_web_contents_created_ = true;
101 // DistillerPageWebContents::CreateNewWebContents resets the scoped_ptr to
102 // the WebContents, so intentionally leak WebContents here, since it is
103 // owned by the shell.
104 content::WebContents* web_contents = web_contents_.release();
105 web_contents->GetLastCommittedURL();
106 DistillerPageWebContents::CreateNewWebContents(url);
109 virtual ~TestDistillerPageWebContents() {
110 if (!expect_new_web_contents_) {
111 // Intentionally leaking WebContents, since it is owned by the shell.
112 content::WebContents* web_contents = web_contents_.release();
113 web_contents->GetLastCommittedURL();
117 bool new_web_contents_created() { return new_web_contents_created_; }
119 private:
120 bool expect_new_web_contents_;
121 bool new_web_contents_created_;
124 // Helper class to know how far in the loading process the current WebContents
125 // has come. It will call the callback either after
126 // DidCommitProvisionalLoadForFrame or DocumentLoadedInFrame is called for the
127 // main frame, based on the value of |wait_for_document_loaded|.
128 class WebContentsMainFrameHelper : public content::WebContentsObserver {
129 public:
130 WebContentsMainFrameHelper(content::WebContents* web_contents,
131 const base::Closure& callback,
132 bool wait_for_document_loaded)
133 : web_contents_(web_contents),
134 callback_(callback),
135 wait_for_document_loaded_(wait_for_document_loaded) {
136 content::WebContentsObserver::Observe(web_contents);
139 virtual void DidCommitProvisionalLoadForFrame(
140 int64 frame_id,
141 const base::string16& frame_unique_name,
142 bool is_main_frame,
143 const GURL& url,
144 content::PageTransition transition_type,
145 content::RenderViewHost* render_view_host) OVERRIDE {
146 if (wait_for_document_loaded_)
147 return;
148 if (is_main_frame)
149 callback_.Run();
152 virtual void DocumentLoadedInFrame(
153 int64 frame_id,
154 content::RenderViewHost* render_view_host) OVERRIDE {
155 if (wait_for_document_loaded_) {
156 if (web_contents_ &&
157 frame_id == web_contents_->GetMainFrame()->GetRoutingID()) {
158 callback_.Run();
163 private:
164 content::WebContents* web_contents_;
165 base::Closure callback_;
166 bool wait_for_document_loaded_;
169 IN_PROC_BROWSER_TEST_F(DistillerPageWebContentsTest, BasicDistillationWorks) {
170 DistillerPageWebContents distiller_page(
171 shell()->web_contents()->GetBrowserContext(),
172 scoped_ptr<SourcePageHandleWebContents>());
173 distiller_page_ = &distiller_page;
175 base::RunLoop run_loop;
176 DistillPage(run_loop.QuitClosure(), kSimpleArticlePath);
177 run_loop.Run();
179 EXPECT_EQ("Test Page Title", page_info_.get()->title);
180 EXPECT_THAT(page_info_.get()->html, HasSubstr("Lorem ipsum"));
181 EXPECT_THAT(page_info_.get()->html, Not(HasSubstr("questionable content")));
182 EXPECT_EQ("", page_info_.get()->next_page_url);
183 EXPECT_EQ("", page_info_.get()->prev_page_url);
186 IN_PROC_BROWSER_TEST_F(DistillerPageWebContentsTest, HandlesRelativeLinks) {
187 DistillerPageWebContents distiller_page(
188 shell()->web_contents()->GetBrowserContext(),
189 scoped_ptr<SourcePageHandleWebContents>());
190 distiller_page_ = &distiller_page;
192 base::RunLoop run_loop;
193 DistillPage(run_loop.QuitClosure(), kSimpleArticlePath);
194 run_loop.Run();
196 // A relative link should've been updated.
197 EXPECT_THAT(page_info_.get()->html,
198 ContainsRegex("href=\"http://127.0.0.1:.*/relativelink.html\""));
199 EXPECT_THAT(page_info_.get()->html,
200 HasSubstr("href=\"http://www.google.com/absolutelink.html\""));
203 IN_PROC_BROWSER_TEST_F(DistillerPageWebContentsTest, HandlesRelativeImages) {
204 DistillerPageWebContents distiller_page(
205 shell()->web_contents()->GetBrowserContext(),
206 scoped_ptr<SourcePageHandleWebContents>());
207 distiller_page_ = &distiller_page;
209 base::RunLoop run_loop;
210 DistillPage(run_loop.QuitClosure(), kSimpleArticlePath);
211 run_loop.Run();
213 // A relative link should've been updated.
214 EXPECT_THAT(page_info_.get()->html,
215 ContainsRegex("src=\"http://127.0.0.1:.*/relativeimage.png\""));
216 EXPECT_THAT(page_info_.get()->html,
217 HasSubstr("src=\"http://www.google.com/absoluteimage.png\""));
220 IN_PROC_BROWSER_TEST_F(DistillerPageWebContentsTest, VisibilityDetection) {
221 DistillerPageWebContents distiller_page(
222 shell()->web_contents()->GetBrowserContext(),
223 scoped_ptr<SourcePageHandleWebContents>());
224 distiller_page_ = &distiller_page;
226 // visble_style.html and invisible_style.html only differ by the visibility
227 // internal stylesheet.
230 base::RunLoop run_loop;
231 DistillPage(run_loop.QuitClosure(), "/visible_style.html");
232 run_loop.Run();
233 EXPECT_THAT(page_info_.get()->html, HasSubstr("Lorem ipsum"));
237 base::RunLoop run_loop;
238 DistillPage(run_loop.QuitClosure(), "/invisible_style.html");
239 run_loop.Run();
240 EXPECT_THAT(page_info_.get()->html, Not(HasSubstr("Lorem ipsum")));
244 IN_PROC_BROWSER_TEST_F(DistillerPageWebContentsTest,
245 UsingCurrentWebContentsWrongUrl) {
246 std::string url("/bogus");
247 bool expect_new_web_contents = true;
248 bool setup_main_frame_observer = true;
249 bool wait_for_document_loaded = true;
250 RunUseCurrentWebContentsTest(url,
251 expect_new_web_contents,
252 setup_main_frame_observer,
253 wait_for_document_loaded);
256 IN_PROC_BROWSER_TEST_F(DistillerPageWebContentsTest,
257 UsingCurrentWebContentsNoMainFrameObserver) {
258 std::string url(kSimpleArticlePath);
259 bool expect_new_web_contents = true;
260 bool setup_main_frame_observer = false;
261 bool wait_for_document_loaded = true;
262 RunUseCurrentWebContentsTest(url,
263 expect_new_web_contents,
264 setup_main_frame_observer,
265 wait_for_document_loaded);
268 IN_PROC_BROWSER_TEST_F(DistillerPageWebContentsTest,
269 UsingCurrentWebContentsNotFinishedLoadingYet) {
270 std::string url(kSimpleArticlePath);
271 bool expect_new_web_contents = false;
272 bool setup_main_frame_observer = true;
273 bool wait_for_document_loaded = false;
274 RunUseCurrentWebContentsTest(url,
275 expect_new_web_contents,
276 setup_main_frame_observer,
277 wait_for_document_loaded);
280 IN_PROC_BROWSER_TEST_F(DistillerPageWebContentsTest,
281 UsingCurrentWebContentsReadyForDistillation) {
282 std::string url(kSimpleArticlePath);
283 bool expect_new_web_contents = false;
284 bool setup_main_frame_observer = true;
285 bool wait_for_document_loaded = true;
286 RunUseCurrentWebContentsTest(url,
287 expect_new_web_contents,
288 setup_main_frame_observer,
289 wait_for_document_loaded);
292 void DistillerPageWebContentsTest::RunUseCurrentWebContentsTest(
293 const std::string& url,
294 bool expect_new_web_contents,
295 bool setup_main_frame_observer,
296 bool wait_for_document_loaded) {
297 content::WebContents* current_web_contents = shell()->web_contents();
298 if (setup_main_frame_observer) {
299 dom_distiller::WebContentsMainFrameObserver::CreateForWebContents(
300 current_web_contents);
302 base::RunLoop url_loaded_runner;
303 WebContentsMainFrameHelper main_frame_loaded(current_web_contents,
304 url_loaded_runner.QuitClosure(),
305 wait_for_document_loaded);
306 current_web_contents->GetController().LoadURL(
307 embedded_test_server()->GetURL(url),
308 content::Referrer(),
309 content::PAGE_TRANSITION_TYPED,
310 std::string());
311 url_loaded_runner.Run();
313 scoped_ptr<content::WebContents> old_web_contents_sptr(current_web_contents);
314 scoped_ptr<SourcePageHandleWebContents> source_page_handle(
315 new SourcePageHandleWebContents(old_web_contents_sptr.Pass()));
317 TestDistillerPageWebContents distiller_page(
318 shell()->web_contents()->GetBrowserContext(),
319 source_page_handle.Pass(),
320 expect_new_web_contents);
321 distiller_page_ = &distiller_page;
323 base::RunLoop run_loop;
324 DistillPage(run_loop.QuitClosure(), kSimpleArticlePath);
325 run_loop.Run();
327 // Sanity check of distillation process.
328 EXPECT_EQ(expect_new_web_contents, distiller_page.new_web_contents_created());
329 EXPECT_EQ("Test Page Title", page_info_.get()->title);
332 } // namespace dom_distiller