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> | |
| 8 | |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 9 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 10 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 11 #include "base/macros.h" | 13 #include "base/macros.h" |
| 12 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/path_service.h" | 15 #include "base/path_service.h" |
| 14 #include "base/sequenced_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
| 15 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 17 #include "base/task_scheduler/post_task.h" | 19 #include "base/task_scheduler/post_task.h" |
| 18 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
| 19 #include "base/threading/thread_restrictions.h" | 21 #include "base/threading/thread_restrictions.h" |
| 20 #include "base/trace_event/trace_event.h" | 22 #include "base/trace_event/trace_event.h" |
| 21 #include "chrome/browser/chrome_notification_types.h" | 23 #include "chrome/browser/chrome_notification_types.h" |
| 22 #include "chrome/browser/favicon/favicon_service_factory.h" | 24 #include "chrome/browser/favicon/favicon_service_factory.h" |
| 23 #include "chrome/browser/history/top_sites_factory.h" | 25 #include "chrome/browser/history/top_sites_factory.h" |
| 24 #include "chrome/browser/metrics/jumplist_metrics_win.h" | 26 #include "chrome/browser/metrics/jumplist_metrics_win.h" |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 return false; | 223 return false; |
| 222 | 224 |
| 223 // Commit this transaction and send the updated JumpList to Windows. | 225 // Commit this transaction and send the updated JumpList to Windows. |
| 224 if (!jumplist_updater.CommitUpdate()) | 226 if (!jumplist_updater.CommitUpdate()) |
| 225 return false; | 227 return false; |
| 226 | 228 |
| 227 return true; | 229 return true; |
| 228 } | 230 } |
| 229 | 231 |
| 230 // Updates the jumplist, once all the data has been fetched. | 232 // Updates the jumplist, once all the data has been fetched. |
| 231 void RunUpdateOnFileThread( | 233 void RunUpdateJumpList(IncognitoModePrefs::Availability incognito_availability, |
| 232 IncognitoModePrefs::Availability incognito_availability, | 234 const std::wstring& app_id, |
| 233 const std::wstring& app_id, | 235 const base::FilePath& icon_dir, |
| 234 const base::FilePath& icon_dir, | 236 base::RefCountedData<JumpListData>* ref_counted_data) { |
| 235 base::RefCountedData<JumpListData>* ref_counted_data, | |
| 236 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner) { | |
| 237 JumpListData* data = &ref_counted_data->data; | 237 JumpListData* data = &ref_counted_data->data; |
| 238 ShellLinkItemList local_most_visited_pages; | 238 ShellLinkItemList local_most_visited_pages; |
| 239 ShellLinkItemList local_recently_closed_pages; | 239 ShellLinkItemList local_recently_closed_pages; |
| 240 | 240 |
| 241 { | 241 { |
| 242 base::AutoLock auto_lock(data->list_lock_); | 242 base::AutoLock auto_lock(data->list_lock_); |
| 243 // Make sure we are not out of date: if icon_urls_ is not empty, then | 243 // Make sure we are not out of date: if icon_urls_ is not empty, then |
| 244 // another notification has been received since we processed this one | 244 // another notification has been received since we processed this one |
| 245 if (!data->icon_urls_.empty()) | 245 if (!data->icon_urls_.empty()) |
| 246 return; | 246 return; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 281 // Create icon files for shortcuts in the "Recently Closed" | 281 // Create icon files for shortcuts in the "Recently Closed" |
| 282 // category. | 282 // category. |
| 283 CreateIconFiles(icon_dir, local_recently_closed_pages); | 283 CreateIconFiles(icon_dir, local_recently_closed_pages); |
| 284 } | 284 } |
| 285 | 285 |
| 286 // Create a new JumpList and replace the current JumpList with it. The | 286 // Create a new JumpList and replace the current JumpList with it. The |
| 287 // jumplist links are updated anyway, while the jumplist icons may not as | 287 // jumplist links are updated anyway, while the jumplist icons may not as |
| 288 // mentioned above. | 288 // mentioned above. |
| 289 UpdateJumpList(app_id.c_str(), local_most_visited_pages, | 289 UpdateJumpList(app_id.c_str(), local_most_visited_pages, |
| 290 local_recently_closed_pages, incognito_availability); | 290 local_recently_closed_pages, incognito_availability); |
| 291 | |
| 292 // Post a background task to delete JumpListIconsOld folder if it exists and | |
| 293 // log the delete results to UMA. | |
| 294 base::FilePath icon_dir_old = icon_dir.DirName().Append( | |
| 295 icon_dir.BaseName().value() + FILE_PATH_LITERAL("Old")); | |
| 296 | |
| 297 if (base::DirectoryExists(icon_dir_old)) { | |
| 298 sequenced_task_runner->PostTask( | |
| 299 FROM_HERE, base::Bind(&DeleteDirectoryAndLogResults, icon_dir_old, | |
| 300 kFileDeleteLimit)); | |
| 301 } | |
| 302 } | 291 } |
| 303 | 292 |
| 304 } // namespace | 293 } // namespace |
| 305 | 294 |
| 306 JumpList::JumpListData::JumpListData() {} | 295 JumpList::JumpListData::JumpListData() {} |
| 307 | 296 |
| 308 JumpList::JumpListData::~JumpListData() {} | 297 JumpList::JumpListData::~JumpListData() {} |
| 309 | 298 |
| 310 JumpList::JumpList(Profile* profile) | 299 JumpList::JumpList(Profile* profile) |
| 311 : RefcountedKeyedService(content::BrowserThread::GetTaskRunnerForThread( | 300 : RefcountedKeyedService(content::BrowserThread::GetTaskRunnerForThread( |
| 312 content::BrowserThread::UI)), | 301 content::BrowserThread::UI)), |
| 313 profile_(profile), | 302 profile_(profile), |
| 314 jumplist_data_(new base::RefCountedData<JumpListData>), | 303 jumplist_data_(new base::RefCountedData<JumpListData>), |
| 315 task_id_(base::CancelableTaskTracker::kBadTaskId), | 304 task_id_(base::CancelableTaskTracker::kBadTaskId), |
| 316 sequenced_task_runner_(base::CreateSequencedTaskRunnerWithTraits( | 305 single_thread_task_runner_(base::CreateCOMSTATaskRunnerWithTraits( |
| 317 base::TaskTraits() | 306 base::TaskTraits() |
| 318 .WithPriority(base::TaskPriority::BACKGROUND) | 307 .WithPriority(base::TaskPriority::BACKGROUND) |
| 319 .WithShutdownBehavior( | 308 .WithShutdownBehavior( |
| 320 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) | 309 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) |
| 321 .MayBlock())), | 310 .MayBlock())), |
| 322 weak_ptr_factory_(this) { | 311 weak_ptr_factory_(this) { |
| 323 DCHECK(Enabled()); | 312 DCHECK(Enabled()); |
| 324 // To update JumpList when a tab is added or removed, we add this object to | 313 // To update JumpList when a tab is added or removed, we add this object to |
| 325 // the observer list of the TabRestoreService class. | 314 // the observer list of the TabRestoreService class. |
| 326 // When we add this object to the observer list, we save the pointer to this | 315 // When we add this object to the observer list, we save the pointer to this |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 waiting_for_icons = !data->icon_urls_.empty(); | 513 waiting_for_icons = !data->icon_urls_.empty(); |
| 525 if (waiting_for_icons) { | 514 if (waiting_for_icons) { |
| 526 // Ask FaviconService if it has a favicon of a URL. | 515 // Ask FaviconService if it has a favicon of a URL. |
| 527 // When FaviconService has one, it will call OnFaviconDataAvailable(). | 516 // When FaviconService has one, it will call OnFaviconDataAvailable(). |
| 528 url = GURL(data->icon_urls_.front().first); | 517 url = GURL(data->icon_urls_.front().first); |
| 529 } | 518 } |
| 530 } | 519 } |
| 531 | 520 |
| 532 if (!waiting_for_icons) { | 521 if (!waiting_for_icons) { |
| 533 // No more favicons are needed by the application JumpList. Schedule a | 522 // No more favicons are needed by the application JumpList. Schedule a |
| 534 // RunUpdateOnFileThread call. | 523 // RunUpdateJumpList call. |
| 535 PostRunUpdate(); | 524 PostRunUpdate(); |
| 536 return; | 525 return; |
| 537 } | 526 } |
| 538 | 527 |
| 539 favicon::FaviconService* favicon_service = | 528 favicon::FaviconService* favicon_service = |
| 540 FaviconServiceFactory::GetForProfile(profile_, | 529 FaviconServiceFactory::GetForProfile(profile_, |
| 541 ServiceAccessType::EXPLICIT_ACCESS); | 530 ServiceAccessType::EXPLICIT_ACCESS); |
| 542 task_id_ = favicon_service->GetFaviconImageForPageURL( | 531 task_id_ = favicon_service->GetFaviconImageForPageURL( |
| 543 url, | 532 url, |
| 544 base::Bind(&JumpList::OnFaviconDataAvailable, base::Unretained(this)), | 533 base::Bind(&JumpList::OnFaviconDataAvailable, base::Unretained(this)), |
| 545 &cancelable_task_tracker_); | 534 &cancelable_task_tracker_); |
| 546 } | 535 } |
| 547 | 536 |
| 548 void JumpList::OnFaviconDataAvailable( | 537 void JumpList::OnFaviconDataAvailable( |
| 549 const favicon_base::FaviconImageResult& image_result) { | 538 const favicon_base::FaviconImageResult& image_result) { |
| 550 DCHECK(CalledOnValidThread()); | 539 DCHECK(CalledOnValidThread()); |
| 551 | 540 |
| 552 // If there is currently a favicon request in progress, it is now outdated, | 541 // If there is currently a favicon request in progress, it is now outdated, |
| 553 // as we have received another, so nullify the handle from the old request. | 542 // as we have received another, so nullify the handle from the old request. |
| 554 task_id_ = base::CancelableTaskTracker::kBadTaskId; | 543 task_id_ = base::CancelableTaskTracker::kBadTaskId; |
| 555 // Lock the list to set icon data and pop the url. | 544 // Lock the list to set icon data and pop the url. |
| 556 { | 545 { |
| 557 JumpListData* data = &jumplist_data_->data; | 546 JumpListData* data = &jumplist_data_->data; |
| 558 base::AutoLock auto_lock(data->list_lock_); | 547 base::AutoLock auto_lock(data->list_lock_); |
| 559 // Attach the received data to the ShellLinkItem object. | 548 // Attach the received data to the ShellLinkItem object. |
| 560 // This data will be decoded by the RunUpdateOnFileThread method. | 549 // This data will be decoded by the RunUpdateJumpList method. |
| 561 if (!image_result.image.IsEmpty() && !data->icon_urls_.empty() && | 550 if (!image_result.image.IsEmpty() && !data->icon_urls_.empty() && |
| 562 data->icon_urls_.front().second.get()) { | 551 data->icon_urls_.front().second.get()) { |
| 563 gfx::ImageSkia image_skia = image_result.image.AsImageSkia(); | 552 gfx::ImageSkia image_skia = image_result.image.AsImageSkia(); |
| 564 image_skia.EnsureRepsForSupportedScales(); | 553 image_skia.EnsureRepsForSupportedScales(); |
| 565 std::unique_ptr<gfx::ImageSkia> deep_copy(image_skia.DeepCopy()); | 554 std::unique_ptr<gfx::ImageSkia> deep_copy(image_skia.DeepCopy()); |
| 566 data->icon_urls_.front().second->set_icon_image(*deep_copy); | 555 data->icon_urls_.front().second->set_icon_image(*deep_copy); |
| 567 } | 556 } |
| 568 | 557 |
| 569 if (!data->icon_urls_.empty()) | 558 if (!data->icon_urls_.empty()) |
| 570 data->icon_urls_.pop_front(); | 559 data->icon_urls_.pop_front(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 608 | 597 |
| 609 void JumpList::DeferredRunUpdate() { | 598 void JumpList::DeferredRunUpdate() { |
| 610 DCHECK(CalledOnValidThread()); | 599 DCHECK(CalledOnValidThread()); |
| 611 | 600 |
| 612 TRACE_EVENT0("browser", "JumpList::DeferredRunUpdate"); | 601 TRACE_EVENT0("browser", "JumpList::DeferredRunUpdate"); |
| 613 // Check if incognito windows (or normal windows) are disabled by policy. | 602 // Check if incognito windows (or normal windows) are disabled by policy. |
| 614 IncognitoModePrefs::Availability incognito_availability = | 603 IncognitoModePrefs::Availability incognito_availability = |
| 615 profile_ ? IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) | 604 profile_ ? IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) |
| 616 : IncognitoModePrefs::ENABLED; | 605 : IncognitoModePrefs::ENABLED; |
| 617 | 606 |
| 618 BrowserThread::PostTask( | 607 // Post a task to update the jumplist used by the shell. |
| 619 BrowserThread::FILE, FROM_HERE, | 608 single_thread_task_runner_->PostTask( |
|
robliao
2017/04/05 00:27:50
Is this expected to be called a lot? If not, you c
chengx
2017/04/05 03:25:50
It will be called each time a Chrome tab is closed
gab
2017/04/05 20:53:27
Yeah agreed that's a lot.
@robliao: I'm also seei
robliao
2017/04/05 23:02:29
Yeah. I'm pondering if the API should expose that
| |
| 620 base::Bind(&RunUpdateOnFileThread, incognito_availability, app_id_, | 609 FROM_HERE, base::Bind(&RunUpdateJumpList, incognito_availability, app_id_, |
| 621 icon_dir_, base::RetainedRef(jumplist_data_), | 610 icon_dir_, base::RetainedRef(jumplist_data_))); |
| 622 sequenced_task_runner_)); | 611 |
| 612 // Post a task to delete JumpListIconsOld folder if it exists and log the | |
| 613 // delete results to UMA. | |
| 614 base::FilePath icon_dir_old = icon_dir_.DirName().Append( | |
| 615 icon_dir_.BaseName().value() + FILE_PATH_LITERAL("Old")); | |
| 616 | |
| 617 single_thread_task_runner_->PostTask( | |
| 618 FROM_HERE, base::Bind(&DeleteDirectoryAndLogResults, | |
| 619 std::move(icon_dir_old), kFileDeleteLimit)); | |
| 623 } | 620 } |
| 624 | 621 |
| 625 void JumpList::TopSitesLoaded(history::TopSites* top_sites) { | 622 void JumpList::TopSitesLoaded(history::TopSites* top_sites) { |
| 626 } | 623 } |
| 627 | 624 |
| 628 void JumpList::TopSitesChanged(history::TopSites* top_sites, | 625 void JumpList::TopSitesChanged(history::TopSites* top_sites, |
| 629 ChangeReason change_reason) { | 626 ChangeReason change_reason) { |
| 630 top_sites->GetMostVisitedURLs( | 627 top_sites->GetMostVisitedURLs( |
| 631 base::Bind(&JumpList::OnMostVisitedURLsAvailable, | 628 base::Bind(&JumpList::OnMostVisitedURLsAvailable, |
| 632 weak_ptr_factory_.GetWeakPtr()), | 629 weak_ptr_factory_.GetWeakPtr()), |
| 633 false); | 630 false); |
| 634 } | 631 } |
| OLD | NEW |