Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / dom_distiller / dom_distiller_viewer_source_browsertest.cc
1 // Copyright 2014 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 <string.h>
6
7 #include "base/command_line.h"
8 #include "base/guid.h"
9 #include "chrome/browser/dom_distiller/dom_distiller_service_factory.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/tabs/tab_strip_model.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "chrome/common/url_constants.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "components/dom_distiller/content/dom_distiller_viewer_source.h"
18 #include "components/dom_distiller/core/distiller.h"
19 #include "components/dom_distiller/core/dom_distiller_service.h"
20 #include "components/dom_distiller/core/dom_distiller_store.h"
21 #include "components/dom_distiller/core/dom_distiller_test_util.h"
22 #include "components/dom_distiller/core/fake_db.h"
23 #include "components/dom_distiller/core/fake_distiller.h"
24 #include "components/dom_distiller/core/task_tracker.h"
25 #include "components/dom_distiller/core/url_utils.h"
26 #include "content/public/browser/render_view_host.h"
27 #include "content/public/browser/url_data_source.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/browser/web_contents_observer.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 namespace dom_distiller {
33
34 using test::FakeDB;
35 using test::FakeDistiller;
36 using test::MockDistillerFactory;
37 using test::util::CreateStoreWithFakeDB;
38
39 namespace {
40
41 void AddEntry(const ArticleEntry& e, FakeDB::EntryMap* map) {
42   (*map)[e.entry_id()] = e;
43 }
44
45 ArticleEntry CreateEntry(std::string entry_id, std::string page_url) {
46   ArticleEntry entry;
47   entry.set_entry_id(entry_id);
48   if (!page_url.empty()) {
49     ArticleEntryPage* page = entry.add_pages();
50     page->set_url(page_url);
51   }
52   return entry;
53 }
54
55 }  // namespace
56
57 // WebContents observer that stores reference to the current |RenderViewHost|.
58 class LoadSuccessObserver : public content::WebContentsObserver {
59  public:
60   explicit LoadSuccessObserver(content::WebContents* contents)
61       : content::WebContentsObserver(contents),
62         validated_url_(GURL()),
63         finished_load_(false),
64         load_failed_(false),
65         web_contents_(contents),
66         render_view_host_(NULL) {}
67
68   virtual void DidFinishLoad(int64 frame_id,
69                              const GURL& validated_url,
70                              bool is_main_frame,
71                              content::RenderViewHost* render_view_host)
72       OVERRIDE {
73     validated_url_ = validated_url;
74     finished_load_ = true;
75     render_view_host_ = render_view_host;
76   }
77
78   virtual void DidFailProvisionalLoad(int64 frame_id,
79                                       const base::string16& frame_unique_name,
80                                       bool is_main_frame,
81                                       const GURL& validated_url,
82                                       int error_code,
83                                       const base::string16& error_description,
84                                       content::RenderViewHost* render_view_host)
85       OVERRIDE {
86     load_failed_ = true;
87   }
88
89   const GURL& validated_url() const { return validated_url_; }
90   bool finished_load() const { return finished_load_; }
91   bool load_failed() const { return load_failed_; }
92   content::WebContents* web_contents() const { return web_contents_; }
93
94   const content::RenderViewHost* render_view_host() const {
95     return render_view_host_;
96   }
97
98  private:
99   GURL validated_url_;
100   bool finished_load_;
101   bool load_failed_;
102   content::WebContents* web_contents_;
103   content::RenderViewHost* render_view_host_;
104
105   DISALLOW_COPY_AND_ASSIGN(LoadSuccessObserver);
106 };
107
108 class DomDistillerViewerSourceBrowserTest : public InProcessBrowserTest {
109  public:
110   DomDistillerViewerSourceBrowserTest() {}
111   virtual ~DomDistillerViewerSourceBrowserTest() {}
112
113   virtual void SetUpOnMainThread() OVERRIDE {
114     database_model_ = new FakeDB::EntryMap;
115   }
116
117   virtual void CleanUpOnMainThread() OVERRIDE { delete database_model_; }
118
119   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
120     command_line->AppendSwitch(switches::kEnableDomDistiller);
121   }
122
123   static KeyedService* Build(content::BrowserContext* context) {
124     FakeDB* fake_db = new FakeDB(database_model_);
125     MockDistillerFactory* factory = new MockDistillerFactory();
126     DomDistillerContextKeyedService* service =
127         new DomDistillerContextKeyedService(
128             scoped_ptr<DomDistillerStoreInterface>(
129                 CreateStoreWithFakeDB(fake_db, FakeDB::EntryMap())),
130             scoped_ptr<DistillerFactory>(factory),
131             scoped_ptr<DistillerPageFactory>());
132     fake_db->InitCallback(true);
133     fake_db->LoadCallback(true);
134     if (expect_distillation_) {
135       // There will only be destillation of an article if the database contains
136       // the article.
137       FakeDistiller* distiller = new FakeDistiller(true);
138       EXPECT_CALL(*factory, CreateDistillerImpl())
139           .WillOnce(testing::Return(distiller));
140     }
141     return service;
142   }
143
144   void ViewSingleDistilledPage(const GURL& url);
145
146   // Database entries.
147   static FakeDB::EntryMap* database_model_;
148   static bool expect_distillation_;
149 };
150
151 FakeDB::EntryMap* DomDistillerViewerSourceBrowserTest::database_model_;
152 bool DomDistillerViewerSourceBrowserTest::expect_distillation_ = false;
153
154 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings
155 // are enabled when the article exists in the database.
156 // Flakiness: crbug.com/356866
157 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest,
158                        DISABLED_NoWebUIBindingsArticleExists) {
159   // Ensure there is one item in the database, which will trigger distillation.
160   const ArticleEntry entry = CreateEntry("DISTILLED", "http://example.com/1");
161   AddEntry(entry, database_model_);
162   expect_distillation_ = true;
163   const GURL url = url_utils::GetDistillerViewUrlFromEntryId(
164       chrome::kDomDistillerScheme, entry.entry_id());
165   ViewSingleDistilledPage(url);
166 }
167
168 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings
169 // are enabled when the article is not found.
170 // Flakiness: crbug.com/356866
171 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest,
172                        DISABLED_NoWebUIBindingsArticleNotFound) {
173   // The article does not exist, so assume no distillation will happen.
174   expect_distillation_ = false;
175   const GURL url(std::string(chrome::kDomDistillerScheme) + "://" +
176                  base::GenerateGUID() + "/");
177   ViewSingleDistilledPage(url);
178 }
179
180 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings
181 // are enabled when requesting to view an arbitrary URL.
182 // Flakiness: crbug.com/356866
183 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest,
184                        DISABLED_NoWebUIBindingsViewUrl) {
185   // We should expect distillation for any valid URL.
186   expect_distillation_ = true;
187   GURL view_url("http://www.example.com/1");
188   const GURL url = url_utils::GetDistillerViewUrlFromUrl(
189       chrome::kDomDistillerScheme, view_url);
190   ViewSingleDistilledPage(url);
191 }
192
193 void DomDistillerViewerSourceBrowserTest::ViewSingleDistilledPage(
194     const GURL& url) {
195   // Ensure the correct factory is used for the DomDistillerService.
196   dom_distiller::DomDistillerServiceFactory::GetInstance()
197       ->SetTestingFactoryAndUse(browser()->profile(), &Build);
198
199   // Setup observer to inspect the RenderViewHost after committed navigation.
200   content::WebContents* contents =
201       browser()->tab_strip_model()->GetActiveWebContents();
202   LoadSuccessObserver observer(contents);
203
204   // Navigate to a URL which the source should respond to.
205   ui_test_utils::NavigateToURL(browser(), url);
206
207   // A navigation should have succeeded to the correct URL.
208   ASSERT_FALSE(observer.load_failed());
209   ASSERT_TRUE(observer.finished_load());
210   ASSERT_EQ(url, observer.validated_url());
211   // Ensure no bindings.
212   const content::RenderViewHost* render_view_host = observer.render_view_host();
213   ASSERT_EQ(0, render_view_host->GetEnabledBindings());
214   // The MIME-type should always be text/html for the distilled articles.
215   EXPECT_EQ("text/html", observer.web_contents()->GetContentsMimeType());
216 }
217
218 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings
219 // are enabled when the CSS resource is loaded. This CSS might be bundle with
220 // Chrome or provided by an extension.
221 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest,
222                        NoWebUIBindingsDisplayCSS) {
223   // Setup observer to inspect the RenderViewHost after committed navigation.
224   content::WebContents* contents =
225       browser()->tab_strip_model()->GetActiveWebContents();
226   LoadSuccessObserver observer(contents);
227
228   // Navigate to a URL which the source should respond to with CSS.
229   std::string url_without_scheme = "://foobar/readability.css";
230   GURL url(chrome::kDomDistillerScheme + url_without_scheme);
231   ui_test_utils::NavigateToURL(browser(), url);
232
233   // A navigation should have succeeded to the correct URL.
234   ASSERT_FALSE(observer.load_failed());
235   ASSERT_TRUE(observer.finished_load());
236   ASSERT_EQ(url, observer.validated_url());
237   // Ensure no bindings.
238   const content::RenderViewHost* render_view_host = observer.render_view_host();
239   ASSERT_EQ(0, render_view_host->GetEnabledBindings());
240   // The MIME-type should always be text/css for the CSS resources.
241   EXPECT_EQ("text/css", observer.web_contents()->GetContentsMimeType());
242 }
243
244 }  // namespace dom_distiller