| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <string.h> | 5 #include <string.h> |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/guid.h" | 8 #include "base/guid.h" |
| 9 #include "base/path_service.h" | 9 #include "base/path_service.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 entry.set_entry_id(entry_id); | 65 entry.set_entry_id(entry_id); |
| 66 if (!page_url.empty()) { | 66 if (!page_url.empty()) { |
| 67 ArticleEntryPage* page = entry.add_pages(); | 67 ArticleEntryPage* page = entry.add_pages(); |
| 68 page->set_url(page_url); | 68 page->set_url(page_url); |
| 69 } | 69 } |
| 70 return entry; | 70 return entry; |
| 71 } | 71 } |
| 72 | 72 |
| 73 } // namespace | 73 } // namespace |
| 74 | 74 |
| 75 // WebContents observer that stores reference to the current |RenderViewHost|. | |
| 76 class LoadSuccessObserver : public content::WebContentsObserver { | |
| 77 public: | |
| 78 explicit LoadSuccessObserver(content::WebContents* contents) | |
| 79 : content::WebContentsObserver(contents), | |
| 80 validated_url_(GURL()), | |
| 81 finished_load_(false), | |
| 82 load_failed_(false), | |
| 83 web_contents_(contents), | |
| 84 render_view_host_(NULL) {} | |
| 85 | |
| 86 virtual void DidFinishLoad(int64 frame_id, | |
| 87 const GURL& validated_url, | |
| 88 bool is_main_frame, | |
| 89 content::RenderViewHost* render_view_host) | |
| 90 OVERRIDE { | |
| 91 validated_url_ = validated_url; | |
| 92 finished_load_ = true; | |
| 93 render_view_host_ = render_view_host; | |
| 94 } | |
| 95 | |
| 96 virtual void DidFailProvisionalLoad(int64 frame_id, | |
| 97 const base::string16& frame_unique_name, | |
| 98 bool is_main_frame, | |
| 99 const GURL& validated_url, | |
| 100 int error_code, | |
| 101 const base::string16& error_description, | |
| 102 content::RenderViewHost* render_view_host) | |
| 103 OVERRIDE { | |
| 104 load_failed_ = true; | |
| 105 } | |
| 106 | |
| 107 const GURL& validated_url() const { return validated_url_; } | |
| 108 bool finished_load() const { return finished_load_; } | |
| 109 bool load_failed() const { return load_failed_; } | |
| 110 content::WebContents* web_contents() const { return web_contents_; } | |
| 111 | |
| 112 const content::RenderViewHost* render_view_host() const { | |
| 113 return render_view_host_; | |
| 114 } | |
| 115 | |
| 116 private: | |
| 117 GURL validated_url_; | |
| 118 bool finished_load_; | |
| 119 bool load_failed_; | |
| 120 content::WebContents* web_contents_; | |
| 121 content::RenderViewHost* render_view_host_; | |
| 122 | |
| 123 DISALLOW_COPY_AND_ASSIGN(LoadSuccessObserver); | |
| 124 }; | |
| 125 | |
| 126 class DomDistillerViewerSourceBrowserTest : public InProcessBrowserTest { | 75 class DomDistillerViewerSourceBrowserTest : public InProcessBrowserTest { |
| 127 public: | 76 public: |
| 128 DomDistillerViewerSourceBrowserTest() {} | 77 DomDistillerViewerSourceBrowserTest() {} |
| 129 virtual ~DomDistillerViewerSourceBrowserTest() {} | 78 virtual ~DomDistillerViewerSourceBrowserTest() {} |
| 130 | 79 |
| 131 virtual void SetUpOnMainThread() OVERRIDE { | 80 virtual void SetUpOnMainThread() OVERRIDE { |
| 132 database_model_ = new FakeDB::EntryMap; | 81 database_model_ = new FakeDB::EntryMap; |
| 133 } | 82 } |
| 134 | 83 |
| 135 virtual void CleanUpOnMainThread() OVERRIDE { delete database_model_; } | 84 virtual void CleanUpOnMainThread() OVERRIDE { delete database_model_; } |
| 136 | 85 |
| 137 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 86 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
| 138 command_line->AppendSwitch(switches::kEnableDomDistiller); | 87 command_line->AppendSwitch(switches::kEnableDomDistiller); |
| 139 } | 88 } |
| 140 | 89 |
| 141 static KeyedService* Build(content::BrowserContext* context) { | 90 static KeyedService* Build(content::BrowserContext* context) { |
| 142 FakeDB* fake_db = new FakeDB(database_model_); | 91 FakeDB* fake_db = new FakeDB(database_model_); |
| 143 distiller_factory_ = new MockDistillerFactory(); | 92 distiller_factory_ = new MockDistillerFactory(); |
| 144 MockDistillerPageFactory* distiller_page_factory_ = | 93 MockDistillerPageFactory* distiller_page_factory_ = |
| 145 new MockDistillerPageFactory(); | 94 new MockDistillerPageFactory(); |
| 146 DomDistillerContextKeyedService* service = | 95 DomDistillerContextKeyedService* service = |
| 147 new DomDistillerContextKeyedService( | 96 new DomDistillerContextKeyedService( |
| 148 scoped_ptr<DomDistillerStoreInterface>( | 97 scoped_ptr<DomDistillerStoreInterface>( |
| 149 CreateStoreWithFakeDB(fake_db, FakeDB::EntryMap())), | 98 CreateStoreWithFakeDB(fake_db, FakeDB::EntryMap())), |
| 150 scoped_ptr<DistillerFactory>(distiller_factory_), | 99 scoped_ptr<DistillerFactory>(distiller_factory_), |
| 151 scoped_ptr<DistillerPageFactory>(distiller_page_factory_)); | 100 scoped_ptr<DistillerPageFactory>(distiller_page_factory_)); |
| 152 MockDistillerPage* distiller_page = new MockDistillerPage(); | |
| 153 EXPECT_CALL(*distiller_page_factory_, CreateDistillerPageImpl()) | |
| 154 .WillOnce(testing::Return(distiller_page)); | |
| 155 fake_db->InitCallback(true); | 101 fake_db->InitCallback(true); |
| 156 fake_db->LoadCallback(true); | 102 fake_db->LoadCallback(true); |
| 157 if (expect_distillation_) { | 103 if (expect_distillation_) { |
| 158 // There will only be destillation of an article if the database contains | 104 // There will only be destillation of an article if the database contains |
| 159 // the article. | 105 // the article. |
| 160 FakeDistiller* distiller = new FakeDistiller(true); | 106 FakeDistiller* distiller = new FakeDistiller(true); |
| 161 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) | 107 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) |
| 162 .WillOnce(testing::Return(distiller)); | 108 .WillOnce(testing::Return(distiller)); |
| 163 } | 109 } |
| 110 if (expect_distiller_page_) { |
| 111 MockDistillerPage* distiller_page = new MockDistillerPage(); |
| 112 EXPECT_CALL(*distiller_page_factory_, CreateDistillerPageImpl()) |
| 113 .WillOnce(testing::Return(distiller_page)); |
| 114 } |
| 164 return service; | 115 return service; |
| 165 } | 116 } |
| 166 | 117 |
| 167 void ViewSingleDistilledPage(const GURL& url); | 118 void ViewSingleDistilledPage(const GURL& url, |
| 119 const std::string& expected_mime_type); |
| 168 // Database entries. | 120 // Database entries. |
| 169 static FakeDB::EntryMap* database_model_; | 121 static FakeDB::EntryMap* database_model_; |
| 170 static bool expect_distillation_; | 122 static bool expect_distillation_; |
| 123 static bool expect_distiller_page_; |
| 171 static MockDistillerFactory* distiller_factory_; | 124 static MockDistillerFactory* distiller_factory_; |
| 172 }; | 125 }; |
| 173 | 126 |
| 174 FakeDB::EntryMap* DomDistillerViewerSourceBrowserTest::database_model_; | 127 FakeDB::EntryMap* DomDistillerViewerSourceBrowserTest::database_model_; |
| 175 bool DomDistillerViewerSourceBrowserTest::expect_distillation_ = false; | 128 bool DomDistillerViewerSourceBrowserTest::expect_distillation_ = false; |
| 129 bool DomDistillerViewerSourceBrowserTest::expect_distiller_page_ = false; |
| 176 MockDistillerFactory* DomDistillerViewerSourceBrowserTest::distiller_factory_ = | 130 MockDistillerFactory* DomDistillerViewerSourceBrowserTest::distiller_factory_ = |
| 177 NULL; | 131 NULL; |
| 178 | 132 |
| 179 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings | 133 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings |
| 180 // are enabled when the article exists in the database. | 134 // are enabled when the article exists in the database. |
| 181 // Flakiness: crbug.com/356866 | |
| 182 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, | 135 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, |
| 183 DISABLED_NoWebUIBindingsArticleExists) { | 136 NoWebUIBindingsArticleExists) { |
| 184 // Ensure there is one item in the database, which will trigger distillation. | 137 // Ensure there is one item in the database, which will trigger distillation. |
| 185 const ArticleEntry entry = CreateEntry("DISTILLED", "http://example.com/1"); | 138 const ArticleEntry entry = CreateEntry("DISTILLED", "http://example.com/1"); |
| 186 AddEntry(entry, database_model_); | 139 AddEntry(entry, database_model_); |
| 187 expect_distillation_ = true; | 140 expect_distillation_ = true; |
| 141 expect_distiller_page_ = true; |
| 188 const GURL url = url_utils::GetDistillerViewUrlFromEntryId( | 142 const GURL url = url_utils::GetDistillerViewUrlFromEntryId( |
| 189 chrome::kDomDistillerScheme, entry.entry_id()); | 143 chrome::kDomDistillerScheme, entry.entry_id()); |
| 190 ViewSingleDistilledPage(url); | 144 ViewSingleDistilledPage(url, "text/html"); |
| 191 } | 145 } |
| 192 | 146 |
| 193 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings | 147 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings |
| 194 // are enabled when the article is not found. | 148 // are enabled when the article is not found. |
| 195 // Flakiness: crbug.com/356866 | |
| 196 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, | 149 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, |
| 197 DISABLED_NoWebUIBindingsArticleNotFound) { | 150 NoWebUIBindingsArticleNotFound) { |
| 198 // The article does not exist, so assume no distillation will happen. | 151 // The article does not exist, so assume no distillation will happen. |
| 199 expect_distillation_ = false; | 152 expect_distillation_ = false; |
| 200 const GURL url(std::string(chrome::kDomDistillerScheme) + "://" + | 153 expect_distiller_page_ = false; |
| 201 base::GenerateGUID() + "/"); | 154 const GURL url = url_utils::GetDistillerViewUrlFromEntryId( |
| 202 ViewSingleDistilledPage(url); | 155 chrome::kDomDistillerScheme, "DOES_NOT_EXIST"); |
| 156 ViewSingleDistilledPage(url, "text/html"); |
| 203 } | 157 } |
| 204 | 158 |
| 205 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings | 159 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings |
| 206 // are enabled when requesting to view an arbitrary URL. | 160 // are enabled when requesting to view an arbitrary URL. |
| 207 // Flakiness: crbug.com/356866 | |
| 208 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, | 161 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, |
| 209 DISABLED_NoWebUIBindingsViewUrl) { | 162 NoWebUIBindingsViewUrl) { |
| 210 // We should expect distillation for any valid URL. | 163 // We should expect distillation for any valid URL. |
| 211 expect_distillation_ = true; | 164 expect_distillation_ = true; |
| 165 expect_distiller_page_ = true; |
| 212 GURL view_url("http://www.example.com/1"); | 166 GURL view_url("http://www.example.com/1"); |
| 213 const GURL url = url_utils::GetDistillerViewUrlFromUrl( | 167 const GURL url = url_utils::GetDistillerViewUrlFromUrl( |
| 214 chrome::kDomDistillerScheme, view_url); | 168 chrome::kDomDistillerScheme, view_url); |
| 215 ViewSingleDistilledPage(url); | 169 ViewSingleDistilledPage(url, "text/html"); |
| 216 } | 170 } |
| 217 | 171 |
| 218 void DomDistillerViewerSourceBrowserTest::ViewSingleDistilledPage( | 172 void DomDistillerViewerSourceBrowserTest::ViewSingleDistilledPage( |
| 219 const GURL& url) { | 173 const GURL& url, |
| 174 const std::string& expected_mime_type) { |
| 220 // Ensure the correct factory is used for the DomDistillerService. | 175 // Ensure the correct factory is used for the DomDistillerService. |
| 221 dom_distiller::DomDistillerServiceFactory::GetInstance() | 176 dom_distiller::DomDistillerServiceFactory::GetInstance() |
| 222 ->SetTestingFactoryAndUse(browser()->profile(), &Build); | 177 ->SetTestingFactoryAndUse(browser()->profile(), &Build); |
| 223 | 178 |
| 224 // Setup observer to inspect the RenderViewHost after committed navigation. | |
| 225 content::WebContents* contents = | |
| 226 browser()->tab_strip_model()->GetActiveWebContents(); | |
| 227 LoadSuccessObserver observer(contents); | |
| 228 | |
| 229 // Navigate to a URL which the source should respond to. | 179 // Navigate to a URL which the source should respond to. |
| 230 ui_test_utils::NavigateToURL(browser(), url); | 180 ui_test_utils::NavigateToURL(browser(), url); |
| 231 | 181 |
| 232 // A navigation should have succeeded to the correct URL. | 182 // Ensure no bindings for the loaded |url|. |
| 233 ASSERT_FALSE(observer.load_failed()); | 183 content::WebContents* contents_after_nav = |
| 234 ASSERT_TRUE(observer.finished_load()); | 184 browser()->tab_strip_model()->GetActiveWebContents(); |
| 235 ASSERT_EQ(url, observer.validated_url()); | 185 ASSERT_TRUE(contents_after_nav != NULL); |
| 236 // Ensure no bindings. | 186 EXPECT_EQ(url, contents_after_nav->GetLastCommittedURL()); |
| 237 const content::RenderViewHost* render_view_host = observer.render_view_host(); | 187 const content::RenderViewHost* render_view_host = |
| 238 ASSERT_EQ(0, render_view_host->GetEnabledBindings()); | 188 contents_after_nav->GetRenderViewHost(); |
| 239 // The MIME-type should always be text/html for the distilled articles. | 189 EXPECT_EQ(0, render_view_host->GetEnabledBindings()); |
| 240 EXPECT_EQ("text/html", observer.web_contents()->GetContentsMimeType()); | 190 EXPECT_EQ(expected_mime_type, contents_after_nav->GetContentsMimeType()); |
| 241 } | 191 } |
| 242 | 192 |
| 243 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings | 193 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings |
| 244 // are enabled when the CSS resource is loaded. This CSS might be bundle with | 194 // are enabled when the CSS resource is loaded. This CSS might be bundle with |
| 245 // Chrome or provided by an extension. | 195 // Chrome or provided by an extension. |
| 246 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, | 196 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, |
| 247 NoWebUIBindingsDisplayCSS) { | 197 NoWebUIBindingsDisplayCSS) { |
| 248 // Setup observer to inspect the RenderViewHost after committed navigation. | 198 expect_distillation_ = false; |
| 249 content::WebContents* contents = | 199 expect_distiller_page_ = false; |
| 250 browser()->tab_strip_model()->GetActiveWebContents(); | |
| 251 LoadSuccessObserver observer(contents); | |
| 252 | |
| 253 // Navigate to a URL which the source should respond to with CSS. | 200 // Navigate to a URL which the source should respond to with CSS. |
| 254 std::string url_without_scheme = std::string("://foobar/") + kViewerCssPath; | 201 std::string url_without_scheme = std::string("://foobar/") + kViewerCssPath; |
| 255 GURL url(chrome::kDomDistillerScheme + url_without_scheme); | 202 GURL url(chrome::kDomDistillerScheme + url_without_scheme); |
| 256 ui_test_utils::NavigateToURL(browser(), url); | 203 ViewSingleDistilledPage(url, "text/css"); |
| 257 | |
| 258 // A navigation should have succeeded to the correct URL. | |
| 259 ASSERT_FALSE(observer.load_failed()); | |
| 260 ASSERT_TRUE(observer.finished_load()); | |
| 261 ASSERT_EQ(url, observer.validated_url()); | |
| 262 // Ensure no bindings. | |
| 263 const content::RenderViewHost* render_view_host = observer.render_view_host(); | |
| 264 ASSERT_EQ(0, render_view_host->GetEnabledBindings()); | |
| 265 // The MIME-type should always be text/css for the CSS resources. | |
| 266 EXPECT_EQ("text/css", observer.web_contents()->GetContentsMimeType()); | |
| 267 } | 204 } |
| 268 | 205 |
| 206 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, |
| 207 EmptyURLShouldNotCrash) { |
| 208 // This is a bogus URL, so no distillation will happen. |
| 209 expect_distillation_ = false; |
| 210 expect_distiller_page_ = false; |
| 211 const GURL url(std::string(chrome::kDomDistillerScheme) + "://bogus/"); |
| 212 ViewSingleDistilledPage(url, "text/html"); |
| 213 } |
| 214 |
| 215 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, |
| 216 InvalidURLShouldNotCrash) { |
| 217 // This is a bogus URL, so no distillation will happen. |
| 218 expect_distillation_ = false; |
| 219 expect_distiller_page_ = false; |
| 220 const GURL url(std::string(chrome::kDomDistillerScheme) + "://bogus/foobar"); |
| 221 ViewSingleDistilledPage(url, "text/html"); |
| 222 } |
| 269 | 223 |
| 270 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, | 224 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, |
| 271 MultiPageArticle) { | 225 MultiPageArticle) { |
| 272 expect_distillation_ = false; | 226 expect_distillation_ = false; |
| 227 expect_distiller_page_ = true; |
| 273 dom_distiller::DomDistillerServiceFactory::GetInstance() | 228 dom_distiller::DomDistillerServiceFactory::GetInstance() |
| 274 ->SetTestingFactoryAndUse(browser()->profile(), &Build); | 229 ->SetTestingFactoryAndUse(browser()->profile(), &Build); |
| 275 | 230 |
| 276 scoped_refptr<content::MessageLoopRunner> distillation_done_runner = | 231 scoped_refptr<content::MessageLoopRunner> distillation_done_runner = |
| 277 new content::MessageLoopRunner; | 232 new content::MessageLoopRunner; |
| 278 | 233 |
| 279 FakeDistiller* distiller = new FakeDistiller( | 234 FakeDistiller* distiller = new FakeDistiller( |
| 280 false, | 235 false, |
| 281 distillation_done_runner->QuitClosure()); | 236 distillation_done_runner->QuitClosure()); |
| 282 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) | 237 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) |
| 283 .WillOnce(testing::Return(distiller)); | 238 .WillOnce(testing::Return(distiller)); |
| 284 | 239 |
| 285 // Setup observer to inspect the RenderViewHost after committed navigation. | 240 // Setup observer to inspect the RenderViewHost after committed navigation. |
| 286 content::WebContents* contents = | 241 content::WebContents* contents = |
| 287 browser()->tab_strip_model()->GetActiveWebContents(); | 242 browser()->tab_strip_model()->GetActiveWebContents(); |
| 288 LoadSuccessObserver observer(contents); | |
| 289 | 243 |
| 290 // Navigate to a URL and wait for the distiller to flush contents to the page. | 244 // Navigate to a URL and wait for the distiller to flush contents to the page. |
| 291 GURL url(dom_distiller::url_utils::GetDistillerViewUrlFromUrl( | 245 GURL url(dom_distiller::url_utils::GetDistillerViewUrlFromUrl( |
| 292 chrome::kDomDistillerScheme, GURL("http://urlthatlooksvalid.com"))); | 246 chrome::kDomDistillerScheme, GURL("http://urlthatlooksvalid.com"))); |
| 293 chrome::NavigateParams params(browser(), url, content::PAGE_TRANSITION_TYPED); | 247 chrome::NavigateParams params(browser(), url, content::PAGE_TRANSITION_TYPED); |
| 294 chrome::Navigate(¶ms); | 248 chrome::Navigate(¶ms); |
| 295 distillation_done_runner->Run(); | 249 distillation_done_runner->Run(); |
| 296 | 250 |
| 297 // Fake a multi-page response from distiller. | 251 // Fake a multi-page response from distiller. |
| 298 | 252 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 EXPECT_TRUE(content::ExecuteScriptAndExtractString( | 312 EXPECT_TRUE(content::ExecuteScriptAndExtractString( |
| 359 contents, kGetLoadIndicatorClassName, &result)); | 313 contents, kGetLoadIndicatorClassName, &result)); |
| 360 EXPECT_EQ("hidden", result); | 314 EXPECT_EQ("hidden", result); |
| 361 EXPECT_TRUE(content::ExecuteScriptAndExtractString( | 315 EXPECT_TRUE(content::ExecuteScriptAndExtractString( |
| 362 contents, kGetContent , &result)); | 316 contents, kGetContent , &result)); |
| 363 EXPECT_THAT(result, HasSubstr("Page 1 content")); | 317 EXPECT_THAT(result, HasSubstr("Page 1 content")); |
| 364 EXPECT_THAT(result, HasSubstr("Page 2 content")); | 318 EXPECT_THAT(result, HasSubstr("Page 2 content")); |
| 365 } | 319 } |
| 366 | 320 |
| 367 } // namespace dom_distiller | 321 } // namespace dom_distiller |
| OLD | NEW |