// 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/tabs/tab_strip_model.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" #include "extensions/common/constants.h" #include "extensions/common/extension.h" using content::WebContents; using extensions::Extension; namespace { const char kSubscribePage[] = "/subscribe.html"; const char kFeedPageMultiRel[] = "files/feeds/feed_multi_rel.html"; const char kValidFeedNoLinks[] = "files/feeds/feed_nolinks.xml"; const char kValidFeed0[] = "files/feeds/feed_script.xml"; const char kValidFeed1[] = "files/feeds/feed1.xml"; const char kValidFeed2[] = "files/feeds/feed2.xml"; const char kValidFeed3[] = "files/feeds/feed3.xml"; const char kValidFeed4[] = "files/feeds/feed4.xml"; const char kValidFeed5[] = "files/feeds/feed5.xml"; const char kValidFeed6[] = "files/feeds/feed6.xml"; const char kInvalidFeed1[] = "files/feeds/feed_invalid1.xml"; const char 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 char kFeedTripleEncoded[] = "files/feeds/url%25255Fdecoding.html"; static const char kScriptFeedTitle[] = "window.domAutomationController.send(" " document.getElementById('title') ? " " document.getElementById('title').textContent : " " \"element 'title' not found\"" ");"; static const char kScriptAnchor[] = "window.domAutomationController.send(" " document.getElementById('anchor_0') ? " " document.getElementById('anchor_0').textContent : " " \"element 'anchor_0' not found\"" ");"; static const char kScriptDesc[] = "window.domAutomationController.send(" " document.getElementById('desc_0') ? " " document.getElementById('desc_0').textContent : " " \"element 'desc_0' not found\"" ");"; static const char kScriptError[] = "window.domAutomationController.send(" " document.getElementById('error') ? " " document.getElementById('error').textContent : " " \"No error\"" ");"; GURL GetFeedUrl(net::SpawnedTestServer* 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(extensions::kExtensionScheme) + url::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(content::RenderFrameHost* frame, const std::string& javascript, const std::string& expected_value) { std::string returned_value; if (!content::ExecuteScriptAndExtractString(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::SpawnedTestServer* 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 = browser->tab_strip_model()->GetActiveWebContents(); content::RenderFrameHost* frame = content::FrameMatchingPredicate( tab, base::Bind(&content::FrameIsChildOfMainFrame)); ASSERT_TRUE(ValidatePageElement( tab->GetMainFrame(), kScriptFeedTitle, expected_feed_title)); ASSERT_TRUE(ValidatePageElement(frame, kScriptAnchor, expected_item_title)); ASSERT_TRUE(ValidatePageElement(frame, kScriptDesc, expected_item_desc)); ASSERT_TRUE(ValidatePageElement(frame, kScriptError, 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)); } // This test is flaky on all platforms; see http://crbug.com/340354 IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, DISABLED_RSSParseFeedValidFeed1) { 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, RSSParseFeedValidFeed2) { 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, RSSParseFeedValidFeed3) { 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, RSSParseFeedValidFeed4) { 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