1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/windows/JumpListItem.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,641 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "JumpListItem.h" 1.10 + 1.11 +#include <shellapi.h> 1.12 +#include <propvarutil.h> 1.13 +#include <propkey.h> 1.14 + 1.15 +#include "nsIFile.h" 1.16 +#include "nsNetUtil.h" 1.17 +#include "nsCRT.h" 1.18 +#include "nsNetCID.h" 1.19 +#include "nsCExternalHandlerService.h" 1.20 +#include "nsCycleCollectionParticipant.h" 1.21 +#include "mozilla/Preferences.h" 1.22 +#include "JumpListBuilder.h" 1.23 +#include "WinUtils.h" 1.24 + 1.25 +namespace mozilla { 1.26 +namespace widget { 1.27 + 1.28 +// ISUPPORTS Impl's 1.29 +NS_IMPL_ISUPPORTS(JumpListItem, 1.30 + nsIJumpListItem) 1.31 + 1.32 +NS_IMPL_ISUPPORTS_INHERITED(JumpListSeparator, 1.33 + JumpListItem, 1.34 + nsIJumpListSeparator) 1.35 + 1.36 +NS_IMPL_ISUPPORTS_INHERITED(JumpListLink, 1.37 + JumpListItem, 1.38 + nsIJumpListLink) 1.39 + 1.40 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JumpListShortcut) 1.41 + NS_INTERFACE_MAP_ENTRY(nsIJumpListShortcut) 1.42 +NS_INTERFACE_MAP_END_INHERITING(JumpListItem) 1.43 + 1.44 +NS_IMPL_CYCLE_COLLECTION(JumpListShortcut, mHandlerApp) 1.45 + 1.46 +NS_IMPL_CYCLE_COLLECTING_ADDREF(JumpListShortcut) 1.47 +NS_IMPL_CYCLE_COLLECTING_RELEASE(JumpListShortcut) 1.48 + 1.49 +/* attribute short type; */ 1.50 +NS_IMETHODIMP JumpListItem::GetType(int16_t *aType) 1.51 +{ 1.52 + NS_ENSURE_ARG_POINTER(aType); 1.53 + 1.54 + *aType = mItemType; 1.55 + 1.56 + return NS_OK; 1.57 +} 1.58 + 1.59 +/* boolean equals(nsIJumpListItem item); */ 1.60 +NS_IMETHODIMP JumpListItem::Equals(nsIJumpListItem *aItem, bool *aResult) 1.61 +{ 1.62 + NS_ENSURE_ARG_POINTER(aItem); 1.63 + 1.64 + *aResult = false; 1.65 + 1.66 + int16_t theType = nsIJumpListItem::JUMPLIST_ITEM_EMPTY; 1.67 + if (NS_FAILED(aItem->GetType(&theType))) 1.68 + return NS_OK; 1.69 + 1.70 + // Make sure the types match. 1.71 + if (Type() != theType) 1.72 + return NS_OK; 1.73 + 1.74 + *aResult = true; 1.75 + 1.76 + return NS_OK; 1.77 +} 1.78 + 1.79 +/* link impl. */ 1.80 + 1.81 +/* attribute nsIURI uri; */ 1.82 +NS_IMETHODIMP JumpListLink::GetUri(nsIURI **aURI) 1.83 +{ 1.84 + NS_IF_ADDREF(*aURI = mURI); 1.85 + 1.86 + return NS_OK; 1.87 +} 1.88 + 1.89 +NS_IMETHODIMP JumpListLink::SetUri(nsIURI *aURI) 1.90 +{ 1.91 + mURI = aURI; 1.92 + 1.93 + return NS_OK; 1.94 +} 1.95 + 1.96 +/* attribute AString uriTitle; */ 1.97 +NS_IMETHODIMP JumpListLink::SetUriTitle(const nsAString &aUriTitle) 1.98 +{ 1.99 + mUriTitle.Assign(aUriTitle); 1.100 + 1.101 + return NS_OK; 1.102 +} 1.103 + 1.104 +NS_IMETHODIMP JumpListLink::GetUriTitle(nsAString& aUriTitle) 1.105 +{ 1.106 + aUriTitle.Assign(mUriTitle); 1.107 + 1.108 + return NS_OK; 1.109 +} 1.110 + 1.111 +/* readonly attribute long uriHash; */ 1.112 +NS_IMETHODIMP JumpListLink::GetUriHash(nsACString& aUriHash) 1.113 +{ 1.114 + if (!mURI) 1.115 + return NS_ERROR_NOT_AVAILABLE; 1.116 + 1.117 + return mozilla::widget::FaviconHelper::HashURI(mCryptoHash, mURI, aUriHash); 1.118 +} 1.119 + 1.120 +/* boolean compareHash(in nsIURI uri); */ 1.121 +NS_IMETHODIMP JumpListLink::CompareHash(nsIURI *aUri, bool *aResult) 1.122 +{ 1.123 + nsresult rv; 1.124 + 1.125 + if (!mURI) { 1.126 + *aResult = !aUri; 1.127 + return NS_OK; 1.128 + } 1.129 + 1.130 + NS_ENSURE_ARG_POINTER(aUri); 1.131 + 1.132 + nsAutoCString hash1, hash2; 1.133 + 1.134 + rv = mozilla::widget::FaviconHelper::HashURI(mCryptoHash, mURI, hash1); 1.135 + NS_ENSURE_SUCCESS(rv, rv); 1.136 + rv = mozilla::widget::FaviconHelper::HashURI(mCryptoHash, aUri, hash2); 1.137 + NS_ENSURE_SUCCESS(rv, rv); 1.138 + 1.139 + *aResult = hash1.Equals(hash2); 1.140 + 1.141 + return NS_OK; 1.142 +} 1.143 + 1.144 +/* boolean equals(nsIJumpListItem item); */ 1.145 +NS_IMETHODIMP JumpListLink::Equals(nsIJumpListItem *aItem, bool *aResult) 1.146 +{ 1.147 + NS_ENSURE_ARG_POINTER(aItem); 1.148 + 1.149 + nsresult rv; 1.150 + 1.151 + *aResult = false; 1.152 + 1.153 + int16_t theType = nsIJumpListItem::JUMPLIST_ITEM_EMPTY; 1.154 + if (NS_FAILED(aItem->GetType(&theType))) 1.155 + return NS_OK; 1.156 + 1.157 + // Make sure the types match. 1.158 + if (Type() != theType) 1.159 + return NS_OK; 1.160 + 1.161 + nsCOMPtr<nsIJumpListLink> link = do_QueryInterface(aItem, &rv); 1.162 + if (NS_FAILED(rv)) 1.163 + return rv; 1.164 + 1.165 + // Check the titles 1.166 + nsAutoString title; 1.167 + link->GetUriTitle(title); 1.168 + if (!mUriTitle.Equals(title)) 1.169 + return NS_OK; 1.170 + 1.171 + // Call the internal object's equals() method to check. 1.172 + nsCOMPtr<nsIURI> theUri; 1.173 + bool equals = false; 1.174 + if (NS_SUCCEEDED(link->GetUri(getter_AddRefs(theUri)))) { 1.175 + if (!theUri) { 1.176 + if (!mURI) 1.177 + *aResult = true; 1.178 + return NS_OK; 1.179 + } 1.180 + if (NS_SUCCEEDED(theUri->Equals(mURI, &equals)) && equals) { 1.181 + *aResult = true; 1.182 + } 1.183 + } 1.184 + 1.185 + return NS_OK; 1.186 +} 1.187 + 1.188 +/* shortcut impl. */ 1.189 + 1.190 +/* attribute nsILocalHandlerApp app; */ 1.191 +NS_IMETHODIMP JumpListShortcut::GetApp(nsILocalHandlerApp **aApp) 1.192 +{ 1.193 + NS_IF_ADDREF(*aApp = mHandlerApp); 1.194 + 1.195 + return NS_OK; 1.196 +} 1.197 + 1.198 +NS_IMETHODIMP JumpListShortcut::SetApp(nsILocalHandlerApp *aApp) 1.199 +{ 1.200 + mHandlerApp = aApp; 1.201 + 1.202 + // Confirm the app is present on the system 1.203 + if (!ExecutableExists(mHandlerApp)) 1.204 + return NS_ERROR_FILE_NOT_FOUND; 1.205 + 1.206 + return NS_OK; 1.207 +} 1.208 + 1.209 +/* attribute long iconIndex; */ 1.210 +NS_IMETHODIMP JumpListShortcut::GetIconIndex(int32_t *aIconIndex) 1.211 +{ 1.212 + NS_ENSURE_ARG_POINTER(aIconIndex); 1.213 + 1.214 + *aIconIndex = mIconIndex; 1.215 + return NS_OK; 1.216 +} 1.217 + 1.218 +NS_IMETHODIMP JumpListShortcut::SetIconIndex(int32_t aIconIndex) 1.219 +{ 1.220 + mIconIndex = aIconIndex; 1.221 + return NS_OK; 1.222 +} 1.223 + 1.224 +/* attribute long iconURI; */ 1.225 +NS_IMETHODIMP JumpListShortcut::GetFaviconPageUri(nsIURI **aFaviconPageURI) 1.226 +{ 1.227 + NS_IF_ADDREF(*aFaviconPageURI = mFaviconPageURI); 1.228 + 1.229 + return NS_OK; 1.230 +} 1.231 + 1.232 +NS_IMETHODIMP JumpListShortcut::SetFaviconPageUri(nsIURI *aFaviconPageURI) 1.233 +{ 1.234 + mFaviconPageURI = aFaviconPageURI; 1.235 + return NS_OK; 1.236 +} 1.237 + 1.238 +/* boolean equals(nsIJumpListItem item); */ 1.239 +NS_IMETHODIMP JumpListShortcut::Equals(nsIJumpListItem *aItem, bool *aResult) 1.240 +{ 1.241 + NS_ENSURE_ARG_POINTER(aItem); 1.242 + 1.243 + nsresult rv; 1.244 + 1.245 + *aResult = false; 1.246 + 1.247 + int16_t theType = nsIJumpListItem::JUMPLIST_ITEM_EMPTY; 1.248 + if (NS_FAILED(aItem->GetType(&theType))) 1.249 + return NS_OK; 1.250 + 1.251 + // Make sure the types match. 1.252 + if (Type() != theType) 1.253 + return NS_OK; 1.254 + 1.255 + nsCOMPtr<nsIJumpListShortcut> shortcut = do_QueryInterface(aItem, &rv); 1.256 + if (NS_FAILED(rv)) 1.257 + return rv; 1.258 + 1.259 + // Check the icon index 1.260 + //int32_t idx; 1.261 + //shortcut->GetIconIndex(&idx); 1.262 + //if (mIconIndex != idx) 1.263 + // return NS_OK; 1.264 + // No need to check the icon page URI either 1.265 + 1.266 + // Call the internal object's equals() method to check. 1.267 + nsCOMPtr<nsILocalHandlerApp> theApp; 1.268 + bool equals = false; 1.269 + if (NS_SUCCEEDED(shortcut->GetApp(getter_AddRefs(theApp)))) { 1.270 + if (!theApp) { 1.271 + if (!mHandlerApp) 1.272 + *aResult = true; 1.273 + return NS_OK; 1.274 + } 1.275 + if (NS_SUCCEEDED(theApp->Equals(mHandlerApp, &equals)) && equals) { 1.276 + *aResult = true; 1.277 + } 1.278 + } 1.279 + 1.280 + return NS_OK; 1.281 +} 1.282 + 1.283 +/* internal helpers */ 1.284 + 1.285 +// (static) Creates a ShellLink that encapsulate a separator. 1.286 +nsresult JumpListSeparator::GetSeparator(nsRefPtr<IShellLinkW>& aShellLink) 1.287 +{ 1.288 + HRESULT hr; 1.289 + IShellLinkW* psl; 1.290 + 1.291 + // Create a IShellLink. 1.292 + hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, 1.293 + IID_IShellLinkW, (LPVOID*)&psl); 1.294 + if (FAILED(hr)) 1.295 + return NS_ERROR_UNEXPECTED; 1.296 + 1.297 + IPropertyStore* pPropStore = nullptr; 1.298 + hr = psl->QueryInterface(IID_IPropertyStore, (LPVOID*)&pPropStore); 1.299 + if (FAILED(hr)) 1.300 + return NS_ERROR_UNEXPECTED; 1.301 + 1.302 + PROPVARIANT pv; 1.303 + InitPropVariantFromBoolean(TRUE, &pv); 1.304 + 1.305 + pPropStore->SetValue(PKEY_AppUserModel_IsDestListSeparator, pv); 1.306 + pPropStore->Commit(); 1.307 + pPropStore->Release(); 1.308 + 1.309 + PropVariantClear(&pv); 1.310 + 1.311 + aShellLink = dont_AddRef(psl); 1.312 + 1.313 + return NS_OK; 1.314 +} 1.315 + 1.316 +// (static) Creates a ShellLink that encapsulate a shortcut to local apps. 1.317 +nsresult JumpListShortcut::GetShellLink(nsCOMPtr<nsIJumpListItem>& item, 1.318 + nsRefPtr<IShellLinkW>& aShellLink, 1.319 + nsCOMPtr<nsIThread> &aIOThread) 1.320 +{ 1.321 + HRESULT hr; 1.322 + IShellLinkW* psl; 1.323 + nsresult rv; 1.324 + 1.325 + // Shell links: 1.326 + // http://msdn.microsoft.com/en-us/library/bb776891(VS.85).aspx 1.327 + // http://msdn.microsoft.com/en-us/library/bb774950(VS.85).aspx 1.328 + 1.329 + int16_t type; 1.330 + if (NS_FAILED(item->GetType(&type))) 1.331 + return NS_ERROR_INVALID_ARG; 1.332 + 1.333 + if (type != nsIJumpListItem::JUMPLIST_ITEM_SHORTCUT) 1.334 + return NS_ERROR_INVALID_ARG; 1.335 + 1.336 + nsCOMPtr<nsIJumpListShortcut> shortcut = do_QueryInterface(item, &rv); 1.337 + NS_ENSURE_SUCCESS(rv, rv); 1.338 + 1.339 + nsCOMPtr<nsILocalHandlerApp> handlerApp; 1.340 + rv = shortcut->GetApp(getter_AddRefs(handlerApp)); 1.341 + NS_ENSURE_SUCCESS(rv, rv); 1.342 + 1.343 + // Create a IShellLink 1.344 + hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, 1.345 + IID_IShellLinkW, (LPVOID*)&psl); 1.346 + if (FAILED(hr)) 1.347 + return NS_ERROR_UNEXPECTED; 1.348 + 1.349 + // Retrieve the app path, title, description and optional command line args. 1.350 + nsAutoString appPath, appTitle, appDescription, appArgs; 1.351 + int32_t appIconIndex = 0; 1.352 + 1.353 + // Path 1.354 + nsCOMPtr<nsIFile> executable; 1.355 + handlerApp->GetExecutable(getter_AddRefs(executable)); 1.356 + 1.357 + rv = executable->GetPath(appPath); 1.358 + NS_ENSURE_SUCCESS(rv, rv); 1.359 + 1.360 + // Command line parameters 1.361 + uint32_t count = 0; 1.362 + handlerApp->GetParameterCount(&count); 1.363 + for (uint32_t idx = 0; idx < count; idx++) { 1.364 + if (idx > 0) 1.365 + appArgs.Append(NS_LITERAL_STRING(" ")); 1.366 + nsAutoString param; 1.367 + rv = handlerApp->GetParameter(idx, param); 1.368 + if (NS_FAILED(rv)) 1.369 + return rv; 1.370 + appArgs.Append(param); 1.371 + } 1.372 + 1.373 + handlerApp->GetName(appTitle); 1.374 + handlerApp->GetDetailedDescription(appDescription); 1.375 + 1.376 + bool useUriIcon = false; // if we want to use the URI icon 1.377 + bool usedUriIcon = false; // if we did use the URI icon 1.378 + shortcut->GetIconIndex(&appIconIndex); 1.379 + 1.380 + nsCOMPtr<nsIURI> iconUri; 1.381 + rv = shortcut->GetFaviconPageUri(getter_AddRefs(iconUri)); 1.382 + if (NS_SUCCEEDED(rv) && iconUri) { 1.383 + useUriIcon = true; 1.384 + } 1.385 + 1.386 + // Store the title of the app 1.387 + if (appTitle.Length() > 0) { 1.388 + IPropertyStore* pPropStore = nullptr; 1.389 + hr = psl->QueryInterface(IID_IPropertyStore, (LPVOID*)&pPropStore); 1.390 + if (FAILED(hr)) 1.391 + return NS_ERROR_UNEXPECTED; 1.392 + 1.393 + PROPVARIANT pv; 1.394 + InitPropVariantFromString(appTitle.get(), &pv); 1.395 + 1.396 + pPropStore->SetValue(PKEY_Title, pv); 1.397 + pPropStore->Commit(); 1.398 + pPropStore->Release(); 1.399 + 1.400 + PropVariantClear(&pv); 1.401 + } 1.402 + 1.403 + // Store the rest of the params 1.404 + psl->SetPath(appPath.get()); 1.405 + psl->SetDescription(appDescription.get()); 1.406 + psl->SetArguments(appArgs.get()); 1.407 + 1.408 + if (useUriIcon) { 1.409 + nsString icoFilePath; 1.410 + rv = mozilla::widget::FaviconHelper::ObtainCachedIconFile(iconUri, 1.411 + icoFilePath, 1.412 + aIOThread, 1.413 + false); 1.414 + if (NS_SUCCEEDED(rv)) { 1.415 + // Always use the first icon in the ICO file 1.416 + // our encoded icon only has 1 resource 1.417 + psl->SetIconLocation(icoFilePath.get(), 0); 1.418 + usedUriIcon = true; 1.419 + } 1.420 + } 1.421 + 1.422 + // We didn't use an ICO via URI so fall back to the app icon 1.423 + if (!usedUriIcon) { 1.424 + psl->SetIconLocation(appPath.get(), appIconIndex); 1.425 + } 1.426 + 1.427 + aShellLink = dont_AddRef(psl); 1.428 + 1.429 + return NS_OK; 1.430 +} 1.431 + 1.432 +// If successful fills in the aSame parameter 1.433 +// aSame will be true if the path is in our icon cache 1.434 +static nsresult IsPathInOurIconCache(nsCOMPtr<nsIJumpListShortcut>& aShortcut, 1.435 + wchar_t *aPath, bool *aSame) 1.436 +{ 1.437 + NS_ENSURE_ARG_POINTER(aPath); 1.438 + NS_ENSURE_ARG_POINTER(aSame); 1.439 + 1.440 + *aSame = false; 1.441 + 1.442 + // Construct the path of our jump list cache 1.443 + nsCOMPtr<nsIFile> jumpListCache; 1.444 + nsresult rv = NS_GetSpecialDirectory("ProfLDS", getter_AddRefs(jumpListCache)); 1.445 + NS_ENSURE_SUCCESS(rv, rv); 1.446 + rv = jumpListCache->AppendNative(nsDependentCString(FaviconHelper::kJumpListCacheDir)); 1.447 + NS_ENSURE_SUCCESS(rv, rv); 1.448 + nsAutoString jumpListCachePath; 1.449 + rv = jumpListCache->GetPath(jumpListCachePath); 1.450 + NS_ENSURE_SUCCESS(rv, rv); 1.451 + 1.452 + // Construct the parent path of the passed in path 1.453 + nsCOMPtr<nsIFile> passedInFile = do_CreateInstance("@mozilla.org/file/local;1"); 1.454 + NS_ENSURE_TRUE(passedInFile, NS_ERROR_FAILURE); 1.455 + nsAutoString passedInPath(aPath); 1.456 + rv = passedInFile->InitWithPath(passedInPath); 1.457 + nsCOMPtr<nsIFile> passedInParentFile; 1.458 + passedInFile->GetParent(getter_AddRefs(passedInParentFile)); 1.459 + nsAutoString passedInParentPath; 1.460 + rv = jumpListCache->GetPath(passedInParentPath); 1.461 + NS_ENSURE_SUCCESS(rv, rv); 1.462 + 1.463 + *aSame = jumpListCachePath.Equals(passedInParentPath); 1.464 + return NS_OK; 1.465 +} 1.466 + 1.467 +// (static) For a given IShellLink, create and return a populated nsIJumpListShortcut. 1.468 +nsresult JumpListShortcut::GetJumpListShortcut(IShellLinkW *pLink, nsCOMPtr<nsIJumpListShortcut>& aShortcut) 1.469 +{ 1.470 + NS_ENSURE_ARG_POINTER(pLink); 1.471 + 1.472 + nsresult rv; 1.473 + HRESULT hres; 1.474 + 1.475 + nsCOMPtr<nsILocalHandlerApp> handlerApp = 1.476 + do_CreateInstance(NS_LOCALHANDLERAPP_CONTRACTID, &rv); 1.477 + NS_ENSURE_SUCCESS(rv, rv); 1.478 + 1.479 + wchar_t buf[MAX_PATH]; 1.480 + 1.481 + // Path 1.482 + hres = pLink->GetPath(buf, MAX_PATH, nullptr, SLGP_UNCPRIORITY); 1.483 + if (FAILED(hres)) 1.484 + return NS_ERROR_INVALID_ARG; 1.485 + 1.486 + nsCOMPtr<nsIFile> file; 1.487 + nsDependentString filepath(buf); 1.488 + rv = NS_NewLocalFile(filepath, false, getter_AddRefs(file)); 1.489 + NS_ENSURE_SUCCESS(rv, rv); 1.490 + 1.491 + rv = handlerApp->SetExecutable(file); 1.492 + NS_ENSURE_SUCCESS(rv, rv); 1.493 + 1.494 + // Parameters 1.495 + hres = pLink->GetArguments(buf, MAX_PATH); 1.496 + if (SUCCEEDED(hres)) { 1.497 + LPWSTR *arglist; 1.498 + int32_t numArgs; 1.499 + int32_t idx; 1.500 + 1.501 + arglist = ::CommandLineToArgvW(buf, &numArgs); 1.502 + if(arglist) { 1.503 + for (idx = 0; idx < numArgs; idx++) { 1.504 + // szArglist[i] is null terminated 1.505 + nsDependentString arg(arglist[idx]); 1.506 + handlerApp->AppendParameter(arg); 1.507 + } 1.508 + ::LocalFree(arglist); 1.509 + } 1.510 + } 1.511 + 1.512 + rv = aShortcut->SetApp(handlerApp); 1.513 + NS_ENSURE_SUCCESS(rv, rv); 1.514 + 1.515 + // Icon index or file location 1.516 + int iconIdx = 0; 1.517 + hres = pLink->GetIconLocation(buf, MAX_PATH, &iconIdx); 1.518 + if (SUCCEEDED(hres)) { 1.519 + // XXX How do we handle converting local files to images here? Do we need to? 1.520 + aShortcut->SetIconIndex(iconIdx); 1.521 + 1.522 + // Obtain the local profile directory and construct the output icon file path 1.523 + // We only set the Icon Uri if we're sure it was from our icon cache. 1.524 + bool isInOurCache; 1.525 + if (NS_SUCCEEDED(IsPathInOurIconCache(aShortcut, buf, &isInOurCache)) && 1.526 + isInOurCache) { 1.527 + nsCOMPtr<nsIURI> iconUri; 1.528 + nsAutoString path(buf); 1.529 + rv = NS_NewURI(getter_AddRefs(iconUri), path); 1.530 + if (NS_SUCCEEDED(rv)) { 1.531 + aShortcut->SetFaviconPageUri(iconUri); 1.532 + } 1.533 + } 1.534 + } 1.535 + 1.536 + // Do we need the title and description? Probably not since handler app doesn't compare 1.537 + // these in equals. 1.538 + 1.539 + return NS_OK; 1.540 +} 1.541 + 1.542 +// (static) ShellItems are used to encapsulate links to things. We currently only support URI links, 1.543 +// but more support could be added, such as local file and directory links. 1.544 +nsresult JumpListLink::GetShellItem(nsCOMPtr<nsIJumpListItem>& item, nsRefPtr<IShellItem2>& aShellItem) 1.545 +{ 1.546 + IShellItem2 *psi = nullptr; 1.547 + nsresult rv; 1.548 + 1.549 + int16_t type; 1.550 + if (NS_FAILED(item->GetType(&type))) 1.551 + return NS_ERROR_INVALID_ARG; 1.552 + 1.553 + if (type != nsIJumpListItem::JUMPLIST_ITEM_LINK) 1.554 + return NS_ERROR_INVALID_ARG; 1.555 + 1.556 + nsCOMPtr<nsIJumpListLink> link = do_QueryInterface(item, &rv); 1.557 + NS_ENSURE_SUCCESS(rv, rv); 1.558 + 1.559 + nsCOMPtr<nsIURI> uri; 1.560 + rv = link->GetUri(getter_AddRefs(uri)); 1.561 + NS_ENSURE_SUCCESS(rv, rv); 1.562 + 1.563 + nsAutoCString spec; 1.564 + rv = uri->GetSpec(spec); 1.565 + NS_ENSURE_SUCCESS(rv, rv); 1.566 + 1.567 + // Create the IShellItem 1.568 + if (FAILED(WinUtils::SHCreateItemFromParsingName( 1.569 + NS_ConvertASCIItoUTF16(spec).get(), 1.570 + nullptr, IID_PPV_ARGS(&psi)))) { 1.571 + return NS_ERROR_INVALID_ARG; 1.572 + } 1.573 + 1.574 + // Set the title 1.575 + nsAutoString linkTitle; 1.576 + link->GetUriTitle(linkTitle); 1.577 + 1.578 + IPropertyStore* pPropStore = nullptr; 1.579 + HRESULT hres = psi->GetPropertyStore(GPS_DEFAULT, IID_IPropertyStore, (void**)&pPropStore); 1.580 + if (FAILED(hres)) 1.581 + return NS_ERROR_UNEXPECTED; 1.582 + 1.583 + PROPVARIANT pv; 1.584 + InitPropVariantFromString(linkTitle.get(), &pv); 1.585 + 1.586 + // May fail due to shell item access permissions. 1.587 + pPropStore->SetValue(PKEY_ItemName, pv); 1.588 + pPropStore->Commit(); 1.589 + pPropStore->Release(); 1.590 + 1.591 + PropVariantClear(&pv); 1.592 + 1.593 + aShellItem = dont_AddRef(psi); 1.594 + 1.595 + return NS_OK; 1.596 +} 1.597 + 1.598 +// (static) For a given IShellItem, create and return a populated nsIJumpListLink. 1.599 +nsresult JumpListLink::GetJumpListLink(IShellItem *pItem, nsCOMPtr<nsIJumpListLink>& aLink) 1.600 +{ 1.601 + NS_ENSURE_ARG_POINTER(pItem); 1.602 + 1.603 + // We assume for now these are URI links, but through properties we could 1.604 + // query and create other types. 1.605 + nsresult rv; 1.606 + LPWSTR lpstrName = nullptr; 1.607 + 1.608 + if (SUCCEEDED(pItem->GetDisplayName(SIGDN_URL, &lpstrName))) { 1.609 + nsCOMPtr<nsIURI> uri; 1.610 + nsAutoString spec(lpstrName); 1.611 + 1.612 + rv = NS_NewURI(getter_AddRefs(uri), NS_ConvertUTF16toUTF8(spec)); 1.613 + if (NS_FAILED(rv)) 1.614 + return NS_ERROR_INVALID_ARG; 1.615 + 1.616 + aLink->SetUri(uri); 1.617 + 1.618 + ::CoTaskMemFree(lpstrName); 1.619 + } 1.620 + 1.621 + return NS_OK; 1.622 +} 1.623 + 1.624 +// Confirm the app is on the system 1.625 +bool JumpListShortcut::ExecutableExists(nsCOMPtr<nsILocalHandlerApp>& handlerApp) 1.626 +{ 1.627 + nsresult rv; 1.628 + 1.629 + if (!handlerApp) 1.630 + return false; 1.631 + 1.632 + nsCOMPtr<nsIFile> executable; 1.633 + rv = handlerApp->GetExecutable(getter_AddRefs(executable)); 1.634 + if (NS_SUCCEEDED(rv) && executable) { 1.635 + bool exists; 1.636 + executable->Exists(&exists); 1.637 + return exists; 1.638 + } 1.639 + return false; 1.640 +} 1.641 + 1.642 +} // namespace widget 1.643 +} // namespace mozilla 1.644 +