diff options
author | rdevlin.cronin <rdevlin.cronin@chromium.org> | 2015-12-01 10:22:10 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-01 18:23:09 +0000 |
commit | 3589f9c97cf26dc162be2b118dee2a4de004ba50 (patch) | |
tree | 1a002fbe62432f2cca3f7eb3e0a3764e05ad5a38 | |
parent | 8f9bdd3412ed4d6cb1912a730398218cda02a388 (diff) | |
download | chromium_src-3589f9c97cf26dc162be2b118dee2a4de004ba50.zip chromium_src-3589f9c97cf26dc162be2b118dee2a4de004ba50.tar.gz chromium_src-3589f9c97cf26dc162be2b118dee2a4de004ba50.tar.bz2 |
[Extensions UI Mac] Fix crash in overflow toolbar actions bar
Fix a crash that would happen when a new action was added with the overflow
menu open. The overflow container would try to update before adding the
new action.
Fix, and add a test.
BUG=561237
Review URL: https://codereview.chromium.org/1488703002
Cr-Commit-Position: refs/heads/master@{#362453}
3 files changed, 66 insertions, 2 deletions
diff --git a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm index 8574e16..4cc6cd6 100644 --- a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm +++ b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm @@ -5,7 +5,10 @@ #import "chrome/browser/ui/cocoa/app_menu/app_menu_controller.h" #include "base/basictypes.h" +#include "base/bind.h" #include "base/mac/bundle_locations.h" +#include "base/memory/weak_ptr.h" +#include "base/message_loop/message_loop.h" #include "base/scoped_observer.h" #include "base/strings/string16.h" #include "base/strings/sys_string_conversions.h" @@ -119,7 +122,8 @@ class ToolbarActionsBarObserverHelper : public ToolbarActionsBarObserver { ToolbarActionsBarObserverHelper(AppMenuController* controller, ToolbarActionsBar* toolbar_actions_bar) : controller_(controller), - scoped_observer_(this) { + scoped_observer_(this), + weak_ptr_factory_(this) { scoped_observer_.Add(toolbar_actions_bar); } ~ToolbarActionsBarObserverHelper() override {} @@ -130,11 +134,24 @@ class ToolbarActionsBarObserverHelper : public ToolbarActionsBarObserver { scoped_observer_.RemoveAll(); } void OnToolbarActionsBarDidStartResize() override { + // No point in having multiple pending update calls. + weak_ptr_factory_.InvalidateWeakPtrs(); + // Edge case: If the resize is caused by an action being added while the + // menu is open, we need to wait for both toolbars to be updated. This can + // happen if a user's data is synced with the menu open. + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&ToolbarActionsBarObserverHelper::UpdateSubmenu, + weak_ptr_factory_.GetWeakPtr())); + } + + void UpdateSubmenu() { [controller_ updateBrowserActionsSubmenu]; } AppMenuController* controller_; ScopedObserver<ToolbarActionsBar, ToolbarActionsBarObserver> scoped_observer_; + base::WeakPtrFactory<ToolbarActionsBarObserverHelper> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBarObserverHelper); }; diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm b/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm index bd97931..8a51d8a 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm +++ b/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm @@ -408,3 +408,50 @@ IN_PROC_BROWSER_TEST_F(BrowserActionButtonUiTest, TestOverflowContainerLayout) { resizeAndActivateWrench(kNumExtensions / 2, "GlobalError Half"); resizeAndActivateWrench(1, "GlobalError One"); } + +void AddExtensionWithMenuOpen(ToolbarController* toolbarController, + ExtensionService* extensionService, + const base::Closure& closure) { + AppMenuController* appMenuController = + [toolbarController appMenuController]; + + scoped_refptr<const extensions::Extension> extension = + extensions::extension_action_test_util::CreateActionExtension( + "extension", + extensions::extension_action_test_util::BROWSER_ACTION); + extensionService->AddExtension(extension.get()); + + base::RunLoop().RunUntilIdle(); + + // Close the app menu. + [appMenuController cancel]; + EXPECT_FALSE([appMenuController isMenuOpen]); + base::MessageLoop::current()->PostTask(FROM_HERE, closure); +} + +// Test adding an extension while the app menu is open. Regression test for +// crbug.com/561237. +IN_PROC_BROWSER_TEST_F(BrowserActionButtonUiTest, AddExtensionWithMenuOpen) { + // Add an extension to ensure the overflow menu is present. + scoped_refptr<const extensions::Extension> extension = + extensions::extension_action_test_util::CreateActionExtension( + "original extension", + extensions::extension_action_test_util::BROWSER_ACTION); + extension_service()->AddExtension(extension.get()); + ASSERT_EQ(1, static_cast<int>(model()->toolbar_items().size())); + model()->SetVisibleIconCount(0); + + MoveMouseToCenter(wrenchButton()); + + base::RunLoop runLoop; + // Click on the app menu, and pass in a callback to continue the test in + // AddExtensionWithMenuOpen (due to the blocking nature of Cocoa menus, + // passing in runLoop.QuitClosure() is not sufficient here.) + ui_controls::SendMouseEventsNotifyWhenDone( + ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP, + base::Bind(&AddExtensionWithMenuOpen, + base::Unretained(toolbarController()), + extension_service(), + runLoop.QuitClosure())); + runLoop.Run(); +} diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc index a7c651d..3f6313c 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc @@ -78,7 +78,7 @@ template<typename Type1, typename Type2, typename FunctionType> void SortContainer(std::vector<Type1>* to_sort, const std::vector<Type2>& reference, FunctionType equal) { - DCHECK_GE(to_sort->size(), reference.size()) << + CHECK_GE(to_sort->size(), reference.size()) << "|to_sort| must contain all elements in |reference|."; if (reference.empty()) return; |