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