зеркало из https://github.com/mozilla/pjs.git
Bug 549472 - Add support for fave icons on jump list uri entries. r=jmathies, sr=gavin.sharp
This commit is contained in:
Родитель
9ff03ca7b4
Коммит
178a975663
|
@ -49,7 +49,7 @@ interface nsIJumpListBuilder : nsISupports
|
|||
*
|
||||
* Jump lists are built and then applied. Modifying an applied jump list is not
|
||||
* permitted. Callers should begin the creation of a new jump list using
|
||||
* initListBuild, add sub lists using addListBuild, then commit the jump list
|
||||
* initListBuild, add sub lists using addListToBuild, then commit the jump list
|
||||
* using commitListBuild. Lists are built in real-time during the sequence of
|
||||
* build calls, make sure to check for errors on each individual step.
|
||||
*
|
||||
|
@ -66,7 +66,7 @@ interface nsIJumpListBuilder : nsISupports
|
|||
* users have removed, applications are encoraged to track removed items
|
||||
* internally.
|
||||
*
|
||||
* Each list is made up of an array of nsIWinJumpListItems representing items
|
||||
* Each list is made up of an array of nsIJumpListItem representing items
|
||||
* such as shortcuts, links, and separators. See nsIJumpListItem for information
|
||||
* on adding additional jump list types.
|
||||
*/
|
||||
|
|
|
@ -129,7 +129,7 @@ interface nsIJumpListLink : nsIJumpListItem
|
|||
* A generic application shortcut with command line support.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(9664389E-11D6-4bea-B68C-D70232162068)]
|
||||
[scriptable, uuid(CBE3A37C-BCE1-4fec-80A5-5FFBC7F33EEA)]
|
||||
interface nsIJumpListShortcut : nsIJumpListItem
|
||||
{
|
||||
/**
|
||||
|
@ -147,5 +147,15 @@ interface nsIJumpListShortcut : nsIJumpListItem
|
|||
* within the the handler executable.
|
||||
*/
|
||||
attribute long iconIndex;
|
||||
|
||||
/**
|
||||
* Set or get the URI of an image to use as the jump list item icon.
|
||||
* The image will be retrieved, scaled to the needed size and converted
|
||||
* to the needed format.
|
||||
*
|
||||
* If there is an error setting the iconImageUri, the
|
||||
* app and iconIndex will be used to generate the icon.
|
||||
*/
|
||||
attribute nsIURI iconImageUri;
|
||||
};
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Jim Mathies <jmathies@mozilla.com>
|
||||
* Brian R. Bondy <netzen@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -145,6 +146,9 @@ NS_IMETHODIMP JumpListBuilder::InitListBuild(nsIMutableArray *removedItems, PRBo
|
|||
TransferIObjectArrayToIMutableArray(objArray, removedItems);
|
||||
objArray->Release();
|
||||
}
|
||||
|
||||
RemoveIconCacheForItems(removedItems);
|
||||
|
||||
sBuildingList = PR_TRUE;
|
||||
*_retval = PR_TRUE;
|
||||
return NS_OK;
|
||||
|
@ -153,6 +157,48 @@ NS_IMETHODIMP JumpListBuilder::InitListBuild(nsIMutableArray *removedItems, PRBo
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Ensures that we don't have old ICO files that aren't in our jump lists
|
||||
// anymore left over in the cache.
|
||||
nsresult JumpListBuilder::RemoveIconCacheForItems(nsIMutableArray *items)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(items);
|
||||
|
||||
nsresult rv;
|
||||
PRUint32 length;
|
||||
items->GetLength(&length);
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
|
||||
//Obtain an IJumpListItem and get the type
|
||||
nsCOMPtr<nsIJumpListItem> item = do_QueryElementAt(items, i);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
PRInt16 type;
|
||||
if (NS_FAILED(item->GetType(&type))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the item is a shortcut, remove its associated icon if any
|
||||
if (type == nsIJumpListItem::JUMPLIST_ITEM_SHORTCUT) {
|
||||
nsCOMPtr<nsIJumpListShortcut> shortcut = do_QueryInterface(item);
|
||||
if (shortcut) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = shortcut->GetIconImageUri(getter_AddRefs(uri));
|
||||
if (NS_SUCCEEDED(rv) && uri) {
|
||||
JumpListShortcut::RemoveCacheIcon(uri); // doesn't matter if it fails
|
||||
|
||||
// The shortcut was generated from an IShellLinkW so IShellLinkW can
|
||||
// only tell us what the original icon is and not the URI.
|
||||
// So this field was used only temporarily as the actual icon file
|
||||
// path. It should be cleared.
|
||||
shortcut->SetIconImageUri(nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end for
|
||||
}
|
||||
|
||||
/* boolean addListToBuild(in short aCatType, [optional] in nsIArray items, [optional] in AString catName); */
|
||||
NS_IMETHODIMP JumpListBuilder::AddListToBuild(PRInt16 aCatType, nsIArray *items, const nsAString &catName, PRBool *_retval)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Jim Mathies <jmathies@mozilla.com>
|
||||
* Brian R. Bondy <netzen@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -77,6 +78,7 @@ private:
|
|||
|
||||
PRBool IsSeparator(nsCOMPtr<nsIJumpListItem>& item);
|
||||
nsresult TransferIObjectArrayToIMutableArray(IObjectArray *objArray, nsIMutableArray *removedItems);
|
||||
nsresult RemoveIconCacheForItems(nsIMutableArray *removedItems);
|
||||
|
||||
friend class WinTaskbar;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Jim Mathies <jmathies@mozilla.com>
|
||||
* Brian R. Bondy <netzen@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -51,6 +52,11 @@
|
|||
#include "nsNetCID.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "imgITools.h"
|
||||
#include "nsIFaviconService.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsStringStream.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
@ -59,6 +65,7 @@ namespace widget {
|
|||
// need to call it on win7+.
|
||||
JumpListLink::SHCreateItemFromParsingNamePtr JumpListLink::createItemFromParsingName = nsnull;
|
||||
const PRUnichar JumpListLink::kSehllLibraryName[] = L"shell32.dll";
|
||||
const char kJumpListCacheDir[] = "jumpListCache";
|
||||
HMODULE JumpListLink::sShellDll = nsnull;
|
||||
|
||||
// ISUPPORTS Impl's
|
||||
|
@ -158,7 +165,7 @@ NS_IMETHODIMP JumpListLink::GetUriHash(nsACString& aUriHash)
|
|||
if (!mURI)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
return HashURI(mURI, aUriHash);
|
||||
return JumpListItem::HashURI(mCryptoHash, mURI, aUriHash);
|
||||
}
|
||||
|
||||
/* boolean compareHash(in nsIURI uri); */
|
||||
|
@ -175,9 +182,9 @@ NS_IMETHODIMP JumpListLink::CompareHash(nsIURI *aUri, PRBool *aResult)
|
|||
|
||||
nsCAutoString hash1, hash2;
|
||||
|
||||
rv = HashURI(mURI, hash1);
|
||||
rv = JumpListItem::HashURI(mCryptoHash, mURI, hash1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = HashURI(aUri, hash2);
|
||||
rv = JumpListItem::HashURI(mCryptoHash, aUri, hash2);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aResult = hash1.Equals(hash2);
|
||||
|
@ -265,6 +272,20 @@ NS_IMETHODIMP JumpListShortcut::SetIconIndex(PRInt32 aIconIndex)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute long iconURI; */
|
||||
NS_IMETHODIMP JumpListShortcut::GetIconImageUri(nsIURI **aIconImageURI)
|
||||
{
|
||||
NS_IF_ADDREF(*aIconImageURI = mIconImageURI);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP JumpListShortcut::SetIconImageUri(nsIURI *aIconImageURI)
|
||||
{
|
||||
mIconImageURI = aIconImageURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* boolean equals(nsIJumpListItem item); */
|
||||
NS_IMETHODIMP JumpListShortcut::Equals(nsIJumpListItem *aItem, PRBool *aResult)
|
||||
{
|
||||
|
@ -291,6 +312,7 @@ NS_IMETHODIMP JumpListShortcut::Equals(nsIJumpListItem *aItem, PRBool *aResult)
|
|||
//shortcut->GetIconIndex(&idx);
|
||||
//if (mIconIndex != idx)
|
||||
// return NS_OK;
|
||||
// No need to check the icon page URI either
|
||||
|
||||
// Call the internal object's equals() method to check.
|
||||
nsCOMPtr<nsILocalHandlerApp> theApp;
|
||||
|
@ -342,6 +364,225 @@ nsresult JumpListSeparator::GetSeparator(nsRefPtr<IShellLinkW>& aShellLink)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Obtains the jump list 'ICO cache timeout in seconds' pref
|
||||
static PRInt32 GetICOCacheSecondsTimeout() {
|
||||
|
||||
// Only obtain the setting at most once from the pref service.
|
||||
// In the rare case that 2 threads call this at the same
|
||||
// time it is no harm and we will simply obtain the pref twice.
|
||||
// None of the taskbar list prefs are currently updated via a
|
||||
// pref observer so I think this should suffice.
|
||||
const PRInt32 kSecondsPerDay = 86400;
|
||||
static PRBool alreadyObtained = PR_FALSE;
|
||||
static PRInt32 icoReCacheSecondsTimeout = kSecondsPerDay;
|
||||
if (alreadyObtained) {
|
||||
return icoReCacheSecondsTimeout;
|
||||
}
|
||||
|
||||
// Obtain the pref
|
||||
const char PREF_ICOTIMEOUT[] = "browser.taskbar.lists.icoTimeoutInSeconds";
|
||||
icoReCacheSecondsTimeout = Preferences::GetInt(PREF_ICOTIMEOUT,
|
||||
kSecondsPerDay);
|
||||
alreadyObtained = PR_TRUE;
|
||||
return icoReCacheSecondsTimeout;
|
||||
}
|
||||
|
||||
// (static) Obtains the ICO data on disk for the specified aIconURI and
|
||||
// fills the path where the ICO file data was stored to.
|
||||
nsresult JumpListShortcut::ObtainCachedIconFile(nsCOMPtr<nsIURI> aIconURI,
|
||||
nsString &aICOFilePath)
|
||||
{
|
||||
// Obtain the ICO file path
|
||||
nsCOMPtr<nsIFile> icoFile;
|
||||
nsresult rv = GetOutputIconPath(aIconURI, icoFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Check if the cached ICO file already exists
|
||||
PRBool exists;
|
||||
rv = icoFile->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (exists) {
|
||||
|
||||
// Obtain the file's last modification date in seconds
|
||||
PRInt64 fileModTime = LL_ZERO;
|
||||
rv = icoFile->GetLastModifiedTime(&fileModTime);
|
||||
fileModTime /= PR_MSEC_PER_SEC;
|
||||
PRInt32 icoReCacheSecondsTimeout = GetICOCacheSecondsTimeout();
|
||||
PRInt64 nowTime = PR_Now() / PRInt64(PR_USEC_PER_SEC);
|
||||
|
||||
// If the last mod call failed or the icon is old then re-cache it
|
||||
// This check is in case the favicon of a page changes
|
||||
if (NS_FAILED(rv) ||
|
||||
(nowTime - fileModTime) > icoReCacheSecondsTimeout) {
|
||||
rv = CacheIconFileFromIconURI(aIconURI, icoFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
} else {
|
||||
// The file does not exist yet, cache it
|
||||
rv = CacheIconFileFromIconURI(aIconURI, icoFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// The icoFile is filled with a path that exists, get its path
|
||||
rv = icoFile->GetPath(aICOFilePath);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// (static) Obtains the ICO file for the aIconURI that should be used
|
||||
// If successful, the file path on disk is in the format:
|
||||
// <ProfLDS>\jumpListCache\<aIconURI_Hash>.ico
|
||||
nsresult JumpListShortcut::GetOutputIconPath(nsCOMPtr<nsIURI> aIconURI,
|
||||
nsCOMPtr<nsIFile> &aICOFile)
|
||||
{
|
||||
// Hash the input URI and replace any / with _
|
||||
nsCAutoString inputURIHash;
|
||||
nsCOMPtr<nsICryptoHash> cryptoHash;
|
||||
nsresult rv = JumpListItem::HashURI(cryptoHash, aIconURI, inputURIHash);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
char* cur = inputURIHash.BeginWriting();
|
||||
char* end = inputURIHash.EndWriting();
|
||||
for (; cur < end; ++cur) {
|
||||
if ('/' == *cur) {
|
||||
*cur = '_';
|
||||
}
|
||||
}
|
||||
|
||||
// Obtain the local profile directory and construct the output icon file path
|
||||
rv = NS_GetSpecialDirectory("ProfLDS", getter_AddRefs(aICOFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aICOFile->AppendNative(nsDependentCString(kJumpListCacheDir));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Try to create the directory if it's not there yet
|
||||
rv = aICOFile->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Append the icon extension
|
||||
inputURIHash.Append(".ico");
|
||||
rv = aICOFile->AppendNative(inputURIHash);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// (static) Creates a cached ICO file on disk for an the image at aIconURI
|
||||
// and stores it to disk at the path of aICOFile
|
||||
nsresult JumpListShortcut::CacheIconFileFromIconURI(nsCOMPtr<nsIURI> aIconURI,
|
||||
nsCOMPtr<nsIFile> aICOFile)
|
||||
{
|
||||
// Obtain the favicon service and get the favicon for the specified page
|
||||
nsCOMPtr<nsIFaviconService> favIconSvc(
|
||||
do_GetService("@mozilla.org/browser/favicon-service;1"));
|
||||
NS_ENSURE_TRUE(favIconSvc, NS_ERROR_FAILURE);
|
||||
|
||||
// Get the favicon data for the passed in URL from the favicon service
|
||||
nsCString mimeType;
|
||||
PRUint32 dataLength;
|
||||
PRUint8 *data;
|
||||
// Careful! data needs to be freed, GetFaviconData is a pretty unsafe function
|
||||
nsresult rv = favIconSvc->GetFaviconData(aIconURI, mimeType,
|
||||
&dataLength, &data);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoArrayPtr<PRUint8> freeMeWhenScopeEnds(data);
|
||||
if(dataLength == 0 || !data) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Convert the obtained favicon data to an input stream
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
rv = NS_NewByteInputStream(getter_AddRefs(stream),
|
||||
reinterpret_cast<const char*>(data), dataLength,
|
||||
NS_ASSIGNMENT_DEPEND);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Decode the image from the format it was returned to us in (probably PNG)
|
||||
nsCOMPtr<imgIContainer> container;
|
||||
nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");
|
||||
rv = imgtool->DecodeImageData(stream, mimeType, getter_AddRefs(container));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get the recommended icon width and height, or if failure to obtain
|
||||
// these settings, fall back to 16x16 ICOs. These values can be different
|
||||
// if the user has a different DPI setting other than 100%.
|
||||
// Windows would scale the 16x16 icon themselves, but it's better
|
||||
// we let our ICO encoder do it.
|
||||
PRInt32 systemIconWidth = GetSystemMetrics(SM_CXSMICON);
|
||||
PRInt32 systemIconHeight = GetSystemMetrics(SM_CYSMICON);
|
||||
if (systemIconWidth == 0 || systemIconHeight == 0) {
|
||||
systemIconWidth = 16;
|
||||
systemIconHeight = 16;
|
||||
}
|
||||
// Scale the image to the needed size and in ICO format
|
||||
mimeType.AssignLiteral("image/vnd.microsoft.icon");
|
||||
nsCOMPtr<nsIInputStream> iconStream;
|
||||
rv = imgtool->EncodeScaledImage(container, mimeType,
|
||||
systemIconWidth,
|
||||
systemIconHeight,
|
||||
getter_AddRefs(iconStream));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Setup the output stream for the ICO file on disk
|
||||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), aICOFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Obtain the ICO buffer size from the re-encoded ICO stream
|
||||
PRUint32 bufSize;
|
||||
rv = iconStream->Available(&bufSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Setup a buffered output stream from the stream object
|
||||
// so that we can simply use WriteFrom with the stream object
|
||||
nsCOMPtr<nsIOutputStream> bufferedOutputStream;
|
||||
rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
|
||||
outputStream, bufSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Write out the icon stream to disk and make sure we wrote everything
|
||||
PRUint32 wrote;
|
||||
rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if(bufSize != wrote) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
bufferedOutputStream->Close();
|
||||
outputStream->Close();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// (static) Removes the cached icon file
|
||||
// Assumes that the local file path is stored inside the nsIURI
|
||||
nsresult JumpListShortcut::RemoveCacheIcon(nsCOMPtr<nsIURI> aUri)
|
||||
{
|
||||
// Get the nsIURI spec which stores the local path for the icon to remove
|
||||
nsCAutoString spec;
|
||||
nsresult rv = aUri->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Construct the parent path of the passed in path
|
||||
nsCOMPtr<nsILocalFile> icoFile = do_CreateInstance("@mozilla.org/file/local;1");
|
||||
NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
|
||||
rv = icoFile->InitWithPath(NS_ConvertUTF8toUTF16(spec));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Check if the cached ICO file exists
|
||||
PRBool exists;
|
||||
rv = icoFile->Exists(&exists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If the file exists, remove it
|
||||
if (exists) {
|
||||
icoFile->Remove(PR_FALSE);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// (static) Creates a ShellLink that encapsulate a shortcut to local apps.
|
||||
nsresult JumpListShortcut::GetShellLink(nsCOMPtr<nsIJumpListItem>& item, nsRefPtr<IShellLinkW>& aShellLink)
|
||||
{
|
||||
|
@ -401,7 +642,16 @@ nsresult JumpListShortcut::GetShellLink(nsCOMPtr<nsIJumpListItem>& item, nsRefPt
|
|||
|
||||
handlerApp->GetName(appTitle);
|
||||
handlerApp->GetDetailedDescription(appDescription);
|
||||
|
||||
PRBool useUriIcon = PR_FALSE; // if we want to use the URI icon
|
||||
PRBool usedUriIcon = PR_FALSE; // if we did use the URI icon
|
||||
shortcut->GetIconIndex(&appIconIndex);
|
||||
|
||||
nsCOMPtr<nsIURI> iconUri;
|
||||
rv = shortcut->GetIconImageUri(getter_AddRefs(iconUri));
|
||||
if (NS_SUCCEEDED(rv) && iconUri) {
|
||||
useUriIcon = PR_TRUE;
|
||||
}
|
||||
|
||||
// Store the title of the app
|
||||
if (appTitle.Length() > 0) {
|
||||
|
@ -424,13 +674,63 @@ nsresult JumpListShortcut::GetShellLink(nsCOMPtr<nsIJumpListItem>& item, nsRefPt
|
|||
psl->SetPath(appPath.get());
|
||||
psl->SetDescription(appDescription.get());
|
||||
psl->SetArguments(appArgs.get());
|
||||
psl->SetIconLocation(appPath.get(), appIconIndex);
|
||||
|
||||
if (useUriIcon) {
|
||||
nsString icoFilePath;
|
||||
rv = ObtainCachedIconFile(iconUri, icoFilePath);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Always use the first icon in the ICO file
|
||||
// our encoded icon only has 1 resource
|
||||
psl->SetIconLocation(icoFilePath.get(), 0);
|
||||
usedUriIcon = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't use an ICO via URI so fall back to the app icon
|
||||
if (!usedUriIcon) {
|
||||
psl->SetIconLocation(appPath.get(), appIconIndex);
|
||||
}
|
||||
|
||||
aShellLink = dont_AddRef(psl);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If successful fills in the aSame parameter
|
||||
// aSame will be true if the path is in our icon cache
|
||||
static nsresult IsPathInOurIconCache(nsCOMPtr<nsIJumpListShortcut>& aShortcut,
|
||||
PRUnichar *aPath, PRBool *aSame)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aPath);
|
||||
NS_ENSURE_ARG_POINTER(aSame);
|
||||
|
||||
*aSame = PR_FALSE;
|
||||
|
||||
// Construct the path of our jump list cache
|
||||
nsCOMPtr<nsIFile> jumpListCache;
|
||||
nsresult rv = NS_GetSpecialDirectory("ProfLDS", getter_AddRefs(jumpListCache));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = jumpListCache->AppendNative(nsDependentCString(kJumpListCacheDir));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsAutoString jumpListCachePath;
|
||||
rv = jumpListCache->GetPath(jumpListCachePath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Construct the parent path of the passed in path
|
||||
nsCOMPtr<nsILocalFile> passedInFile = do_CreateInstance("@mozilla.org/file/local;1");
|
||||
NS_ENSURE_TRUE(passedInFile, NS_ERROR_FAILURE);
|
||||
nsAutoString passedInPath(aPath);
|
||||
rv = passedInFile->InitWithPath(passedInPath);
|
||||
nsCOMPtr<nsIFile> passedInParentFile;
|
||||
passedInFile->GetParent(getter_AddRefs(passedInParentFile));
|
||||
nsAutoString passedInParentPath;
|
||||
rv = jumpListCache->GetPath(passedInParentPath);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aSame = jumpListCachePath.Equals(passedInParentPath);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// (static) For a given IShellLink, create and return a populated nsIJumpListShortcut.
|
||||
nsresult JumpListShortcut::GetJumpListShortcut(IShellLinkW *pLink, nsCOMPtr<nsIJumpListShortcut>& aShortcut)
|
||||
{
|
||||
|
@ -485,6 +785,19 @@ nsresult JumpListShortcut::GetJumpListShortcut(IShellLinkW *pLink, nsCOMPtr<nsIJ
|
|||
if (SUCCEEDED(hres)) {
|
||||
// XXX How do we handle converting local files to images here? Do we need to?
|
||||
aShortcut->SetIconIndex(iconIdx);
|
||||
|
||||
// Obtain the local profile directory and construct the output icon file path
|
||||
// We only set the Icon Uri if we're sure it was from our icon cache.
|
||||
PRBool isInOurCache;
|
||||
if (NS_SUCCEEDED(IsPathInOurIconCache(aShortcut, buf, &isInOurCache)) &&
|
||||
isInOurCache) {
|
||||
nsCOMPtr<nsIURI> iconUri;
|
||||
nsAutoString path(buf);
|
||||
rv = NS_NewURI(getter_AddRefs(iconUri), path);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aShortcut->SetIconImageUri(iconUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do we need the title and description? Probably not since handler app doesn't compare
|
||||
|
@ -602,27 +915,28 @@ PRBool JumpListShortcut::ExecutableExists(nsCOMPtr<nsILocalHandlerApp>& handlerA
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult JumpListLink::HashURI(nsIURI *aUri, nsACString& aUriHash)
|
||||
// (static) Helper method which will hash a URI
|
||||
nsresult JumpListItem::HashURI(nsCOMPtr<nsICryptoHash> &aCryptoHash,
|
||||
nsIURI *aUri, nsACString& aUriHash)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!aUri)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsCAutoString spec;
|
||||
rv = aUri->GetSpec(spec);
|
||||
nsresult rv = aUri->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mCryptoHash) {
|
||||
mCryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
|
||||
if (!aCryptoHash) {
|
||||
aCryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = mCryptoHash->Init(nsICryptoHash::MD5);
|
||||
rv = aCryptoHash->Init(nsICryptoHash::MD5);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mCryptoHash->Update(reinterpret_cast<const PRUint8*>(spec.BeginReading()), spec.Length());
|
||||
rv = aCryptoHash->Update(reinterpret_cast<const PRUint8*>(spec.BeginReading()),
|
||||
spec.Length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mCryptoHash->Finish(PR_TRUE, aUriHash);
|
||||
rv = aCryptoHash->Finish(PR_TRUE, aUriHash);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Jim Mathies <jmathies@mozilla.com>
|
||||
* Brian R. Bondy <netzen@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -78,6 +79,9 @@ public:
|
|||
protected:
|
||||
short Type() { return mItemType; }
|
||||
short mItemType;
|
||||
|
||||
static nsresult HashURI(nsCOMPtr<nsICryptoHash> &aCryptoHash,
|
||||
nsIURI *aUri, nsACString& aUriHash);
|
||||
};
|
||||
|
||||
class JumpListSeparator : public JumpListItem, public nsIJumpListSeparator
|
||||
|
@ -118,8 +122,6 @@ protected:
|
|||
static const PRUnichar kSehllLibraryName[];
|
||||
static HMODULE sShellDll;
|
||||
static SHCreateItemFromParsingNamePtr createItemFromParsingName;
|
||||
|
||||
nsresult HashURI(nsIURI *uri, nsACString& aUriHas);
|
||||
};
|
||||
|
||||
class JumpListShortcut : public JumpListItem, public nsIJumpListShortcut
|
||||
|
@ -137,12 +139,20 @@ public:
|
|||
|
||||
static nsresult GetShellLink(nsCOMPtr<nsIJumpListItem>& item, nsRefPtr<IShellLinkW>& aShellLink);
|
||||
static nsresult GetJumpListShortcut(IShellLinkW *pLink, nsCOMPtr<nsIJumpListShortcut>& aShortcut);
|
||||
static nsresult RemoveCacheIcon(nsCOMPtr<nsIURI> aURI);
|
||||
|
||||
protected:
|
||||
PRInt32 mIconIndex;
|
||||
nsCOMPtr<nsIURI> mIconImageURI;
|
||||
nsCOMPtr<nsILocalHandlerApp> mHandlerApp;
|
||||
|
||||
PRBool ExecutableExists(nsCOMPtr<nsILocalHandlerApp>& handlerApp);
|
||||
static nsresult ObtainCachedIconFile(nsCOMPtr<nsIURI> aIconURI,
|
||||
nsString &aICOFilePath);
|
||||
static nsresult GetOutputIconPath(nsCOMPtr<nsIURI> aIconURI,
|
||||
nsCOMPtr<nsIFile> &aICOFile);
|
||||
static nsresult CacheIconFileFromIconURI(nsCOMPtr<nsIURI> aIconURI,
|
||||
nsCOMPtr<nsIFile> aICOFile);
|
||||
};
|
||||
|
||||
} // namespace widget
|
||||
|
|
|
@ -184,9 +184,14 @@ function test_shortcuts()
|
|||
handlerApp.appendParameter("-test");
|
||||
|
||||
sc.iconIndex = 1;
|
||||
|
||||
do_check_eq(sc.iconIndex, 1);
|
||||
|
||||
var iconImageUri = Cc["@mozilla.org/network/simple-uri;1"]
|
||||
.createInstance(Ci.nsIURI);
|
||||
iconImageUri.spec = "http://www.123.com/";
|
||||
sc.iconImageUri = iconImageUri;
|
||||
do_check_eq(sc.iconImageUri, iconImageUri);
|
||||
|
||||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties).
|
||||
QueryInterface(Ci.nsIDirectoryService);
|
||||
|
|
Загрузка…
Ссылка в новой задаче