Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(716)

Side by Side Diff: chrome/browser/extensions/extension_menu_manager_unittest.cc

Issue 10664037: Moved ExtensionMenuManager and ExtensionMenuItem into extensions namespace (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Merged with latest master Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 <vector>
6
7 #include "base/json/json_reader.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/scoped_temp_dir.h"
12 #include "base/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/extensions/extension_event_names.h"
15 #include "chrome/browser/extensions/extension_event_router.h"
16 #include "chrome/browser/extensions/extension_menu_manager.h"
17 #include "chrome/browser/extensions/test_extension_prefs.h"
18 #include "chrome/common/chrome_notification_types.h"
19 #include "chrome/common/chrome_paths.h"
20 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/extensions/extension_constants.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "content/public/browser/notification_service.h"
24 #include "content/public/common/context_menu_params.h"
25 #include "content/public/test/test_browser_thread.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 using content::BrowserThread;
30 using extensions::Extension;
31 using testing::_;
32 using testing::AtLeast;
33 using testing::InSequence;
34 using testing::Return;
35 using testing::SaveArg;
36
37 // Base class for tests.
38 class ExtensionMenuManagerTest : public testing::Test {
39 public:
40 ExtensionMenuManagerTest()
41 : ui_thread_(BrowserThread::UI, &message_loop_),
42 file_thread_(BrowserThread::FILE, &message_loop_),
43 manager_(&profile_),
44 next_id_(1) {
45 }
46
47 // Returns a test item.
48 ExtensionMenuItem* CreateTestItem(Extension* extension) {
49 ExtensionMenuItem::Type type = ExtensionMenuItem::NORMAL;
50 ExtensionMenuItem::ContextList contexts(ExtensionMenuItem::ALL);
51 ExtensionMenuItem::Id id(false, extension->id());
52 id.uid = next_id_++;
53 return new ExtensionMenuItem(id, "test", false, true, type, contexts);
54 }
55
56 // Returns a test item with the given string ID.
57 ExtensionMenuItem* CreateTestItemWithID(Extension* extension,
58 const std::string& string_id) {
59 ExtensionMenuItem::Type type = ExtensionMenuItem::NORMAL;
60 ExtensionMenuItem::ContextList contexts(ExtensionMenuItem::ALL);
61 ExtensionMenuItem::Id id(false, extension->id());
62 id.string_uid = string_id;
63 return new ExtensionMenuItem(id, "test", false, true, type, contexts);
64 }
65
66 // Creates and returns a test Extension. The caller does *not* own the return
67 // value.
68 Extension* AddExtension(std::string name) {
69 scoped_refptr<Extension> extension = prefs_.AddExtension(name);
70 extensions_.push_back(extension);
71 return extension;
72 }
73
74 protected:
75 TestingProfile profile_;
76 MessageLoopForUI message_loop_;
77 content::TestBrowserThread ui_thread_;
78 content::TestBrowserThread file_thread_;
79
80 ExtensionMenuManager manager_;
81 extensions::ExtensionList extensions_;
82 TestExtensionPrefs prefs_;
83 int next_id_;
84
85 private:
86 DISALLOW_COPY_AND_ASSIGN(ExtensionMenuManagerTest);
87 };
88
89 // Tests adding, getting, and removing items.
90 TEST_F(ExtensionMenuManagerTest, AddGetRemoveItems) {
91 Extension* extension = AddExtension("test");
92
93 // Add a new item, make sure you can get it back.
94 ExtensionMenuItem* item1 = CreateTestItem(extension);
95 ASSERT_TRUE(item1 != NULL);
96 ASSERT_TRUE(manager_.AddContextItem(extension, item1));
97 ASSERT_EQ(item1, manager_.GetItemById(item1->id()));
98 const ExtensionMenuItem::List* items =
99 manager_.MenuItems(item1->extension_id());
100 ASSERT_EQ(1u, items->size());
101 ASSERT_EQ(item1, items->at(0));
102
103 // Add a second item, make sure it comes back too.
104 ExtensionMenuItem* item2 = CreateTestItemWithID(extension, "id2");
105 ASSERT_TRUE(manager_.AddContextItem(extension, item2));
106 ASSERT_EQ(item2, manager_.GetItemById(item2->id()));
107 items = manager_.MenuItems(item2->extension_id());
108 ASSERT_EQ(2u, items->size());
109 ASSERT_EQ(item1, items->at(0));
110 ASSERT_EQ(item2, items->at(1));
111
112 // Try adding item 3, then removing it.
113 ExtensionMenuItem* item3 = CreateTestItem(extension);
114 ExtensionMenuItem::Id id3 = item3->id();
115 std::string extension_id = item3->extension_id();
116 ASSERT_TRUE(manager_.AddContextItem(extension, item3));
117 ASSERT_EQ(item3, manager_.GetItemById(id3));
118 ASSERT_EQ(3u, manager_.MenuItems(extension_id)->size());
119 ASSERT_TRUE(manager_.RemoveContextMenuItem(id3));
120 ASSERT_EQ(NULL, manager_.GetItemById(id3));
121 ASSERT_EQ(2u, manager_.MenuItems(extension_id)->size());
122
123 // Make sure removing a non-existent item returns false.
124 ExtensionMenuItem::Id id(false, extension->id());
125 id.uid = id3.uid + 50;
126 ASSERT_FALSE(manager_.RemoveContextMenuItem(id));
127
128 // Make sure adding an item with the same string ID returns false.
129 scoped_ptr<ExtensionMenuItem> item2too(
130 CreateTestItemWithID(extension, "id2"));
131 ASSERT_FALSE(manager_.AddContextItem(extension, item2too.get()));
132
133 // But the same string ID should not collide with another extension.
134 Extension* extension2 = AddExtension("test2");
135 ExtensionMenuItem* item2other = CreateTestItemWithID(extension2, "id2");
136 ASSERT_TRUE(manager_.AddContextItem(extension2, item2other));
137 }
138
139 // Test adding/removing child items.
140 TEST_F(ExtensionMenuManagerTest, ChildFunctions) {
141 Extension* extension1 = AddExtension("1111");
142 Extension* extension2 = AddExtension("2222");
143 Extension* extension3 = AddExtension("3333");
144
145 ExtensionMenuItem* item1 = CreateTestItem(extension1);
146 ExtensionMenuItem* item2 = CreateTestItem(extension2);
147 ExtensionMenuItem* item2_child = CreateTestItemWithID(extension2, "2child");
148 ExtensionMenuItem* item2_grandchild = CreateTestItem(extension2);
149
150 // This third item we expect to fail inserting, so we use a scoped_ptr to make
151 // sure it gets deleted.
152 scoped_ptr<ExtensionMenuItem> item3(CreateTestItem(extension3));
153
154 // Add in the first two items.
155 ASSERT_TRUE(manager_.AddContextItem(extension1, item1));
156 ASSERT_TRUE(manager_.AddContextItem(extension2, item2));
157
158 ExtensionMenuItem::Id id1 = item1->id();
159 ExtensionMenuItem::Id id2 = item2->id();
160
161 // Try adding item3 as a child of item2 - this should fail because item3 has
162 // a different extension id.
163 ASSERT_FALSE(manager_.AddChildItem(id2, item3.get()));
164
165 // Add item2_child as a child of item2.
166 ExtensionMenuItem::Id id2_child = item2_child->id();
167 ASSERT_TRUE(manager_.AddChildItem(id2, item2_child));
168 ASSERT_EQ(1, item2->child_count());
169 ASSERT_EQ(0, item1->child_count());
170 ASSERT_EQ(item2_child, manager_.GetItemById(id2_child));
171
172 ASSERT_EQ(1u, manager_.MenuItems(item1->extension_id())->size());
173 ASSERT_EQ(item1, manager_.MenuItems(item1->extension_id())->at(0));
174
175 // Add item2_grandchild as a child of item2_child, then remove it.
176 ExtensionMenuItem::Id id2_grandchild = item2_grandchild->id();
177 ASSERT_TRUE(manager_.AddChildItem(id2_child, item2_grandchild));
178 ASSERT_EQ(1, item2->child_count());
179 ASSERT_EQ(1, item2_child->child_count());
180 ASSERT_TRUE(manager_.RemoveContextMenuItem(id2_grandchild));
181
182 // We should only get 1 thing back when asking for item2's extension id, since
183 // it has a child item.
184 ASSERT_EQ(1u, manager_.MenuItems(item2->extension_id())->size());
185 ASSERT_EQ(item2, manager_.MenuItems(item2->extension_id())->at(0));
186
187 // Remove child2_item.
188 ASSERT_TRUE(manager_.RemoveContextMenuItem(id2_child));
189 ASSERT_EQ(1u, manager_.MenuItems(item2->extension_id())->size());
190 ASSERT_EQ(item2, manager_.MenuItems(item2->extension_id())->at(0));
191 ASSERT_EQ(0, item2->child_count());
192 }
193
194 // Tests that deleting a parent properly removes descendants.
195 TEST_F(ExtensionMenuManagerTest, DeleteParent) {
196 Extension* extension = AddExtension("1111");
197
198 // Set up 5 items to add.
199 ExtensionMenuItem* item1 = CreateTestItem(extension);
200 ExtensionMenuItem* item2 = CreateTestItem(extension);
201 ExtensionMenuItem* item3 = CreateTestItemWithID(extension, "id3");
202 ExtensionMenuItem* item4 = CreateTestItemWithID(extension, "id4");
203 ExtensionMenuItem* item5 = CreateTestItem(extension);
204 ExtensionMenuItem* item6 = CreateTestItem(extension);
205 ExtensionMenuItem::Id item1_id = item1->id();
206 ExtensionMenuItem::Id item2_id = item2->id();
207 ExtensionMenuItem::Id item3_id = item3->id();
208 ExtensionMenuItem::Id item4_id = item4->id();
209 ExtensionMenuItem::Id item5_id = item5->id();
210 ExtensionMenuItem::Id item6_id = item6->id();
211
212 // Add the items in the hierarchy
213 // item1 -> item2 -> item3 -> item4 -> item5 -> item6.
214 ASSERT_TRUE(manager_.AddContextItem(extension, item1));
215 ASSERT_TRUE(manager_.AddChildItem(item1_id, item2));
216 ASSERT_TRUE(manager_.AddChildItem(item2_id, item3));
217 ASSERT_TRUE(manager_.AddChildItem(item3_id, item4));
218 ASSERT_TRUE(manager_.AddChildItem(item4_id, item5));
219 ASSERT_TRUE(manager_.AddChildItem(item5_id, item6));
220 ASSERT_EQ(item1, manager_.GetItemById(item1_id));
221 ASSERT_EQ(item2, manager_.GetItemById(item2_id));
222 ASSERT_EQ(item3, manager_.GetItemById(item3_id));
223 ASSERT_EQ(item4, manager_.GetItemById(item4_id));
224 ASSERT_EQ(item5, manager_.GetItemById(item5_id));
225 ASSERT_EQ(item6, manager_.GetItemById(item6_id));
226 ASSERT_EQ(1u, manager_.MenuItems(extension->id())->size());
227 ASSERT_EQ(6u, manager_.items_by_id_.size());
228
229 // Remove item6 (a leaf node).
230 ASSERT_TRUE(manager_.RemoveContextMenuItem(item6_id));
231 ASSERT_EQ(item1, manager_.GetItemById(item1_id));
232 ASSERT_EQ(item2, manager_.GetItemById(item2_id));
233 ASSERT_EQ(item3, manager_.GetItemById(item3_id));
234 ASSERT_EQ(item4, manager_.GetItemById(item4_id));
235 ASSERT_EQ(item5, manager_.GetItemById(item5_id));
236 ASSERT_EQ(NULL, manager_.GetItemById(item6_id));
237 ASSERT_EQ(1u, manager_.MenuItems(extension->id())->size());
238 ASSERT_EQ(5u, manager_.items_by_id_.size());
239
240 // Remove item4 and make sure item5 is gone as well.
241 ASSERT_TRUE(manager_.RemoveContextMenuItem(item4_id));
242 ASSERT_EQ(item1, manager_.GetItemById(item1_id));
243 ASSERT_EQ(item2, manager_.GetItemById(item2_id));
244 ASSERT_EQ(item3, manager_.GetItemById(item3_id));
245 ASSERT_EQ(NULL, manager_.GetItemById(item4_id));
246 ASSERT_EQ(NULL, manager_.GetItemById(item5_id));
247 ASSERT_EQ(1u, manager_.MenuItems(extension->id())->size());
248 ASSERT_EQ(3u, manager_.items_by_id_.size());
249
250 // Now remove item1 and make sure item2 and item3 are gone as well.
251 ASSERT_TRUE(manager_.RemoveContextMenuItem(item1_id));
252 ASSERT_EQ(NULL, manager_.MenuItems(extension->id()));
253 ASSERT_EQ(0u, manager_.items_by_id_.size());
254 ASSERT_EQ(NULL, manager_.GetItemById(item1_id));
255 ASSERT_EQ(NULL, manager_.GetItemById(item2_id));
256 ASSERT_EQ(NULL, manager_.GetItemById(item3_id));
257 }
258
259 // Tests changing parents.
260 TEST_F(ExtensionMenuManagerTest, ChangeParent) {
261 Extension* extension1 = AddExtension("1111");
262
263 // First create two items and add them both to the manager.
264 ExtensionMenuItem* item1 = CreateTestItem(extension1);
265 ExtensionMenuItem* item2 = CreateTestItem(extension1);
266
267 ASSERT_TRUE(manager_.AddContextItem(extension1, item1));
268 ASSERT_TRUE(manager_.AddContextItem(extension1, item2));
269
270 const ExtensionMenuItem::List* items =
271 manager_.MenuItems(item1->extension_id());
272 ASSERT_EQ(2u, items->size());
273 ASSERT_EQ(item1, items->at(0));
274 ASSERT_EQ(item2, items->at(1));
275
276 // Now create a third item, initially add it as a child of item1, then move
277 // it to be a child of item2.
278 ExtensionMenuItem* item3 = CreateTestItem(extension1);
279
280 ASSERT_TRUE(manager_.AddChildItem(item1->id(), item3));
281 ASSERT_EQ(1, item1->child_count());
282 ASSERT_EQ(item3, item1->children()[0]);
283
284 ASSERT_TRUE(manager_.ChangeParent(item3->id(), &item2->id()));
285 ASSERT_EQ(0, item1->child_count());
286 ASSERT_EQ(1, item2->child_count());
287 ASSERT_EQ(item3, item2->children()[0]);
288
289 // Move item2 to be a child of item1.
290 ASSERT_TRUE(manager_.ChangeParent(item2->id(), &item1->id()));
291 ASSERT_EQ(1, item1->child_count());
292 ASSERT_EQ(item2, item1->children()[0]);
293 ASSERT_EQ(1, item2->child_count());
294 ASSERT_EQ(item3, item2->children()[0]);
295
296 // Since item2 was a top-level item but is no longer, we should only have 1
297 // top-level item.
298 items = manager_.MenuItems(item1->extension_id());
299 ASSERT_EQ(1u, items->size());
300 ASSERT_EQ(item1, items->at(0));
301
302 // Move item3 back to being a child of item1, so it's now a sibling of item2.
303 ASSERT_TRUE(manager_.ChangeParent(item3->id(), &item1->id()));
304 ASSERT_EQ(2, item1->child_count());
305 ASSERT_EQ(item2, item1->children()[0]);
306 ASSERT_EQ(item3, item1->children()[1]);
307
308 // Try switching item3 to be the parent of item1 - this should fail.
309 ASSERT_FALSE(manager_.ChangeParent(item1->id(), &item3->id()));
310 ASSERT_EQ(0, item3->child_count());
311 ASSERT_EQ(2, item1->child_count());
312 ASSERT_EQ(item2, item1->children()[0]);
313 ASSERT_EQ(item3, item1->children()[1]);
314 items = manager_.MenuItems(item1->extension_id());
315 ASSERT_EQ(1u, items->size());
316 ASSERT_EQ(item1, items->at(0));
317
318 // Move item2 to be a top-level item.
319 ASSERT_TRUE(manager_.ChangeParent(item2->id(), NULL));
320 items = manager_.MenuItems(item1->extension_id());
321 ASSERT_EQ(2u, items->size());
322 ASSERT_EQ(item1, items->at(0));
323 ASSERT_EQ(item2, items->at(1));
324 ASSERT_EQ(1, item1->child_count());
325 ASSERT_EQ(item3, item1->children()[0]);
326
327 // Make sure you can't move a node to be a child of another extension's item.
328 Extension* extension2 = AddExtension("2222");
329 ExtensionMenuItem* item4 = CreateTestItem(extension2);
330 ASSERT_TRUE(manager_.AddContextItem(extension2, item4));
331 ASSERT_FALSE(manager_.ChangeParent(item4->id(), &item1->id()));
332 ASSERT_FALSE(manager_.ChangeParent(item1->id(), &item4->id()));
333
334 // Make sure you can't make an item be it's own parent.
335 ASSERT_FALSE(manager_.ChangeParent(item1->id(), &item1->id()));
336 }
337
338 // Tests that we properly remove an extension's menu item when that extension is
339 // unloaded.
340 TEST_F(ExtensionMenuManagerTest, ExtensionUnloadRemovesMenuItems) {
341 content::NotificationService* notifier =
342 content::NotificationService::current();
343 ASSERT_TRUE(notifier != NULL);
344
345 // Create a test extension.
346 Extension* extension1 = AddExtension("1111");
347
348 // Create an ExtensionMenuItem and put it into the manager.
349 ExtensionMenuItem* item1 = CreateTestItem(extension1);
350 ExtensionMenuItem::Id id1 = item1->id();
351 ASSERT_EQ(extension1->id(), item1->extension_id());
352 ASSERT_TRUE(manager_.AddContextItem(extension1, item1));
353 ASSERT_EQ(1u, manager_.MenuItems(extension1->id())->size());
354
355 // Create a menu item with a different extension id and add it to the manager.
356 Extension* extension2 = AddExtension("2222");
357 ExtensionMenuItem* item2 = CreateTestItem(extension2);
358 ASSERT_NE(item1->extension_id(), item2->extension_id());
359 ASSERT_TRUE(manager_.AddContextItem(extension2, item2));
360
361 // Notify that the extension was unloaded, and make sure the right item is
362 // gone.
363 extensions::UnloadedExtensionInfo details(
364 extension1, extension_misc::UNLOAD_REASON_DISABLE);
365 notifier->Notify(chrome::NOTIFICATION_EXTENSION_UNLOADED,
366 content::Source<Profile>(&profile_),
367 content::Details<extensions::UnloadedExtensionInfo>(
368 &details));
369 ASSERT_EQ(NULL, manager_.MenuItems(extension1->id()));
370 ASSERT_EQ(1u, manager_.MenuItems(extension2->id())->size());
371 ASSERT_TRUE(manager_.GetItemById(id1) == NULL);
372 ASSERT_TRUE(manager_.GetItemById(item2->id()) != NULL);
373 }
374
375 // A mock message service for tests of ExtensionMenuManager::ExecuteCommand.
376 class MockExtensionEventRouter : public ExtensionEventRouter {
377 public:
378 explicit MockExtensionEventRouter(Profile* profile) :
379 ExtensionEventRouter(profile) {}
380
381 MOCK_METHOD6(DispatchEventToExtension,
382 void(const std::string& extension_id,
383 const std::string& event_name,
384 const std::string& event_args,
385 Profile* source_profile,
386 const GURL& event_url,
387 ExtensionEventRouter::UserGestureState state));
388
389
390 private:
391 DISALLOW_COPY_AND_ASSIGN(MockExtensionEventRouter);
392 };
393
394 // A mock profile for tests of ExtensionMenuManager::ExecuteCommand.
395 class MockTestingProfile : public TestingProfile {
396 public:
397 MockTestingProfile() {}
398 MOCK_METHOD0(GetExtensionEventRouter, ExtensionEventRouter*());
399
400 private:
401 DISALLOW_COPY_AND_ASSIGN(MockTestingProfile);
402 };
403
404 // Tests the RemoveAll functionality.
405 TEST_F(ExtensionMenuManagerTest, RemoveAll) {
406 // Try removing all items for an extension id that doesn't have any items.
407 manager_.RemoveAllContextItems("CCCC");
408
409 // Add 2 top-level and one child item for extension 1.
410 Extension* extension1 = AddExtension("1111");
411 ExtensionMenuItem* item1 = CreateTestItem(extension1);
412 ExtensionMenuItem* item2 = CreateTestItem(extension1);
413 ExtensionMenuItem* item3 = CreateTestItem(extension1);
414 ASSERT_TRUE(manager_.AddContextItem(extension1, item1));
415 ASSERT_TRUE(manager_.AddContextItem(extension1, item2));
416 ASSERT_TRUE(manager_.AddChildItem(item1->id(), item3));
417
418 // Add one top-level item for extension 2.
419 Extension* extension2 = AddExtension("2222");
420 ExtensionMenuItem* item4 = CreateTestItem(extension2);
421 ASSERT_TRUE(manager_.AddContextItem(extension2, item4));
422
423 EXPECT_EQ(2u, manager_.MenuItems(extension1->id())->size());
424 EXPECT_EQ(1u, manager_.MenuItems(extension2->id())->size());
425
426 // Remove extension2's item.
427 manager_.RemoveAllContextItems(extension2->id());
428 EXPECT_EQ(2u, manager_.MenuItems(extension1->id())->size());
429 EXPECT_EQ(NULL, manager_.MenuItems(extension2->id()));
430
431 // Remove extension1's items.
432 manager_.RemoveAllContextItems(extension1->id());
433 EXPECT_EQ(NULL, manager_.MenuItems(extension1->id()));
434 }
435
436 // Tests that removing all items one-by-one doesn't leave an entry around.
437 TEST_F(ExtensionMenuManagerTest, RemoveOneByOne) {
438 // Add 2 test items.
439 Extension* extension1 = AddExtension("1111");
440 ExtensionMenuItem* item1 = CreateTestItem(extension1);
441 ExtensionMenuItem* item2 = CreateTestItem(extension1);
442 ExtensionMenuItem* item3 = CreateTestItemWithID(extension1, "id3");
443 ASSERT_TRUE(manager_.AddContextItem(extension1, item1));
444 ASSERT_TRUE(manager_.AddContextItem(extension1, item2));
445 ASSERT_TRUE(manager_.AddContextItem(extension1, item3));
446
447 ASSERT_FALSE(manager_.context_items_.empty());
448
449 manager_.RemoveContextMenuItem(item3->id());
450 manager_.RemoveContextMenuItem(item1->id());
451 manager_.RemoveContextMenuItem(item2->id());
452
453 ASSERT_TRUE(manager_.context_items_.empty());
454 }
455
456 TEST_F(ExtensionMenuManagerTest, ExecuteCommand) {
457 MockTestingProfile profile;
458
459 scoped_ptr<MockExtensionEventRouter> mock_event_router(
460 new MockExtensionEventRouter(&profile));
461
462 content::ContextMenuParams params;
463 params.media_type = WebKit::WebContextMenuData::MediaTypeImage;
464 params.src_url = GURL("http://foo.bar/image.png");
465 params.page_url = GURL("http://foo.bar");
466 params.selection_text = ASCIIToUTF16("Hello World");
467 params.is_editable = false;
468
469 Extension* extension = AddExtension("test");
470 ExtensionMenuItem* item = CreateTestItem(extension);
471 ExtensionMenuItem::Id id = item->id();
472 ASSERT_TRUE(manager_.AddContextItem(extension, item));
473
474 EXPECT_CALL(profile, GetExtensionEventRouter())
475 .Times(1)
476 .WillOnce(Return(mock_event_router.get()));
477
478 // Use the magic of googlemock to save a parameter to our mock's
479 // DispatchEventToExtension method into event_args.
480 std::string event_args;
481 {
482 InSequence s;
483 EXPECT_CALL(*mock_event_router.get(),
484 DispatchEventToExtension(
485 item->extension_id(),
486 extension_event_names::kOnContextMenus,
487 _,
488 &profile,
489 GURL(),
490 ExtensionEventRouter::USER_GESTURE_ENABLED))
491 .Times(1)
492 .WillOnce(SaveArg<2>(&event_args));
493 EXPECT_CALL(*mock_event_router.get(),
494 DispatchEventToExtension(
495 item->extension_id(),
496 extension_event_names::kOnContextMenuClicked,
497 _,
498 &profile,
499 GURL(),
500 ExtensionEventRouter::USER_GESTURE_ENABLED))
501 .Times(1);
502 }
503 manager_.ExecuteCommand(&profile, NULL /* tab_contents */, params, id);
504
505 // Parse the json event_args, which should turn into a 2-element list where
506 // the first element is a dictionary we want to inspect for the correct
507 // values.
508 scoped_ptr<Value> result(
509 base::JSONReader::Read(event_args, base::JSON_ALLOW_TRAILING_COMMAS));
510 Value* value = result.get();
511 ASSERT_TRUE(result.get() != NULL);
512 ASSERT_EQ(Value::TYPE_LIST, value->GetType());
513 ListValue* list = static_cast<ListValue*>(value);
514 ASSERT_EQ(2u, list->GetSize());
515
516 DictionaryValue* info;
517 ASSERT_TRUE(list->GetDictionary(0, &info));
518
519 int tmp_id = 0;
520 ASSERT_TRUE(info->GetInteger("menuItemId", &tmp_id));
521 ASSERT_EQ(id.uid, tmp_id);
522
523 std::string tmp;
524 ASSERT_TRUE(info->GetString("mediaType", &tmp));
525 ASSERT_EQ("image", tmp);
526 ASSERT_TRUE(info->GetString("srcUrl", &tmp));
527 ASSERT_EQ(params.src_url.spec(), tmp);
528 ASSERT_TRUE(info->GetString("pageUrl", &tmp));
529 ASSERT_EQ(params.page_url.spec(), tmp);
530
531 string16 tmp16;
532 ASSERT_TRUE(info->GetString("selectionText", &tmp16));
533 ASSERT_EQ(params.selection_text, tmp16);
534
535 bool bool_tmp = true;
536 ASSERT_TRUE(info->GetBoolean("editable", &bool_tmp));
537 ASSERT_EQ(params.is_editable, bool_tmp);
538 }
539
540 // Test that there is always only one radio item selected.
541 TEST_F(ExtensionMenuManagerTest, SanitizeRadioButtons) {
542 Extension* extension = AddExtension("test");
543
544 // A single unchecked item should get checked
545 ExtensionMenuItem* item1 = CreateTestItem(extension);
546
547 item1->set_type(ExtensionMenuItem::RADIO);
548 item1->SetChecked(false);
549 ASSERT_FALSE(item1->checked());
550 manager_.AddContextItem(extension, item1);
551 ASSERT_TRUE(item1->checked());
552
553 // In a run of two unchecked items, the first should get selected.
554 item1->SetChecked(false);
555 ExtensionMenuItem* item2 = CreateTestItem(extension);
556 item2->set_type(ExtensionMenuItem::RADIO);
557 item2->SetChecked(false);
558 ASSERT_FALSE(item1->checked());
559 ASSERT_FALSE(item2->checked());
560 manager_.AddContextItem(extension, item2);
561 ASSERT_TRUE(item1->checked());
562 ASSERT_FALSE(item2->checked());
563
564 // If multiple items are checked, only the last item should get checked.
565 item1->SetChecked(true);
566 item2->SetChecked(true);
567 ASSERT_TRUE(item1->checked());
568 ASSERT_TRUE(item2->checked());
569 manager_.ItemUpdated(item1->id());
570 ASSERT_FALSE(item1->checked());
571 ASSERT_TRUE(item2->checked());
572
573 // If the checked item is removed, the new first item should get checked.
574 item1->SetChecked(false);
575 item2->SetChecked(true);
576 ASSERT_FALSE(item1->checked());
577 ASSERT_TRUE(item2->checked());
578 manager_.RemoveContextMenuItem(item2->id());
579 item2 = NULL;
580 ASSERT_TRUE(item1->checked());
581
582 // If a checked item is added to a run that already has a checked item,
583 // then the new item should get checked.
584 item1->SetChecked(true);
585 ExtensionMenuItem* new_item = CreateTestItem(extension);
586 new_item->set_type(ExtensionMenuItem::RADIO);
587 new_item->SetChecked(true);
588 ASSERT_TRUE(item1->checked());
589 ASSERT_TRUE(new_item->checked());
590 manager_.AddContextItem(extension, new_item);
591 ASSERT_FALSE(item1->checked());
592 ASSERT_TRUE(new_item->checked());
593 // Make sure that children are checked as well.
594 ExtensionMenuItem* parent = CreateTestItem(extension);
595 manager_.AddContextItem(extension, parent);
596 ExtensionMenuItem* child1 = CreateTestItem(extension);
597 child1->set_type(ExtensionMenuItem::RADIO);
598 child1->SetChecked(false);
599 ExtensionMenuItem* child2 = CreateTestItem(extension);
600 child2->set_type(ExtensionMenuItem::RADIO);
601 child2->SetChecked(true);
602 ASSERT_FALSE(child1->checked());
603 ASSERT_TRUE(child2->checked());
604
605 manager_.AddChildItem(parent->id(), child1);
606 ASSERT_TRUE(child1->checked());
607
608 manager_.AddChildItem(parent->id(), child2);
609 ASSERT_FALSE(child1->checked());
610 ASSERT_TRUE(child2->checked());
611
612 // Removing the checked item from the children should cause the
613 // remaining child to be checked.
614 manager_.RemoveContextMenuItem(child2->id());
615 child2 = NULL;
616 ASSERT_TRUE(child1->checked());
617
618 // This should NOT cause |new_item| to be deseleted because
619 // |parent| will be seperating the two runs of radio items.
620 manager_.ChangeParent(child1->id(), NULL);
621 ASSERT_TRUE(new_item->checked());
622 ASSERT_TRUE(child1->checked());
623
624 // Removing |parent| should cause only |child1| to be selected.
625 manager_.RemoveContextMenuItem(parent->id());
626 parent = NULL;
627 ASSERT_FALSE(new_item->checked());
628 ASSERT_TRUE(child1->checked());
629 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_menu_manager.cc ('k') | chrome/browser/extensions/extension_prefs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698