| 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 |