| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "base/utf_string_conversions.h" | 5 #include "base/utf_string_conversions.h" |
| 6 #include "chrome/app/chrome_command_ids.h" | 6 #include "chrome/app/chrome_command_ids.h" |
| 7 #include "chrome/browser/extensions/extension_browsertest.h" | 7 #include "chrome/browser/extensions/extension_browsertest.h" |
| 8 #include "chrome/browser/extensions/extension_context_menu_model.h" | 8 #include "chrome/browser/extensions/extension_context_menu_model.h" |
| 9 #include "chrome/browser/extensions/extension_service.h" | 9 #include "chrome/browser/extensions/extension_service.h" |
| 10 #include "chrome/browser/extensions/extension_system.h" | 10 #include "chrome/browser/extensions/extension_system.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 // real context menu, while still running through the actual code in | 32 // real context menu, while still running through the actual code in |
| 33 // RenderViewContextMenu where extension items get added and executed. | 33 // RenderViewContextMenu where extension items get added and executed. |
| 34 class TestRenderViewContextMenu : public RenderViewContextMenu { | 34 class TestRenderViewContextMenu : public RenderViewContextMenu { |
| 35 public: | 35 public: |
| 36 TestRenderViewContextMenu(WebContents* web_contents, | 36 TestRenderViewContextMenu(WebContents* web_contents, |
| 37 const content::ContextMenuParams& params) | 37 const content::ContextMenuParams& params) |
| 38 : RenderViewContextMenu(web_contents, params) {} | 38 : RenderViewContextMenu(web_contents, params) {} |
| 39 | 39 |
| 40 virtual ~TestRenderViewContextMenu() {} | 40 virtual ~TestRenderViewContextMenu() {} |
| 41 | 41 |
| 42 bool HasExtensionItemWithLabel(const std::string& label) { | |
| 43 string16 label16 = UTF8ToUTF16(label); | |
| 44 std::map<int, MenuItem::Id>::iterator i; | |
| 45 for (i = extension_item_map_.begin(); i != extension_item_map_.end(); ++i) { | |
| 46 const MenuItem::Id& id = i->second; | |
| 47 string16 tmp_label; | |
| 48 EXPECT_TRUE(GetItemLabel(id, &tmp_label)); | |
| 49 if (tmp_label == label16) | |
| 50 return true; | |
| 51 } | |
| 52 return false; | |
| 53 } | |
| 54 | |
| 55 // Looks in the menu for an extension item with |id|, and if it is found and | |
| 56 // has a label, that is put in |result| and we return true. Otherwise returns | |
| 57 // false. | |
| 58 bool GetItemLabel(const MenuItem::Id& id, string16* result) { | |
| 59 int command_id = 0; | |
| 60 if (!FindCommandId(id, &command_id)) | |
| 61 return false; | |
| 62 | |
| 63 MenuModel* model = NULL; | |
| 64 int index = -1; | |
| 65 if (!GetMenuModelAndItemIndex(command_id, &model, &index)) { | |
| 66 return false; | |
| 67 } | |
| 68 *result = model->GetLabelAt(index); | |
| 69 return true; | |
| 70 } | |
| 71 | |
| 72 // Searches for an menu item with |command_id|. If it's found, the return | 42 // Searches for an menu item with |command_id|. If it's found, the return |
| 73 // value is true and the model and index where it appears in that model are | 43 // value is true and the model and index where it appears in that model are |
| 74 // returned in |found_model| and |found_index|. Otherwise returns false. | 44 // returned in |found_model| and |found_index|. Otherwise returns false. |
| 75 bool GetMenuModelAndItemIndex(int command_id, | 45 bool GetMenuModelAndItemIndex(int command_id, |
| 76 MenuModel** found_model, | 46 MenuModel** found_model, |
| 77 int *found_index) { | 47 int *found_index) { |
| 78 std::vector<MenuModel*> models_to_search; | 48 std::vector<MenuModel*> models_to_search; |
| 79 models_to_search.push_back(&menu_model_); | 49 models_to_search.push_back(&menu_model_); |
| 80 | 50 |
| 81 while (!models_to_search.empty()) { | 51 while (!models_to_search.empty()) { |
| 82 MenuModel* model = models_to_search.back(); | 52 MenuModel* model = models_to_search.back(); |
| 83 models_to_search.pop_back(); | 53 models_to_search.pop_back(); |
| 84 for (int i = 0; i < model->GetItemCount(); i++) { | 54 for (int i = 0; i < model->GetItemCount(); i++) { |
| 85 if (model->GetCommandIdAt(i) == command_id) { | 55 if (model->GetCommandIdAt(i) == command_id) { |
| 86 *found_model = model; | 56 *found_model = model; |
| 87 *found_index = i; | 57 *found_index = i; |
| 88 return true; | 58 return true; |
| 89 } else if (model->GetTypeAt(i) == MenuModel::TYPE_SUBMENU) { | 59 } else if (model->GetTypeAt(i) == MenuModel::TYPE_SUBMENU) { |
| 90 models_to_search.push_back(model->GetSubmenuModelAt(i)); | 60 models_to_search.push_back(model->GetSubmenuModelAt(i)); |
| 91 } | 61 } |
| 92 } | 62 } |
| 93 } | 63 } |
| 94 | 64 |
| 95 return false; | 65 return false; |
| 96 } | 66 } |
| 97 | 67 |
| 98 // Given an extension menu item id, tries to find the corresponding command id | 68 extensions::ContextMenuMatcher& extension_items() { |
| 99 // in the menu. | 69 return extension_items_; |
| 100 bool FindCommandId(const MenuItem::Id& id, int* command_id) { | |
| 101 std::map<int, MenuItem::Id>::const_iterator i; | |
| 102 for (i = extension_item_map_.begin(); i != extension_item_map_.end(); ++i) { | |
| 103 if (i->second == id) { | |
| 104 *command_id = i->first; | |
| 105 return true; | |
| 106 } | |
| 107 } | |
| 108 return false; | |
| 109 } | 70 } |
| 110 | 71 |
| 111 protected: | 72 protected: |
| 112 // These two functions implement pure virtual methods of | 73 // These two functions implement pure virtual methods of |
| 113 // RenderViewContextMenu. | 74 // RenderViewContextMenu. |
| 114 virtual bool GetAcceleratorForCommandId(int command_id, | 75 virtual bool GetAcceleratorForCommandId(int command_id, |
| 115 ui::Accelerator* accelerator) { | 76 ui::Accelerator* accelerator) { |
| 116 // None of our commands have accelerators, so always return false. | 77 // None of our commands have accelerators, so always return false. |
| 117 return false; | 78 return false; |
| 118 } | 79 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 | 151 |
| 191 // This creates a test menu for a page with |page_url| and |link_url|, looks | 152 // This creates a test menu for a page with |page_url| and |link_url|, looks |
| 192 // for an extension item with the given |label|, and returns true if the item | 153 // for an extension item with the given |label|, and returns true if the item |
| 193 // was found. | 154 // was found. |
| 194 bool MenuHasItemWithLabel(const GURL& page_url, | 155 bool MenuHasItemWithLabel(const GURL& page_url, |
| 195 const GURL& link_url, | 156 const GURL& link_url, |
| 196 const GURL& frame_url, | 157 const GURL& frame_url, |
| 197 const std::string& label) { | 158 const std::string& label) { |
| 198 scoped_ptr<TestRenderViewContextMenu> menu( | 159 scoped_ptr<TestRenderViewContextMenu> menu( |
| 199 CreateMenu(browser(), page_url, link_url, frame_url)); | 160 CreateMenu(browser(), page_url, link_url, frame_url)); |
| 200 return menu->HasExtensionItemWithLabel(label); | 161 return MenuHasExtensionItemWithLabel(menu.get(), label); |
| 201 } | 162 } |
| 202 | 163 |
| 203 // This creates an extension that starts |enabled| and then switches to | 164 // This creates an extension that starts |enabled| and then switches to |
| 204 // |!enabled|. | 165 // |!enabled|. |
| 205 void TestEnabledContextMenu(bool enabled) { | 166 void TestEnabledContextMenu(bool enabled) { |
| 206 ExtensionTestMessageListener begin("begin", true); | 167 ExtensionTestMessageListener begin("begin", true); |
| 207 ExtensionTestMessageListener create("create", true); | 168 ExtensionTestMessageListener create("create", true); |
| 208 ExtensionTestMessageListener update("update", false); | 169 ExtensionTestMessageListener update("update", false); |
| 209 ASSERT_TRUE(LoadContextMenuExtension("enabled")); | 170 ASSERT_TRUE(LoadContextMenuExtension("enabled")); |
| 210 | 171 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 226 CreateMenu(browser(), page_url, GURL(), GURL())); | 187 CreateMenu(browser(), page_url, GURL(), GURL())); |
| 227 | 188 |
| 228 // Look for the extension item in the menu, and make sure it's |enabled|. | 189 // Look for the extension item in the menu, and make sure it's |enabled|. |
| 229 int command_id = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST; | 190 int command_id = IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST; |
| 230 ASSERT_EQ(enabled, menu->IsCommandIdEnabled(command_id)); | 191 ASSERT_EQ(enabled, menu->IsCommandIdEnabled(command_id)); |
| 231 | 192 |
| 232 // Update the item and make sure it is now |!enabled|. | 193 // Update the item and make sure it is now |!enabled|. |
| 233 ASSERT_TRUE(update.WaitUntilSatisfied()); | 194 ASSERT_TRUE(update.WaitUntilSatisfied()); |
| 234 ASSERT_EQ(!enabled, menu->IsCommandIdEnabled(command_id)); | 195 ASSERT_EQ(!enabled, menu->IsCommandIdEnabled(command_id)); |
| 235 } | 196 } |
| 197 |
| 198 bool MenuHasExtensionItemWithLabel(TestRenderViewContextMenu* menu, |
| 199 const std::string& label) { |
| 200 string16 label16 = UTF8ToUTF16(label); |
| 201 std::map<int, MenuItem::Id>::iterator i; |
| 202 for (i = menu->extension_items().extension_item_map_.begin(); |
| 203 i != menu->extension_items().extension_item_map_.end(); ++i) { |
| 204 const MenuItem::Id& id = i->second; |
| 205 string16 tmp_label; |
| 206 EXPECT_TRUE(GetItemLabel(menu, id, &tmp_label)); |
| 207 if (tmp_label == label16) |
| 208 return true; |
| 209 } |
| 210 return false; |
| 211 } |
| 212 |
| 213 // Looks in the menu for an extension item with |id|, and if it is found and |
| 214 // has a label, that is put in |result| and we return true. Otherwise returns |
| 215 // false. |
| 216 bool GetItemLabel(TestRenderViewContextMenu* menu, |
| 217 const MenuItem::Id& id, |
| 218 string16* result) { |
| 219 int command_id = 0; |
| 220 if (!FindCommandId(menu, id, &command_id)) |
| 221 return false; |
| 222 |
| 223 MenuModel* model = NULL; |
| 224 int index = -1; |
| 225 if (!menu->GetMenuModelAndItemIndex(command_id, &model, &index)) { |
| 226 return false; |
| 227 } |
| 228 *result = model->GetLabelAt(index); |
| 229 return true; |
| 230 } |
| 231 |
| 232 // Given an extension menu item id, tries to find the corresponding command id |
| 233 // in the menu. |
| 234 bool FindCommandId(TestRenderViewContextMenu* menu, |
| 235 const MenuItem::Id& id, |
| 236 int* command_id) { |
| 237 std::map<int, MenuItem::Id>::const_iterator i; |
| 238 for (i = menu->extension_items().extension_item_map_.begin(); |
| 239 i != menu->extension_items().extension_item_map_.end(); ++i) { |
| 240 if (i->second == id) { |
| 241 *command_id = i->first; |
| 242 return true; |
| 243 } |
| 244 } |
| 245 return false; |
| 246 } |
| 236 }; | 247 }; |
| 237 | 248 |
| 238 // Tests adding a simple context menu item. | 249 // Tests adding a simple context menu item. |
| 239 IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Simple) { | 250 IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, Simple) { |
| 240 ExtensionTestMessageListener listener1("created item", false); | 251 ExtensionTestMessageListener listener1("created item", false); |
| 241 ExtensionTestMessageListener listener2("onclick fired", false); | 252 ExtensionTestMessageListener listener2("onclick fired", false); |
| 242 ASSERT_TRUE(LoadContextMenuExtension("simple")); | 253 ASSERT_TRUE(LoadContextMenuExtension("simple")); |
| 243 | 254 |
| 244 // Wait for the extension to tell us it's created an item. | 255 // Wait for the extension to tell us it's created an item. |
| 245 ASSERT_TRUE(listener1.WaitUntilSatisfied()); | 256 ASSERT_TRUE(listener1.WaitUntilSatisfied()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 // Tests registering an item with a very long title that should get truncated in | 306 // Tests registering an item with a very long title that should get truncated in |
| 296 // the actual menu displayed. | 307 // the actual menu displayed. |
| 297 IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, LongTitle) { | 308 IN_PROC_BROWSER_TEST_F(ExtensionContextMenuBrowserTest, LongTitle) { |
| 298 ExtensionTestMessageListener listener("created", false); | 309 ExtensionTestMessageListener listener("created", false); |
| 299 | 310 |
| 300 // Load the extension and wait until it's created a menu item. | 311 // Load the extension and wait until it's created a menu item. |
| 301 ASSERT_TRUE(LoadContextMenuExtension("long_title")); | 312 ASSERT_TRUE(LoadContextMenuExtension("long_title")); |
| 302 ASSERT_TRUE(listener.WaitUntilSatisfied()); | 313 ASSERT_TRUE(listener.WaitUntilSatisfied()); |
| 303 | 314 |
| 304 // Make sure we have an item registered with a long title. | 315 // Make sure we have an item registered with a long title. |
| 305 size_t limit = RenderViewContextMenu::kMaxExtensionItemTitleLength; | 316 size_t limit = extensions::ContextMenuMatcher::kMaxExtensionItemTitleLength; |
| 306 MenuItem::List items = GetItems(); | 317 MenuItem::List items = GetItems(); |
| 307 ASSERT_EQ(1u, items.size()); | 318 ASSERT_EQ(1u, items.size()); |
| 308 MenuItem* item = items.at(0); | 319 MenuItem* item = items.at(0); |
| 309 ASSERT_GT(item->title().size(), limit); | 320 ASSERT_GT(item->title().size(), limit); |
| 310 | 321 |
| 311 // Create a context menu, then find the item's label. It should be properly | 322 // Create a context menu, then find the item's label. It should be properly |
| 312 // truncated. | 323 // truncated. |
| 313 GURL url("http://foo.com/"); | 324 GURL url("http://foo.com/"); |
| 314 scoped_ptr<TestRenderViewContextMenu> menu( | 325 scoped_ptr<TestRenderViewContextMenu> menu( |
| 315 CreateMenu(browser(), url, GURL(), GURL())); | 326 CreateMenu(browser(), url, GURL(), GURL())); |
| 316 | 327 |
| 317 string16 label; | 328 string16 label; |
| 318 ASSERT_TRUE(menu->GetItemLabel(item->id(), &label)); | 329 ASSERT_TRUE(GetItemLabel(menu.get(), item->id(), &label)); |
| 319 ASSERT_TRUE(label.size() <= limit); | 330 ASSERT_TRUE(label.size() <= limit); |
| 320 } | 331 } |
| 321 | 332 |
| 322 // Checks that in |menu|, the item at |index| has type |expected_type| and a | 333 // Checks that in |menu|, the item at |index| has type |expected_type| and a |
| 323 // label of |expected_label|. | 334 // label of |expected_label|. |
| 324 static void ExpectLabelAndType(const char* expected_label, | 335 static void ExpectLabelAndType(const char* expected_label, |
| 325 MenuModel::ItemType expected_type, | 336 MenuModel::ItemType expected_type, |
| 326 const MenuModel& menu, | 337 const MenuModel& menu, |
| 327 int index) { | 338 int index) { |
| 328 EXPECT_EQ(expected_type, menu.GetTypeAt(index)); | 339 EXPECT_EQ(expected_type, menu.GetTypeAt(index)); |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 ASSERT_TRUE(MenuHasItemWithLabel( | 584 ASSERT_TRUE(MenuHasItemWithLabel( |
| 574 about_blank, GURL(), GURL(), std::string("Checkbox 1"))); | 585 about_blank, GURL(), GURL(), std::string("Checkbox 1"))); |
| 575 | 586 |
| 576 // Test that checked menu items retain their checkedness. | 587 // Test that checked menu items retain their checkedness. |
| 577 LazyBackgroundObserver checkbox_checked; | 588 LazyBackgroundObserver checkbox_checked; |
| 578 scoped_ptr<TestRenderViewContextMenu> menu( | 589 scoped_ptr<TestRenderViewContextMenu> menu( |
| 579 CreateMenu(browser(), about_blank, GURL(), GURL())); | 590 CreateMenu(browser(), about_blank, GURL(), GURL())); |
| 580 MenuItem::Id id(false, extension->id()); | 591 MenuItem::Id id(false, extension->id()); |
| 581 id.string_uid = "checkbox1"; | 592 id.string_uid = "checkbox1"; |
| 582 int command_id = -1; | 593 int command_id = -1; |
| 583 ASSERT_TRUE(menu->FindCommandId(id, &command_id)); | 594 ASSERT_TRUE(FindCommandId(menu.get(), id, &command_id)); |
| 584 EXPECT_FALSE(menu->IsCommandIdChecked(command_id)); | 595 EXPECT_FALSE(menu->IsCommandIdChecked(command_id)); |
| 585 | 596 |
| 586 // Executing the checkbox also fires the onClicked event. | 597 // Executing the checkbox also fires the onClicked event. |
| 587 ExtensionTestMessageListener listener("onClicked fired for checkbox1", false); | 598 ExtensionTestMessageListener listener("onClicked fired for checkbox1", false); |
| 588 menu->ExecuteCommand(command_id); | 599 menu->ExecuteCommand(command_id); |
| 589 checkbox_checked.WaitUntilClosed(); | 600 checkbox_checked.WaitUntilClosed(); |
| 590 | 601 |
| 591 EXPECT_TRUE(menu->IsCommandIdChecked(command_id)); | 602 EXPECT_TRUE(menu->IsCommandIdChecked(command_id)); |
| 592 ASSERT_TRUE(listener.WaitUntilSatisfied()); | 603 ASSERT_TRUE(listener.WaitUntilSatisfied()); |
| 593 } | 604 } |
| OLD | NEW |