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

Side by Side Diff: chrome/browser/ui/views/toolbar/browser_actions_container.cc

Issue 675023002: Make extensions that desire to act pop out if in overflow (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Test fixes Created 6 years, 1 month 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/ui/views/toolbar/browser_actions_container.h" 5 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "chrome/browser/extensions/extension_action_manager.h" 9 #include "chrome/browser/extensions/extension_action_manager.h"
10 #include "chrome/browser/extensions/tab_helper.h" 10 #include "chrome/browser/extensions/tab_helper.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 // TODO(devlin): We should move this to the model, once it supports component 52 // TODO(devlin): We should move this to the model, once it supports component
53 // actions. 53 // actions.
54 ScopedVector<ToolbarActionViewController> GetToolbarActions( 54 ScopedVector<ToolbarActionViewController> GetToolbarActions(
55 extensions::ExtensionToolbarModel* model, 55 extensions::ExtensionToolbarModel* model,
56 Browser* browser) { 56 Browser* browser) {
57 ScopedVector<ToolbarActionViewController> actions; 57 ScopedVector<ToolbarActionViewController> actions;
58 58
59 // Extension actions come first. 59 // Extension actions come first.
60 extensions::ExtensionActionManager* action_manager = 60 extensions::ExtensionActionManager* action_manager =
61 extensions::ExtensionActionManager::Get(browser->profile()); 61 extensions::ExtensionActionManager::Get(browser->profile());
62 const extensions::ExtensionList& toolbar_items = model->toolbar_items(); 62 const extensions::ExtensionList& toolbar_items = model->GetItemOrderForTab(
63 browser->tab_strip_model()->GetActiveWebContents());
63 for (const scoped_refptr<const Extension>& extension : toolbar_items) { 64 for (const scoped_refptr<const Extension>& extension : toolbar_items) {
64 actions.push_back(new ExtensionActionViewController( 65 actions.push_back(new ExtensionActionViewController(
65 extension.get(), 66 extension.get(),
66 browser, 67 browser,
67 action_manager->GetExtensionAction(*extension))); 68 action_manager->GetExtensionAction(*extension)));
68 } 69 }
69 70
70 // Component actions come second. 71 // Component actions come second.
71 ScopedVector<ToolbarActionViewController> component_actions = 72 ScopedVector<ToolbarActionViewController> component_actions =
72 ComponentToolbarActionsFactory::GetInstance()-> 73 ComponentToolbarActionsFactory::GetInstance()->
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 : initialized_(false), 118 : initialized_(false),
118 profile_(browser->profile()), 119 profile_(browser->profile()),
119 browser_(browser), 120 browser_(browser),
120 main_container_(main_container), 121 main_container_(main_container),
121 popup_owner_(NULL), 122 popup_owner_(NULL),
122 model_(extensions::ExtensionToolbarModel::Get(browser->profile())), 123 model_(extensions::ExtensionToolbarModel::Get(browser->profile())),
123 container_width_(0), 124 container_width_(0),
124 resize_area_(NULL), 125 resize_area_(NULL),
125 chevron_(NULL), 126 chevron_(NULL),
126 suppress_chevron_(false), 127 suppress_chevron_(false),
128 suppress_animation_(false),
129 suppress_layout_(false),
127 resize_amount_(0), 130 resize_amount_(0),
128 animation_target_size_(0) { 131 animation_target_size_(0) {
129 set_id(VIEW_ID_BROWSER_ACTION_TOOLBAR); 132 set_id(VIEW_ID_BROWSER_ACTION_TOOLBAR);
130 if (model_) // |model_| can be NULL in views unittests. 133 if (model_) // |model_| can be NULL in views unittests.
131 model_->AddObserver(this); 134 model_->AddObserver(this);
132 135
133 bool overflow_experiment = 136 bool overflow_experiment =
134 extensions::FeatureSwitch::extension_action_redesign()->IsEnabled(); 137 extensions::FeatureSwitch::extension_action_redesign()->IsEnabled();
135 DCHECK(!in_overflow_mode() || overflow_experiment); 138 DCHECK(!in_overflow_mode() || overflow_experiment);
136 139
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 BrowserActionView* BrowserActionsContainer::GetViewForExtension( 189 BrowserActionView* BrowserActionsContainer::GetViewForExtension(
187 const Extension* extension) { 190 const Extension* extension) {
188 for (BrowserActionView* view : browser_action_views_) { 191 for (BrowserActionView* view : browser_action_views_) {
189 if (view->view_controller()->GetId() == extension->id()) 192 if (view->view_controller()->GetId() == extension->id())
190 return view; 193 return view;
191 } 194 }
192 return NULL; 195 return NULL;
193 } 196 }
194 197
195 void BrowserActionsContainer::RefreshBrowserActionViews() { 198 void BrowserActionsContainer::RefreshBrowserActionViews() {
199 if (browser_action_views_.empty())
200 return; // Nothing to do.
201
202 // When we do a bulk-refresh of views (such as when we switch tabs), we don't
203 // animate the difference. We only animate when it's a change driven by the
204 // action.
205 suppress_animation_ = true;
206 // Don't layout until the end.
207 suppress_layout_ = true;
208
196 for (BrowserActionView* view : browser_action_views_) 209 for (BrowserActionView* view : browser_action_views_)
197 view->UpdateState(); 210 view->UpdateState();
211
212 suppress_layout_ = false;
213 ReorderViews(); // Also triggers a layout.
214
215 suppress_animation_ = false;
198 } 216 }
199 217
200 void BrowserActionsContainer::CreateBrowserActionViews() { 218 void BrowserActionsContainer::CreateBrowserActionViews() {
201 DCHECK(browser_action_views_.empty()); 219 DCHECK(browser_action_views_.empty());
202 if (!model_) 220 if (!model_)
203 return; 221 return;
204 222
223 // We don't Layout while creating views. Instead, Layout() once at the end.
224 suppress_layout_ = true;
225
205 ScopedVector<ToolbarActionViewController> actions = 226 ScopedVector<ToolbarActionViewController> actions =
206 GetToolbarActions(model_, browser_); 227 GetToolbarActions(model_, browser_);
207 for (ToolbarActionViewController* controller : actions) { 228 for (ToolbarActionViewController* controller : actions) {
208 BrowserActionView* view = 229 BrowserActionView* view =
209 new BrowserActionView(make_scoped_ptr(controller), browser_, this); 230 new BrowserActionView(make_scoped_ptr(controller), browser_, this);
210 browser_action_views_.push_back(view); 231 browser_action_views_.push_back(view);
211 AddChildView(view); 232 AddChildView(view);
212 } 233 }
213 actions.weak_clear(); 234 actions.weak_clear();
235
236 suppress_layout_ = false;
237
238 Layout();
239 SchedulePaint();
214 } 240 }
215 241
216 void BrowserActionsContainer::DeleteBrowserActionViews() { 242 void BrowserActionsContainer::DeleteBrowserActionViews() {
217 HideActivePopup(); 243 HideActivePopup();
218 STLDeleteElements(&browser_action_views_); 244 STLDeleteElements(&browser_action_views_);
219 } 245 }
220 246
221 size_t BrowserActionsContainer::VisibleBrowserActions() const { 247 size_t BrowserActionsContainer::VisibleBrowserActions() const {
222 size_t visible_actions = 0; 248 size_t visible_actions = 0;
223 for (const BrowserActionView* view : browser_action_views_) { 249 for (const BrowserActionView* view : browser_action_views_) {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 int min_width = std::min(MinimumNonemptyWidth(), IconCountToWidth(-1)); 380 int min_width = std::min(MinimumNonemptyWidth(), IconCountToWidth(-1));
355 return gfx::Size(min_width, IconHeight()); 381 return gfx::Size(min_width, IconHeight());
356 } 382 }
357 383
358 void BrowserActionsContainer::Layout() { 384 void BrowserActionsContainer::Layout() {
359 if (browser_action_views_.empty()) { 385 if (browser_action_views_.empty()) {
360 SetVisible(false); 386 SetVisible(false);
361 return; 387 return;
362 } 388 }
363 389
390 if (suppress_layout_)
391 return;
392
364 SetVisible(true); 393 SetVisible(true);
365 if (resize_area_) 394 if (resize_area_)
366 resize_area_->SetBounds(0, 0, kItemSpacing, height()); 395 resize_area_->SetBounds(0, 0, kItemSpacing, height());
367 396
368 // If the icons don't all fit, show the chevron (unless suppressed). 397 // If the icons don't all fit, show the chevron (unless suppressed).
369 int max_x = GetPreferredSize().width(); 398 int max_x = GetPreferredSize().width();
370 if (IconCountToWidth(-1) > max_x && !suppress_chevron_ && chevron_) { 399 if (IconCountToWidth(-1) > max_x && !suppress_chevron_ && chevron_) {
371 chevron_->SetVisible(true); 400 chevron_->SetVisible(true);
372 gfx::Size chevron_size(chevron_->GetPreferredSize()); 401 gfx::Size chevron_size(chevron_->GetPreferredSize());
373 max_x -= chevron_size.width() + kChevronSpacing; 402 max_x -= chevron_size.width() + kChevronSpacing;
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 resize_amount_ = 0; 658 resize_amount_ = 0;
630 suppress_chevron_ = false; 659 suppress_chevron_ = false;
631 SetChevronVisibility(); 660 SetChevronVisibility();
632 OnBrowserActionVisibilityChanged(); 661 OnBrowserActionVisibilityChanged();
633 662
634 FOR_EACH_OBSERVER(BrowserActionsContainerObserver, 663 FOR_EACH_OBSERVER(BrowserActionsContainerObserver,
635 observers_, 664 observers_,
636 OnBrowserActionsContainerAnimationEnded()); 665 OnBrowserActionsContainerAnimationEnded());
637 } 666 }
638 667
639 content::WebContents* BrowserActionsContainer::GetCurrentWebContents() { 668 content::WebContents* BrowserActionsContainer::GetCurrentWebContents() const {
640 return browser_->tab_strip_model()->GetActiveWebContents(); 669 return browser_->tab_strip_model()->GetActiveWebContents();
641 } 670 }
642 671
643 extensions::ActiveTabPermissionGranter* 672 extensions::ActiveTabPermissionGranter*
644 BrowserActionsContainer::GetActiveTabPermissionGranter() { 673 BrowserActionsContainer::GetActiveTabPermissionGranter() {
645 content::WebContents* web_contents = GetCurrentWebContents(); 674 content::WebContents* web_contents = GetCurrentWebContents();
646 if (!web_contents) 675 if (!web_contents)
647 return NULL; 676 return NULL;
648 return extensions::TabHelper::FromWebContents(web_contents)-> 677 return extensions::TabHelper::FromWebContents(web_contents)->
649 active_tab_permission_granter(); 678 active_tab_permission_granter();
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 bool grant_active_tab) { 906 bool grant_active_tab) {
878 // Don't override another popup, and only show in the active window. 907 // Don't override another popup, and only show in the active window.
879 if (popup_owner_ || !browser_->window()->IsActive()) 908 if (popup_owner_ || !browser_->window()->IsActive())
880 return false; 909 return false;
881 910
882 BrowserActionView* view = GetViewForExtension(extension); 911 BrowserActionView* view = GetViewForExtension(extension);
883 return view && view->view_controller()->ExecuteAction(grant_active_tab); 912 return view && view->view_controller()->ExecuteAction(grant_active_tab);
884 } 913 }
885 914
886 void BrowserActionsContainer::ToolbarVisibleCountChanged() { 915 void BrowserActionsContainer::ToolbarVisibleCountChanged() {
887 if (GetPreferredWidth() != container_width_) 916 if (GetPreferredWidth() != container_width_) {
888 Animate(gfx::Tween::EASE_OUT, GetIconCount()); 917 Animate(gfx::Tween::EASE_OUT, GetIconCount());
918 } else if (animation_target_size_ != 0) {
919 // It's possible that we're right where we're supposed to be in terms of
920 // icon count, but that we're also currently resizing. If this is the case,
921 // end the current animation with the current width.
922 animation_target_size_ = container_width_;
923 resize_animation_->Reset();
924 }
889 } 925 }
890 926
891 void BrowserActionsContainer::ToolbarHighlightModeChanged( 927 void BrowserActionsContainer::ToolbarHighlightModeChanged(
892 bool is_highlighting) { 928 bool is_highlighting) {
893 // The visual highlighting is done in OnPaint(). It's a bit of a pain that 929 // The visual highlighting is done in OnPaint(). It's a bit of a pain that
894 // we delete and recreate everything here, but given everything else going on 930 // we delete and recreate everything here, but given everything else going on
895 // (the lack of highlight, n more extensions appearing, etc), it's not worth 931 // (the lack of highlight, n more extensions appearing, etc), it's not worth
896 // the extra complexity to create and insert only the new extensions. 932 // the extra complexity to create and insert only the new extensions.
897 DeleteBrowserActionViews(); 933 DeleteBrowserActionViews();
898 CreateBrowserActionViews(); 934 CreateBrowserActionViews();
899 Animate(gfx::Tween::LINEAR, GetIconCount()); 935 Animate(gfx::Tween::LINEAR, GetIconCount());
900 } 936 }
901 937
938 void BrowserActionsContainer::ToolbarReorderNecessary(
939 content::WebContents* web_contents) {
940 if (GetCurrentWebContents() == web_contents)
941 ReorderViews();
942 }
943
902 Browser* BrowserActionsContainer::GetBrowser() { 944 Browser* BrowserActionsContainer::GetBrowser() {
903 return browser_; 945 return browser_;
904 } 946 }
905 947
906 void BrowserActionsContainer::LoadImages() { 948 void BrowserActionsContainer::LoadImages() {
907 if (in_overflow_mode()) 949 if (in_overflow_mode())
908 return; // Overflow mode has neither a chevron nor highlighting. 950 return; // Overflow mode has neither a chevron nor highlighting.
909 951
910 ui::ThemeProvider* tp = GetThemeProvider(); 952 ui::ThemeProvider* tp = GetThemeProvider();
911 if (tp && chevron_) { 953 if (tp && chevron_) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 int BrowserActionsContainer::MinimumNonemptyWidth() const { 1019 int BrowserActionsContainer::MinimumNonemptyWidth() const {
978 if (!chevron_) 1020 if (!chevron_)
979 return ToolbarView::kStandardSpacing; 1021 return ToolbarView::kStandardSpacing;
980 return (ToolbarView::kStandardSpacing * 2) + kChevronSpacing + 1022 return (ToolbarView::kStandardSpacing * 2) + kChevronSpacing +
981 chevron_->GetPreferredSize().width(); 1023 chevron_->GetPreferredSize().width();
982 } 1024 }
983 1025
984 void BrowserActionsContainer::Animate(gfx::Tween::Type tween_type, 1026 void BrowserActionsContainer::Animate(gfx::Tween::Type tween_type,
985 size_t num_visible_icons) { 1027 size_t num_visible_icons) {
986 int target_size = IconCountToWidth(num_visible_icons); 1028 int target_size = IconCountToWidth(num_visible_icons);
987 if (resize_animation_ && !disable_animations_during_testing_) { 1029 if (resize_animation_ && !disable_animations_during_testing_ &&
1030 !suppress_animation_) {
988 // Animate! We have to set the animation_target_size_ after calling Reset(), 1031 // Animate! We have to set the animation_target_size_ after calling Reset(),
989 // because that could end up calling AnimationEnded which clears the value. 1032 // because that could end up calling AnimationEnded which clears the value.
990 resize_animation_->Reset(); 1033 resize_animation_->Reset();
991 resize_animation_->SetTweenType(tween_type); 1034 resize_animation_->SetTweenType(tween_type);
992 animation_target_size_ = target_size; 1035 animation_target_size_ = target_size;
993 resize_animation_->Show(); 1036 resize_animation_->Show();
994 } else { 1037 } else {
995 animation_target_size_ = target_size; 1038 animation_target_size_ = target_size;
996 AnimationEnded(resize_animation_.get()); 1039 AnimationEnded(resize_animation_.get());
997 } 1040 }
998 } 1041 }
999 1042
1043 void BrowserActionsContainer::ReorderViews() {
1044 extensions::ExtensionList new_order =
1045 model_->GetItemOrderForTab(GetCurrentWebContents());
1046 if (new_order.empty())
1047 return; // Nothing to do.
1048
1049 // Run through the views and compare them to the desired order. If something
1050 // is out of place, find the correct spot for it.
1051 for (size_t i = 0; i < new_order.size() - 1; ++i) {
1052 if (new_order[i]->id() !=
1053 browser_action_views_[i]->view_controller()->GetId()) {
1054 // Find where the correct view is (it's guaranteed to be after our current
1055 // index, since everything up to this point is correct).
1056 size_t j = i + 1;
1057 while (new_order[i]->id() !=
1058 browser_action_views_[j]->view_controller()->GetId())
1059 ++j;
1060 std::swap(browser_action_views_[i], browser_action_views_[j]);
1061 }
1062 }
1063
1064 // Our visible browser actions may have changed - re-Layout() and check the
1065 // size.
1066 ToolbarVisibleCountChanged();
1067 OnBrowserActionVisibilityChanged();
1068 }
1069
1000 size_t BrowserActionsContainer::GetIconCount() const { 1070 size_t BrowserActionsContainer::GetIconCount() const {
1001 if (!model_) 1071 if (!model_)
1002 return 0u; 1072 return 0u;
1003 1073
1004 // Find the absolute value for the model's visible count. 1074 // Find the absolute value for the model's visible count.
1005 int model_visible_size = model_->GetVisibleIconCount(); 1075 int model_visible_size =
1076 model_->GetVisibleIconCountForTab(GetCurrentWebContents());
1006 size_t absolute_model_visible_size = model_visible_size == -1 ? 1077 size_t absolute_model_visible_size = model_visible_size == -1 ?
1007 model_->toolbar_items().size() : model_visible_size; 1078 model_->toolbar_items().size() : model_visible_size;
1008 1079
1009 #if defined(DEBUG) 1080 #if defined(DEBUG)
1010 // Good time for some sanity checks: We should never try to display more 1081 // Good time for some sanity checks: We should never try to display more
1011 // icons than we have, and we should always have a view per item in the model. 1082 // icons than we have, and we should always have a view per item in the model.
1012 // (The only exception is if this is in initialization.) 1083 // (The only exception is if this is in initialization.)
1013 if (initialized_) { 1084 if (initialized_) {
1014 size_t num_extension_actions = 0u; 1085 size_t num_extension_actions = 0u;
1015 for (const BrowserActionView* view : browser_action_views_) { 1086 for (const BrowserActionView* view : browser_action_views_) {
1016 num_extension_actions += 1087 num_extension_actions +=
1017 view->view_controller()->GetType() == 1088 view->view_controller()->GetType() ==
1018 ToolbarActionViewController::TYPE_EXTENSION_ACTION ? 1 : 0; 1089 ToolbarActionViewController::TYPE_EXTENSION_ACTION ? 1 : 0;
1019 } 1090 }
1020 DCHECK_LE(absolute_model_visible_size, browser_action_views_.size()); 1091 DCHECK_LE(absolute_model_visible_size, browser_action_views_.size());
1021 DCHECK_EQ(model_->toolbar_items().size(), browser_action_views_.size()); 1092 DCHECK_EQ(model_->toolbar_items().size(), browser_action_views_.size());
1022 } 1093 }
1023 #endif 1094 #endif
1024 1095
1025 // The overflow displays any icons not shown by the main bar. 1096 // The overflow displays any icons not shown by the main bar.
1026 return in_overflow_mode() ? 1097 return in_overflow_mode() ?
1027 model_->toolbar_items().size() - absolute_model_visible_size : 1098 model_->toolbar_items().size() - absolute_model_visible_size :
1028 absolute_model_visible_size; 1099 absolute_model_visible_size;
1029 } 1100 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698