Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } | |
| OLD | NEW |