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

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

Issue 419023002: Move ShowPopup logic from BrowserActionsContainer to BrowserActionView (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/toolbar/browser_action_view.h" 5 #include "chrome/browser/ui/views/toolbar/browser_action_view.h"
6 6
7 #include <string>
8
7 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/extensions/api/commands/command_service.h" 11 #include "chrome/browser/extensions/api/commands/command_service.h"
10 #include "chrome/browser/extensions/extension_action.h" 12 #include "chrome/browser/extensions/extension_action.h"
11 #include "chrome/browser/extensions/extension_action_manager.h" 13 #include "chrome/browser/extensions/extension_action_manager.h"
12 #include "chrome/browser/extensions/extension_context_menu_model.h" 14 #include "chrome/browser/extensions/extension_context_menu_model.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/themes/theme_service.h" 16 #include "chrome/browser/themes/theme_service.h"
16 #include "chrome/browser/themes/theme_service_factory.h" 17 #include "chrome/browser/themes/theme_service_factory.h"
17 #include "chrome/browser/ui/browser.h" 18 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/extensions/accelerator_priority.h" 19 #include "chrome/browser/ui/extensions/accelerator_priority.h"
19 #include "chrome/browser/ui/view_ids.h" 20 #include "chrome/browser/ui/view_ids.h"
20 #include "chrome/browser/ui/views/frame/browser_view.h" 21 #include "chrome/browser/ui/views/frame/browser_view.h"
21 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h" 22 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
22 #include "chrome/browser/ui/views/toolbar/toolbar_view.h" 23 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
23 #include "extensions/common/extension.h" 24 #include "extensions/common/extension.h"
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 // to GTK requires that we regrab our browser action images. 132 // to GTK requires that we regrab our browser action images.
132 registrar_.Add( 133 registrar_.Add(
133 this, 134 this,
134 chrome::NOTIFICATION_BROWSER_THEME_CHANGED, 135 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
135 content::Source<ThemeService>( 136 content::Source<ThemeService>(
136 ThemeServiceFactory::GetForProfile(browser->profile()))); 137 ThemeServiceFactory::GetForProfile(browser->profile())));
137 } 138 }
138 139
139 void BrowserActionButton::Destroy() { 140 void BrowserActionButton::Destroy() {
140 MaybeUnregisterExtensionCommand(false); 141 MaybeUnregisterExtensionCommand(false);
141 142 HidePopup();
142 if (menu_runner_) { 143 if (menu_runner_) {
143 menu_runner_->Cancel(); 144 menu_runner_->Cancel();
144 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); 145 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
145 } else { 146 } else {
146 delete this; 147 delete this;
147 } 148 }
148 } 149 }
149 150
150 void BrowserActionButton::ViewHierarchyChanged( 151 void BrowserActionButton::ViewHierarchyChanged(
151 const ViewHierarchyChangedDetails& details) { 152 const ViewHierarchyChangedDetails& details) {
(...skipping 17 matching lines...) Expand all
169 return true; 170 return true;
170 } 171 }
171 172
172 void BrowserActionButton::GetAccessibleState(ui::AXViewState* state) { 173 void BrowserActionButton::GetAccessibleState(ui::AXViewState* state) {
173 views::MenuButton::GetAccessibleState(state); 174 views::MenuButton::GetAccessibleState(state);
174 state->role = ui::AX_ROLE_BUTTON; 175 state->role = ui::AX_ROLE_BUTTON;
175 } 176 }
176 177
177 void BrowserActionButton::ButtonPressed(views::Button* sender, 178 void BrowserActionButton::ButtonPressed(views::Button* sender,
178 const ui::Event& event) { 179 const ui::Event& event) {
179 delegate_->OnBrowserActionExecuted(this); 180 ExecuteBrowserAction();
180 } 181 }
181 182
182 void BrowserActionButton::ShowContextMenuForView( 183 void BrowserActionButton::ShowContextMenuForView(
183 View* source, 184 View* source,
184 const gfx::Point& point, 185 const gfx::Point& point,
185 ui::MenuSourceType source_type) { 186 ui::MenuSourceType source_type) {
186 if (!extension()->ShowConfigureContextMenus()) 187 if (!extension()->ShowConfigureContextMenus())
187 return; 188 return;
188 189
189 SetButtonPushed(); 190 SetButtonPushed();
190 191
191 // Reconstructs the menu every time because the menu's contents are dynamic. 192 // Reconstructs the menu every time because the menu's contents are dynamic.
192 scoped_refptr<ExtensionContextMenuModel> context_menu_contents( 193 scoped_refptr<ExtensionContextMenuModel> context_menu_contents(
193 new ExtensionContextMenuModel(extension(), browser_, delegate_)); 194 new ExtensionContextMenuModel(extension(), browser_, this));
194 gfx::Point screen_loc; 195 gfx::Point screen_loc;
195 views::View::ConvertPointToScreen(this, &screen_loc); 196 views::View::ConvertPointToScreen(this, &screen_loc);
196 197
197 views::Widget* parent = NULL; 198 views::Widget* parent = NULL;
198 int run_types = views::MenuRunner::HAS_MNEMONICS | 199 int run_types = views::MenuRunner::HAS_MNEMONICS |
199 views::MenuRunner::CONTEXT_MENU; 200 views::MenuRunner::CONTEXT_MENU;
200 if (delegate_->ShownInsideMenu()) { 201 if (delegate_->ShownInsideMenu()) {
201 run_types |= views::MenuRunner::IS_NESTED; 202 run_types |= views::MenuRunner::IS_NESTED;
202 // RunMenuAt expects a nested menu to be parented by the same widget as the 203 // RunMenuAt expects a nested menu to be parented by the same widget as the
203 // already visible menu, in this case the Chrome menu. 204 // already visible menu, in this case the Chrome menu.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 bool BrowserActionButton::IsPopup() { 265 bool BrowserActionButton::IsPopup() {
265 int tab_id = delegate_->GetCurrentTabId(); 266 int tab_id = delegate_->GetCurrentTabId();
266 return (tab_id < 0) ? false : browser_action_->HasPopup(tab_id); 267 return (tab_id < 0) ? false : browser_action_->HasPopup(tab_id);
267 } 268 }
268 269
269 GURL BrowserActionButton::GetPopupUrl() { 270 GURL BrowserActionButton::GetPopupUrl() {
270 int tab_id = delegate_->GetCurrentTabId(); 271 int tab_id = delegate_->GetCurrentTabId();
271 return (tab_id < 0) ? GURL() : browser_action_->GetPopupUrl(tab_id); 272 return (tab_id < 0) ? GURL() : browser_action_->GetPopupUrl(tab_id);
272 } 273 }
273 274
275 bool BrowserActionButton::ShowPopup(
276 ExtensionPopup::ShowAction show_action,
277 bool grant_tab_permissions) {
278 GURL popup_url;
279 if (delegate_->GetModel()->ExecuteBrowserAction(
280 extension_, browser_, &popup_url, grant_tab_permissions) ==
281 extensions::ExtensionToolbarModel::ACTION_NONE) {
282 return false;
283 }
284
285 // If we're showing the popup for this browser action, just hide it and
Peter Kasting 2014/07/29 21:49:48 Nit: showing -> already showing
Devlin 2014/07/30 16:14:26 Done.
286 // return.
287 bool already_showing = popup_ != NULL;
288
289 // Always hide the current popup, even if it's not the same.
290 // Only one popup should be visible at a time.
291 delegate_->HideActivePopup();
292 if (already_showing)
293 return false;
294
295 // Browser actions in the overflow menu can still show popups, so we may need
296 // a reference view other than this view. If so, use the overflow view.
Yoyo Zhou 2014/07/30 01:46:33 "other than this button"?
Devlin 2014/07/30 16:14:26 Done.
297 views::View* reference_view =
298 parent()->visible() ? this : delegate_->GetOverflowReferenceView();
299
300 popup_ = ExtensionPopup::ShowPopup(popup_url,
301 browser_,
302 reference_view,
303 views::BubbleBorder::TOP_RIGHT,
304 show_action);
305 popup_->GetWidget()->AddObserver(this);
306 delegate_->SetPopupOwner(this);
307
308 // Only set button as pushed if it was triggered by a user click.
309 if (grant_tab_permissions)
310 SetButtonPushed();
311 return true;
312 }
313
314 void BrowserActionButton::HidePopup() {
315 if (popup_)
316 CleanupPopup(true);
317 }
318
319 void BrowserActionButton::ExecuteBrowserAction() {
320 ShowPopup(ExtensionPopup::SHOW, true);
321 }
322
274 void BrowserActionButton::Observe(int type, 323 void BrowserActionButton::Observe(int type,
275 const content::NotificationSource& source, 324 const content::NotificationSource& source,
276 const content::NotificationDetails& details) { 325 const content::NotificationDetails& details) {
277 switch (type) { 326 switch (type) {
278 case chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED: 327 case chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED:
279 UpdateState(); 328 UpdateState();
280 // The browser action may have become visible/hidden so we need to make 329 // The browser action may have become visible/hidden so we need to make
281 // sure the state gets updated. 330 // sure the state gets updated.
282 delegate_->OnBrowserActionVisibilityChanged(); 331 delegate_->OnBrowserActionVisibilityChanged();
283 break; 332 break;
(...skipping 24 matching lines...) Expand all
308 void BrowserActionButton::OnIconUpdated() { 357 void BrowserActionButton::OnIconUpdated() {
309 UpdateState(); 358 UpdateState();
310 if (icon_observer_) 359 if (icon_observer_)
311 icon_observer_->OnIconUpdated(GetIconWithBadge()); 360 icon_observer_->OnIconUpdated(GetIconWithBadge());
312 } 361 }
313 362
314 bool BrowserActionButton::Activate() { 363 bool BrowserActionButton::Activate() {
315 if (!IsPopup()) 364 if (!IsPopup())
316 return true; 365 return true;
317 366
318 delegate_->OnBrowserActionExecuted(this); 367 ExecuteBrowserAction();
319 368
320 // TODO(erikkay): Run a nested modal loop while the mouse is down to 369 // TODO(erikkay): Run a nested modal loop while the mouse is down to
321 // enable menu-like drag-select behavior. 370 // enable menu-like drag-select behavior.
322 371
323 // The return value of this method is returned via OnMousePressed. 372 // The return value of this method is returned via OnMousePressed.
324 // We need to return false here since we're handing off focus to another 373 // We need to return false here since we're handing off focus to another
325 // widget/view, and true will grab it right back and try to send events 374 // widget/view, and true will grab it right back and try to send events
326 // to us. 375 // to us.
327 return false; 376 return false;
328 } 377 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 } 428 }
380 429
381 bool BrowserActionButton::AcceleratorPressed( 430 bool BrowserActionButton::AcceleratorPressed(
382 const ui::Accelerator& accelerator) { 431 const ui::Accelerator& accelerator) {
383 // Normal priority shortcuts must be handled via standard browser commands to 432 // Normal priority shortcuts must be handled via standard browser commands to
384 // be processed at the proper time. 433 // be processed at the proper time.
385 if (GetAcceleratorPriority(accelerator, extension_) == 434 if (GetAcceleratorPriority(accelerator, extension_) ==
386 ui::AcceleratorManager::kNormalPriority) 435 ui::AcceleratorManager::kNormalPriority)
387 return false; 436 return false;
388 437
389 delegate_->OnBrowserActionExecuted(this); 438 ExecuteBrowserAction();
390 return true; 439 return true;
391 } 440 }
392 441
393 void BrowserActionButton::SetButtonPushed() { 442 void BrowserActionButton::SetButtonPushed() {
394 SetState(views::CustomButton::STATE_PRESSED); 443 SetState(views::CustomButton::STATE_PRESSED);
395 menu_visible_ = true; 444 menu_visible_ = true;
396 } 445 }
397 446
398 void BrowserActionButton::SetButtonNotPushed() { 447 void BrowserActionButton::SetButtonNotPushed() {
399 SetState(views::CustomButton::STATE_NORMAL); 448 SetState(views::CustomButton::STATE_NORMAL);
(...skipping 13 matching lines...) Expand all
413 return browser_action_->GetIconWithBadge(icon, tab_id, spacing); 462 return browser_action_->GetIconWithBadge(icon, tab_id, spacing);
414 } 463 }
415 464
416 gfx::ImageSkia BrowserActionButton::GetIconForTest() { 465 gfx::ImageSkia BrowserActionButton::GetIconForTest() {
417 return GetImage(views::Button::STATE_NORMAL); 466 return GetImage(views::Button::STATE_NORMAL);
418 } 467 }
419 468
420 BrowserActionButton::~BrowserActionButton() { 469 BrowserActionButton::~BrowserActionButton() {
421 } 470 }
422 471
472 void BrowserActionButton::InspectPopup(ExtensionAction* action) {
473 DCHECK_EQ(browser_action_, action);
474 ShowPopup(ExtensionPopup::SHOW_AND_INSPECT, true); // grant active tab
Yoyo Zhou 2014/07/30 01:46:33 May as well be consistent about commenting on bool
Devlin 2014/07/30 16:14:26 Done.
475 }
476
477 void BrowserActionButton::OnWidgetDestroying(views::Widget* widget) {
478 DCHECK(popup_);
479 DCHECK_EQ(popup_->GetWidget(), widget);
480 CleanupPopup(false);
481 }
482
423 void BrowserActionButton::MaybeRegisterExtensionCommand() { 483 void BrowserActionButton::MaybeRegisterExtensionCommand() {
424 extensions::CommandService* command_service = 484 extensions::CommandService* command_service =
425 extensions::CommandService::Get(browser_->profile()); 485 extensions::CommandService::Get(browser_->profile());
426 extensions::Command browser_action_command; 486 extensions::Command browser_action_command;
427 if (command_service->GetBrowserActionCommand( 487 if (command_service->GetBrowserActionCommand(
428 extension_->id(), 488 extension_->id(),
429 extensions::CommandService::ACTIVE_ONLY, 489 extensions::CommandService::ACTIVE_ONLY,
430 &browser_action_command, 490 &browser_action_command,
431 NULL)) { 491 NULL)) {
432 keybinding_.reset(new ui::Accelerator( 492 keybinding_.reset(new ui::Accelerator(
(...skipping 16 matching lines...) Expand all
449 extensions::Command browser_action_command; 509 extensions::Command browser_action_command;
450 if (!only_if_active || !command_service->GetBrowserActionCommand( 510 if (!only_if_active || !command_service->GetBrowserActionCommand(
451 extension_->id(), 511 extension_->id(),
452 extensions::CommandService::ACTIVE_ONLY, 512 extensions::CommandService::ACTIVE_ONLY,
453 &browser_action_command, 513 &browser_action_command,
454 NULL)) { 514 NULL)) {
455 GetFocusManager()->UnregisterAccelerator(*keybinding_.get(), this); 515 GetFocusManager()->UnregisterAccelerator(*keybinding_.get(), this);
456 keybinding_.reset(NULL); 516 keybinding_.reset(NULL);
457 } 517 }
458 } 518 }
519
520 void BrowserActionButton::CleanupPopup(bool close_widget) {
521 DCHECK(popup_);
522 // We need to do these actions synchronously (instead of closing and then
523 // performing the rest of the cleanup in OnWidgetDestroyed()) because
524 // OnWidgetDestroyed() can be called asynchronously from Close(), and we need
525 // to keep the delegate's popup owner up-to-date.
526 popup_->GetWidget()->RemoveObserver(this);
527 if (close_widget)
528 popup_->GetWidget()->Close();
529 popup_ = NULL;
530 SetButtonNotPushed();
531 delegate_->SetPopupOwner(NULL);
532 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698