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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 const int kMostVistedCount = 9; | 284 const int kMostVistedCount = 9; |
476 { | 285 { |
477 JumpListData* data = &jumplist_data_->data; | 286 JumpListData* data = &jumplist_data_->data; |
478 base::AutoLock auto_lock(data->list_lock_); | 287 base::AutoLock auto_lock(data->list_lock_); |
479 data->most_visited_pages_.clear(); | 288 data->most_visited_pages_.clear(); |
480 | 289 |
481 for (size_t i = 0; i < urls.size() && i < kMostVistedCount; i++) { | 290 for (size_t i = 0; i < urls.size() && i < kMostVistedCount; i++) { |
482 const history::MostVisitedURL& url = urls[i]; | 291 const history::MostVisitedURL& url = urls[i]; |
483 scoped_refptr<ShellLinkItem> link = CreateShellLink(); | 292 scoped_refptr<ShellLinkItem> link = CreateShellLink(); |
484 std::string url_string = url.url.spec(); | 293 std::string url_string = url.url.spec(); |
485 std::wstring url_string_wide = base::UTF8ToWide(url_string); | 294 base::string16 url_string_wide = base::UTF8ToUTF16(url_string); |
486 link->GetCommandLine()->AppendArgNative(url_string_wide); | 295 link->GetCommandLine()->AppendArgNative(url_string_wide); |
487 link->GetCommandLine()->AppendSwitchASCII( | 296 link->GetCommandLine()->AppendSwitchASCII( |
488 switches::kWinJumplistAction, jumplist::kMostVisitedCategory); | 297 switches::kWinJumplistAction, jumplist::kMostVisitedCategory); |
489 link->set_title(!url.title.empty() ? url.title : url_string_wide); | 298 link->set_title(!url.title.empty() ? url.title : url_string_wide); |
490 data->most_visited_pages_.push_back(link); | 299 data->most_visited_pages_.push_back(link); |
491 data->icon_urls_.push_back(std::make_pair(url_string, link)); | 300 data->icon_urls_.push_back(std::make_pair(url_string, link)); |
492 } | 301 } |
493 data->most_visited_pages_have_updates_ = true; | 302 data->most_visited_pages_have_updates_ = true; |
494 } | 303 } |
495 | 304 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 data->list_lock_.AssertAcquired(); | 337 data->list_lock_.AssertAcquired(); |
529 | 338 |
530 // This code adds the URL and the title strings of the given tab to |data|. | 339 // This code adds the URL and the title strings of the given tab to |data|. |
531 if (data->recently_closed_pages_.size() >= max_items) | 340 if (data->recently_closed_pages_.size() >= max_items) |
532 return false; | 341 return false; |
533 | 342 |
534 scoped_refptr<ShellLinkItem> link = CreateShellLink(); | 343 scoped_refptr<ShellLinkItem> link = CreateShellLink(); |
535 const sessions::SerializedNavigationEntry& current_navigation = | 344 const sessions::SerializedNavigationEntry& current_navigation = |
536 tab.navigations.at(tab.current_navigation_index); | 345 tab.navigations.at(tab.current_navigation_index); |
537 std::string url = current_navigation.virtual_url().spec(); | 346 std::string url = current_navigation.virtual_url().spec(); |
538 link->GetCommandLine()->AppendArgNative(base::UTF8ToWide(url)); | 347 link->GetCommandLine()->AppendArgNative(base::UTF8ToUTF16(url)); |
539 link->GetCommandLine()->AppendSwitchASCII(switches::kWinJumplistAction, | 348 link->GetCommandLine()->AppendSwitchASCII(switches::kWinJumplistAction, |
540 jumplist::kRecentlyClosedCategory); | 349 jumplist::kRecentlyClosedCategory); |
541 link->set_title(current_navigation.title()); | 350 link->set_title(current_navigation.title()); |
542 data->recently_closed_pages_.push_back(link); | 351 data->recently_closed_pages_.push_back(link); |
543 data->icon_urls_.push_back(std::make_pair(std::move(url), std::move(link))); | 352 data->icon_urls_.push_back(std::make_pair(std::move(url), std::move(link))); |
544 | 353 |
545 return true; | 354 return true; |
546 } | 355 } |
547 | 356 |
548 void JumpList::AddWindow(const sessions::TabRestoreService::Window& window, | 357 void JumpList::AddWindow(const sessions::TabRestoreService::Window& window, |
(...skipping 112 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, this, incognito_availability, |
| 482 app_id_, profile_dir, base::RetainedRef(jumplist_data_))); |
673 | 483 |
674 // Post a task to delete JumpListIcons folder as it's no longer needed. | 484 // Post a task to delete JumpListIcons folder as it's no longer needed. |
675 // Now we have JumpListIconsMostVisited folder and JumpListIconsRecentClosed | 485 // Now we have JumpListIconsMostVisited folder and JumpListIconsRecentClosed |
676 // folder instead. | 486 // folder instead. |
677 base::FilePath icon_dir = | 487 base::FilePath icon_dir = |
678 GenerateJumplistIconDirName(profile_dir, FILE_PATH_LITERAL("")); | 488 GenerateJumplistIconDirName(profile_dir, FILE_PATH_LITERAL("")); |
679 | 489 |
680 delete_jumplisticons_task_runner_->PostTask( | 490 delete_jumplisticons_task_runner_->PostTask( |
681 FROM_HERE, | 491 FROM_HERE, |
682 base::Bind(&DeleteDirectory, std::move(icon_dir), kFileDeleteLimit)); | 492 base::Bind(&DeleteDirectory, std::move(icon_dir), kFileDeleteLimit)); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 break; | 567 break; |
758 } | 568 } |
759 } | 569 } |
760 | 570 |
761 data->recently_closed_pages_have_updates_ = true; | 571 data->recently_closed_pages_have_updates_ = true; |
762 } | 572 } |
763 | 573 |
764 // Send a query that retrieves the first favicon. | 574 // Send a query that retrieves the first favicon. |
765 StartLoadingFavicon(); | 575 StartLoadingFavicon(); |
766 } | 576 } |
| 577 |
| 578 void JumpList::CreateIconFiles(const base::FilePath& icon_dir, |
| 579 const ShellLinkItemList& item_list, |
| 580 size_t max_items) { |
| 581 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
| 582 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.CreateIconFilesDuration"); |
| 583 |
| 584 for (ShellLinkItemList::const_iterator item = item_list.begin(); |
| 585 item != item_list.end() && max_items > 0; ++item, --max_items) { |
| 586 base::FilePath icon_path; |
| 587 if (CreateIconFile((*item)->icon_image(), icon_dir, &icon_path)) |
| 588 (*item)->set_icon(icon_path.value(), 0); |
| 589 } |
| 590 } |
| 591 |
| 592 void JumpList::UpdateIconFiles(const base::FilePath& icon_dir, |
| 593 const ShellLinkItemList& page_list, |
| 594 size_t slot_limit) { |
| 595 DeleteDirectoryContentAndLogRuntime(icon_dir, kFileDeleteLimit); |
| 596 |
| 597 // Create new icons only when the directory exists and is empty. |
| 598 if (base::CreateDirectory(icon_dir) && base::IsDirectoryEmpty(icon_dir)) |
| 599 CreateIconFiles(icon_dir, page_list, slot_limit); |
| 600 } |
| 601 |
| 602 bool JumpList::UpdateJumpList( |
| 603 const base::string16& app_id, |
| 604 const base::FilePath& profile_dir, |
| 605 const ShellLinkItemList& most_visited_pages, |
| 606 const ShellLinkItemList& recently_closed_pages, |
| 607 bool most_visited_pages_have_updates, |
| 608 bool recently_closed_pages_have_updates, |
| 609 IncognitoModePrefs::Availability incognito_availability) { |
| 610 if (!JumpListUpdater::IsEnabled()) |
| 611 return true; |
| 612 |
| 613 JumpListUpdater jumplist_updater(app_id); |
| 614 |
| 615 base::ElapsedTimer begin_update_timer; |
| 616 |
| 617 if (!jumplist_updater.BeginUpdate()) |
| 618 return false; |
| 619 |
| 620 // Discard this JumpList update if JumpListUpdater::BeginUpdate takes longer |
| 621 // than the maximum allowed time, as it's very likely the following update |
| 622 // steps will also take a long time. |
| 623 if (begin_update_timer.Elapsed() >= kTimeOutForJumplistUpdate) |
| 624 return false; |
| 625 |
| 626 // The default maximum number of items to display in JumpList is 10. |
| 627 // https://msdn.microsoft.com/library/windows/desktop/dd378398.aspx |
| 628 // The "Most visited" category title always takes 1 of the JumpList slots if |
| 629 // |most_visited_pages| isn't empty. |
| 630 // The "Recently closed" category title will also take 1 if |
| 631 // |recently_closed_pages| isn't empty. |
| 632 // For the remaining slots, we allocate 5/8 (i.e., 5 slots if both categories |
| 633 // present) to "most-visited" items and 3/8 (i.e., 3 slots if both categories |
| 634 // present) to "recently-closed" items, respectively. |
| 635 // Nevertheless, if there are not so many items in |recently_closed_pages|, |
| 636 // we give the remaining slots to "most-visited" items. |
| 637 |
| 638 const int kMostVisited = 50; |
| 639 const int kRecentlyClosed = 30; |
| 640 const int kTotal = kMostVisited + kRecentlyClosed; |
| 641 |
| 642 // Adjust the available jumplist slots to account for the category titles. |
| 643 size_t user_max_items_adjusted = jumplist_updater.user_max_items(); |
| 644 if (!most_visited_pages.empty()) |
| 645 --user_max_items_adjusted; |
| 646 if (!recently_closed_pages.empty()) |
| 647 --user_max_items_adjusted; |
| 648 |
| 649 size_t most_visited_items = |
| 650 MulDiv(user_max_items_adjusted, kMostVisited, kTotal); |
| 651 size_t recently_closed_items = user_max_items_adjusted - most_visited_items; |
| 652 if (recently_closed_pages.size() < recently_closed_items) { |
| 653 most_visited_items += recently_closed_items - recently_closed_pages.size(); |
| 654 recently_closed_items = recently_closed_pages.size(); |
| 655 } |
| 656 |
| 657 // Record the desired number of icons to create in this JumpList update. |
| 658 int icons_to_create = 0; |
| 659 |
| 660 // Update the icons for "Most Visisted" category of the JumpList if needed. |
| 661 if (most_visited_pages_have_updates) { |
| 662 base::FilePath icon_dir_most_visited = GenerateJumplistIconDirName( |
| 663 profile_dir, FILE_PATH_LITERAL("MostVisited")); |
| 664 |
| 665 UpdateIconFiles(icon_dir_most_visited, most_visited_pages, |
| 666 most_visited_items); |
| 667 |
| 668 icons_to_create += std::min(most_visited_pages.size(), most_visited_items); |
| 669 } |
| 670 |
| 671 // Update the icons for "Recently Closed" category of the JumpList if needed. |
| 672 if (recently_closed_pages_have_updates) { |
| 673 base::FilePath icon_dir_recent_closed = GenerateJumplistIconDirName( |
| 674 profile_dir, FILE_PATH_LITERAL("RecentClosed")); |
| 675 |
| 676 UpdateIconFiles(icon_dir_recent_closed, recently_closed_pages, |
| 677 recently_closed_items); |
| 678 |
| 679 icons_to_create += |
| 680 std::min(recently_closed_pages.size(), recently_closed_items); |
| 681 } |
| 682 |
| 683 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
| 684 UMA_HISTOGRAM_COUNTS_100("WinJumplist.CreateIconFilesCount", icons_to_create); |
| 685 |
| 686 // TODO(chengx): Remove the UMA histogram after fixing http://crbug.com/40407. |
| 687 SCOPED_UMA_HISTOGRAM_TIMER("WinJumplist.UpdateJumpListDuration"); |
| 688 |
| 689 // Update the "Most Visited" category of the JumpList if it exists. |
| 690 // This update request is applied into the JumpList when we commit this |
| 691 // transaction. |
| 692 if (!jumplist_updater.AddCustomCategory( |
| 693 l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED), |
| 694 most_visited_pages, most_visited_items)) { |
| 695 return false; |
| 696 } |
| 697 |
| 698 // Update the "Recently Closed" category of the JumpList. |
| 699 if (!jumplist_updater.AddCustomCategory( |
| 700 l10n_util::GetStringUTF16(IDS_RECENTLY_CLOSED), recently_closed_pages, |
| 701 recently_closed_items)) { |
| 702 return false; |
| 703 } |
| 704 |
| 705 // Update the "Tasks" category of the JumpList. |
| 706 if (!UpdateTaskCategory(&jumplist_updater, incognito_availability)) |
| 707 return false; |
| 708 |
| 709 // Commit this transaction and send the updated JumpList to Windows. |
| 710 return jumplist_updater.CommitUpdate(); |
| 711 } |
| 712 |
| 713 void JumpList::RunUpdateJumpList( |
| 714 IncognitoModePrefs::Availability incognito_availability, |
| 715 const base::string16& app_id, |
| 716 const base::FilePath& profile_dir, |
| 717 base::RefCountedData<JumpListData>* ref_counted_data) { |
| 718 JumpListData* data = &ref_counted_data->data; |
| 719 ShellLinkItemList local_most_visited_pages; |
| 720 ShellLinkItemList local_recently_closed_pages; |
| 721 bool most_visited_pages_have_updates; |
| 722 bool recently_closed_pages_have_updates; |
| 723 |
| 724 { |
| 725 base::AutoLock auto_lock(data->list_lock_); |
| 726 // Make sure we are not out of date: if icon_urls_ is not empty, then |
| 727 // another notification has been received since we processed this one |
| 728 if (!data->icon_urls_.empty()) |
| 729 return; |
| 730 |
| 731 // Make local copies of lists and flags so we can release the lock. |
| 732 local_most_visited_pages = data->most_visited_pages_; |
| 733 local_recently_closed_pages = data->recently_closed_pages_; |
| 734 |
| 735 most_visited_pages_have_updates = data->most_visited_pages_have_updates_; |
| 736 recently_closed_pages_have_updates = |
| 737 data->recently_closed_pages_have_updates_; |
| 738 |
| 739 // Clear the flags to reflect that we'll take actions on these updates. |
| 740 data->most_visited_pages_have_updates_ = false; |
| 741 data->recently_closed_pages_have_updates_ = false; |
| 742 } |
| 743 |
| 744 if (!most_visited_pages_have_updates && !recently_closed_pages_have_updates) |
| 745 return; |
| 746 |
| 747 // Update the application JumpList. If it fails, reset the flags to true if |
| 748 // they were so that the corresponding JumpList categories will be tried to |
| 749 // update again in the next run. |
| 750 if (!UpdateJumpList( |
| 751 app_id, profile_dir, local_most_visited_pages, |
| 752 local_recently_closed_pages, most_visited_pages_have_updates, |
| 753 recently_closed_pages_have_updates, incognito_availability)) { |
| 754 base::AutoLock auto_lock(data->list_lock_); |
| 755 if (most_visited_pages_have_updates) |
| 756 data->most_visited_pages_have_updates_ = true; |
| 757 if (recently_closed_pages_have_updates) |
| 758 data->recently_closed_pages_have_updates_ = true; |
| 759 } |
| 760 } |
OLD | NEW |