jumplist_win.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/prefs/pref_change_registrar.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.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" 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/common/pref_names.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h" 310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/favicon_base/favicon_types.h" 326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/history/core/browser/page_usage_data.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/favicon_size.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/icon_util.h" 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image_family.h" 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Append the common switches to each shell link. 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AppendCommonSwitches(ShellLinkItem* shell_link) { 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const char* kSwitchNames[] = { switches::kUserDataDir }; 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) shell_link->GetCommandLine()->CopySwitchesFrom(command_line, 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kSwitchNames, 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) arraysize(kSwitchNames)); 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Create a ShellLinkItem preloaded with common switches. 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_refptr<ShellLinkItem> CreateShellLink() { 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<ShellLinkItem> link(new ShellLinkItem); 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) AppendCommonSwitches(link.get()); 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return link; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a temporary icon file to be shown in JumpList. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateIconFile(const SkBitmap& bitmap, 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& icon_dir, 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath* icon_path) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieve the path to a temporary file. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't have to care about the extension of this temporary file because 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JumpList does not care about it. 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path; 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateTemporaryFileInDir(icon_dir, &path)) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an icon file from the favicon attached to the given |page|, and 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save it as the temporary file. 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::ImageFamily image_family; 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) image_family.Add(gfx::Image::CreateFrom1xBitmap(bitmap)); 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!IconUtil::CreateIconFileFromImageFamily(image_family, path)) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add this icon file to the list and return its absolute path. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The IShellLink::SetIcon() function needs the absolute path to an icon. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *icon_path = path; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Updates the "Tasks" category of the JumpList. 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool UpdateTaskCategory( 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci JumpListUpdater* jumplist_updater, 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IncognitoModePrefs::Availability incognito_availability) { 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::FilePath chrome_path; 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!PathService::Get(base::FILE_EXE, &chrome_path)) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ShellLinkItemList items; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an IShellLink object which launches Chrome, and add it to the 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // collection. We use our application icon as the icon for this item. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We remove '&' characters from this string so we can share it with our 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // system menu. 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (incognito_availability != IncognitoModePrefs::FORCED) { 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<ShellLinkItem> chrome = CreateShellLink(); 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::string16 chrome_title = l10n_util::GetStringUTF16(IDS_NEW_WINDOW); 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReplaceSubstringsAfterOffset(&chrome_title, 0, L"&", L""); 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome->set_title(chrome_title); 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chrome->set_icon(chrome_path.value(), 0); 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci items.push_back(chrome); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an IShellLink object which launches Chrome in incognito mode, and 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // add it to the collection. We use our application icon as the icon for 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this item. 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (incognito_availability != IncognitoModePrefs::DISABLED) { 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<ShellLinkItem> incognito = CreateShellLink(); 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci incognito->GetCommandLine()->AppendSwitch(switches::kIncognito); 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::string16 incognito_title = 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci l10n_util::GetStringUTF16(IDS_NEW_INCOGNITO_WINDOW); 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ReplaceSubstringsAfterOffset(&incognito_title, 0, L"&", L""); 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci incognito->set_title(incognito_title); 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci incognito->set_icon(chrome_path.value(), 0); 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci items.push_back(incognito); 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return jumplist_updater->AddTasks(items); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Updates the application JumpList. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UpdateJumpList(const wchar_t* app_id, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ShellLinkItemList& most_visited_pages, 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ShellLinkItemList& recently_closed_pages, 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IncognitoModePrefs::Availability incognito_availability) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JumpList is implemented only on Windows 7 or later. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So, we should return now when this function is called on earlier versions 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of Windows. 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!JumpListUpdater::IsEnabled()) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) JumpListUpdater jumplist_updater(app_id); 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!jumplist_updater.BeginUpdate()) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We allocate 60% of the given JumpList slots to "most-visited" items 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and 40% to "recently-closed" items, respectively. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Nevertheless, if there are not so many items in |recently_closed_pages|, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we give the remaining slots to "most-visited" items. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMostVisited = 60; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kRecentlyClosed = 40; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kTotal = kMostVisited + kRecentlyClosed; 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t most_visited_items = 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MulDiv(jumplist_updater.user_max_items(), kMostVisited, kTotal); 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t recently_closed_items = 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) jumplist_updater.user_max_items() - most_visited_items; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (recently_closed_pages.size() < recently_closed_items) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) most_visited_items += recently_closed_items - recently_closed_pages.size(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recently_closed_items = recently_closed_pages.size(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the "Most Visited" category of the JumpList. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This update request is applied into the JumpList when we commit this 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transaction. 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!jumplist_updater.AddCustomCategory( 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::UTF16ToWide( 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED)), 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) most_visited_pages, most_visited_items)) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the "Recently Closed" category of the JumpList. 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!jumplist_updater.AddCustomCategory( 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::UTF16ToWide( 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED)), 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) recently_closed_pages, recently_closed_items)) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the "Tasks" category of the JumpList. 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Commit this transaction and send the updated JumpList to Windows. 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!jumplist_updater.CommitUpdate()) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciJumpList::JumpList(Profile* profile) 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : profile_(profile), 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_id_(base::CancelableTaskTracker::kBadTaskId), 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_(this) { 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(Enabled()); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To update JumpList when a tab is added or removed, we add this object to 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the observer list of the TabRestoreService class. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we add this object to the observer list, we save the pointer to this 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TabRestoreService object. This pointer is used when we remove this object 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from the observer list. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreService* tab_restore_service = 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TabRestoreServiceFactory::GetForProfile(profile_); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tab_restore_service) 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci app_id_ = ShellIntegration::GetChromiumModelIdForProfile(profile_->GetPath()); 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci icon_dir_ = profile_->GetPath().Append(chrome::kJumpListIconDirname); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::TopSites* top_sites = profile_->GetTopSites(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top_sites) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TopSites updates itself after a delay. This is especially noticable when 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // your profile is empty. Ask TopSites to update itself when jumplist is 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // initialized. 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_sites->SyncWithHistory(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.reset(new content::NotificationRegistrar); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register for notification when TopSites changes so that we can update 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ourself. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_->Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<history::TopSites>(top_sites)); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register for notification when profile is destroyed to ensure that all 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // observers are detatched at that time. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_->Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>(profile_)); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_restore_service->AddObserver(this); 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pref_change_registrar_.reset(new PrefChangeRegistrar); 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pref_change_registrar_->Init(profile_->GetPrefs()); 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pref_change_registrar_->Add( 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci prefs::kIncognitoModeAvailability, 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&JumpList::OnIncognitoAvailabilityChanged, this)); 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciJumpList::~JumpList() { 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Terminate(); 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool JumpList::Enabled() { 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return JumpListUpdater::IsEnabled(); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::Observe(int type, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_TOP_SITES_CHANGED: { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Most visited urls changed, query again. 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::TopSites* top_sites = profile_->GetTopSites(); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top_sites) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_sites->GetMostVisitedURLs( 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&JumpList::OnMostVisitedURLsAvailable, 248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), false); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_PROFILE_DESTROYED: { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Profile was destroyed, do clean-up. 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Terminate(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Unexpected notification type."; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::CancelPendingUpdate() { 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (task_id_ != base::CancelableTaskTracker::kBadTaskId) { 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cancelable_task_tracker_.TryCancel(task_id_); 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) task_id_ = base::CancelableTaskTracker::kBadTaskId; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::Terminate() { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingUpdate(); 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (profile_) { 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TabRestoreService* tab_restore_service = 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TabRestoreServiceFactory::GetForProfile(profile_); 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (tab_restore_service) 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tab_restore_service->RemoveObserver(this); 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci registrar_.reset(); 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pref_change_registrar_.reset(); 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profile_ = NULL; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::OnMostVisitedURLsAvailable( 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::MostVisitedURLList& data) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have a pending favicon request, cancel it here (it is out of date). 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingUpdate(); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) most_visited_pages_.clear(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < data.size(); i++) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const history::MostVisitedURL& url = data[i]; 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<ShellLinkItem> link = CreateShellLink(); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url_string = url.url.spec(); 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::wstring url_string_wide = base::UTF8ToWide(url_string); 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) link->GetCommandLine()->AppendArgNative(url_string_wide); 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) link->set_title(!url.title.empty()? url.title : url_string_wide); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) most_visited_pages_.push_back(link); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls_.push_back(make_pair(url_string, link)); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send a query that retrieves the first favicon. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartLoadingFavicon(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::TabRestoreServiceChanged(TabRestoreService* service) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if we have a pending handle request, cancel it here (it is out of date). 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelPendingUpdate(); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // local list to pass to methods 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList temp_list; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a list of ShellLinkItems from the "Recently Closed" pages. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As noted above, we create a ShellLinkItem objects with the following 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parameters. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * arguments 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last URL of the tab object. 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * title 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The title of the last URL. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * icon 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An empty string. This value is to be updated in OnFaviconDataAvailable(). 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code is copied from 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RecentlyClosedTabsHandler::TabRestoreServiceChanged() to emulate it. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kRecentlyClosedCount = 4; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreService* tab_restore_service = 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabRestoreServiceFactory::GetForProfile(profile_); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TabRestoreService::Entries& entries = tab_restore_service->entries(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (TabRestoreService::Entries::const_iterator it = entries.begin(); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != entries.end(); ++it) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TabRestoreService::Entry* entry = *it; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->type == TabRestoreService::TAB) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddTab(static_cast<const TabRestoreService::Tab*>(entry), 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &temp_list, kRecentlyClosedCount); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (entry->type == TabRestoreService::WINDOW) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddWindow(static_cast<const TabRestoreService::Window*>(entry), 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &temp_list, kRecentlyClosedCount); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Lock recently_closed_pages and copy temp_list into it. 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recently_closed_pages_ = temp_list; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send a query that retrieves the first favicon. 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartLoadingFavicon(); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JumpList::AddTab(const TabRestoreService::Tab* tab, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList* list, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_items) { 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code adds the URL and the title strings of the given tab to the 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // specified list. 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (list->size() >= max_items) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<ShellLinkItem> link = CreateShellLink(); 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const sessions::SerializedNavigationEntry& current_navigation = 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab->navigations.at(tab->current_navigation_index); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url = current_navigation.virtual_url().spec(); 365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) link->GetCommandLine()->AppendArgNative(base::UTF8ToWide(url)); 366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) link->set_title(current_navigation.title()); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) list->push_back(link); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls_.push_back(make_pair(url, link)); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::AddWindow(const TabRestoreService::Window* window, 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList* list, 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_items) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This code enumerates al the tabs in the given window object and add their 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URLs and titles to the list. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!window->tabs.empty()); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < window->tabs.size(); ++i) { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!AddTab(&window->tabs[i], list, max_items)) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::StartLoadingFavicon() { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url; 3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool waiting_for_icons = true; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci waiting_for_icons = !icon_urls_.empty(); 3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (waiting_for_icons) { 3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Ask FaviconService if it has a favicon of a URL. 3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // When FaviconService has one, it will call OnFaviconDataAvailable(). 3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url = GURL(icon_urls_.front().first); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!waiting_for_icons) { 3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // No more favicons are needed by the application JumpList. Schedule a 4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // RunUpdate call. 4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PostRunUpdate(); 4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconService* favicon_service = 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); 407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) task_id_ = favicon_service->GetFaviconImageForPageURL( 408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch url, 4090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::Bind(&JumpList::OnFaviconDataAvailable, base::Unretained(this)), 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelable_task_tracker_); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::OnFaviconDataAvailable( 4140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const favicon_base::FaviconImageResult& image_result) { 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is currently a favicon request in progress, it is now outdated, 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as we have received another, so nullify the handle from the old request. 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) task_id_ = base::CancelableTaskTracker::kBadTaskId; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lock the list to set icon data and pop the url 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Attach the received data to the ShellLinkItem object. 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This data will be decoded by the RunUpdate method. 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image_result.image.IsEmpty()) { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon_urls_.empty() && icon_urls_.front().second) 425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) icon_urls_.front().second->set_icon_data(image_result.image.AsBitmap()); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon_urls_.empty()) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_urls_.pop_front(); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check whether we need to load more favicons. 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartLoadingFavicon(); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid JumpList::OnIncognitoAvailabilityChanged() { 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool waiting_for_icons = true; 4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::AutoLock auto_lock(list_lock_); 4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci waiting_for_icons = !icon_urls_.empty(); 4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!waiting_for_icons) 4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PostRunUpdate(); 4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If |icon_urls_| isn't empty then OnFaviconDataAvailable will eventually 4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // call PostRunUpdate(). 4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid JumpList::PostRunUpdate() { 4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Check if incognito windows (or normal windows) are disabled by policy. 4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IncognitoModePrefs::Availability incognito_availability = 4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profile_ ? IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) 4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : IncognitoModePrefs::ENABLED; 4521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserThread::PostTask( 4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserThread::FILE, FROM_HERE, 4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&JumpList::RunUpdate, this, incognito_availability)); 4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid JumpList::RunUpdate( 4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IncognitoModePrefs::Availability incognito_availability) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList local_most_visited_pages; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellLinkItemList local_recently_closed_pages; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(list_lock_); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we are not out of date: if icon_urls_ is not empty, then 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // another notification has been received since we processed this one 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon_urls_.empty()) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make local copies of lists so we can release the lock. 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_most_visited_pages = most_visited_pages_; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_recently_closed_pages = recently_closed_pages_; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the directory which contains old icon files, rename the current 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon directory, and create a new directory which contains new JumpList 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon files. 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath icon_dir_old(icon_dir_.value() + L"Old"); 4797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (base::PathExists(icon_dir_old)) 4807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(icon_dir_old, true); 481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Move(icon_dir_, icon_dir_old); 482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::CreateDirectory(icon_dir_); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create temporary icon files for shortcuts in the "Most Visited" category. 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateIconFiles(local_most_visited_pages); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create temporary icon files for shortcuts in the "Recently Closed" 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // category. 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateIconFiles(local_recently_closed_pages); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We finished collecting all resources needed for updating an application 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JumpList. So, create a new JumpList and replace the current JumpList 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with it. 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateJumpList(app_id_.c_str(), local_most_visited_pages, 4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci local_recently_closed_pages, incognito_availability); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JumpList::CreateIconFiles(const ShellLinkItemList& item_list) { 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ShellLinkItemList::const_iterator item = item_list.begin(); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item != item_list.end(); ++item) { 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath icon_path; 502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (CreateIconFile((*item)->icon_data(), icon_dir_, &icon_path)) 503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (*item)->set_icon(icon_path.value(), 0); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 506