Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(445)

Side by Side Diff: chrome/browser/jumplist_win.cc

Issue 168583011: Move Windows Jump List boilerplate out of jumplist_win for reuse (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed win x64 compile failure Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/jumplist_win.h" 5 #include "chrome/browser/jumplist_win.h"
6 6
7 #include <windows.h>
8 #include <shobjidl.h>
9 #include <propkey.h>
10 #include <propvarutil.h>
11
12 #include <string>
13 #include <vector>
14
15 #include "base/bind.h" 7 #include "base/bind.h"
16 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
17 #include "base/command_line.h" 9 #include "base/command_line.h"
18 #include "base/file_util.h" 10 #include "base/file_util.h"
19 #include "base/path_service.h" 11 #include "base/path_service.h"
20 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
22 #include "base/threading/thread.h" 14 #include "base/threading/thread.h"
23 #include "base/win/scoped_comptr.h"
24 #include "base/win/scoped_propvariant.h"
25 #include "base/win/windows_version.h"
26 #include "chrome/browser/chrome_notification_types.h" 15 #include "chrome/browser/chrome_notification_types.h"
27 #include "chrome/browser/favicon/favicon_service.h" 16 #include "chrome/browser/favicon/favicon_service.h"
28 #include "chrome/browser/favicon/favicon_service_factory.h" 17 #include "chrome/browser/favicon/favicon_service_factory.h"
29 #include "chrome/browser/history/history_service.h" 18 #include "chrome/browser/history/history_service.h"
30 #include "chrome/browser/history/page_usage_data.h" 19 #include "chrome/browser/history/page_usage_data.h"
31 #include "chrome/browser/history/top_sites.h" 20 #include "chrome/browser/history/top_sites.h"
32 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/profiles/profile.h"
33 #include "chrome/browser/sessions/session_types.h" 22 #include "chrome/browser/sessions/session_types.h"
34 #include "chrome/browser/sessions/tab_restore_service.h" 23 #include "chrome/browser/sessions/tab_restore_service.h"
35 #include "chrome/browser/sessions/tab_restore_service_factory.h" 24 #include "chrome/browser/sessions/tab_restore_service_factory.h"
36 #include "chrome/browser/shell_integration.h" 25 #include "chrome/browser/shell_integration.h"
37 #include "chrome/common/chrome_constants.h" 26 #include "chrome/common/chrome_constants.h"
38 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
39 #include "chrome/common/favicon/favicon_types.h" 28 #include "chrome/common/favicon/favicon_types.h"
40 #include "chrome/common/url_constants.h" 29 #include "chrome/common/url_constants.h"
41 #include "content/public/browser/browser_thread.h" 30 #include "content/public/browser/browser_thread.h"
42 #include "content/public/browser/notification_source.h" 31 #include "content/public/browser/notification_source.h"
43 #include "grit/chromium_strings.h" 32 #include "grit/chromium_strings.h"
44 #include "grit/generated_resources.h" 33 #include "grit/generated_resources.h"
45 #include "third_party/skia/include/core/SkBitmap.h"
46 #include "ui/base/l10n/l10n_util.h" 34 #include "ui/base/l10n/l10n_util.h"
47 #include "ui/gfx/codec/png_codec.h" 35 #include "ui/gfx/codec/png_codec.h"
48 #include "ui/gfx/favicon_size.h" 36 #include "ui/gfx/favicon_size.h"
49 #include "ui/gfx/icon_util.h" 37 #include "ui/gfx/icon_util.h"
50 #include "ui/gfx/image/image_family.h" 38 #include "ui/gfx/image/image_family.h"
51 #include "url/gurl.h" 39 #include "url/gurl.h"
52 40
53 using content::BrowserThread; 41 using content::BrowserThread;
54 42
55 namespace { 43 namespace {
56 44
57 // COM interfaces used in this file. 45 // Append the common switches to each shell link.
58 // These interface declarations are copied from Windows SDK 7.0. 46 void AppendCommonSwitches(ShellLinkItem* shell_link) {
59 // TODO(hbono): Bug 16903: delete them when we use Windows SDK 7.0. 47 const char* kSwitchNames[] = { switches::kUserDataDir };
60 #ifndef __IObjectArray_INTERFACE_DEFINED__ 48 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
61 #define __IObjectArray_INTERFACE_DEFINED__ 49 shell_link->CopySwitchesFrom(command_line,
50 kSwitchNames,
51 arraysize(kSwitchNames));
52 }
62 53
63 MIDL_INTERFACE("92CA9DCD-5622-4bba-A805-5E9F541BD8C9") 54 // Create a ShellLinkItem preloaded with common switches.
64 IObjectArray : public IUnknown { 55 scoped_refptr<ShellLinkItem> CreateShellLink() {
65 public: 56 scoped_refptr<ShellLinkItem> link(new ShellLinkItem);
66 virtual HRESULT STDMETHODCALLTYPE GetCount( 57 AppendCommonSwitches(link.get());
67 /* [out] */ __RPC__out UINT *pcObjects) = 0; 58 return link;
68 virtual HRESULT STDMETHODCALLTYPE GetAt(
69 /* [in] */ UINT uiIndex,
70 /* [in] */ __RPC__in REFIID riid,
71 /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
72 };
73
74 #endif // __IObjectArray_INTERFACE_DEFINED__
75
76 #ifndef __IObjectCollection_INTERFACE_DEFINED__
77 #define __IObjectCollection_INTERFACE_DEFINED__
78
79 MIDL_INTERFACE("5632b1a4-e38a-400a-928a-d4cd63230295")
80 IObjectCollection : public IObjectArray {
81 public:
82 virtual HRESULT STDMETHODCALLTYPE AddObject(
83 /* [in] */ __RPC__in_opt IUnknown *punk) = 0;
84 virtual HRESULT STDMETHODCALLTYPE AddFromArray(
85 /* [in] */ __RPC__in_opt IObjectArray *poaSource) = 0;
86 virtual HRESULT STDMETHODCALLTYPE RemoveObjectAt(
87 /* [in] */ UINT uiIndex) = 0;
88 virtual HRESULT STDMETHODCALLTYPE Clear(void) = 0;
89 };
90
91 #endif // __IObjectCollection_INTERFACE_DEFINED__
92
93 #ifndef __ICustomDestinationList_INTERFACE_DEFINED__
94 #define __ICustomDestinationList_INTERFACE_DEFINED__
95
96 typedef /* [v1_enum] */ enum tagKNOWNDESTCATEGORY {
97 KDC_FREQUENT = 1,
98 KDC_RECENT = (KDC_FREQUENT + 1)
99 } KNOWNDESTCATEGORY;
100
101 MIDL_INTERFACE("6332debf-87b5-4670-90c0-5e57b408a49e")
102 ICustomDestinationList : public IUnknown {
103 public:
104 virtual HRESULT STDMETHODCALLTYPE SetAppID(
105 /* [string][in] */__RPC__in_string LPCWSTR pszAppID) = 0;
106 virtual HRESULT STDMETHODCALLTYPE BeginList(
107 /* [out] */ __RPC__out UINT *pcMaxSlots,
108 /* [in] */ __RPC__in REFIID riid,
109 /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
110 virtual HRESULT STDMETHODCALLTYPE AppendCategory(
111 /* [string][in] */ __RPC__in_string LPCWSTR pszCategory,
112 /* [in] */ __RPC__in_opt IObjectArray *poa) = 0;
113 virtual HRESULT STDMETHODCALLTYPE AppendKnownCategory(
114 /* [in] */ KNOWNDESTCATEGORY category) = 0;
115 virtual HRESULT STDMETHODCALLTYPE AddUserTasks(
116 /* [in] */ __RPC__in_opt IObjectArray *poa) = 0;
117 virtual HRESULT STDMETHODCALLTYPE CommitList(void) = 0;
118 virtual HRESULT STDMETHODCALLTYPE GetRemovedDestinations(
119 /* [in] */ __RPC__in REFIID riid,
120 /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
121 virtual HRESULT STDMETHODCALLTYPE DeleteList(
122 /* [string][in] */ __RPC__in_string LPCWSTR pszAppID) = 0;
123 virtual HRESULT STDMETHODCALLTYPE AbortList(void) = 0;
124 };
125
126 #endif // __ICustomDestinationList_INTERFACE_DEFINED__
127
128 // Class IDs used in this file.
129 // These class IDs must be defined in an anonymous namespace to avoid
130 // conflicts with ones defined in "shell32.lib" of Visual Studio 2008.
131 // TODO(hbono): Bug 16903: delete them when we use Windows SDK 7.0.
132 const CLSID CLSID_DestinationList = {
133 0x77f10cf0, 0x3db5, 0x4966, {0xb5, 0x20, 0xb7, 0xc5, 0x4f, 0xd3, 0x5e, 0xd6}
134 };
135
136 const CLSID CLSID_EnumerableObjectCollection = {
137 0x2d3468c1, 0x36a7, 0x43b6, {0xac, 0x24, 0xd3, 0xf0, 0x2f, 0xd9, 0x60, 0x7a}
138 };
139
140 }; // namespace
141
142 // END OF WINDOWS 7 SDK DEFINITIONS
143
144 namespace {
145
146 // Creates an IShellLink object.
147 // An IShellLink object is almost the same as an application shortcut, and it
148 // requires three items: the absolute path to an application, an argument
149 // string, and a title string.
150 HRESULT AddShellLink(base::win::ScopedComPtr<IObjectCollection> collection,
151 const std::wstring& application,
152 const std::wstring& switches,
153 scoped_refptr<ShellLinkItem> item) {
154 // Create an IShellLink object.
155 base::win::ScopedComPtr<IShellLink> link;
156 HRESULT result = link.CreateInstance(CLSID_ShellLink, NULL,
157 CLSCTX_INPROC_SERVER);
158 if (FAILED(result))
159 return result;
160
161 // Set the application path.
162 // We should exit this function when this call fails because it doesn't make
163 // any sense to add a shortcut that we cannot execute.
164 result = link->SetPath(application.c_str());
165 if (FAILED(result))
166 return result;
167
168 // Attach the command-line switches of this process before the given
169 // arguments and set it as the arguments of this IShellLink object.
170 // We also exit this function when this call fails because it isn't usuful to
171 // add a shortcut that cannot open the given page.
172 std::wstring arguments(switches);
173 if (!item->arguments().empty()) {
174 arguments.push_back(L' ');
175 arguments += item->arguments();
176 }
177 result = link->SetArguments(arguments.c_str());
178 if (FAILED(result))
179 return result;
180
181 // Attach the given icon path to this IShellLink object.
182 // Since an icon is an optional item for an IShellLink object, so we don't
183 // have to exit even when it fails.
184 if (!item->icon().empty())
185 link->SetIconLocation(item->icon().c_str(), item->index());
186
187 // Set the title of the IShellLink object.
188 // The IShellLink interface does not have any functions which update its
189 // title because this interface is originally for creating an application
190 // shortcut which doesn't have titles.
191 // So, we should use the IPropertyStore interface to set its title as
192 // listed in the steps below:
193 // 1. Retrieve the IPropertyStore interface from the IShellLink object;
194 // 2. Start a transaction that changes a value of the object with the
195 // IPropertyStore interface;
196 // 3. Create a string PROPVARIANT, and;
197 // 4. Call the IPropertyStore::SetValue() function to Set the title property
198 // of the IShellLink object.
199 // 5. Commit the transaction.
200 base::win::ScopedComPtr<IPropertyStore> property_store;
201 result = link.QueryInterface(property_store.Receive());
202 if (FAILED(result))
203 return result;
204
205 base::win::ScopedPropVariant property_title;
206 // Call InitPropVariantFromString() to initialize |property_title|. Reading
207 // <propvarutil.h>, it seems InitPropVariantFromString() is an inline function
208 // that initializes a PROPVARIANT object and calls SHStrDupW() to set a copy
209 // of its input string. It is thus safe to call it without first creating a
210 // copy here.
211 result = InitPropVariantFromString(item->title().c_str(),
212 property_title.Receive());
213 if (FAILED(result))
214 return result;
215
216 result = property_store->SetValue(PKEY_Title, property_title.get());
217 if (FAILED(result))
218 return result;
219
220 result = property_store->Commit();
221 if (FAILED(result))
222 return result;
223
224 // Add this IShellLink object to the given collection.
225 return collection->AddObject(link);
226 } 59 }
227 60
228 // Creates a temporary icon file to be shown in JumpList. 61 // Creates a temporary icon file to be shown in JumpList.
229 bool CreateIconFile(const SkBitmap& bitmap, 62 bool CreateIconFile(const SkBitmap& bitmap,
230 const base::FilePath& icon_dir, 63 const base::FilePath& icon_dir,
231 base::FilePath* icon_path) { 64 base::FilePath* icon_path) {
232 // Retrieve the path to a temporary file. 65 // Retrieve the path to a temporary file.
233 // We don't have to care about the extension of this temporary file because 66 // We don't have to care about the extension of this temporary file because
234 // JumpList does not care about it. 67 // JumpList does not care about it.
235 base::FilePath path; 68 base::FilePath path;
236 if (!base::CreateTemporaryFileInDir(icon_dir, &path)) 69 if (!base::CreateTemporaryFileInDir(icon_dir, &path))
237 return false; 70 return false;
238 71
239 // Create an icon file from the favicon attached to the given |page|, and 72 // Create an icon file from the favicon attached to the given |page|, and
240 // save it as the temporary file. 73 // save it as the temporary file.
241 gfx::ImageFamily image_family; 74 gfx::ImageFamily image_family;
242 image_family.Add(gfx::Image::CreateFrom1xBitmap(bitmap)); 75 image_family.Add(gfx::Image::CreateFrom1xBitmap(bitmap));
243 if (!IconUtil::CreateIconFileFromImageFamily(image_family, path)) 76 if (!IconUtil::CreateIconFileFromImageFamily(image_family, path))
244 return false; 77 return false;
245 78
246 // Add this icon file to the list and return its absolute path. 79 // Add this icon file to the list and return its absolute path.
247 // The IShellLink::SetIcon() function needs the absolute path to an icon. 80 // The IShellLink::SetIcon() function needs the absolute path to an icon.
248 *icon_path = path; 81 *icon_path = path;
249 return true; 82 return true;
250 } 83 }
251 84
252 // Updates a specified category of an application JumpList. 85 // Updates the "Tasks" category of the JumpList.
253 // This function cannot update registered categories (such as "Tasks") because 86 bool UpdateTaskCategory(JumpListUpdater* jumplist_updater) {
254 // special steps are required for updating them. 87 base::FilePath chrome_path;
255 // So, this function can be used only for adding an unregistered category. 88 if (!PathService::Get(base::FILE_EXE, &chrome_path))
256 // Parameters:
257 // * category_id (int)
258 // A string ID which contains the category name.
259 // * application (std::wstring)
260 // An application name to be used for creating JumpList items.
261 // Even though we can add command-line switches to this parameter, it is
262 // better to use the |switches| parameter below.
263 // * switches (std::wstring)
264 // Command-lien switches for the application. This string is to be added
265 // before the arguments of each ShellLinkItem object. If there aren't any
266 // switches, use an empty string.
267 // * data (ShellLinkItemList)
268 // A list of ShellLinkItem objects to be added under the specified category.
269 HRESULT UpdateCategory(base::win::ScopedComPtr<ICustomDestinationList> list,
270 int category_id,
271 const std::wstring& application,
272 const std::wstring& switches,
273 const ShellLinkItemList& data,
274 int max_slots) {
275 // Exit this function when the given vector does not contain any items
276 // because an ICustomDestinationList::AppendCategory() call fails in this
277 // case.
278 if (data.empty() || !max_slots)
279 return S_OK;
280
281 std::wstring category =
282 base::UTF16ToWide(l10n_util::GetStringUTF16(category_id));
283
284 // Create an EnumerableObjectCollection object.
285 // We once add the given items to this collection object and add this
286 // collection to the JumpList.
287 base::win::ScopedComPtr<IObjectCollection> collection;
288 HRESULT result = collection.CreateInstance(CLSID_EnumerableObjectCollection,
289 NULL, CLSCTX_INPROC_SERVER);
290 if (FAILED(result))
291 return false; 89 return false;
292 90
293 for (ShellLinkItemList::const_iterator item = data.begin(); 91 ShellLinkItemList items;
294 item != data.end() && max_slots > 0; ++item, --max_slots) {
295 scoped_refptr<ShellLinkItem> link(*item);
296 AddShellLink(collection, application, switches, link);
297 }
298
299 // We can now add the new list to the JumpList.
300 // The ICustomDestinationList::AppendCategory() function needs the
301 // IObjectArray interface to retrieve each item in the list. So, we retrive
302 // the IObjectArray interface from the IEnumeratableObjectCollection object
303 // and use it.
304 // It seems the ICustomDestinationList::AppendCategory() function just
305 // replaces all items in the given category with the ones in the new list.
306 base::win::ScopedComPtr<IObjectArray> object_array;
307 result = collection.QueryInterface(object_array.Receive());
308 if (FAILED(result))
309 return false;
310
311 return list->AppendCategory(category.c_str(), object_array);
312 }
313
314 // Updates the "Tasks" category of the JumpList.
315 // Even though this function is almost the same as UpdateCategory(), this
316 // function has the following differences:
317 // * The "Task" category is a registered category.
318 // We should use AddUserTasks() instead of AppendCategory().
319 // * The items in the "Task" category are static.
320 // We don't have to use a list.
321 HRESULT UpdateTaskCategory(base::win::ScopedComPtr<ICustomDestinationList> list,
322 const std::wstring& chrome_path,
323 const std::wstring& chrome_switches) {
324 // Create an EnumerableObjectCollection object to be added items of the
325 // "Task" category. (We can also use this object for the "Task" category.)
326 base::win::ScopedComPtr<IObjectCollection> collection;
327 HRESULT result = collection.CreateInstance(CLSID_EnumerableObjectCollection,
328 NULL, CLSCTX_INPROC_SERVER);
329 if (FAILED(result))
330 return result;
331 92
332 // Create an IShellLink object which launches Chrome, and add it to the 93 // Create an IShellLink object which launches Chrome, and add it to the
333 // collection. We use our application icon as the icon for this item. 94 // collection. We use our application icon as the icon for this item.
334 // We remove '&' characters from this string so we can share it with our 95 // We remove '&' characters from this string so we can share it with our
335 // system menu. 96 // system menu.
336 scoped_refptr<ShellLinkItem> chrome(new ShellLinkItem); 97 scoped_refptr<ShellLinkItem> chrome = CreateShellLink();
337 std::wstring chrome_title = 98 std::wstring chrome_title =
338 base::UTF16ToWide(l10n_util::GetStringUTF16(IDS_NEW_WINDOW)); 99 base::UTF16ToWide(l10n_util::GetStringUTF16(IDS_NEW_WINDOW));
339 ReplaceSubstringsAfterOffset(&chrome_title, 0, L"&", L""); 100 ReplaceSubstringsAfterOffset(&chrome_title, 0, L"&", L"");
340 chrome->SetTitle(chrome_title); 101 chrome->SetTitle(chrome_title);
341 chrome->SetIcon(chrome_path, 0, false); 102 chrome->SetIcon(chrome_path.value(), 0);
342 AddShellLink(collection, chrome_path, chrome_switches, chrome); 103 items.push_back(chrome);
343 104
344 // Create an IShellLink object which launches Chrome in incognito mode, and 105 // Create an IShellLink object which launches Chrome in incognito mode, and
345 // add it to the collection. We use our application icon as the icon for 106 // add it to the collection. We use our application icon as the icon for
346 // this item. 107 // this item.
347 scoped_refptr<ShellLinkItem> incognito(new ShellLinkItem); 108 scoped_refptr<ShellLinkItem> incognito = CreateShellLink();
348 incognito->SetArguments( 109 incognito->AppendArgument(
tapted 2014/02/18 06:12:43 incognito->AppendSwitch(switches::kIncognito) or
tmdiep 2014/02/18 06:58:34 Done.
349 base::ASCIIToWide(std::string("--") + switches::kIncognito)); 110 base::ASCIIToWide(std::string("--") + switches::kIncognito));
350 std::wstring incognito_title = 111 std::wstring incognito_title =
351 base::UTF16ToWide(l10n_util::GetStringUTF16(IDS_NEW_INCOGNITO_WINDOW)); 112 base::UTF16ToWide(l10n_util::GetStringUTF16(IDS_NEW_INCOGNITO_WINDOW));
352 ReplaceSubstringsAfterOffset(&incognito_title, 0, L"&", L""); 113 ReplaceSubstringsAfterOffset(&incognito_title, 0, L"&", L"");
353 incognito->SetTitle(incognito_title); 114 incognito->SetTitle(incognito_title);
354 incognito->SetIcon(chrome_path, 0, false); 115 incognito->SetIcon(chrome_path.value(), 0);
355 AddShellLink(collection, chrome_path, chrome_switches, incognito); 116 items.push_back(incognito);
356 117
357 // We can now add the new list to the JumpList. 118 return jumplist_updater->AddTasks(items);
358 // ICustomDestinationList::AddUserTasks() also uses the IObjectArray
359 // interface to retrieve each item in the list. So, we retrieve the
360 // IObjectArray interface from the EnumerableObjectCollection object.
361 base::win::ScopedComPtr<IObjectArray> object_array;
362 result = collection.QueryInterface(object_array.Receive());
363 if (FAILED(result))
364 return result;
365
366 return list->AddUserTasks(object_array);
367 } 119 }
368 120
369 // Updates the application JumpList. 121 // Updates the application JumpList.
370 // This function encapsulates all OS-specific operations required for updating
371 // the Chromium JumpList, such as:
372 // * Creating an ICustomDestinationList instance;
373 // * Updating the categories of the ICustomDestinationList instance, and;
374 // * Sending it to Taskbar of Windows 7.
375 bool UpdateJumpList(const wchar_t* app_id, 122 bool UpdateJumpList(const wchar_t* app_id,
376 const ShellLinkItemList& most_visited_pages, 123 const ShellLinkItemList& most_visited_pages,
377 const ShellLinkItemList& recently_closed_pages) { 124 const ShellLinkItemList& recently_closed_pages) {
378 // JumpList is implemented only on Windows 7 or later. 125 // JumpList is implemented only on Windows 7 or later.
379 // So, we should return now when this function is called on earlier versions 126 // So, we should return now when this function is called on earlier versions
380 // of Windows. 127 // of Windows.
381 if (base::win::GetVersion() < base::win::VERSION_WIN7) 128 if (!JumpListUpdater::IsEnabled())
382 return true; 129 return true;
383 130
384 // Create an ICustomDestinationList object and attach it to our application. 131 JumpListUpdater jumplist_updater(app_id);
385 base::win::ScopedComPtr<ICustomDestinationList> destination_list; 132 if (!jumplist_updater.BeginUpdate())
386 HRESULT result = destination_list.CreateInstance(CLSID_DestinationList, NULL,
387 CLSCTX_INPROC_SERVER);
388 if (FAILED(result))
389 return false; 133 return false;
390 134
391 // Set the App ID for this JumpList.
392 destination_list->SetAppID(app_id);
393
394 // Start a transaction that updates the JumpList of this application.
395 // This implementation just replaces the all items in this JumpList, so
396 // we don't have to use the IObjectArray object returned from this call.
397 // It seems Windows 7 RC (Build 7100) automatically checks the items in this
398 // removed list and prevent us from adding the same item.
399 UINT max_slots;
400 base::win::ScopedComPtr<IObjectArray> removed;
401 result = destination_list->BeginList(&max_slots, __uuidof(*removed),
402 reinterpret_cast<void**>(&removed));
403 if (FAILED(result))
404 return false;
405
406 // Retrieve the absolute path to "chrome.exe".
407 base::FilePath chrome_path;
408 if (!PathService::Get(base::FILE_EXE, &chrome_path))
409 return false;
410
411 // Retrieve the command-line switches of this process.
412 CommandLine command_line(CommandLine::NO_PROGRAM);
413 base::FilePath user_data_dir = CommandLine::ForCurrentProcess()->
414 GetSwitchValuePath(switches::kUserDataDir);
415 if (!user_data_dir.empty())
416 command_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
417
418 std::wstring chrome_switches = command_line.GetCommandLineString();
419
420 // We allocate 60% of the given JumpList slots to "most-visited" items 135 // We allocate 60% of the given JumpList slots to "most-visited" items
421 // and 40% to "recently-closed" items, respectively. 136 // and 40% to "recently-closed" items, respectively.
422 // Nevertheless, if there are not so many items in |recently_closed_pages|, 137 // Nevertheless, if there are not so many items in |recently_closed_pages|,
423 // we give the remaining slots to "most-visited" items. 138 // we give the remaining slots to "most-visited" items.
424 const int kMostVisited = 60; 139 const int kMostVisited = 60;
425 const int kRecentlyClosed = 40; 140 const int kRecentlyClosed = 40;
426 const int kTotal = kMostVisited + kRecentlyClosed; 141 const int kTotal = kMostVisited + kRecentlyClosed;
427 size_t most_visited_items = MulDiv(max_slots, kMostVisited, kTotal); 142 size_t most_visited_items =
428 size_t recently_closed_items = max_slots - most_visited_items; 143 MulDiv(jumplist_updater.user_max_items(), kMostVisited, kTotal);
144 size_t recently_closed_items =
145 jumplist_updater.user_max_items() - most_visited_items;
429 if (recently_closed_pages.size() < recently_closed_items) { 146 if (recently_closed_pages.size() < recently_closed_items) {
430 most_visited_items += recently_closed_items - recently_closed_pages.size(); 147 most_visited_items += recently_closed_items - recently_closed_pages.size();
431 recently_closed_items = recently_closed_pages.size(); 148 recently_closed_items = recently_closed_pages.size();
432 } 149 }
433 150
434 // Update the "Most Visited" category of the JumpList. 151 // Update the "Most Visited" category of the JumpList.
435 // This update request is applied into the JumpList when we commit this 152 // This update request is applied into the JumpList when we commit this
436 // transaction. 153 // transaction.
437 result = UpdateCategory(destination_list, IDS_NEW_TAB_MOST_VISITED, 154 if (!jumplist_updater.AddCustomCategory(
438 chrome_path.value(), chrome_switches, 155 base::UTF16ToWide(
439 most_visited_pages, most_visited_items); 156 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED)),
440 if (FAILED(result)) 157 most_visited_pages, most_visited_items)) {
441 return false; 158 return false;
159 }
442 160
443 // Update the "Recently Closed" category of the JumpList. 161 // Update the "Recently Closed" category of the JumpList.
444 result = UpdateCategory(destination_list, IDS_NEW_TAB_RECENTLY_CLOSED, 162 if (!jumplist_updater.AddCustomCategory(
445 chrome_path.value(), chrome_switches, 163 base::UTF16ToWide(
446 recently_closed_pages, recently_closed_items); 164 l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED)),
447 if (FAILED(result)) 165 recently_closed_pages, recently_closed_items)) {
448 return false; 166 return false;
167 }
449 168
450 // Update the "Tasks" category of the JumpList. 169 // Update the "Tasks" category of the JumpList.
451 result = UpdateTaskCategory(destination_list, chrome_path.value(), 170 if (!UpdateTaskCategory(&jumplist_updater))
452 chrome_switches);
453 if (FAILED(result))
454 return false; 171 return false;
455 172
456 // Commit this transaction and send the updated JumpList to Windows. 173 // Commit this transaction and send the updated JumpList to Windows.
457 result = destination_list->CommitList(); 174 if (!jumplist_updater.CommitUpdate())
458 if (FAILED(result))
459 return false; 175 return false;
460 176
461 return true; 177 return true;
462 } 178 }
463 179
464 } // namespace 180 } // namespace
465 181
466 JumpList::JumpList() 182 JumpList::JumpList()
467 : weak_ptr_factory_(this), 183 : weak_ptr_factory_(this),
468 profile_(NULL), 184 profile_(NULL),
469 task_id_(base::CancelableTaskTracker::kBadTaskId) {} 185 task_id_(base::CancelableTaskTracker::kBadTaskId) {}
470 186
471 JumpList::~JumpList() { 187 JumpList::~JumpList() {
472 Terminate(); 188 Terminate();
473 } 189 }
474 190
475 // static 191 // static
476 bool JumpList::Enabled() { 192 bool JumpList::Enabled() {
477 return (base::win::GetVersion() >= base::win::VERSION_WIN7 && 193 return (JumpListUpdater::IsEnabled() &&
478 !CommandLine::ForCurrentProcess()->HasSwitch( 194 !CommandLine::ForCurrentProcess()->HasSwitch(
479 switches::kDisableCustomJumpList)); 195 switches::kDisableCustomJumpList));
480 } 196 }
481 197
482 bool JumpList::AddObserver(Profile* profile) { 198 bool JumpList::AddObserver(Profile* profile) {
483 // To update JumpList when a tab is added or removed, we add this object to 199 // To update JumpList when a tab is added or removed, we add this object to
484 // the observer list of the TabRestoreService class. 200 // the observer list of the TabRestoreService class.
485 // When we add this object to the observer list, we save the pointer to this 201 // When we add this object to the observer list, we save the pointer to this
486 // TabRestoreService object. This pointer is used when we remove this object 202 // TabRestoreService object. This pointer is used when we remove this object
487 // from the observer list. 203 // from the observer list.
488 if (base::win::GetVersion() < base::win::VERSION_WIN7 || !profile) 204 if (!JumpListUpdater::IsEnabled() || !profile)
489 return false; 205 return false;
490 206
491 TabRestoreService* tab_restore_service = 207 TabRestoreService* tab_restore_service =
492 TabRestoreServiceFactory::GetForProfile(profile); 208 TabRestoreServiceFactory::GetForProfile(profile);
493 if (!tab_restore_service) 209 if (!tab_restore_service)
494 return false; 210 return false;
495 211
496 app_id_ = ShellIntegration::GetChromiumModelIdForProfile(profile->GetPath()); 212 app_id_ = ShellIntegration::GetChromiumModelIdForProfile(profile->GetPath());
497 icon_dir_ = profile->GetPath().Append(chrome::kJumpListIconDirname); 213 icon_dir_ = profile->GetPath().Append(chrome::kJumpListIconDirname);
498 profile_ = profile; 214 profile_ = profile;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 const history::MostVisitedURLList& data) { 283 const history::MostVisitedURLList& data) {
568 284
569 // If we have a pending favicon request, cancel it here (it is out of date). 285 // If we have a pending favicon request, cancel it here (it is out of date).
570 CancelPendingUpdate(); 286 CancelPendingUpdate();
571 287
572 { 288 {
573 base::AutoLock auto_lock(list_lock_); 289 base::AutoLock auto_lock(list_lock_);
574 most_visited_pages_.clear(); 290 most_visited_pages_.clear();
575 for (size_t i = 0; i < data.size(); i++) { 291 for (size_t i = 0; i < data.size(); i++) {
576 const history::MostVisitedURL& url = data[i]; 292 const history::MostVisitedURL& url = data[i];
577 scoped_refptr<ShellLinkItem> link(new ShellLinkItem); 293 scoped_refptr<ShellLinkItem> link = CreateShellLink();
578 std::string url_string = url.url.spec(); 294 std::string url_string = url.url.spec();
579 link->SetArguments(base::UTF8ToWide(url_string)); 295 std::wstring url_string_wide = base::UTF8ToWide(url_string);
580 link->SetTitle(!url.title.empty()? url.title : link->arguments()); 296 link->AppendArgument(url_string_wide);
297 link->SetTitle(!url.title.empty()? url.title : url_string_wide);
581 most_visited_pages_.push_back(link); 298 most_visited_pages_.push_back(link);
582 icon_urls_.push_back(make_pair(url_string, link)); 299 icon_urls_.push_back(make_pair(url_string, link));
583 } 300 }
584 } 301 }
585 302
586 // Send a query that retrieves the first favicon. 303 // Send a query that retrieves the first favicon.
587 StartLoadingFavicon(); 304 StartLoadingFavicon();
588 } 305 }
589 306
590 void JumpList::TabRestoreServiceChanged(TabRestoreService* service) { 307 void JumpList::TabRestoreServiceChanged(TabRestoreService* service) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 } 351 }
635 352
636 bool JumpList::AddTab(const TabRestoreService::Tab* tab, 353 bool JumpList::AddTab(const TabRestoreService::Tab* tab,
637 ShellLinkItemList* list, 354 ShellLinkItemList* list,
638 size_t max_items) { 355 size_t max_items) {
639 // This code adds the URL and the title strings of the given tab to the 356 // This code adds the URL and the title strings of the given tab to the
640 // specified list. 357 // specified list.
641 if (list->size() >= max_items) 358 if (list->size() >= max_items)
642 return false; 359 return false;
643 360
644 scoped_refptr<ShellLinkItem> link(new ShellLinkItem); 361 scoped_refptr<ShellLinkItem> link = CreateShellLink();
645 const sessions::SerializedNavigationEntry& current_navigation = 362 const sessions::SerializedNavigationEntry& current_navigation =
646 tab->navigations.at(tab->current_navigation_index); 363 tab->navigations.at(tab->current_navigation_index);
647 std::string url = current_navigation.virtual_url().spec(); 364 std::string url = current_navigation.virtual_url().spec();
648 link->SetArguments(base::UTF8ToWide(url)); 365 link->AppendArgument(base::UTF8ToWide(url));
649 link->SetTitle(current_navigation.title()); 366 link->SetTitle(current_navigation.title());
650 list->push_back(link); 367 list->push_back(link);
651 icon_urls_.push_back(make_pair(url, link)); 368 icon_urls_.push_back(make_pair(url, link));
652 return true; 369 return true;
653 } 370 }
654 371
655 void JumpList::AddWindow(const TabRestoreService::Window* window, 372 void JumpList::AddWindow(const TabRestoreService::Window* window,
656 ShellLinkItemList* list, 373 ShellLinkItemList* list,
657 size_t max_items) { 374 size_t max_items) {
658 // This code enumerates al the tabs in the given window object and add their 375 // This code enumerates al the tabs in the given window object and add their
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 // JumpList. So, create a new JumpList and replace the current JumpList 467 // JumpList. So, create a new JumpList and replace the current JumpList
751 // with it. 468 // with it.
752 UpdateJumpList(app_id_.c_str(), local_most_visited_pages, 469 UpdateJumpList(app_id_.c_str(), local_most_visited_pages,
753 local_recently_closed_pages); 470 local_recently_closed_pages);
754 } 471 }
755 472
756 void JumpList::CreateIconFiles(const ShellLinkItemList& item_list) { 473 void JumpList::CreateIconFiles(const ShellLinkItemList& item_list) {
757 for (ShellLinkItemList::const_iterator item = item_list.begin(); 474 for (ShellLinkItemList::const_iterator item = item_list.begin();
758 item != item_list.end(); ++item) { 475 item != item_list.end(); ++item) {
759 base::FilePath icon_path; 476 base::FilePath icon_path;
760 if (CreateIconFile((*item)->data(), icon_dir_, &icon_path)) 477 if (CreateIconFile((*item)->icon_data(), icon_dir_, &icon_path))
761 (*item)->SetIcon(icon_path.value(), 0, true); 478 (*item)->SetIcon(icon_path.value(), 0);
762 } 479 }
763 } 480 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698