diff options
author | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-26 00:32:11 +0000 |
---|---|---|
committer | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-26 00:32:11 +0000 |
commit | 61a523f378291307081d46277cca5dd087fb30ac (patch) | |
tree | 76a60b79fafd0f01c2e94b5740db63e88cd9ef99 /chrome/browser/resources | |
parent | 5bbf2884b6ff9466d95e3c6f177ebb7a39b70268 (diff) | |
download | chromium_src-61a523f378291307081d46277cca5dd087fb30ac.zip chromium_src-61a523f378291307081d46277cca5dd087fb30ac.tar.gz chromium_src-61a523f378291307081d46277cca5dd087fb30ac.tar.bz2 |
Add single line of tips to NNTP.
BUG= http://crbug.com/19162
TEST= Start browser with NNTP, note line of tips at bottom.
Review URL: http://codereview.chromium.org/173087
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24384 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resources')
-rw-r--r-- | chrome/browser/resources/new_new_tab.css | 7 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.html | 5 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.js | 98 | ||||
-rw-r--r-- | chrome/browser/resources/new_tab_theme.css | 7 |
4 files changed, 116 insertions, 1 deletions
diff --git a/chrome/browser/resources/new_new_tab.css b/chrome/browser/resources/new_new_tab.css index c2ce487..a2af6fb0 100644 --- a/chrome/browser/resources/new_new_tab.css +++ b/chrome/browser/resources/new_new_tab.css @@ -682,6 +682,13 @@ html[dir='rtl'] #t4 { top: 183px; } +/* tip line */ +#tip-line { + margin-top: 40px; + margin-bottom: 10px; + text-align: center; +} + /* small */ @media (max-width: 920px) { diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html index 9415d16..5266a88 100644 --- a/chrome/browser/resources/new_new_tab.html +++ b/chrome/browser/resources/new_new_tab.html @@ -35,11 +35,13 @@ function registerCallback(name) { chrome.send('getShownSections'); chrome.send('getMostVisited'); chrome.send('getRecentlyClosedTabs'); +chrome.send('getTips'); registerCallback('onShownSections'); registerCallback('mostVisitedPages'); registerCallback('recentlyClosedTabs'); registerCallback('syncMessageChanged'); +registerCallback('tips'); logEvent('log start'); @@ -223,6 +225,9 @@ document.write('<link id="themecss" rel="stylesheet" ' + <span><a href=""> </a></span> </div> + <div id="tip-line"> + </div> + <div id="attribution" class="attribution"> <span i18n-content="attributionintro"></span><br /> <img id="attribution-img" /> diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js index 78f7912..e9618a9 100644 --- a/chrome/browser/resources/new_new_tab.js +++ b/chrome/browser/resources/new_new_tab.js @@ -94,6 +94,31 @@ function mostVisitedPages(data, firstRun) { } } +var tipCache = {}; + +function tips(data) { + logEvent('received tips'); + tipCache = data; + renderTip(); +} + +function createTip(data) { + var parsedTips; + try { + parsedTips = parseHtmlSubset(data[0].tip_html_text); + } catch (parseErr) { + console.log('Error parsing tips: ' + parseErr.message); + } + return parsedTips; +} + +function renderTip() { + var tipElement = $('tip-line'); + // There should always be only one tip. + tipElement.textContent = ''; + tipElement.appendChild(createTip(tipCache)); +} + function recentlyClosedTabs(data) { logEvent('received recently closed tabs'); // We need to store the recent items so we can update the layout on a resize. @@ -1539,3 +1564,76 @@ var dnd = { }; dnd.init(); + +/** + * Whitelist of tag names allowed in parseHtmlSubset. + * @type {[string]} + * / +var allowedTags = ['A', 'B', 'STRONG']; + +/** + * Parse a very small subset of HTML. + * @param {string} s The string to parse. + * @throws {Error} In case of non supported markup. + * @return {DocumentFragment} A document fragment containing the DOM tree. + */ +var allowedAttributes = { + 'href': function(node, value) { + // Only allow a[href] starting with http:// and https:// + return node.tagName == 'A' && (value.indexOf('http://') == 0 || + value.indexOf('https://') == 0); + } +} + +/** + * Parse a very small subset of HTML. This ensures that insecure HTML / + * javascript cannot be injected into the new tab page. + * @param {string} s The string to parse. + * @throws {Error} In case of non supported markup. + * @return {DocumentFragment} A document fragment containing the DOM tree. + */ +function parseHtmlSubset(s) { + function walk(n, f) { + f(n); + for (var i = 0; i < n.childNodes.length; i++) { + walk(n.childNodes[i], f); + } + } + + function assertElement(node) { + if (allowedTags.indexOf(node.tagName) == -1) + throw Error(node.tagName + ' is not supported'); + } + + function assertAttribute(attrNode, node) { + var n = attrNode.nodeName; + var v = attrNode.nodeValue; + if (!allowedAttributes.hasOwnProperty(n) || !allowedAttributes[n](node, v)) + throw Error(node.tagName + '[' + n + '="' + v + '"] is not supported'); + } + + var r = document.createRange(); + r.selectNode(document.body); + // This does not execute any scripts. + var df = r.createContextualFragment(s); + walk(df, function(node) { + switch (node.nodeType) { + case Node.ELEMENT_NODE: + assertElement(node); + var attrs = node.attributes; + for (var i = 0; i < attrs.length; i++) { + assertAttribute(attrs[i], node); + } + break; + + case Node.COMMENT_NODE: + case Node.DOCUMENT_FRAGMENT_NODE: + case Node.TEXT_NODE: + break; + + default: + throw Error('Node type ' + node.nodeType + ' is not supported'); + } + }); + return df; +} diff --git a/chrome/browser/resources/new_tab_theme.css b/chrome/browser/resources/new_tab_theme.css index b59ef62c..e4547cd 100644 --- a/chrome/browser/resources/new_tab_theme.css +++ b/chrome/browser/resources/new_tab_theme.css @@ -56,7 +56,8 @@ body { } #recently-closed span, #recently-closed a, -#recently-closed a:link { +#recently-closed a:link, +#tip-line a { color: $$4; /* COLOR_NTP_SECTION_LINK */ text-decoration:underline; } @@ -66,3 +67,7 @@ body { color: $9; text-align:right; } + +#tip-line { + color: $$8; +} |