1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/toolbar/wrench_menu_model.h" 6 7#include "chrome/app/chrome_command_ids.h" 8#include "chrome/browser/prefs/browser_prefs.h" 9#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 10#include "chrome/browser/ui/browser.h" 11#include "chrome/browser/ui/global_error/global_error.h" 12#include "chrome/browser/ui/global_error/global_error_service.h" 13#include "chrome/browser/ui/global_error/global_error_service_factory.h" 14#include "chrome/browser/ui/tabs/tab_strip_model.h" 15#include "chrome/test/base/browser_with_test_window_test.h" 16#include "chrome/test/base/menu_model_test.h" 17#include "chrome/test/base/testing_browser_process.h" 18#include "chrome/test/base/testing_io_thread_state.h" 19#include "chrome/test/base/testing_pref_service_syncable.h" 20#include "chrome/test/base/testing_profile.h" 21#include "grit/generated_resources.h" 22#include "testing/gtest/include/gtest/gtest.h" 23 24namespace { 25 26// Error class has a menu item. 27class MenuError : public GlobalError { 28 public: 29 explicit MenuError(int command_id) 30 : command_id_(command_id), 31 execute_count_(0) { 32 } 33 34 int execute_count() { return execute_count_; } 35 36 virtual bool HasMenuItem() OVERRIDE { return true; } 37 virtual int MenuItemCommandID() OVERRIDE { return command_id_; } 38 virtual base::string16 MenuItemLabel() OVERRIDE { return base::string16(); } 39 virtual void ExecuteMenuItem(Browser* browser) OVERRIDE { execute_count_++; } 40 41 virtual bool HasBubbleView() OVERRIDE { return false; } 42 virtual bool HasShownBubbleView() OVERRIDE { return false; } 43 virtual void ShowBubbleView(Browser* browser) OVERRIDE { ADD_FAILURE(); } 44 virtual GlobalErrorBubbleViewBase* GetBubbleView() OVERRIDE { return NULL; } 45 46 private: 47 int command_id_; 48 int execute_count_; 49 50 DISALLOW_COPY_AND_ASSIGN(MenuError); 51}; 52 53} // namespace 54 55class WrenchMenuModelTest : public BrowserWithTestWindowTest, 56 public ui::AcceleratorProvider { 57 public: 58 // Don't handle accelerators. 59 virtual bool GetAcceleratorForCommandId( 60 int command_id, 61 ui::Accelerator* accelerator) OVERRIDE { return false; } 62 63 protected: 64 virtual void SetUp() OVERRIDE { 65 prefs_.reset(new TestingPrefServiceSimple()); 66 chrome::RegisterLocalState(prefs_->registry()); 67 68 TestingBrowserProcess::GetGlobal()->SetLocalState(prefs_.get()); 69 testing_io_thread_state_.reset(new chrome::TestingIOThreadState()); 70 BrowserWithTestWindowTest::SetUp(); 71 } 72 73 virtual void TearDown() OVERRIDE { 74 BrowserWithTestWindowTest::TearDown(); 75 testing_io_thread_state_.reset(); 76 TestingBrowserProcess::GetGlobal()->SetLocalState(NULL); 77 DestroyBrowserAndProfile(); 78 } 79 80 private: 81 scoped_ptr<TestingPrefServiceSimple> prefs_; 82 scoped_ptr<chrome::TestingIOThreadState> testing_io_thread_state_; 83}; 84 85// Copies parts of MenuModelTest::Delegate and combines them with the 86// WrenchMenuModel since WrenchMenuModel is now a SimpleMenuModel::Delegate and 87// not derived from SimpleMenuModel. 88class TestWrenchMenuModel : public WrenchMenuModel { 89 public: 90 TestWrenchMenuModel(ui::AcceleratorProvider* provider, 91 Browser* browser) 92 : WrenchMenuModel(provider, browser, false), 93 execute_count_(0), 94 checked_count_(0), 95 enable_count_(0) { 96 } 97 98 // Testing overrides to ui::SimpleMenuModel::Delegate: 99 virtual bool IsCommandIdChecked(int command_id) const OVERRIDE { 100 bool val = WrenchMenuModel::IsCommandIdChecked(command_id); 101 if (val) 102 checked_count_++; 103 return val; 104 } 105 106 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE { 107 ++enable_count_; 108 return true; 109 } 110 111 virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE { 112 ++execute_count_; 113 } 114 115 int execute_count_; 116 mutable int checked_count_; 117 mutable int enable_count_; 118}; 119 120TEST_F(WrenchMenuModelTest, Basics) { 121 TestWrenchMenuModel model(this, browser()); 122 int itemCount = model.GetItemCount(); 123 124 // Verify it has items. The number varies by platform, so we don't check 125 // the exact number. 126 EXPECT_GT(itemCount, 10); 127 128 // Execute a couple of the items and make sure it gets back to our delegate. 129 // We can't use CountEnabledExecutable() here because the encoding menu's 130 // delegate is internal, it doesn't use the one we pass in. 131 // Note: The new menu has a spacing separator at the first slot. 132 model.ActivatedAt(1); 133 EXPECT_TRUE(model.IsEnabledAt(1)); 134 // Make sure to use the index that is not separator in all configurations. 135 model.ActivatedAt(2); 136 EXPECT_TRUE(model.IsEnabledAt(2)); 137 EXPECT_EQ(model.execute_count_, 2); 138 EXPECT_EQ(model.enable_count_, 2); 139 140 model.execute_count_ = 0; 141 model.enable_count_ = 0; 142 143 // Choose something from the bookmark submenu and make sure it makes it back 144 // to the delegate as well. 145 int bookmarksModelIndex = -1; 146 for (int i = 0; i < itemCount; ++i) { 147 if (model.GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) { 148 bookmarksModelIndex = i; 149 break; 150 } 151 } 152 EXPECT_GT(bookmarksModelIndex, -1); 153 ui::MenuModel* bookmarksModel = model.GetSubmenuModelAt(bookmarksModelIndex); 154 EXPECT_TRUE(bookmarksModel); 155 // The bookmarks model may be empty until we tell it we're going to show it. 156 bookmarksModel->MenuWillShow(); 157 EXPECT_GT(bookmarksModel->GetItemCount(), 1); 158 bookmarksModel->ActivatedAt(1); 159 EXPECT_TRUE(bookmarksModel->IsEnabledAt(1)); 160 EXPECT_EQ(model.execute_count_, 1); 161 EXPECT_EQ(model.enable_count_, 1); 162} 163 164// Tests global error menu items in the wrench menu. 165TEST_F(WrenchMenuModelTest, GlobalError) { 166 // Make sure services required for tests are initialized. 167 GlobalErrorService* service = 168 GlobalErrorServiceFactory::GetForProfile(browser()->profile()); 169 ProfileOAuth2TokenServiceFactory::GetForProfile(browser()->profile()); 170 const int command1 = 1234567; 171 // AddGlobalError takes ownership of error1. 172 MenuError* error1 = new MenuError(command1); 173 service->AddGlobalError(error1); 174 const int command2 = 1234568; 175 // AddGlobalError takes ownership of error2. 176 MenuError* error2 = new MenuError(command2); 177 service->AddGlobalError(error2); 178 179 WrenchMenuModel model(this, browser(), false); 180 int index1 = model.GetIndexOfCommandId(command1); 181 EXPECT_GT(index1, -1); 182 int index2 = model.GetIndexOfCommandId(command2); 183 EXPECT_GT(index2, -1); 184 185 EXPECT_TRUE(model.IsEnabledAt(index1)); 186 EXPECT_EQ(0, error1->execute_count()); 187 model.ActivatedAt(index1); 188 EXPECT_EQ(1, error1->execute_count()); 189 190 EXPECT_TRUE(model.IsEnabledAt(index2)); 191 EXPECT_EQ(0, error2->execute_count()); 192 model.ActivatedAt(index2); 193 EXPECT_EQ(1, error1->execute_count()); 194} 195 196class EncodingMenuModelTest : public BrowserWithTestWindowTest, 197 public MenuModelTest { 198}; 199 200TEST_F(EncodingMenuModelTest, IsCommandIdCheckedWithNoTabs) { 201 EncodingMenuModel model(browser()); 202 ASSERT_EQ(NULL, browser()->tab_strip_model()->GetActiveWebContents()); 203 EXPECT_FALSE(model.IsCommandIdChecked(IDC_ENCODING_ISO88591)); 204} 205