diff --git a/toolkit/components/places/public/nsIFaviconService.idl b/toolkit/components/places/public/nsIFaviconService.idl index 3a9cd6be542a..1431ec86c024 100644 --- a/toolkit/components/places/public/nsIFaviconService.idl +++ b/toolkit/components/places/public/nsIFaviconService.idl @@ -58,12 +58,12 @@ interface nsIFaviconService : nsISupports * the page might not get a notification sent for it since data setting does * not send notifications. * - * @param aPage + * @param aPageURI * URI of the page whose favicon is being set. - * @param aFavicon + * @param aFaviconURI * URI of the favicon to associate with the page. */ - void setFaviconUrlForPage(in nsIURI aPage, in nsIURI aFavicon); + void setFaviconUrlForPage(in nsIURI aPageURI, in nsIURI aFaviconURI); /** * Same as SetFaviconUrlForPage except that this also attempts to set the @@ -77,27 +77,27 @@ interface nsIFaviconService : nsISupports * a reload of the data. This will remove the favicon from the failed * cache. If it then fails again, it will be re-added to the failed cache. * - * SetFaviconUrlForPage and SetFaviconData will take any URL you provide + * SetFaviconUrlForPage and SetFaviconData will take any URI you provide * and save it. This function is intended for automatic usage, and will - * only save favicons for "good" URLs, as defined by what gets added to - * history. For "bad" URLs, this function will succeed and do nothing. - * This function will also ignore favicons that are data URLs. Icons that + * only save favicons for "good" URIs, as defined by what gets added to + * history. For "bad" URIs, this function will succeed and do nothing. + * This function will also ignore favicons that are data URIs. Icons that * fail to load will automatically be added to the failed favicon cache. * - * This function will not save favicons for non-bookmarked URLs when + * This function will not save favicons for non-bookmarked URIs when * history is disabled (expiration time is 0 days). The rest of the functions * here will always store favicons even when history is disabled. * - * @param aPage + * @param aPageURI * URI of the page whose favicon is being set. - * @param aFavicon + * @param aFaviconURI * URI of the favicon to associate with the page. * @param aForceReload * Unset is normal behavior, we will only try to reload the favicon * if we don't have it or if it has expired from the cache. If set, * it will always try to reload the favicon. */ - void setAndLoadFaviconForPage(in nsIURI aPage, in nsIURI aFavicon, + void setAndLoadFaviconForPage(in nsIURI aPageURI, in nsIURI aFaviconURI, in boolean aForceReload); /** @@ -118,7 +118,7 @@ interface nsIFaviconService : nsISupports * The expiration time is stored. This will be used if you call * SetAndLoadFaviconForPage to see whether the data needs reloading. * - * Do not use this function for chrome: icon URLs. You should reference the + * Do not use this function for chrome: icon URIs. You should reference the * chrome image yourself. The GetFaviconLinkForIcon/Page will ignore any * associated data if the favicon URI is "chrome:" and just return the same * chrome URI. @@ -129,7 +129,7 @@ interface nsIFaviconService : nsISupports * notifications is very intensive. Those pages will keep the old icon * until they have been refreshed by other means. * - * @param aFavicon + * @param aFaviconURI * URI of the favicon whose data is being set. * @param aData * Binary contents of the favicon to save @@ -142,7 +142,7 @@ interface nsIFaviconService : nsISupports * Time in microseconds since the epoch when this favicon expires. * Until this time, we won't try to load it again. */ - void setFaviconData(in nsIURI aFavicon, + void setFaviconData(in nsIURI aFaviconURI, [const,array,size_is(aDataLen)] in octet aData, in unsigned long aDataLen, in AUTF8String aMimeType, in PRTime aExpiration); @@ -153,28 +153,28 @@ interface nsIFaviconService : nsISupports * If there is no data but we have an entry for this favicon, aDataLen will * be 0 and aData will be NULL. * - * @param aFavicon - * URL of the favicon whose data is being read + * @param aFaviconURI + * URI of the favicon whose data is being read * @param aData * Output parameter where the binary favicon data will be placed. - * This will be null if we have this URL but have no data associated + * This will be null if we have this URI but have no data associated * with it. * @param aDataLen * Output parameter where the size of the binary data will be placed. * @param aMimeType * Output parameter where the MIME type will be placed. * @throws NS_ERROR_NOT_AVAILABLE - * Thrown when we have never heard of this favicon URL. + * Thrown when we have never heard of this favicon URI. */ - void getFaviconData(in nsIURI aFavicon, + void getFaviconData(in nsIURI aFaviconURI, out AUTF8String aMimeType, out unsigned long aDataLen, [array,retval,size_is(aDataLen)] out octet aData); /** - * Retrieves the URL of the favicon for the given page. + * Retrieves the URI of the favicon for the given page. * - * @param aPage + * @param aPageURI * URI of the page whose favicon is desired * @returns The URI of the favicon associated with that page. Returning a * URI here does NOT mean that we have data for this favicon, only @@ -182,7 +182,7 @@ interface nsIFaviconService : nsISupports * @throws NS_ERROR_NOT_AVAILABLE * When the page is not found or it has no favicon. */ - nsIURI getFaviconForPage(in nsIURI aPage); + nsIURI getFaviconForPage(in nsIURI aPageURI); /** * For a given page, this will give you a URI that, when displayed in chrome, @@ -194,7 +194,7 @@ interface nsIFaviconService : nsISupports * This function only adds the extra level of indirection, looking up * the favicon based on the page URI and using the default if not found. * - * @param aPage + * @param aPageURI * URI of the page whose favicon is desired * @returns A URI that will give you the icon image. This is NOT the URI of * the icon as set on the page, but a URI that will give you the @@ -204,7 +204,7 @@ interface nsIFaviconService : nsISupports * service. For pages where we don't have a favicon, this will be a * chrome URI of the default icon for a web page. */ - nsIURI getFaviconImageForPage(in nsIURI aPage); + nsIURI getFaviconImageForPage(in nsIURI aPageURI); /** * For a given icon URI, this will return a URI that will result in the image. @@ -212,8 +212,8 @@ interface nsIFaviconService : nsISupports * and return the input URI. For NULL input, this will return the URI of * the default favicon. * - * @param aIcon - * The URL of an icon in the favicon service. Can be NULL. + * @param aFaviconURI + * The URI of an icon in the favicon service. Can be NULL. * @returns A URI that will load the desired icon. This is NOT the URI of the * icon as set on the page, but a URI that will give you the data * out of the favicon service. For a normal page with a favicon @@ -231,7 +231,7 @@ interface nsIFaviconService : nsISupports * the default icon, although without caching. For invalid chrome * URIs, you'll get a broken image. */ - nsIURI getFaviconLinkForIcon(in nsIURI aIcon); + nsIURI getFaviconLinkForIcon(in nsIURI aFaviconURI); /** * Adds a given favicon's URI to the failed favicon cache. @@ -242,13 +242,13 @@ interface nsIFaviconService : nsISupports * * @see isFailedFavicon */ - void addFailedFavicon(in nsIURI aIcon); + void addFailedFavicon(in nsIURI aFaviconURI); /** * Removes the given favicon from the failed favicon cache. If the icon is * not in the cache, this function will silently succeed. */ - void removeFailedFavicon(in nsIURI aIcon); + void removeFailedFavicon(in nsIURI aFaviconURI); /** * Checks to see if this favicon is in the failed favicon cache. Returns true @@ -257,10 +257,10 @@ interface nsIFaviconService : nsISupports * This allows you to avoid trying to load "foo.com/favicon.ico" for every * page on a site that doesn't have a favicon. */ - boolean isFailedFavicon(in nsIURI aIcon); + boolean isFailedFavicon(in nsIURI aFaviconURI); /** - * The default favicon URL + * The default favicon URI */ readonly attribute nsIURI defaultFavicon; }; diff --git a/toolkit/components/places/src/nsFaviconService.cpp b/toolkit/components/places/src/nsFaviconService.cpp index 59001a90b40b..b5dcb963baa9 100644 --- a/toolkit/components/places/src/nsFaviconService.cpp +++ b/toolkit/components/places/src/nsFaviconService.cpp @@ -131,32 +131,44 @@ nsFaviconService::~nsFaviconService() nsresult nsFaviconService::Init() { - nsresult rv; - + // creation of history service will call InitTables nsNavHistory* historyService = nsNavHistory::GetHistoryService(); NS_ENSURE_TRUE(historyService, NS_ERROR_OUT_OF_MEMORY); mDBConn = historyService->GetStorageConnection(); NS_ENSURE_TRUE(mDBConn, NS_ERROR_FAILURE); - // creation of history service will have called InitTables before now + nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT id, length(data), expiration FROM moz_favicons WHERE url = ?1"), + getter_AddRefs(mDBGetIconInfo)); + NS_ENSURE_SUCCESS(rv, rv); - rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT id, length(data), expiration FROM moz_favicons WHERE url = ?1"), - getter_AddRefs(mDBGetIconInfo)); + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT f.id, f.url, length(f.data), f.expiration " + "FROM moz_places h JOIN moz_favicons f ON h.favicon_id = f.id " + "WHERE h.url = ?1"), + getter_AddRefs(mDBGetURL)); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT f.id, f.url, length(f.data), f.expiration FROM moz_places h JOIN moz_favicons f ON h.favicon_id = f.id WHERE h.url = ?1"), - getter_AddRefs(mDBGetURL)); + + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT f.data, f.mime_type FROM moz_favicons f WHERE url = ?1"), + getter_AddRefs(mDBGetData)); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT f.data, f.mime_type FROM moz_favicons f WHERE url = ?1"), - getter_AddRefs(mDBGetData)); + + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "INSERT INTO moz_favicons (url, data, mime_type, expiration) " + "VALUES (?1, ?2, ?3, ?4)"), + getter_AddRefs(mDBInsertIcon)); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_favicons (url, data, mime_type, expiration) VALUES (?1, ?2, ?3, ?4)"), - getter_AddRefs(mDBInsertIcon)); + + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "UPDATE moz_favicons SET data = ?2, mime_type = ?3, expiration = ?4 " + "WHERE id = ?1"), + getter_AddRefs(mDBUpdateIcon)); NS_ENSURE_SUCCESS(rv, rv); - rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("UPDATE moz_favicons SET data = ?2, mime_type = ?3, expiration = ?4 where id = ?1"), - getter_AddRefs(mDBUpdateIcon)); - NS_ENSURE_SUCCESS(rv, rv); - rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("UPDATE moz_places SET favicon_id = ?2 WHERE id = ?1"), - getter_AddRefs(mDBSetPageFavicon)); + + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "UPDATE moz_places SET favicon_id = ?2 WHERE id = ?1"), + getter_AddRefs(mDBSetPageFavicon)); NS_ENSURE_SUCCESS(rv, rv); // failed favicon cache @@ -180,7 +192,12 @@ nsFaviconService::InitTables(mozIStorageConnection* aDBConn) PRBool exists = PR_FALSE; aDBConn->TableExists(NS_LITERAL_CSTRING("moz_favicons"), &exists); if (! exists) { - rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE TABLE moz_favicons (id INTEGER PRIMARY KEY, url LONGVARCHAR UNIQUE, data BLOB, mime_type VARCHAR(32), expiration LONG)")); + rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE TABLE moz_favicons (id INTEGER PRIMARY KEY, " + "url LONGVARCHAR UNIQUE, " + "data BLOB, " + "mime_type VARCHAR(32), " + "expiration LONG)")); NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; @@ -190,18 +207,21 @@ nsFaviconService::InitTables(mozIStorageConnection* aDBConn) // nsFaviconService::SetFaviconUrlForPage NS_IMETHODIMP -nsFaviconService::SetFaviconUrlForPage(nsIURI* aPage, nsIURI* aFavicon) +nsFaviconService::SetFaviconUrlForPage(nsIURI* aPageURI, nsIURI* aFaviconURI) { + NS_ENSURE_ARG_POINTER(aPageURI); + NS_ENSURE_ARG_POINTER(aFaviconURI); + // we don't care whether there was data or what the expiration was PRBool hasData; PRTime expiration; - nsresult rv = SetFaviconUrlForPageInternal(aPage, aFavicon, + nsresult rv = SetFaviconUrlForPageInternal(aPageURI, aFaviconURI, &hasData, &expiration); NS_ENSURE_SUCCESS(rv, rv); // send favicon change notifications if the URL has any data if (hasData) - SendFaviconNotifications(aPage, aFavicon); + SendFaviconNotifications(aPageURI, aFaviconURI); return NS_OK; } @@ -222,7 +242,7 @@ nsFaviconService::GetDefaultFavicon(nsIURI** _retval) // nsFaviconService::SetFaviconUrlForPageInternal // // This creates a new entry in the favicon table if necessary and tells the -// history service to associate the given favicon ID with the given URL. We +// history service to associate the given favicon ID with the given URI. We // don't want to update the history table directly since that may involve // creating a new row in the history table, which should only be done by // history. @@ -236,53 +256,48 @@ nsFaviconService::GetDefaultFavicon(nsIURI** _retval) // if the favicon has data. nsresult -nsFaviconService::SetFaviconUrlForPageInternal(nsIURI* aPage, nsIURI* aFavicon, +nsFaviconService::SetFaviconUrlForPageInternal(nsIURI* aPageURI, + nsIURI* aFaviconURI, PRBool* aHasData, PRTime* aExpiration) { - mozStorageStatementScoper scoper(mDBGetIconInfo); + nsresult rv; + PRInt64 iconId = -1; mozStorageTransaction transaction(mDBConn, PR_FALSE); - nsresult rv = BindStatementURI(mDBGetIconInfo, 0, aFavicon); - NS_ENSURE_SUCCESS(rv, rv); - - PRBool hasResult; - rv = mDBGetIconInfo->ExecuteStep(&hasResult); - NS_ENSURE_SUCCESS(rv, rv); - - PRInt64 iconId; - if (hasResult) { - // have an entry for this icon already, just get the stats - rv = mDBGetIconInfo->GetInt64(0, &iconId); + { + mozStorageStatementScoper scoper(mDBGetIconInfo); + rv = BindStatementURI(mDBGetIconInfo, 0, aFaviconURI); NS_ENSURE_SUCCESS(rv, rv); - // see if there's data already - PRInt32 dataSize; - rv = mDBGetIconInfo->GetInt32(1, &dataSize); - NS_ENSURE_SUCCESS(rv, rv); - if (dataSize > 0) - *aHasData = PR_TRUE; + PRBool hasResult = PR_FALSE; + if (NS_SUCCEEDED(mDBGetIconInfo->ExecuteStep(&hasResult)) && hasResult) { + // We already have an entry for this icon, just get the stats + rv = mDBGetIconInfo->GetInt64(0, &iconId); + NS_ENSURE_SUCCESS(rv, rv); - // expiration - rv = mDBGetIconInfo->GetInt64(2, aExpiration); - NS_ENSURE_SUCCESS(rv, rv); + // see if this icon has data already + PRInt32 dataSize; + rv = mDBGetIconInfo->GetInt32(1, &dataSize); + NS_ENSURE_SUCCESS(rv, rv); + if (dataSize > 0) + *aHasData = PR_TRUE; - mDBGetIconInfo->Reset(); - scoper.Abandon(); - } else { - // create a new icon entry - mDBGetIconInfo->Reset(); - scoper.Abandon(); + // expiration + rv = mDBGetIconInfo->GetInt64(2, aExpiration); + NS_ENSURE_SUCCESS(rv, rv); + } + } + if (iconId == -1) { + // We did not find any entry, so create a new one *aHasData = PR_FALSE; *aExpiration = 0; - // no entry for this icon yet, create it - mozStorageStatementScoper scoper2(mDBInsertIcon); - rv = BindStatementURI(mDBInsertIcon, 0, aFavicon); + // not-binded params are automatically nullified by mozStorage + mozStorageStatementScoper scoper(mDBInsertIcon); + rv = BindStatementURI(mDBInsertIcon, 0, aFaviconURI); NS_ENSURE_SUCCESS(rv, rv); - mDBInsertIcon->BindNullParameter(1); - mDBInsertIcon->BindNullParameter(2); - mDBInsertIcon->BindNullParameter(3); + rv = mDBInsertIcon->Execute(); NS_ENSURE_SUCCESS(rv, rv); @@ -290,15 +305,15 @@ nsFaviconService::SetFaviconUrlForPageInternal(nsIURI* aPage, nsIURI* aFavicon, NS_ENSURE_SUCCESS(rv, rv); } - // now link our entry with the history service + // now link our icon entry with the page nsNavHistory* historyService = nsNavHistory::GetHistoryService(); NS_ENSURE_TRUE(historyService, NS_ERROR_OUT_OF_MEMORY); PRInt64 pageId; - rv = historyService->GetUrlIdFor(aPage, &pageId, PR_TRUE); + rv = historyService->GetUrlIdFor(aPageURI, &pageId, PR_TRUE); NS_ENSURE_SUCCESS(rv, rv); - mozStorageStatementScoper scoper2(mDBSetPageFavicon); + mozStorageStatementScoper scoper(mDBSetPageFavicon); rv = mDBSetPageFavicon->BindInt64Parameter(0, pageId); NS_ENSURE_SUCCESS(rv, rv); rv = mDBSetPageFavicon->BindInt64Parameter(1, iconId); @@ -306,7 +321,8 @@ nsFaviconService::SetFaviconUrlForPageInternal(nsIURI* aPage, nsIURI* aFavicon, rv = mDBSetPageFavicon->Execute(); NS_ENSURE_SUCCESS(rv, rv); - transaction.Commit(); + rv = transaction.Commit(); + NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } @@ -324,32 +340,36 @@ nsFaviconService::SetFaviconUrlForPageInternal(nsIURI* aPage, nsIURI* aFavicon, // page. nsresult -nsFaviconService::UpdateBookmarkRedirectFavicon(nsIURI* aPage, nsIURI* aFavicon) +nsFaviconService::UpdateBookmarkRedirectFavicon(nsIURI* aPageURI, + nsIURI* aFaviconURI) { - NS_ENSURE_TRUE(aPage, NS_ERROR_INVALID_ARG); - NS_ENSURE_TRUE(aFavicon, NS_ERROR_INVALID_ARG); + NS_ENSURE_ARG_POINTER(aPageURI); + NS_ENSURE_ARG_POINTER(aFaviconURI); nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService(); NS_ENSURE_TRUE(bookmarks, NS_ERROR_UNEXPECTED); nsCOMPtr bookmarkURI; - nsresult rv = bookmarks->GetBookmarkedURIFor(aPage, getter_AddRefs(bookmarkURI)); + nsresult rv = bookmarks->GetBookmarkedURIFor(aPageURI, + getter_AddRefs(bookmarkURI)); NS_ENSURE_SUCCESS(rv, rv); if (! bookmarkURI) return NS_OK; // no bookmark redirect PRBool sameAsBookmark; - if (NS_SUCCEEDED(bookmarkURI->Equals(aPage, &sameAsBookmark)) && sameAsBookmark) + if (NS_SUCCEEDED(bookmarkURI->Equals(aPageURI, &sameAsBookmark)) && + sameAsBookmark) return NS_OK; // bookmarked directly, not through a redirect PRBool hasData = PR_FALSE; PRTime expiration = 0; - rv = SetFaviconUrlForPageInternal(bookmarkURI, aFavicon, &hasData, &expiration); + rv = SetFaviconUrlForPageInternal(bookmarkURI, aFaviconURI, + &hasData, &expiration); NS_ENSURE_SUCCESS(rv, rv); if (hasData) { // send notifications - SendFaviconNotifications(bookmarkURI, aFavicon); + SendFaviconNotifications(bookmarkURI, aFaviconURI); } else { NS_WARNING("Calling UpdateBookmarkRedirectFavicon when you don't have data for the favicon yet."); } @@ -363,12 +383,13 @@ nsFaviconService::UpdateBookmarkRedirectFavicon(nsIURI* aPage, nsIURI* aFavicon) // when you know there is data loaded for the favicon. void -nsFaviconService::SendFaviconNotifications(nsIURI* aPage, nsIURI* aFaviconURI) +nsFaviconService::SendFaviconNotifications(nsIURI* aPageURI, + nsIURI* aFaviconURI) { nsCAutoString faviconSpec; nsNavHistory* historyService = nsNavHistory::GetHistoryService(); if (historyService && NS_SUCCEEDED(aFaviconURI->GetSpec(faviconSpec))) { - historyService->SendPageChangedNotification(aPage, + historyService->SendPageChangedNotification(aPageURI, nsINavHistoryObserver::ATTRIBUTE_FAVICON, NS_ConvertUTF8toUTF16(faviconSpec)); } @@ -378,19 +399,21 @@ nsFaviconService::SendFaviconNotifications(nsIURI* aPage, nsIURI* aFaviconURI) // nsFaviconService::SetAndLoadFaviconForPage NS_IMETHODIMP -nsFaviconService::SetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, +nsFaviconService::SetAndLoadFaviconForPage(nsIURI* aPageURI, + nsIURI* aFaviconURI, PRBool aForceReload) { - NS_ENSURE_ARG_POINTER(aPage); - NS_ENSURE_ARG_POINTER(aFavicon); + NS_ENSURE_ARG_POINTER(aPageURI); + NS_ENSURE_ARG_POINTER(aFaviconURI); #ifdef LAZY_ADD nsNavHistory* historyService = nsNavHistory::GetHistoryService(); NS_ENSURE_TRUE(historyService, NS_ERROR_OUT_OF_MEMORY); - return historyService->AddLazyLoadFaviconMessage(aPage, aFavicon, + return historyService->AddLazyLoadFaviconMessage(aPageURI, + aFaviconURI, aForceReload); #else - return DoSetAndLoadFaviconForPage(aPage, aFavicon, aForceReload); + return DoSetAndLoadFaviconForPage(aPageURI, aFaviconURI, aForceReload); #endif } @@ -398,10 +421,11 @@ nsFaviconService::SetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, // nsFaviconService::DoSetAndLoadFaviconForPage nsresult -nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, +nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPageURI, + nsIURI* aFaviconURI, PRBool aForceReload) { - nsCOMPtr page(aPage); + nsCOMPtr page(aPageURI); // don't load favicons when history is disabled nsNavHistory* history = nsNavHistory::GetHistoryService(); @@ -413,7 +437,7 @@ nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, NS_ENSURE_TRUE(bookmarks, NS_ERROR_UNEXPECTED); nsCOMPtr bookmarkURI; - nsresult rv = bookmarks->GetBookmarkedURIFor(aPage, + nsresult rv = bookmarks->GetBookmarkedURIFor(aPageURI, getter_AddRefs(bookmarkURI)); NS_ENSURE_SUCCESS(rv, rv); if (! bookmarkURI) { @@ -430,11 +454,11 @@ nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, // check the failed favicon cache PRBool previouslyFailed; - nsresult rv = IsFailedFavicon(aFavicon, &previouslyFailed); + nsresult rv = IsFailedFavicon(aFaviconURI, &previouslyFailed); NS_ENSURE_SUCCESS(rv, rv); if (previouslyFailed) { if (aForceReload) - RemoveFailedFavicon(aFavicon); // force reload clears from failed cache + RemoveFailedFavicon(aFaviconURI); // force reload clears from failed cache else return NS_OK; // ignore previously failed favicons } @@ -451,7 +475,7 @@ nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, // but that's prohibitive for now. This workaround just refuses to save the // favicon in this case. PRBool pageEqualsFavicon; - rv = page->Equals(aFavicon, &pageEqualsFavicon); + rv = page->Equals(aFaviconURI, &pageEqualsFavicon); NS_ENSURE_SUCCESS(rv, rv); if (pageEqualsFavicon) return NS_OK; @@ -460,7 +484,7 @@ nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, // a data URL as the favicon. The result is that we get the data URL in the // favicon table associated with the decoded version of the data URL. PRBool isDataURL; - rv = aFavicon->SchemeIs("data", &isDataURL); + rv = aFaviconURI->SchemeIs("data", &isDataURL); NS_ENSURE_SUCCESS(rv, rv); if (isDataURL) return NS_OK; @@ -475,7 +499,7 @@ nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, PRTime expiration = 0; { // scope for statement mozStorageStatementScoper scoper(mDBGetIconInfo); - rv = BindStatementURI(mDBGetIconInfo, 0, aFavicon); + rv = BindStatementURI(mDBGetIconInfo, 0, aFaviconURI); NS_ENSURE_SUCCESS(rv, rv); PRBool hasMatch; @@ -502,16 +526,16 @@ nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, nsCOMPtr oldFavicon; PRBool faviconsEqual; if (NS_SUCCEEDED(GetFaviconForPage(page, getter_AddRefs(oldFavicon))) && - NS_SUCCEEDED(aFavicon->Equals(oldFavicon, &faviconsEqual)) && + NS_SUCCEEDED(aFaviconURI->Equals(oldFavicon, &faviconsEqual)) && faviconsEqual) return NS_OK; // already set // This will associate the favicon URL with the page. - rv = SetFaviconUrlForPageInternal(page, aFavicon, &hasData, &expiration); + rv = SetFaviconUrlForPageInternal(page, aFaviconURI, &hasData, &expiration); NS_ENSURE_SUCCESS(rv, rv); - SendFaviconNotifications(page, aFavicon); - UpdateBookmarkRedirectFavicon(page, aFavicon); + SendFaviconNotifications(page, aFaviconURI); + UpdateBookmarkRedirectFavicon(page, aFaviconURI); return NS_OK; } @@ -519,11 +543,11 @@ nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr channel; - rv = ioservice->NewChannelFromURI(aFavicon, getter_AddRefs(channel)); + rv = ioservice->NewChannelFromURI(aFaviconURI, getter_AddRefs(channel)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr listener = - new FaviconLoadListener(this, page, aFavicon, channel); + new FaviconLoadListener(this, page, aFaviconURI, channel); NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY); nsCOMPtr listenerRequestor = do_QueryInterface(listener, &rv); @@ -546,7 +570,7 @@ nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPage, nsIURI* aFavicon, // send out notifications. NS_IMETHODIMP -nsFaviconService::SetFaviconData(nsIURI* aFavicon, const PRUint8* aData, +nsFaviconService::SetFaviconData(nsIURI* aFaviconURI, const PRUint8* aData, PRUint32 aDataLen, const nsACString& aMimeType, PRTime aExpiration) { @@ -574,7 +598,7 @@ nsFaviconService::SetFaviconData(nsIURI* aFavicon, const PRUint8* aData, // this block forces the scoper to reset our statement: necessary for the // next statement mozStorageStatementScoper scoper(mDBGetIconInfo); - rv = BindStatementURI(mDBGetIconInfo, 0, aFavicon); + rv = BindStatementURI(mDBGetIconInfo, 0, aFaviconURI); NS_ENSURE_SUCCESS(rv, rv); PRBool hasResult; @@ -591,7 +615,7 @@ nsFaviconService::SetFaviconData(nsIURI* aFavicon, const PRUint8* aData, } else { // insert new one (statement parameter 0 = favicon URL) statement = mDBInsertIcon; - rv = BindStatementURI(statement, 0, aFavicon); + rv = BindStatementURI(statement, 0, aFaviconURI); } NS_ENSURE_SUCCESS(rv, rv); } @@ -612,63 +636,57 @@ nsFaviconService::SetFaviconData(nsIURI* aFavicon, const PRUint8* aData, // nsFaviconService::GetFaviconData NS_IMETHODIMP -nsFaviconService::GetFaviconData(nsIURI* aFavicon, nsACString& aMimeType, +nsFaviconService::GetFaviconData(nsIURI* aFaviconURI, nsACString& aMimeType, PRUint32* aDataLen, PRUint8** aData) { mozStorageStatementScoper scoper(mDBGetData); - nsresult rv = BindStatementURI(mDBGetData, 0, aFavicon); + nsresult rv = BindStatementURI(mDBGetData, 0, aFaviconURI); NS_ENSURE_SUCCESS(rv, rv); - PRBool hasResult; - rv = mDBGetData->ExecuteStep(&hasResult); - NS_ENSURE_SUCCESS(rv, rv); - if (! hasResult) - return NS_ERROR_NOT_AVAILABLE; + PRBool hasResult = PR_FALSE; + if (NS_SUCCEEDED(mDBGetData->ExecuteStep(&hasResult)) && hasResult) { + rv = mDBGetData->GetUTF8String(1, aMimeType); + NS_ENSURE_SUCCESS(rv, rv); - rv = mDBGetData->GetUTF8String(1, aMimeType); - NS_ENSURE_SUCCESS(rv, rv); - return mDBGetData->GetBlob(0, aDataLen, aData); + return mDBGetData->GetBlob(0, aDataLen, aData); + } + return NS_ERROR_NOT_AVAILABLE; } // nsFaviconService::GetFaviconForPage NS_IMETHODIMP -nsFaviconService::GetFaviconForPage(nsIURI* aPage, nsIURI** _retval) +nsFaviconService::GetFaviconForPage(nsIURI* aPageURI, nsIURI** _retval) { mozStorageStatementScoper scoper(mDBGetURL); - nsresult rv = BindStatementURI(mDBGetURL, 0, aPage); + nsresult rv = BindStatementURI(mDBGetURL, 0, aPageURI); NS_ENSURE_SUCCESS(rv, rv); PRBool hasResult; - rv = mDBGetURL->ExecuteStep(&hasResult); - NS_ENSURE_SUCCESS(rv, rv); - if (! hasResult) - return NS_ERROR_NOT_AVAILABLE; + if (NS_SUCCEEDED(mDBGetURL->ExecuteStep(&hasResult)) && hasResult) { + nsCAutoString url; + rv = mDBGetURL->GetUTF8String(1, url); + NS_ENSURE_SUCCESS(rv, rv); - nsCAutoString url; - rv = mDBGetURL->GetUTF8String(1, url); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_NewURI(_retval, url); + return NS_NewURI(_retval, url); + } + return NS_ERROR_NOT_AVAILABLE; } // nsFaviconService::GetFaviconImageForPage NS_IMETHODIMP -nsFaviconService::GetFaviconImageForPage(nsIURI* aPage, nsIURI** _retval) +nsFaviconService::GetFaviconImageForPage(nsIURI* aPageURI, nsIURI** _retval) { mozStorageStatementScoper scoper(mDBGetURL); - nsresult rv = BindStatementURI(mDBGetURL, 0, aPage); + nsresult rv = BindStatementURI(mDBGetURL, 0, aPageURI); NS_ENSURE_SUCCESS(rv, rv); PRBool hasResult; - rv = mDBGetURL->ExecuteStep(&hasResult); - NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr faviconURI; - if (hasResult) - { + if (NS_SUCCEEDED(mDBGetURL->ExecuteStep(&hasResult)) && hasResult) { PRInt32 dataLen; rv = mDBGetURL->GetInt32(2, &dataLen); NS_ENSURE_SUCCESS(rv, rv); @@ -690,14 +708,15 @@ nsFaviconService::GetFaviconImageForPage(nsIURI* aPage, nsIURI** _retval) // nsFaviconService::GetFaviconLinkForIcon nsresult -nsFaviconService::GetFaviconLinkForIcon(nsIURI* aIcon, nsIURI** aOutput) +nsFaviconService::GetFaviconLinkForIcon(nsIURI* aFaviconURI, + nsIURI** aOutputURI) { nsCAutoString spec; - if (aIcon) { - nsresult rv = aIcon->GetSpec(spec); + if (aFaviconURI) { + nsresult rv = aFaviconURI->GetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); } - return GetFaviconLinkForIconString(spec, aOutput); + return GetFaviconLinkForIconString(spec, aOutputURI); } @@ -715,10 +734,10 @@ ExpireFailedFaviconsCallback(nsCStringHashKey::KeyType aKey, } NS_IMETHODIMP -nsFaviconService::AddFailedFavicon(nsIURI* aIcon) +nsFaviconService::AddFailedFavicon(nsIURI* aFaviconURI) { nsCAutoString spec; - nsresult rv = aIcon->GetSpec(spec); + nsresult rv = aFaviconURI->GetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); if (! mFailedFavicons.Put(spec, mFailedFaviconSerial)) @@ -729,7 +748,7 @@ nsFaviconService::AddFailedFavicon(nsIURI* aIcon) // need to expire some entries, delete the FAVICON_CACHE_REDUCE_COUNT number // of items that are the oldest PRUint32 threshold = mFailedFaviconSerial - - MAX_FAVICON_CACHE_SIZE + FAVICON_CACHE_REDUCE_COUNT; + MAX_FAVICON_CACHE_SIZE + FAVICON_CACHE_REDUCE_COUNT; mFailedFavicons.Enumerate(ExpireFailedFaviconsCallback, &threshold); } return NS_OK; @@ -739,10 +758,10 @@ nsFaviconService::AddFailedFavicon(nsIURI* aIcon) // nsFaviconService::RemoveFailedFavicon NS_IMETHODIMP -nsFaviconService::RemoveFailedFavicon(nsIURI* aIcon) +nsFaviconService::RemoveFailedFavicon(nsIURI* aFaviconURI) { nsCAutoString spec; - nsresult rv = aIcon->GetSpec(spec); + nsresult rv = aFaviconURI->GetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); // we silently do nothing and succeed if the icon is not in the cache @@ -754,11 +773,11 @@ nsFaviconService::RemoveFailedFavicon(nsIURI* aIcon) // nsFaviconService::IsFailedFavicon NS_IMETHODIMP -nsFaviconService::IsFailedFavicon(nsIURI* aIcon, PRBool* _retval) +nsFaviconService::IsFailedFavicon(nsIURI* aFaviconURI, PRBool* _retval) { - NS_ENSURE_ARG(aIcon); + NS_ENSURE_ARG(aFaviconURI); nsCAutoString spec; - nsresult rv = aIcon->GetSpec(spec); + nsresult rv = aFaviconURI->GetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); PRUint32 serial; @@ -773,7 +792,8 @@ nsFaviconService::IsFailedFavicon(nsIURI* aIcon, PRBool* _retval) // default one to minimize parsing. nsresult -nsFaviconService::GetFaviconLinkForIconString(const nsCString& aSpec, nsIURI** aOutput) +nsFaviconService::GetFaviconLinkForIconString(const nsCString& aSpec, + nsIURI** aOutput) { if (aSpec.IsEmpty()) { // default icon for empty strings @@ -804,7 +824,8 @@ nsFaviconService::GetFaviconLinkForIconString(const nsCString& aSpec, nsIURI** a // the tree view implementation), sparing all parsing and normalization. void -nsFaviconService::GetFaviconSpecForIconString(const nsCString& aSpec, nsACString& aOutput) +nsFaviconService::GetFaviconSpecForIconString(const nsCString& aSpec, + nsACString& aOutput) { if (aSpec.IsEmpty()) { aOutput.AssignLiteral(FAVICON_DEFAULT_URL); @@ -859,10 +880,9 @@ nsFaviconService::OptimizeFaviconImage(const PRUint8* aData, PRUint32 aDataLen, } -NS_IMPL_ISUPPORTS5(FaviconLoadListener, +NS_IMPL_ISUPPORTS4(FaviconLoadListener, nsIRequestObserver, nsIStreamListener, - nsIRequestObserver, nsIInterfaceRequestor, nsIChannelEventSink) @@ -982,9 +1002,11 @@ FaviconLoadListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, // FaviconLoadListener::OnDataAvailable (nsIStreamListener) NS_IMETHODIMP -FaviconLoadListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, - nsIInputStream *aInputStream, - PRUint32 aOffset, PRUint32 aCount) +FaviconLoadListener::OnDataAvailable(nsIRequest *aRequest, + nsISupports *aContext, + nsIInputStream *aInputStream, + PRUint32 aOffset, + PRUint32 aCount) { nsCString buffer; nsresult rv = NS_ConsumeStream(aInputStream, aCount, buffer); @@ -1009,7 +1031,8 @@ FaviconLoadListener::GetInterface(const nsIID& uuid, void** aResult) NS_IMETHODIMP FaviconLoadListener::OnChannelRedirect(nsIChannel* oldChannel, - nsIChannel* newChannel, PRUint32 flags) + nsIChannel* newChannel, + PRUint32 flags) { mChannel = newChannel; return NS_OK; diff --git a/toolkit/components/places/src/nsNavHistory.cpp b/toolkit/components/places/src/nsNavHistory.cpp index 6fcd0069af48..8b9976c316d6 100644 --- a/toolkit/components/places/src/nsNavHistory.cpp +++ b/toolkit/components/places/src/nsNavHistory.cpp @@ -4876,8 +4876,6 @@ nsNavHistory::CommitLazyMessages() case LazyMessage::Type_Favicon: { nsFaviconService* faviconService = nsFaviconService::GetFaviconService(); if (faviconService) { - nsCString spec; - message.uri->GetSpec(spec); faviconService->DoSetAndLoadFaviconForPage(message.uri, message.favicon, message.alwaysLoadFavicon); diff --git a/toolkit/components/places/src/nsNavHistoryResult.cpp b/toolkit/components/places/src/nsNavHistoryResult.cpp index f059fe492b7d..1017521a950f 100644 --- a/toolkit/components/places/src/nsNavHistoryResult.cpp +++ b/toolkit/components/places/src/nsNavHistoryResult.cpp @@ -136,12 +136,12 @@ nsNavHistoryResultNode::nsNavHistoryResultNode( NS_IMETHODIMP nsNavHistoryResultNode::GetIcon(nsIURI** aURI) { - nsFaviconService* faviconService = nsFaviconService::GetFaviconService(); - NS_ENSURE_TRUE(faviconService, NS_ERROR_OUT_OF_MEMORY); if (mFaviconURI.IsEmpty()) { *aURI = nsnull; return NS_OK; } + nsFaviconService* faviconService = nsFaviconService::GetFaviconService(); + NS_ENSURE_TRUE(faviconService, NS_ERROR_OUT_OF_MEMORY); return faviconService->GetFaviconLinkForIconString(mFaviconURI, aURI); } diff --git a/toolkit/components/places/tests/unit/test_favicons.js b/toolkit/components/places/tests/unit/test_favicons.js index 99b634665903..5332e8ed2ad2 100644 --- a/toolkit/components/places/tests/unit/test_favicons.js +++ b/toolkit/components/places/tests/unit/test_favicons.js @@ -11,25 +11,25 @@ const TESTDIR = "toolkit/components/places/tests/unit/"; * Call |dumpToFile(outData);| in a test to file to a file. */ function dumpToFile(aData) { - const path = "/tmp"; + const path = "/tmp"; - var outputFile = Cc["@mozilla.org/file/local;1"]. - createInstance(Ci.nsILocalFile); - outputFile.initWithPath(path); - outputFile.append("testdump.png"); + var outputFile = Cc["@mozilla.org/file/local;1"]. + createInstance(Ci.nsILocalFile); + outputFile.initWithPath(path); + outputFile.append("testdump.png"); - var outputStream = Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(Ci.nsIFileOutputStream); - // WR_ONLY|CREAT|TRUNC - outputStream.init(outputFile, 0x02 | 0x08 | 0x20, 0644, null); + var outputStream = Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(Ci.nsIFileOutputStream); + // WR_ONLY|CREAT|TRUNC + outputStream.init(outputFile, 0x02 | 0x08 | 0x20, 0644, null); - var bos = Cc["@mozilla.org/binaryoutputstream;1"]. - createInstance(Ci.nsIBinaryOutputStream); - bos.setOutputStream(outputStream); + var bos = Cc["@mozilla.org/binaryoutputstream;1"]. + createInstance(Ci.nsIBinaryOutputStream); + bos.setOutputStream(outputStream); - bos.writeByteArray(aData, aData.length); + bos.writeByteArray(aData, aData.length); - outputStream.close(); + outputStream.close(); } /* @@ -38,23 +38,23 @@ function dumpToFile(aData) { * Reads the data from the specified nsIFile, and returns an array of bytes. */ function readFileData(aFile) { - var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - // init the stream as RD_ONLY, -1 == default permissions. - inputStream.init(aFile, 0x01, -1, null); - var size = inputStream.available(); + var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Ci.nsIFileInputStream); + // init the stream as RD_ONLY, -1 == default permissions. + inputStream.init(aFile, 0x01, -1, null); + var size = inputStream.available(); - // use a binary input stream to grab the bytes. - var bis = Cc["@mozilla.org/binaryinputstream;1"]. - createInstance(Ci.nsIBinaryInputStream); - bis.setInputStream(inputStream); + // use a binary input stream to grab the bytes. + var bis = Cc["@mozilla.org/binaryinputstream;1"]. + createInstance(Ci.nsIBinaryInputStream); + bis.setInputStream(inputStream); - var bytes = bis.readByteArray(size); + var bytes = bis.readByteArray(size); - if (size != bytes.length) - throw "Didn't read expected number of bytes"; + if (size != bytes.length) + throw "Didn't read expected number of bytes"; - return bytes; + return bytes; } @@ -66,18 +66,18 @@ function readFileData(aFile) { * and array of bytes and mimetype. */ function setAndGetFaviconData(aFilename, aData, aMimeType) { - var iconURI = uri("http://places.test/" + aFilename); + var iconURI = uri("http://places.test/" + aFilename); - iconsvc.setFaviconData(iconURI, - aData, aData.length, aMimeType, - Number.MAX_VALUE); + iconsvc.setFaviconData(iconURI, + aData, aData.length, aMimeType, + Number.MAX_VALUE); - var mimeTypeOutparam = {}; + var mimeTypeOutparam = {}; - var outData = iconsvc.getFaviconData(iconURI, - mimeTypeOutparam, {}); + var outData = iconsvc.getFaviconData(iconURI, + mimeTypeOutparam, {}); - return [outData, mimeTypeOutparam.value]; + return [outData, mimeTypeOutparam.value]; } @@ -87,40 +87,45 @@ function setAndGetFaviconData(aFilename, aData, aMimeType) { * Compares two arrays, and throws if there's a difference. */ function compareArrays(aArray1, aArray2) { - do_check_eq(aArray1.length, aArray2.length); + do_check_eq(aArray1.length, aArray2.length); - for (var i = 0; i < aArray1.length; i++) - if (aArray1[i] != aArray2[i]) - throw "arrays differ at index " + i; + for (var i = 0; i < aArray1.length; i++) + if (aArray1[i] != aArray2[i]) + throw "arrays differ at index " + i; } -var iconsvc; +// Get favicon service +try { + var iconsvc = Cc["@mozilla.org/browser/favicon-service;1"]. + getService(Ci.nsIFaviconService); + + // Ugh, this is an ugly hack. The pixel values we get in Windows are sometimes + // +/- 1 value compared to other platforms, so we need to compare against a + // different set of reference images. nsIXULRuntime.OS doesn't seem to be + // available in xpcshell, so we'll use this as a kludgy way to figure out if + // we're running on Windows. + var isWindows = ("@mozilla.org/windows-registry-key;1" in Cc); +} catch(ex) { + do_throw("Could not get favicon service\n"); +} + +// Get history services +try { + var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsINavHistoryService); + var bhist = histsvc.QueryInterface(Ci.nsIBrowserHistory); +} catch(ex) { + do_throw("Could not get history services\n"); +} + function run_test() { try { -/* ========== 0 ========== */ -var testnum = 0; -var testdesc = "nsIFaviconService setup"; - -iconsvc = Cc["@mozilla.org/browser/favicon-service;1"]. - getService(Ci.nsIFaviconService); - -if (!iconsvc) - throw "Couldn't get nsIFaviconService service" - -// Ugh, this is an ugly hack. The pixel values we get in Windows are sometimes -// +/- 1 value compared to other platforms, so we need to compare against a -// different set of reference images. nsIXULRuntime.OS doesn't seem to be -// available in xpcshell, so we'll use this as a kludgy way to figure out if -// we're running on Windows. -var isWindows = ("@mozilla.org/windows-registry-key;1" in Cc); - - /* ========== 1 ========== */ -testnum++; -testdesc = "test storing a normal 16x16 icon"; +var testnum = 1; +var testdesc = "test storing a normal 16x16 icon"; // 16x16 png, 286 bytes. var iconName = "favicon-normal16.png"; @@ -324,6 +329,121 @@ do_check_eq("image/png", outMimeType); compareArrays(expectedData, outData); +/* ========== 10 ========== */ +testnum++; +testdesc = "test set and get favicon "; + +// 32x32 png, 344 bytes. +var icon1Name = "favicon-normal32.png"; +var icon1MimeType = "image/png"; +var icon1File = do_get_file(TESTDIR + icon1Name); +var icon1Data = readFileData(icon1File); +do_check_eq(icon1Data.length, 344); +var icon1URI = uri("file:///./" + TESTDIR + icon1Name); + +// 16x16 png, 286 bytes. +var icon2Name = "favicon-normal16.png"; +var icon2MimeType = "image/png"; +var icon2File = do_get_file(TESTDIR + icon2Name); +var icon2Data = readFileData(icon2File); +do_check_eq(icon2Data.length, 286); +var icon2URI = uri("file:///./" + TESTDIR + icon2Name); + +var page1URI = uri("http://foo.bar/"); +var page2URI = uri("http://bar.foo/"); +var page3URI = uri("http://foo.bar.moz/"); + +// add visits to the db +histsvc.addVisit(page1URI, Date.now() * 1000, null, + histsvc.TRANSITION_TYPED, false, 0); +histsvc.addVisit(page2URI, Date.now() * 1000, null, + histsvc.TRANSITION_TYPED, false, 0); +histsvc.addVisit(page3URI, Date.now() * 1000, null, + histsvc.TRANSITION_TYPED, false, 0); + +// set first page icon +iconsvc.setFaviconUrlForPage(page1URI, icon1URI); +iconsvc.setFaviconData(icon1URI, icon1Data, icon1Data.length, + icon1MimeType, Number.MAX_VALUE); +var savedIcon1URI = iconsvc.getFaviconForPage(page1URI); + +// set second page icon +iconsvc.setFaviconUrlForPage(page2URI, icon2URI); +iconsvc.setFaviconData(icon2URI, icon2Data, icon2Data.length, + icon2MimeType, Number.MAX_VALUE); +var savedIcon2URI = iconsvc.getFaviconForPage(page2URI); + +// set third page icon as the same as first page one +iconsvc.setFaviconUrlForPage(page3URI, icon1URI); +iconsvc.setFaviconData(icon1URI, icon1Data, icon1Data.length, + icon1MimeType, Number.MAX_VALUE); +var savedIcon3URI = iconsvc.getFaviconForPage(page3URI); + +// check first page icon +var out1MimeType = {}; +var out1Data = iconsvc.getFaviconData(savedIcon1URI, out1MimeType, {}); +do_check_eq(icon1MimeType, out1MimeType.value); +compareArrays(icon1Data, out1Data); + +// check second page icon +var out2MimeType = {}; +var out2Data = iconsvc.getFaviconData(savedIcon2URI, out2MimeType, {}); +do_check_eq(icon2MimeType, out2MimeType.value); +compareArrays(icon2Data, out2Data); + +// check third page icon +var out3MimeType = {}; +var out3Data = iconsvc.getFaviconData(savedIcon3URI, out3MimeType, {}); +do_check_eq(icon1MimeType, out3MimeType.value); +compareArrays(icon1Data, out3Data); + + +/* ========== 11 ========== */ +testnum++; +testdesc = "test setAndLoadFaviconForPage "; + +// 32x32 png, 344 bytes. +iconName = "favicon-normal32.png"; +inMimeType = "image/png"; +iconFile = do_get_file(TESTDIR + iconName); +inData = readFileData(iconFile); +do_check_eq(inData.length, 344); +var pageURI = uri("http://foo.bar/"); + +faviconURI = uri("file:///./" + TESTDIR + iconName); + +iconsvc.setAndLoadFaviconForPage(pageURI, faviconURI, true); + +var savedFaviconURI = iconsvc.getFaviconForPage(pageURI); +outMimeType = {}; +outData = iconsvc.getFaviconData(savedFaviconURI, outMimeType, {}); + +// Ensure input and output are identical +do_check_eq(inMimeType, outMimeType.value); +compareArrays(inData, outData); + + +/* ========== 12 ========== */ +testnum++; +testdesc = "test favicon links "; + +do_check_eq(iconsvc.getFaviconImageForPage(pageURI).spec, + iconsvc.getFaviconLinkForIcon(faviconURI).spec); + + +/* ========== 13 ========== */ +testnum++; +testdesc = "test failed favicon cache "; + +// 32x32 png, 344 bytes. +iconName = "favicon-normal32.png"; +faviconURI = uri("file:///./" + TESTDIR + iconName); + +iconsvc.addFailedFavicon(faviconURI); +do_check_true(iconsvc.isFailedFavicon(faviconURI)); +iconsvc.removeFailedFavicon(faviconURI); +do_check_false(iconsvc.isFailedFavicon(faviconURI)); + /* ========== end ========== */