jumplist_win.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/page_usage_data.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/top_sites.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_types.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/tab_restore_service.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/tab_restore_service_factory.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/shell_integration.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/favicon_base/favicon_types.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/favicon_size.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/icon_util.h" 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image_family.h" 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Append the common switches to each shell link. 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppendCommonSwitches(ShellLinkItem* shell_link) { 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const char* kSwitchNames[] = { switches::kUserDataDir }; 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) shell_link->GetCommandLine()->CopySwitchesFrom(command_line, 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kSwitchNames, 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) arraysize(kSwitchNames)); 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Create a ShellLinkItem preloaded with common switches. 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_refptr<ShellLinkItem> CreateShellLink() { 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<ShellLinkItem> link(new ShellLinkItem); 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AppendCommonSwitches(link.get()); 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return link; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a temporary icon file to be shown in JumpList. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateIconFile(const SkBitmap& bitmap, 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& icon_dir, 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath* icon_path) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the path to a temporary file. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't have to care about the extension of this temporary file because 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JumpList does not care about it. 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path; 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateTemporaryFileInDir(icon_dir, &path)) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an icon file from the favicon attached to the given |page|, and 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save it as the temporary file. 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::ImageFamily image_family; 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) image_family.Add(gfx::Image::CreateFrom1xBitmap(bitmap)); 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!IconUtil::CreateIconFileFromImageFamily(image_family, path)) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add this icon file to the list and return its absolute path. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The IShellLink::SetIcon() function needs the absolute path to an icon. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *icon_path = path; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Updates the "Tasks" category of the JumpList. 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool UpdateTaskCategory(JumpListUpdater* jumplist_updater) { 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::FilePath chrome_path; 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!PathService::Get(base::FILE_EXE, &chrome_path)) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ShellLinkItemList items; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an IShellLink object which launches Chrome, and add it to the 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // collection. We use our application icon as the icon for this item. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We remove '&' characters from this string so we can share it with our 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // system menu. 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<ShellLinkItem> chrome = CreateShellLink(); 9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::string16 chrome_title = l10n_util::GetStringUTF16(IDS_NEW_WINDOW); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplaceSubstringsAfterOffset(&chrome_title, 0, L"&", L""); 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome->set_title(chrome_title); 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome->set_icon(chrome_path.value(), 0); 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) items.push_back(chrome); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an IShellLink object which launches Chrome in incognito mode, and 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // add it to the collection. We use our application icon as the icon for 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this item. 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<ShellLinkItem> incognito = CreateShellLink(); 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) incognito->GetCommandLine()->AppendSwitch(switches::kIncognito); 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::string16 incognito_title = 11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_NEW_INCOGNITO_WINDOW); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplaceSubstringsAfterOffset(&incognito_title, 0, L"&", L""); 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) incognito->set_title(incognito_title); 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) incognito->set_icon(chrome_path.value(), 0); 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) items.push_back(incognito); 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return jumplist_updater->AddTasks(items); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Updates the application JumpList. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UpdateJumpList(const wchar_t* app_id, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ShellLinkItemList& most_visited_pages, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ShellLinkItemList& recently_closed_pages) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JumpList is implemented only on Windows 7 or later. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So, we should return now when this function is called on earlier versions 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of Windows. 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!JumpListUpdater::IsEnabled()) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) JumpListUpdater jumplist_updater(app_id); 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!jumplist_updater.BeginUpdate()) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We allocate 60% of the given JumpList slots to "most-visited" items 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and 40% to "recently-closed" items, respectively. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Nevertheless, if there are not so many items in |recently_closed_pages|, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we give the remaining slots to "most-visited" items. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMostVisited = 60; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kRecentlyClosed = 40; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kTotal = kMostVisited + kRecentlyClosed; 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t most_visited_items = 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MulDiv(jumplist_updater.user_max_items(), kMostVisited, kTotal); 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t recently_closed_items = 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) jumplist_updater.user_max_items() - most_visited_items; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (recently_closed_pages.size() < recently_closed_items) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) most_visited_items += recently_closed_items - recently_closed_pages.size(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recently_closed_items = recently_closed_pages.size(); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the "Most Visited" category of the JumpList. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This update request is applied into the JumpList when we commit this 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction. 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!jumplist_updater.AddCustomCategory( 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::UTF16ToWide( 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED)), 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) most_visited_pages, most_visited_items)) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the "Recently Closed" category of the JumpList. 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!jumplist_updater.AddCustomCategory( 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::UTF16ToWide( 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED)), 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) recently_closed_pages, recently_closed_items)) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the "Tasks" category of the JumpList. 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!UpdateTaskCategory(&jumplist_updater)) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Commit this transaction and send the updated JumpList to Windows. 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!jumplist_updater.CommitUpdate()) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JumpList::JumpList() 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : weak_ptr_factory_(this), 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(NULL), 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) task_id_(base::CancelableTaskTracker::kBadTaskId) {} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JumpList::~JumpList() { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Terminate(); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JumpList::Enabled() { 191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return JumpListUpdater::IsEnabled(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JumpList::AddObserver(Profile* profile) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To update JumpList when a tab is added or removed, we add this object to 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the observer list of the TabRestoreService class. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we add this object to the observer list, we save the pointer to this 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TabRestoreService object. This pointer is used when we remove this object 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the observer list. 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!JumpListUpdater::IsEnabled() || !profile) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreService* tab_restore_service = 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceFactory::GetForProfile(profile); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tab_restore_service) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) app_id_ = ShellIntegration::GetChromiumModelIdForProfile(profile->GetPath()); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_dir_ = profile->GetPath().Append(chrome::kJumpListIconDirname); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_ = profile; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::TopSites* top_sites = profile_->GetTopSites(); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top_sites) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TopSites updates itself after a delay. This is especially noticable when 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // your profile is empty. Ask TopSites to update itself when jumplist is 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // initialized. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_sites->SyncWithHistory(); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.reset(new content::NotificationRegistrar); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register for notification when TopSites changes so that we can update 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ourself. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_->Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<history::TopSites>(top_sites)); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register for notification when profile is destroyed to ensure that all 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // observers are detatched at that time. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_->Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(profile_)); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_restore_service->AddObserver(this); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::Observe(int type, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_TOP_SITES_CHANGED: { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Most visited urls changed, query again. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::TopSites* top_sites = profile_->GetTopSites(); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top_sites) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_sites->GetMostVisitedURLs( 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&JumpList::OnMostVisitedURLsAvailable, 241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), false); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_PROFILE_DESTROYED: { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Profile was destroyed, do clean-up. 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Terminate(); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unexpected notification type."; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::RemoveObserver() { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_) { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreService* tab_restore_service = 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceFactory::GetForProfile(profile_); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_restore_service) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_restore_service->RemoveObserver(this); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.reset(); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_ = NULL; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::CancelPendingUpdate() { 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (task_id_ != base::CancelableTaskTracker::kBadTaskId) { 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cancelable_task_tracker_.TryCancel(task_id_); 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) task_id_ = base::CancelableTaskTracker::kBadTaskId; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::Terminate() { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingUpdate(); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveObserver(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::OnMostVisitedURLsAvailable( 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::MostVisitedURLList& data) { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have a pending favicon request, cancel it here (it is out of date). 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingUpdate(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) most_visited_pages_.clear(); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); i++) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::MostVisitedURL& url = data[i]; 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<ShellLinkItem> link = CreateShellLink(); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url_string = url.url.spec(); 291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::wstring url_string_wide = base::UTF8ToWide(url_string); 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) link->GetCommandLine()->AppendArgNative(url_string_wide); 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) link->set_title(!url.title.empty()? url.title : url_string_wide); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) most_visited_pages_.push_back(link); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls_.push_back(make_pair(url_string, link)); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send a query that retrieves the first favicon. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartLoadingFavicon(); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::TabRestoreServiceChanged(TabRestoreService* service) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if we have a pending handle request, cancel it here (it is out of date). 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingUpdate(); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // local list to pass to methods 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList temp_list; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a list of ShellLinkItems from the "Recently Closed" pages. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As noted above, we create a ShellLinkItem objects with the following 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parameters. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * arguments 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last URL of the tab object. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * title 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The title of the last URL. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * icon 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An empty string. This value is to be updated in OnFaviconDataAvailable(). 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code is copied from 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RecentlyClosedTabsHandler::TabRestoreServiceChanged() to emulate it. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kRecentlyClosedCount = 4; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreService* tab_restore_service = 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceFactory::GetForProfile(profile_); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TabRestoreService::Entries& entries = tab_restore_service->entries(); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (TabRestoreService::Entries::const_iterator it = entries.begin(); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != entries.end(); ++it) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TabRestoreService::Entry* entry = *it; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->type == TabRestoreService::TAB) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddTab(static_cast<const TabRestoreService::Tab*>(entry), 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &temp_list, kRecentlyClosedCount); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (entry->type == TabRestoreService::WINDOW) { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddWindow(static_cast<const TabRestoreService::Window*>(entry), 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &temp_list, kRecentlyClosedCount); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Lock recently_closed_pages and copy temp_list into it. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recently_closed_pages_ = temp_list; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send a query that retrieves the first favicon. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartLoadingFavicon(); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JumpList::AddTab(const TabRestoreService::Tab* tab, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList* list, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_items) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code adds the URL and the title strings of the given tab to the 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // specified list. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list->size() >= max_items) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<ShellLinkItem> link = CreateShellLink(); 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const sessions::SerializedNavigationEntry& current_navigation = 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab->navigations.at(tab->current_navigation_index); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url = current_navigation.virtual_url().spec(); 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) link->GetCommandLine()->AppendArgNative(base::UTF8ToWide(url)); 362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) link->set_title(current_navigation.title()); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list->push_back(link); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls_.push_back(make_pair(url, link)); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::AddWindow(const TabRestoreService::Window* window, 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList* list, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_items) { 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code enumerates al the tabs in the given window object and add their 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URLs and titles to the list. 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!window->tabs.empty()); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < window->tabs.size(); ++i) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddTab(&window->tabs[i], list, max_items)) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::StartLoadingFavicon() { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icon_urls_.empty()) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No more favicons are needed by the application JumpList. Schedule a 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RunUpdate call. 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&JumpList::RunUpdate, this)); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ask FaviconService if it has a favicon of a URL. 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When FaviconService has one, it will call OnFaviconDataAvailable(). 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url = GURL(icon_urls_.front().first); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconService* favicon_service = 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); 399f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) task_id_ = favicon_service->GetFaviconImageForPageURL( 400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FaviconService::FaviconForPageURLParams( 4010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url, favicon_base::FAVICON, gfx::kFaviconSize), 4020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Bind(&JumpList::OnFaviconDataAvailable, base::Unretained(this)), 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::OnFaviconDataAvailable( 4070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const favicon_base::FaviconImageResult& image_result) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is currently a favicon request in progress, it is now outdated, 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as we have received another, so nullify the handle from the old request. 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) task_id_ = base::CancelableTaskTracker::kBadTaskId; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lock the list to set icon data and pop the url 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Attach the received data to the ShellLinkItem object. 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This data will be decoded by the RunUpdate method. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image_result.image.IsEmpty()) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon_urls_.empty() && icon_urls_.front().second) 418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) icon_urls_.front().second->set_icon_data(image_result.image.AsBitmap()); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon_urls_.empty()) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls_.pop_front(); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check whether we need to load more favicons. 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartLoadingFavicon(); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::RunUpdate() { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList local_most_visited_pages; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList local_recently_closed_pages; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we are not out of date: if icon_urls_ is not empty, then 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // another notification has been received since we processed this one 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon_urls_.empty()) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make local copies of lists so we can release the lock. 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_most_visited_pages = most_visited_pages_; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_recently_closed_pages = recently_closed_pages_; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the directory which contains old icon files, rename the current 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon directory, and create a new directory which contains new JumpList 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon files. 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath icon_dir_old(icon_dir_.value() + L"Old"); 4487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (base::PathExists(icon_dir_old)) 4497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(icon_dir_old, true); 450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Move(icon_dir_, icon_dir_old); 451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::CreateDirectory(icon_dir_); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create temporary icon files for shortcuts in the "Most Visited" category. 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateIconFiles(local_most_visited_pages); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create temporary icon files for shortcuts in the "Recently Closed" 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // category. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateIconFiles(local_recently_closed_pages); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We finished collecting all resources needed for updating an appliation 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JumpList. So, create a new JumpList and replace the current JumpList 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with it. 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateJumpList(app_id_.c_str(), local_most_visited_pages, 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_recently_closed_pages); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::CreateIconFiles(const ShellLinkItemList& item_list) { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ShellLinkItemList::const_iterator item = item_list.begin(); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item != item_list.end(); ++item) { 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath icon_path; 471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (CreateIconFile((*item)->icon_data(), icon_dir_, &icon_path)) 472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (*item)->set_icon(icon_path.value(), 0); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475