OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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> | 7 #include <windows.h> |
8 #include <shobjidl.h> | 8 #include <shobjidl.h> |
9 #include <propkey.h> | 9 #include <propkey.h> |
10 #include <propvarutil.h> | 10 #include <propvarutil.h> |
11 | 11 |
12 #include <string> | 12 #include <string> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include "base/callback.h" | 15 #include "base/callback.h" |
16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
17 #include "base/file_util.h" | 17 #include "base/file_util.h" |
18 #include "base/path_service.h" | 18 #include "base/path_service.h" |
19 #include "base/scoped_comptr_win.h" | |
20 #include "base/string_util.h" | 19 #include "base/string_util.h" |
21 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
22 #include "base/utf_string_conversions.h" | 21 #include "base/utf_string_conversions.h" |
| 22 #include "base/win/scoped_comptr.h" |
23 #include "base/win/windows_version.h" | 23 #include "base/win/windows_version.h" |
24 #include "chrome/browser/favicon_service.h" | 24 #include "chrome/browser/favicon_service.h" |
25 #include "chrome/browser/history/history.h" | 25 #include "chrome/browser/history/history.h" |
26 #include "chrome/browser/history/page_usage_data.h" | 26 #include "chrome/browser/history/page_usage_data.h" |
27 #include "chrome/browser/profiles/profile.h" | 27 #include "chrome/browser/profiles/profile.h" |
28 #include "chrome/browser/sessions/session_types.h" | 28 #include "chrome/browser/sessions/session_types.h" |
29 #include "chrome/browser/sessions/tab_restore_service.h" | 29 #include "chrome/browser/sessions/tab_restore_service.h" |
30 #include "chrome/browser/shell_integration.h" | 30 #include "chrome/browser/shell_integration.h" |
31 #include "chrome/common/chrome_constants.h" | 31 #include "chrome/common/chrome_constants.h" |
32 #include "chrome/common/chrome_switches.h" | 32 #include "chrome/common/chrome_switches.h" |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 private: | 163 private: |
164 PROPVARIANT property_; | 164 PROPVARIANT property_; |
165 | 165 |
166 DISALLOW_COPY_AND_ASSIGN(PropVariantString); | 166 DISALLOW_COPY_AND_ASSIGN(PropVariantString); |
167 }; | 167 }; |
168 | 168 |
169 // Creates an IShellLink object. | 169 // Creates an IShellLink object. |
170 // An IShellLink object is almost the same as an application shortcut, and it | 170 // An IShellLink object is almost the same as an application shortcut, and it |
171 // requires three items: the absolute path to an application, an argument | 171 // requires three items: the absolute path to an application, an argument |
172 // string, and a title string. | 172 // string, and a title string. |
173 HRESULT AddShellLink(ScopedComPtr<IObjectCollection> collection, | 173 HRESULT AddShellLink(base::win::ScopedComPtr<IObjectCollection> collection, |
174 const std::wstring& application, | 174 const std::wstring& application, |
175 const std::wstring& switches, | 175 const std::wstring& switches, |
176 scoped_refptr<ShellLinkItem> item) { | 176 scoped_refptr<ShellLinkItem> item) { |
177 // Create an IShellLink object. | 177 // Create an IShellLink object. |
178 ScopedComPtr<IShellLink> link; | 178 base::win::ScopedComPtr<IShellLink> link; |
179 HRESULT result = link.CreateInstance(CLSID_ShellLink, NULL, | 179 HRESULT result = link.CreateInstance(CLSID_ShellLink, NULL, |
180 CLSCTX_INPROC_SERVER); | 180 CLSCTX_INPROC_SERVER); |
181 if (FAILED(result)) | 181 if (FAILED(result)) |
182 return result; | 182 return result; |
183 | 183 |
184 // Set the application path. | 184 // Set the application path. |
185 // We should exit this function when this call fails because it doesn't make | 185 // We should exit this function when this call fails because it doesn't make |
186 // any sense to add a shortcut that we cannot execute. | 186 // any sense to add a shortcut that we cannot execute. |
187 result = link->SetPath(application.c_str()); | 187 result = link->SetPath(application.c_str()); |
188 if (FAILED(result)) | 188 if (FAILED(result)) |
(...skipping 24 matching lines...) Expand all Loading... |
213 // shortcut which doesn't have titles. | 213 // shortcut which doesn't have titles. |
214 // So, we should use the IPropertyStore interface to set its title as | 214 // So, we should use the IPropertyStore interface to set its title as |
215 // listed in the steps below: | 215 // listed in the steps below: |
216 // 1. Retrieve the IPropertyStore interface from the IShellLink object; | 216 // 1. Retrieve the IPropertyStore interface from the IShellLink object; |
217 // 2. Start a transaction that changes a value of the object with the | 217 // 2. Start a transaction that changes a value of the object with the |
218 // IPropertyStore interface; | 218 // IPropertyStore interface; |
219 // 3. Create a string PROPVARIANT, and; | 219 // 3. Create a string PROPVARIANT, and; |
220 // 4. Call the IPropertyStore::SetValue() function to Set the title property | 220 // 4. Call the IPropertyStore::SetValue() function to Set the title property |
221 // of the IShellLink object. | 221 // of the IShellLink object. |
222 // 5. Commit the transaction. | 222 // 5. Commit the transaction. |
223 ScopedComPtr<IPropertyStore> property_store; | 223 base::win::ScopedComPtr<IPropertyStore> property_store; |
224 result = link.QueryInterface(property_store.Receive()); | 224 result = link.QueryInterface(property_store.Receive()); |
225 if (FAILED(result)) | 225 if (FAILED(result)) |
226 return result; | 226 return result; |
227 | 227 |
228 PropVariantString property_title; | 228 PropVariantString property_title; |
229 result = property_title.Init(item->title()); | 229 result = property_title.Init(item->title()); |
230 if (FAILED(result)) | 230 if (FAILED(result)) |
231 return result; | 231 return result; |
232 | 232 |
233 result = property_store->SetValue(PKEY_Title, property_title.Get()); | 233 result = property_store->SetValue(PKEY_Title, property_title.Get()); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 // * application (std::wstring) | 274 // * application (std::wstring) |
275 // An application name to be used for creating JumpList items. | 275 // An application name to be used for creating JumpList items. |
276 // Even though we can add command-line switches to this parameter, it is | 276 // Even though we can add command-line switches to this parameter, it is |
277 // better to use the |switches| parameter below. | 277 // better to use the |switches| parameter below. |
278 // * switches (std::wstring) | 278 // * switches (std::wstring) |
279 // Command-lien switches for the application. This string is to be added | 279 // Command-lien switches for the application. This string is to be added |
280 // before the arguments of each ShellLinkItem object. If there aren't any | 280 // before the arguments of each ShellLinkItem object. If there aren't any |
281 // switches, use an empty string. | 281 // switches, use an empty string. |
282 // * data (ShellLinkItemList) | 282 // * data (ShellLinkItemList) |
283 // A list of ShellLinkItem objects to be added under the specified category. | 283 // A list of ShellLinkItem objects to be added under the specified category. |
284 HRESULT UpdateCategory(ScopedComPtr<ICustomDestinationList> list, | 284 HRESULT UpdateCategory(base::win::ScopedComPtr<ICustomDestinationList> list, |
285 int category_id, | 285 int category_id, |
286 const std::wstring& application, | 286 const std::wstring& application, |
287 const std::wstring& switches, | 287 const std::wstring& switches, |
288 const ShellLinkItemList& data, | 288 const ShellLinkItemList& data, |
289 int max_slots) { | 289 int max_slots) { |
290 // Exit this function when the given vector does not contain any items | 290 // Exit this function when the given vector does not contain any items |
291 // because an ICustomDestinationList::AppendCategory() call fails in this | 291 // because an ICustomDestinationList::AppendCategory() call fails in this |
292 // case. | 292 // case. |
293 if (data.empty() || !max_slots) | 293 if (data.empty() || !max_slots) |
294 return S_OK; | 294 return S_OK; |
295 | 295 |
296 std::wstring category = UTF16ToWide(l10n_util::GetStringUTF16(category_id)); | 296 std::wstring category = UTF16ToWide(l10n_util::GetStringUTF16(category_id)); |
297 | 297 |
298 // Create an EnumerableObjectCollection object. | 298 // Create an EnumerableObjectCollection object. |
299 // We once add the given items to this collection object and add this | 299 // We once add the given items to this collection object and add this |
300 // collection to the JumpList. | 300 // collection to the JumpList. |
301 ScopedComPtr<IObjectCollection> collection; | 301 base::win::ScopedComPtr<IObjectCollection> collection; |
302 HRESULT result = collection.CreateInstance(CLSID_EnumerableObjectCollection, | 302 HRESULT result = collection.CreateInstance(CLSID_EnumerableObjectCollection, |
303 NULL, CLSCTX_INPROC_SERVER); | 303 NULL, CLSCTX_INPROC_SERVER); |
304 if (FAILED(result)) | 304 if (FAILED(result)) |
305 return false; | 305 return false; |
306 | 306 |
307 for (ShellLinkItemList::const_iterator item = data.begin(); | 307 for (ShellLinkItemList::const_iterator item = data.begin(); |
308 item != data.end() && max_slots > 0; ++item, --max_slots) { | 308 item != data.end() && max_slots > 0; ++item, --max_slots) { |
309 scoped_refptr<ShellLinkItem> link(*item); | 309 scoped_refptr<ShellLinkItem> link(*item); |
310 AddShellLink(collection, application, switches, link); | 310 AddShellLink(collection, application, switches, link); |
311 } | 311 } |
312 | 312 |
313 // We can now add the new list to the JumpList. | 313 // We can now add the new list to the JumpList. |
314 // The ICustomDestinationList::AppendCategory() function needs the | 314 // The ICustomDestinationList::AppendCategory() function needs the |
315 // IObjectArray interface to retrieve each item in the list. So, we retrive | 315 // IObjectArray interface to retrieve each item in the list. So, we retrive |
316 // the IObjectArray interface from the IEnumeratableObjectCollection object | 316 // the IObjectArray interface from the IEnumeratableObjectCollection object |
317 // and use it. | 317 // and use it. |
318 // It seems the ICustomDestinationList::AppendCategory() function just | 318 // It seems the ICustomDestinationList::AppendCategory() function just |
319 // replaces all items in the given category with the ones in the new list. | 319 // replaces all items in the given category with the ones in the new list. |
320 ScopedComPtr<IObjectArray> object_array; | 320 base::win::ScopedComPtr<IObjectArray> object_array; |
321 result = collection.QueryInterface(object_array.Receive()); | 321 result = collection.QueryInterface(object_array.Receive()); |
322 if (FAILED(result)) | 322 if (FAILED(result)) |
323 return false; | 323 return false; |
324 | 324 |
325 return list->AppendCategory(category.c_str(), object_array); | 325 return list->AppendCategory(category.c_str(), object_array); |
326 } | 326 } |
327 | 327 |
328 // Updates the "Tasks" category of the JumpList. | 328 // Updates the "Tasks" category of the JumpList. |
329 // Even though this function is almost the same as UpdateCategory(), this | 329 // Even though this function is almost the same as UpdateCategory(), this |
330 // function has the following differences: | 330 // function has the following differences: |
331 // * The "Task" category is a registered category. | 331 // * The "Task" category is a registered category. |
332 // We should use AddUserTasks() instead of AppendCategory(). | 332 // We should use AddUserTasks() instead of AppendCategory(). |
333 // * The items in the "Task" category are static. | 333 // * The items in the "Task" category are static. |
334 // We don't have to use a list. | 334 // We don't have to use a list. |
335 HRESULT UpdateTaskCategory(ScopedComPtr<ICustomDestinationList> list, | 335 HRESULT UpdateTaskCategory(base::win::ScopedComPtr<ICustomDestinationList> list, |
336 const std::wstring& chrome_path, | 336 const std::wstring& chrome_path, |
337 const std::wstring& chrome_switches) { | 337 const std::wstring& chrome_switches) { |
338 // Create an EnumerableObjectCollection object to be added items of the | 338 // Create an EnumerableObjectCollection object to be added items of the |
339 // "Task" category. (We can also use this object for the "Task" category.) | 339 // "Task" category. (We can also use this object for the "Task" category.) |
340 ScopedComPtr<IObjectCollection> collection; | 340 base::win::ScopedComPtr<IObjectCollection> collection; |
341 HRESULT result = collection.CreateInstance(CLSID_EnumerableObjectCollection, | 341 HRESULT result = collection.CreateInstance(CLSID_EnumerableObjectCollection, |
342 NULL, CLSCTX_INPROC_SERVER); | 342 NULL, CLSCTX_INPROC_SERVER); |
343 if (FAILED(result)) | 343 if (FAILED(result)) |
344 return result; | 344 return result; |
345 | 345 |
346 // Create an IShellLink object which launches Chrome, and add it to the | 346 // Create an IShellLink object which launches Chrome, and add it to the |
347 // collection. We use our application icon as the icon for this item. | 347 // collection. We use our application icon as the icon for this item. |
348 // We remove '&' characters from this string so we can share it with our | 348 // We remove '&' characters from this string so we can share it with our |
349 // system menu. | 349 // system menu. |
350 scoped_refptr<ShellLinkItem> chrome(new ShellLinkItem); | 350 scoped_refptr<ShellLinkItem> chrome(new ShellLinkItem); |
(...skipping 14 matching lines...) Expand all Loading... |
365 UTF16ToWide(l10n_util::GetStringUTF16(IDS_NEW_INCOGNITO_WINDOW)); | 365 UTF16ToWide(l10n_util::GetStringUTF16(IDS_NEW_INCOGNITO_WINDOW)); |
366 ReplaceSubstringsAfterOffset(&incognito_title, 0, L"&", L""); | 366 ReplaceSubstringsAfterOffset(&incognito_title, 0, L"&", L""); |
367 incognito->SetTitle(incognito_title); | 367 incognito->SetTitle(incognito_title); |
368 incognito->SetIcon(chrome_path, 0, false); | 368 incognito->SetIcon(chrome_path, 0, false); |
369 AddShellLink(collection, chrome_path, chrome_switches, incognito); | 369 AddShellLink(collection, chrome_path, chrome_switches, incognito); |
370 | 370 |
371 // We can now add the new list to the JumpList. | 371 // We can now add the new list to the JumpList. |
372 // ICustomDestinationList::AddUserTasks() also uses the IObjectArray | 372 // ICustomDestinationList::AddUserTasks() also uses the IObjectArray |
373 // interface to retrieve each item in the list. So, we retrieve the | 373 // interface to retrieve each item in the list. So, we retrieve the |
374 // IObjectArray interface from the EnumerableObjectCollection object. | 374 // IObjectArray interface from the EnumerableObjectCollection object. |
375 ScopedComPtr<IObjectArray> object_array; | 375 base::win::ScopedComPtr<IObjectArray> object_array; |
376 result = collection.QueryInterface(object_array.Receive()); | 376 result = collection.QueryInterface(object_array.Receive()); |
377 if (FAILED(result)) | 377 if (FAILED(result)) |
378 return result; | 378 return result; |
379 | 379 |
380 return list->AddUserTasks(object_array); | 380 return list->AddUserTasks(object_array); |
381 } | 381 } |
382 | 382 |
383 // Updates the application JumpList. | 383 // Updates the application JumpList. |
384 // This function encapsulates all OS-specific operations required for updating | 384 // This function encapsulates all OS-specific operations required for updating |
385 // the Chromium JumpList, such as: | 385 // the Chromium JumpList, such as: |
386 // * Creating an ICustomDestinationList instance; | 386 // * Creating an ICustomDestinationList instance; |
387 // * Updating the categories of the ICustomDestinationList instance, and; | 387 // * Updating the categories of the ICustomDestinationList instance, and; |
388 // * Sending it to Taskbar of Windows 7. | 388 // * Sending it to Taskbar of Windows 7. |
389 bool UpdateJumpList(const wchar_t* app_id, | 389 bool UpdateJumpList(const wchar_t* app_id, |
390 const ShellLinkItemList& most_visited_pages, | 390 const ShellLinkItemList& most_visited_pages, |
391 const ShellLinkItemList& recently_closed_pages) { | 391 const ShellLinkItemList& recently_closed_pages) { |
392 // JumpList is implemented only on Windows 7 or later. | 392 // JumpList is implemented only on Windows 7 or later. |
393 // So, we should return now when this function is called on earlier versions | 393 // So, we should return now when this function is called on earlier versions |
394 // of Windows. | 394 // of Windows. |
395 if (base::win::GetVersion() < base::win::VERSION_WIN7) | 395 if (base::win::GetVersion() < base::win::VERSION_WIN7) |
396 return true; | 396 return true; |
397 | 397 |
398 // Create an ICustomDestinationList object and attach it to our application. | 398 // Create an ICustomDestinationList object and attach it to our application. |
399 ScopedComPtr<ICustomDestinationList> destination_list; | 399 base::win::ScopedComPtr<ICustomDestinationList> destination_list; |
400 HRESULT result = destination_list.CreateInstance(CLSID_DestinationList, NULL, | 400 HRESULT result = destination_list.CreateInstance(CLSID_DestinationList, NULL, |
401 CLSCTX_INPROC_SERVER); | 401 CLSCTX_INPROC_SERVER); |
402 if (FAILED(result)) | 402 if (FAILED(result)) |
403 return false; | 403 return false; |
404 | 404 |
405 // Set the App ID for this JumpList. | 405 // Set the App ID for this JumpList. |
406 destination_list->SetAppID(app_id); | 406 destination_list->SetAppID(app_id); |
407 | 407 |
408 // Start a transaction that updates the JumpList of this application. | 408 // Start a transaction that updates the JumpList of this application. |
409 // This implementation just replaces the all items in this JumpList, so | 409 // This implementation just replaces the all items in this JumpList, so |
410 // we don't have to use the IObjectArray object returned from this call. | 410 // we don't have to use the IObjectArray object returned from this call. |
411 // It seems Windows 7 RC (Build 7100) automatically checks the items in this | 411 // It seems Windows 7 RC (Build 7100) automatically checks the items in this |
412 // removed list and prevent us from adding the same item. | 412 // removed list and prevent us from adding the same item. |
413 UINT max_slots; | 413 UINT max_slots; |
414 ScopedComPtr<IObjectArray> removed; | 414 base::win::ScopedComPtr<IObjectArray> removed; |
415 result = destination_list->BeginList(&max_slots, __uuidof(*removed), | 415 result = destination_list->BeginList(&max_slots, __uuidof(*removed), |
416 reinterpret_cast<void**>(&removed)); | 416 reinterpret_cast<void**>(&removed)); |
417 if (FAILED(result)) | 417 if (FAILED(result)) |
418 return false; | 418 return false; |
419 | 419 |
420 // Retrieve the absolute path to "chrome.exe". | 420 // Retrieve the absolute path to "chrome.exe". |
421 FilePath chrome_path; | 421 FilePath chrome_path; |
422 if (!PathService::Get(base::FILE_EXE, &chrome_path)) | 422 if (!PathService::Get(base::FILE_EXE, &chrome_path)) |
423 return false; | 423 return false; |
424 | 424 |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 // the file thread. | 772 // the file thread. |
773 BrowserThread::PostTask( | 773 BrowserThread::PostTask( |
774 BrowserThread::FILE, FROM_HERE, | 774 BrowserThread::FILE, FROM_HERE, |
775 new JumpListUpdateTask(app_id_.c_str(), icon_dir_, most_visited_pages_, | 775 new JumpListUpdateTask(app_id_.c_str(), icon_dir_, most_visited_pages_, |
776 recently_closed_pages_)); | 776 recently_closed_pages_)); |
777 | 777 |
778 // Delete all items in these lists since we don't need these lists any longer. | 778 // Delete all items in these lists since we don't need these lists any longer. |
779 most_visited_pages_.clear(); | 779 most_visited_pages_.clear(); |
780 recently_closed_pages_.clear(); | 780 recently_closed_pages_.clear(); |
781 } | 781 } |
OLD | NEW |