browser_actions_container.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/browser_actions_container.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/extension_view_host.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_tab_helper.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/ui/browser_window.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/view_ids.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/extensions/browser_action_drag_data.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/extensions/extension_keybinding_registry_views.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/extensions/extension_popup.h" 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/browser_action_view.h" 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/toolbar_view.h" 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/common/extensions/command.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/pref_names.h" 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/runtime_data.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_resources.h" 33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "third_party/skia/include/core/SkColor.h" 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/drag_utils.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/base/nine_image_painter_factory.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/theme_provider.h" 40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/slide_animation.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/gfx/geometry/rect.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/resize_area.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/metrics.h" 45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/views/painter.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Horizontal spacing between most items in the container, as well as after the 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// last item or chevron (if visible). 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kItemSpacing = ToolbarView::kStandardSpacing; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Horizontal spacing before the chevron (if visible). 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kChevronSpacing = kItemSpacing - 2; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::disable_animations_during_testing_ = false; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserActionsContainer 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserActionsContainer::BrowserActionsContainer(Browser* browser, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View* owner_view) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : profile_(browser->profile()), 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_(browser), 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owner_view_(owner_view), 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_(NULL), 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_button_(NULL), 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_(NULL), 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_(0), 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_(NULL), 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_(NULL), 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppress_chevron_(false), 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_(0), 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_(0), 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_indicator_position_(-1), 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) task_factory_(this), 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) show_menu_task_factory_(this) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_id(VIEW_ID_BROWSER_ACTION_TOOLBAR); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch model_ = extensions::ExtensionToolbarModel::Get(browser->profile()); 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (model_) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->AddObserver(this); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryViews( 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser->profile(), 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owner_view->GetFocusManager(), 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExtensionKeybindingRegistry::ALL_EXTENSIONS, 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) this)); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) resize_animation_.reset(new gfx::SlideAnimation(this)); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_area_ = new views::ResizeArea(this); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(resize_area_); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) chevron_ = new views::MenuButton(NULL, base::string16(), this, false); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chevron_->SetBorder(views::Border::NullBorder()); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->EnableCanvasFlippingForRTLUI(true); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetAccessibleName( 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS_CHEVRON)); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible(false); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(chevron_); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserActionsContainer::~BrowserActionsContainer() { 110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FOR_EACH_OBSERVER(BrowserActionsContainerObserver, 111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_, 112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnBrowserActionsContainerDestroyed()); 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (overflow_menu_) 1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) overflow_menu_->set_observer(NULL); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->RemoveObserver(this); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopShowFolderDropMenuTimer(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup_) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->GetWidget()->RemoveObserver(this); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HidePopup(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteBrowserActionViews(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::Init() { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadImages(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We wait to set the container width until now so that the chevron images 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be loaded. The width calculation needs to know the chevron size. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_ && 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !profile_->GetPrefs()->HasPrefPath( 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::pref_names::kToolbarSize)) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Migration code to the new VisibleIconCount pref. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mpcomplete): remove this after users are upgraded to 5.0. 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int predefined_width = profile_->GetPrefs()->GetInteger( 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::pref_names::kBrowserActionContainerWidth); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (predefined_width != 0) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetVisibleIconCount(WidthToIconCount(predefined_width)); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_ && model_->extensions_initialized()) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetContainerWidth(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserActionView* BrowserActionsContainer::GetBrowserActionView( 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionAction* action) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BrowserActionViews::iterator i(browser_action_views_.begin()); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != browser_action_views_.end(); ++i) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*i)->button()->browser_action() == action) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *i; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::RefreshBrowserActionViews() { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_[i]->button()->UpdateState(); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::CreateBrowserActionViews() { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(browser_action_views_.empty()); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!model_) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::ExtensionList& toolbar_items = model_->toolbar_items(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (extensions::ExtensionList::const_iterator i(toolbar_items.begin()); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != toolbar_items.end(); ++i) { 1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!ShouldDisplayBrowserAction(i->get())) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BrowserActionView* view = new BrowserActionView(i->get(), browser_, this); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_.push_back(view); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(view); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::DeleteBrowserActionViews() { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HidePopup(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&browser_action_views_); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BrowserActionsContainer::VisibleBrowserActions() const { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t visible_actions = 0; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action_views_[i]->visible()) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++visible_actions; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VLOG(4) << "BAC::VisibleBrowserActions() returns " << visible_actions 18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << " with size=" << browser_action_views_.size(); 18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return visible_actions; 19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)size_t BrowserActionsContainer::VisibleBrowserActionsAfterAnimation() const { 19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!animating()) 19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return VisibleBrowserActions(); 19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) size_t visible_actions = WidthToIconCount(animation_target_size_); 19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VLOG(4) << "BAC::VisibleBrowserActionsAfterAnimation() returns " 19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << visible_actions 19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << " with size=" << browser_action_views_.size(); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return visible_actions; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BrowserActionsContainer::ExecuteExtensionCommand( 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const extensions::Extension* extension, 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const extensions::Command& command) { 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Global commands are handled by the ExtensionCommandsGlobalRegistry 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // instance. 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!command.global()); 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extension_keybinding_registry_->ExecuteCommand(extension->id(), 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) command.accelerator()); 211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BrowserActionsContainer::AddObserver( 214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BrowserActionsContainerObserver* observer) { 215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_.AddObserver(observer); 216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 218effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BrowserActionsContainer::RemoveObserver( 219effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BrowserActionsContainerObserver* observer) { 220effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_.RemoveObserver(observer); 221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size BrowserActionsContainer::GetPreferredSize() const { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We calculate the size of the view by taking the current width and 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subtracting resize_amount_ (the latter represents how far the user is 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resizing the view or, if animating the snapping, how far to animate it). 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // But we also clamp it to a minimum size and the maximum size, so that the 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // container can never shrink too far or take up more space than it needs. In 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // other words: MinimumNonemptyWidth() < width() - resize < ClampTo(MAX). 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int preferred_width = std::min( 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::max(MinimumNonemptyWidth(), container_width_ - resize_amount_), 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconCountToWidth(-1, false)); 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Height will be ignored by the ToolbarView. 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return gfx::Size(preferred_width, 0); 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size BrowserActionsContainer::GetMinimumSize() const { 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int min_width = std::min(MinimumNonemptyWidth(), IconCountToWidth(-1, false)); 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Height will be ignored by the ToolbarView. 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return gfx::Size(min_width, 0); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::Layout() { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action_views_.empty()) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVisible(false); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVisible(true); 250effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch resize_area_->SetBounds(0, 0, kItemSpacing, height()); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the icons don't all fit, show the chevron (unless suppressed). 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_x = GetPreferredSize().width(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((IconCountToWidth(-1, false) > max_x) && !suppress_chevron_) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible(true); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size chevron_size(chevron_->GetPreferredSize()); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_x -= 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ToolbarView::kStandardSpacing + chevron_size.width() + kChevronSpacing; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetBounds( 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width() - ToolbarView::kStandardSpacing - chevron_size.width(), 261effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 0, 262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chevron_size.width(), 263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chevron_size.height()); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible(false); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now draw the icons for the browser actions in the available space. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_width = IconWidth(false); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionView* view = browser_action_views_[i]; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = ToolbarView::kStandardSpacing + (i * IconWidth(true)); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (x + icon_width <= max_x) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->SetBounds(x, 0, icon_width, height()); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->SetVisible(true); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->SetVisible(false); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::GetDropFormats( 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* formats, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<OSExchangeData::CustomFormat>* custom_formats) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) custom_formats->insert(BrowserActionDragData::GetBrowserActionCustomFormat()); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::AreDropTypesRequired() { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::CanDrop(const OSExchangeData& data) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionDragData drop_data; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return drop_data.Read(data) ? drop_data.IsFromProfile(profile_) : false; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnDragEntered( 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event) { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::OnDragUpdated( 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First check if we are above the chevron (overflow) menu. 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetEventHandlerForPoint(event.location()) == chevron_) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!show_menu_task_factory_.HasWeakPtrs() && !overflow_menu_) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartShowFolderDropMenuTimer(); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopShowFolderDropMenuTimer(); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out where to display the indicator. This is a complex calculation: 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First, we figure out how much space is to the left of the icon area, so we 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can calculate the true offset into the icon area. 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width_before_icons = ToolbarView::kStandardSpacing + 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (base::i18n::IsRTL() ? 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (chevron_->GetPreferredSize().width() + kChevronSpacing) : 0); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int offset_into_icon_area = event.x() - width_before_icons; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Next, we determine which icon to place the indicator in front of. We want 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to place the indicator in front of icon n when the cursor is between the 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // midpoints of icons (n - 1) and n. To do this we take the offset into the 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon area and transform it as follows: 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Real icon area: 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0 a * b c 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // | | | | 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |[IC|ON] [IC|ON] [IC|ON] 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We want to be before icon 0 for 0 < x <= a, icon 1 for a < x <= b, etc. 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Here the "*" represents the offset into the icon area, and since it's 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // between a and b, we want to return "1". 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Transformed "icon area": 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0 a * b c 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // | | | | 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |[ICON] |[ICON] |[ICON] | 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we shift both our offset and our divider points later by half an icon 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // plus one spacing unit, then it becomes very easy to calculate how many 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // divider points we've passed, because they're the multiples of "one icon 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // plus padding". 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int before_icon_unclamped = (offset_into_icon_area + (IconWidth(false) / 2) + 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kItemSpacing) / IconWidth(true); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Because the user can drag outside the container bounds, we need to clamp to 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the valid range. Note that the maximum allowable value is (num icons), not 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (num icons - 1), because we represent the indicator being past the last 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon as being "before the (last + 1) icon". 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int before_icon = std::min(std::max(before_icon_unclamped, 0), 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(VisibleBrowserActions())); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now we convert back to a pixel offset into the container. We want to place 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the center of the drop indicator at the midpoint of the space before our 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chosen icon. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetDropIndicator(width_before_icons + (before_icon * IconWidth(true)) - 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (kItemSpacing / 2)); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnDragExited() { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopShowFolderDropMenuTimer(); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_indicator_position_ = -1; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::OnPerformDrop( 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionDragData data; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!data.Read(event.data())) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_NONE; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we have the same view as we started with. 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(browser_action_views_[data.index()]->button()->extension()->id(), 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.id()); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(model_); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t i = 0; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; i < browser_action_views_.size(); ++i) { 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int view_x = browser_action_views_[i]->GetMirroredBounds().x(); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!browser_action_views_[i]->visible() || 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (base::i18n::IsRTL() ? (view_x < drop_indicator_position_) : 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (view_x >= drop_indicator_position_))) { 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have reached the end of the visible icons or found one that has a 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // higher x position than the drop point. 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |i| now points to the item to the right of the drop indicator*, which is 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // correct when dragging an icon to the left. When dragging to the right, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // however, we want the icon being dragged to get the index of the item to 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the left of the drop indicator, so we subtract one. 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * Well, it can also point to the end, but not when dragging to the left. :) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i > data.index()) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --i; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = model_->IncognitoIndexToOriginal(i); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->MoveBrowserAction( 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_[data.index()]->button()->extension(), i); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnDragExited(); // Perform clean up after dragging. 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::GetAccessibleState( 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui::AXViewState* state) { 411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->role = ui::AX_ROLE_GROUP; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnMenuButtonClicked(views::View* source, 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source == chevron_) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_ = new BrowserActionOverflowMenuController( 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, browser_, chevron_, browser_action_views_, 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisibleBrowserActions()); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->set_observer(this); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->RunMenu(GetWidget(), false); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::WriteDragDataForView(View* sender, 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& press_pt, 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSExchangeData* data) { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton* button = browser_action_views_[i]->button(); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (button == sender) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the dragging image for the icon. 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::ImageSkia badge(browser_action_views_[i]->GetIconWithBadge()); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_utils::SetDragImageOnDataObject(badge, button->size(), 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) press_pt.OffsetFromOrigin(), 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill in the remaining info. 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionDragData drag_data( 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_[i]->button()->extension()->id(), i); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data.Write(profile_, data); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::GetDragOperationsForView(View* sender, 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& p) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::CanStartDragForView(View* sender, 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& press_pt, 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& p) { 457effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // We don't allow dragging while we're highlighting. 458effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return !model_->is_highlighting(); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnResize(int resize_amount, bool done_resizing) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!done_resizing) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_ = resize_amount; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Up until now we've only been modifying the resize_amount, but now it is 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time to set the container size to the size we have resized to, and then 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // animate to the nearest icon count size if necessary (which may be 0). 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_width = IconCountToWidth(-1, false); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_ = 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::min(std::max(0, container_width_ - resize_amount), max_width); 474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SaveDesiredSizeAndAnimate(gfx::Tween::EASE_OUT, 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WidthToIconCount(container_width_)); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::AnimationProgressed( 479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const gfx::Animation* animation) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(resize_animation_.get(), animation); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_ = static_cast<int>(resize_animation_->GetCurrentValue() * 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (container_width_ - animation_target_size_)); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 486d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void BrowserActionsContainer::AnimationEnded(const gfx::Animation* animation) { 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_ = animation_target_size_; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_ = 0; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_ = 0; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppress_chevron_ = false; 491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 492effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 493effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FOR_EACH_OBSERVER(BrowserActionsContainerObserver, 494effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_, 495effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnBrowserActionsContainerAnimationEnded()); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::NotifyMenuDeleted( 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionOverflowMenuController* controller) { 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(overflow_menu_, controller); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_ = NULL; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserActionsContainer::OnWidgetDestroying(views::Widget* widget) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(popup_->GetWidget(), widget); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->GetWidget()->RemoveObserver(this); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_ = NULL; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |popup_button_| is NULL if the extension has been removed. 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup_button_) { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_button_->SetButtonNotPushed(); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_button_ = NULL; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::InspectPopup(ExtensionAction* action) { 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionView* view = GetBrowserActionView(action); 5178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ShowPopup(view->button(), ExtensionPopup::SHOW_AND_INSPECT, true); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::GetCurrentTabId() const { 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::WebContents* active_tab = 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_->tab_strip_model()->GetActiveWebContents(); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!active_tab) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SessionTabHelper::FromWebContents(active_tab)->session_id().id(); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnBrowserActionExecuted( 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton* button) { 5318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ShowPopup(button, ExtensionPopup::SHOW, true); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnBrowserActionVisibilityChanged() { 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVisible(!browser_action_views_.empty()); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owner_view_->Layout(); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owner_view_->SchedulePaint(); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extensions::ActiveTabPermissionGranter* 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionsContainer::GetActiveTabPermissionGranter() { 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::WebContents* web_contents = 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_->tab_strip_model()->GetActiveWebContents(); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!web_contents) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extensions::TabHelper::FromWebContents(web_contents)-> 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_tab_permission_granter(); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::MoveBrowserAction(const std::string& extension_id, 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t new_index) { 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionService* service = 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)->extension_service(); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (service) { 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = service->GetExtensionById(extension_id, false); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->MoveBrowserAction(extension, new_index); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool BrowserActionsContainer::ShowPopup(const extensions::Extension* extension, 562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool should_grant) { 563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Do not override other popups and only show in active window. The window 564a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // must also have a toolbar, otherwise it should not be showing popups. 565a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(justinlin): Remove toolbar check when http://crbug.com/308645 is 566a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // fixed. 567a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (popup_ || 568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !browser_->window()->IsActive() || 569a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !browser_->window()->IsToolbarVisible()) { 570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 572a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 573a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (BrowserActionViews::iterator it = browser_action_views_.begin(); 574a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) it != browser_action_views_.end(); ++it) { 575a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BrowserActionButton* button = (*it)->button(); 576a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (button && button->extension() == extension) 577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return ShowPopup(button, ExtensionPopup::SHOW, should_grant); 578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 579a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 580a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 581a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::HidePopup() { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove this as an observer and clear |popup_| and |popup_button_| here, 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // since we might change them before OnWidgetDestroying() gets called. 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup_) { 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->GetWidget()->RemoveObserver(this); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->GetWidget()->Close(); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_ = NULL; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup_button_) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_button_->SetButtonNotPushed(); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_button_ = NULL; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::TestExecuteBrowserAction(int index) { 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton* button = browser_action_views_[index]->button(); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionExecuted(button); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::TestSetIconVisibilityCount(size_t icons) { 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetVisibleIconCount(icons); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible(icons < browser_action_views_.size()); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_ = IconCountToWidth(icons, chevron_->visible()); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Layout(); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnPaint(gfx::Canvas* canvas) { 610effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If the views haven't been initialized yet, wait for the next call to 611effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // paint (one will be triggered by entering highlight mode). 612effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (model_->is_highlighting() && !browser_action_views_.empty()) { 613effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch views::Painter::PaintPainterAt( 614effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch canvas, highlight_painter_.get(), GetLocalBounds()); 615effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 616effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sky/glen): Instead of using a drop indicator, animate the icons while 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dragging (like we do for tab dragging). 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drop_indicator_position_ > -1) { 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The two-pixel width drop indicator. 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kDropIndicatorWidth = 2; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect indicator_bounds( 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_indicator_position_ - (kDropIndicatorWidth / 2), 624effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 0, 625effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kDropIndicatorWidth, 626effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch height()); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Color of the drop indicator. 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const SkColor kDropIndicatorColor = SK_ColorBLACK; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->FillRect(indicator_bounds, kDropIndicatorColor); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnThemeChanged() { 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadImages(); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 638a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void BrowserActionsContainer::ViewHierarchyChanged( 639a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const ViewHierarchyChangedDetails& details) { 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No extensions (e.g., incognito). 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!model_) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 644a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (details.is_add && details.child == this) { 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initial toolbar button creation and placement in the widget hierarchy. 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We do this here instead of in the constructor because AddBrowserAction 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calls Layout on the Toolbar, which needs this object to be constructed 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before its Layout function is called. 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateBrowserActionViews(); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::IconWidth(bool include_padding) { 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = false; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int icon_width = 0; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized) { 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized = true; 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_width = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTION)->width(); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return icon_width + (include_padding ? kItemSpacing : 0); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::IconHeight() { 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = false; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int icon_height = 0; 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized = true; 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_height = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTION)->height(); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return icon_height; 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::BrowserActionAdded(const Extension* extension, 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(DEBUG) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) { 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(browser_action_views_[i]->button()->extension() != extension) << 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Asked to add a browser action view for an extension that already " 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "exists."; 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseOverflowMenu(); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 68846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!ShouldDisplayBrowserAction(extension)) { 68946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VLOG(4) << "Should not display: " << extension->name().c_str(); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 69146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 69346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) size_t visible_actions = VisibleBrowserActionsAfterAnimation(); 69446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VLOG(4) << "Got back " << visible_actions << " visible."; 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the new browser action to the vector and the view hierarchy. 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = model_->OriginalIndexToIncognito(index); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionView* view = new BrowserActionView(extension, browser_, this); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_.insert(browser_action_views_.begin() + index, view); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildViewAt(view, index); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are still initializing the container, don't bother animating. 70446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!model_->extensions_initialized()) { 70546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VLOG(4) << "Still initializing"; 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 70746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enlarge the container if it was already at maximum size and we're not in 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the middle of upgrading. 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((model_->GetVisibleIconCount() < 0) && 7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !extensions::ExtensionSystem::Get(profile_)->runtime_data()-> 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsBeingUpgraded(extension)) { 71446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VLOG(4) << "At max, Save and animate"; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppress_chevron_ = true; 716d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SaveDesiredSizeAndAnimate(gfx::Tween::LINEAR, visible_actions + 1); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 71846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VLOG(4) << "Not at max"; 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Just redraw the (possibly modified) visible icon set. 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::BrowserActionRemoved(const Extension* extension) { 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseOverflowMenu(); 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup_ && popup_->host()->extension() == extension) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HidePopup(); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 73046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) size_t visible_actions = VisibleBrowserActionsAfterAnimation(); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BrowserActionViews::iterator i(browser_action_views_.begin()); 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != browser_action_views_.end(); ++i) { 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*i)->button()->extension() == extension) { 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete *i; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_.erase(i); 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the extension is being upgraded we don't want the bar to shrink 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because the icon is just going to get re-added to the same location. 7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (extensions::ExtensionSystem::Get(profile_)->runtime_data()-> 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsBeingUpgraded(extension)) 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action_views_.size() > visible_actions) { 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have more icons than we can show, then we must not be changing 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the container size (since we either removed an icon from the main 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // area and one from the overflow list will have shifted in, or we 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // removed an entry directly from the overflow list). 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either we went from overflow to no-overflow, or we shrunk the no- 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // overflow container by 1. Either way the size changed, so animate. 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible(false); 753d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SaveDesiredSizeAndAnimate(gfx::Tween::EASE_OUT, 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_.size()); 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::BrowserActionMoved(const Extension* extension, 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ShouldDisplayBrowserAction(extension)) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = model_->OriginalIndexToIncognito(index); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index >= 0 && index < static_cast<int>(browser_action_views_.size())); 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteBrowserActionViews(); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateBrowserActionViews(); 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Layout(); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool BrowserActionsContainer::BrowserActionShowPopup( 7788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const extensions::Extension* extension) { 779a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return ShowPopup(extension, false); 7808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 7818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BrowserActionsContainer::VisibleCountChanged() { 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetContainerWidth(); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 786effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BrowserActionsContainer::HighlightModeChanged(bool is_highlighting) { 787effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // The visual highlighting is done in OnPaint(). It's a bit of a pain that 788effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // we delete and recreate everything here, but that's how it's done in 789effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // BrowserActionMoved(), too. If we want to optimize it, we could move the 790effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // existing icons, instead of deleting it all. 791effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DeleteBrowserActionViews(); 792effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateBrowserActionViews(); 793effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SaveDesiredSizeAndAnimate(gfx::Tween::LINEAR, browser_action_views_.size()); 794effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 795effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::LoadImages() { 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ThemeProvider* tp = GetThemeProvider(); 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetIcon(*tp->GetImageSkiaNamed(IDR_BROWSER_ACTIONS_OVERFLOW)); 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetHoverIcon(*tp->GetImageSkiaNamed( 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTIONS_OVERFLOW_H)); 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetPushedIcon(*tp->GetImageSkiaNamed( 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTIONS_OVERFLOW_P)); 803effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 804effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const int kImages[] = IMAGE_GRID(IDR_DEVELOPER_MODE_HIGHLIGHT); 805effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch highlight_painter_.reset(views::Painter::CreateImageGridPainter(kImages)); 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::SetContainerWidth() { 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int visible_actions = model_->GetVisibleIconCount(); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visible_actions < 0) // All icons should be visible. 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visible_actions = model_->toolbar_items().size(); 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible( 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<size_t>(visible_actions) < model_->toolbar_items().size()); 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_ = IconCountToWidth(visible_actions, chevron_->visible()); 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::CloseOverflowMenu() { 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (overflow_menu_) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->CancelMenu(); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::StopShowFolderDropMenuTimer() { 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_menu_task_factory_.InvalidateWeakPtrs(); 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::StartShowFolderDropMenuTimer() { 827b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BrowserActionsContainer::ShowDropFolder, 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_menu_task_factory_.GetWeakPtr()), 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(views::GetMenuShowDelay())); 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::ShowDropFolder() { 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!overflow_menu_); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetDropIndicator(-1); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_ = new BrowserActionOverflowMenuController( 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, browser_, chevron_, browser_action_views_, VisibleBrowserActions()); 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->set_observer(this); 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->RunMenu(GetWidget(), true); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::SetDropIndicator(int x_pos) { 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drop_indicator_position_ != x_pos) { 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_indicator_position_ = x_pos; 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::IconCountToWidth(int icons, 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool display_chevron) const { 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icons < 0) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icons = browser_action_views_.size(); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((icons == 0) && !display_chevron) 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ToolbarView::kStandardSpacing; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icons_size = 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (icons == 0) ? 0 : ((icons * IconWidth(true)) - kItemSpacing); 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int chevron_size = display_chevron ? 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (kChevronSpacing + chevron_->GetPreferredSize().width()) : 0; 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ToolbarView::kStandardSpacing + icons_size + chevron_size + 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ToolbarView::kStandardSpacing; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BrowserActionsContainer::WidthToIconCount(int pixels) const { 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for widths large enough to show the entire icon set. 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pixels >= IconCountToWidth(-1, false)) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browser_action_views_.size(); 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to reserve space for the resize area, chevron, and the spacing on 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // either side of the chevron. 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int available_space = pixels - ToolbarView::kStandardSpacing - 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->GetPreferredSize().width() - kChevronSpacing - 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ToolbarView::kStandardSpacing; 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now we add an extra between-item padding value so the space can be divided 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // evenly by (size of icon with padding). 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<size_t>( 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(0, available_space + kItemSpacing) / IconWidth(true)); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 880cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int BrowserActionsContainer::MinimumNonemptyWidth() const { 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ToolbarView::kStandardSpacing + kChevronSpacing + 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->GetPreferredSize().width() + ToolbarView::kStandardSpacing; 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::SaveDesiredSizeAndAnimate( 886d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) gfx::Tween::Type tween_type, 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t num_visible_icons) { 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save off the desired number of visible icons. We do this now instead of at 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the end of the animation so that even if the browser is shut down while 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // animating, the right value will be restored on next run. 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: Don't save the icon count in incognito because there may be fewer 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icons in that mode. The result is that the container in a normal window is 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // always at least as wide as in an incognito window. 89446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!profile_->IsOffTheRecord()) { 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetVisibleIconCount(num_visible_icons); 89646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VLOG(4) << "Setting visible count: " << num_visible_icons; 89746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } else { 89846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) VLOG(4) << "|Skipping| setting visible count: " << num_visible_icons; 89946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_size = IconCountToWidth(num_visible_icons, 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_visible_icons < browser_action_views_.size()); 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!disable_animations_during_testing_) { 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Animate! We have to set the animation_target_size_ after calling Reset(), 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because that could end up calling AnimationEnded which clears the value. 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_->Reset(); 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_->SetTweenType(tween_type); 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_ = target_size; 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_->Show(); 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_ = target_size; 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnimationEnded(resize_animation_.get()); 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::ShouldDisplayBrowserAction( 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only display incognito-enabled extensions while in incognito mode. 9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !profile_->IsOffTheRecord() || 9195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::util::IsIncognitoEnabled(extension->id(), profile_); 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool BrowserActionsContainer::ShowPopup( 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton* button, 9248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ExtensionPopup::ShowAction show_action, 9258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool should_grant) { 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = button->extension(); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL popup_url; 9288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (model_->ExecuteBrowserAction( 9298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) extension, browser_, &popup_url, should_grant) != 930effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch extensions::ExtensionToolbarModel::ACTION_SHOW_POPUP) { 9318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're showing the same popup, just hide it and return. 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool same_showing = popup_ && button == popup_button_; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Always hide the current popup, even if it's not the same. 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only one popup should be visible at a time. 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HidePopup(); 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (same_showing) 9428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can get the execute event for browser actions that are not visible, 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since buttons can be activated from the overflow menu (chevron). In that 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case we show the popup as originating from the chevron. 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View* reference_view = button->parent()->visible() ? button : chevron_; 948a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) popup_ = ExtensionPopup::ShowPopup(popup_url, browser_, reference_view, 949a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) views::BubbleBorder::TOP_RIGHT, 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_action); 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_->GetWidget()->AddObserver(this); 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup_button_ = button; 9538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 9548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Only set button as pushed if it was triggered by a user click. 9558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (should_grant) 9568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) popup_button_->SetButtonPushed(); 9578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 959