--- a/devtools/client/aboutdebugging/components/tabs/panel.js
+++ b/devtools/client/aboutdebugging/components/tabs/panel.js
@@ -34,36 +34,36 @@ module.exports = createClass({
componentWillUnmount() {
let { client } = this.props;
client.removeListener("tabListChanged", this.update);
},
update() {
this.props.client.mainRoot.listTabs().then(({ tabs }) => {
+ let TabIconPromises = [];
// Filter out closed tabs (represented as `null`).
tabs = tabs.filter(tab => !!tab);
+
tabs.forEach(tab => {
- // FIXME Also try to fetch low-res favicon. But we should use actor
- // support for this to get the high-res one (bug 1061654).
- let url = new URL(tab.url);
- if (url.protocol.startsWith("http")) {
- let prePath = url.origin;
- let idx = url.pathname.lastIndexOf("/");
- if (idx === -1) {
- prePath += url.pathname;
- } else {
- prePath += url.pathname.substr(0, idx);
- }
- tab.icon = prePath + "/favicon.ico";
- } else {
- tab.icon = "chrome://devtools/skin/images/tabs-icon.svg";
+ let packet = {
+ to: tab.actor,
+ type: "getFavicon"
+ };
+
+ let tabIconPromise = this.props.client.request(packet);
+ TabIconPromises.push(tabIconPromise);
+ });
+
+ Promise.all(TabIconPromises).then(responses => {
+ for (let i = 0; i < responses.length; i++) {
+ tabs[i].icon = responses[i].icon;
}
+ this.setState({ tabs });
});
- this.setState({ tabs });
});
},
render() {
let { client, id } = this.props;
let { tabs } = this.state;
return dom.div({
--- a/devtools/server/actors/webbrowser.js
+++ b/devtools/server/actors/webbrowser.js
@@ -1,16 +1,15 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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";
-
var { Ci, Cu } = require("chrome");
var Services = require("Services");
var { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
var promise = require("promise");
var {
ActorPool, createExtraActors, appendExtraActors, GeneratedLocation
} = require("devtools/server/actors/common");
var { DebuggerServer } = require("devtools/server/main");
@@ -23,17 +22,19 @@ loader.lazyRequireGetter(this, "RootActo
loader.lazyRequireGetter(this, "ThreadActor", "devtools/server/actors/script", true);
loader.lazyRequireGetter(this, "unwrapDebuggerObjectGlobal", "devtools/server/actors/script", true);
loader.lazyRequireGetter(this, "BrowserAddonActor", "devtools/server/actors/addon", true);
loader.lazyRequireGetter(this, "WorkerActorList", "devtools/server/actors/worker", true);
loader.lazyRequireGetter(this, "ServiceWorkerRegistrationActorList", "devtools/server/actors/worker", true);
loader.lazyRequireGetter(this, "ProcessActorList", "devtools/server/actors/process", true);
loader.lazyImporter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
loader.lazyImporter(this, "ExtensionContent", "resource://gre/modules/ExtensionContent.jsm");
-
+XPCOMUtils.defineLazyServiceGetter(this, "favicons",
+ "@mozilla.org/browser/favicon-service;1",
+ "mozIAsyncFavicons");
// Assumptions on events module:
// events needs to be dispatched synchronously,
// by calling the listeners in the order or registration.
loader.lazyRequireGetter(this, "events", "sdk/event/core");
loader.lazyRequireGetter(this, "StyleSheetActor", "devtools/server/actors/stylesheets", true);
function getWindowID(window) {
@@ -1218,16 +1219,50 @@ TabActor.prototype = {
// We watch for all child docshells under the current document,
this._progressListener.watch(this.docShell);
// And list all already existing ones.
this._updateChildDocShells();
},
+
+ // FIXME Also try to fetch low-res favicon. But we should use actor
+ // support for this to get the high-res one (bug 1061654).
+ onGetFavicon() {
+ let url = new URL(this.url);
+ if (url.protocol.startsWith("http")) {
+ if (!(url instanceof Ci.nsIURI)) {
+ url = Services.io.newURI(url, null, null);
+ }
+
+ return new Promise(resolve => {
+ favicons.getFaviconURLForPage(url, uri => {
+ if (uri) {
+ uri = favicons.getFaviconLinkForIcon(uri);
+ resolve(uri.spec);
+ } else {
+ resolve(favicons.defaultFavicon.spec);
+ }
+ });
+ }).then(iconUri => {
+ return {
+ "from": this.actorID,
+ "icon": iconUri
+ };
+ });
+ } else {
+ return {
+ "from": this.actorID,
+ "icon": favicons.defaultFavicon.spec
+ };
+ }
+ },
+
+
onSwitchToFrame(request) {
let windowId = request.windowId;
let win;
try {
win = Services.wm.getOuterWindowWithId(windowId);
} catch (e) {
// ignore
@@ -2119,17 +2154,18 @@ TabActor.prototype.requestTypes = {
"detach": TabActor.prototype.onDetach,
"focus": TabActor.prototype.onFocus,
"reload": TabActor.prototype.onReload,
"navigateTo": TabActor.prototype.onNavigateTo,
"reconfigure": TabActor.prototype.onReconfigure,
"switchToFrame": TabActor.prototype.onSwitchToFrame,
"listFrames": TabActor.prototype.onListFrames,
"listWorkers": TabActor.prototype.onListWorkers,
- "resolveLocation": TabActor.prototype.onResolveLocation
+ "resolveLocation": TabActor.prototype.onResolveLocation,
+ "getFavicon": TabActor.prototype.onGetFavicon
};
exports.TabActor = TabActor;
/**
* Creates a tab actor for handling requests to a single in-process
* <xul:browser> tab, or <html:iframe>.
* Most of the implementation comes from TabActor.