diff --git a/README b/README new file mode 100644 index 0000000..820de6a --- /dev/null +++ b/README @@ -0,0 +1,32 @@ +Chrome LOD extension +==================== + +An extension for Chrome that looks for the presence of Linked Open +Data behind the pages you browse and if available, reveals the +underlying data. + +Debugging/Building +------------------ + +In Chrome, open the tools/extensions page, ensure that developer mode +is selected, and click to 'load unpacked extension...'. Select the +directory you checked out the chrome-lod source to. This should +enable the extension directly. + +In order to package the extension for deployment, use the 'pack +extension' button, which will result in a chrome-lod.crx file and +associated keyfile. + +Rationale +--------- + +The extension runs once on each page you visit, looking for +tags in the page with relationship 'meta' or 'alternate' pointing to a +URI with media-type application/rdf+xml or text/turtle. Failing that, +the extension will attempt to do content negotiation on the current +URI, asking for application/rdf+xml or text/turtle representation of +the current resource. + +If an RDF representation is available, it will be rendered behind the +current page and a peel-back animation will reveal the background RDF +data as the mouse hovers over the top left corner of the page. diff --git a/background.js b/background.js index 551ebae..23434cb 100644 --- a/background.js +++ b/background.js @@ -1,25 +1,49 @@ chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) { console.log("Message from content: " + request); - var messages = { - 'error': 'Error parsing RDF', - 'unlicensed': 'No machine readable licensing', - 'licensed': 'License declared' - }; - chrome.pageAction.setTitle({ - tabId: sender.tab.id, - title: messages[request.check] - }); - var icon = { - 'error': 'red', - 'unlicensed': 'amber', - 'licensed': 'green' - }; - chrome.pageAction.show(sender.tab.id); - chrome.pageAction.setIcon({ - tabId: sender.tab.id, - path: 'pageIcon-' + icon[request.check] + '.png' - }); - sendResponse({text: "ok"}); + if (request.method == 'setLicense') { + var messages = { + 'error': 'Error parsing RDF', + 'unlicensed': 'No machine readable licensing', + 'licensed': 'License declared' + }; + chrome.pageAction.setTitle({ + tabId: sender.tab.id, + title: messages[request.check] + }); + var icon = { + 'error': 'red', + 'unlicensed': 'amber', + 'licensed': 'green' + }; + chrome.pageAction.show(sender.tab.id); + chrome.pageAction.setIcon({ + tabId: sender.tab.id, + path: 'pageIcon-' + icon[request.check] + '.png' + }); + sendResponse({text: "ok"}); + } else if (request.method == 'isRedirect') { + if (request.url == redirectToUrl) { + sendResponse({redirect: true, + fromUrl: redirectFromUrl}); + } else { + sendResponse({redirect: false}); + } + } } ); + +redirectToUrl = null; +redirectFromUrl = null; + +chrome.webRequest.onBeforeRedirect.addListener( + function(details) { + if (details.statusCode == 303) { + console.log(details.url + " is being redirected to " + details.redirectUrl); + redirectToUrl = details.redirectUrl; + redirectFromUrl = details.url; + } + console.log("redirect"); + }, + {urls: [""]} +); diff --git a/contentscript.js b/contentscript.js index 4d5ff85..d05b1de 100644 --- a/contentscript.js +++ b/contentscript.js @@ -12,15 +12,32 @@ }); $('#turn_wrapper').click( function() { - $('#turn_fold').hide(); - $('#turn_wrapper').width('100%').height('100%').off(); - $('#turn_object').width('100%').height('100%').off(); - $('#turn_hideme').width('100%').height('100%').off(); + if ($('#turn_fold').is(':visible')) { + $('#turn_fold').hide(); + $('#turn_wrapper').width('100%').height('100%').off(); + $('#turn_object').width('100%').height('100%').off(); + $('#turn_hideme').width('100%').height('100%').off(); + }/* else { + $('#turn_fold').show(); + $('#turn_wrapper').width('80px').height('80px'); + $('#turn_object').width('80px').height('80px'); + $('#turn_hideme').width('85px').height('85px'); + } */ } ); } -function checkRdf(data, format) { +$.typedValue.types['http://www.w3.org/2001/XMLSchema#positiveInteger'] = { + regex: /^[1-9][0-9]*$/, + strip: true, + /** @ignore */ + value: function (v) { + return parseInt(v, 10); + } + }; + + +function checkRdfXmlLicense(data, format) { var parser = new DOMParser(); doc = parser.parseFromString(data, 'text/xml'); try { @@ -44,6 +61,45 @@ } } +function fetchRdf(rdfUrl, failfunc) { + $.ajax(rdfUrl, { + headers: { + Accept: acceptFormats.join(', ') + }, + cache: false, + dataType: 'text', + error: function(req, textStatus, errorThrown) { + failfunc(); + }, + success: function(data, textStatus, res) { + var ct = res.getResponseHeader('Content-Type'); + if (ct != null) { + var format = null; + for (var i = 0; i < acceptFormats.length; i++) { + if (ct.slice(0, acceptFormats[i].length) == acceptFormats[i]) { + format = acceptFormats[i]; + break; + } + } + if (format != null) { + peelBackRdf(data, format); + chrome.runtime.sendMessage({ + method: 'setLicense', + type: format, + check: checkRdfXmlLicense(data, format) + }, function(response) { + console.log(response.text); + }); + } else { + failfunc(); + } + } else { + failfunc(); + } + } + }); +} + var res = document.evaluate("//link[(@rel = 'alternate') or (@rel = 'meta')]", document.head, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null) var rdfUrl = null; @@ -58,46 +114,20 @@ } } -if (rdfUrl == null) { // Try fetching current page as RDF - $.ajax(document.URL, { - headers: { - Accept: acceptFormats.join(', ') - }, - dataType: 'text', - success: function(data, textStatus, res) { - var ct = res.getResponseHeader('Content-Type'); - if (ct != null) { - var format = null; - for (var i = 0; i < acceptFormats.length; i++) { - if (ct.slice(0, acceptFormats[i].length) == acceptFormats[i]) { - format = acceptFormats[i]; - break; - } - } - if (format != null) { - peelBackRdf(data, format); - chrome.runtime.sendMessage({ - type: format, - check: checkRdf(data, format) - }, function(response) { - console.log(response.text); - }); - } - } +if (rdfUrl == null) { + // check to see whether we've been redirected here + chrome.runtime.sendMessage({ + method: 'isRedirect', + url: document.URL + }, function(response) { + if (response.redirect) { + fetchRdf(response.fromUrl, function() { + fetchRdf(document.URL); // if failed to fetch prior page as RDF + }); + } else { // if no redirect, try fetching current page as RDF + fetchRdf(document.URL, function() {}); } }); } else { - $.ajax(rdfUrl, { - accepts: { text: rdfFormat }, - dataType: 'text', - success: function(data, textStatus, res) { - peelBackRdf(data, rdfFormat); - chrome.runtime.sendMessage({ - type: format, - check: checkRdf(data, rdfFormat) - }, function(response) { - console.log(response.text); - }); - } - }); + fetchRdf(rdfUrl, function() {}); } diff --git a/custom.css b/custom.css index ca2c2de..edef100 100644 --- a/custom.css +++ b/custom.css @@ -5,7 +5,7 @@ } #turn_wrapper { - z-index: 100; + z-index: 10000; } .CodeMirror-code pre { @@ -20,4 +20,4 @@ .CodeMirror-scroll { overflow-y: hidden; overflow-x: auto; -} \ No newline at end of file +} diff --git a/manifest.json b/manifest.json index e85a4fa..e9606c6 100644 --- a/manifest.json +++ b/manifest.json @@ -4,6 +4,10 @@ "name": "LOD-check", "description": "Checks pages as you browse for the presence of Linked Open Data behind them and reveals the underlying data.", "version": "1.0", + "permissions": [ + "webRequest", + "" + ], "icons": { "16": "package-icon-16.png", "48": "package-icon-48.png", @@ -11,11 +15,11 @@ }, "page_action": { "default_icon": { - "19": "r-icon.png" + "19": "package-icon-19.png" } }, "background": { - "persistent": false, + "persistent": true, "scripts": ["background.js"] }, "content_scripts": [ diff --git a/package-icon-19.png b/package-icon-19.png new file mode 100644 index 0000000..81c0920 --- /dev/null +++ b/package-icon-19.png Binary files differ diff --git a/pageIcon-amber.png b/pageIcon-amber.png index 9c0ac52..071ec3a 100644 --- a/pageIcon-amber.png +++ b/pageIcon-amber.png Binary files differ diff --git a/pageIcon-green.png b/pageIcon-green.png index c5e5f10..3df9256 100644 --- a/pageIcon-green.png +++ b/pageIcon-green.png Binary files differ diff --git a/pageIcon-red.png b/pageIcon-red.png index 82fada4..3533995 100644 --- a/pageIcon-red.png +++ b/pageIcon-red.png Binary files differ