Chromium Code Reviews| 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/win/jumplist.h" | 5 #include "chrome/browser/win/jumplist.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 base::DeleteFile(path, false); | 120 base::DeleteFile(path, false); |
| 121 return false; | 121 return false; |
| 122 } | 122 } |
| 123 | 123 |
| 124 // Add this icon file to the list and return its absolute path. | 124 // Add this icon file to the list and return its absolute path. |
| 125 // The IShellLink::SetIcon() function needs the absolute path to an icon. | 125 // The IShellLink::SetIcon() function needs the absolute path to an icon. |
| 126 *icon_path = path; | 126 *icon_path = path; |
| 127 return true; | 127 return true; |
| 128 } | 128 } |
| 129 | 129 |
| 130 // Creates icon files for the asynchrounously loaded icons. | |
| 131 void CreateIconFiles(const base::FilePath& icon_dir, | |
| 132 const ShellLinkItemList& item_list, | |
| 133 size_t max_items) { | |
| 134 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | |
| 135 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); | |
| 136 | |
| 137 for (ShellLinkItemList::const_iterator item = item_list.begin(); | |
| 138 item != item_list.end() && max_items > 0; ++item, --max_items) { | |
| 139 base::FilePath icon_path; | |
| 140 if (CreateIconFile((*item)->icon_image(), icon_dir, &icon_path)) | |
| 141 (*item)->set_icon(icon_path.value(), 0); | |
| 142 } | |
| 143 } | |
| 144 | |
| 145 // Updates icon files in |icon_dir|, which includes deleting old icons and | |
| 146 // creating at most |slot_limit| new icons for |page_list|. | |
| 147 void UpdateIconFiles(const base::FilePath& icon_dir, | |
| 148 const ShellLinkItemList& page_list, | |
| 149 size_t slot_limit) { | |
| 150 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); | |
| 151 | |
| 152 // Create new icons only when the directory exists and is empty. | |
| 153 if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir)) | |
| 154 CreateIconFiles(icon_dir, page_list, slot_limit); | |
| 155 } | |
| 156 | |
| 157 // Updates the "Tasks" category of the JumpList. | 130 // Updates the "Tasks" category of the JumpList. |
| 158 bool UpdateTaskCategory( | 131 bool UpdateTaskCategory( |
| 159 JumpListUpdater* jumplist_updater, | 132 JumpListUpdater* jumplist_updater, |
| 160 IncognitoModePrefs::Availability incognito_availability) { | 133 IncognitoModePrefs::Availability incognito_availability) { |
| 161 base::FilePath chrome_path; | 134 base::FilePath chrome_path; |
| 162 if (!PathService::Get(base::FILE_EXE, &chrome_path)) | 135 if (!PathService::Get(base::FILE_EXE, &chrome_path)) |
| 163 return false; | 136 return false; |
| 164 | 137 |
| 165 int icon_index = install_static::GetIconResourceIndex(); | 138 int icon_index = install_static::GetIconResourceIndex(); |
| 166 | 139 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 // Returns the full path of the JumpListIcons[|suffix|] directory in | 173 // Returns the full path of the JumpListIcons[|suffix|] directory in |
| 201 // |profile_dir|. | 174 // |profile_dir|. |
| 202 base::FilePath GenerateJumplistIconDirName( | 175 base::FilePath GenerateJumplistIconDirName( |
| 203 const base::FilePath& profile_dir, | 176 const base::FilePath& profile_dir, |
| 204 const base::FilePath::StringPieceType& suffix) { | 177 const base::FilePath::StringPieceType& suffix) { |
| 205 base::FilePath::StringType dir_name(chrome::kJumpListIconDirname); | 178 base::FilePath::StringType dir_name(chrome::kJumpListIconDirname); |
| 206 suffix.AppendToString(&dir_name); | 179 suffix.AppendToString(&dir_name); |
| 207 return profile_dir.Append(dir_name); | 180 return profile_dir.Append(dir_name); |
| 208 } | 181 } |
| 209 | 182 |
| 210 // Updates the application JumpList, which consists of 1) delete old icon files; | |
| 211 // 2) create new icon files; 3) notify the OS. | |
| 212 // Note that any timeout error along the way results in the old jumplist being | |
| 213 // left as-is, while any non-timeout error results in the old jumplist being | |
| 214 // left as-is, but without icon files. | |
| 215 bool UpdateJumpList(const wchar_t* app_id, | |
| 216 const base::FilePath& profile_dir, | |
| 217 const ShellLinkItemList& most_visited_pages, | |
| 218 const ShellLinkItemList& recently_closed_pages, | |
| 219 bool most_visited_pages_have_updates, | |
| 220 bool recently_closed_pages_have_updates, | |
| 221 IncognitoModePrefs::Availability incognito_availability) { | |
| 222 if (!JumpListUpdater::IsEnabled()) | |
| 223 return true; | |
| 224 | |
| 225 JumpListUpdater jumplist_updater(app_id); | |
| 226 | |
| 227 base::ElapsedTimer begin_update_timer; | |
| 228 | |
| 229 if (!jumplist_updater.BeginUpdate()) | |
| 230 return false; | |
| 231 | |
| 232 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer | |
| 233 // than the maximum allowed time, as it's very likely the following update | |
| 234 // steps will also take a long time. | |
| 235 if (begin_update_timer.Elapsed() >= kTimeOutForJumplistUpdate) | |
| 236 return false; | |
| 237 | |
| 238 // The default maximum number of items to display in JumpList is 10. | |
| 239 // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx | |
| 240 // The "Most visited" category title always takes 1 of the JumpList slots if | |
| 241 // |most_visited_pages| isn't empty. | |
| 242 // The "Recently closed" category title will also take 1 if | |
| 243 // |recently_closed_pages| isn't empty. | |
| 244 // For the remaining slots, we allocate 5/8 (i.e., 5 slots if both categories | |
| 245 // present) to "most-visited" items and 3/8 (i.e., 3 slots if both categories | |
| 246 // present) to "recently-closed" items, respectively. | |
| 247 // Nevertheless, if there are not so many items in |recently_closed_pages|, | |
| 248 // we give the remaining slots to "most-visited" items. | |
| 249 | |
| 250 const int kMostVisited = 50; | |
| 251 const int kRecentlyClosed = 30; | |
| 252 const int kTotal = kMostVisited + kRecentlyClosed; | |
| 253 | |
| 254 // Adjust the available jumplist slots to account for the category titles. | |
| 255 size_t user_max_items_adjusted = jumplist_updater.user_max_items(); | |
| 256 if (!most_visited_pages.empty()) | |
| 257 --user_max_items_adjusted; | |
| 258 if (!recently_closed_pages.empty()) | |
| 259 --user_max_items_adjusted; | |
| 260 | |
| 261 size_t most_visited_items = | |
| 262 MulDiv(user_max_items_adjusted, kMostVisited, kTotal); | |
| 263 size_t recently_closed_items = user_max_items_adjusted - most_visited_items; | |
| 264 if (recently_closed_pages.size() < recently_closed_items) { | |
| 265 most_visited_items += recently_closed_items - recently_closed_pages.size(); | |
| 266 recently_closed_items = recently_closed_pages.size(); | |
| 267 } | |
| 268 | |
| 269 // Record the desired number of icons to create in this JumpList update. | |
| 270 int icons_to_create = 0; | |
| 271 | |
| 272 // Update the icons for "Most Visisted" category of the JumpList if needed. | |
| 273 if (most_visited_pages_have_updates) { | |
| 274 base::FilePath icon_dir_most_visited = GenerateJumplistIconDirName( | |
| 275 profile_dir, FILE_PATH_LITERAL("MostVisited")); | |
| 276 | |
| 277 UpdateIconFiles(icon_dir_most_visited, most_visited_pages, | |
| 278 most_visited_items); | |
| 279 | |
| 280 icons_to_create += std::min(most_visited_pages.size(), most_visited_items); | |
| 281 } | |
| 282 | |
| 283 // Update the icons for "Recently Closed" category of the JumpList if needed. | |
| 284 if (recently_closed_pages_have_updates) { | |
| 285 base::FilePath icon_dir_recent_closed = GenerateJumplistIconDirName( | |
| 286 profile_dir, FILE_PATH_LITERAL("RecentClosed")); | |
| 287 | |
| 288 UpdateIconFiles(icon_dir_recent_closed, recently_closed_pages, | |
| 289 recently_closed_items); | |
| 290 | |
| 291 icons_to_create += | |
| 292 std::min(recently_closed_pages.size(), recently_closed_items); | |
| 293 } | |
| 294 | |
| 295 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | |
| 296 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_to_create); | |
| 297 | |
| 298 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | |
| 299 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); | |
| 300 | |
| 301 // Update the "Most Visited" category of the JumpList if it exists. | |
| 302 // This update request is applied into the JumpList when we commit this | |
| 303 // transaction. | |
| 304 if (!jumplist_updater.AddCustomCategory( | |
| 305 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), | |
| 306 most_visited_pages, most_visited_items)) { | |
| 307 return false; | |
| 308 } | |
| 309 | |
| 310 // Update the "Recently Closed" category of the JumpList. | |
| 311 if (!jumplist_updater.AddCustomCategory( | |
| 312 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), | |
| 313 recently_closed_pages, recently_closed_items)) { | |
| 314 return false; | |
| 315 } | |
| 316 | |
| 317 // Update the "Tasks" category of the JumpList. | |
| 318 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) | |
| 319 return false; | |
| 320 | |
| 321 // Commit this transaction and send the updated JumpList to Windows. | |
| 322 return jumplist_updater.CommitUpdate(); | |
| 323 } | |
| 324 | |
| 325 // Updates the jumplist, once all the data has been fetched. | |
| 326 void RunUpdateJumpList(IncognitoModePrefs::Availability incognito_availability, | |
| 327 const std::wstring& app_id, | |
| 328 const base::FilePath& profile_dir, | |
| 329 base::RefCountedData<JumpListData>* ref_counted_data) { | |
| 330 JumpListData* data = &ref_counted_data->data; | |
| 331 ShellLinkItemList local_most_visited_pages; | |
| 332 ShellLinkItemList local_recently_closed_pages; | |
| 333 bool most_visited_pages_have_updates; | |
| 334 bool recently_closed_pages_have_updates; | |
| 335 | |
| 336 { | |
| 337 base::AutoLock auto_lock(data->list_lock_); | |
| 338 // Make sure we are not out of date: if icon_urls_ is not empty, then | |
| 339 // another notification has been received since we processed this one | |
| 340 if (!data->icon_urls_.empty()) | |
| 341 return; | |
| 342 | |
| 343 // Make local copies of lists and flags so we can release the lock. | |
| 344 local_most_visited_pages = data->most_visited_pages_; | |
| 345 local_recently_closed_pages = data->recently_closed_pages_; | |
| 346 | |
| 347 most_visited_pages_have_updates = data->most_visited_pages_have_updates_; | |
| 348 recently_closed_pages_have_updates = | |
| 349 data->recently_closed_pages_have_updates_; | |
| 350 | |
| 351 // Clear the flags to reflect that we'll take actions on these updates. | |
| 352 data->most_visited_pages_have_updates_ = false; | |
| 353 data->recently_closed_pages_have_updates_ = false; | |
| 354 } | |
| 355 | |
| 356 if (!most_visited_pages_have_updates && !recently_closed_pages_have_updates) | |
| 357 return; | |
| 358 | |
| 359 // Update the application JumpList. If it fails, reset the flags to true if | |
| 360 // they were so that the corresponding JumpList categories will be tried to | |
| 361 // update again in the next run. | |
| 362 if (!UpdateJumpList( | |
| 363 app_id.c_str(), profile_dir, local_most_visited_pages, | |
| 364 local_recently_closed_pages, most_visited_pages_have_updates, | |
| 365 recently_closed_pages_have_updates, incognito_availability)) { | |
| 366 base::AutoLock auto_lock(data->list_lock_); | |
| 367 if (most_visited_pages_have_updates) | |
| 368 data->most_visited_pages_have_updates_ = true; | |
| 369 if (recently_closed_pages_have_updates) | |
| 370 data->recently_closed_pages_have_updates_ = true; | |
| 371 } | |
| 372 } | |
| 373 | |
| 374 } // namespace | 183 } // namespace |
| 375 | 184 |
| 376 JumpList::JumpListData::JumpListData() {} | 185 JumpList::JumpListData::JumpListData() {} |
| 377 | 186 |
| 378 JumpList::JumpListData::~JumpListData() {} | 187 JumpList::JumpListData::~JumpListData() {} |
| 379 | 188 |
| 380 JumpList::JumpList(Profile* profile) | 189 JumpList::JumpList(Profile* profile) |
| 381 : RefcountedKeyedService(content::BrowserThread::GetTaskRunnerForThread( | 190 : RefcountedKeyedService(content::BrowserThread::GetTaskRunnerForThread( |
| 382 content::BrowserThread::UI)), | 191 content::BrowserThread::UI)), |
| 383 profile_(profile), | 192 profile_(profile), |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 661 | 470 |
| 662 base::FilePath profile_dir = profile_->GetPath(); | 471 base::FilePath profile_dir = profile_->GetPath(); |
| 663 | 472 |
| 664 // Check if incognito windows (or normal windows) are disabled by policy. | 473 // Check if incognito windows (or normal windows) are disabled by policy. |
| 665 IncognitoModePrefs::Availability incognito_availability = | 474 IncognitoModePrefs::Availability incognito_availability = |
| 666 IncognitoModePrefs::GetAvailability(profile_->GetPrefs()); | 475 IncognitoModePrefs::GetAvailability(profile_->GetPrefs()); |
| 667 | 476 |
| 668 // Post a task to update the JumpList, which consists of 1) delete old icons, | 477 // Post a task to update the JumpList, which consists of 1) delete old icons, |
| 669 // 2) create new icons, 3) notify the OS. | 478 // 2) create new icons, 3) notify the OS. |
| 670 update_jumplist_task_runner_->PostTask( | 479 update_jumplist_task_runner_->PostTask( |
| 671 FROM_HERE, base::Bind(&RunUpdateJumpList, incognito_availability, app_id_, | 480 FROM_HERE, |
| 672 profile_dir, base::RetainedRef(jumplist_data_))); | 481 base::Bind(&JumpList::RunUpdateJumpList, base::Unretained(this), |
|
gab
2017/05/09 14:54:28
Looks like jumplist is owned by BrowserView [1]. A
chengx
2017/05/09 18:04:14
Thanks for pointing me to this, and I'm happy to f
gab
2017/05/09 18:37:36
Well you can't leave Unretained(this) in this CL t
chengx
2017/05/09 18:56:03
Oh, I see. I've changed base::Unretained(this) to
| |
| 482 incognito_availability, app_id_, profile_dir, | |
| 483 base::RetainedRef(jumplist_data_))); | |
| 673 | 484 |
| 674 // Post a task to delete JumpListIcons folder as it's no longer needed. | 485 // Post a task to delete JumpListIcons folder as it's no longer needed. |
| 675 // Now we have JumpListIconsMostVisited folder and JumpListIconsRecentClosed | 486 // Now we have JumpListIconsMostVisited folder and JumpListIconsRecentClosed |
| 676 // folder instead. | 487 // folder instead. |
| 677 base::FilePath icon_dir = | 488 base::FilePath icon_dir = |
| 678 GenerateJumplistIconDirName(profile_dir, FILE_PATH_LITERAL("")); | 489 GenerateJumplistIconDirName(profile_dir, FILE_PATH_LITERAL("")); |
| 679 | 490 |
| 680 delete_jumplisticons_task_runner_->PostTask( | 491 delete_jumplisticons_task_runner_->PostTask( |
| 681 FROM_HERE, | 492 FROM_HERE, |
| 682 base::Bind(&DeleteDirectory, std::move(icon_dir), kFileDeleteLimit)); | 493 base::Bind(&DeleteDirectory, std::move(icon_dir), kFileDeleteLimit)); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 757 break; | 568 break; |
| 758 } | 569 } |
| 759 } | 570 } |
| 760 | 571 |
| 761 data->recently_closed_pages_have_updates_ = true; | 572 data->recently_closed_pages_have_updates_ = true; |
| 762 } | 573 } |
| 763 | 574 |
| 764 // Send a query that retrieves the first favicon. | 575 // Send a query that retrieves the first favicon. |
| 765 StartLoadingFavicon(); | 576 StartLoadingFavicon(); |
| 766 } | 577 } |
| 578 | |
| 579 void JumpList::CreateIconFiles(const base::FilePath& icon_dir, | |
| 580 const ShellLinkItemList& item_list, | |
| 581 size_t max_items) { | |
| 582 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | |
| 583 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); | |
| 584 | |
| 585 for (ShellLinkItemList::const_iterator item = item_list.begin(); | |
| 586 item != item_list.end() && max_items > 0; ++item, --max_items) { | |
| 587 base::FilePath icon_path; | |
| 588 if (CreateIconFile((*item)->icon_image(), icon_dir, &icon_path)) | |
| 589 (*item)->set_icon(icon_path.value(), 0); | |
| 590 } | |
| 591 } | |
| 592 | |
| 593 void JumpList::UpdateIconFiles(const base::FilePath& icon_dir, | |
| 594 const ShellLinkItemList& page_list, | |
| 595 size_t slot_limit) { | |
| 596 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); | |
| 597 | |
| 598 // Create new icons only when the directory exists and is empty. | |
| 599 if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir)) | |
| 600 CreateIconFiles(icon_dir, page_list, slot_limit); | |
| 601 } | |
| 602 | |
| 603 bool JumpList::UpdateJumpList( | |
| 604 const wchar_t* app_id, | |
| 605 const base::FilePath& profile_dir, | |
| 606 const ShellLinkItemList& most_visited_pages, | |
| 607 const ShellLinkItemList& recently_closed_pages, | |
| 608 bool most_visited_pages_have_updates, | |
| 609 bool recently_closed_pages_have_updates, | |
| 610 IncognitoModePrefs::Availability incognito_availability) { | |
| 611 if (!JumpListUpdater::IsEnabled()) | |
| 612 return true; | |
| 613 | |
| 614 JumpListUpdater jumplist_updater(app_id); | |
|
gab
2017/05/09 14:54:28
Looks like this is taking a string& (so taking it
chengx
2017/05/09 18:04:14
I've updated JumpList::UpdateJumpList to use strin
gab
2017/05/09 20:07:11
No, refcounting is the default for Bind. Since Jum
chengx
2017/05/09 20:11:31
Cool. Thanks for the explanation!
| |
| 615 | |
| 616 base::ElapsedTimer begin_update_timer; | |
| 617 | |
| 618 if (!jumplist_updater.BeginUpdate()) | |
| 619 return false; | |
| 620 | |
| 621 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer | |
| 622 // than the maximum allowed time, as it's very likely the following update | |
| 623 // steps will also take a long time. | |
| 624 if (begin_update_timer.Elapsed() >= kTimeOutForJumplistUpdate) | |
| 625 return false; | |
| 626 | |
| 627 // The default maximum number of items to display in JumpList is 10. | |
| 628 // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx | |
| 629 // The "Most visited" category title always takes 1 of the JumpList slots if | |
| 630 // |most_visited_pages| isn't empty. | |
| 631 // The "Recently closed" category title will also take 1 if | |
| 632 // |recently_closed_pages| isn't empty. | |
| 633 // For the remaining slots, we allocate 5/8 (i.e., 5 slots if both categories | |
| 634 // present) to "most-visited" items and 3/8 (i.e., 3 slots if both categories | |
| 635 // present) to "recently-closed" items, respectively. | |
| 636 // Nevertheless, if there are not so many items in |recently_closed_pages|, | |
| 637 // we give the remaining slots to "most-visited" items. | |
| 638 | |
| 639 const int kMostVisited = 50; | |
| 640 const int kRecentlyClosed = 30; | |
| 641 const int kTotal = kMostVisited + kRecentlyClosed; | |
| 642 | |
| 643 // Adjust the available jumplist slots to account for the category titles. | |
| 644 size_t user_max_items_adjusted = jumplist_updater.user_max_items(); | |
| 645 if (!most_visited_pages.empty()) | |
| 646 --user_max_items_adjusted; | |
| 647 if (!recently_closed_pages.empty()) | |
| 648 --user_max_items_adjusted; | |
| 649 | |
| 650 size_t most_visited_items = | |
| 651 MulDiv(user_max_items_adjusted, kMostVisited, kTotal); | |
| 652 size_t recently_closed_items = user_max_items_adjusted - most_visited_items; | |
| 653 if (recently_closed_pages.size() < recently_closed_items) { | |
| 654 most_visited_items += recently_closed_items - recently_closed_pages.size(); | |
| 655 recently_closed_items = recently_closed_pages.size(); | |
| 656 } | |
| 657 | |
| 658 // Record the desired number of icons to create in this JumpList update. | |
| 659 int icons_to_create = 0; | |
| 660 | |
| 661 // Update the icons for "Most Visisted" category of the JumpList if needed. | |
| 662 if (most_visited_pages_have_updates) { | |
| 663 base::FilePath icon_dir_most_visited = GenerateJumplistIconDirName( | |
| 664 profile_dir, FILE_PATH_LITERAL("MostVisited")); | |
| 665 | |
| 666 UpdateIconFiles(icon_dir_most_visited, most_visited_pages, | |
| 667 most_visited_items); | |
| 668 | |
| 669 icons_to_create += std::min(most_visited_pages.size(), most_visited_items); | |
| 670 } | |
| 671 | |
| 672 // Update the icons for "Recently Closed" category of the JumpList if needed. | |
| 673 if (recently_closed_pages_have_updates) { | |
| 674 base::FilePath icon_dir_recent_closed = GenerateJumplistIconDirName( | |
| 675 profile_dir, FILE_PATH_LITERAL("RecentClosed")); | |
| 676 | |
| 677 UpdateIconFiles(icon_dir_recent_closed, recently_closed_pages, | |
| 678 recently_closed_items); | |
| 679 | |
| 680 icons_to_create += | |
| 681 std::min(recently_closed_pages.size(), recently_closed_items); | |
| 682 } | |
| 683 | |
| 684 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | |
| 685 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_to_create); | |
| 686 | |
| 687 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. | |
| 688 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); | |
| 689 | |
| 690 // Update the "Most Visited" category of the JumpList if it exists. | |
| 691 // This update request is applied into the JumpList when we commit this | |
| 692 // transaction. | |
| 693 if (!jumplist_updater.AddCustomCategory( | |
| 694 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), | |
| 695 most_visited_pages, most_visited_items)) { | |
| 696 return false; | |
| 697 } | |
| 698 | |
| 699 // Update the "Recently Closed" category of the JumpList. | |
| 700 if (!jumplist_updater.AddCustomCategory( | |
| 701 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), recently_closed_pages, | |
| 702 recently_closed_items)) { | |
| 703 return false; | |
| 704 } | |
| 705 | |
| 706 // Update the "Tasks" category of the JumpList. | |
| 707 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) | |
| 708 return false; | |
| 709 | |
| 710 // Commit this transaction and send the updated JumpList to Windows. | |
| 711 return jumplist_updater.CommitUpdate(); | |
| 712 } | |
| 713 | |
| 714 void JumpList::RunUpdateJumpList( | |
| 715 IncognitoModePrefs::Availability incognito_availability, | |
| 716 const std::wstring& app_id, | |
| 717 const base::FilePath& profile_dir, | |
| 718 base::RefCountedData<JumpListData>* ref_counted_data) { | |
| 719 JumpListData* data = &ref_counted_data->data; | |
| 720 ShellLinkItemList local_most_visited_pages; | |
| 721 ShellLinkItemList local_recently_closed_pages; | |
| 722 bool most_visited_pages_have_updates; | |
| 723 bool recently_closed_pages_have_updates; | |
| 724 | |
| 725 { | |
| 726 base::AutoLock auto_lock(data->list_lock_); | |
| 727 // Make sure we are not out of date: if icon_urls_ is not empty, then | |
| 728 // another notification has been received since we processed this one | |
| 729 if (!data->icon_urls_.empty()) | |
| 730 return; | |
| 731 | |
| 732 // Make local copies of lists and flags so we can release the lock. | |
| 733 local_most_visited_pages = data->most_visited_pages_; | |
| 734 local_recently_closed_pages = data->recently_closed_pages_; | |
| 735 | |
| 736 most_visited_pages_have_updates = data->most_visited_pages_have_updates_; | |
| 737 recently_closed_pages_have_updates = | |
| 738 data->recently_closed_pages_have_updates_; | |
| 739 | |
| 740 // Clear the flags to reflect that we'll take actions on these updates. | |
| 741 data->most_visited_pages_have_updates_ = false; | |
| 742 data->recently_closed_pages_have_updates_ = false; | |
| 743 } | |
| 744 | |
| 745 if (!most_visited_pages_have_updates && !recently_closed_pages_have_updates) | |
| 746 return; | |
| 747 | |
| 748 // Update the application JumpList. If it fails, reset the flags to true if | |
| 749 // they were so that the corresponding JumpList categories will be tried to | |
| 750 // update again in the next run. | |
| 751 if (!UpdateJumpList( | |
| 752 app_id.c_str(), profile_dir, local_most_visited_pages, | |
| 753 local_recently_closed_pages, most_visited_pages_have_updates, | |
| 754 recently_closed_pages_have_updates, incognito_availability)) { | |
| 755 base::AutoLock auto_lock(data->list_lock_); | |
| 756 if (most_visited_pages_have_updates) | |
| 757 data->most_visited_pages_have_updates_ = true; | |
| 758 if (recently_closed_pages_have_updates) | |
| 759 data->recently_closed_pages_have_updates_ = true; | |
| 760 } | |
| 761 } | |
| OLD | NEW |