summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/PageIconProtocolHandler.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/PageIconProtocolHandler.js')
-rw-r--r--toolkit/components/places/PageIconProtocolHandler.js128
1 files changed, 128 insertions, 0 deletions
diff --git a/toolkit/components/places/PageIconProtocolHandler.js b/toolkit/components/places/PageIconProtocolHandler.js
new file mode 100644
index 000000000..05e43ccf3
--- /dev/null
+++ b/toolkit/components/places/PageIconProtocolHandler.js
@@ -0,0 +1,128 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
+ "resource://gre/modules/PlacesUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
+ "resource://gre/modules/NetUtil.jsm");
+
+function makeDefaultFaviconChannel(uri, loadInfo) {
+ let channel = Services.io.newChannelFromURIWithLoadInfo(
+ PlacesUtils.favicons.defaultFavicon, loadInfo);
+ channel.originalURI = uri;
+ return channel;
+}
+
+function streamDefaultFavicon(uri, loadInfo, outputStream) {
+ try {
+ // Open up a new channel to get that data, and push it to our output stream.
+ // Create a listener to hand data to the pipe's output stream.
+ let listener = Cc["@mozilla.org/network/simple-stream-listener;1"]
+ .createInstance(Ci.nsISimpleStreamListener);
+ listener.init(outputStream, {
+ onStartRequest(request, context) {},
+ onStopRequest(request, context, statusCode) {
+ // We must close the outputStream regardless.
+ outputStream.close();
+ }
+ });
+ let defaultIconChannel = makeDefaultFaviconChannel(uri, loadInfo);
+ defaultIconChannel.asyncOpen2(listener);
+ } catch (ex) {
+ Cu.reportError(ex);
+ outputStream.close();
+ }
+}
+
+function PageIconProtocolHandler() {
+}
+
+PageIconProtocolHandler.prototype = {
+ get scheme() {
+ return "page-icon";
+ },
+
+ get defaultPort() {
+ return -1;
+ },
+
+ get protocolFlags() {
+ return Ci.nsIProtocolHandler.URI_NORELATIVE |
+ Ci.nsIProtocolHandler.URI_NOAUTH |
+ Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD |
+ Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE;
+ },
+
+ newURI(spec, originCharset, baseURI) {
+ let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
+ uri.spec = spec;
+ return uri;
+ },
+
+ newChannel2(uri, loadInfo) {
+ try {
+ // Create a pipe that will give us an output stream that we can use once
+ // we got all the favicon data.
+ let pipe = Cc["@mozilla.org/pipe;1"]
+ .createInstance(Ci.nsIPipe);
+ pipe.init(true, true, 0, Ci.nsIFaviconService.MAX_FAVICON_BUFFER_SIZE);
+
+ // Create our channel.
+ let channel = Cc['@mozilla.org/network/input-stream-channel;1']
+ .createInstance(Ci.nsIInputStreamChannel);
+ channel.QueryInterface(Ci.nsIChannel);
+ channel.setURI(uri);
+ channel.contentStream = pipe.inputStream;
+ channel.loadInfo = loadInfo;
+
+ let pageURI = NetUtil.newURI(uri.path);
+ PlacesUtils.favicons.getFaviconDataForPage(pageURI, (iconuri, len, data, mime) => {
+ if (len == 0) {
+ channel.contentType = "image/png";
+ streamDefaultFavicon(uri, loadInfo, pipe.outputStream);
+ return;
+ }
+
+ try {
+ channel.contentType = mime;
+ // Pass the icon data to the output stream.
+ let stream = Cc["@mozilla.org/binaryoutputstream;1"]
+ .createInstance(Ci.nsIBinaryOutputStream);
+ stream.setOutputStream(pipe.outputStream);
+ stream.writeByteArray(data, len);
+ stream.close();
+ pipe.outputStream.close();
+ } catch (ex) {
+ channel.contentType = "image/png";
+ streamDefaultFavicon(uri, loadInfo, pipe.outputStream);
+ }
+ });
+
+ return channel;
+ } catch (ex) {
+ return makeDefaultFaviconChannel(uri, loadInfo);
+ }
+ },
+
+ newChannel(uri) {
+ return this.newChannel2(uri, null);
+ },
+
+ allowPort(port, scheme) {
+ return false;
+ },
+
+ classID: Components.ID("{60a1f7c6-4ff9-4a42-84d3-5a185faa6f32}"),
+ QueryInterface: XPCOMUtils.generateQI([
+ Ci.nsIProtocolHandler
+ ])
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PageIconProtocolHandler]);