jumplist_win.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/jumplist_win.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shobjidl.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <propkey.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <propvarutil.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_comptr.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/page_usage_data.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/top_sites.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_types.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/tab_restore_service.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/tab_restore_service_factory.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/shell_integration.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/favicon_size.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/icon_util.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// COM interfaces used in this file. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These interface declarations are copied from Windows SDK 7.0. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(hbono): Bug 16903: delete them when we use Windows SDK 7.0. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __IObjectArray_INTERFACE_DEFINED__ 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define __IObjectArray_INTERFACE_DEFINED__ 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MIDL_INTERFACE("92CA9DCD-5622-4bba-A805-5E9F541BD8C9") 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IObjectArray : public IUnknown { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE GetCount( 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [out] */ __RPC__out UINT *pcObjects) = 0; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE GetAt( 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [in] */ UINT uiIndex, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [in] */ __RPC__in REFIID riid, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // __IObjectArray_INTERFACE_DEFINED__ 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __IObjectCollection_INTERFACE_DEFINED__ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define __IObjectCollection_INTERFACE_DEFINED__ 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MIDL_INTERFACE("5632b1a4-e38a-400a-928a-d4cd63230295") 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IObjectCollection : public IObjectArray { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE AddObject( 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [in] */ __RPC__in_opt IUnknown *punk) = 0; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE AddFromArray( 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [in] */ __RPC__in_opt IObjectArray *poaSource) = 0; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE RemoveObjectAt( 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [in] */ UINT uiIndex) = 0; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE Clear(void) = 0; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // __IObjectCollection_INTERFACE_DEFINED__ 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __ICustomDestinationList_INTERFACE_DEFINED__ 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define __ICustomDestinationList_INTERFACE_DEFINED__ 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef /* [v1_enum] */ enum tagKNOWNDESTCATEGORY { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KDC_FREQUENT = 1, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KDC_RECENT = (KDC_FREQUENT + 1) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} KNOWNDESTCATEGORY; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MIDL_INTERFACE("6332debf-87b5-4670-90c0-5e57b408a49e") 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ICustomDestinationList : public IUnknown { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE SetAppID( 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [string][in] */__RPC__in_string LPCWSTR pszAppID) = 0; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE BeginList( 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [out] */ __RPC__out UINT *pcMaxSlots, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [in] */ __RPC__in REFIID riid, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE AppendCategory( 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [string][in] */ __RPC__in_string LPCWSTR pszCategory, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [in] */ __RPC__in_opt IObjectArray *poa) = 0; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE AppendKnownCategory( 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [in] */ KNOWNDESTCATEGORY category) = 0; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE AddUserTasks( 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [in] */ __RPC__in_opt IObjectArray *poa) = 0; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE CommitList(void) = 0; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE GetRemovedDestinations( 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [in] */ __RPC__in REFIID riid, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE DeleteList( 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* [string][in] */ __RPC__in_string LPCWSTR pszAppID) = 0; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT STDMETHODCALLTYPE AbortList(void) = 0; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // __ICustomDestinationList_INTERFACE_DEFINED__ 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Class IDs used in this file. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These class IDs must be defined in an anonymous namespace to avoid 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// conflicts with ones defined in "shell32.lib" of Visual Studio 2008. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(hbono): Bug 16903: delete them when we use Windows SDK 7.0. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const CLSID CLSID_DestinationList = { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0x77f10cf0, 0x3db5, 0x4966, {0xb5, 0x20, 0xb7, 0xc5, 0x4f, 0xd3, 0x5e, 0xd6} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const CLSID CLSID_EnumerableObjectCollection = { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0x2d3468c1, 0x36a7, 0x43b6, {0xac, 0x24, 0xd3, 0xf0, 0x2f, 0xd9, 0x60, 0x7a} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // namespace 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// END OF WINDOWS 7 SDK DEFINITIONS 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Represents a class which encapsulates a PROPVARIANT object containing a 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// string for AddShellLink(). 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class automatically deletes all the resources attached to the 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PROPVARIANT object in its destructor. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PropVariantString { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PropVariantString() { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) property_.vt = VT_EMPTY; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT Init(const std::wstring& value) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call InitPropVariantFromString() to initialize this PROPVARIANT object. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To read <propvarutil.h>, it seems InitPropVariantFromString() is an 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // inline function that initialize a PROPVARIANT object and calls 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SHStrDupW() to set a copy of its input string. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So, we just calls it without creating a copy. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InitPropVariantFromString(value.c_str(), &property_); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~PropVariantString() { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (property_.vt != VT_EMPTY) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PropVariantClear(&property_); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PROPVARIANT& Get() { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return property_; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PROPVARIANT property_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(PropVariantString); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates an IShellLink object. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An IShellLink object is almost the same as an application shortcut, and it 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// requires three items: the absolute path to an application, an argument 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// string, and a title string. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT AddShellLink(base::win::ScopedComPtr<IObjectCollection> collection, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& application, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& switches, 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ShellLinkItem> item) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an IShellLink object. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<IShellLink> link; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT result = link.CreateInstance(CLSID_ShellLink, NULL, 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLSCTX_INPROC_SERVER); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the application path. 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should exit this function when this call fails because it doesn't make 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // any sense to add a shortcut that we cannot execute. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = link->SetPath(application.c_str()); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Attach the command-line switches of this process before the given 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // arguments and set it as the arguments of this IShellLink object. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We also exit this function when this call fails because it isn't usuful to 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // add a shortcut that cannot open the given page. 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring arguments(switches); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!item->arguments().empty()) { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arguments.push_back(L' '); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arguments += item->arguments(); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = link->SetArguments(arguments.c_str()); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Attach the given icon path to this IShellLink object. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since an icon is an optional item for an IShellLink object, so we don't 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have to exit even when it fails. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!item->icon().empty()) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) link->SetIconLocation(item->icon().c_str(), item->index()); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the title of the IShellLink object. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The IShellLink interface does not have any functions which update its 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // title because this interface is originally for creating an application 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shortcut which doesn't have titles. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So, we should use the IPropertyStore interface to set its title as 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // listed in the steps below: 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Retrieve the IPropertyStore interface from the IShellLink object; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. Start a transaction that changes a value of the object with the 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IPropertyStore interface; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3. Create a string PROPVARIANT, and; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4. Call the IPropertyStore::SetValue() function to Set the title property 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the IShellLink object. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 5. Commit the transaction. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<IPropertyStore> property_store; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = link.QueryInterface(property_store.Receive()); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PropVariantString property_title; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = property_title.Init(item->title()); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = property_store->SetValue(PKEY_Title, property_title.Get()); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = property_store->Commit(); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add this IShellLink object to the given collection. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return collection->AddObject(link); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a temporary icon file to be shown in JumpList. 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateIconFile(const SkBitmap& bitmap, 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilePath& icon_dir, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath* icon_path) { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the path to a temporary file. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't have to care about the extension of this temporary file because 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JumpList does not care about it. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath path; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file_util::CreateTemporaryFileInDir(icon_dir, &path)) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an icon file from the favicon attached to the given |page|, and 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save it as the temporary file. 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IconUtil::CreateIconFileFromSkBitmap(bitmap, path)) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add this icon file to the list and return its absolute path. 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The IShellLink::SetIcon() function needs the absolute path to an icon. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *icon_path = path; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Updates a specified category of an application JumpList. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function cannot update registered categories (such as "Tasks") because 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// special steps are required for updating them. 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// So, this function can be used only for adding an unregistered category. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parameters: 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * category_id (int) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A string ID which contains the category name. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * application (std::wstring) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An application name to be used for creating JumpList items. 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Even though we can add command-line switches to this parameter, it is 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// better to use the |switches| parameter below. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * switches (std::wstring) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Command-lien switches for the application. This string is to be added 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before the arguments of each ShellLinkItem object. If there aren't any 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// switches, use an empty string. 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * data (ShellLinkItemList) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A list of ShellLinkItem objects to be added under the specified category. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT UpdateCategory(base::win::ScopedComPtr<ICustomDestinationList> list, 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int category_id, 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& application, 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& switches, 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ShellLinkItemList& data, 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_slots) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Exit this function when the given vector does not contain any items 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because an ICustomDestinationList::AppendCategory() call fails in this 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data.empty() || !max_slots) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring category = UTF16ToWide(l10n_util::GetStringUTF16(category_id)); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an EnumerableObjectCollection object. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We once add the given items to this collection object and add this 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // collection to the JumpList. 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<IObjectCollection> collection; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT result = collection.CreateInstance(CLSID_EnumerableObjectCollection, 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, CLSCTX_INPROC_SERVER); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ShellLinkItemList::const_iterator item = data.begin(); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item != data.end() && max_slots > 0; ++item, --max_slots) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ShellLinkItem> link(*item); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddShellLink(collection, application, switches, link); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can now add the new list to the JumpList. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The ICustomDestinationList::AppendCategory() function needs the 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IObjectArray interface to retrieve each item in the list. So, we retrive 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the IObjectArray interface from the IEnumeratableObjectCollection object 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and use it. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It seems the ICustomDestinationList::AppendCategory() function just 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // replaces all items in the given category with the ones in the new list. 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<IObjectArray> object_array; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = collection.QueryInterface(object_array.Receive()); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return list->AppendCategory(category.c_str(), object_array); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Updates the "Tasks" category of the JumpList. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Even though this function is almost the same as UpdateCategory(), this 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function has the following differences: 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * The "Task" category is a registered category. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We should use AddUserTasks() instead of AppendCategory(). 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * The items in the "Task" category are static. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We don't have to use a list. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT UpdateTaskCategory(base::win::ScopedComPtr<ICustomDestinationList> list, 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& chrome_path, 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& chrome_switches) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an EnumerableObjectCollection object to be added items of the 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "Task" category. (We can also use this object for the "Task" category.) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<IObjectCollection> collection; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT result = collection.CreateInstance(CLSID_EnumerableObjectCollection, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, CLSCTX_INPROC_SERVER); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an IShellLink object which launches Chrome, and add it to the 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // collection. We use our application icon as the icon for this item. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We remove '&' characters from this string so we can share it with our 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // system menu. 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ShellLinkItem> chrome(new ShellLinkItem); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring chrome_title = 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UTF16ToWide(l10n_util::GetStringUTF16(IDS_NEW_WINDOW)); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplaceSubstringsAfterOffset(&chrome_title, 0, L"&", L""); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome->SetTitle(chrome_title); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome->SetIcon(chrome_path, 0, false); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddShellLink(collection, chrome_path, chrome_switches, chrome); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an IShellLink object which launches Chrome in incognito mode, and 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // add it to the collection. We use our application icon as the icon for 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this item. 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ShellLinkItem> incognito(new ShellLinkItem); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) incognito->SetArguments( 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCIIToWide(std::string("--") + switches::kIncognito)); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring incognito_title = 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UTF16ToWide(l10n_util::GetStringUTF16(IDS_NEW_INCOGNITO_WINDOW)); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplaceSubstringsAfterOffset(&incognito_title, 0, L"&", L""); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) incognito->SetTitle(incognito_title); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) incognito->SetIcon(chrome_path, 0, false); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddShellLink(collection, chrome_path, chrome_switches, incognito); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can now add the new list to the JumpList. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ICustomDestinationList::AddUserTasks() also uses the IObjectArray 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // interface to retrieve each item in the list. So, we retrieve the 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IObjectArray interface from the EnumerableObjectCollection object. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<IObjectArray> object_array; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = collection.QueryInterface(object_array.Receive()); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return list->AddUserTasks(object_array); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Updates the application JumpList. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function encapsulates all OS-specific operations required for updating 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the Chromium JumpList, such as: 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Creating an ICustomDestinationList instance; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Updating the categories of the ICustomDestinationList instance, and; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Sending it to Taskbar of Windows 7. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UpdateJumpList(const wchar_t* app_id, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ShellLinkItemList& most_visited_pages, 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ShellLinkItemList& recently_closed_pages) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JumpList is implemented only on Windows 7 or later. 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So, we should return now when this function is called on earlier versions 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of Windows. 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::win::GetVersion() < base::win::VERSION_WIN7) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an ICustomDestinationList object and attach it to our application. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<ICustomDestinationList> destination_list; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT result = destination_list.CreateInstance(CLSID_DestinationList, NULL, 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLSCTX_INPROC_SERVER); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the App ID for this JumpList. 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) destination_list->SetAppID(app_id); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start a transaction that updates the JumpList of this application. 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This implementation just replaces the all items in this JumpList, so 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we don't have to use the IObjectArray object returned from this call. 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It seems Windows 7 RC (Build 7100) automatically checks the items in this 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // removed list and prevent us from adding the same item. 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT max_slots; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedComPtr<IObjectArray> removed; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = destination_list->BeginList(&max_slots, __uuidof(*removed), 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void**>(&removed)); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the absolute path to "chrome.exe". 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_path; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!PathService::Get(base::FILE_EXE, &chrome_path)) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the command-line switches of this process. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine command_line(CommandLine::NO_PROGRAM); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath user_data_dir = CommandLine::ForCurrentProcess()-> 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSwitchValuePath(switches::kUserDataDir); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!user_data_dir.empty()) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring chrome_switches = command_line.GetCommandLineString(); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We allocate 60% of the given JumpList slots to "most-visited" items 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and 40% to "recently-closed" items, respectively. 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Nevertheless, if there are not so many items in |recently_closed_pages|, 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we give the remaining slots to "most-visited" items. 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMostVisited = 60; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kRecentlyClosed = 40; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kTotal = kMostVisited + kRecentlyClosed; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t most_visited_items = MulDiv(max_slots, kMostVisited, kTotal); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t recently_closed_items = max_slots - most_visited_items; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (recently_closed_pages.size() < recently_closed_items) { 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) most_visited_items += recently_closed_items - recently_closed_pages.size(); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recently_closed_items = recently_closed_pages.size(); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the "Most Visited" category of the JumpList. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This update request is applied into the JumpList when we commit this 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction. 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = UpdateCategory(destination_list, IDS_NEW_TAB_MOST_VISITED, 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_path.value(), chrome_switches, 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) most_visited_pages, most_visited_items); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the "Recently Closed" category of the JumpList. 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = UpdateCategory(destination_list, IDS_NEW_TAB_RECENTLY_CLOSED, 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_path.value(), chrome_switches, 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recently_closed_pages, recently_closed_items); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the "Tasks" category of the JumpList. 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = UpdateTaskCategory(destination_list, chrome_path.value(), 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_switches); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Commit this transaction and send the updated JumpList to Windows. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = destination_list->CommitList(); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(result)) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JumpList::JumpList() 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(NULL), 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_(NULL) { 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JumpList::~JumpList() { 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Terminate(); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JumpList::Enabled() { 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (base::win::GetVersion() >= base::win::VERSION_WIN7 && 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CommandLine::ForCurrentProcess()->HasSwitch( 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kDisableCustomJumpList)); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JumpList::AddObserver(Profile* profile) { 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To update JumpList when a tab is added or removed, we add this object to 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the observer list of the TabRestoreService class. 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we add this object to the observer list, we save the pointer to this 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TabRestoreService object. This pointer is used when we remove this object 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the observer list. 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::win::GetVersion() < base::win::VERSION_WIN7 || !profile) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreService* tab_restore_service = 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceFactory::GetForProfile(profile); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tab_restore_service) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) app_id_ = ShellIntegration::GetChromiumModelIdForProfile(profile->GetPath()); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_dir_ = profile->GetPath().Append(chrome::kJumpListIconDirname); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_ = profile; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::TopSites* top_sites = profile_->GetTopSites(); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top_sites) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TopSites updates itself after a delay. This is especially noticable when 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // your profile is empty. Ask TopSites to update itself when jumplist is 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // initialized. 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_sites->SyncWithHistory(); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.reset(new content::NotificationRegistrar); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register for notification when TopSites changes so that we can update 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ourself. 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_->Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<history::TopSites>(top_sites)); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register for notification when profile is destroyed to ensure that all 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // observers are detatched at that time. 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_->Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(profile_)); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_restore_service->AddObserver(this); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::Observe(int type, 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_TOP_SITES_CHANGED: { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Most visited urls changed, query again. 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::TopSites* top_sites = profile_->GetTopSites(); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top_sites) { 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_sites->GetMostVisitedURLs( 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&JumpList::OnMostVisitedURLsAvailable, 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_PROFILE_DESTROYED: { 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Profile was destroyed, do clean-up. 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Terminate(); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unexpected notification type."; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::RemoveObserver() { 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_) { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreService* tab_restore_service = 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceFactory::GetForProfile(profile_); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_restore_service) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_restore_service->RemoveObserver(this); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.reset(); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_ = NULL; 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::CancelPendingUpdate() { 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle_) { 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_, Profile::EXPLICIT_ACCESS); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) favicon_service->CancelRequest(handle_); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_ = NULL; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::Terminate() { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingUpdate(); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveObserver(); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::OnMostVisitedURLsAvailable( 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::MostVisitedURLList& data) { 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have a pending favicon request, cancel it here (it is out of date). 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingUpdate(); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) most_visited_pages_.clear(); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); i++) { 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::MostVisitedURL& url = data[i]; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ShellLinkItem> link(new ShellLinkItem); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url_string = url.url.spec(); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) link->SetArguments(UTF8ToWide(url_string)); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) link->SetTitle(!url.title.empty()? url.title : link->arguments()); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) most_visited_pages_.push_back(link); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls_.push_back(make_pair(url_string, link)); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send a query that retrieves the first favicon. 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartLoadingFavicon(); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::TabRestoreServiceChanged(TabRestoreService* service) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if we have a pending handle request, cancel it here (it is out of date). 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingUpdate(); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // local list to pass to methods 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList temp_list; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a list of ShellLinkItems from the "Recently Closed" pages. 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As noted above, we create a ShellLinkItem objects with the following 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parameters. 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * arguments 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last URL of the tab object. 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * title 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The title of the last URL. 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * icon 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An empty string. This value is to be updated in OnFaviconDataAvailable(). 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code is copied from 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RecentlyClosedTabsHandler::TabRestoreServiceChanged() to emulate it. 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kRecentlyClosedCount = 4; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreService* tab_restore_service = 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceFactory::GetForProfile(profile_); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TabRestoreService::Entries& entries = tab_restore_service->entries(); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (TabRestoreService::Entries::const_iterator it = entries.begin(); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != entries.end(); ++it) { 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TabRestoreService::Entry* entry = *it; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->type == TabRestoreService::TAB) { 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddTab(static_cast<const TabRestoreService::Tab*>(entry), 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &temp_list, kRecentlyClosedCount); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (entry->type == TabRestoreService::WINDOW) { 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddWindow(static_cast<const TabRestoreService::Window*>(entry), 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &temp_list, kRecentlyClosedCount); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Lock recently_closed_pages and copy temp_list into it. 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recently_closed_pages_ = temp_list; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send a query that retrieves the first favicon. 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartLoadingFavicon(); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) { 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JumpList::AddTab(const TabRestoreService::Tab* tab, 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList* list, 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_items) { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code adds the URL and the title strings of the given tab to the 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // specified list. 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list->size() >= max_items) 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ShellLinkItem> link(new ShellLinkItem); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TabNavigation& current_navigation = 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab->navigations.at(tab->current_navigation_index); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url = current_navigation.virtual_url().spec(); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) link->SetArguments(UTF8ToWide(url)); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) link->SetTitle(current_navigation.title()); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list->push_back(link); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls_.push_back(make_pair(url, link)); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::AddWindow(const TabRestoreService::Window* window, 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList* list, 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_items) { 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code enumerates al the tabs in the given window object and add their 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URLs and titles to the list. 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!window->tabs.empty()); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < window->tabs.size(); ++i) { 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddTab(&window->tabs[i], list, max_items)) 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::StartLoadingFavicon() { 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url; 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_urls_.empty()) { 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No more favicons are needed by the application JumpList. Schedule a 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RunUpdate call. 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&JumpList::RunUpdate, this)); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ask FaviconService if it has a favicon of a URL. 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When FaviconService has one, it will call OnFaviconDataAvailable(). 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url = GURL(icon_urls_.front().first); 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconService* favicon_service = 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_ = favicon_service->GetFaviconImageForURL( 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconService::FaviconForURLParams(profile_, url, history::FAVICON, 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::kFaviconSize, &favicon_consumer_), 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&JumpList::OnFaviconDataAvailable, base::Unretained(this))); 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::OnFaviconDataAvailable( 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconService::Handle handle, 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::FaviconImageResult& image_result) { 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is currently a favicon request in progress, it is now outdated, 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as we have received another, so nullify the handle from the old request. 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_ = NULL; 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lock the list to set icon data and pop the url 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Attach the received data to the ShellLinkItem object. 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This data will be decoded by the RunUpdate method. 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image_result.image.IsEmpty()) { 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon_urls_.empty() && icon_urls_.front().second) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls_.front().second->SetIconData(image_result.image.AsBitmap()); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon_urls_.empty()) 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls_.pop_front(); 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check whether we need to load more favicons. 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartLoadingFavicon(); 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::RunUpdate() { 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList local_most_visited_pages; 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList local_recently_closed_pages; 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we are not out of date: if icon_urls_ is not empty, then 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // another notification has been received since we processed this one 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon_urls_.empty()) 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make local copies of lists so we can release the lock. 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_most_visited_pages = most_visited_pages_; 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_recently_closed_pages = recently_closed_pages_; 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the directory which contains old icon files, rename the current 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon directory, and create a new directory which contains new JumpList 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon files. 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath icon_dir_old(icon_dir_.value() + L"Old"); 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file_util::PathExists(icon_dir_old)) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::Delete(icon_dir_old, true); 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::Move(icon_dir_, icon_dir_old); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::CreateDirectory(icon_dir_); 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create temporary icon files for shortcuts in the "Most Visited" category. 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateIconFiles(local_most_visited_pages); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create temporary icon files for shortcuts in the "Recently Closed" 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // category. 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateIconFiles(local_recently_closed_pages); 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We finished collecting all resources needed for updating an appliation 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JumpList. So, create a new JumpList and replace the current JumpList 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with it. 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateJumpList(app_id_.c_str(), local_most_visited_pages, 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_recently_closed_pages); 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::CreateIconFiles(const ShellLinkItemList& item_list) { 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ShellLinkItemList::const_iterator item = item_list.begin(); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item != item_list.end(); ++item) { 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath icon_path; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CreateIconFile((*item)->data(), icon_dir_, &icon_path)) 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*item)->SetIcon(icon_path.value(), 0, true); 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 787