Bug 420605 - Notify the favicon service when we do a hash navigation so fragment history entries get favicons correctly. r=sicking

This commit is contained in:
Philipp von Weitershausen ext:(%2C%20Justin%20Lebar%20%3Cjustin.lebar%40gmail.com%3E) 2011-05-22 12:51:55 -04:00
Родитель d869da05f2
Коммит 00510b3b3f
4 изменённых файлов: 211 добавлений и 44 удалений

Просмотреть файл

@ -7846,6 +7846,56 @@ nsDocShell::CheckLoadingPermissions()
//*****************************************************************************
// nsDocShell: Site Loading
//*****************************************************************************
namespace
{
// Callback used by CopyFavicon to inform the favicon service that one URI
// (mNewURI) has the same favicon URI (OnFaviconDataAvailable's aFaviconURI) as
// another.
class nsCopyFaviconCallback : public nsIFaviconDataCallback
{
public:
NS_DECL_ISUPPORTS
nsCopyFaviconCallback(nsIURI *aNewURI)
: mNewURI(aNewURI)
{
}
NS_IMETHODIMP
OnFaviconDataAvailable(nsIURI *aFaviconURI, PRUint32 aDataLen,
const PRUint8 *aData, const nsACString &aMimeType)
{
NS_ASSERTION(aDataLen == 0,
"We weren't expecting the callback to deliver data.");
nsCOMPtr<mozIAsyncFavicons> favSvc =
do_GetService("@mozilla.org/browser/favicon-service;1");
NS_ENSURE_STATE(favSvc);
return favSvc->SetAndFetchFaviconForPage(mNewURI, aFaviconURI,
PR_FALSE, nsnull);
}
private:
nsCOMPtr<nsIURI> mNewURI;
};
NS_IMPL_ISUPPORTS1(nsCopyFaviconCallback, nsIFaviconDataCallback)
// Tell the favicon service that aNewURI has the same favicon as aOldURI.
void CopyFavicon(nsIURI *aOldURI, nsIURI *aNewURI)
{
nsCOMPtr<mozIAsyncFavicons> favSvc =
do_GetService("@mozilla.org/browser/favicon-service;1");
if (favSvc) {
nsCOMPtr<nsIFaviconDataCallback> callback =
new nsCopyFaviconCallback(aNewURI);
favSvc->GetFaviconURLForPage(aOldURI, callback);
}
}
} // anonymous namespace
class InternalLoadEvent : public nsRunnable
{
public:
@ -8450,6 +8500,10 @@ nsDocShell::InternalLoad(nsIURI * aURI,
}
}
// Inform the favicon service that the favicon for oldURI also
// applies to aURI.
CopyFavicon(oldURI, aURI);
return NS_OK;
}
}
@ -9439,43 +9493,6 @@ nsDocShell::SetReferrerURI(nsIURI * aURI)
// nsDocShell: Session History
//*****************************************************************************
namespace
{
// Callback used in nsDocShell::AddState. When we change URIs with
// push/replaceState, we use this callback to ensure that Places associates
// a favicon with the new URI.
class nsAddStateFaviconCallback : public nsIFaviconDataCallback
{
public:
NS_DECL_ISUPPORTS
nsAddStateFaviconCallback(nsIURI *aNewURI)
: mNewURI(aNewURI)
{
}
NS_IMETHODIMP
OnFaviconDataAvailable(nsIURI *aFaviconURI, PRUint32 aDataLen,
const PRUint8 *aData, const nsACString &aMimeType)
{
NS_ASSERTION(aDataLen == 0,
"We weren't expecting the callback to deliver data.");
nsCOMPtr<mozIAsyncFavicons> favSvc =
do_GetService("@mozilla.org/browser/favicon-service;1");
NS_ENSURE_STATE(favSvc);
return favSvc->SetAndFetchFaviconForPage(mNewURI, aFaviconURI,
PR_FALSE, nsnull);
}
private:
nsCOMPtr<nsIURI> mNewURI;
};
NS_IMPL_ISUPPORTS1(nsAddStateFaviconCallback, nsIFaviconDataCallback)
} // anonymous namespace
NS_IMETHODIMP
nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
const nsAString& aURL, PRBool aReplace, JSContext* aCx)
@ -9766,13 +9783,7 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
// Inform the favicon service that our old favicon applies to this new
// URI.
nsCOMPtr<mozIAsyncFavicons> favSvc =
do_GetService("@mozilla.org/browser/favicon-service;1");
if (favSvc) {
nsCOMPtr<nsIFaviconDataCallback> callback =
new nsAddStateFaviconCallback(newURI);
favSvc->GetFaviconURLForPage(oldURI, callback);
}
CopyFavicon(oldURI, newURI);
}
else {
FireDummyOnLocationChange();

Просмотреть файл

@ -51,6 +51,8 @@ _BROWSER_TEST_FILES = \
browser_bug388121-1.js \
browser_bug388121-2.js \
browser_bug441169.js \
browser_bug420605.js \
file_bug420605.html \
browser_bug503832.js \
browser_loadDisallowInherit.js \
file_bug503832.html \

Просмотреть файл

@ -0,0 +1,123 @@
/* Test for Bug 420605
* https://bugzilla.mozilla.org/show_bug.cgi?id=420605
*/
function test() {
waitForExplicitFinish();
var pageurl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug420605.html";
var fragmenturl = "http://mochi.test:8888/browser/docshell/test/browser/file_bug420605.html#firefox";
var historyService = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsINavHistoryService);
/* Queries nsINavHistoryService and returns a single history entry
* for a given URI */
function getNavHistoryEntry(aURI) {
var options = historyService.getNewQueryOptions();
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY;
options.maxResults = 1;
var query = historyService.getNewQuery();
query.uri = aURI;
var result = historyService.executeQuery(query, options);
result.root.containerOpen = true;
if (!result.root.childCount) {
return null;
}
return result.root.getChild(0);
}
// We'll save the favicon URL of the orignal page here and check that the
// page with a hash has the same favicon.
var originalFavicon;
// Control flow in this test is a bit complicated.
//
// When the page loads, onPageLoad (the DOMContentLoaded handler) and
// historyObserver::onPageChanged are both called, in some order. Once
// they've both run, we click a fragment link in the content page
// (clickLinkIfReady), which should trigger another onPageChanged event,
// this time for the fragment's URL.
var _clickLinkTimes = 0;
function clickLinkIfReady() {
_clickLinkTimes++;
if (_clickLinkTimes == 2) {
EventUtils.sendMouseEvent({type:'click'}, 'firefox-link',
gBrowser.selectedBrowser.contentWindow);
}
}
/* Global history observer that triggers for the two test URLs above. */
var historyObserver = {
onBeginUpdateBatch: function() {},
onEndUpdateBatch: function() {},
onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
aTransitionType, _added) {},
onTitleChanged: function(aURI, aPageTitle) {},
onBeforeDeleteURI: function(aURI) {},
onDeleteURI: function(aURI) {},
onClearHistory: function() {},
onPageChanged: function(aURI, aWhat, aValue) {
if (aWhat != Ci.nsINavHistoryObserver.ATTRIBUTE_FAVICON) {
return;
}
aURI = aURI.spec;
switch (aURI) {
case pageurl:
ok(aValue, "Favicon value is not null for page without fragment.");
originalFavicon = aValue;
// Now that the favicon has loaded, click on fragment link.
// This should trigger the |case fragmenturl| below.
clickLinkIfReady();
return;
case fragmenturl:
// If the fragment URL's favicon isn't set, this branch won't
// be called and the test will time out.
is(aValue, originalFavicon, "New favicon should be same as original favicon.");
// Let's explicitly check that we can get the favicon
// from nsINavHistoryService now.
let info = getNavHistoryEntry(makeURI(aURI));
ok(info, "There must be a history entry for the fragment.");
ok(info.icon, "The history entry must have an associated favicon.");
historyService.removeObserver(historyObserver, false);
gBrowser.removeCurrentTab();
finish();
}
},
onPageExpired: function(aURI, aVisitTime, aWholeEntry) {},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsINavHistoryObserver) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
};
historyService.addObserver(historyObserver, false);
function onPageLoad() {
gBrowser.selectedBrowser
.removeEventListener("DOMContentLoaded", arguments.callee, true);
clickLinkIfReady();
}
// Make sure neither of the test pages haven't been loaded before.
var info = getNavHistoryEntry(makeURI(pageurl));
ok(!info, "The test page must not have been visited already.");
info = getNavHistoryEntry(makeURI(fragmenturl));
ok(!info, "The fragment test page must not have been visited already.");
// Now open the test page in a new tab.
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener(
"DOMContentLoaded", onPageLoad, true);
content.location = pageurl;
}

Просмотреть файл

@ -0,0 +1,31 @@
<head>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="/>
<title>Page Title for Bug 420605</title>
</head>
<body>
<h1>Fragment links</h1>
<p>This page has a bunch of fragment links to sections below:</p>
<ul>
<li><a id="firefox-link" href="#firefox">Firefox</a></li>
<li><a id="thunderbird-link" href="#thunderbird">Thunderbird</a></li>
<li><a id="seamonkey-link" href="#seamonkey">Seamonkey</a></li>
</ul>
<p>And here are the sections:</p>
<h2 id="firefox">Firefox</h2>
<p>Firefox is a browser.</p>
<h2 id="thunderbird">Thunderbird</h2>
<p>Thunderbird is an email client</p>
<h2 id="seamonkey">Seamonkey</h2>
<p>Seamonkey is the all-in-one application.</p>
</body>
</html>