PK /}4@7s s broken-links/background.js// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. function validateLinks(links, callback) { var results = []; var pendingRequests = 0; function fetchLink(link) { if (!/^http(s?):\/\//.test(link.href)) return; var xhr = new XMLHttpRequest(); xhr.open("HEAD", link.href, true); xhr.onreadystatechange = function() { if (xhr.readyState < xhr.HEADERS_RECEIVED || xhr.processed) return; if (!xhr.status || xhr.status >= 400) { results.push({ href: link.href, text: link.text, status: xhr.statusText }); } xhr.processed = true; xhr.abort(); if (!--pendingRequests) { callback({ total: links.length, badlinks: results }); } } try { xhr.send(null); pendingRequests++; } catch (e) { console.error("XHR failed for " + link.href + ", " + e); } } for (var i = 0; i < links.length; ++i) fetchLink(links[i]); } chrome.extension.onRequest.addListener(function(request, sender, callback) { var tabId = request.tabId; chrome.tabs.executeScript(tabId, { file: "content.js" }, function() { chrome.tabs.sendRequest(tabId, {}, function(results) { validateLinks(results, callback); }); }); }); PK >8 8 broken-links/content.jsfunction getLinks() { var links = document.querySelectorAll("a"); var results = []; var seenLinks = {}; for (var i = 0; i < links.length; ++i) { var text = links[i].textContent; if (text.length > 100) text = text.substring(0, 100) + "..."; var link = links[i].href.replace(/(.*)#?/, "$1"); if (seenLinks[link]) continue; seenLinks[link] = 1; results.push({ href: link, text: text }); } return results; }; chrome.extension.onRequest.addListener(function(request, sender, sendResponse) { sendResponse(getLinks()); }); PK K?@ \B B broken-links/devtools.html
PK K?@\ broken-links/devtools.js// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. var category = chrome.experimental.devtools.audits.addCategory( "Broken links", 1); category.onAuditStarted.addListener(function callback(auditResults) { chrome.extension.sendRequest({ tabId: webInspector.inspectedWindow.tabId }, function(results) { if (!results.badlinks.length) { auditResults.addResult("No broken links", "There are no broken links on the page!", auditResults.Severity.Info); } else { var details = auditResults.createResult(results.badlinks.length + " links out of " + results.total + " are broken"); for (var i = 0; i < results.badlinks.length; ++i) { details.addChild(auditResults.createURL(results.badlinks[i].href, results.badlinks[i].text)); } auditResults.addResult("Broken links found (" + results.badlinks.length + ")", "", auditResults.Severity.Severe, details); } auditResults.done(); }); });PK K?@(| | broken-links/manifest.json{ "name": "Broken Links", "version": "1.1", "description": "Extends the Developer Tools, adding an audit category that finds broken links on the inspected page.", "background": { "scripts": ["background.js"] }, "devtools_page": "devtools.html", "permissions": [ "experimental", "tabs", "http://*/*", "https://*/*" ], "manifest_version": 2 } PK /}4@7s s broken-links/background.jsPK >8 8 broken-links/content.jsPK K?@ \B B broken-links/devtools.htmlPK K?@\ broken-links/devtools.jsPK K?@(| | ( broken-links/manifest.json44648be98237278fda3a08ef2ded7355fcdcf1daPK