OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/gtk/location_bar_view_gtk.h" | 5 #include "chrome/browser/gtk/location_bar_view_gtk.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "app/gfx/canvas_paint.h" | 9 #include "app/gfx/canvas_paint.h" |
10 #include "app/gfx/gtk_util.h" | 10 #include "app/gfx/gtk_util.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "chrome/browser/gtk/rounded_window.h" | 26 #include "chrome/browser/gtk/rounded_window.h" |
27 #include "chrome/browser/profile.h" | 27 #include "chrome/browser/profile.h" |
28 #include "chrome/browser/search_engines/template_url.h" | 28 #include "chrome/browser/search_engines/template_url.h" |
29 #include "chrome/browser/search_engines/template_url_model.h" | 29 #include "chrome/browser/search_engines/template_url_model.h" |
30 #include "chrome/browser/tab_contents/tab_contents.h" | 30 #include "chrome/browser/tab_contents/tab_contents.h" |
31 #include "chrome/common/gtk_util.h" | 31 #include "chrome/common/gtk_util.h" |
32 #include "chrome/common/notification_service.h" | 32 #include "chrome/common/notification_service.h" |
33 #include "chrome/common/page_transition_types.h" | 33 #include "chrome/common/page_transition_types.h" |
34 #include "grit/generated_resources.h" | 34 #include "grit/generated_resources.h" |
35 #include "grit/theme_resources.h" | 35 #include "grit/theme_resources.h" |
36 #include "third_party/skia/include/core/SkBitmap.h" | |
37 #include "webkit/glue/window_open_disposition.h" | 36 #include "webkit/glue/window_open_disposition.h" |
38 | 37 |
39 namespace { | 38 namespace { |
40 | 39 |
41 // We are positioned with a little bit of extra space that we don't use now. | 40 // We are positioned with a little bit of extra space that we don't use now. |
42 const int kTopMargin = 1; | 41 const int kTopMargin = 1; |
43 const int kBottomMargin = 1; | 42 const int kBottomMargin = 1; |
44 const int kLeftMargin = 1; | 43 const int kLeftMargin = 1; |
45 const int kRightMargin = 1; | 44 const int kRightMargin = 1; |
46 // We draw a border on the top and bottom (but not on left or right). | 45 // We draw a border on the top and bottom (but not on left or right). |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 location_entry_->SetFocus(); | 398 location_entry_->SetFocus(); |
400 location_entry_->SelectAll(true); | 399 location_entry_->SelectAll(true); |
401 } | 400 } |
402 | 401 |
403 void LocationBarViewGtk::FocusSearch() { | 402 void LocationBarViewGtk::FocusSearch() { |
404 location_entry_->SetFocus(); | 403 location_entry_->SetFocus(); |
405 location_entry_->SetForcedQuery(); | 404 location_entry_->SetForcedQuery(); |
406 } | 405 } |
407 | 406 |
408 void LocationBarViewGtk::UpdatePageActions() { | 407 void LocationBarViewGtk::UpdatePageActions() { |
409 std::vector<ExtensionAction*> page_actions; | 408 std::vector<ExtensionAction2*> page_actions; |
410 if (profile_->GetExtensionsService()) | 409 ExtensionsService* service = profile_->GetExtensionsService(); |
411 page_actions = profile_->GetExtensionsService()->GetPageActions(); | 410 if (!service) |
| 411 return; |
412 | 412 |
413 // Page actions can be created without an icon, so make sure we count only | 413 // Find all the page actions. |
414 // those that have been given an icon. | 414 for (size_t i = 0; i < service->extensions()->size(); ++i) { |
415 for (size_t i = 0; i < page_actions.size();) { | 415 if (service->extensions()->at(i)->page_action()) |
416 if (page_actions[i]->icon_paths().empty()) | 416 page_actions.push_back(service->extensions()->at(i)->page_action()); |
417 page_actions.erase(page_actions.begin() + i); | |
418 else | |
419 ++i; | |
420 } | 417 } |
421 | 418 |
422 // Initialize on the first call, or re-inialize if more extensions have been | 419 // Initialize on the first call, or re-inialize if more extensions have been |
423 // loaded or added after startup. | 420 // loaded or added after startup. |
424 if (page_actions.size() != page_action_views_.size()) { | 421 if (page_actions.size() != page_action_views_.size()) { |
425 page_action_views_.reset(); // Delete the old views (if any). | 422 page_action_views_.reset(); // Delete the old views (if any). |
426 | 423 |
427 for (size_t i = 0; i < page_actions.size(); ++i) { | 424 for (size_t i = 0; i < page_actions.size(); ++i) { |
428 page_action_views_.push_back( | 425 page_action_views_.push_back( |
429 new PageActionViewGtk(this, profile_, page_actions[i])); | 426 new PageActionViewGtk(this, profile_, page_actions[i])); |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 } | 680 } |
684 tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true); | 681 tab->ShowPageInfo(nav_entry->url(), nav_entry->ssl(), true); |
685 return true; | 682 return true; |
686 } | 683 } |
687 | 684 |
688 //////////////////////////////////////////////////////////////////////////////// | 685 //////////////////////////////////////////////////////////////////////////////// |
689 // LocationBarViewGtk::PageActionViewGtk | 686 // LocationBarViewGtk::PageActionViewGtk |
690 | 687 |
691 LocationBarViewGtk::PageActionViewGtk::PageActionViewGtk( | 688 LocationBarViewGtk::PageActionViewGtk::PageActionViewGtk( |
692 LocationBarViewGtk* owner, Profile* profile, | 689 LocationBarViewGtk* owner, Profile* profile, |
693 const ExtensionAction* page_action) | 690 ExtensionAction2* page_action) |
694 : owner_(owner), | 691 : owner_(owner), |
695 profile_(profile), | 692 profile_(profile), |
696 page_action_(page_action), | 693 page_action_(page_action), |
697 last_icon_skbitmap_(NULL), | |
698 last_icon_pixbuf_(NULL) { | 694 last_icon_pixbuf_(NULL) { |
699 event_box_.Own(gtk_event_box_new()); | 695 event_box_.Own(gtk_event_box_new()); |
700 gtk_widget_set_size_request(event_box_.get(), kButtonSize, kButtonSize); | 696 gtk_widget_set_size_request(event_box_.get(), kButtonSize, kButtonSize); |
701 | 697 |
702 // Make the event box not visible so it does not paint a background. | 698 // Make the event box not visible so it does not paint a background. |
703 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE); | 699 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE); |
704 g_signal_connect(event_box_.get(), "button-press-event", | 700 g_signal_connect(event_box_.get(), "button-press-event", |
705 G_CALLBACK(&OnButtonPressed), this); | 701 G_CALLBACK(&OnButtonPressed), this); |
706 g_signal_connect_after(event_box_.get(), "expose-event", | 702 g_signal_connect_after(event_box_.get(), "expose-event", |
707 G_CALLBACK(OnExposeEvent), this); | 703 G_CALLBACK(OnExposeEvent), this); |
708 | 704 |
709 image_.Own(gtk_image_new()); | 705 image_.Own(gtk_image_new()); |
710 gtk_container_add(GTK_CONTAINER(event_box_.get()), image_.get()); | 706 gtk_container_add(GTK_CONTAINER(event_box_.get()), image_.get()); |
711 | 707 |
712 Extension* extension = profile->GetExtensionsService()->GetExtensionById( | 708 Extension* extension = profile->GetExtensionsService()->GetExtensionById( |
713 page_action->extension_id()); | 709 page_action->extension_id()); |
714 DCHECK(extension); | 710 DCHECK(extension); |
715 | 711 |
716 DCHECK(!page_action->icon_paths().empty()); | 712 // Load all the icons declared in the manifest. This is the contents of the |
717 const std::vector<std::string>& icon_paths = page_action->icon_paths(); | 713 // icons array, plus the default_icon property, if any. |
718 pixbufs_.resize(icon_paths.size()); | 714 std::vector<std::string> icon_paths(*page_action->icon_paths()); |
| 715 if (!page_action_->default_icon_path().empty()) |
| 716 icon_paths.push_back(page_action_->default_icon_path()); |
| 717 |
719 tracker_ = new ImageLoadingTracker(this, icon_paths.size()); | 718 tracker_ = new ImageLoadingTracker(this, icon_paths.size()); |
720 for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); | 719 for (std::vector<std::string>::iterator iter = icon_paths.begin(); |
721 iter != icon_paths.end(); ++iter) { | 720 iter != icon_paths.end(); ++iter) { |
722 tracker_->PostLoadImageTask( | 721 tracker_->PostLoadImageTask( |
723 extension->GetResource(*iter), | 722 extension->GetResource(*iter), |
724 gfx::Size(Extension::kPageActionIconMaxSize, | 723 gfx::Size(Extension::kPageActionIconMaxSize, |
725 Extension::kPageActionIconMaxSize)); | 724 Extension::kPageActionIconMaxSize)); |
726 } | 725 } |
727 } | 726 } |
728 | 727 |
729 LocationBarViewGtk::PageActionViewGtk::~PageActionViewGtk() { | 728 LocationBarViewGtk::PageActionViewGtk::~PageActionViewGtk() { |
730 if (tracker_) | 729 if (tracker_) |
731 tracker_->StopTrackingImageLoad(); | 730 tracker_->StopTrackingImageLoad(); |
732 image_.Destroy(); | 731 image_.Destroy(); |
733 event_box_.Destroy(); | 732 event_box_.Destroy(); |
734 for (size_t i = 0; i < pixbufs_.size(); ++i) { | 733 for (PixbufMap::iterator iter = pixbufs_.begin(); iter != pixbufs_.end(); |
735 if (pixbufs_[i]) | 734 ++iter) { |
736 g_object_unref(pixbufs_[i]); | 735 g_object_unref(iter->second); |
737 } | 736 } |
738 if (last_icon_pixbuf_) | 737 if (last_icon_pixbuf_) |
739 g_object_unref(last_icon_pixbuf_); | 738 g_object_unref(last_icon_pixbuf_); |
740 } | 739 } |
741 | 740 |
742 void LocationBarViewGtk::PageActionViewGtk::UpdateVisibility( | 741 void LocationBarViewGtk::PageActionViewGtk::UpdateVisibility( |
743 TabContents* contents, GURL url) { | 742 TabContents* contents, GURL url) { |
744 // Save this off so we can pass it back to the extension when the action gets | 743 // Save this off so we can pass it back to the extension when the action gets |
745 // executed. See PageActionImageView::OnMousePressed. | 744 // executed. See PageActionImageView::OnMousePressed. |
746 current_tab_id_ = ExtensionTabUtil::GetTabId(contents); | 745 current_tab_id_ = ExtensionTabUtil::GetTabId(contents); |
747 current_url_ = url; | 746 current_url_ = url; |
748 | 747 |
749 const ExtensionActionState* state = | 748 bool visible = page_action_->GetIsVisible(current_tab_id_); |
750 contents->GetPageActionState(page_action_); | |
751 bool visible = state && !state->hidden(); | |
752 if (visible) { | 749 if (visible) { |
753 // Set the tooltip. | 750 // Set the tooltip. |
754 if (state->title().empty()) | 751 gtk_widget_set_tooltip_text(event_box_.get(), |
755 gtk_widget_set_tooltip_text(event_box_.get(), | 752 page_action_->GetTitle(current_tab_id_).c_str())
; |
756 page_action_->title().c_str()); | |
757 else | |
758 gtk_widget_set_tooltip_text(event_box_.get(), state->title().c_str()); | |
759 | 753 |
760 // Set the image. | 754 // Set the image. |
761 SkBitmap* icon = state->icon(); | 755 // It can come from three places. In descending order of priority: |
| 756 // - The developer can set it dynamically by path or bitmap. It will be in |
| 757 // page_action_->GetIcon(). |
| 758 // - The developer can set it dyanmically by index. It will be in |
| 759 // page_action_->GetIconIndex(). |
| 760 // - It can be set in the manifest by path. It will be in page_action_-> |
| 761 // default_icon_path(). |
| 762 |
| 763 // First look for a dynamically set bitmap. |
| 764 SkBitmap icon = page_action_->GetIcon(current_tab_id_); |
762 GdkPixbuf* pixbuf = NULL; | 765 GdkPixbuf* pixbuf = NULL; |
763 if (icon) { | 766 if (!icon.isNull()) { |
764 if (icon != last_icon_skbitmap_) { | 767 if (icon.pixelRef() != last_icon_skbitmap_.pixelRef()) { |
765 if (last_icon_pixbuf_) | 768 if (last_icon_pixbuf_) |
766 g_object_unref(last_icon_pixbuf_); | 769 g_object_unref(last_icon_pixbuf_); |
767 last_icon_skbitmap_ = icon; | 770 last_icon_skbitmap_ = icon; |
768 last_icon_pixbuf_ = gfx::GdkPixbufFromSkBitmap(icon); | 771 last_icon_pixbuf_ = gfx::GdkPixbufFromSkBitmap(&icon); |
769 } | 772 } |
770 DCHECK(last_icon_pixbuf_); | 773 DCHECK(last_icon_pixbuf_); |
771 pixbuf = last_icon_pixbuf_; | 774 pixbuf = last_icon_pixbuf_; |
772 } else { | 775 } else { |
773 int index = state->icon_index(); | 776 // Otherwise look for a dynamically set index, or fall back to the |
774 // The image index (if not within bounds) will be set to the first image. | 777 // default path. |
775 if (index < 0 || index >= static_cast<int>(pixbufs_.size())) | 778 int icon_index = page_action_->GetIconIndex(current_tab_id_); |
776 index = 0; | 779 std::string icon_path; |
777 pixbuf = pixbufs_[index]; | 780 if (icon_index >= 0) |
| 781 icon_path = page_action_->icon_paths()->at(icon_index); |
| 782 else |
| 783 icon_path = page_action_->default_icon_path(); |
| 784 |
| 785 if (!icon_path.empty()) { |
| 786 PixbufMap::iterator iter = pixbufs_.find(icon_path); |
| 787 if (iter != pixbufs_.end()) |
| 788 pixbuf = iter->second; |
| 789 } |
778 } | 790 } |
779 | 791 |
780 // The pixbuf might not be loaded yet. | 792 // The pixbuf might not be loaded yet. |
781 if (pixbuf) | 793 if (pixbuf) |
782 gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()), pixbuf); | 794 gtk_image_set_from_pixbuf(GTK_IMAGE(image_.get()), pixbuf); |
783 else | 795 else |
784 visible = false; | 796 visible = false; |
785 } | 797 } |
786 | 798 |
787 if (visible) { | 799 if (visible) { |
788 gtk_widget_show_all(event_box_.get()); | 800 gtk_widget_show_all(event_box_.get()); |
789 } else { | 801 } else { |
790 gtk_widget_hide_all(event_box_.get()); | 802 gtk_widget_hide_all(event_box_.get()); |
791 } | 803 } |
792 } | 804 } |
793 | 805 |
794 void LocationBarViewGtk::PageActionViewGtk::OnImageLoaded(SkBitmap* image, | 806 void LocationBarViewGtk::PageActionViewGtk::OnImageLoaded(SkBitmap* image, |
795 size_t index) { | 807 size_t index) { |
796 DCHECK(index < pixbufs_.size()); | 808 // We loaded icons()->size() icons, plus one extra if the page action had |
797 if (index == pixbufs_.size() - 1) | 809 // a default icon. |
798 tracker_ = NULL; // The tracker object will delete itself when we return. | 810 size_t total_icons = page_action_->icon_paths()->size(); |
799 pixbufs_[index] = gfx::GdkPixbufFromSkBitmap(image); | 811 if (!page_action_->default_icon_path().empty()) |
| 812 total_icons++; |
| 813 DCHECK(index < total_icons); |
| 814 |
| 815 // Map the index of the loaded image back to its name. If we ever get an |
| 816 // index greater than the number of icons, it must be the default icon. |
| 817 if (image) { |
| 818 GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(image); |
| 819 if (index < page_action_->icon_paths()->size()) |
| 820 pixbufs_[page_action_->icon_paths()->at(index)] = pixbuf; |
| 821 else |
| 822 pixbufs_[page_action_->default_icon_path()] = pixbuf; |
| 823 } |
| 824 |
| 825 // If we are done, release the tracker. |
| 826 if (index == (total_icons - 1)) |
| 827 tracker_ = NULL; |
| 828 |
800 owner_->UpdatePageActions(); | 829 owner_->UpdatePageActions(); |
801 } | 830 } |
802 | 831 |
803 // static | 832 // static |
804 gboolean LocationBarViewGtk::PageActionViewGtk::OnButtonPressed( | 833 gboolean LocationBarViewGtk::PageActionViewGtk::OnButtonPressed( |
805 GtkWidget* sender, | 834 GtkWidget* sender, |
806 GdkEventButton* event, | 835 GdkEventButton* event, |
807 LocationBarViewGtk::PageActionViewGtk* page_action_view) { | 836 LocationBarViewGtk::PageActionViewGtk* page_action_view) { |
808 ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( | 837 ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( |
809 page_action_view->profile_, | 838 page_action_view->profile_, |
810 page_action_view->page_action_->extension_id(), | 839 page_action_view->page_action_->extension_id(), |
811 page_action_view->page_action_->id(), | 840 page_action_view->page_action_->id(), |
812 page_action_view->current_tab_id_, | 841 page_action_view->current_tab_id_, |
813 page_action_view->current_url_.spec(), | 842 page_action_view->current_url_.spec(), |
814 event->button); | 843 event->button); |
815 return true; | 844 return true; |
816 } | 845 } |
817 | 846 |
818 // static | 847 // static |
819 gboolean LocationBarViewGtk::PageActionViewGtk::OnExposeEvent( | 848 gboolean LocationBarViewGtk::PageActionViewGtk::OnExposeEvent( |
820 GtkWidget* widget, GdkEventExpose* event, PageActionViewGtk* view) { | 849 GtkWidget* widget, GdkEventExpose* event, PageActionViewGtk* view) { |
821 TabContents* contents = view->owner_->browser_->GetSelectedTabContents(); | 850 TabContents* contents = view->owner_->browser_->GetSelectedTabContents(); |
822 if (!contents) | 851 if (!contents) |
823 return FALSE; | 852 return FALSE; |
824 const ExtensionActionState* state = | 853 |
825 contents->GetPageActionState(view->page_action_); | 854 int tab_id = ExtensionTabUtil::GetTabId(contents); |
826 if (!state || state->badge_text().empty()) | 855 if (tab_id < 0) |
| 856 return FALSE; |
| 857 |
| 858 std::string badge_text = view->page_action_->GetBadgeText(tab_id); |
| 859 if (badge_text.empty()) |
827 return FALSE; | 860 return FALSE; |
828 | 861 |
829 gfx::CanvasPaint canvas(event, false); | 862 gfx::CanvasPaint canvas(event, false); |
830 gfx::Rect bounding_rect(widget->allocation); | 863 gfx::Rect bounding_rect(widget->allocation); |
831 ExtensionActionState::PaintBadge(&canvas, bounding_rect, | 864 view->page_action_->PaintBadge(&canvas, bounding_rect, tab_id); |
832 state->badge_text(), | |
833 state->badge_text_color(), | |
834 state->badge_background_color()); | |
835 return FALSE; | 865 return FALSE; |
836 } | 866 } |
OLD | NEW |