blob: eef1afda0b561eb580bedec75b3c05f4bd862267 [file] [log] [blame]
[email protected]f20d7332011-03-08 21:11:531// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]2e3b5202010-03-23 06:52:412// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <vector>
6
7#include "base/json/json_reader.h"
[email protected]3b63f8f42011-03-28 01:54:158#include "base/memory/scoped_vector.h"
[email protected]2e3b5202010-03-23 06:52:419#include "base/path_service.h"
[email protected]e0785902011-05-19 23:34:1710#include "base/scoped_temp_dir.h"
[email protected]944b4212010-12-14 00:00:3311#include "base/utf_string_conversions.h"
[email protected]2e3b5202010-03-23 06:52:4112#include "base/values.h"
[email protected]2c699652010-10-15 18:22:4113#include "chrome/browser/extensions/extension_event_router.h"
[email protected]2e3b5202010-03-23 06:52:4114#include "chrome/browser/extensions/extension_menu_manager.h"
[email protected]052c92702010-06-25 07:25:5215#include "chrome/browser/extensions/test_extension_prefs.h"
[email protected]432115822011-07-10 15:52:2716#include "chrome/common/chrome_notification_types.h"
[email protected]2e3b5202010-03-23 06:52:4117#include "chrome/common/chrome_paths.h"
18#include "chrome/common/extensions/extension.h"
19#include "chrome/common/extensions/extension_constants.h"
[email protected]a4ff9eae2011-08-01 19:58:1620#include "chrome/test/base/testing_profile.h"
[email protected]1bda97552011-03-01 20:11:5221#include "content/browser/browser_thread.h"
[email protected]f20d7332011-03-08 21:11:5322#include "content/common/notification_service.h"
[email protected]2e3b5202010-03-23 06:52:4123#include "testing/gmock/include/gmock/gmock.h"
[email protected]f20d7332011-03-08 21:11:5324#include "testing/gtest/include/gtest/gtest.h"
[email protected]2e3b5202010-03-23 06:52:4125#include "webkit/glue/context_menu.h"
26
27using testing::_;
28using testing::AtLeast;
29using testing::Return;
30using testing::SaveArg;
31
32// Base class for tests.
[email protected]583844c2011-08-27 00:38:3533class ExtensionMenuManagerTest : public testing::Test {
[email protected]2e3b5202010-03-23 06:52:4134 public:
[email protected]6cad5bf2011-03-10 21:21:5535 ExtensionMenuManagerTest()
36 : ui_thread_(BrowserThread::UI, &message_loop_),
37 file_thread_(BrowserThread::FILE, &message_loop_),
38 next_id_(1) {
39 }
[email protected]2e3b5202010-03-23 06:52:4140
[email protected]052c92702010-06-25 07:25:5241 // Returns a test item.
[email protected]f4f04592010-07-14 20:40:1342 ExtensionMenuItem* CreateTestItem(Extension* extension) {
[email protected]2e3b5202010-03-23 06:52:4143 ExtensionMenuItem::Type type = ExtensionMenuItem::NORMAL;
44 ExtensionMenuItem::ContextList contexts(ExtensionMenuItem::ALL);
[email protected]5a7b5eaf2010-11-02 20:52:1945 ExtensionMenuItem::Id id(NULL, extension->id(), next_id_++);
[email protected]f4f04592010-07-14 20:40:1346 return new ExtensionMenuItem(id, "test", false, type, contexts);
[email protected]06a0c94e2010-06-24 23:20:1547 }
48
[email protected]052c92702010-06-25 07:25:5249 // Creates and returns a test Extension. The caller does *not* own the return
50 // value.
51 Extension* AddExtension(std::string name) {
[email protected]66e4eb32010-10-27 20:37:4152 scoped_refptr<Extension> extension = prefs_.AddExtension(name);
[email protected]819faeb02010-06-25 21:16:2253 extensions_.push_back(extension);
54 return extension;
[email protected]052c92702010-06-25 07:25:5255 }
56
[email protected]2e3b5202010-03-23 06:52:4157 protected:
[email protected]6cad5bf2011-03-10 21:21:5558 MessageLoopForUI message_loop_;
59 BrowserThread ui_thread_;
60 BrowserThread file_thread_;
61
[email protected]2e3b5202010-03-23 06:52:4162 ExtensionMenuManager manager_;
[email protected]66e4eb32010-10-27 20:37:4163 ExtensionList extensions_;
[email protected]052c92702010-06-25 07:25:5264 TestExtensionPrefs prefs_;
[email protected]f4f04592010-07-14 20:40:1365 int next_id_;
[email protected]2e3b5202010-03-23 06:52:4166
67 private:
68 DISALLOW_COPY_AND_ASSIGN(ExtensionMenuManagerTest);
69};
70
71// Tests adding, getting, and removing items.
72TEST_F(ExtensionMenuManagerTest, AddGetRemoveItems) {
[email protected]052c92702010-06-25 07:25:5273 Extension* extension = AddExtension("test");
74
[email protected]2e3b5202010-03-23 06:52:4175 // Add a new item, make sure you can get it back.
[email protected]052c92702010-06-25 07:25:5276 ExtensionMenuItem* item1 = CreateTestItem(extension);
[email protected]2e3b5202010-03-23 06:52:4177 ASSERT_TRUE(item1 != NULL);
[email protected]f4f04592010-07-14 20:40:1378 ASSERT_TRUE(manager_.AddContextItem(extension, item1));
79 ASSERT_EQ(item1, manager_.GetItemById(item1->id()));
[email protected]63a414b52010-06-03 23:20:4980 const ExtensionMenuItem::List* items =
[email protected]2e3b5202010-03-23 06:52:4181 manager_.MenuItems(item1->extension_id());
[email protected]63a414b52010-06-03 23:20:4982 ASSERT_EQ(1u, items->size());
83 ASSERT_EQ(item1, items->at(0));
[email protected]2e3b5202010-03-23 06:52:4184
85 // Add a second item, make sure it comes back too.
[email protected]052c92702010-06-25 07:25:5286 ExtensionMenuItem* item2 = CreateTestItem(extension);
[email protected]f4f04592010-07-14 20:40:1387 ASSERT_TRUE(manager_.AddContextItem(extension, item2));
88 ASSERT_EQ(item2, manager_.GetItemById(item2->id()));
[email protected]2e3b5202010-03-23 06:52:4189 items = manager_.MenuItems(item2->extension_id());
[email protected]63a414b52010-06-03 23:20:4990 ASSERT_EQ(2u, items->size());
91 ASSERT_EQ(item1, items->at(0));
92 ASSERT_EQ(item2, items->at(1));
[email protected]2e3b5202010-03-23 06:52:4193
94 // Try adding item 3, then removing it.
[email protected]052c92702010-06-25 07:25:5295 ExtensionMenuItem* item3 = CreateTestItem(extension);
[email protected]f4f04592010-07-14 20:40:1396 ExtensionMenuItem::Id id3 = item3->id();
[email protected]2e3b5202010-03-23 06:52:4197 std::string extension_id = item3->extension_id();
[email protected]f4f04592010-07-14 20:40:1398 ASSERT_TRUE(manager_.AddContextItem(extension, item3));
[email protected]2e3b5202010-03-23 06:52:4199 ASSERT_EQ(item3, manager_.GetItemById(id3));
[email protected]63a414b52010-06-03 23:20:49100 ASSERT_EQ(3u, manager_.MenuItems(extension_id)->size());
[email protected]2e3b5202010-03-23 06:52:41101 ASSERT_TRUE(manager_.RemoveContextMenuItem(id3));
102 ASSERT_EQ(NULL, manager_.GetItemById(id3));
[email protected]63a414b52010-06-03 23:20:49103 ASSERT_EQ(2u, manager_.MenuItems(extension_id)->size());
[email protected]2e3b5202010-03-23 06:52:41104
105 // Make sure removing a non-existent item returns false.
[email protected]5a7b5eaf2010-11-02 20:52:19106 ExtensionMenuItem::Id id(NULL, extension->id(), id3.uid + 50);
[email protected]f4f04592010-07-14 20:40:13107 ASSERT_FALSE(manager_.RemoveContextMenuItem(id));
[email protected]2e3b5202010-03-23 06:52:41108}
109
110// Test adding/removing child items.
111TEST_F(ExtensionMenuManagerTest, ChildFunctions) {
[email protected]052c92702010-06-25 07:25:52112 Extension* extension1 = AddExtension("1111");
113 Extension* extension2 = AddExtension("2222");
114 Extension* extension3 = AddExtension("3333");
[email protected]2e3b5202010-03-23 06:52:41115
[email protected]052c92702010-06-25 07:25:52116 ExtensionMenuItem* item1 = CreateTestItem(extension1);
117 ExtensionMenuItem* item2 = CreateTestItem(extension2);
118 ExtensionMenuItem* item2_child = CreateTestItem(extension2);
119 ExtensionMenuItem* item2_grandchild = CreateTestItem(extension2);
[email protected]2e3b5202010-03-23 06:52:41120
121 // This third item we expect to fail inserting, so we use a scoped_ptr to make
122 // sure it gets deleted.
[email protected]052c92702010-06-25 07:25:52123 scoped_ptr<ExtensionMenuItem> item3(CreateTestItem(extension3));
[email protected]2e3b5202010-03-23 06:52:41124
125 // Add in the first two items.
[email protected]f4f04592010-07-14 20:40:13126 ASSERT_TRUE(manager_.AddContextItem(extension1, item1));
127 ASSERT_TRUE(manager_.AddContextItem(extension2, item2));
[email protected]2e3b5202010-03-23 06:52:41128
[email protected]f4f04592010-07-14 20:40:13129 ExtensionMenuItem::Id id1 = item1->id();
130 ExtensionMenuItem::Id id2 = item2->id();
[email protected]2e3b5202010-03-23 06:52:41131
132 // Try adding item3 as a child of item2 - this should fail because item3 has
133 // a different extension id.
[email protected]f4f04592010-07-14 20:40:13134 ASSERT_FALSE(manager_.AddChildItem(id2, item3.get()));
[email protected]2e3b5202010-03-23 06:52:41135
136 // Add item2_child as a child of item2.
[email protected]f4f04592010-07-14 20:40:13137 ExtensionMenuItem::Id id2_child = item2_child->id();
138 ASSERT_TRUE(manager_.AddChildItem(id2, item2_child));
[email protected]2e3b5202010-03-23 06:52:41139 ASSERT_EQ(1, item2->child_count());
140 ASSERT_EQ(0, item1->child_count());
141 ASSERT_EQ(item2_child, manager_.GetItemById(id2_child));
142
[email protected]63a414b52010-06-03 23:20:49143 ASSERT_EQ(1u, manager_.MenuItems(item1->extension_id())->size());
144 ASSERT_EQ(item1, manager_.MenuItems(item1->extension_id())->at(0));
[email protected]2e3b5202010-03-23 06:52:41145
146 // Add item2_grandchild as a child of item2_child, then remove it.
[email protected]f4f04592010-07-14 20:40:13147 ExtensionMenuItem::Id id2_grandchild = item2_grandchild->id();
148 ASSERT_TRUE(manager_.AddChildItem(id2_child, item2_grandchild));
[email protected]2e3b5202010-03-23 06:52:41149 ASSERT_EQ(1, item2->child_count());
150 ASSERT_EQ(1, item2_child->child_count());
151 ASSERT_TRUE(manager_.RemoveContextMenuItem(id2_grandchild));
152
153 // We should only get 1 thing back when asking for item2's extension id, since
154 // it has a child item.
[email protected]63a414b52010-06-03 23:20:49155 ASSERT_EQ(1u, manager_.MenuItems(item2->extension_id())->size());
156 ASSERT_EQ(item2, manager_.MenuItems(item2->extension_id())->at(0));
[email protected]2e3b5202010-03-23 06:52:41157
158 // Remove child2_item.
159 ASSERT_TRUE(manager_.RemoveContextMenuItem(id2_child));
[email protected]63a414b52010-06-03 23:20:49160 ASSERT_EQ(1u, manager_.MenuItems(item2->extension_id())->size());
161 ASSERT_EQ(item2, manager_.MenuItems(item2->extension_id())->at(0));
[email protected]2e3b5202010-03-23 06:52:41162 ASSERT_EQ(0, item2->child_count());
163}
164
[email protected]2b07c93f2010-08-02 23:13:04165// Tests that deleting a parent properly removes descendants.
166TEST_F(ExtensionMenuManagerTest, DeleteParent) {
167 Extension* extension = AddExtension("1111");
168
169 // Set up 5 items to add.
170 ExtensionMenuItem* item1 = CreateTestItem(extension);
171 ExtensionMenuItem* item2 = CreateTestItem(extension);
172 ExtensionMenuItem* item3 = CreateTestItem(extension);
173 ExtensionMenuItem* item4 = CreateTestItem(extension);
174 ExtensionMenuItem* item5 = CreateTestItem(extension);
175 ExtensionMenuItem* item6 = CreateTestItem(extension);
176 ExtensionMenuItem::Id item1_id = item1->id();
177 ExtensionMenuItem::Id item2_id = item2->id();
178 ExtensionMenuItem::Id item3_id = item3->id();
179 ExtensionMenuItem::Id item4_id = item4->id();
180 ExtensionMenuItem::Id item5_id = item5->id();
181 ExtensionMenuItem::Id item6_id = item6->id();
182
183 // Add the items in the hierarchy
184 // item1 -> item2 -> item3 -> item4 -> item5 -> item6.
185 ASSERT_TRUE(manager_.AddContextItem(extension, item1));
186 ASSERT_TRUE(manager_.AddChildItem(item1_id, item2));
187 ASSERT_TRUE(manager_.AddChildItem(item2_id, item3));
188 ASSERT_TRUE(manager_.AddChildItem(item3_id, item4));
189 ASSERT_TRUE(manager_.AddChildItem(item4_id, item5));
190 ASSERT_TRUE(manager_.AddChildItem(item5_id, item6));
191 ASSERT_EQ(item1, manager_.GetItemById(item1_id));
192 ASSERT_EQ(item2, manager_.GetItemById(item2_id));
193 ASSERT_EQ(item3, manager_.GetItemById(item3_id));
194 ASSERT_EQ(item4, manager_.GetItemById(item4_id));
195 ASSERT_EQ(item5, manager_.GetItemById(item5_id));
196 ASSERT_EQ(item6, manager_.GetItemById(item6_id));
197 ASSERT_EQ(1u, manager_.MenuItems(extension->id())->size());
198 ASSERT_EQ(6u, manager_.items_by_id_.size());
199
200 // Remove item6 (a leaf node).
201 ASSERT_TRUE(manager_.RemoveContextMenuItem(item6_id));
202 ASSERT_EQ(item1, manager_.GetItemById(item1_id));
203 ASSERT_EQ(item2, manager_.GetItemById(item2_id));
204 ASSERT_EQ(item3, manager_.GetItemById(item3_id));
205 ASSERT_EQ(item4, manager_.GetItemById(item4_id));
206 ASSERT_EQ(item5, manager_.GetItemById(item5_id));
207 ASSERT_EQ(NULL, manager_.GetItemById(item6_id));
208 ASSERT_EQ(1u, manager_.MenuItems(extension->id())->size());
209 ASSERT_EQ(5u, manager_.items_by_id_.size());
210
211 // Remove item4 and make sure item5 is gone as well.
212 ASSERT_TRUE(manager_.RemoveContextMenuItem(item4_id));
213 ASSERT_EQ(item1, manager_.GetItemById(item1_id));
214 ASSERT_EQ(item2, manager_.GetItemById(item2_id));
215 ASSERT_EQ(item3, manager_.GetItemById(item3_id));
216 ASSERT_EQ(NULL, manager_.GetItemById(item4_id));
217 ASSERT_EQ(NULL, manager_.GetItemById(item5_id));
218 ASSERT_EQ(1u, manager_.MenuItems(extension->id())->size());
219 ASSERT_EQ(3u, manager_.items_by_id_.size());
220
221 // Now remove item1 and make sure item2 and item3 are gone as well.
222 ASSERT_TRUE(manager_.RemoveContextMenuItem(item1_id));
[email protected]f50da8592010-10-28 23:39:32223 ASSERT_EQ(NULL, manager_.MenuItems(extension->id()));
[email protected]2b07c93f2010-08-02 23:13:04224 ASSERT_EQ(0u, manager_.items_by_id_.size());
225 ASSERT_EQ(NULL, manager_.GetItemById(item1_id));
226 ASSERT_EQ(NULL, manager_.GetItemById(item2_id));
227 ASSERT_EQ(NULL, manager_.GetItemById(item3_id));
228}
229
[email protected]66dbfb2c2010-05-12 20:20:15230// Tests changing parents.
231TEST_F(ExtensionMenuManagerTest, ChangeParent) {
[email protected]052c92702010-06-25 07:25:52232 Extension* extension1 = AddExtension("1111");
[email protected]06a0c94e2010-06-24 23:20:15233
[email protected]052c92702010-06-25 07:25:52234 // First create two items and add them both to the manager.
235 ExtensionMenuItem* item1 = CreateTestItem(extension1);
236 ExtensionMenuItem* item2 = CreateTestItem(extension1);
237
[email protected]f4f04592010-07-14 20:40:13238 ASSERT_TRUE(manager_.AddContextItem(extension1, item1));
239 ASSERT_TRUE(manager_.AddContextItem(extension1, item2));
[email protected]66dbfb2c2010-05-12 20:20:15240
[email protected]63a414b52010-06-03 23:20:49241 const ExtensionMenuItem::List* items =
[email protected]66dbfb2c2010-05-12 20:20:15242 manager_.MenuItems(item1->extension_id());
[email protected]63a414b52010-06-03 23:20:49243 ASSERT_EQ(2u, items->size());
244 ASSERT_EQ(item1, items->at(0));
245 ASSERT_EQ(item2, items->at(1));
[email protected]66dbfb2c2010-05-12 20:20:15246
247 // Now create a third item, initially add it as a child of item1, then move
248 // it to be a child of item2.
[email protected]052c92702010-06-25 07:25:52249 ExtensionMenuItem* item3 = CreateTestItem(extension1);
[email protected]66dbfb2c2010-05-12 20:20:15250
[email protected]f4f04592010-07-14 20:40:13251 ASSERT_TRUE(manager_.AddChildItem(item1->id(), item3));
[email protected]66dbfb2c2010-05-12 20:20:15252 ASSERT_EQ(1, item1->child_count());
[email protected]63a414b52010-06-03 23:20:49253 ASSERT_EQ(item3, item1->children()[0]);
[email protected]66dbfb2c2010-05-12 20:20:15254
[email protected]f4f04592010-07-14 20:40:13255 ASSERT_TRUE(manager_.ChangeParent(item3->id(), &item2->id()));
[email protected]66dbfb2c2010-05-12 20:20:15256 ASSERT_EQ(0, item1->child_count());
257 ASSERT_EQ(1, item2->child_count());
[email protected]63a414b52010-06-03 23:20:49258 ASSERT_EQ(item3, item2->children()[0]);
[email protected]66dbfb2c2010-05-12 20:20:15259
260 // Move item2 to be a child of item1.
[email protected]f4f04592010-07-14 20:40:13261 ASSERT_TRUE(manager_.ChangeParent(item2->id(), &item1->id()));
[email protected]66dbfb2c2010-05-12 20:20:15262 ASSERT_EQ(1, item1->child_count());
[email protected]63a414b52010-06-03 23:20:49263 ASSERT_EQ(item2, item1->children()[0]);
[email protected]66dbfb2c2010-05-12 20:20:15264 ASSERT_EQ(1, item2->child_count());
[email protected]63a414b52010-06-03 23:20:49265 ASSERT_EQ(item3, item2->children()[0]);
[email protected]66dbfb2c2010-05-12 20:20:15266
267 // Since item2 was a top-level item but is no longer, we should only have 1
268 // top-level item.
269 items = manager_.MenuItems(item1->extension_id());
[email protected]63a414b52010-06-03 23:20:49270 ASSERT_EQ(1u, items->size());
271 ASSERT_EQ(item1, items->at(0));
[email protected]66dbfb2c2010-05-12 20:20:15272
273 // Move item3 back to being a child of item1, so it's now a sibling of item2.
[email protected]f4f04592010-07-14 20:40:13274 ASSERT_TRUE(manager_.ChangeParent(item3->id(), &item1->id()));
[email protected]66dbfb2c2010-05-12 20:20:15275 ASSERT_EQ(2, item1->child_count());
[email protected]63a414b52010-06-03 23:20:49276 ASSERT_EQ(item2, item1->children()[0]);
277 ASSERT_EQ(item3, item1->children()[1]);
[email protected]66dbfb2c2010-05-12 20:20:15278
279 // Try switching item3 to be the parent of item1 - this should fail.
[email protected]f4f04592010-07-14 20:40:13280 ASSERT_FALSE(manager_.ChangeParent(item1->id(), &item3->id()));
[email protected]66dbfb2c2010-05-12 20:20:15281 ASSERT_EQ(0, item3->child_count());
282 ASSERT_EQ(2, item1->child_count());
[email protected]63a414b52010-06-03 23:20:49283 ASSERT_EQ(item2, item1->children()[0]);
284 ASSERT_EQ(item3, item1->children()[1]);
[email protected]66dbfb2c2010-05-12 20:20:15285 items = manager_.MenuItems(item1->extension_id());
[email protected]63a414b52010-06-03 23:20:49286 ASSERT_EQ(1u, items->size());
287 ASSERT_EQ(item1, items->at(0));
[email protected]66dbfb2c2010-05-12 20:20:15288
289 // Move item2 to be a top-level item.
[email protected]f4f04592010-07-14 20:40:13290 ASSERT_TRUE(manager_.ChangeParent(item2->id(), NULL));
[email protected]66dbfb2c2010-05-12 20:20:15291 items = manager_.MenuItems(item1->extension_id());
[email protected]63a414b52010-06-03 23:20:49292 ASSERT_EQ(2u, items->size());
293 ASSERT_EQ(item1, items->at(0));
294 ASSERT_EQ(item2, items->at(1));
[email protected]66dbfb2c2010-05-12 20:20:15295 ASSERT_EQ(1, item1->child_count());
[email protected]63a414b52010-06-03 23:20:49296 ASSERT_EQ(item3, item1->children()[0]);
[email protected]66dbfb2c2010-05-12 20:20:15297
298 // Make sure you can't move a node to be a child of another extension's item.
[email protected]052c92702010-06-25 07:25:52299 Extension* extension2 = AddExtension("2222");
300 ExtensionMenuItem* item4 = CreateTestItem(extension2);
[email protected]f4f04592010-07-14 20:40:13301 ASSERT_TRUE(manager_.AddContextItem(extension2, item4));
302 ASSERT_FALSE(manager_.ChangeParent(item4->id(), &item1->id()));
303 ASSERT_FALSE(manager_.ChangeParent(item1->id(), &item4->id()));
[email protected]66dbfb2c2010-05-12 20:20:15304
305 // Make sure you can't make an item be it's own parent.
[email protected]f4f04592010-07-14 20:40:13306 ASSERT_FALSE(manager_.ChangeParent(item1->id(), &item1->id()));
[email protected]66dbfb2c2010-05-12 20:20:15307}
308
[email protected]2e3b5202010-03-23 06:52:41309// Tests that we properly remove an extension's menu item when that extension is
310// unloaded.
311TEST_F(ExtensionMenuManagerTest, ExtensionUnloadRemovesMenuItems) {
[email protected]2e3b5202010-03-23 06:52:41312 NotificationService* notifier = NotificationService::current();
313 ASSERT_TRUE(notifier != NULL);
314
315 // Create a test extension.
[email protected]052c92702010-06-25 07:25:52316 Extension* extension1 = AddExtension("1111");
[email protected]2e3b5202010-03-23 06:52:41317
318 // Create an ExtensionMenuItem and put it into the manager.
[email protected]052c92702010-06-25 07:25:52319 ExtensionMenuItem* item1 = CreateTestItem(extension1);
[email protected]f4f04592010-07-14 20:40:13320 ExtensionMenuItem::Id id1 = item1->id();
[email protected]052c92702010-06-25 07:25:52321 ASSERT_EQ(extension1->id(), item1->extension_id());
[email protected]f4f04592010-07-14 20:40:13322 ASSERT_TRUE(manager_.AddContextItem(extension1, item1));
[email protected]052c92702010-06-25 07:25:52323 ASSERT_EQ(1u, manager_.MenuItems(extension1->id())->size());
[email protected]2e3b5202010-03-23 06:52:41324
325 // Create a menu item with a different extension id and add it to the manager.
[email protected]052c92702010-06-25 07:25:52326 Extension* extension2 = AddExtension("2222");
327 ExtensionMenuItem* item2 = CreateTestItem(extension2);
[email protected]2e3b5202010-03-23 06:52:41328 ASSERT_NE(item1->extension_id(), item2->extension_id());
[email protected]f4f04592010-07-14 20:40:13329 ASSERT_TRUE(manager_.AddContextItem(extension2, item2));
[email protected]2e3b5202010-03-23 06:52:41330
331 // Notify that the extension was unloaded, and make sure the right item is
332 // gone.
[email protected]814a7bf0f2011-08-13 05:30:59333 UnloadedExtensionInfo details(
334 extension1, extension_misc::UNLOAD_REASON_DISABLE);
[email protected]432115822011-07-10 15:52:27335 notifier->Notify(chrome::NOTIFICATION_EXTENSION_UNLOADED,
[email protected]2e3b5202010-03-23 06:52:41336 Source<Profile>(NULL),
[email protected]a9f39a312010-12-23 22:14:27337 Details<UnloadedExtensionInfo>(&details));
[email protected]052c92702010-06-25 07:25:52338 ASSERT_EQ(NULL, manager_.MenuItems(extension1->id()));
339 ASSERT_EQ(1u, manager_.MenuItems(extension2->id())->size());
[email protected]2e3b5202010-03-23 06:52:41340 ASSERT_TRUE(manager_.GetItemById(id1) == NULL);
[email protected]f4f04592010-07-14 20:40:13341 ASSERT_TRUE(manager_.GetItemById(item2->id()) != NULL);
[email protected]2e3b5202010-03-23 06:52:41342}
343
344// A mock message service for tests of ExtensionMenuManager::ExecuteCommand.
[email protected]2c699652010-10-15 18:22:41345class MockExtensionEventRouter : public ExtensionEventRouter {
[email protected]2e3b5202010-03-23 06:52:41346 public:
[email protected]2c699652010-10-15 18:22:41347 explicit MockExtensionEventRouter(Profile* profile) :
348 ExtensionEventRouter(profile) {}
[email protected]2e3b5202010-03-23 06:52:41349
[email protected]f72d0c62011-08-31 16:27:44350 MOCK_METHOD5(DispatchEventToExtension, void(const std::string& extension_id,
351 const std::string& event_name,
352 const std::string& event_args,
353 Profile* source_profile,
354 const GURL& event_url));
355
[email protected]2e3b5202010-03-23 06:52:41356
357 private:
[email protected]2c699652010-10-15 18:22:41358 DISALLOW_COPY_AND_ASSIGN(MockExtensionEventRouter);
[email protected]2e3b5202010-03-23 06:52:41359};
360
361// A mock profile for tests of ExtensionMenuManager::ExecuteCommand.
362class MockTestingProfile : public TestingProfile {
363 public:
364 MockTestingProfile() {}
[email protected]2c699652010-10-15 18:22:41365 MOCK_METHOD0(GetExtensionEventRouter, ExtensionEventRouter*());
[email protected]2e3b5202010-03-23 06:52:41366 MOCK_METHOD0(IsOffTheRecord, bool());
367
368 private:
369 DISALLOW_COPY_AND_ASSIGN(MockTestingProfile);
370};
371
[email protected]66dbfb2c2010-05-12 20:20:15372// Tests the RemoveAll functionality.
373TEST_F(ExtensionMenuManagerTest, RemoveAll) {
374 // Try removing all items for an extension id that doesn't have any items.
375 manager_.RemoveAllContextItems("CCCC");
376
[email protected]052c92702010-06-25 07:25:52377 // Add 2 top-level and one child item for extension 1.
378 Extension* extension1 = AddExtension("1111");
379 ExtensionMenuItem* item1 = CreateTestItem(extension1);
380 ExtensionMenuItem* item2 = CreateTestItem(extension1);
381 ExtensionMenuItem* item3 = CreateTestItem(extension1);
[email protected]f4f04592010-07-14 20:40:13382 ASSERT_TRUE(manager_.AddContextItem(extension1, item1));
383 ASSERT_TRUE(manager_.AddContextItem(extension1, item2));
384 ASSERT_TRUE(manager_.AddChildItem(item1->id(), item3));
[email protected]66dbfb2c2010-05-12 20:20:15385
[email protected]052c92702010-06-25 07:25:52386 // Add one top-level item for extension 2.
387 Extension* extension2 = AddExtension("2222");
388 ExtensionMenuItem* item4 = CreateTestItem(extension2);
[email protected]f4f04592010-07-14 20:40:13389 ASSERT_TRUE(manager_.AddContextItem(extension2, item4));
[email protected]66dbfb2c2010-05-12 20:20:15390
[email protected]052c92702010-06-25 07:25:52391 EXPECT_EQ(2u, manager_.MenuItems(extension1->id())->size());
392 EXPECT_EQ(1u, manager_.MenuItems(extension2->id())->size());
[email protected]66dbfb2c2010-05-12 20:20:15393
[email protected]052c92702010-06-25 07:25:52394 // Remove extension2's item.
395 manager_.RemoveAllContextItems(extension2->id());
396 EXPECT_EQ(2u, manager_.MenuItems(extension1->id())->size());
397 EXPECT_EQ(NULL, manager_.MenuItems(extension2->id()));
[email protected]66dbfb2c2010-05-12 20:20:15398
[email protected]052c92702010-06-25 07:25:52399 // Remove extension1's items.
400 manager_.RemoveAllContextItems(extension1->id());
401 EXPECT_EQ(NULL, manager_.MenuItems(extension1->id()));
[email protected]66dbfb2c2010-05-12 20:20:15402}
403
[email protected]f50da8592010-10-28 23:39:32404// Tests that removing all items one-by-one doesn't leave an entry around.
405TEST_F(ExtensionMenuManagerTest, RemoveOneByOne) {
406 // Add 2 test items.
407 Extension* extension1 = AddExtension("1111");
408 ExtensionMenuItem* item1 = CreateTestItem(extension1);
409 ExtensionMenuItem* item2 = CreateTestItem(extension1);
410 ASSERT_TRUE(manager_.AddContextItem(extension1, item1));
411 ASSERT_TRUE(manager_.AddContextItem(extension1, item2));
412
413 ASSERT_FALSE(manager_.context_items_.empty());
414
415 manager_.RemoveContextMenuItem(item1->id());
416 manager_.RemoveContextMenuItem(item2->id());
417
418 ASSERT_TRUE(manager_.context_items_.empty());
419}
420
[email protected]2e3b5202010-03-23 06:52:41421TEST_F(ExtensionMenuManagerTest, ExecuteCommand) {
[email protected]2e3b5202010-03-23 06:52:41422 MockTestingProfile profile;
423
[email protected]2c699652010-10-15 18:22:41424 scoped_ptr<MockExtensionEventRouter> mock_event_router(
425 new MockExtensionEventRouter(&profile));
[email protected]2e3b5202010-03-23 06:52:41426
427 ContextMenuParams params;
428 params.media_type = WebKit::WebContextMenuData::MediaTypeImage;
429 params.src_url = GURL("http://foo.bar/image.png");
430 params.page_url = GURL("http://foo.bar");
[email protected]944b4212010-12-14 00:00:33431 params.selection_text = ASCIIToUTF16("Hello World");
[email protected]2e3b5202010-03-23 06:52:41432 params.is_editable = false;
433
[email protected]052c92702010-06-25 07:25:52434 Extension* extension = AddExtension("test");
435 ExtensionMenuItem* item = CreateTestItem(extension);
[email protected]f4f04592010-07-14 20:40:13436 ExtensionMenuItem::Id id = item->id();
437 ASSERT_TRUE(manager_.AddContextItem(extension, item));
[email protected]2e3b5202010-03-23 06:52:41438
[email protected]2c699652010-10-15 18:22:41439 EXPECT_CALL(profile, GetExtensionEventRouter())
[email protected]2e3b5202010-03-23 06:52:41440 .Times(1)
[email protected]2c699652010-10-15 18:22:41441 .WillOnce(Return(mock_event_router.get()));
[email protected]2e3b5202010-03-23 06:52:41442
[email protected]2e3b5202010-03-23 06:52:41443 // Use the magic of googlemock to save a parameter to our mock's
[email protected]0a184b52011-06-23 00:41:13444 // DispatchEventToExtension method into event_args.
[email protected]2e3b5202010-03-23 06:52:41445 std::string event_args;
[email protected]a7ab1b782010-10-21 23:24:16446 std::string expected_event_name = "contextMenus";
[email protected]2c699652010-10-15 18:22:41447 EXPECT_CALL(*mock_event_router.get(),
[email protected]f72d0c62011-08-31 16:27:44448 DispatchEventToExtension(item->extension_id(),
449 expected_event_name,
450 _,
451 &profile,
452 GURL()))
[email protected]2e3b5202010-03-23 06:52:41453 .Times(1)
[email protected]a7ab1b782010-10-21 23:24:16454 .WillOnce(SaveArg<2>(&event_args));
[email protected]2e3b5202010-03-23 06:52:41455
456 manager_.ExecuteCommand(&profile, NULL /* tab_contents */, params, id);
457
458 // Parse the json event_args, which should turn into a 2-element list where
459 // the first element is a dictionary we want to inspect for the correct
460 // values.
461 scoped_ptr<Value> result(base::JSONReader::Read(event_args, true));
462 Value* value = result.get();
463 ASSERT_TRUE(result.get() != NULL);
464 ASSERT_EQ(Value::TYPE_LIST, value->GetType());
465 ListValue* list = static_cast<ListValue*>(value);
466 ASSERT_EQ(2u, list->GetSize());
467
468 DictionaryValue* info;
469 ASSERT_TRUE(list->GetDictionary(0, &info));
470
471 int tmp_id = 0;
[email protected]88dc0692010-08-14 16:29:42472 ASSERT_TRUE(info->GetInteger("menuItemId", &tmp_id));
[email protected]5a7b5eaf2010-11-02 20:52:19473 ASSERT_EQ(id.uid, tmp_id);
[email protected]2e3b5202010-03-23 06:52:41474
475 std::string tmp;
[email protected]88dc0692010-08-14 16:29:42476 ASSERT_TRUE(info->GetString("mediaType", &tmp));
[email protected]1741b972010-08-04 23:47:41477 ASSERT_EQ("image", tmp);
[email protected]88dc0692010-08-14 16:29:42478 ASSERT_TRUE(info->GetString("srcUrl", &tmp));
[email protected]2e3b5202010-03-23 06:52:41479 ASSERT_EQ(params.src_url.spec(), tmp);
[email protected]88dc0692010-08-14 16:29:42480 ASSERT_TRUE(info->GetString("pageUrl", &tmp));
[email protected]2e3b5202010-03-23 06:52:41481 ASSERT_EQ(params.page_url.spec(), tmp);
482
[email protected]944b4212010-12-14 00:00:33483 string16 tmp16;
484 ASSERT_TRUE(info->GetString("selectionText", &tmp16));
485 ASSERT_EQ(params.selection_text, tmp16);
[email protected]2e3b5202010-03-23 06:52:41486
487 bool bool_tmp = true;
[email protected]88dc0692010-08-14 16:29:42488 ASSERT_TRUE(info->GetBoolean("editable", &bool_tmp));
[email protected]2e3b5202010-03-23 06:52:41489 ASSERT_EQ(params.is_editable, bool_tmp);
490}