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

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()
485 :handle_(NULL) {
MAD 2011/08/05 21:21:43 Single line...
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(
588 switches::kDisableCustomJumpList)); 496 switches::kDisableCustomJumpList));
589 } 497 }
590 498
591 bool JumpList::AddObserver(Profile* profile) { 499 bool JumpList::AddObserver(Profile* profile) {
592 // To update JumpList when a tab is added or removed, we add this object to 500 // To update JumpList when a tab is added or removed, we add this object to
593 // the observer list of the TabRestoreService class. 501 // the observer list of the TabRestoreService class.
594 // When we add this object to the observer list, we save the pointer to this 502 // When we add this object to the observer list, we save the pointer to this
595 // TabRestoreService object. This pointer is used when we remove this object 503 // TabRestoreService object. This pointer is used when we remove this object
596 // from the observer list. 504 // from the observer list.
597 if (base::win::GetVersion() < base::win::VERSION_WIN7 || !profile) 505 if (base::win::GetVersion() < base::win::VERSION_WIN7 || !profile)
598 return false; 506 return false;
599 507 profile_ = profile;
MAD 2011/08/05 21:21:43 No need to move that up anymore, might as well put
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 history::TopSites* ts = profile_->GetTopSites();
MAD 2011/08/05 21:21:43 I would prefer a more meaningful variable name tha
516 if (ts) {
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 ts->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>(ts));
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.
MAD 2011/08/05 21:21:43 Most visited -> Top sites
536 StartQueryForMostVisited();
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::StartQueryForMostVisited() {
550 history::TopSites* ts = profile_->GetTopSites();
MAD 2011/08/05 21:21:43 Again, ts -> top_sites, please... :-)
551 if (ts) {
552 ts->GetMostVisitedURLs(
553 &topsites_consumer_,
554 NewCallback(this,
555 &JumpList::OnMostVisitedURLsAvailable));
Evan Stade 2011/08/05 20:39:03 too much indent. Can this fit on the line above?
556 }
557 }
558
559 void JumpList::OnMostVisitedURLsAvailable(
560 const history::MostVisitedURLList& data) {
561
562 // If we have a pending favicon request, cancel it here (it is out of date).
563 if (handle_) {
564 FaviconService* favicon_service =
565 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
MAD 2011/08/05 21:21:43 Need 4 more spaces of indent...
566 favicon_service->CancelRequest(handle_);
567 handle_ = NULL;
568 }
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 if (handle_) {
625 if (!icon_urls_.empty()) 591 FaviconService* favicon_service =
626 return; 592 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
MAD 2011/08/05 21:21:43 Again, 4 more indent spaces please...
593 favicon_service->CancelRequest(handle_);
594 handle_ = NULL;
595 }
627 596
628 // Send a query to HistoryService and retrieve the "Most Visited" pages. 597 {
629 // This code is copied from MostVisitedHandler::HandleGetMostVisited() to 598 base::AutoLock auto_lock(list_lock_);
630 // emulate its behaviors. 599 recently_closed_pages_.clear();
631 const int kMostVisitedScope = 90; 600 }
632 const int kMostVisitedCount = 9; 601
633 int result_count = kMostVisitedCount; 602 // Create a list of ShellLinkItems from the "Recently Closed" pages.
634 HistoryService* history_service = 603 // As noted above, we create a ShellLinkItem objects with the following
635 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 604 // parameters.
636 history_service->QuerySegmentUsageSince( 605 // * arguments
637 &most_visited_consumer_, 606 // The last URL of the tab object.
638 base::Time::Now() - base::TimeDelta::FromDays(kMostVisitedScope), 607 // * title
639 result_count, 608 // The title of the last URL.
640 NewCallback(this, &JumpList::OnSegmentUsageAvailable)); 609 // * icon
610 // An empty string. This value is to be updated in OnFaviconDataAvailable().
611 // This code is copied from
612 // RecentlyClosedTabsHandler::TabRestoreServiceChanged() to emulate it.
613 const int kRecentlyClosedCount = 4;
614 TabRestoreService* tab_restore_service =
615 TabRestoreServiceFactory::GetForProfile(profile_);
616 const TabRestoreService::Entries& entries = tab_restore_service->entries();
617 for (TabRestoreService::Entries::const_iterator it = entries.begin();
618 it != entries.end(); ++it) {
619 const TabRestoreService::Entry* entry = *it;
620 if (entry->type == TabRestoreService::TAB) {
621 AddTab(static_cast<const TabRestoreService::Tab*>(entry),
622 &recently_closed_pages_, kRecentlyClosedCount);
MAD 2011/08/05 21:21:43 I'm not comfortable passing the pointers to protec
623 } else if (entry->type == TabRestoreService::WINDOW) {
624 AddWindow(static_cast<const TabRestoreService::Window*>(entry),
625 &recently_closed_pages_, kRecentlyClosedCount);
626 }
627 }
628
629 // Send a query that retrieves the first favicon.
630 StartLoadingFavicon();
641 } 631 }
642 632
643 void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) { 633 void JumpList::TabRestoreServiceDestroyed(TabRestoreService* service) {
644 } 634 }
645 635
646 bool JumpList::AddTab(const TabRestoreService::Tab* tab, 636 bool JumpList::AddTab(const TabRestoreService::Tab* tab,
647 ShellLinkItemList* list, 637 ShellLinkItemList* list,
648 size_t max_items) { 638 size_t max_items) {
649 // This code adds the URL and the title strings of the given tab to the 639 // This code adds the URL and the title strings of the given tab to the
650 // specified list. 640 // specified list.
651 // This code is copied from RecentlyClosedTabsHandler::TabToValue(). 641 // This code is copied from RecentlyClosedTabsHandler::TabToValue().
642 base::AutoLock auto_lock(list_lock_);
652 if (tab->navigations.empty() || list->size() >= max_items) 643 if (tab->navigations.empty() || list->size() >= max_items)
653 return false; 644 return false;
654 645
655 const TabNavigation& current_navigation = 646 const TabNavigation& current_navigation =
656 tab->navigations.at(tab->current_navigation_index); 647 tab->navigations.at(tab->current_navigation_index);
657 if (current_navigation.virtual_url() == GURL(chrome::kChromeUINewTabURL)) 648 if (current_navigation.virtual_url() == GURL(chrome::kChromeUINewTabURL))
658 return false; 649 return false;
659 650
660 scoped_refptr<ShellLinkItem> link(new ShellLinkItem); 651 scoped_refptr<ShellLinkItem> link(new ShellLinkItem);
661 std::string url = current_navigation.virtual_url().spec(); 652 std::string url = current_navigation.virtual_url().spec();
(...skipping 16 matching lines...) Expand all
678 } 669 }
679 for (size_t i = 0; i < window->tabs.size(); ++i) { 670 for (size_t i = 0; i < window->tabs.size(); ++i) {
680 if (!AddTab(&window->tabs[i], list, max_items)) 671 if (!AddTab(&window->tabs[i], list, max_items))
681 return false; 672 return false;
682 } 673 }
683 674
684 return true; 675 return true;
685 } 676 }
686 677
687 bool JumpList::StartLoadingFavicon() { 678 bool JumpList::StartLoadingFavicon() {
679 // Ask FaviconService if it has a favicon of a URL.
MAD 2011/08/05 21:21:43 I would bring back this comment where it was...
680 // When FaviconService has one, it will call OnFaviconDataAvailable().
688 if (icon_urls_.empty()) 681 if (icon_urls_.empty())
MAD 2011/08/05 21:21:43 Even though this is atomic, I would prefer we did
689 return false; 682 return false;
690 683
691 // Ask FaviconService if it has a favicon of a URL. 684 GURL url;
692 // When FaviconService has one, it will call OnFaviconDataAvailable(). 685 {
693 GURL url(icon_urls_.front().first); 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 handle_ = NULL;
MAD 2011/08/05 21:21:43 Maybe add a comment to specify why we do this?
765 // This data will be decoded by JumpListUpdateTask. 701 // lock the list to set icon data and pop the url
766 if (favicon.is_valid()) { 702 {
767 if (!icon_urls_.empty() && icon_urls_.front().second) 703 base::AutoLock auto_lock(list_lock_);
768 icon_urls_.front().second->SetIconData(favicon.image_data); 704 // Attach the received data to the ShellLinkItem object.
705 // This data will be decoded by JumpListUpdateTask.
Evan Stade 2011/08/05 20:39:03 comment out of date
706 if (favicon.is_valid()) {
707 if (!icon_urls_.empty() && icon_urls_.front().second)
708 icon_urls_.front().second->SetIconData(favicon.image_data);
709 }
710
711 if (!icon_urls_.empty())
712 icon_urls_.pop_front();
769 } 713 }
770
771 // if we need to load more favicons, we send another query and exit. 714 // 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()) 715 if (StartLoadingFavicon())
775 return; 716 return;
776 717
777 // Finished loading all favicons needed by the application JumpList. 718 // Finished loading all favicons needed by the application JumpList.
778 // We create a JumpListUpdateTask that creates icon files, and we post it to 719 // We create a RunnableMethod that creates icon files, and we post it to
779 // the file thread. 720 // the file thread.
721 this->AddRef();
MAD 2011/08/05 21:21:43 Please add a comment stating who/where will releas
Cait (Slow) 2011/08/05 22:49:16 Actually..this AddRef is not supposed to be here..
780 BrowserThread::PostTask( 722 BrowserThread::PostTask(
781 BrowserThread::FILE, FROM_HERE, 723 BrowserThread::FILE, FROM_HERE,
782 new JumpListUpdateTask(app_id_.c_str(), icon_dir_, most_visited_pages_, 724 NewRunnableMethod(this, &JumpList::RunUpdate));
783 recently_closed_pages_)); 725 }
784 726
785 // Delete all items in these lists since we don't need these lists any longer. 727 void JumpList::RunUpdate() {
786 most_visited_pages_.clear(); 728 ShellLinkItemList local_most_visited_pages;
787 recently_closed_pages_.clear(); 729 ShellLinkItemList local_recently_closed_pages;
Evan Stade 2011/08/05 20:39:03 please sprinkle in some newlines for readability
730 {
731 base::AutoLock auto_lock(list_lock_);
732 // Make sure we are not out of date: if icon_urls_ is not empty, then
733 // another notification has been received since we processed this one
734 if (!icon_urls_.empty())
735 return;
736 // Make local copies of lists so we can release the lock.
737 ShellLinkItemList temp_most_visited_pages(most_visited_pages_);
MAD 2011/08/05 21:21:43 Why do we need these temps? Can't we simply do: lo
Cait (Slow) 2011/08/05 22:49:16 The data member lists only get cleared immediately
738 ShellLinkItemList temp_recently_closed_pages(recently_closed_pages_);
739 local_most_visited_pages = temp_most_visited_pages;
740 local_recently_closed_pages = temp_recently_closed_pages;
741 }
742 // Delete the directory which contains old icon files, rename the current
743 // icon directory, and create a new directory which contains new JumpList
744 // icon files.
745 FilePath icon_dir_old(icon_dir_.value() + L"Old");
746 if (file_util::PathExists(icon_dir_old))
747 file_util::Delete(icon_dir_old, true);
748 file_util::Move(icon_dir_, icon_dir_old);
749 file_util::CreateDirectory(icon_dir_);
750
751 // Create temporary icon files for shortcuts in the "Most Visited" category.
752 for (ShellLinkItemList::const_iterator item = local_most_visited_pages.begin() ;
Evan Stade 2011/08/05 20:39:03 80
753 item != local_most_visited_pages.end(); ++item) {
754 SkBitmap icon_bitmap;
755 if ((*item)->data().get() &&
756 gfx::PNGCodec::Decode((*item)->data()->front(),
757 (*item)->data()->size(),
758 &icon_bitmap)) {
759 FilePath icon_path;
760 if (CreateIconFile(icon_bitmap, icon_dir_, &icon_path))
761 (*item)->SetIcon(icon_path.value(), 0, true);
762 }
763 }
764
765 // Create temporary icon files for shortcuts in the "Recently Closed"
766 // category.
767 for (ShellLinkItemList::const_iterator item = local_recently_closed_pages.begi n();
Evan Stade 2011/08/05 20:39:03 80
768 item != local_recently_closed_pages.end(); ++item) {
769 SkBitmap icon_bitmap;
770 if ((*item)->data().get() &&
771 gfx::PNGCodec::Decode((*item)->data()->front(),
772 (*item)->data()->size(),
773 &icon_bitmap)) {
774 FilePath icon_path;
775 if (CreateIconFile(icon_bitmap, icon_dir_, &icon_path))
776 (*item)->SetIcon(icon_path.value(), 0, true);
Evan Stade 2011/08/05 20:39:03 refactor this loop into helper function (it seems
777 }
778 }
779
780 // We finished collecting all resources needed for updating an appliation
781 // JumpList. So, create a new JumpList and replace the current JumpList
782 // with it.
783 UpdateJumpList(app_id_.c_str(), local_most_visited_pages,
784 local_recently_closed_pages);
788 } 785 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698