// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" using content::WebContents; using extensions::Extension; namespace { const std::string kSubscribePage = "/subscribe.html"; const std::string kFeedPageMultiRel = "files/feeds/feed_multi_rel.html"; const std::string kValidFeedNoLinks = "files/feeds/feed_nolinks.xml"; const std::string kValidFeed0 = "files/feeds/feed_script.xml"; const std::string kValidFeed1 = "files/feeds/feed1.xml"; const std::string kValidFeed2 = "files/feeds/feed2.xml"; const std::string kValidFeed3 = "files/feeds/feed3.xml"; const std::string kValidFeed4 = "files/feeds/feed4.xml"; const std::string kValidFeed5 = "files/feeds/feed5.xml"; const std::string kValidFeed6 = "files/feeds/feed6.xml"; const std::string kInvalidFeed1 = "files/feeds/feed_invalid1.xml"; const std::string kInvalidFeed2 = "files/feeds/feed_invalid2.xml"; // We need a triple encoded string to prove that we are not decoding twice in // subscribe.js because one layer is also stripped off when subscribe.js passes // it to the XMLHttpRequest object. const std::string kFeedTripleEncoded = "files/feeds/url%25255Fdecoding.html"; static const wchar_t* jscript_feed_title = L"window.domAutomationController.send(" L" document.getElementById('title') ? " L" document.getElementById('title').textContent : " L" \"element 'title' not found\"" L");"; static const wchar_t* jscript_anchor = L"window.domAutomationController.send(" L" document.getElementById('anchor_0') ? " L" document.getElementById('anchor_0').textContent : " L" \"element 'anchor_0' not found\"" L");"; static const wchar_t* jscript_desc = L"window.domAutomationController.send(" L" document.getElementById('desc_0') ? " L" document.getElementById('desc_0').textContent : " L" \"element 'desc_0' not found\"" L");"; static const wchar_t* jscript_error = L"window.domAutomationController.send(" L" document.getElementById('error') ? " L" document.getElementById('error').textContent : " L" \"No error\"" L");"; GURL GetFeedUrl(net::TestServer* server, const std::string& feed_page, bool direct_url, std::string extension_id) { GURL feed_url = server->GetURL(feed_page); if (direct_url) { // We navigate directly to the subscribe page for feeds where the feed // sniffing won't work, in other words, as is the case for malformed feeds. return GURL(std::string(chrome::kExtensionScheme) + content::kStandardSchemeSeparator + extension_id + std::string(kSubscribePage) + std::string("?") + feed_url.spec() + std::string("&synchronous")); } else { // Navigate to the feed content (which will cause the extension to try to // sniff the type and display the subscribe page in another tab. return GURL(feed_url.spec()); } } bool ValidatePageElement(WebContents* tab, const std::wstring& frame, const std::wstring& javascript, const std::string& expected_value) { std::string returned_value; std::string error; if (!content::ExecuteJavaScriptAndExtractString( tab->GetRenderViewHost(), frame, javascript, &returned_value)) return false; EXPECT_STREQ(expected_value.c_str(), returned_value.c_str()); return expected_value == returned_value; } // Navigates to a feed page and, if |sniff_xml_type| is set, wait for the // extension to kick in, detect the feed and redirect to a feed preview page. // |sniff_xml_type| is generally set to true if the feed is sniffable and false // for invalid feeds. void NavigateToFeedAndValidate(net::TestServer* server, const std::string& url, Browser* browser, std::string extension_id, bool sniff_xml_type, const std::string& expected_feed_title, const std::string& expected_item_title, const std::string& expected_item_desc, const std::string& expected_error) { if (sniff_xml_type) { // TODO(finnur): Implement this is a non-flaky way. } // Navigate to the subscribe page directly. ui_test_utils::NavigateToURL(browser, GetFeedUrl(server, url, true, extension_id)); WebContents* tab = chrome::GetActiveWebContents(browser); ASSERT_TRUE(ValidatePageElement(tab, L"", jscript_feed_title, expected_feed_title)); ASSERT_TRUE(ValidatePageElement(tab, L"//html/body/div/iframe[1]", jscript_anchor, expected_item_title)); ASSERT_TRUE(ValidatePageElement(tab, L"//html/body/div/iframe[1]", jscript_desc, expected_item_desc)); ASSERT_TRUE(ValidatePageElement(tab, L"//html/body/div/iframe[1]", jscript_error, expected_error)); } } // namespace // Makes sure that the RSS detects RSS feed links, even when rel tag contains // more than just "alternate". IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, RSSMultiRelLink) { ASSERT_TRUE(test_server()->Start()); ASSERT_TRUE(LoadExtension( test_data_dir_.AppendASCII("subscribe_page_action"))); ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(0)); // Navigate to the feed page. GURL feed_url = test_server()->GetURL(kFeedPageMultiRel); ui_test_utils::NavigateToURL(browser(), feed_url); // We should now have one page action ready to go in the LocationBar. ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1)); } IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed1) { ASSERT_TRUE(test_server()->Start()); const Extension* extension = LoadExtension( test_data_dir_.AppendASCII("subscribe_page_action")); ASSERT_TRUE(extension); std::string id = extension->id(); NavigateToFeedAndValidate(test_server(), kValidFeed1, browser(), id, true, "Feed for MyFeedTitle", "Title 1", "Desc", "No error"); } IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed2) { ASSERT_TRUE(test_server()->Start()); const Extension* extension = LoadExtension( test_data_dir_.AppendASCII("subscribe_page_action")); ASSERT_TRUE(extension); std::string id = extension->id(); NavigateToFeedAndValidate(test_server(), kValidFeed2, browser(), id, true, "Feed for MyFeed2", "My item title1", "This is a summary.", "No error"); } IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed3) { ASSERT_TRUE(test_server()->Start()); const Extension* extension = LoadExtension( test_data_dir_.AppendASCII("subscribe_page_action")); ASSERT_TRUE(extension); std::string id = extension->id(); NavigateToFeedAndValidate(test_server(), kValidFeed3, browser(), id, true, "Feed for Google Code buglist rss feed", "My dear title", "My dear content", "No error"); } IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed4) { ASSERT_TRUE(test_server()->Start()); const Extension* extension = LoadExtension( test_data_dir_.AppendASCII("subscribe_page_action")); ASSERT_TRUE(extension); std::string id = extension->id(); NavigateToFeedAndValidate(test_server(), kValidFeed4, browser(), id, true, "Feed for Title chars