make google news samples functional (#855)
* update old google news samples Co-authored-by: Joe Medley <jmedley@google.com>
This commit is contained in:
Родитель
4baa57bd47
Коммит
7b5d882159
|
@ -0,0 +1,7 @@
|
|||
# News
|
||||
|
||||
This sample demonstrates a popup panel that access a remote URL. In this case, we are the Google News RSS feed, and building a UI to display that information.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Note that this is a _very_ old example, and is kept here purely for archival purposes. We do not recommend using this as a base of a new extension.
|
|
@ -209,8 +209,7 @@ function buildPreview(doc) {
|
|||
// The story body is created as an iframe with a data: URL in order to
|
||||
// isolate it from this page and protect against XSS. As a data URL, it
|
||||
// has limited privileges and must communicate back using postMessage().
|
||||
desc.src = 'data:text/html;charset=utf-8,' + iframe_src + itemDesc +
|
||||
'</body></html>';
|
||||
desc.src = 'data:text/html;charset=utf-8,' + btoa(unescape(encodeURIComponent(iframe_src + itemDesc + '</body></html>')));
|
||||
}
|
||||
if (moreStoriesUrl && entries.length != 0) {
|
||||
var more = document.createElement('a');
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# News (accessibility)
|
||||
|
||||
This sample demonstrates a popup panel that access a remote URL. In this case, we are the Google News RSS feed, and building a UI to display that information. The UI here was built in a way to be particularly mindful of accessibility, and is fully navigable by a keyboard.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Note that this is a _very_ old example, and is kept here purely for archival purposes. We do not recommend using this as a base of a new extension.
|
|
@ -3,7 +3,7 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
// Feed
|
||||
var feedUrl = 'http://news.google.com/?output=rss';
|
||||
var feedUrl = 'https://news.google.com/?output=rss';
|
||||
|
||||
// The XMLHttpRequest object that tries to load and parse the feed.
|
||||
var req;
|
||||
|
@ -79,11 +79,11 @@ function buildPreview(doc) {
|
|||
}
|
||||
|
||||
// Construct the iframe's HTML.
|
||||
var iframe_src = '<!doctype html><html><head><script ' +
|
||||
'src="chrome-extension://ldglnfnokeifbcaeppacaejckagballg/' +
|
||||
'feed_iframe.js"><' + '/script><link href="chrome-extension://ldglnf' +
|
||||
'nokeifbcaeppacaejckagballg/feed_iframe.css" rel="stylesheet" ' +
|
||||
'type="text/css"></head><body>';
|
||||
var iframe_src = `<!doctype html><html><head><title>f</title>
|
||||
<script src="${chrome.runtime.getURL('/feed_iframe.js')}"></script>
|
||||
<link href="${chrome.runtime.getURL('/feed_iframe.css')} rel="stylesheet" type="text/css">
|
||||
</head><body>`;
|
||||
|
||||
|
||||
var feed = document.getElementById('feed');
|
||||
// Set ARIA role indicating the feed element has a tree structure
|
||||
|
@ -159,11 +159,10 @@ function buildPreview(doc) {
|
|||
// Disable keyboard focus on elements in iFrames that have not been
|
||||
// displayed yet
|
||||
desc.tabIndex = -1;
|
||||
|
||||
// The story body is created as an iframe with a data: URL in order to
|
||||
// isolate it from this page and protect against XSS. As a data URL, it
|
||||
// has limited privileges and must communicate back using postMessage().
|
||||
desc.src='data:text/html,' + iframe_src + itemDesc + '</body></html>';
|
||||
desc.src=`data:text/html,${iframe_src}${itemDesc.replace(/#/g,"")}</body></html>`;
|
||||
|
||||
item.appendChild(desc);
|
||||
feed.appendChild(item);
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
},
|
||||
"permissions": [
|
||||
"tabs",
|
||||
"http://news.google.com/*"
|
||||
"https://news.google.com/*"
|
||||
],
|
||||
"manifest_version": 2,
|
||||
"content_security_policy": "img-src 'self' http://* https://*; script-src 'self'; connect-src http://news.google.com; frame-src data:"
|
||||
"content_security_policy": "default-src; img-src 'self' http://* https://*; script-src 'self'; connect-src http://news.google.com; frame-src data:"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# News (i18n)
|
||||
|
||||
This sample demonstrates a popup panel that access a remote URL. In this case, we are the Google News RSS feed, and building a UI to display that information. Additionally, this sample was built for multiple languages, to demonstrate how to support multiple languages within one extension.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Note that this is a _very_ old example, and is kept here purely for archival purposes. We do not recommend using this as a base of a new extension.
|
|
@ -56,7 +56,7 @@
|
|||
}
|
||||
},
|
||||
"newsUrl": {
|
||||
"message": "http://news.google.com",
|
||||
"message": "https://news.google.com",
|
||||
"description": "Url to Google News."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": {
|
||||
"message": "Lector de noticias",
|
||||
"description": "Nombre de la extensión en el manifiesto."
|
||||
"description": "Nombre de la extensi\xC3\xB3n en el manifiesto."
|
||||
},
|
||||
"description": {
|
||||
"message": "Muestra los primeros 5 eventos de '$Google$ noticias - destacados' RSS feed en una ventana.",
|
||||
"description": "Descripción de la extensión en el manifiesto.",
|
||||
"description": "Descripci\xC3\xB3n de la extensi\xC3\xB3n en el manifiesto.",
|
||||
"placeholders": {
|
||||
"google": {
|
||||
"content": "Google",
|
||||
|
@ -15,7 +15,7 @@
|
|||
},
|
||||
"default_title": {
|
||||
"message": "$Google$ noticias",
|
||||
"description": "Texto de la accion de menú de la extension en el manifiesto.",
|
||||
"description": "Texto de la accion de men\xC3\xBA de la extension en el manifiesto.",
|
||||
"placeholders": {
|
||||
"google": {
|
||||
"content": "Google",
|
||||
|
@ -24,12 +24,12 @@
|
|||
}
|
||||
},
|
||||
"unknown_title": {
|
||||
"message": "Título desconocido",
|
||||
"description": "Noticia con título desconocido."
|
||||
"message": "T\xC3\xADtulo desconocido",
|
||||
"description": "Noticia con t\xC3\xADtulo desconocido."
|
||||
},
|
||||
"error": {
|
||||
"message": "Error: $error$",
|
||||
"description": "Plantilla de error genérico. Hace falta pasar un parámetro de error.",
|
||||
"description": "Plantilla de error gen\xC3\xA9rico. Hace falta pasar un par\xC3\xA1metro de error.",
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"content": "$1",
|
||||
|
@ -42,7 +42,7 @@
|
|||
"description": "Mensaje de error visible para el usuario."
|
||||
},
|
||||
"not_a_valid_feed": {
|
||||
"message": "Feed no válido.",
|
||||
"message": "Feed no v\xC3\xA1lido.",
|
||||
"description": "Mensaje de error visible para el usuario."
|
||||
},
|
||||
"more_stories": {
|
||||
|
@ -56,8 +56,8 @@
|
|||
}
|
||||
},
|
||||
"newsUrl": {
|
||||
"message": "http://news.google.es",
|
||||
"description": "Dirección de Google News."
|
||||
"message": "https://news.google.es",
|
||||
"description": "Direcci\xC3\xB3n de Google News."
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
body {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
color:#0000CC;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.open_box {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin-right: 4px;
|
||||
margin-top: 2px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
float: left;
|
||||
clear: left;
|
||||
background-image: url(sprite_arrows.gif);
|
||||
background-position: 0px -24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.opened .open_box {
|
||||
background-position:-12px -24px;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 2px 0px;
|
||||
}
|
||||
|
||||
.item_title {
|
||||
display: block;
|
||||
min-width: 300px;
|
||||
padding-left: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item_desc {
|
||||
min-width: 500px;
|
||||
height: 0px;
|
||||
display: block;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
transition: height 0.2s ease-out;
|
||||
}
|
||||
|
||||
#title {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.error {
|
||||
white-space: nowrap;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.more {
|
||||
display: block;
|
||||
text-align: right;
|
||||
padding-top: 20px;
|
||||
padding-right: 10px;
|
||||
color: #88C;
|
||||
}
|
||||
|
|
@ -1,309 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
font-family: helvetica, arial, sans-serif;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
color:#0000CC;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.open_box {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin-right: 4px;
|
||||
margin-top: 2px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
float: left;
|
||||
clear: left;
|
||||
background-image: url(sprite_arrows.gif);
|
||||
background-position: 0px -24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.opened .open_box {
|
||||
background-position:-12px -24px;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 2px 0px;
|
||||
}
|
||||
|
||||
.item_title {
|
||||
display: block;
|
||||
min-width: 300px;
|
||||
padding-left: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item_desc {
|
||||
min-width: 500px;
|
||||
height: 0px;
|
||||
display: block;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
transition: height 0.2s ease-out;
|
||||
}
|
||||
|
||||
#title {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.error {
|
||||
white-space: nowrap;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.more {
|
||||
display: block;
|
||||
text-align: right;
|
||||
padding-top: 20px;
|
||||
padding-right: 10px;
|
||||
color: #88C;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script id="iframe_script">
|
||||
function reportHeight() {
|
||||
var msg = JSON.stringify({type:"size", size:document.body.offsetHeight});
|
||||
parent.postMessage(msg, "*");
|
||||
}
|
||||
|
||||
function frameLoaded() {
|
||||
var links = document.getElementsByTagName("A");
|
||||
for (i = 0; i < links.length; i++) {
|
||||
var class = links[i].className;
|
||||
if (class != "item_title" && class != "open_box") {
|
||||
links[i].addEventListener("click", showStory);
|
||||
}
|
||||
}
|
||||
window.addEventListener("message", messageHandler);
|
||||
}
|
||||
|
||||
function showStory(event) {
|
||||
var href = event.currentTarget.href;
|
||||
parent.postMessage(JSON.stringify({type:"show", url:href}), "*");
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function messageHandler(event) {
|
||||
reportHeight();
|
||||
}
|
||||
|
||||
</script>
|
||||
<script>
|
||||
// Feed URL.
|
||||
var feedUrl = chrome.i18n.getMessage('newsUrl') + '/?output=rss';
|
||||
|
||||
// The XMLHttpRequest object that tries to load and parse the feed.
|
||||
var req;
|
||||
|
||||
function main() {
|
||||
req = new XMLHttpRequest();
|
||||
req.onload = handleResponse;
|
||||
req.onerror = handleError;
|
||||
req.open("GET", feedUrl, true);
|
||||
req.send(null);
|
||||
}
|
||||
|
||||
// Handles feed parsing errors.
|
||||
function handleFeedParsingFailed(error) {
|
||||
var feed = document.getElementById("feed");
|
||||
feed.className = "error";
|
||||
feed.innerText = chrome.i18n.getMessage("error", error);
|
||||
}
|
||||
|
||||
// Handles errors during the XMLHttpRequest.
|
||||
function handleError() {
|
||||
handleFeedParsingFailed(chrome.i18n.getMessage('failed_to_fetch_rss'));
|
||||
}
|
||||
|
||||
// Handles parsing the feed data we got back from XMLHttpRequest.
|
||||
function handleResponse() {
|
||||
var doc = req.responseXML;
|
||||
if (!doc) {
|
||||
handleFeedParsingFailed(chrome.i18n.getMessage('not_a_valid_feed'));
|
||||
return;
|
||||
}
|
||||
buildPreview(doc);
|
||||
}
|
||||
|
||||
// The maximum number of feed items to show in the preview.
|
||||
var maxFeedItems = 5;
|
||||
|
||||
// Where the more stories link should navigate to.
|
||||
var moreStoriesUrl;
|
||||
|
||||
function buildPreview(doc) {
|
||||
// Get the link to the feed source.
|
||||
var link = doc.getElementsByTagName("link");
|
||||
var parentTag = link[0].parentNode.tagName;
|
||||
if (parentTag != "item" && parentTag != "entry") {
|
||||
moreStoriesUrl = link[0].textContent;
|
||||
}
|
||||
|
||||
// Setup the title image.
|
||||
var images = doc.getElementsByTagName("image");
|
||||
var titleImg;
|
||||
if (images.length != 0) {
|
||||
var urls = images[0].getElementsByTagName("url");
|
||||
if (urls.length != 0) {
|
||||
titleImg = urls[0].textContent;
|
||||
}
|
||||
}
|
||||
var img = document.getElementById("title");
|
||||
if (titleImg) {
|
||||
img.src = titleImg;
|
||||
if (moreStoriesUrl) {
|
||||
document.getElementById("title_a").addEventListener("click", moreStories);
|
||||
}
|
||||
} else {
|
||||
img.style.display = "none";
|
||||
}
|
||||
|
||||
// Construct the iframe's HTML.
|
||||
var iframe_src = "<!doctype html><html><head><script>" +
|
||||
document.getElementById("iframe_script").textContent + "<" +
|
||||
"/script></head><body onload='frameLoaded();' " +
|
||||
"style='padding:0px;margin:0px;'>";
|
||||
|
||||
var feed = document.getElementById("feed");
|
||||
var entries = doc.getElementsByTagName('entry');
|
||||
if (entries.length == 0) {
|
||||
entries = doc.getElementsByTagName('item');
|
||||
}
|
||||
var count = Math.min(entries.length, maxFeedItems);
|
||||
for (var i = 0; i < count; i++) {
|
||||
item = entries.item(i);
|
||||
|
||||
// Grab the title for the feed item.
|
||||
var itemTitle = item.getElementsByTagName('title')[0];
|
||||
if (itemTitle) {
|
||||
itemTitle = itemTitle.textContent;
|
||||
} else {
|
||||
itemTitle = chrome.i18n.getMessage("unknown_title");
|
||||
}
|
||||
|
||||
// Grab the description.
|
||||
var itemDesc = item.getElementsByTagName('description')[0];
|
||||
if (!itemDesc) {
|
||||
itemDesc = item.getElementsByTagName('summary')[0];
|
||||
if (!itemDesc) {
|
||||
itemDesc = item.getElementsByTagName('content')[0];
|
||||
}
|
||||
}
|
||||
if (itemDesc) {
|
||||
itemDesc = itemDesc.childNodes[0].nodeValue;
|
||||
} else {
|
||||
itemDesc = '';
|
||||
}
|
||||
|
||||
var item = document.createElement("div");
|
||||
item.className = "item";
|
||||
var box = document.createElement("div");
|
||||
box.className = "open_box";
|
||||
box.addEventListener("click", showDesc);
|
||||
item.appendChild(box);
|
||||
|
||||
var title = document.createElement("a");
|
||||
title.className = "item_title";
|
||||
title.innerText = itemTitle;
|
||||
title.addEventListener("click", showDesc);
|
||||
item.appendChild(title);
|
||||
|
||||
var desc = document.createElement("iframe");
|
||||
desc.scrolling = "no";
|
||||
desc.className = "item_desc";
|
||||
item.appendChild(desc);
|
||||
feed.appendChild(item);
|
||||
|
||||
// The story body is created as an iframe with a data: URL in order to
|
||||
// isolate it from this page and protect against XSS. As a data URL, it
|
||||
// has limited privileges and must communicate back using postMessage().
|
||||
desc.src="data:text/html," + iframe_src + itemDesc + "</body></html>";
|
||||
}
|
||||
|
||||
if (moreStoriesUrl) {
|
||||
var more = document.createElement("a");
|
||||
more.className = "more";
|
||||
more.innerText = chrome.i18n.getMessage("more_stories");
|
||||
more.addEventListener("click", moreStories);
|
||||
feed.appendChild(more);
|
||||
}
|
||||
}
|
||||
|
||||
// Show |url| in a new tab.
|
||||
function showUrl(url) {
|
||||
// Only allow http and https URLs.
|
||||
if (url.indexOf("http:") != 0 && url.indexOf("https:") != 0) {
|
||||
return;
|
||||
}
|
||||
chrome.tabs.create({url: url});
|
||||
}
|
||||
|
||||
function moreStories(event) {
|
||||
showUrl(moreStoriesUrl);
|
||||
}
|
||||
|
||||
function showDesc(event) {
|
||||
var item = event.currentTarget.parentNode;
|
||||
var items = document.getElementsByClassName("item");
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var iframe = items[i].getElementsByClassName("item_desc")[0];
|
||||
if (items[i] == item && items[i].className == "item") {
|
||||
items[i].className = "item opened";
|
||||
iframe.contentWindow.postMessage("reportHeight", "*");
|
||||
} else {
|
||||
items[i].className = "item";
|
||||
iframe.style.height = "0px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function iframeMessageHandler(e) {
|
||||
// Only listen to messages from one of our own iframes.
|
||||
var iframes = document.getElementsByTagName("IFRAME");
|
||||
for (var i = 0; i < iframes.length; i++) {
|
||||
if (iframes[i].contentWindow == e.source) {
|
||||
var msg = JSON.parse(e.data);
|
||||
if (msg) {
|
||||
if (msg.type == "size") {
|
||||
iframes[i].style.height = msg.size + "px";
|
||||
} else if (msg.type == "show") {
|
||||
var url = msg.url;
|
||||
if (url.indexOf(chrome.i18n.getMessage('newsUrl')) == 0) {
|
||||
// If the URL is a redirect URL, strip of the destination and go to
|
||||
// that directly. This is necessary because the Google news
|
||||
// redirector blocks use of the redirects in this case.
|
||||
var index = url.indexOf("&url=");
|
||||
if (index >= 0) {
|
||||
url = url.substring(index + 5);
|
||||
index = url.indexOf("&");
|
||||
if (index >= 0)
|
||||
url = url.substring(0, index);
|
||||
}
|
||||
}
|
||||
showUrl(url);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("message", iframeMessageHandler);
|
||||
</script>
|
||||
<head>
|
||||
<link rel="stylesheet" href="./feed.css" />
|
||||
<script id="iframe_script" src="./feed.js"></script>
|
||||
</head>
|
||||
<body onload="main();">
|
||||
<body>
|
||||
<a id="title_a"><img id='title'></a>
|
||||
<div id="feed"></div>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
function reportHeight() {
|
||||
var msg = JSON.stringify({type:"size", size:document.body.offsetHeight});
|
||||
parent.postMessage(msg, "*");
|
||||
}
|
||||
|
||||
function frameLoaded() {
|
||||
var links = document.getElementsByTagName("A");
|
||||
for (i = 0; i < links.length; i++) {
|
||||
var klass = links[i].klassName;
|
||||
if (klass != "item_title" && klass != "open_box") {
|
||||
links[i].addEventListener("click", showStory);
|
||||
}
|
||||
}
|
||||
window.addEventListener("message", messageHandler);
|
||||
}
|
||||
|
||||
function showStory(event) {
|
||||
var href = event.currentTarget.href;
|
||||
parent.postMessage(JSON.stringify({type:"show", url:href}), "*");
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
function messageHandler(event) {
|
||||
reportHeight();
|
||||
}
|
||||
|
||||
// Feed URL.
|
||||
var feedUrl = chrome.i18n.getMessage('newsUrl') + '/?output=rss';
|
||||
|
||||
// The XMLHttpRequest object that tries to load and parse the feed.
|
||||
var req;
|
||||
|
||||
function main() {
|
||||
req = new XMLHttpRequest();
|
||||
req.onload = handleResponse;
|
||||
req.onerror = handleError;
|
||||
req.open("GET", feedUrl, true);
|
||||
req.send(null);
|
||||
}
|
||||
|
||||
// Handles feed parsing errors.
|
||||
function handleFeedParsingFailed(error) {
|
||||
var feed = document.getElementById("feed");
|
||||
feed.klassName = "error";
|
||||
feed.innerText = chrome.i18n.getMessage("error", error);
|
||||
}
|
||||
|
||||
// Handles errors during the XMLHttpRequest.
|
||||
function handleError() {
|
||||
handleFeedParsingFailed(chrome.i18n.getMessage('failed_to_fetch_rss'));
|
||||
}
|
||||
|
||||
// Handles parsing the feed data we got back from XMLHttpRequest.
|
||||
function handleResponse() {
|
||||
var doc = req.responseXML;
|
||||
if (!doc) {
|
||||
handleFeedParsingFailed(chrome.i18n.getMessage('not_a_valid_feed'));
|
||||
return;
|
||||
}
|
||||
buildPreview(doc);
|
||||
}
|
||||
|
||||
// The maximum number of feed items to show in the preview.
|
||||
var maxFeedItems = 5;
|
||||
|
||||
// Where the more stories link should navigate to.
|
||||
var moreStoriesUrl;
|
||||
|
||||
function buildPreview(doc) {
|
||||
// Get the link to the feed source.
|
||||
var link = doc.getElementsByTagName("link");
|
||||
var parentTag = link[0].parentNode.tagName;
|
||||
if (parentTag != "item" && parentTag != "entry") {
|
||||
moreStoriesUrl = link[0].textContent;
|
||||
}
|
||||
|
||||
// Setup the title image.
|
||||
var images = doc.getElementsByTagName("image");
|
||||
var titleImg;
|
||||
if (images.length != 0) {
|
||||
var urls = images[0].getElementsByTagName("url");
|
||||
if (urls.length != 0) {
|
||||
titleImg = urls[0].textContent;
|
||||
}
|
||||
}
|
||||
var img = document.getElementById("title");
|
||||
if (titleImg) {
|
||||
img.src = titleImg;
|
||||
if (moreStoriesUrl) {
|
||||
document.getElementById("title_a").addEventListener("click", moreStories);
|
||||
}
|
||||
} else {
|
||||
img.style.display = "none";
|
||||
}
|
||||
|
||||
// Construct the iframe's HTML.
|
||||
var iframe_src = "<!doctype html><html><head><script>" +
|
||||
document.getElementById("iframe_script").textContent + "<" +
|
||||
"/script></head><body onload='frameLoaded();' " +
|
||||
"style='padding:0px;margin:0px;'>";
|
||||
|
||||
var feed = document.getElementById("feed");
|
||||
var entries = doc.getElementsByTagName('entry');
|
||||
if (entries.length == 0) {
|
||||
entries = doc.getElementsByTagName('item');
|
||||
}
|
||||
var count = Math.min(entries.length, maxFeedItems);
|
||||
for (var i = 0; i < count; i++) {
|
||||
item = entries.item(i);
|
||||
|
||||
// Grab the title for the feed item.
|
||||
var itemTitle = item.getElementsByTagName('title')[0];
|
||||
if (itemTitle) {
|
||||
itemTitle = itemTitle.textContent;
|
||||
} else {
|
||||
itemTitle = chrome.i18n.getMessage("unknown_title");
|
||||
}
|
||||
|
||||
// Grab the description.
|
||||
var itemDesc = item.getElementsByTagName('description')[0];
|
||||
if (!itemDesc) {
|
||||
itemDesc = item.getElementsByTagName('summary')[0];
|
||||
if (!itemDesc) {
|
||||
itemDesc = item.getElementsByTagName('content')[0];
|
||||
}
|
||||
}
|
||||
if (itemDesc) {
|
||||
itemDesc = itemDesc.childNodes[0].nodeValue;
|
||||
} else {
|
||||
itemDesc = '';
|
||||
}
|
||||
|
||||
var item = document.createElement("div");
|
||||
item.klassName = "item";
|
||||
var box = document.createElement("div");
|
||||
box.klassName = "open_box";
|
||||
box.addEventListener("click", showDesc);
|
||||
item.appendChild(box);
|
||||
|
||||
var title = document.createElement("a");
|
||||
title.klassName = "item_title";
|
||||
title.innerText = itemTitle;
|
||||
title.addEventListener("click", showDesc);
|
||||
item.appendChild(title);
|
||||
|
||||
var desc = document.createElement("iframe");
|
||||
desc.scrolling = "no";
|
||||
desc.klassName = "item_desc";
|
||||
item.appendChild(desc);
|
||||
feed.appendChild(item);
|
||||
|
||||
// The story body is created as an iframe with a data: URL in order to
|
||||
// isolate it from this page and protect against XSS. As a data URL, it
|
||||
// has limited privileges and must communicate back using postMessage().
|
||||
desc.src="data:text/html," + iframe_src + itemDesc + "</body></html>";
|
||||
}
|
||||
|
||||
if (moreStoriesUrl) {
|
||||
var more = document.createElement("a");
|
||||
more.klassName = "more";
|
||||
more.innerText = chrome.i18n.getMessage("more_stories");
|
||||
more.addEventListener("click", moreStories);
|
||||
feed.appendChild(more);
|
||||
}
|
||||
}
|
||||
|
||||
// Show |url| in a new tab.
|
||||
function showUrl(url) {
|
||||
// Only allow http and https URLs.
|
||||
if (url.indexOf("http:") != 0 && url.indexOf("https:") != 0) {
|
||||
return;
|
||||
}
|
||||
chrome.tabs.create({url: url});
|
||||
}
|
||||
|
||||
function moreStories(event) {
|
||||
showUrl(moreStoriesUrl);
|
||||
}
|
||||
|
||||
function showDesc(event) {
|
||||
var item = event.currentTarget.parentNode;
|
||||
var items = document.getElementsByClassName("item");
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var iframe = items[i].getElementsByClassName("item_desc")[0];
|
||||
if (items[i] == item && items[i].klassName == "item") {
|
||||
items[i].klassName = "item opened";
|
||||
iframe.contentWindow.postMessage("reportHeight", "*");
|
||||
} else {
|
||||
items[i].klassName = "item";
|
||||
iframe.style.height = "0px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function iframeMessageHandler(e) {
|
||||
// Only listen to messages from one of our own iframes.
|
||||
var iframes = document.getElementsByTagName("IFRAME");
|
||||
for (var i = 0; i < iframes.length; i++) {
|
||||
if (iframes[i].contentWindow == e.source) {
|
||||
var msg = JSON.parse(e.data);
|
||||
if (msg) {
|
||||
if (msg.type == "size") {
|
||||
iframes[i].style.height = msg.size + "px";
|
||||
} else if (msg.type == "show") {
|
||||
var url = msg.url;
|
||||
if (url.indexOf(chrome.i18n.getMessage('newsUrl')) == 0) {
|
||||
// If the URL is a redirect URL, strip of the destination and go to
|
||||
// that directly. This is necessary because the Google news
|
||||
// redirector blocks use of the redirects in this case.
|
||||
var index = url.indexOf("&url=");
|
||||
if (index >= 0) {
|
||||
url = url.substring(index + 5);
|
||||
index = url.indexOf("&");
|
||||
if (index >= 0)
|
||||
url = url.substring(0, index);
|
||||
}
|
||||
}
|
||||
showUrl(url);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("message", iframeMessageHandler);
|
||||
window.addEventListener("DOMContentLoaded", main);
|
|
@ -1,17 +1,19 @@
|
|||
{
|
||||
"name": "__MSG_name__",
|
||||
"name": "News Reader",
|
||||
"version": "1.1",
|
||||
"description": "__MSG_description__",
|
||||
"description": "Displays the first 5 items from the 'Google News - top news' RSS feed in a popup.",
|
||||
"icons": { "128": "news_icon.png" },
|
||||
"browser_action": {
|
||||
"default_title": "__MSG_default_title__",
|
||||
"default_title": "Google News",
|
||||
"default_icon": "news_action.png",
|
||||
"default_popup": "feed.html"
|
||||
},
|
||||
"default_locale": "en",
|
||||
"permissions": [
|
||||
"tabs",
|
||||
"http://news.google.com/*",
|
||||
"http://news.google.es/*"
|
||||
"https://news.google.es/*",
|
||||
"https://news.google.com/*"
|
||||
],
|
||||
"default_locale": "en"
|
||||
"manifest_version": 2,
|
||||
"content_security_policy": "default-src; img-src 'self' http://* https://*; script-src 'self'; connect-src https://news.google.com; frame-src data:"
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче