Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: chrome/browser/jumplist_win.cc

Issue 7538022: Jumplist Bug (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 <windows.h> 7 #include <windows.h>
8 #include <shobjidl.h> 8 #include <shobjidl.h>
9 #include <propkey.h> 9 #include <propkey.h>
10 #include <propvarutil.h> 10 #include <propvarutil.h>
11 11
12 #include <string> 12 #include <string>
13 #include <vector> 13 #include <vector>
14 14
15 #include "base/callback.h" 15 #include "base/callback.h"
16 #include "base/command_line.h" 16 #include "base/command_line.h"
17 #include "base/file_util.h" 17 #include "base/file_util.h"
18 #include "base/path_service.h" 18 #include "base/path_service.h"
19 #include "base/string_util.h" 19 #include "base/string_util.h"
20 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
21 #include "base/utf_string_conversions.h" 21 #include "base/utf_string_conversions.h"
22 #include "base/win/scoped_comptr.h" 22 #include "base/win/scoped_comptr.h"
23 #include "base/win/windows_version.h" 23 #include "base/win/windows_version.h"
24 #include "chrome/browser/favicon/favicon_service.h" 24 #include "chrome/browser/favicon/favicon_service.h"
25 #include "chrome/browser/history/history.h" 25 #include "chrome/browser/history/history.h"
26 #include "chrome/browser/history/page_usage_data.h" 26 #include "chrome/browser/history/page_usage_data.h"
27 #include "chrome/browser/history/top_sites.h"
27 #include "chrome/browser/profiles/profile.h" 28 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/sessions/session_types.h" 29 #include "chrome/browser/sessions/session_types.h"
29 #include "chrome/browser/sessions/tab_restore_service.h" 30 #include "chrome/browser/sessions/tab_restore_service.h"
30 #include "chrome/browser/sessions/tab_restore_service_factory.h" 31 #include "chrome/browser/sessions/tab_restore_service_factory.h"
31 #include "chrome/browser/shell_integration.h" 32 #include "chrome/browser/shell_integration.h"
32 #include "chrome/common/chrome_constants.h" 33 #include "chrome/common/chrome_constants.h"
34 #include "chrome/common/chrome_notification_types.h"
33 #include "chrome/common/chrome_switches.h" 35 #include "chrome/common/chrome_switches.h"
34 #include "chrome/common/url_constants.h" 36 #include "chrome/common/url_constants.h"
35 #include "content/browser/browser_thread.h" 37 #include "content/browser/browser_thread.h"
38 #include "content/common/notification_service.h"
36 #include "googleurl/src/gurl.h" 39 #include "googleurl/src/gurl.h"
37 #include "grit/chromium_strings.h" 40 #include "grit/chromium_strings.h"
38 #include "grit/generated_resources.h" 41 #include "grit/generated_resources.h"
39 #include "third_party/skia/include/core/SkBitmap.h" 42 #include "third_party/skia/include/core/SkBitmap.h"
40 #include "ui/base/l10n/l10n_util.h" 43 #include "ui/base/l10n/l10n_util.h"
41 #include "ui/gfx/codec/png_codec.h" 44 #include "ui/gfx/codec/png_codec.h"
42 #include "ui/gfx/icon_util.h" 45 #include "ui/gfx/icon_util.h"
43 46
44 47
45 namespace { 48 namespace {
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 return false; 472 return false;
470 473
471 // Commit this transaction and send the updated JumpList to Windows. 474 // Commit this transaction and send the updated JumpList to Windows.
472 result = destination_list->CommitList(); 475 result = destination_list->CommitList();
473 if (FAILED(result)) 476 if (FAILED(result))
474 return false; 477 return false;
475 478
476 return true; 479 return true;
477 } 480 }
478 481
479 // Represents a task which updates an application JumpList.
480 // This task encapsulates all I/O tasks and OS-specific tasks required for
481 // updating a JumpList from Chromium, such as:
482 // * Deleting the directory containing temporary icon files;
483 // * Creating temporary icon files used by the JumpList;
484 // * Creating an ICustomDestinationList instance;
485 // * Adding items in the ICustomDestinationList instance.
486 // To spawn this task,
487 // 1. Prepare objects required by this task:
488 // * a std::wstring that contains a temporary icons;
489 // * a ShellLinkItemList that contains the items of the "Most Visited"
490 // category, and;
491 // * a ShellLinkItemList that contains the items of the "Recently Closed"
492 // category.
493 // 2. Create a JumpListUpdateTask instance, and;
494 // 3. Post this task to the file thread.
495 class JumpListUpdateTask : public Task {
496 public:
497 JumpListUpdateTask(const wchar_t* app_id,
498 const FilePath& icon_dir,
499 const ShellLinkItemList& most_visited_pages,
500 const ShellLinkItemList& recently_closed_pages)
501 : app_id_(app_id),
502 icon_dir_(icon_dir),
503 most_visited_pages_(most_visited_pages),
504 recently_closed_pages_(recently_closed_pages) {
505 }
506
507 private:
508 // Represents an entry point of this task.
509 // When we post this task to a file thread, the thread calls this function.
510 void Run();
511
512 // App id to associate with the jump list.
513 std::wstring app_id_;
514
515 // The directory which contains JumpList icons.
516 FilePath icon_dir_;
517
518 // Items in the "Most Visited" category of the application JumpList.
519 ShellLinkItemList most_visited_pages_;
520
521 // Items in the "Recently Closed" category of the application JumpList.
522 ShellLinkItemList recently_closed_pages_;
523 };
524
525 void JumpListUpdateTask::Run() {
526 // Delete the directory which contains old icon files, rename the current
527 // icon directory, and create a new directory which contains new JumpList
528 // icon files.
529 FilePath icon_dir_old(icon_dir_.value() + L"Old");
530 if (file_util::PathExists(icon_dir_old))
531 file_util::Delete(icon_dir_old, true);
532 file_util::Move(icon_dir_, icon_dir_old);
533 file_util::CreateDirectory(icon_dir_);
534
535 // Create temporary icon files for shortcuts in the "Most Visited" category.
536 for (ShellLinkItemList::const_iterator item = most_visited_pages_.begin();
537 item != most_visited_pages_.end(); ++item) {
538 SkBitmap icon_bitmap;
539 if ((*item)->data().get() &&
540 gfx::PNGCodec::Decode((*item)->data()->front(),
541 (*item)->data()->size(),
542 &icon_bitmap)) {
543 FilePath icon_path;
544 if (CreateIconFile(icon_bitmap, icon_dir_, &icon_path))
545 (*item)->SetIcon(icon_path.value(), 0, true);
546 }
547 }
548
549 // Create temporary icon files for shortcuts in the "Recently Closed"
550 // category.
551 for (ShellLinkItemList::const_iterator item = recently_closed_pages_.begin();
552 item != recently_closed_pages_.end(); ++item) {
553 SkBitmap icon_bitmap;
554 if ((*item)->data().get() &&
555 gfx::PNGCodec::Decode((*item)->data()->front(),
556 (*item)->data()->size(),
557 &icon_bitmap)) {
558 FilePath icon_path;
559 if (CreateIconFile(icon_bitmap, icon_dir_, &icon_path))
560 (*item)->SetIcon(icon_path.value(), 0, true);
561 }
562 }
563
564 // We finished collecting all resources needed for updating an appliation
565 // JumpList. So, create a new JumpList and replace the current JumpList
566 // with it.
567 UpdateJumpList(app_id_.c_str(), most_visited_pages_, recently_closed_pages_);
568
569 // Delete all items in these lists now since we don't need the ShellLinkItem
570 // objects in these lists.
571 most_visited_pages_.clear();
572 recently_closed_pages_.clear();
573 }
574
575 } // namespace 482 } // namespace
576 483
577 JumpList::JumpList() : profile_(NULL) { 484 JumpList::JumpList():handle_(NULL) {
MAD 2011/08/15 16:16:16 We should still set the profile to NULL here...
578 } 485 }
579 486
580 JumpList::~JumpList() { 487 JumpList::~JumpList() {
581 RemoveObserver(); 488 RemoveObserver();
582 } 489 }
583 490
584 // static 491 // static
585 bool JumpList::Enabled() { 492 bool JumpList::Enabled() {
586 return (base::win::GetVersion() >= base::win::VERSION_WIN7 && 493 return (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
587 !CommandLine::ForCurrentProcess()->HasSwitch( 494 !CommandLine::ForCurrentProcess()->HasSwitch(
(...skipping 10 matching lines...) Expand all
598 return false; 505 return false;
599 506
600 TabRestoreService* tab_restore_service = 507 TabRestoreService* tab_restore_service =
601 TabRestoreServiceFactory::GetForProfile(profile); 508 TabRestoreServiceFactory::GetForProfile(profile);
602 if (!tab_restore_service) 509 if (!tab_restore_service)
603 return false; 510 return false;
604 511
605 app_id_ = ShellIntegration::GetChromiumAppId(profile->GetPath()); 512 app_id_ = ShellIntegration::GetChromiumAppId(profile->GetPath());
606 icon_dir_ = profile->GetPath().Append(chrome::kJumpListIconDirname); 513 icon_dir_ = profile->GetPath().Append(chrome::kJumpListIconDirname);
607 profile_ = profile; 514 profile_ = profile;
515 history::TopSites* top_sites = profile_->GetTopSites();
516 if (top_sites) {
517 // TopSites updates itself after a delay. This is especially noticable when
518 // your profile is empty. Ask TopSites to update itself when we're about to
519 // show the new tab page.
520 top_sites->SyncWithHistory();
521 // Register for notification when TopSites changes so that we can update
522 // ourself.
523 registrar_.Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED,
524 Source<history::TopSites>(top_sites));
525 }
608 tab_restore_service->AddObserver(this); 526 tab_restore_service->AddObserver(this);
609 return true; 527 return true;
610 } 528 }
611 529
530 void JumpList::Observe(int type,
531 const NotificationSource& source,
532 const NotificationDetails& details) {
533 DCHECK_EQ(type, chrome::NOTIFICATION_TOP_SITES_CHANGED);
534
535 // Most visited urls changed, query again.
536 StartQueryForTopSites();
537 }
538
612 void JumpList::RemoveObserver() { 539 void JumpList::RemoveObserver() {
613 if (profile_) { 540 if (profile_) {
614 TabRestoreService* tab_restore_service = 541 TabRestoreService* tab_restore_service =
615 TabRestoreServiceFactory::GetForProfile(profile_); 542 TabRestoreServiceFactory::GetForProfile(profile_);
616 if (tab_restore_service) 543 if (tab_restore_service)
617 tab_restore_service->RemoveObserver(this); 544 tab_restore_service->RemoveObserver(this);
618 } 545 }
619 profile_ = NULL; 546 profile_ = NULL;
620 } 547 }
621 548
549 void JumpList::StartQueryForTopSites() {
MAD 2011/08/15 16:16:16 I think this code is small enough and unlikely to
550 history::TopSites* top_sites = profile_->GetTopSites();
551 if (top_sites) {
552 top_sites->GetMostVisitedURLs(
553 &topsites_consumer_,
554 NewCallback(this, &JumpList::OnMostVisitedURLsAvailable));
555 }
556 }
557
558 void JumpList::OnMostVisitedURLsAvailable(
559 const history::MostVisitedURLList& data) {
560
561 // If we have a pending favicon request, cancel it here (it is out of date).
562 if (handle_) {
563 FaviconService* favicon_service =
564 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
565 favicon_service->CancelRequest(handle_);
566 handle_ = NULL;
567 }
568
569 {
570 base::AutoLock auto_lock(list_lock_);
571 most_visited_pages_.clear();
572 for (size_t i = 0; i < data.size(); i++) {
573 const history::MostVisitedURL& url = data[i];
574 scoped_refptr<ShellLinkItem> link(new ShellLinkItem);
575 std::string url_string = url.url.spec();
576 link->SetArguments(UTF8ToWide(url_string));
577 link->SetTitle(!url.title.empty()? url.title : link->arguments());
578 most_visited_pages_.push_back(link);
579 icon_urls_.push_back(make_pair(url_string, link));
580 }
581 }
582
583 // Send a query that retrieves the first favicon.
584 StartLoadingFavicon();
585 }
586
622 void JumpList::TabRestoreServiceChanged(TabRestoreService* service) { 587 void JumpList::TabRestoreServiceChanged(TabRestoreService* service) {
623 // Added or removed a tab. 588 // if we have a pending handle request, cancel it here (it is out of date).
624 // Exit if we are updating the application JumpList. 589 if (handle_) {
625 if (!icon_urls_.empty()) 590 FaviconService* favicon_service =
MAD 2011/08/15 16:16:16 Maybe extract this common code to a method...
626 return; 591 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
592 favicon_service->CancelRequest(handle_);
593 handle_ = NULL;
594 }
627 595
628 // Send a query to HistoryService and retrieve the "Most Visited" pages. 596 {
629 // This code is copied from MostVisitedHandler::HandleGetMostVisited() to 597 base::AutoLock auto_lock(list_lock_);
630 // emulate its behaviors. 598 recently_closed_pages_.clear();
MAD 2011/08/15 16:16:16 I'm a it uncomfortable with the isolated locks her
631 const int kMostVisitedScope = 90; 599 }
632 const int kMostVisitedCount = 9; 600
633 int result_count = kMostVisitedCount; 601 // Create a list of ShellLinkItems from the "Recently Closed" pages.
634 HistoryService* history_service = 602 // As noted above, we create a ShellLinkItem objects with the following
635 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 603 // parameters.
636 history_service->QuerySegmentUsageSince( 604 // * arguments
637 &most_visited_consumer_, 605 // The last URL of the tab object.
638 base::Time::Now() - base::TimeDelta::FromDays(kMostVisitedScope), 606 // * title
639 result_count, 607 // The title of the last URL.
640 NewCallback(this, &JumpList::OnSegmentUsageAvailable)); 608 // * icon
609 // An empty string. This value is to be updated in OnFaviconDataAvailable().
610 // This code is copied from
611 // RecentlyClosedTabsHandler::TabRestoreServiceChanged() to emulate it.
612 const int kRecentlyClosedCount = 4;
613 TabRestoreService* tab_restore_service =
614 TabRestoreServiceFactory::GetForProfile(profile_);
615 const TabRestoreService::Entries& entries = tab_restore_service->entries();
616 for (TabRestoreService::Entries::const_iterator it = entries.begin();
617 it != entries.end(); ++it) {
618 const TabRestoreService::Entry* entry = *it;
619 if (entry->type == TabRestoreService::TAB) {
620 AddTab(static_cast<const TabRestoreService::Tab*>(entry),
621 kRecentlyClosedCount);
622 } else if (entry->type == TabRestoreService::WINDOW) {
623 AddWindow(static_cast<const TabRestoreService::Window*>(entry),
624 kRecentlyClosedCount);
625 }
626 }
627
628 // Send a query that retrieves the first favicon.
629 StartLoadingFavicon();
641 } 630 }
642 631
643 void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) { 632 void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) {
644 } 633 }
645 634
646 bool JumpList::AddTab(const TabRestoreService::Tab* tab, 635 bool JumpList::AddTab(const TabRestoreService::Tab* tab, size_t max_items) {
647 ShellLinkItemList* list,
648 size_t max_items) {
649 // This code adds the URL and the title strings of the given tab to the 636 // This code adds the URL and the title strings of the given tab to the
650 // specified list. 637 // specified list.
651 // This code is copied from RecentlyClosedTabsHandler::TabToValue(). 638 // This code is copied from RecentlyClosedTabsHandler::TabToValue().
652 if (tab->navigations.empty() || list->size() >= max_items) 639 base::AutoLock auto_lock(list_lock_);
640 if (tab->navigations.empty() || recently_closed_pages_.size() >= max_items)
MAD 2011/08/15 16:16:16 If we would keep this within a lock (which we migh
653 return false; 641 return false;
654 642
655 const TabNavigation& current_navigation = 643 const TabNavigation& current_navigation =
656 tab->navigations.at(tab->current_navigation_index); 644 tab->navigations.at(tab->current_navigation_index);
657 if (current_navigation.virtual_url() == GURL(chrome::kChromeUINewTabURL)) 645 if (current_navigation.virtual_url() == GURL(chrome::kChromeUINewTabURL))
658 return false; 646 return false;
659 647
660 scoped_refptr<ShellLinkItem> link(new ShellLinkItem); 648 scoped_refptr<ShellLinkItem> link(new ShellLinkItem);
661 std::string url = current_navigation.virtual_url().spec(); 649 std::string url = current_navigation.virtual_url().spec();
MAD 2011/08/15 16:16:16 Not sure if it is safe to call virtual_url on the
662 link->SetArguments(UTF8ToWide(url)); 650 link->SetArguments(UTF8ToWide(url));
663 link->SetTitle(current_navigation.title()); 651 link->SetTitle(current_navigation.title());
664 list->push_back(link); 652 recently_closed_pages_.push_back(link);
665 icon_urls_.push_back(make_pair(url, link)); 653 icon_urls_.push_back(make_pair(url, link));
666 return true; 654 return true;
667 } 655 }
668 656
669 bool JumpList::AddWindow(const TabRestoreService::Window* window, 657 bool JumpList::AddWindow(const TabRestoreService::Window* window,
670 ShellLinkItemList* list,
671 size_t max_items) { 658 size_t max_items) {
672 // This code enumerates al the tabs in the given window object and add their 659 // This code enumerates al the tabs in the given window object and add their
673 // URLs and titles to the list. 660 // URLs and titles to the list.
674 // This code is copied from RecentlyClosedTabsHandler::WindowToValue(). 661 // This code is copied from RecentlyClosedTabsHandler::WindowToValue().
675 if (window->tabs.empty()) { 662 if (window->tabs.empty()) {
676 NOTREACHED(); 663 NOTREACHED();
677 return false; 664 return false;
678 } 665 }
679 for (size_t i = 0; i < window->tabs.size(); ++i) { 666 for (size_t i = 0; i < window->tabs.size(); ++i) {
680 if (!AddTab(&window->tabs[i], list, max_items)) 667 if (!AddTab(&window->tabs[i], max_items))
681 return false; 668 return false;
682 } 669 }
683 670
684 return true; 671 return true;
685 } 672 }
686 673
687 bool JumpList::StartLoadingFavicon() { 674 bool JumpList::StartLoadingFavicon() {
688 if (icon_urls_.empty()) 675 {
689 return false; 676 base::AutoLock auto_lock(list_lock_);
677 if (icon_urls_.empty())
678 return false;
679 }
690 680
691 // Ask FaviconService if it has a favicon of a URL. 681 // Ask FaviconService if it has a favicon of a URL.
692 // When FaviconService has one, it will call OnFaviconDataAvailable(). 682 // When FaviconService has one, it will call OnFaviconDataAvailable().
693 GURL url(icon_urls_.front().first); 683 GURL url;
684 {
685 base::AutoLock auto_lock(list_lock_);
686 url = GURL(icon_urls_.front().first);
687 }
694 FaviconService* favicon_service = 688 FaviconService* favicon_service =
695 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS); 689 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
696 FaviconService::Handle handle = favicon_service->GetFaviconForURL( 690 handle_ = favicon_service->GetFaviconForURL(
697 url, history::FAVICON, &favicon_consumer_, 691 url, history::FAVICON, &favicon_consumer_,
698 NewCallback(this, &JumpList::OnFaviconDataAvailable)); 692 NewCallback(this, &JumpList::OnFaviconDataAvailable));
699 return true; 693 return true;
700 } 694 }
701 695
702 void JumpList::OnSegmentUsageAvailable(
703 CancelableRequestProvider::Handle handle,
704 std::vector<PageUsageData*>* data) {
705 // Create a list of ShellLinkItem objects from the given list of
706 // PageUsageData objects.
707 // The command that opens a web page with chrome is:
708 // "chrome.exe <url-to-the-web-page>".
709 // So, we create a ShellLinkItem object with the following parameters.
710 // * arguments
711 // The URL of a PageUsagedata object (converted to std::wstring).
712 // * title
713 // The title of a PageUsageData object. If this string is empty, we use
714 // the URL as our "Most Visited" page does.
715 // * icon
716 // An empty string. This value is to be updated in OnFaviconDataAvailable().
717 most_visited_pages_.clear();
718 for (std::vector<PageUsageData*>::const_iterator page = data->begin();
719 page != data->end(); ++page) {
720 scoped_refptr<ShellLinkItem> link(new ShellLinkItem);
721 std::string url = (*page)->GetURL().spec();
722 link->SetArguments(UTF8ToWide(url));
723 link->SetTitle(
724 !(*page)->GetTitle().empty() ? (*page)->GetTitle() : link->arguments());
725 most_visited_pages_.push_back(link);
726 icon_urls_.push_back(make_pair(url, link));
727 }
728
729 // Create a list of ShellLinkItems from the "Recently Closed" pages.
730 // As noted above, we create a ShellLinkItem objects with the following
731 // parameters.
732 // * arguments
733 // The last URL of the tab object.
734 // * title
735 // The title of the last URL.
736 // * icon
737 // An empty string. This value is to be updated in OnFaviconDataAvailable().
738 // This code is copied from
739 // RecentlyClosedTabsHandler::TabRestoreServiceChanged() to emulate it.
740 const int kRecentlyClosedCount = 4;
741 recently_closed_pages_.clear();
742 TabRestoreService* tab_restore_service =
743 TabRestoreServiceFactory::GetForProfile(profile_);
744 const TabRestoreService::Entries& entries = tab_restore_service->entries();
745 for (TabRestoreService::Entries::const_iterator it = entries.begin();
746 it != entries.end(); ++it) {
747 const TabRestoreService::Entry* entry = *it;
748 if (entry->type == TabRestoreService::TAB) {
749 AddTab(static_cast<const TabRestoreService::Tab*>(entry),
750 &recently_closed_pages_, kRecentlyClosedCount);
751 } else if (entry->type == TabRestoreService::WINDOW) {
752 AddWindow(static_cast<const TabRestoreService::Window*>(entry),
753 &recently_closed_pages_, kRecentlyClosedCount);
754 }
755 }
756
757 // Send a query that retrieves the first favicon.
758 StartLoadingFavicon();
759 }
760
761 void JumpList::OnFaviconDataAvailable( 696 void JumpList::OnFaviconDataAvailable(
762 FaviconService::Handle handle, 697 FaviconService::Handle handle,
763 history::FaviconData favicon) { 698 history::FaviconData favicon) {
764 // Attach the received data to the ShellLinkItem object. 699 // If there is currently an favicon request in progress, it is now outdated,
MAD 2011/08/15 16:16:16 an favicon -> a favicon
765 // This data will be decoded by JumpListUpdateTask. 700 // as we have received another, so nullify the handle from the old request.
766 if (favicon.is_valid()) { 701 handle_ = NULL;
767 if (!icon_urls_.empty() && icon_urls_.front().second) 702 // lock the list to set icon data and pop the url
768 icon_urls_.front().second->SetIconData(favicon.image_data); 703 {
704 base::AutoLock auto_lock(list_lock_);
705 // Attach the received data to the ShellLinkItem object.
706 // This data will be decoded by the RunUpdate method.
707 if (favicon.is_valid()) {
708 if (!icon_urls_.empty() && icon_urls_.front().second)
709 icon_urls_.front().second->SetIconData(favicon.image_data);
710 }
711
712 if (!icon_urls_.empty())
713 icon_urls_.pop_front();
769 } 714 }
770
771 // if we need to load more favicons, we send another query and exit. 715 // if we need to load more favicons, we send another query and exit.
772 if (!icon_urls_.empty())
773 icon_urls_.pop_front();
774 if (StartLoadingFavicon()) 716 if (StartLoadingFavicon())
775 return; 717 return;
776 718
777 // Finished loading all favicons needed by the application JumpList. 719 // Finished loading all favicons needed by the application JumpList.
778 // We create a JumpListUpdateTask that creates icon files, and we post it to 720 // We create a RunnableMethod that creates icon files, and we post it to
MAD 2011/08/15 16:16:16 We don't actually "create" a runnable method...
779 // the file thread. 721 // the file thread.
722 this->AddRef();
MAD 2011/08/15 16:16:16 Do we need this??? If so, please add a comment...
Cait (Slow) 2011/08/15 19:44:45 We *shouldn't* need this (I think RunnableMethod h
780 BrowserThread::PostTask( 723 BrowserThread::PostTask(
781 BrowserThread::FILE, FROM_HERE, 724 BrowserThread::FILE, FROM_HERE,
782 new JumpListUpdateTask(app_id_.c_str(), icon_dir_, most_visited_pages_, 725 NewRunnableMethod(this, &JumpList::RunUpdate));
MAD 2011/08/15 16:16:16 Alignment should be kept as it was, i.e., at the s
783 recently_closed_pages_)); 726 }
784 727
785 // Delete all items in these lists since we don't need these lists any longer. 728 void JumpList::RunUpdate() {
786 most_visited_pages_.clear(); 729 ShellLinkItemList local_most_visited_pages;
787 recently_closed_pages_.clear(); 730 ShellLinkItemList local_recently_closed_pages;
731
732 {
733 base::AutoLock auto_lock(list_lock_);
734 // Make sure we are not out of date: if icon_urls_ is not empty, then
735 // another notification has been received since we processed this one
736 if (!icon_urls_.empty())
737 return;
738
739 // Make local copies of lists so we can release the lock.
740 local_most_visited_pages = most_visited_pages_;
741 local_recently_closed_pages = recently_closed_pages_;
742 }
743
744 // Delete the directory which contains old icon files, rename the current
745 // icon directory, and create a new directory which contains new JumpList
746 // icon files.
747 FilePath icon_dir_old(icon_dir_.value() + L"Old");
748 if (file_util::PathExists(icon_dir_old))
749 file_util::Delete(icon_dir_old, true);
750 file_util::Move(icon_dir_, icon_dir_old);
751 file_util::CreateDirectory(icon_dir_);
752
753 // Create temporary icon files for shortcuts in the "Most Visited" category.
754 DecodeIconData(local_most_visited_pages);
755
756 // Create temporary icon files for shortcuts in the "Recently Closed"
757 // category.
758 DecodeIconData(local_recently_closed_pages);
759
760 // We finished collecting all resources needed for updating an appliation
761 // JumpList. So, create a new JumpList and replace the current JumpList
762 // with it.
763 UpdateJumpList(app_id_.c_str(), local_most_visited_pages,
764 local_recently_closed_pages);
788 } 765 }
766
767 void JumpList::DecodeIconData(const ShellLinkItemList& item_list) {
768 for (ShellLinkItemList::const_iterator item = item_list.begin();
769 item != item_list.end(); ++item) {
MAD 2011/08/15 16:16:16 indent two more spaces please...
MAD 2011/08/15 21:52:42 You missed this one too...
770 SkBitmap icon_bitmap;
771 if ((*item)->data().get() &&
772 gfx::PNGCodec::Decode((*item)->data()->front(),
773 (*item)->data()->size(),
774 &icon_bitmap)) {
775 FilePath icon_path;
776 if (CreateIconFile(icon_bitmap, icon_dir_, &icon_path))
777 (*item)->SetIcon(icon_path.value(), 0, true);
778 }
779 }
780 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698