From 9ea996ea3e694542ed40e920672b043da3aa6248 Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Sat, 14 Apr 2012 00:18:27 +0200 Subject: [PATCH 1/3] Bug 744152 - [Page Thumbnails] Capture thumbnails only for the selected tab; r=dietrich --- browser/base/content/browser-thumbnails.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/browser/base/content/browser-thumbnails.js b/browser/base/content/browser-thumbnails.js index eb5cdac3898..eeae68040e3 100644 --- a/browser/base/content/browser-thumbnails.js +++ b/browser/base/content/browser-thumbnails.js @@ -8,7 +8,7 @@ * Keeps thumbnails of open web pages up-to-date. */ let gBrowserThumbnails = { - _captureDelayMS: 2000, + _captureDelayMS: 1000, /** * Map of capture() timeouts assigned to their browsers. @@ -98,6 +98,11 @@ let gBrowserThumbnails = { }, _shouldCapture: function Thumbnails_shouldCapture(aBrowser) { + // Capture only if it's the currently selected tab. + if (aBrowser != gBrowser.selectedBrowser) + return false; + + // Don't capture in private browsing mode. if (gPrivateBrowsingUI.privateBrowsingEnabled) return false; From 1964f0fd7182f95e450cc7cea2504016de0aa5ac Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Sat, 14 Apr 2012 00:43:29 +0200 Subject: [PATCH 2/3] Bug 721442 - [New Tab Page] Display the URL of the page on mouseover of thumbnails on about:newtab; r=dietrich --- browser/base/content/newtab/sites.js | 9 +++++--- browser/base/content/test/newtab/Makefile.in | 1 + .../test/newtab/browser_newtab_bug721442.js | 23 +++++++++++++++++++ browser/base/content/test/newtab/head.js | 4 ++-- 4 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 browser/base/content/test/newtab/browser_newtab_bug721442.js diff --git a/browser/base/content/newtab/sites.js b/browser/base/content/newtab/sites.js index 7a3bff50325..6b3c80b0de1 100644 --- a/browser/base/content/newtab/sites.js +++ b/browser/base/content/newtab/sites.js @@ -119,10 +119,13 @@ Site.prototype = { * Renders the site's data (fills the HTML fragment). */ _render: function Site_render() { - let title = this.title || this.url; + let url = this.url; + let title = this.title || url; + let tooltip = (title == url ? title : title + "\n" + url); + let link = this._querySelector(".newtab-link"); - link.setAttribute("title", title); - link.setAttribute("href", this.url); + link.setAttribute("title", tooltip); + link.setAttribute("href", url); this._querySelector(".newtab-title").textContent = title; if (this.isPinned()) diff --git a/browser/base/content/test/newtab/Makefile.in b/browser/base/content/test/newtab/Makefile.in index 668c839730e..a9f153c20a1 100644 --- a/browser/base/content/test/newtab/Makefile.in +++ b/browser/base/content/test/newtab/Makefile.in @@ -20,6 +20,7 @@ _BROWSER_FILES = \ browser_newtab_reset.js \ browser_newtab_tabsync.js \ browser_newtab_unpin.js \ + browser_newtab_bug721442.js \ browser_newtab_bug722273.js \ browser_newtab_bug723102.js \ browser_newtab_bug723121.js \ diff --git a/browser/base/content/test/newtab/browser_newtab_bug721442.js b/browser/base/content/test/newtab/browser_newtab_bug721442.js new file mode 100644 index 00000000000..297726a6ee9 --- /dev/null +++ b/browser/base/content/test/newtab/browser_newtab_bug721442.js @@ -0,0 +1,23 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function runTests() { + setLinks("0,1,2,3,4,5,6,7,8"); + NewTabUtils.pinnedLinks._links = [ + {url: "about:blank#7", title: ""}, + {url: "about:blank#8", title: "title"}, + {url: "about:blank#9", title: "about:blank#9"} + ]; + + yield addNewTabPageTab(); + checkGrid("7p,8p,9p,0,1,2,3,4,5"); + + checkTooltip(0, "about:blank#7", "1st tooltip is correct"); + checkTooltip(1, "title\nabout:blank#8", "2nd tooltip is correct"); + checkTooltip(2, "about:blank#9", "3rd tooltip is correct"); +} + +function checkTooltip(aIndex, aExpected, aMessage) { + let link = getCell(aIndex).node.querySelector(".newtab-link"); + is(link.getAttribute("title"), aExpected, aMessage); +} diff --git a/browser/base/content/test/newtab/head.js b/browser/base/content/test/newtab/head.js index c56c4d0b859..fe92378085e 100644 --- a/browser/base/content/test/newtab/head.js +++ b/browser/base/content/test/newtab/head.js @@ -194,7 +194,7 @@ function addNewTabPageTab() { function checkGrid(aSitesPattern, aSites) { let length = aSitesPattern.split(",").length; let sites = (aSites || getGrid().sites).slice(0, length); - let expected = sites.map(function (aSite) { + let current = sites.map(function (aSite) { if (!aSite) return ""; @@ -208,7 +208,7 @@ function checkGrid(aSitesPattern, aSites) { return aSite.url.replace(/^about:blank#(\d+)$/, "$1") + (pinned ? "p" : ""); }); - is(aSitesPattern, expected, "grid status = " + aSitesPattern); + is(current, aSitesPattern, "grid status = " + aSitesPattern); } /** From c4f2ae59bb4c1bebd990213e0f56a7cc6aa8d708 Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Sat, 14 Apr 2012 01:04:57 +0200 Subject: [PATCH 3/3] Bug 740807 - Clean up favicon code in Panorama; r=dietrich --- browser/components/tabview/favicons.js | 141 +++++++++++++++++++++++ browser/components/tabview/groupitems.js | 4 +- browser/components/tabview/tabitems.js | 2 +- browser/components/tabview/tabview.js | 6 +- browser/components/tabview/ui.js | 109 +----------------- 5 files changed, 149 insertions(+), 113 deletions(-) create mode 100644 browser/components/tabview/favicons.js diff --git a/browser/components/tabview/favicons.js b/browser/components/tabview/favicons.js new file mode 100644 index 00000000000..61702750991 --- /dev/null +++ b/browser/components/tabview/favicons.js @@ -0,0 +1,141 @@ +/* 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/. */ + +let FavIcons = { + // Pref that controls whether to display site icons. + PREF_CHROME_SITE_ICONS: "browser.chrome.site_icons", + + // Pref that controls whether to display fav icons. + PREF_CHROME_FAVICONS: "browser.chrome.favicons", + + // Lazy getter for pref browser.chrome.site_icons. + get _prefSiteIcons() { + delete this._prefSiteIcons; + this._prefSiteIcons = Services.prefs.getBoolPref(this.PREF_CHROME_SITE_ICONS); + }, + + // Lazy getter for pref browser.chrome.favicons. + get _prefFavicons() { + delete this._prefFavicons; + this._prefFavicons = Services.prefs.getBoolPref(this.PREF_CHROME_FAVICONS); + }, + + get defaultFavicon() this._favIconService.defaultFavicon.spec, + + init: function FavIcons_init() { + XPCOMUtils.defineLazyServiceGetter(this, "_favIconService", + "@mozilla.org/browser/favicon-service;1", "nsIFaviconService"); + + Services.prefs.addObserver(this.PREF_CHROME_SITE_ICONS, this, false); + Services.prefs.addObserver(this.PREF_CHROME_FAVICONS, this, false); + }, + + uninit: function FavIcons_uninit() { + Services.prefs.removeObserver(this.PREF_CHROME_SITE_ICONS, this); + Services.prefs.removeObserver(this.PREF_CHROME_FAVICONS, this); + }, + + observe: function FavIcons_observe(subject, topic, data) { + let value = Services.prefs.getBoolPref(data); + + if (data == this.PREF_CHROME_SITE_ICONS) + this._prefSiteIcons = value; + else if (data == this.PREF_CHROME_FAVICONS) + this._prefFavicons = value; + }, + + // ---------- + // Function: getFavIconUrlForTab + // Gets the "favicon link URI" for the given xul:tab, or null if unavailable. + getFavIconUrlForTab: function FavIcons_getFavIconUrlForTab(tab, callback) { + this._isImageDocument(tab, function (isImageDoc) { + if (isImageDoc) { + callback(tab.pinned ? tab.image : null); + } else { + this._getFavIconForNonImageDocument(tab, callback); + } + }.bind(this)); + }, + + // ---------- + // Function: _getFavIconForNonImageDocument + // Retrieves the favicon for a tab containing a non-image document. + _getFavIconForNonImageDocument: + function FavIcons_getFavIconForNonImageDocument(tab, callback) { + + if (tab.image) + this._getFavIconFromTabImage(tab, callback); + else if (this._shouldLoadFavIcon(tab)) + this._getFavIconForHttpDocument(tab, callback); + else + callback(null); + }, + + // ---------- + // Function: _getFavIconFromTabImage + // Retrieves the favicon for tab with a tab image. + _getFavIconFromTabImage: + function FavIcons_getFavIconFromTabImage(tab, callback) { + + let tabImage = tab.image; + + // If the tab image's url starts with http(s), fetch icon from favicon + // service via the moz-anno protocol. + if (/^https?:/.test(tabImage)) { + let tabImageURI = gWindow.makeURI(tabImage); + tabImage = this._favIconService.getFaviconLinkForIcon(tabImageURI).spec; + } + + callback(tabImage); + }, + + // ---------- + // Function: _getFavIconForHttpDocument + // Retrieves the favicon for tab containg a http(s) document. + _getFavIconForHttpDocument: + function FavIcons_getFavIconForHttpDocument(tab, callback) { + + let {currentURI} = tab.linkedBrowser; + this._favIconService.getFaviconURLForPage(currentURI, function (uri) { + if (uri) { + callback(this._favIconService.getFaviconLinkForIcon(uri).spec); + } else { + callback(this.defaultFavicon); + } + }.bind(this)); + }, + + // ---------- + // Function: _isImageDocument + // Checks whether an image is loaded into the given tab. + _isImageDocument: function UI__isImageDocument(tab, callback) { + let mm = tab.linkedBrowser.messageManager; + let message = "Panorama:isImageDocument"; + + mm.addMessageListener(message, function onMessage(cx) { + mm.removeMessageListener(cx.name, onMessage); + callback(cx.json.isImageDocument); + }); + + mm.sendAsyncMessage(message); + }, + + // ---------- + // Function: _shouldLoadFavIcon + // Checks whether fav icon should be loaded for a given tab. + _shouldLoadFavIcon: function FavIcons_shouldLoadFavIcon(tab) { + // No need to load a favicon if the user doesn't want site or favicons. + if (!this._prefSiteIcons || !this._prefFavicons) + return false; + + let uri = tab.linkedBrowser.currentURI; + + // Stop here if we don't have a valid nsIURI. + if (!uri || !(uri instanceof Ci.nsIURI)) + return false; + + // Load favicons for http(s) pages only. + return uri.schemeIs("http") || uri.schemeIs("https"); + } +}; diff --git a/browser/components/tabview/groupitems.js b/browser/components/tabview/groupitems.js index 9d1315cb9d3..e99a3e8cd2b 100644 --- a/browser/components/tabview/groupitems.js +++ b/browser/components/tabview/groupitems.js @@ -2107,8 +2107,8 @@ let GroupItems = { // Function: getAppTabFavIconUrl // Gets the fav icon url for app tab. getAppTabFavIconUrl: function GroupItems_getAppTabFavIconUrl(xulTab, callback) { - UI.getFavIconUrlForTab(xulTab, function GroupItems_getAppTabFavIconUrl_getFavIconUrlForTab(iconUrl) { - callback(iconUrl || gFavIconService.defaultFavicon.spec); + FavIcons.getFavIconUrlForTab(xulTab, function GroupItems_getAppTabFavIconUrl_getFavIconUrlForTab(iconUrl) { + callback(iconUrl || FavIcons.defaultFavicon); }); }, diff --git a/browser/components/tabview/tabitems.js b/browser/components/tabview/tabitems.js index 07c4631f187..a754fe7239d 100644 --- a/browser/components/tabview/tabitems.js +++ b/browser/components/tabview/tabitems.js @@ -1010,7 +1010,7 @@ let TabItems = { // Even if the page hasn't loaded, display the favicon and title // ___ icon - UI.getFavIconUrlForTab(tab, function TabItems__update_getFavIconUrlCallback(iconUrl) { + FavIcons.getFavIconUrlForTab(tab, function TabItems__update_getFavIconUrlCallback(iconUrl) { let favImage = tabItem.$favImage[0]; let fav = tabItem.$fav; if (iconUrl) { diff --git a/browser/components/tabview/tabview.js b/browser/components/tabview/tabview.js index b63933967be..1b930a93f38 100644 --- a/browser/components/tabview/tabview.js +++ b/browser/components/tabview/tabview.js @@ -30,11 +30,6 @@ XPCOMUtils.defineLazyGetter(this, "gPrivateBrowsing", function() { getService(Ci.nsIPrivateBrowsingService); }); -XPCOMUtils.defineLazyGetter(this, "gFavIconService", function() { - return Cc["@mozilla.org/browser/favicon-service;1"]. - getService(Ci.nsIFaviconService); -}); - XPCOMUtils.defineLazyGetter(this, "gNetUtil", function() { var obj = {}; Cu.import("resource://gre/modules/NetUtil.jsm", obj); @@ -80,6 +75,7 @@ let AllTabs = { #include items.js #include groupitems.js #include tabitems.js +#include favicons.js #include drag.js #include trench.js #include thumbnailStorage.js diff --git a/browser/components/tabview/ui.js b/browser/components/tabview/ui.js index 6e2f519c52a..f1474b6a611 100644 --- a/browser/components/tabview/ui.js +++ b/browser/components/tabview/ui.js @@ -51,12 +51,6 @@ let Keys = { meta: false }; // Class: UI // Singleton top-level UI manager. let UI = { - // Pref that controls whether to display site icons - PREF_CHROME_SITE_ICONS: "browser.chrome.site_icons", - - // Pref that controls whether to display fav icons - PREF_CHROME_FAVICONS: "browser.chrome.favicons", - // Variable: _frameInitialized // True if the Tab View UI frame has been initialized. _frameInitialized: false, @@ -147,12 +141,6 @@ let UI = { // Used to keep track of the tab strip smooth scroll value. _originalSmoothScroll: null, - // Used to keep track of the browser.chrome.site_icons pref value. - _prefSiteIcons: null, - - // Used to keep track of the browser.chrome.favicons pref value. - _prefFavicons: null, - // ---------- // Function: toString // Prints [UI] for debug use @@ -253,10 +241,6 @@ let UI = { // ___ add tab action handlers this._addTabActionHandlers(); - // ___ add preference observers - Services.prefs.addObserver(this.PREF_CHROME_SITE_ICONS, this, false); - Services.prefs.addObserver(this.PREF_CHROME_FAVICONS, this, false); - // ___ groups GroupItems.init(); GroupItems.pauseArrange(); @@ -266,6 +250,9 @@ let UI = { TabItems.init(); TabItems.pausePainting(); + // ___ favicons + FavIcons.init(); + if (!hasGroupItemsData) this.reset(); @@ -330,12 +317,10 @@ let UI = { // additional clean up TabItems.uninit(); GroupItems.uninit(); + FavIcons.uninit(); Storage.uninit(); StoragePolicy.uninit(); - Services.prefs.removeObserver(this.PREF_CHROME_SITE_ICONS, this); - Services.prefs.removeObserver(this.PREF_CHROME_FAVICONS, this); - this._removeTabActionHandlers(); this._currentTab = null; this._pageBounds = null; @@ -873,19 +858,6 @@ let UI = { AllTabs.unregister(name, this._eventListeners[name]); }, - // ---------- - // Function: observe - // Observes different preference value changes. - observe: function UI_observe(subject, topic, data) { - if (data == this.PREF_CHROME_SITE_ICONS) { - this._prefSiteIcons = - Services.prefs.getBoolPref(this.PREF_CHROME_SITE_ICONS); - } else if (data == this.PREF_CHROME_FAVICONS) { - this._prefFavicons = - Services.prefs.getBoolPref(this.PREF_CHROME_FAVICONS); - } - }, - // ---------- // Function: goToTab // Selects the given xul:tab in the browser. @@ -1655,79 +1627,6 @@ let UI = { TabItems.saveAll(); }, - // ---------- - // Function: _isImageDocument - // Checks whether an image is loaded into the given tab. - _isImageDocument: function UI__isImageDocument(tab, callback) { - let mm = tab.linkedBrowser.messageManager; - let message = "Panorama:isImageDocument"; - - mm.addMessageListener(message, function onMessage(cx) { - mm.removeMessageListener(cx.name, onMessage); - callback(cx.json.isImageDocument); - }); - mm.sendAsyncMessage(message); - }, - - // ---------- - // Function: _shouldLoadFavIcon - // Checks whether fav icon should be loaded for a given tab. - _shouldLoadFavIcon: function UI__shouldLoadFavIcon(tab) { - let uri = tab.linkedBrowser.currentURI; - - if (!uri) - return false; - - if (this._prefSiteIcons == null) - this._prefSiteIcons = - Services.prefs.getBoolPref(this.PREF_CHROME_SITE_ICONS); - - if (!this._prefSiteIcons) - return false; - - if (this._prefFavicons == null) - this._prefFavicons = - Services.prefs.getBoolPref(this.PREF_CHROME_FAVICONS); - - return (this._prefFavicons && ("schemeIs" in uri) && - (uri.schemeIs("http") || uri.schemeIs("https"))); - }, - - // ---------- - // Function: getFavIconUrlForTab - // Gets the "favicon link URI" for the given xul:tab, or null if unavailable. - getFavIconUrlForTab: function UI_getFavIconUrlForTab(tab, callback) { - this._isImageDocument(tab, function(isImageDoc) { - if (isImageDoc) { - callback(tab.pinned ? tab.image : null); - } else { - let tabImage = tab.image; - if (tabImage) { - // if starts with http/https, fetch icon from favicon service via the moz-anno protocal - if (/^https?:/.test(tabImage)) - tabImage = gFavIconService.getFaviconLinkForIcon(gWindow.makeURI(tab.image)).spec; - - callback(tabImage); - } else { - // ensure we don't show the default icon for about:-style error pages - if (!this._shouldLoadFavIcon(tab)) { - callback(null); - } else { - // determine to load the default/cached icon or not - gFavIconService.getFaviconURLForPage(tab.linkedBrowser.currentURI, - function (uri) { - if (!uri) { - callback(gFavIconService.defaultFavicon.spec); - } else { - callback(gFavIconService.getFaviconLinkForIcon(uri).spec); - } - }); - } - } - } - }.bind(this)); - }, - // ---------- // Function: notifySessionRestoreEnabled // Notify the user that session restore has been automatically enabled