зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
d869da05f2
Коммит
00510b3b3f
|
@ -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>
|
Загрузка…
Ссылка в новой задаче