blob: 454742d421431f7345c78b03a47796eae1b50bc0 [file] [log] [blame]
[email protected]fad73672012-06-15 23:26:061// Copyright (c) 2012 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 "chrome/browser/extensions/extension_browsertest.h"
6#include "chrome/browser/ui/browser.h"
7#include "chrome/common/extensions/extension.h"
8#include "chrome/common/url_constants.h"
9#include "chrome/test/base/ui_test_utils.h"
10#include "content/public/browser/web_contents.h"
11
12using content::WebContents;
13using extensions::Extension;
14
15namespace {
16
17const std::string kSubscribePage = "/subscribe.html";
18const std::string kFeedPageMultiRel = "files/feeds/feed_multi_rel.html";
19const std::string kValidFeedNoLinks = "files/feeds/feed_nolinks.xml";
20const std::string kValidFeed0 = "files/feeds/feed_script.xml";
21const std::string kValidFeed1 = "files/feeds/feed1.xml";
22const std::string kValidFeed2 = "files/feeds/feed2.xml";
23const std::string kValidFeed3 = "files/feeds/feed3.xml";
24const std::string kValidFeed4 = "files/feeds/feed4.xml";
25const std::string kValidFeed5 = "files/feeds/feed5.xml";
26const std::string kValidFeed6 = "files/feeds/feed6.xml";
27const std::string kInvalidFeed1 = "files/feeds/feed_invalid1.xml";
28const std::string kInvalidFeed2 = "files/feeds/feed_invalid2.xml";
29// We need a triple encoded string to prove that we are not decoding twice in
30// subscribe.js because one layer is also stripped off when subscribe.js passes
31// it to the XMLHttpRequest object.
32const std::string kFeedTripleEncoded = "files/feeds/url%25255Fdecoding.html";
33
34static const wchar_t* jscript_feed_title =
35 L"window.domAutomationController.send("
36 L" document.getElementById('title') ? "
37 L" document.getElementById('title').textContent : "
38 L" \"element 'title' not found\""
39 L");";
40static const wchar_t* jscript_anchor =
41 L"window.domAutomationController.send("
42 L" document.getElementById('anchor_0') ? "
43 L" document.getElementById('anchor_0').textContent : "
44 L" \"element 'anchor_0' not found\""
45 L");";
46static const wchar_t* jscript_desc =
47 L"window.domAutomationController.send("
48 L" document.getElementById('desc_0') ? "
49 L" document.getElementById('desc_0').textContent : "
50 L" \"element 'desc_0' not found\""
51 L");";
52static const wchar_t* jscript_error =
53 L"window.domAutomationController.send("
54 L" document.getElementById('error') ? "
55 L" document.getElementById('error').textContent : "
56 L" \"No error\""
57 L");";
58
59GURL GetFeedUrl(net::TestServer* server, const std::string& feed_page,
60 bool direct_url, std::string extension_id) {
61 GURL feed_url = server->GetURL(feed_page);
62 if (direct_url) {
63 // We navigate directly to the subscribe page for feeds where the feed
64 // sniffing won't work, in other words, as is the case for malformed feeds.
65 return GURL(std::string(chrome::kExtensionScheme) +
66 content::kStandardSchemeSeparator +
67 extension_id + std::string(kSubscribePage) + std::string("?") +
68 feed_url.spec() + std::string("&synchronous"));
69 } else {
70 // Navigate to the feed content (which will cause the extension to try to
71 // sniff the type and display the subscribe page in another tab.
72 return GURL(feed_url.spec());
73 }
74}
75
76bool ValidatePageElement(WebContents* tab,
77 const std::wstring& frame,
78 const std::wstring& javascript,
79 const std::string& expected_value) {
80 std::string returned_value;
81 std::string error;
82
83 if (!ui_test_utils::ExecuteJavaScriptAndExtractString(
84 tab->GetRenderViewHost(),
85 frame,
86 javascript, &returned_value))
87 return false;
88
89 EXPECT_STREQ(expected_value.c_str(), returned_value.c_str());
90 return expected_value == returned_value;
91}
92
93// Navigates to a feed page and, if |sniff_xml_type| is set, wait for the
94// extension to kick in, detect the feed and redirect to a feed preview page.
95// |sniff_xml_type| is generally set to true if the feed is sniffable and false
96// for invalid feeds.
97void NavigateToFeedAndValidate(net::TestServer* server,
98 const std::string& url,
99 Browser* browser,
100 std::string extension_id,
101 bool sniff_xml_type,
102 const std::string& expected_feed_title,
103 const std::string& expected_item_title,
104 const std::string& expected_item_desc,
105 const std::string& expected_error) {
106 if (sniff_xml_type) {
107 // TODO(finnur): Implement this is a non-flaky way.
108 }
109
110 // Navigate to the subscribe page directly.
111 ui_test_utils::NavigateToURL(browser,
112 GetFeedUrl(server, url, true, extension_id));
113
114 WebContents* tab = browser->GetActiveWebContents();
115 ASSERT_TRUE(ValidatePageElement(tab,
116 L"",
117 jscript_feed_title,
118 expected_feed_title));
119 ASSERT_TRUE(ValidatePageElement(tab,
120 L"//html/body/div/iframe[1]",
121 jscript_anchor,
122 expected_item_title));
123 ASSERT_TRUE(ValidatePageElement(tab,
124 L"//html/body/div/iframe[1]",
125 jscript_desc,
126 expected_item_desc));
127 ASSERT_TRUE(ValidatePageElement(tab,
128 L"//html/body/div/iframe[1]",
129 jscript_error,
130 expected_error));
131}
132
133} // namespace
134
135// Makes sure that the RSS detects RSS feed links, even when rel tag contains
136// more than just "alternate".
137IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, RSSMultiRelLink) {
138 ASSERT_TRUE(test_server()->Start());
139
140 ASSERT_TRUE(LoadExtension(
141 test_data_dir_.AppendASCII("subscribe_page_action")));
142
143 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(0));
144
145 // Navigate to the feed page.
146 GURL feed_url = test_server()->GetURL(kFeedPageMultiRel);
147 ui_test_utils::NavigateToURL(browser(), feed_url);
148 // We should now have one page action ready to go in the LocationBar.
149 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
150}
151
152IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed1) {
153 ASSERT_TRUE(test_server()->Start());
154
155 const Extension* extension = LoadExtension(
156 test_data_dir_.AppendASCII("subscribe_page_action"));
157 ASSERT_TRUE(extension);
158 std::string id = extension->id();
159
160 NavigateToFeedAndValidate(test_server(), kValidFeed1, browser(), id, true,
161 "Feed for MyFeedTitle",
162 "Title 1",
163 "Desc",
164 "No error");
165}
166
167IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed2) {
168 ASSERT_TRUE(test_server()->Start());
169
170 const Extension* extension = LoadExtension(
171 test_data_dir_.AppendASCII("subscribe_page_action"));
172 ASSERT_TRUE(extension);
173 std::string id = extension->id();
174
175 NavigateToFeedAndValidate(test_server(), kValidFeed2, browser(), id, true,
176 "Feed for MyFeed2",
177 "My item title1",
178 "This is a summary.",
179 "No error");
180}
181
182IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed3) {
183 ASSERT_TRUE(test_server()->Start());
184
185 const Extension* extension = LoadExtension(
186 test_data_dir_.AppendASCII("subscribe_page_action"));
187 ASSERT_TRUE(extension);
188 std::string id = extension->id();
189
190 NavigateToFeedAndValidate(test_server(), kValidFeed3, browser(), id, true,
191 "Feed for Google Code buglist rss feed",
192 "My dear title",
193 "My dear content",
194 "No error");
195}
196
197IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed4) {
198 ASSERT_TRUE(test_server()->Start());
199
200 const Extension* extension = LoadExtension(
201 test_data_dir_.AppendASCII("subscribe_page_action"));
202 ASSERT_TRUE(extension);
203 std::string id = extension->id();
204
205 NavigateToFeedAndValidate(test_server(), kValidFeed4, browser(), id, true,
206 "Feed for Title chars <script> %23 stop",
207 "Title chars %23 stop",
208 "My dear content %23 stop",
209 "No error");
210}
211
212IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed0) {
213 ASSERT_TRUE(test_server()->Start());
214
215 const Extension* extension = LoadExtension(
216 test_data_dir_.AppendASCII("subscribe_page_action"));
217 ASSERT_TRUE(extension);
218 std::string id = extension->id();
219
220 // Try a feed with a link with an onclick handler (before r27440 this would
221 // trigger a NOTREACHED).
222 NavigateToFeedAndValidate(test_server(), kValidFeed0, browser(), id, true,
223 "Feed for MyFeedTitle",
224 "Title 1",
225 "Desc VIDEO",
226 "No error");
227}
228
229IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed5) {
230 ASSERT_TRUE(test_server()->Start());
231
232 const Extension* extension = LoadExtension(
233 test_data_dir_.AppendASCII("subscribe_page_action"));
234 ASSERT_TRUE(extension);
235 std::string id = extension->id();
236
237 // Feed with valid but mostly empty xml.
238 NavigateToFeedAndValidate(test_server(), kValidFeed5, browser(), id, true,
239 "Feed for Unknown feed name",
240 "element 'anchor_0' not found",
241 "element 'desc_0' not found",
242 "This feed contains no entries.");
243}
244
245IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed6) {
246 ASSERT_TRUE(test_server()->Start());
247
248 const Extension* extension = LoadExtension(
249 test_data_dir_.AppendASCII("subscribe_page_action"));
250 ASSERT_TRUE(extension);
251 std::string id = extension->id();
252
253 // Feed that is technically invalid but still parseable.
254 NavigateToFeedAndValidate(test_server(), kValidFeed6, browser(), id, true,
255 "Feed for MyFeedTitle",
256 "Title 1",
257 "Desc",
258 "No error");
259}
260
261IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedInvalidFeed1) {
262 ASSERT_TRUE(test_server()->Start());
263
264 const Extension* extension = LoadExtension(
265 test_data_dir_.AppendASCII("subscribe_page_action"));
266 ASSERT_TRUE(extension);
267 std::string id = extension->id();
268
269 // Try an empty feed.
270 NavigateToFeedAndValidate(test_server(), kInvalidFeed1, browser(), id, false,
271 "Feed for Unknown feed name",
272 "element 'anchor_0' not found",
273 "element 'desc_0' not found",
274 "This feed contains no entries.");
275}
276
277IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedInvalidFeed2) {
278 ASSERT_TRUE(test_server()->Start());
279
280 const Extension* extension = LoadExtension(
281 test_data_dir_.AppendASCII("subscribe_page_action"));
282 ASSERT_TRUE(extension);
283 std::string id = extension->id();
284
285 // Try a garbage feed.
286 NavigateToFeedAndValidate(test_server(), kInvalidFeed2, browser(), id, false,
287 "Feed for Unknown feed name",
288 "element 'anchor_0' not found",
289 "element 'desc_0' not found",
290 "This feed contains no entries.");
291}
292
293IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedInvalidFeed3) {
294 ASSERT_TRUE(test_server()->Start());
295
296 const Extension* extension = LoadExtension(
297 test_data_dir_.AppendASCII("subscribe_page_action"));
298 ASSERT_TRUE(extension);
299 std::string id = extension->id();
300
301 // Try a feed that doesn't exist.
302 NavigateToFeedAndValidate(test_server(), "foo.xml", browser(), id, false,
303 "Feed for Unknown feed name",
304 "element 'anchor_0' not found",
305 "element 'desc_0' not found",
306 "This feed contains no entries.");
307}
308
309IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedInvalidFeed4) {
310 ASSERT_TRUE(test_server()->Start());
311
312 const Extension* extension = LoadExtension(
313 test_data_dir_.AppendASCII("subscribe_page_action"));
314 ASSERT_TRUE(extension);
315 std::string id = extension->id();
316
317 // subscribe.js shouldn't double-decode the URL passed in. Otherwise feed
318 // links such as http://search.twitter.com/search.atom?lang=en&q=%23chrome
319 // will result in no feed being downloaded because %23 gets decoded to # and
320 // therefore #chrome is not treated as part of the Twitter query. This test
321 // uses an underscore instead of a hash, but the principle is the same. If
322 // we start erroneously double decoding again, the path (and the feed) will
323 // become valid resulting in a failure for this test.
324 NavigateToFeedAndValidate(
325 test_server(), kFeedTripleEncoded, browser(), id, true,
326 "Feed for Unknown feed name",
327 "element 'anchor_0' not found",
328 "element 'desc_0' not found",
329 "This feed contains no entries.");
330}
331
332IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeedNoLinks) {
333 ASSERT_TRUE(test_server()->Start());
334
335 const Extension* extension = LoadExtension(
336 test_data_dir_.AppendASCII("subscribe_page_action"));
337 ASSERT_TRUE(extension);
338 std::string id = extension->id();
339
340 // Valid feed but containing no links.
341 NavigateToFeedAndValidate(
342 test_server(), kValidFeedNoLinks, browser(), id, true,
343 "Feed for MyFeedTitle",
344 "Title with no link",
345 "Desc",
346 "No error");
347}