michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const DEFAULT_ICON_URL = "chrome://global/skin/icons/webapps-64.png"; michael@0: michael@0: /** michael@0: * This function receives a list of icon sizes michael@0: * and URLs and returns the url string for the biggest icon. michael@0: * michael@0: * @param aIcons An object where the keys are the icon sizes michael@0: * and the values are URL strings. E.g.: michael@0: * aIcons = { michael@0: * "16": "http://www.example.org/icon16.png", michael@0: * "32": "http://www.example.org/icon32.png" michael@0: * }; michael@0: * michael@0: * @returns the URL string for the largest specified icon michael@0: */ michael@0: function getBiggestIconURL(aIcons) { michael@0: if (!aIcons) { michael@0: return DEFAULT_ICON_URL; michael@0: } michael@0: michael@0: let iconSizes = Object.keys(aIcons); michael@0: if (iconSizes.length == 0) { michael@0: return DEFAULT_ICON_URL; michael@0: } michael@0: iconSizes.sort(function(a, b) a - b); michael@0: return aIcons[iconSizes.pop()]; michael@0: } michael@0: michael@0: // Download an icon using either a temp file or a pipe. michael@0: function downloadIcon(aIconURI) { michael@0: let deferred = Promise.defer(); michael@0: michael@0: let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService); michael@0: let mimeType; michael@0: try { michael@0: let tIndex = aIconURI.path.indexOf(";"); michael@0: if("data" == aIconURI.scheme && tIndex != -1) { michael@0: mimeType = aIconURI.path.substring(0, tIndex); michael@0: } else { michael@0: mimeType = mimeService.getTypeFromURI(aIconURI); michael@0: } michael@0: } catch(e) { michael@0: deferred.reject("Failed to determine icon MIME type: " + e); michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function onIconDownloaded(aStatusCode, aIcon) { michael@0: if (Components.isSuccessCode(aStatusCode)) { michael@0: deferred.resolve([ mimeType, aIcon ]); michael@0: } else { michael@0: deferred.reject("Failure downloading icon: " + aStatusCode); michael@0: } michael@0: } michael@0: michael@0: try { michael@0: #ifdef XP_MACOSX michael@0: let downloadObserver = { michael@0: onDownloadComplete: function(downloader, request, cx, aStatus, file) { michael@0: onIconDownloaded(aStatus, file); michael@0: } michael@0: }; michael@0: michael@0: let tmpIcon = Services.dirsvc.get("TmpD", Ci.nsIFile); michael@0: tmpIcon.append("tmpicon." + mimeService.getPrimaryExtension(mimeType, "")); michael@0: tmpIcon.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("666", 8)); michael@0: michael@0: let listener = Cc["@mozilla.org/network/downloader;1"] michael@0: .createInstance(Ci.nsIDownloader); michael@0: listener.init(downloadObserver, tmpIcon); michael@0: #else michael@0: let pipe = Cc["@mozilla.org/pipe;1"] michael@0: .createInstance(Ci.nsIPipe); michael@0: pipe.init(true, true, 0, 0xffffffff, null); michael@0: michael@0: let listener = Cc["@mozilla.org/network/simple-stream-listener;1"] michael@0: .createInstance(Ci.nsISimpleStreamListener); michael@0: listener.init(pipe.outputStream, { michael@0: onStartRequest: function() {}, michael@0: onStopRequest: function(aRequest, aContext, aStatusCode) { michael@0: pipe.outputStream.close(); michael@0: onIconDownloaded(aStatusCode, pipe.inputStream); michael@0: } michael@0: }); michael@0: #endif michael@0: michael@0: let channel = NetUtil.newChannel(aIconURI); michael@0: let { BadCertHandler } = Cu.import("resource://gre/modules/CertUtils.jsm", {}); michael@0: // Pass true to avoid optional redirect-cert-checking behavior. michael@0: channel.notificationCallbacks = new BadCertHandler(true); michael@0: michael@0: channel.asyncOpen(listener, null); michael@0: } catch(e) { michael@0: deferred.reject("Failure initiating download of icon: " + e); michael@0: } michael@0: michael@0: return deferred.promise; michael@0: }