зеркало из https://github.com/mozilla/gecko-dev.git
Bug 429832 - Add API to nsIFaviconService to handle data URIs (for manish@flock.com, r=marco, r=dietrich)
This commit is contained in:
Родитель
320876b222
Коммит
b6f0608f6d
|
@ -95,7 +95,6 @@
|
|||
#include "nsParserCIID.h"
|
||||
#include "nsStringAPI.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "plbase64.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsIPrefService.h"
|
||||
|
@ -424,7 +423,7 @@ protected:
|
|||
nsresult PopFrame();
|
||||
|
||||
nsresult SetFaviconForURI(nsIURI* aPageURI, nsIURI* aFaviconURI,
|
||||
const nsCString& aData);
|
||||
const nsString& aData);
|
||||
|
||||
PRInt64 ConvertImportedIdToInternalId(const nsCString& aId);
|
||||
PRTime ConvertImportedDateToInternalDate(const nsACString& aDate);
|
||||
|
@ -950,8 +949,7 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node)
|
|||
nsCOMPtr<nsIURI> iconUriObject;
|
||||
NS_NewURI(getter_AddRefs(iconUriObject), iconUri);
|
||||
if (!icon.IsEmpty() || iconUriObject) {
|
||||
rv = SetFaviconForURI(frame.mPreviousLink, iconUriObject,
|
||||
NS_ConvertUTF16toUTF8(icon));
|
||||
rv = SetFaviconForURI(frame.mPreviousLink, iconUriObject, icon);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1275,7 +1273,7 @@ BookmarkContentSink::PopFrame()
|
|||
|
||||
nsresult
|
||||
BookmarkContentSink::SetFaviconForURI(nsIURI* aPageURI, nsIURI* aIconURI,
|
||||
const nsCString& aData)
|
||||
const nsString& aData)
|
||||
{
|
||||
nsresult rv;
|
||||
static PRUint32 serialNumber = 0; // for made-up favicon URIs
|
||||
|
@ -1315,53 +1313,13 @@ BookmarkContentSink::SetFaviconForURI(nsIURI* aPageURI, nsIURI* aIconURI,
|
|||
serialNumber++;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> dataURI;
|
||||
rv = NS_NewURI(getter_AddRefs(dataURI), aData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// use the data: protocol handler to convert the data
|
||||
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIProtocolHandler> protocolHandler;
|
||||
rv = ioService->GetProtocolHandler("data", getter_AddRefs(protocolHandler));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = protocolHandler->NewChannel(dataURI, getter_AddRefs(channel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// blocking stream is OK for data URIs
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
rv = channel->Open(getter_AddRefs(stream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 available;
|
||||
rv = stream->Available(&available);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (available == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// read all the decoded data
|
||||
PRUint8* buffer = static_cast<PRUint8*>
|
||||
(nsMemory::Alloc(sizeof(PRUint8) * available));
|
||||
if (!buffer)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
PRUint32 numRead;
|
||||
rv = stream->Read(reinterpret_cast<char*>(buffer), available, &numRead);
|
||||
if (NS_FAILED(rv) || numRead != available) {
|
||||
nsMemory::Free(buffer);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCAutoString mimeType;
|
||||
rv = channel->GetContentType(mimeType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// save in service
|
||||
rv = faviconService->SetFaviconData(faviconURI, buffer, available, mimeType, 0);
|
||||
nsMemory::Free(buffer);
|
||||
rv = faviconService->SetFaviconDataFromDataURL(faviconURI, aData, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = faviconService->SetFaviconUrlForPage(aPageURI, faviconURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1496,27 +1454,6 @@ WriteContainerEpilogue(const nsACString& aIndent, nsIOutputStream* aOutput)
|
|||
}
|
||||
|
||||
|
||||
// DataToDataURI
|
||||
|
||||
static nsresult
|
||||
DataToDataURI(PRUint8* aData, PRUint32 aDataLen, const nsACString& aMimeType,
|
||||
nsACString& aDataURI)
|
||||
{
|
||||
char* encoded = PL_Base64Encode(reinterpret_cast<const char*>(aData),
|
||||
aDataLen, nsnull);
|
||||
if (!encoded)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
aDataURI.AssignLiteral("data:");
|
||||
aDataURI.Append(aMimeType);
|
||||
aDataURI.AppendLiteral(";base64,");
|
||||
aDataURI.Append(encoded);
|
||||
|
||||
nsMemory::Free(encoded);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// WriteFaviconAttribute
|
||||
//
|
||||
// This writes the 'ICON="data:asdlfkjas;ldkfja;skdljfasdf"' attribute for
|
||||
|
@ -1560,22 +1497,14 @@ WriteFaviconAttribute(const nsACString& aURI, nsIOutputStream* aOutput)
|
|||
if (!faviconScheme.EqualsLiteral("chrome")) {
|
||||
// only store data for non-chrome URIs
|
||||
|
||||
// get the data - BE SURE TO FREE
|
||||
nsCAutoString mimeType;
|
||||
PRUint32 dataLen;
|
||||
PRUint8* data;
|
||||
rv = faviconService->GetFaviconData(faviconURI, mimeType, &dataLen, &data);
|
||||
nsAutoString faviconContents;
|
||||
rv = faviconService->GetFaviconDataAsDataURL(faviconURI, faviconContents);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (dataLen > 0) {
|
||||
// convert to URI
|
||||
nsCString faviconContents;
|
||||
rv = DataToDataURI(data, dataLen, mimeType, faviconContents);
|
||||
nsMemory::Free(data);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (faviconContents.Length() > 0) {
|
||||
rv = aOutput->Write(kIconAttribute, sizeof(kIconAttribute)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aOutput->Write(faviconContents.get(), faviconContents.Length(), &dummy);
|
||||
NS_ConvertUTF16toUTF8 utf8Favicon(faviconContents);
|
||||
rv = aOutput->Write(utf8Favicon.get(), utf8Favicon.Length(), &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aOutput->Write(kQuoteStr, sizeof(kQuoteStr)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -64,6 +64,13 @@ try {
|
|||
do_throw("Could not get livemark service\n");
|
||||
}
|
||||
|
||||
// Get favicon service
|
||||
try {
|
||||
var iconsvc = Cc["@mozilla.org/browser/favicon-service;1"].getService(Ci.nsIFaviconService);
|
||||
} catch(ex) {
|
||||
do_throw("Could not get favicon service\n");
|
||||
}
|
||||
|
||||
// Get microsummary service
|
||||
try {
|
||||
var mssvc = Cc["@mozilla.org/microsummary/service;1"].getService(Ci.nsIMicrosummaryService);
|
||||
|
@ -82,6 +89,9 @@ const DESCRIPTION_ANNO = "bookmarkProperties/description";
|
|||
const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
|
||||
const POST_DATA_ANNO = "bookmarkProperties/POSTData";
|
||||
|
||||
const TEST_FAVICON_PAGE_URL = "http://en-US.www.mozilla.com/en-US/firefox/central/";
|
||||
const TEST_FAVICON_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==";
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
// get places import/export service
|
||||
|
@ -306,4 +316,9 @@ function testCanonicalBookmarks(aFolder) {
|
|||
unfiledBookmarks.containerOpen = true;
|
||||
do_check_eq(unfiledBookmarks.childCount, 1);
|
||||
unfiledBookmarks.containerOpen = false;
|
||||
|
||||
// favicons
|
||||
var faviconURI = iconsvc.getFaviconForPage(uri(TEST_FAVICON_PAGE_URL));
|
||||
var dataURL = iconsvc.getFaviconDataAsDataURL(faviconURI);
|
||||
do_check_eq(TEST_FAVICON_DATA_URL, dataURL);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
interface nsIURI;
|
||||
|
||||
[scriptable, uuid(91f635a4-2531-4f3d-89ef-81403a685f44)]
|
||||
[scriptable, uuid(fafe10e0-194f-4e89-aab9-a5849e97287c)]
|
||||
interface nsIFaviconService : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -148,6 +148,24 @@ interface nsIFaviconService : nsISupports
|
|||
in unsigned long aDataLen, in AUTF8String aMimeType,
|
||||
in PRTime aExpiration);
|
||||
|
||||
/**
|
||||
* Stores the data of a given favicon. The data is provided by a string
|
||||
* containing a data URL.
|
||||
*
|
||||
* @see setFaviconData
|
||||
*
|
||||
* @param aFaviconURI
|
||||
* URI of the favicon whose data is being set.
|
||||
* @param aDataURL
|
||||
* string containing a data URL that represents the contents of
|
||||
* the favicon to save
|
||||
* @param aExpiration
|
||||
* Time in microseconds since the epoch when this favicon expires.
|
||||
* Until this time, we won't try to load it again.
|
||||
*/
|
||||
void setFaviconDataFromDataURL(in nsIURI aFaviconURI, in AString aDataURL,
|
||||
in PRTime aExpiration);
|
||||
|
||||
/**
|
||||
* Retrieves the given favicon data. Throws if we don't have data.
|
||||
*
|
||||
|
@ -172,6 +190,24 @@ interface nsIFaviconService : nsISupports
|
|||
out unsigned long aDataLen,
|
||||
[array,retval,size_is(aDataLen)] out octet aData);
|
||||
|
||||
/**
|
||||
* Retrieves the given favicon data as a data URL. Throws if we don't
|
||||
* have data.
|
||||
*
|
||||
* If there is no data but we have an entry for this favicon, the return
|
||||
* value will be NULL.
|
||||
*
|
||||
* @see getFaviconData
|
||||
*
|
||||
* @param aFaviconURI
|
||||
* URI of the favicon whose data is being read
|
||||
* @returns A data URL containing the data of the favicon. This will be
|
||||
* null if we have this URL but have no data associated with it.
|
||||
* @throws NS_ERROR_NOT_AVAILABLE
|
||||
* Thrown when we have never heard of this favicon URL.
|
||||
*/
|
||||
AString getFaviconDataAsDataURL(in nsIURI aFaviconURI);
|
||||
|
||||
/**
|
||||
* Retrieves the URI of the favicon for the given page.
|
||||
*
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "nsStreamUtils.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "mozStorageHelper.h"
|
||||
#include "plbase64.h"
|
||||
|
||||
// For favicon optimization
|
||||
#include "imgITools.h"
|
||||
|
@ -636,6 +637,66 @@ nsFaviconService::SetFaviconData(nsIURI* aFaviconURI, const PRUint8* aData,
|
|||
}
|
||||
|
||||
|
||||
// nsFaviconService::SetFaviconDataFromDataURL
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFaviconService::SetFaviconDataFromDataURL(nsIURI* aFaviconURI,
|
||||
const nsAString& aDataURL,
|
||||
PRTime aExpiration)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIURI> dataURI;
|
||||
rv = NS_NewURI(getter_AddRefs(dataURI), aDataURL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// use the data: protocol handler to convert the data
|
||||
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIProtocolHandler> protocolHandler;
|
||||
rv = ioService->GetProtocolHandler("data", getter_AddRefs(protocolHandler));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = protocolHandler->NewChannel(dataURI, getter_AddRefs(channel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// blocking stream is OK for data URIs
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
rv = channel->Open(getter_AddRefs(stream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 available;
|
||||
rv = stream->Available(&available);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (available == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// read all the decoded data
|
||||
PRUint8* buffer = static_cast<PRUint8*>
|
||||
(nsMemory::Alloc(sizeof(PRUint8) * available));
|
||||
if (!buffer)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
PRUint32 numRead;
|
||||
rv = stream->Read(reinterpret_cast<char*>(buffer), available, &numRead);
|
||||
if (NS_FAILED(rv) || numRead != available) {
|
||||
nsMemory::Free(buffer);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCAutoString mimeType;
|
||||
rv = channel->GetContentType(mimeType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// SetFaviconData can now do the dirty work
|
||||
rv = SetFaviconData(aFaviconURI, buffer, available, mimeType, aExpiration);
|
||||
nsMemory::Free(buffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsFaviconService::GetFaviconData
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -657,6 +718,43 @@ nsFaviconService::GetFaviconData(nsIURI* aFaviconURI, nsACString& aMimeType,
|
|||
}
|
||||
|
||||
|
||||
// nsFaviconService::GetFaviconDataAsDataURL
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFaviconService::GetFaviconDataAsDataURL(nsIURI* aFaviconURI,
|
||||
nsAString& aDataURL)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
PRUint8* data;
|
||||
PRUint32 dataLen;
|
||||
nsCAutoString mimeType;
|
||||
|
||||
rv = GetFaviconData(aFaviconURI, mimeType, &dataLen, &data);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!data) {
|
||||
aDataURL.SetIsVoid(PR_TRUE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
char* encoded = PL_Base64Encode(reinterpret_cast<const char*>(data),
|
||||
dataLen, nsnull);
|
||||
nsMemory::Free(data);
|
||||
|
||||
if (!encoded)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
aDataURL.AssignLiteral("data:");
|
||||
AppendUTF8toUTF16(mimeType, aDataURL);
|
||||
aDataURL.AppendLiteral(";base64,");
|
||||
AppendUTF8toUTF16(encoded, aDataURL);
|
||||
|
||||
nsMemory::Free(encoded);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsFaviconService::GetFaviconForPage
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -72,6 +72,9 @@ function setAndGetFaviconData(aFilename, aData, aMimeType) {
|
|||
aData, aData.length, aMimeType,
|
||||
Number.MAX_VALUE);
|
||||
|
||||
var dataURL = iconsvc.getFaviconDataAsDataURL(iconURI);
|
||||
iconsvc.setFaviconDataFromDataURL(iconURI, dataURL, Number.MAX_VALUE);
|
||||
|
||||
var mimeTypeOutparam = {};
|
||||
|
||||
var outData = iconsvc.getFaviconData(iconURI,
|
||||
|
|
Загрузка…
Ссылка в новой задаче