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

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
« no previous file with comments | « chrome/browser/jumplist_win.h ('k') | chrome/browser/ui/views/frame/browser_view.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(): profile_(NULL)
485 , handle_(NULL) {
MAD 2011/08/15 21:52:42 fits on a single line... otherwise, we prefer this
578 } 486 }
579 487
580 JumpList::~JumpList() { 488 JumpList::~JumpList() {
581 RemoveObserver(); 489 RemoveObserver();
582 } 490 }
583 491
584 // static 492 // static
585 bool JumpList::Enabled() { 493 bool JumpList::Enabled() {
586 return (base::win::GetVersion() >= base::win::VERSION_WIN7 && 494 return (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
587 !CommandLine::ForCurrentProcess()->HasSwitch( 495 !CommandLine::ForCurrentProcess()->HasSwitch(
(...skipping 10 matching lines...) Expand all
598 return false; 506 return false;
599 507
600 TabRestoreService* tab_restore_service = 508 TabRestoreService* tab_restore_service =
601 TabRestoreServiceFactory::GetForProfile(profile); 509 TabRestoreServiceFactory::GetForProfile(profile);
602 if (!tab_restore_service) 510 if (!tab_restore_service)
603 return false; 511 return false;
604 512
605 app_id_ = ShellIntegration::GetChromiumAppId(profile->GetPath()); 513 app_id_ = ShellIntegration::GetChromiumAppId(profile->GetPath());
606 icon_dir_ = profile->GetPath().Append(chrome::kJumpListIconDirname); 514 icon_dir_ = profile->GetPath().Append(chrome::kJumpListIconDirname);
607 profile_ = profile; 515 profile_ = profile;
516 history::TopSites* top_sites = profile_->GetTopSites();
517 if (top_sites) {
518 // TopSites updates itself after a delay. This is especially noticable when
519 // your profile is empty. Ask TopSites to update itself when we're about to
520 // show the new tab page.
521 top_sites->SyncWithHistory();
522 // Register for notification when TopSites changes so that we can update
523 // ourself.
524 registrar_.Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED,
525 Source<history::TopSites>(top_sites));
526 }
608 tab_restore_service->AddObserver(this); 527 tab_restore_service->AddObserver(this);
609 return true; 528 return true;
610 } 529 }
611 530
531 void JumpList::Observe(int type,
532 const NotificationSource& source,
533 const NotificationDetails& details) {
534 DCHECK_EQ(type, chrome::NOTIFICATION_TOP_SITES_CHANGED);
535
536 // Most visited urls changed, query again.
537 history::TopSites* top_sites = profile_->GetTopSites();
538 if (top_sites) {
539 top_sites->GetMostVisitedURLs(
540 &topsites_consumer_,
541 NewCallback(this, &JumpList::OnMostVisitedURLsAvailable));
542 }
543 }
544
612 void JumpList::RemoveObserver() { 545 void JumpList::RemoveObserver() {
613 if (profile_) { 546 if (profile_) {
614 TabRestoreService* tab_restore_service = 547 TabRestoreService* tab_restore_service =
615 TabRestoreServiceFactory::GetForProfile(profile_); 548 TabRestoreServiceFactory::GetForProfile(profile_);
616 if (tab_restore_service) 549 if (tab_restore_service)
617 tab_restore_service->RemoveObserver(this); 550 tab_restore_service->RemoveObserver(this);
618 } 551 }
619 profile_ = NULL; 552 profile_ = NULL;
620 } 553 }
621 554
555 void JumpList::CancelPendingUpdate() {
556 if (handle_) {
557 FaviconService* favicon_service =
558 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
559 favicon_service->CancelRequest(handle_);
560 handle_ = NULL;
561 }
562 }
563
564 void JumpList::OnMostVisitedURLsAvailable(
565 const history::MostVisitedURLList& data) {
566
567 // If we have a pending favicon request, cancel it here (it is out of date).
568 CancelPendingUpdate();
569
570 {
571 base::AutoLock auto_lock(list_lock_);
572 most_visited_pages_.clear();
573 for (size_t i = 0; i < data.size(); i++) {
574 const history::MostVisitedURL& url = data[i];
575 scoped_refptr<ShellLinkItem> link(new ShellLinkItem);
576 std::string url_string = url.url.spec();
577 link->SetArguments(UTF8ToWide(url_string));
578 link->SetTitle(!url.title.empty()? url.title : link->arguments());
579 most_visited_pages_.push_back(link);
580 icon_urls_.push_back(make_pair(url_string, link));
581 }
582 }
583
584 // Send a query that retrieves the first favicon.
585 StartLoadingFavicon();
586 }
587
622 void JumpList::TabRestoreServiceChanged(TabRestoreService* service) { 588 void JumpList::TabRestoreServiceChanged(TabRestoreService* service) {
623 // Added or removed a tab. 589 // if we have a pending handle request, cancel it here (it is out of date).
624 // Exit if we are updating the application JumpList. 590 CancelPendingUpdate();
625 if (!icon_urls_.empty())
626 return;
627 591
628 // Send a query to HistoryService and retrieve the "Most Visited" pages. 592 // local list to pass to methods
629 // This code is copied from MostVisitedHandler::HandleGetMostVisited() to 593 ShellLinkItemList temp_list;
630 // emulate its behaviors. 594
631 const int kMostVisitedScope = 90; 595 // Create a list of ShellLinkItems from the "Recently Closed" pages.
632 const int kMostVisitedCount = 9; 596 // As noted above, we create a ShellLinkItem objects with the following
633 int result_count = kMostVisitedCount; 597 // parameters.
634 HistoryService* history_service = 598 // * arguments
635 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 599 // The last URL of the tab object.
636 history_service->QuerySegmentUsageSince( 600 // * title
637 &most_visited_consumer_, 601 // The title of the last URL.
638 base::Time::Now() - base::TimeDelta::FromDays(kMostVisitedScope), 602 // * icon
639 result_count, 603 // An empty string. This value is to be updated in OnFaviconDataAvailable().
640 NewCallback(this, &JumpList::OnSegmentUsageAvailable)); 604 // This code is copied from
605 // RecentlyClosedTabsHandler::TabRestoreServiceChanged() to emulate it.
606 const int kRecentlyClosedCount = 4;
607 TabRestoreService* tab_restore_service =
608 TabRestoreServiceFactory::GetForProfile(profile_);
609 const TabRestoreService::Entries& entries = tab_restore_service->entries();
610 for (TabRestoreService::Entries::const_iterator it = entries.begin();
611 it != entries.end(); ++it) {
612 const TabRestoreService::Entry* entry = *it;
613 if (entry->type == TabRestoreService::TAB) {
614 AddTab(static_cast<const TabRestoreService::Tab*>(entry),
615 &temp_list, kRecentlyClosedCount);
616 } else if (entry->type == TabRestoreService::WINDOW) {
617 AddWindow(static_cast<const TabRestoreService::Window*>(entry),
618 &temp_list, kRecentlyClosedCount);
619 }
620 }
621 // Lock recently_closed_pages and copy temp_list into it.
622 {
623 base::AutoLock auto_lock(list_lock_);
624 recently_closed_pages_ = temp_list;
625 }
626
627 // Send a query that retrieves the first favicon.
628 StartLoadingFavicon();
641 } 629 }
642 630
643 void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) { 631 void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) {
644 } 632 }
645 633
646 bool JumpList::AddTab(const TabRestoreService::Tab* tab, 634 bool JumpList::AddTab(const TabRestoreService::Tab* tab,
647 ShellLinkItemList* list, 635 ShellLinkItemList* list,
648 size_t max_items) { 636 size_t max_items) {
649 // This code adds the URL and the title strings of the given tab to the 637 // This code adds the URL and the title strings of the given tab to the
650 // specified list. 638 // specified list.
(...skipping 27 matching lines...) Expand all
678 } 666 }
679 for (size_t i = 0; i < window->tabs.size(); ++i) { 667 for (size_t i = 0; i < window->tabs.size(); ++i) {
680 if (!AddTab(&window->tabs[i], list, max_items)) 668 if (!AddTab(&window->tabs[i], list, max_items))
681 return false; 669 return false;
682 } 670 }
683 671
684 return true; 672 return true;
685 } 673 }
686 674
687 bool JumpList::StartLoadingFavicon() { 675 bool JumpList::StartLoadingFavicon() {
688 if (icon_urls_.empty()) 676 {
689 return false; 677 base::AutoLock auto_lock(list_lock_);
678 if (icon_urls_.empty())
679 return false;
680 }
MAD 2011/08/15 21:52:42 I think we can merge these two locked blocks...
690 681
691 // Ask FaviconService if it has a favicon of a URL. 682 // Ask FaviconService if it has a favicon of a URL.
692 // When FaviconService has one, it will call OnFaviconDataAvailable(). 683 // When FaviconService has one, it will call OnFaviconDataAvailable().
693 GURL url(icon_urls_.front().first); 684 GURL url;
685 {
686 base::AutoLock auto_lock(list_lock_);
687 url = GURL(icon_urls_.front().first);
688 }
694 FaviconService* favicon_service = 689 FaviconService* favicon_service =
695 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS); 690 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
696 FaviconService::Handle handle = favicon_service->GetFaviconForURL( 691 handle_ = favicon_service->GetFaviconForURL(
697 url, history::FAVICON, &favicon_consumer_, 692 url, history::FAVICON, &favicon_consumer_,
698 NewCallback(this, &JumpList::OnFaviconDataAvailable)); 693 NewCallback(this, &JumpList::OnFaviconDataAvailable));
699 return true; 694 return true;
700 } 695 }
701 696
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( 697 void JumpList::OnFaviconDataAvailable(
762 FaviconService::Handle handle, 698 FaviconService::Handle handle,
763 history::FaviconData favicon) { 699 history::FaviconData favicon) {
764 // Attach the received data to the ShellLinkItem object. 700 // If there is currently a favicon request in progress, it is now outdated,
765 // This data will be decoded by JumpListUpdateTask. 701 // as we have received another, so nullify the handle from the old request.
766 if (favicon.is_valid()) { 702 handle_ = NULL;
767 if (!icon_urls_.empty() && icon_urls_.front().second) 703 // lock the list to set icon data and pop the url
768 icon_urls_.front().second->SetIconData(favicon.image_data); 704 {
705 base::AutoLock auto_lock(list_lock_);
706 // Attach the received data to the ShellLinkItem object.
707 // This data will be decoded by the RunUpdate method.
708 if (favicon.is_valid()) {
709 if (!icon_urls_.empty() && icon_urls_.front().second)
710 icon_urls_.front().second->SetIconData(favicon.image_data);
711 }
712
713 if (!icon_urls_.empty())
714 icon_urls_.pop_front();
769 } 715 }
770
771 // if we need to load more favicons, we send another query and exit. 716 // 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()) 717 if (StartLoadingFavicon())
775 return; 718 return;
776 719
777 // Finished loading all favicons needed by the application JumpList. 720 // Finished loading all favicons needed by the application JumpList.
778 // We create a JumpListUpdateTask that creates icon files, and we post it to 721 // We use a RunnableMethod that creates icon files, and we post it to
779 // the file thread. 722 // the file thread.
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));
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) {
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
« no previous file with comments | « chrome/browser/jumplist_win.h ('k') | chrome/browser/ui/views/frame/browser_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698