Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / test / data / extensions / subscribe_page_action / subscribe.js
1 // 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 // Grab the querystring, removing question mark at the front and splitting on
6 // the ampersand.
7 var queryString = location.search.substring(1).split("&");
8
9 // The feed URL is the first component and always present.
10 var feedUrl = decodeURIComponent(queryString[0]);
11
12 // This extension's ID.
13 var extension_id = chrome.i18n.getMessage("@@extension_id");
14
15 // During testing, we cannot load the iframe and stylesheet from an external
16 // source, so we allow loading them synchronously and stuff the frame with the
17 // results. Since this is only allowed during testing, it isn't supported for
18 // the official extension ID.
19 var synchronousRequest =
20     extension_id != "nlbjncdgjeocebhnmkbbbdekmmmcbfjd" ?
21         queryString[1] == "synchronous" : false;
22
23 // The XMLHttpRequest object that tries to load and parse the feed, and (if
24 // testing) also the style sheet and the frame js.
25 var req;
26
27 // Depending on whether this is run from a test or from the extension, this
28 // will either be a link to the css file within the extension or contain the
29 // contents of the style sheet, fetched through XmlHttpRequest.
30 var styleSheet = "";
31
32 // Depending on whether this is run from a test or from the extension, this
33 // will either be a link to the js file within the extension or contain the
34 // contents of the style sheet, fetched through XmlHttpRequest.
35 var frameScript = "";
36
37 // What to show when we cannot parse the feed name.
38 var unknownName = chrome.i18n.getMessage("rss_subscription_unknown_feed_name");
39
40 // A list of feed readers, populated by localStorage if available, otherwise
41 // hard coded.
42 var feedReaderList;
43
44 // The token to use during communications with the iframe.
45 var token = "";
46
47 // Navigates to the reader of the user's choice (for subscribing to the feed).
48 function navigate() {
49   var select = document.getElementById('readerDropdown');
50   var url =
51       feedReaderList[select.selectedIndex].url.replace(
52           "%s", encodeURIComponent(feedUrl));
53
54   // Before we navigate, see if we want to skip this step in the future...
55   if (storageEnabled) {
56     // See if the user wants to always use this reader.
57     var alwaysUse = document.getElementById('alwaysUse');
58     if (alwaysUse.checked) {
59       window.localStorage.defaultReader =
60           feedReaderList[select.selectedIndex].url;
61       window.localStorage.showPreviewPage = "No";
62     }
63   }
64
65   document.location = url;
66 }
67
68 /**
69 * The main function. Sets up the selection list for possible readers and
70 * fetches the data.
71 */
72 function main() {
73   if (storageEnabled && window.localStorage.readerList)
74       feedReaderList = JSON.parse(window.localStorage.readerList);
75   if (!feedReaderList)
76     feedReaderList = defaultReaderList();
77
78   // Populate the list of readers.
79   var readerDropdown = document.getElementById('readerDropdown');
80   for (i = 0; i < feedReaderList.length; ++i) {
81     readerDropdown.options[i] = new Option(feedReaderList[i].description, i);
82     if (storageEnabled && isDefaultReader(feedReaderList[i].url))
83       readerDropdown.selectedIndex = i;
84   }
85
86   if (storageEnabled) {
87     // Add the "Manage..." entry to the dropdown and show the checkbox asking
88     // if we always want to use this reader in the future (skip the preview).
89     readerDropdown.options[i] =
90         new Option(chrome.i18n.getMessage("rss_subscription_manage_label"), "");
91     document.getElementById('alwaysUseSpan').style.display = "block";
92   }
93
94   // Set the token.
95   var tokenArray  = new Uint32Array(4);
96   crypto.getRandomValues(tokenArray);
97   token = [].join.call(tokenArray);
98
99   // Now fetch the data.
100   req = new XMLHttpRequest();
101   if (synchronousRequest) {
102     // Tests that load the html page directly through a file:// url don't have
103     // access to the js and css from the frame so we must load them first and
104     // inject them into the src for the iframe.
105     req.open("GET", "style.css", false);
106     req.send(null);
107
108     styleSheet = "<style>" + req.responseText + "</style>";
109
110     req.open("GET", "iframe.js", false);
111     req.send(null);
112
113     if (req.responseText.indexOf('//') != -1) {
114       console.log('Error: Single-line comment(s) found in iframe.js');
115     } else {
116       frameScript = "<script>" +
117                     req.responseText +
118                     "<" + "/script>";
119     }
120   } else {
121     // Normal loading just requires links to the css and the js file.
122     styleSheet = "<link rel='stylesheet' type='text/css' href='" +
123                     chrome.extension.getURL("style.css") + "'>";
124     frameScript = "<script src='" + chrome.extension.getURL("iframe.js") +
125                   "'></" + "script>";
126   }
127
128   req.onload = handleResponse;
129   req.onerror = handleError;
130   req.open("GET", feedUrl, !synchronousRequest);
131   // Not everyone sets the mime type correctly, which causes handleResponse
132   // to fail to XML parse the response text from the server. By forcing
133   // it to text/xml we avoid this.
134   req.overrideMimeType('text/xml');
135   req.send(null);
136
137   document.getElementById('feedUrl').href = 'view-source:' + feedUrl;
138 }
139
140 // Sets the title for the feed.
141 function setFeedTitle(title) {
142   var titleTag = document.getElementById('title');
143   titleTag.textContent =
144       chrome.i18n.getMessage("rss_subscription_feed_for", title);
145 }
146
147 // Handles errors during the XMLHttpRequest.
148 function handleError() {
149   handleFeedParsingFailed(
150       chrome.i18n.getMessage("rss_subscription_error_fetching"));
151 }
152
153 // Handles feed parsing errors.
154 function handleFeedParsingFailed(error) {
155   setFeedTitle(unknownName);
156
157   // The tests always expect an IFRAME, so add one showing the error.
158   var html = "<body><span id=\"error\" class=\"item_desc\">" + error +
159                "</span></body>";
160
161   var error_frame = createFrame('error', html);
162   var itemsTag = document.getElementById('items');
163   itemsTag.appendChild(error_frame);
164 }
165
166 function createFrame(frame_id, html) {
167   // During testing, we stuff the iframe with the script directly, so we relax
168   // the policy on running scripts under that scenario.
169   var csp = synchronousRequest ?
170       '<meta http-equiv="content-security-policy" ' +
171           'content="object-src \'none\'">' :
172       '<meta http-equiv="content-security-policy" ' +
173           'content="object-src \'none\'; script-src \'self\'">';
174   frame = document.createElement('iframe');
175   frame.id = frame_id;
176   frame.src = "data:text/html;charset=utf-8,<html>" + csp +
177               "<!--Token:" + extension_id + token +
178               "-->" + html + "</html>";
179   frame.scrolling = "auto";
180   frame.frameBorder = "0";
181   frame.marginWidth = "0";
182   return frame;
183 }
184
185 // Handles parsing the feed data we got back from XMLHttpRequest.
186 function handleResponse() {
187   // Uncomment these three lines to see what the feed data looks like.
188   // var itemsTag = document.getElementById('items');
189   // itemsTag.textContent = req.responseText;
190   // return;
191
192   var doc = req.responseXML;
193   if (!doc) {
194     // If the XMLHttpRequest object fails to parse the feed we make an attempt
195     // ourselves, because sometimes feeds have html/script code appended below a
196     // valid feed, which makes the feed invalid as a whole even though it is
197     // still parsable.
198     var domParser = new DOMParser();
199     doc = domParser.parseFromString(req.responseText, "text/xml");
200     if (!doc) {
201       handleFeedParsingFailed(
202           chrome.i18n.getMessage("rss_subscription_not_valid_feed"));
203       return;
204     }
205   }
206
207   // We must find at least one 'entry' or 'item' element before proceeding.
208   var entries = doc.getElementsByTagName('entry');
209   if (entries.length == 0)
210     entries = doc.getElementsByTagName('item');
211   if (entries.length == 0) {
212     handleFeedParsingFailed(
213         chrome.i18n.getMessage("rss_subscription_no_entries"))
214     return;
215   }
216
217   // Figure out what the title of the whole feed is.
218   var title = doc.getElementsByTagName('title')[0];
219   if (title)
220     setFeedTitle(title.textContent);
221   else
222     setFeedTitle(unknownName);
223
224   // Embed the iframe.
225   var itemsTag = document.getElementById('items');
226   // TODO(aa): Add base URL tag
227   iframe = createFrame('rss', styleSheet + frameScript);
228   itemsTag.appendChild(iframe);
229 }
230
231 /**
232 * Handler for when selection changes.
233 */
234 function onSelectChanged() {
235   if (!storageEnabled)
236     return;
237   var readerDropdown = document.getElementById('readerDropdown');
238
239   // If the last item (Manage...) was selected we show the options.
240   var oldSelection = readerDropdown.selectedIndex;
241   if (readerDropdown.selectedIndex == readerDropdown.length - 1)
242     window.location = "options.html";
243 }
244
245 document.addEventListener('DOMContentLoaded', function () {
246   document.title =
247       chrome.i18n.getMessage("rss_subscription_default_title");
248   i18nReplace('rss_subscription_subscribe_using');
249   i18nReplace('rss_subscription_subscribe_button');
250   i18nReplace('rss_subscription_always_use');
251   i18nReplace('rss_subscription_feed_preview');
252   i18nReplaceImpl('feedUrl', 'rss_subscription_feed_link', '');
253
254   var dropdown = document.getElementById('readerDropdown');
255   dropdown.addEventListener('change', onSelectChanged);
256   var button = document.getElementById('rss_subscription_subscribe_button');
257   button.addEventListener('click', navigate);
258
259   main();
260 });
261
262 window.addEventListener("message", function(e) {
263   if (e.ports[0] && e.data === token)
264     e.ports[0].postMessage(req.responseText);
265 }, false);