Fix crash when switching menus in menubar

This commit is contained in:
Cheng Zhao 2017-08-28 18:59:06 +09:00
parent b2f3625eaa
commit 4febbec102
2 changed files with 18 additions and 8 deletions

View file

@ -97,6 +97,9 @@ void MenuDelegate::WillHideMenu(views::MenuItemView* menu) {
void MenuDelegate::OnMenuClosed(views::MenuItemView* menu, void MenuDelegate::OnMenuClosed(views::MenuItemView* menu,
views::MenuRunner::RunResult result) { views::MenuRunner::RunResult result) {
// Only switch to new menu when current menu is closed.
if (button_to_open_)
button_to_open_->Activate(nullptr);
delete this; delete this;
} }
@ -106,18 +109,22 @@ views::MenuItemView* MenuDelegate::GetSiblingMenu(
views::MenuAnchorPosition* anchor, views::MenuAnchorPosition* anchor,
bool* has_mnemonics, bool* has_mnemonics,
views::MenuButton**) { views::MenuButton**) {
// TODO(zcbenz): We should follow Chromium's logics on implementing the
// sibling menu switches, this code is almost a hack.
views::MenuButton* button; views::MenuButton* button;
AtomMenuModel* model; AtomMenuModel* model;
if (menu_bar_->GetMenuButtonFromScreenPoint(screen_point, &model, &button) && if (menu_bar_->GetMenuButtonFromScreenPoint(screen_point, &model, &button) &&
button->tag() != id_) { button->tag() != id_) {
DCHECK(menu_runner_->IsRunning()); bool switch_in_progress = !!button_to_open_;
menu_runner_->Cancel(); // Always update target to open.
// After canceling the menu, we need to wait until next tick button_to_open_ = button;
// so we are out of nested message loop. // Switching menu asyncnously to avoid crash.
content::BrowserThread::PostTask( if (!switch_in_progress) {
content::BrowserThread::UI, FROM_HERE, content::BrowserThread::PostTask(
base::Bind(base::IgnoreResult(&views::MenuButton::Activate), content::BrowserThread::UI, FROM_HERE,
base::Unretained(button), nullptr)); base::Bind(&views::MenuRunner::Cancel,
base::Unretained(menu_runner_.get())));
}
} }
return nullptr; return nullptr;

View file

@ -55,6 +55,9 @@ class MenuDelegate : public views::MenuDelegate {
std::unique_ptr<views::MenuDelegate> adapter_; std::unique_ptr<views::MenuDelegate> adapter_;
std::unique_ptr<views::MenuRunner> menu_runner_; std::unique_ptr<views::MenuRunner> menu_runner_;
// The menu button to switch to.
views::MenuButton* button_to_open_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(MenuDelegate); DISALLOW_COPY_AND_ASSIGN(MenuDelegate);
}; };