1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
/**
* (C) Copyright 2008 Jeremy Maitin-Shepard
*
* Portions of this file were derived from Mozilla,
* (C) Copyright 1998-2008 Mozilla Foundation.
*
* Use, modification, and distribution are subject to the terms specified in the
* COPYING file.
**/
const favicon_service = Cc["@mozilla.org/browser/favicon-service;1"].getService(Ci.nsIFaviconService);
define_buffer_local_hook("buffer_favicon_change_hook");
function favicon_content_buffer_started_loading(buffer) {
var old = buffer.favicon;
buffer.favicon = null;
if (old != null)
buffer_favicon_change_hook.run(buffer);
}
add_hook("content_buffer_started_loading_hook", favicon_content_buffer_started_loading);
define_variable("favicon_image_max_size", 1024, "Maximum (pixel) width and height of an image document that is considered for use as a favicon.");
var favicon_image_max_size = 1024;
function favicon_content_buffer_finished_loading(buffer) {
if (buffer.favicon != null)
return;
if (buffer.document instanceof Ci.nsIImageDocument) {
var req = buffer.document.imageRequest;
if (req && req.image &&
req.image.width <= favicon_image_max_size &&
req.image.height <= favicon_image_max_size) {
favicon_set(buffer, buffer.current_URI);
return;
}
}
var uri = buffer.current_URI;
// Only load favicons for http and https
if (!uri.schemeIs("http") && !uri.schemeIs("https"))
return;
var icon_url = makeURL(uri.prePath + "/favicon.ico");
if (!favicon_service.isFailedFavicon(icon_url))
favicon_set(buffer, icon_url);
}
add_hook("content_buffer_finished_loading_hook", favicon_content_buffer_finished_loading);
var content_policy_service = Cc["@mozilla.org/layout/content-policy;1"].getService(Ci.nsIContentPolicy);
function favicon_content_buffer_dom_link_added(buffer, event) {
var link = event.originalTarget;
if (!link || !link.ownerDocument || !link.rel || !link.href)
return;
var rel = link.rel.toLowerCase();
var rel_strings = rel.split(/\s+/);
if (rel_strings.indexOf("icon") == -1)
return;
/* FIXME: perhaps worry about newURI throwing an exception */
var target_doc = link.ownerDocument;
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var uri = ios.newURI(link.href, target_doc.characterSet, null);
if (favicon_service.isFailedFavicon(uri))
return;
// Verify that the load of this icon is legal.
// error pages can load their favicon, to be on the safe side,
// only allow chrome:// favicons
const about_neterr = "about:neterror?";
if (target_doc.documentURI.substr(0, about_neterr.length) != about_neterr || !uri.schemeIs("chrome")) {
var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
try {
ssm.checkLoadURIWithPrincipal(target_doc.nodePrincipal, uri,
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT);
} catch(e) {
return;
}
}
try {
} catch(e) {
return; // Refuse to load if we can't do a security check.
}
// Security says okay, now ask content policy
if (content_policy_service.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE,
uri, target_doc.documentURIObject,
link, link.type, null)
!= Ci.nsIContentPolicy.ACCEPT)
return;
favicon_set(buffer, uri);
}
add_hook("content_buffer_dom_link_added_hook", favicon_content_buffer_dom_link_added);
function favicon_set(buffer, icon_url) {
buffer.favicon = icon_url.spec;
favicon_service.setAndLoadFaviconForPage(buffer.current_URI, icon_url, false);
buffer_favicon_change_hook.run(buffer);
}
|