| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/jumplist_win.h" | 5 #include "chrome/browser/jumplist_win.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| 11 #include "base/metrics/field_trial.h" | |
| 12 #include "base/path_service.h" | 11 #include "base/path_service.h" |
| 13 #include "base/prefs/pref_change_registrar.h" | 12 #include "base/prefs/pref_change_registrar.h" |
| 14 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
| 17 #include "chrome/browser/browser_process.h" | |
| 18 #include "chrome/browser/chrome_notification_types.h" | 16 #include "chrome/browser/chrome_notification_types.h" |
| 19 #include "chrome/browser/favicon/favicon_service.h" | 17 #include "chrome/browser/favicon/favicon_service.h" |
| 20 #include "chrome/browser/favicon/favicon_service_factory.h" | 18 #include "chrome/browser/favicon/favicon_service_factory.h" |
| 21 #include "chrome/browser/history/history_service.h" | 19 #include "chrome/browser/history/history_service.h" |
| 22 #include "chrome/browser/history/top_sites_factory.h" | 20 #include "chrome/browser/history/top_sites_factory.h" |
| 23 #include "chrome/browser/metrics/jumplist_metrics_win.h" | 21 #include "chrome/browser/metrics/jumplist_metrics_win.h" |
| 24 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
| 25 #include "chrome/browser/profiles/profile_info_cache.h" | |
| 26 #include "chrome/browser/profiles/profile_manager.h" | |
| 27 #include "chrome/browser/sessions/tab_restore_service.h" | 23 #include "chrome/browser/sessions/tab_restore_service.h" |
| 28 #include "chrome/browser/sessions/tab_restore_service_factory.h" | 24 #include "chrome/browser/sessions/tab_restore_service_factory.h" |
| 29 #include "chrome/browser/shell_integration.h" | 25 #include "chrome/browser/shell_integration.h" |
| 30 #include "chrome/common/chrome_constants.h" | 26 #include "chrome/common/chrome_constants.h" |
| 31 #include "chrome/common/chrome_switches.h" | 27 #include "chrome/common/chrome_switches.h" |
| 32 #include "chrome/common/pref_names.h" | 28 #include "chrome/common/pref_names.h" |
| 33 #include "chrome/common/url_constants.h" | 29 #include "chrome/common/url_constants.h" |
| 34 #include "chrome/grit/generated_resources.h" | 30 #include "chrome/grit/generated_resources.h" |
| 35 #include "components/favicon_base/favicon_types.h" | 31 #include "components/favicon_base/favicon_types.h" |
| 36 #include "components/history/core/browser/page_usage_data.h" | 32 #include "components/history/core/browser/page_usage_data.h" |
| 37 #include "components/history/core/browser/top_sites.h" | 33 #include "components/history/core/browser/top_sites.h" |
| 38 #include "components/sessions/session_types.h" | 34 #include "components/sessions/session_types.h" |
| 39 #include "components/signin/core/common/profile_management_switches.h" | |
| 40 #include "content/public/browser/browser_thread.h" | 35 #include "content/public/browser/browser_thread.h" |
| 36 #include "content/public/browser/notification_registrar.h" |
| 41 #include "content/public/browser/notification_source.h" | 37 #include "content/public/browser/notification_source.h" |
| 42 #include "ui/base/l10n/l10n_util.h" | 38 #include "ui/base/l10n/l10n_util.h" |
| 43 #include "ui/gfx/codec/png_codec.h" | 39 #include "ui/gfx/codec/png_codec.h" |
| 44 #include "ui/gfx/favicon_size.h" | 40 #include "ui/gfx/favicon_size.h" |
| 45 #include "ui/gfx/icon_util.h" | 41 #include "ui/gfx/icon_util.h" |
| 46 #include "ui/gfx/image/image_family.h" | 42 #include "ui/gfx/image/image_family.h" |
| 47 #include "url/gurl.h" | 43 #include "url/gurl.h" |
| 48 | 44 |
| 49 using content::BrowserThread; | 45 using content::BrowserThread; |
| 50 | 46 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 items.push_back(incognito); | 124 items.push_back(incognito); |
| 129 } | 125 } |
| 130 | 126 |
| 131 return jumplist_updater->AddTasks(items); | 127 return jumplist_updater->AddTasks(items); |
| 132 } | 128 } |
| 133 | 129 |
| 134 // Updates the application JumpList. | 130 // Updates the application JumpList. |
| 135 bool UpdateJumpList(const wchar_t* app_id, | 131 bool UpdateJumpList(const wchar_t* app_id, |
| 136 const ShellLinkItemList& most_visited_pages, | 132 const ShellLinkItemList& most_visited_pages, |
| 137 const ShellLinkItemList& recently_closed_pages, | 133 const ShellLinkItemList& recently_closed_pages, |
| 138 const ShellLinkItemList& profile_switcher, | 134 IncognitoModePrefs::Availability incognito_availability) { |
| 139 IncognitoModePrefs::Availability incognito_availability, | |
| 140 bool use_profiles_category) { | |
| 141 // JumpList is implemented only on Windows 7 or later. | 135 // JumpList is implemented only on Windows 7 or later. |
| 142 // So, we should return now when this function is called on earlier versions | 136 // So, we should return now when this function is called on earlier versions |
| 143 // of Windows. | 137 // of Windows. |
| 144 if (!JumpListUpdater::IsEnabled()) | 138 if (!JumpListUpdater::IsEnabled()) |
| 145 return true; | 139 return true; |
| 146 | 140 |
| 147 JumpListUpdater jumplist_updater(app_id); | 141 JumpListUpdater jumplist_updater(app_id); |
| 148 if (!jumplist_updater.BeginUpdate()) | 142 if (!jumplist_updater.BeginUpdate()) |
| 149 return false; | 143 return false; |
| 150 | 144 |
| 151 size_t recently_closed_items; | 145 // We allocate 60% of the given JumpList slots to "most-visited" items |
| 152 size_t profiles_or_most_visited_items; | 146 // and 40% to "recently-closed" items, respectively. |
| 153 | 147 // Nevertheless, if there are not so many items in |recently_closed_pages|, |
| 154 // Depending on the experiment, we are either showing the "Most-Visited" or | 148 // we give the remaining slots to "most-visited" items. |
| 155 // "People" categories. | 149 const int kMostVisited = 60; |
| 156 if (use_profiles_category) { | 150 const int kRecentlyClosed = 40; |
| 157 // Show at most 8 profiles, and fill the rest of the slots with the | 151 const int kTotal = kMostVisited + kRecentlyClosed; |
| 158 // "recently-closed" items. | 152 size_t most_visited_items = |
| 159 const size_t kMaxProfiles = 8; | 153 MulDiv(jumplist_updater.user_max_items(), kMostVisited, kTotal); |
| 160 size_t max_displayed_items = std::min(kMaxProfiles, | 154 size_t recently_closed_items = |
| 161 jumplist_updater.user_max_items()); | 155 jumplist_updater.user_max_items() - most_visited_items; |
| 162 profiles_or_most_visited_items = std::min(max_displayed_items, | 156 if (recently_closed_pages.size() < recently_closed_items) { |
| 163 profile_switcher.size()); | 157 most_visited_items += recently_closed_items - recently_closed_pages.size(); |
| 164 recently_closed_items = | 158 recently_closed_items = recently_closed_pages.size(); |
| 165 jumplist_updater.user_max_items() - profiles_or_most_visited_items; | |
| 166 } else { | |
| 167 // We allocate 60% of the given JumpList slots to "most-visited" items | |
| 168 // and 40% to "recently-closed" items, respectively. | |
| 169 // Nevertheless, if there are not so many items in |recently_closed_pages|, | |
| 170 // we give the remaining slots to "most-visited" items. | |
| 171 const int kMostVisited = 60; | |
| 172 const int kRecentlyClosed = 40; | |
| 173 const int kTotal = kMostVisited + kRecentlyClosed; | |
| 174 profiles_or_most_visited_items = | |
| 175 MulDiv(jumplist_updater.user_max_items(), kMostVisited, kTotal); | |
| 176 recently_closed_items = | |
| 177 jumplist_updater.user_max_items() - profiles_or_most_visited_items; | |
| 178 if (recently_closed_pages.size() < recently_closed_items) { | |
| 179 profiles_or_most_visited_items += | |
| 180 recently_closed_items - recently_closed_pages.size(); | |
| 181 recently_closed_items = recently_closed_pages.size(); | |
| 182 } | |
| 183 } | 159 } |
| 184 | 160 |
| 185 // Update the "Most Visited" category of the JumpList if it exists. | 161 // Update the "Most Visited" category of the JumpList if it exists. |
| 186 // This update request is applied into the JumpList when we commit this | 162 // This update request is applied into the JumpList when we commit this |
| 187 // transaction. | 163 // transaction. |
| 188 if (!use_profiles_category && !jumplist_updater.AddCustomCategory( | 164 if (!jumplist_updater.AddCustomCategory( |
| 189 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), | 165 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), |
| 190 most_visited_pages, profiles_or_most_visited_items)) { | 166 most_visited_pages, most_visited_items)) { |
| 191 return false; | 167 return false; |
| 192 } | 168 } |
| 193 | 169 |
| 194 // Update the "Recently Closed" category of the JumpList. | 170 // Update the "Recently Closed" category of the JumpList. |
| 195 if (!jumplist_updater.AddCustomCategory( | 171 if (!jumplist_updater.AddCustomCategory( |
| 196 l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED), | 172 l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED), |
| 197 recently_closed_pages, recently_closed_items)) { | 173 recently_closed_pages, recently_closed_items)) { |
| 198 return false; | 174 return false; |
| 199 } | 175 } |
| 200 | 176 |
| 201 // Update the "People" category of the JumpList if it exists. Only display it | |
| 202 // if there's more than one profile available. | |
| 203 if (use_profiles_category && profile_switcher.size() > 1 && | |
| 204 !jumplist_updater.AddCustomCategory( | |
| 205 l10n_util::GetStringUTF16(IDS_PROFILES_OPTIONS_GROUP_NAME), | |
| 206 profile_switcher, profiles_or_most_visited_items)) { | |
| 207 return false; | |
| 208 } | |
| 209 | |
| 210 // Update the "Tasks" category of the JumpList. | 177 // Update the "Tasks" category of the JumpList. |
| 211 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) | 178 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) |
| 212 return false; | 179 return false; |
| 213 | 180 |
| 214 // Commit this transaction and send the updated JumpList to Windows. | 181 // Commit this transaction and send the updated JumpList to Windows. |
| 215 if (!jumplist_updater.CommitUpdate()) | 182 if (!jumplist_updater.CommitUpdate()) |
| 216 return false; | 183 return false; |
| 217 | 184 |
| 218 return true; | 185 return true; |
| 219 } | 186 } |
| 220 | 187 |
| 221 // Checks whether the experiment that replaces the Most Visited category | |
| 222 // with a Profiles list exists. | |
| 223 bool HasProfilesJumplistExperiment() { | |
| 224 const std::string group_name = | |
| 225 base::FieldTrialList::FindFullName("WindowsJumplistProfiles"); | |
| 226 return group_name == "UseProfiles"; | |
| 227 } | |
| 228 | |
| 229 } // namespace | 188 } // namespace |
| 230 | 189 |
| 231 JumpList::JumpList(Profile* profile) | 190 JumpList::JumpList(Profile* profile) |
| 232 : profile_(profile), | 191 : profile_(profile), |
| 233 task_id_(base::CancelableTaskTracker::kBadTaskId), | 192 task_id_(base::CancelableTaskTracker::kBadTaskId), |
| 234 weak_ptr_factory_(this), | 193 weak_ptr_factory_(this) { |
| 235 use_profiles_category_(false) { | |
| 236 DCHECK(Enabled()); | 194 DCHECK(Enabled()); |
| 237 // To update JumpList when a tab is added or removed, we add this object to | 195 // To update JumpList when a tab is added or removed, we add this object to |
| 238 // the observer list of the TabRestoreService class. | 196 // the observer list of the TabRestoreService class. |
| 239 // When we add this object to the observer list, we save the pointer to this | 197 // When we add this object to the observer list, we save the pointer to this |
| 240 // TabRestoreService object. This pointer is used when we remove this object | 198 // TabRestoreService object. This pointer is used when we remove this object |
| 241 // from the observer list. | 199 // from the observer list. |
| 242 TabRestoreService* tab_restore_service = | 200 TabRestoreService* tab_restore_service = |
| 243 TabRestoreServiceFactory::GetForProfile(profile_); | 201 TabRestoreServiceFactory::GetForProfile(profile_); |
| 244 if (!tab_restore_service) | 202 if (!tab_restore_service) |
| 245 return; | 203 return; |
| 246 | 204 |
| 247 app_id_ = ShellIntegration::GetChromiumModelIdForProfile(profile_->GetPath()); | 205 app_id_ = ShellIntegration::GetChromiumModelIdForProfile(profile_->GetPath()); |
| 248 icon_dir_ = profile_->GetPath().Append(chrome::kJumpListIconDirname); | 206 icon_dir_ = profile_->GetPath().Append(chrome::kJumpListIconDirname); |
| 249 use_profiles_category_ = HasProfilesJumplistExperiment(); | |
| 250 | 207 |
| 251 scoped_refptr<history::TopSites> top_sites = | 208 scoped_refptr<history::TopSites> top_sites = |
| 252 TopSitesFactory::GetForProfile(profile_); | 209 TopSitesFactory::GetForProfile(profile_); |
| 253 if (top_sites) { | 210 if (top_sites) { |
| 254 // TopSites updates itself after a delay. This is especially noticable when | 211 // TopSites updates itself after a delay. This is especially noticable when |
| 255 // your profile is empty. Ask TopSites to update itself when jumplist is | 212 // your profile is empty. Ask TopSites to update itself when jumplist is |
| 256 // initialized. | 213 // initialized. |
| 257 top_sites->SyncWithHistory(); | 214 top_sites->SyncWithHistory(); |
| 258 registrar_.reset(new content::NotificationRegistrar); | 215 registrar_.reset(new content::NotificationRegistrar); |
| 259 // Register as TopSitesObserver so that we can update ourselves when the | 216 // Register as TopSitesObserver so that we can update ourselves when the |
| 260 // TopSites changes. | 217 // TopSites changes. |
| 261 top_sites->AddObserver(this); | 218 top_sites->AddObserver(this); |
| 262 // Register for notification when profile is destroyed to ensure that all | 219 // Register for notification when profile is destroyed to ensure that all |
| 263 // observers are detatched at that time. | 220 // observers are detatched at that time. |
| 264 registrar_->Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 221 registrar_->Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 265 content::Source<Profile>(profile_)); | 222 content::Source<Profile>(profile_)); |
| 266 } | 223 } |
| 267 tab_restore_service->AddObserver(this); | 224 tab_restore_service->AddObserver(this); |
| 268 pref_change_registrar_.reset(new PrefChangeRegistrar); | 225 pref_change_registrar_.reset(new PrefChangeRegistrar); |
| 269 pref_change_registrar_->Init(profile_->GetPrefs()); | 226 pref_change_registrar_->Init(profile_->GetPrefs()); |
| 270 pref_change_registrar_->Add( | 227 pref_change_registrar_->Add( |
| 271 prefs::kIncognitoModeAvailability, | 228 prefs::kIncognitoModeAvailability, |
| 272 base::Bind(&JumpList::OnIncognitoAvailabilityChanged, this)); | 229 base::Bind(&JumpList::OnIncognitoAvailabilityChanged, this)); |
| 273 | |
| 274 ProfileManager* profile_manager = g_browser_process->profile_manager(); | |
| 275 avatar_menu_.reset(new AvatarMenu( | |
| 276 &profile_manager->GetProfileInfoCache(), this, NULL)); | |
| 277 if (use_profiles_category_) { | |
| 278 avatar_menu_->RebuildMenu(); | |
| 279 UpdateProfileSwitcher(); | |
| 280 } | |
| 281 } | 230 } |
| 282 | 231 |
| 283 JumpList::~JumpList() { | 232 JumpList::~JumpList() { |
| 284 Terminate(); | 233 Terminate(); |
| 285 } | 234 } |
| 286 | 235 |
| 287 // static | 236 // static |
| 288 bool JumpList::Enabled() { | 237 bool JumpList::Enabled() { |
| 289 return JumpListUpdater::IsEnabled(); | 238 return JumpListUpdater::IsEnabled(); |
| 290 } | 239 } |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 recently_closed_pages_ = temp_list; | 335 recently_closed_pages_ = temp_list; |
| 387 } | 336 } |
| 388 | 337 |
| 389 // Send a query that retrieves the first favicon. | 338 // Send a query that retrieves the first favicon. |
| 390 StartLoadingFavicon(); | 339 StartLoadingFavicon(); |
| 391 } | 340 } |
| 392 | 341 |
| 393 void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) { | 342 void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) { |
| 394 } | 343 } |
| 395 | 344 |
| 396 void JumpList::OnAvatarMenuChanged(AvatarMenu* avatar_menu) { | |
| 397 if (!use_profiles_category_) | |
| 398 return; | |
| 399 | |
| 400 UpdateProfileSwitcher(); | |
| 401 PostRunUpdate(); | |
| 402 } | |
| 403 | |
| 404 bool JumpList::AddTab(const TabRestoreService::Tab* tab, | 345 bool JumpList::AddTab(const TabRestoreService::Tab* tab, |
| 405 ShellLinkItemList* list, | 346 ShellLinkItemList* list, |
| 406 size_t max_items) { | 347 size_t max_items) { |
| 407 // This code adds the URL and the title strings of the given tab to the | 348 // This code adds the URL and the title strings of the given tab to the |
| 408 // specified list. | 349 // specified list. |
| 409 if (list->size() >= max_items) | 350 if (list->size() >= max_items) |
| 410 return false; | 351 return false; |
| 411 | 352 |
| 412 scoped_refptr<ShellLinkItem> link = CreateShellLink(); | 353 scoped_refptr<ShellLinkItem> link = CreateShellLink(); |
| 413 const sessions::SerializedNavigationEntry& current_navigation = | 354 const sessions::SerializedNavigationEntry& current_navigation = |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 BrowserThread::FILE, FROM_HERE, | 448 BrowserThread::FILE, FROM_HERE, |
| 508 base::Bind(&JumpList::RunUpdateOnFileThread, | 449 base::Bind(&JumpList::RunUpdateOnFileThread, |
| 509 this, | 450 this, |
| 510 incognito_availability)); | 451 incognito_availability)); |
| 511 } | 452 } |
| 512 | 453 |
| 513 void JumpList::RunUpdateOnFileThread( | 454 void JumpList::RunUpdateOnFileThread( |
| 514 IncognitoModePrefs::Availability incognito_availability) { | 455 IncognitoModePrefs::Availability incognito_availability) { |
| 515 ShellLinkItemList local_most_visited_pages; | 456 ShellLinkItemList local_most_visited_pages; |
| 516 ShellLinkItemList local_recently_closed_pages; | 457 ShellLinkItemList local_recently_closed_pages; |
| 517 ShellLinkItemList local_profile_switcher; | |
| 518 | 458 |
| 519 { | 459 { |
| 520 base::AutoLock auto_lock(list_lock_); | 460 base::AutoLock auto_lock(list_lock_); |
| 521 // Make sure we are not out of date: if icon_urls_ is not empty, then | 461 // Make sure we are not out of date: if icon_urls_ is not empty, then |
| 522 // another notification has been received since we processed this one | 462 // another notification has been received since we processed this one |
| 523 if (!icon_urls_.empty()) | 463 if (!icon_urls_.empty()) |
| 524 return; | 464 return; |
| 525 | 465 |
| 526 // Make local copies of lists so we can release the lock. | 466 // Make local copies of lists so we can release the lock. |
| 527 local_most_visited_pages = most_visited_pages_; | 467 local_most_visited_pages = most_visited_pages_; |
| 528 local_recently_closed_pages = recently_closed_pages_; | 468 local_recently_closed_pages = recently_closed_pages_; |
| 529 local_profile_switcher = profile_switcher_; | |
| 530 } | 469 } |
| 531 | 470 |
| 532 // Delete the directory which contains old icon files, rename the current | 471 // Delete the directory which contains old icon files, rename the current |
| 533 // icon directory, and create a new directory which contains new JumpList | 472 // icon directory, and create a new directory which contains new JumpList |
| 534 // icon files. | 473 // icon files. |
| 535 base::FilePath icon_dir_old(icon_dir_.value() + L"Old"); | 474 base::FilePath icon_dir_old(icon_dir_.value() + L"Old"); |
| 536 if (base::PathExists(icon_dir_old)) | 475 if (base::PathExists(icon_dir_old)) |
| 537 base::DeleteFile(icon_dir_old, true); | 476 base::DeleteFile(icon_dir_old, true); |
| 538 base::Move(icon_dir_, icon_dir_old); | 477 base::Move(icon_dir_, icon_dir_old); |
| 539 base::CreateDirectory(icon_dir_); | 478 base::CreateDirectory(icon_dir_); |
| 540 | 479 |
| 541 // Create temporary icon files for shortcuts in the "Most Visited" category. | 480 // Create temporary icon files for shortcuts in the "Most Visited" category. |
| 542 CreateIconFiles(local_most_visited_pages); | 481 CreateIconFiles(local_most_visited_pages); |
| 543 | 482 |
| 544 // Create temporary icon files for shortcuts in the "Recently Closed" | 483 // Create temporary icon files for shortcuts in the "Recently Closed" |
| 545 // category. | 484 // category. |
| 546 CreateIconFiles(local_recently_closed_pages); | 485 CreateIconFiles(local_recently_closed_pages); |
| 547 | 486 |
| 548 // Create temporary icon files for the profile avatars in the "People" | |
| 549 // category. | |
| 550 if (use_profiles_category_) | |
| 551 CreateIconFiles(local_profile_switcher); | |
| 552 | |
| 553 // We finished collecting all resources needed for updating an application | 487 // We finished collecting all resources needed for updating an application |
| 554 // JumpList. So, create a new JumpList and replace the current JumpList | 488 // JumpList. So, create a new JumpList and replace the current JumpList |
| 555 // with it. | 489 // with it. |
| 556 UpdateJumpList(app_id_.c_str(), | 490 UpdateJumpList(app_id_.c_str(), |
| 557 local_most_visited_pages, | 491 local_most_visited_pages, |
| 558 local_recently_closed_pages, | 492 local_recently_closed_pages, |
| 559 local_profile_switcher, | 493 incognito_availability); |
| 560 incognito_availability, | |
| 561 use_profiles_category_); | |
| 562 } | 494 } |
| 563 | 495 |
| 564 void JumpList::CreateIconFiles(const ShellLinkItemList& item_list) { | 496 void JumpList::CreateIconFiles(const ShellLinkItemList& item_list) { |
| 565 for (ShellLinkItemList::const_iterator item = item_list.begin(); | 497 for (ShellLinkItemList::const_iterator item = item_list.begin(); |
| 566 item != item_list.end(); ++item) { | 498 item != item_list.end(); ++item) { |
| 567 base::FilePath icon_path; | 499 base::FilePath icon_path; |
| 568 if (CreateIconFile((*item)->icon_data(), icon_dir_, &icon_path)) | 500 if (CreateIconFile((*item)->icon_data(), icon_dir_, &icon_path)) |
| 569 (*item)->set_icon(icon_path.value(), 0); | 501 (*item)->set_icon(icon_path.value(), 0); |
| 570 } | 502 } |
| 571 } | 503 } |
| 572 | 504 |
| 573 void JumpList::UpdateProfileSwitcher() { | |
| 574 DCHECK(use_profiles_category_); | |
| 575 ShellLinkItemList new_profile_switcher; | |
| 576 | |
| 577 // Don't display a menu in the single profile case. | |
| 578 if (avatar_menu_->GetNumberOfItems() > 1) { | |
| 579 for (size_t i = 0; i < avatar_menu_->GetNumberOfItems(); ++i) { | |
| 580 scoped_refptr<ShellLinkItem> link = CreateShellLink(); | |
| 581 const AvatarMenu::Item& item = avatar_menu_->GetItemAt(i); | |
| 582 | |
| 583 link->set_title(item.name); | |
| 584 link->GetCommandLine()->AppendSwitchPath( | |
| 585 switches::kProfileDirectory, item.profile_path.BaseName()); | |
| 586 link->GetCommandLine()->AppendSwitch( | |
| 587 switches::kActivateExistingProfileBrowser); | |
| 588 link->GetCommandLine()->AppendSwitchASCII( | |
| 589 switches::kWinJumplistAction, jumplist::kProfilesCategory); | |
| 590 | |
| 591 gfx::Image avatar; | |
| 592 bool is_rectangle; | |
| 593 avatar_menu_->GetImageForMenuButton( | |
| 594 item.profile_path, &avatar, &is_rectangle); | |
| 595 link->set_icon_data(avatar.AsBitmap()); | |
| 596 new_profile_switcher.push_back(link); | |
| 597 } | |
| 598 } | |
| 599 | |
| 600 { | |
| 601 base::AutoLock auto_lock(list_lock_); | |
| 602 new_profile_switcher.swap(profile_switcher_); | |
| 603 } | |
| 604 } | |
| 605 | |
| 606 void JumpList::TopSitesLoaded(history::TopSites* top_sites) { | 505 void JumpList::TopSitesLoaded(history::TopSites* top_sites) { |
| 607 } | 506 } |
| 608 | 507 |
| 609 void JumpList::TopSitesChanged(history::TopSites* top_sites) { | 508 void JumpList::TopSitesChanged(history::TopSites* top_sites) { |
| 610 top_sites->GetMostVisitedURLs( | 509 top_sites->GetMostVisitedURLs( |
| 611 base::Bind(&JumpList::OnMostVisitedURLsAvailable, | 510 base::Bind(&JumpList::OnMostVisitedURLsAvailable, |
| 612 weak_ptr_factory_.GetWeakPtr()), | 511 weak_ptr_factory_.GetWeakPtr()), |
| 613 false); | 512 false); |
| 614 } | 513 } |
| OLD | NEW |