[email protected] | f20d733 | 2011-03-08 21:11:53 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 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" |
[email protected] | 3b63f8f4 | 2011-03-28 01:54:15 | [diff] [blame] | 8 | #include "base/memory/scoped_vector.h" |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 9 | #include "base/path_service.h" |
[email protected] | e078590 | 2011-05-19 23:34:17 | [diff] [blame] | 10 | #include "base/scoped_temp_dir.h" |
[email protected] | 944b421 | 2010-12-14 00:00:33 | [diff] [blame] | 11 | #include "base/utf_string_conversions.h" |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 12 | #include "base/values.h" |
[email protected] | 2c69965 | 2010-10-15 18:22:41 | [diff] [blame] | 13 | #include "chrome/browser/extensions/extension_event_router.h" |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 14 | #include "chrome/browser/extensions/extension_menu_manager.h" |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 15 | #include "chrome/browser/extensions/test_extension_prefs.h" |
[email protected] | 43211582 | 2011-07-10 15:52:27 | [diff] [blame] | 16 | #include "chrome/common/chrome_notification_types.h" |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 17 | #include "chrome/common/chrome_paths.h" |
| 18 | #include "chrome/common/extensions/extension.h" |
| 19 | #include "chrome/common/extensions/extension_constants.h" |
[email protected] | a4ff9eae | 2011-08-01 19:58:16 | [diff] [blame] | 20 | #include "chrome/test/base/testing_profile.h" |
[email protected] | 1bda9755 | 2011-03-01 20:11:52 | [diff] [blame] | 21 | #include "content/browser/browser_thread.h" |
[email protected] | f20d733 | 2011-03-08 21:11:53 | [diff] [blame] | 22 | #include "content/common/notification_service.h" |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 23 | #include "testing/gmock/include/gmock/gmock.h" |
[email protected] | f20d733 | 2011-03-08 21:11:53 | [diff] [blame] | 24 | #include "testing/gtest/include/gtest/gtest.h" |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 25 | #include "webkit/glue/context_menu.h" |
| 26 | |
| 27 | using testing::_; |
| 28 | using testing::AtLeast; |
| 29 | using testing::Return; |
| 30 | using testing::SaveArg; |
| 31 | |
| 32 | // Base class for tests. |
[email protected] | 583844c | 2011-08-27 00:38:35 | [diff] [blame] | 33 | class ExtensionMenuManagerTest : public testing::Test { |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 34 | public: |
[email protected] | 6cad5bf | 2011-03-10 21:21:55 | [diff] [blame] | 35 | ExtensionMenuManagerTest() |
| 36 | : ui_thread_(BrowserThread::UI, &message_loop_), |
| 37 | file_thread_(BrowserThread::FILE, &message_loop_), |
| 38 | next_id_(1) { |
| 39 | } |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 40 | |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 41 | // Returns a test item. |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 42 | ExtensionMenuItem* CreateTestItem(Extension* extension) { |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 43 | ExtensionMenuItem::Type type = ExtensionMenuItem::NORMAL; |
| 44 | ExtensionMenuItem::ContextList contexts(ExtensionMenuItem::ALL); |
[email protected] | 5a7b5eaf | 2010-11-02 20:52:19 | [diff] [blame] | 45 | ExtensionMenuItem::Id id(NULL, extension->id(), next_id_++); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 46 | return new ExtensionMenuItem(id, "test", false, type, contexts); |
[email protected] | 06a0c94e | 2010-06-24 23:20:15 | [diff] [blame] | 47 | } |
| 48 | |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 49 | // Creates and returns a test Extension. The caller does *not* own the return |
| 50 | // value. |
| 51 | Extension* AddExtension(std::string name) { |
[email protected] | 66e4eb3 | 2010-10-27 20:37:41 | [diff] [blame] | 52 | scoped_refptr<Extension> extension = prefs_.AddExtension(name); |
[email protected] | 819faeb0 | 2010-06-25 21:16:22 | [diff] [blame] | 53 | extensions_.push_back(extension); |
| 54 | return extension; |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 55 | } |
| 56 | |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 57 | protected: |
[email protected] | 6cad5bf | 2011-03-10 21:21:55 | [diff] [blame] | 58 | MessageLoopForUI message_loop_; |
| 59 | BrowserThread ui_thread_; |
| 60 | BrowserThread file_thread_; |
| 61 | |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 62 | ExtensionMenuManager manager_; |
[email protected] | 66e4eb3 | 2010-10-27 20:37:41 | [diff] [blame] | 63 | ExtensionList extensions_; |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 64 | TestExtensionPrefs prefs_; |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 65 | int next_id_; |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 66 | |
| 67 | private: |
| 68 | DISALLOW_COPY_AND_ASSIGN(ExtensionMenuManagerTest); |
| 69 | }; |
| 70 | |
| 71 | // Tests adding, getting, and removing items. |
| 72 | TEST_F(ExtensionMenuManagerTest, AddGetRemoveItems) { |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 73 | Extension* extension = AddExtension("test"); |
| 74 | |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 75 | // Add a new item, make sure you can get it back. |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 76 | ExtensionMenuItem* item1 = CreateTestItem(extension); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 77 | ASSERT_TRUE(item1 != NULL); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 78 | ASSERT_TRUE(manager_.AddContextItem(extension, item1)); |
| 79 | ASSERT_EQ(item1, manager_.GetItemById(item1->id())); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 80 | const ExtensionMenuItem::List* items = |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 81 | manager_.MenuItems(item1->extension_id()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 82 | ASSERT_EQ(1u, items->size()); |
| 83 | ASSERT_EQ(item1, items->at(0)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 84 | |
| 85 | // Add a second item, make sure it comes back too. |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 86 | ExtensionMenuItem* item2 = CreateTestItem(extension); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 87 | ASSERT_TRUE(manager_.AddContextItem(extension, item2)); |
| 88 | ASSERT_EQ(item2, manager_.GetItemById(item2->id())); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 89 | items = manager_.MenuItems(item2->extension_id()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 90 | ASSERT_EQ(2u, items->size()); |
| 91 | ASSERT_EQ(item1, items->at(0)); |
| 92 | ASSERT_EQ(item2, items->at(1)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 93 | |
| 94 | // Try adding item 3, then removing it. |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 95 | ExtensionMenuItem* item3 = CreateTestItem(extension); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 96 | ExtensionMenuItem::Id id3 = item3->id(); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 97 | std::string extension_id = item3->extension_id(); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 98 | ASSERT_TRUE(manager_.AddContextItem(extension, item3)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 99 | ASSERT_EQ(item3, manager_.GetItemById(id3)); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 100 | ASSERT_EQ(3u, manager_.MenuItems(extension_id)->size()); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 101 | ASSERT_TRUE(manager_.RemoveContextMenuItem(id3)); |
| 102 | ASSERT_EQ(NULL, manager_.GetItemById(id3)); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 103 | ASSERT_EQ(2u, manager_.MenuItems(extension_id)->size()); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 104 | |
| 105 | // Make sure removing a non-existent item returns false. |
[email protected] | 5a7b5eaf | 2010-11-02 20:52:19 | [diff] [blame] | 106 | ExtensionMenuItem::Id id(NULL, extension->id(), id3.uid + 50); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 107 | ASSERT_FALSE(manager_.RemoveContextMenuItem(id)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 108 | } |
| 109 | |
| 110 | // Test adding/removing child items. |
| 111 | TEST_F(ExtensionMenuManagerTest, ChildFunctions) { |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 112 | Extension* extension1 = AddExtension("1111"); |
| 113 | Extension* extension2 = AddExtension("2222"); |
| 114 | Extension* extension3 = AddExtension("3333"); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 115 | |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 116 | ExtensionMenuItem* item1 = CreateTestItem(extension1); |
| 117 | ExtensionMenuItem* item2 = CreateTestItem(extension2); |
| 118 | ExtensionMenuItem* item2_child = CreateTestItem(extension2); |
| 119 | ExtensionMenuItem* item2_grandchild = CreateTestItem(extension2); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 120 | |
| 121 | // This third item we expect to fail inserting, so we use a scoped_ptr to make |
| 122 | // sure it gets deleted. |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 123 | scoped_ptr<ExtensionMenuItem> item3(CreateTestItem(extension3)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 124 | |
| 125 | // Add in the first two items. |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 126 | ASSERT_TRUE(manager_.AddContextItem(extension1, item1)); |
| 127 | ASSERT_TRUE(manager_.AddContextItem(extension2, item2)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 128 | |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 129 | ExtensionMenuItem::Id id1 = item1->id(); |
| 130 | ExtensionMenuItem::Id id2 = item2->id(); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 131 | |
| 132 | // Try adding item3 as a child of item2 - this should fail because item3 has |
| 133 | // a different extension id. |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 134 | ASSERT_FALSE(manager_.AddChildItem(id2, item3.get())); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 135 | |
| 136 | // Add item2_child as a child of item2. |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 137 | ExtensionMenuItem::Id id2_child = item2_child->id(); |
| 138 | ASSERT_TRUE(manager_.AddChildItem(id2, item2_child)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 139 | 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] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 143 | ASSERT_EQ(1u, manager_.MenuItems(item1->extension_id())->size()); |
| 144 | ASSERT_EQ(item1, manager_.MenuItems(item1->extension_id())->at(0)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 145 | |
| 146 | // Add item2_grandchild as a child of item2_child, then remove it. |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 147 | ExtensionMenuItem::Id id2_grandchild = item2_grandchild->id(); |
| 148 | ASSERT_TRUE(manager_.AddChildItem(id2_child, item2_grandchild)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 149 | 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] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 155 | ASSERT_EQ(1u, manager_.MenuItems(item2->extension_id())->size()); |
| 156 | ASSERT_EQ(item2, manager_.MenuItems(item2->extension_id())->at(0)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 157 | |
| 158 | // Remove child2_item. |
| 159 | ASSERT_TRUE(manager_.RemoveContextMenuItem(id2_child)); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 160 | ASSERT_EQ(1u, manager_.MenuItems(item2->extension_id())->size()); |
| 161 | ASSERT_EQ(item2, manager_.MenuItems(item2->extension_id())->at(0)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 162 | ASSERT_EQ(0, item2->child_count()); |
| 163 | } |
| 164 | |
[email protected] | 2b07c93f | 2010-08-02 23:13:04 | [diff] [blame] | 165 | // Tests that deleting a parent properly removes descendants. |
| 166 | TEST_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] | f50da859 | 2010-10-28 23:39:32 | [diff] [blame] | 223 | ASSERT_EQ(NULL, manager_.MenuItems(extension->id())); |
[email protected] | 2b07c93f | 2010-08-02 23:13:04 | [diff] [blame] | 224 | 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] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 230 | // Tests changing parents. |
| 231 | TEST_F(ExtensionMenuManagerTest, ChangeParent) { |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 232 | Extension* extension1 = AddExtension("1111"); |
[email protected] | 06a0c94e | 2010-06-24 23:20:15 | [diff] [blame] | 233 | |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 234 | // First create two items and add them both to the manager. |
| 235 | ExtensionMenuItem* item1 = CreateTestItem(extension1); |
| 236 | ExtensionMenuItem* item2 = CreateTestItem(extension1); |
| 237 | |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 238 | ASSERT_TRUE(manager_.AddContextItem(extension1, item1)); |
| 239 | ASSERT_TRUE(manager_.AddContextItem(extension1, item2)); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 240 | |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 241 | const ExtensionMenuItem::List* items = |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 242 | manager_.MenuItems(item1->extension_id()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 243 | ASSERT_EQ(2u, items->size()); |
| 244 | ASSERT_EQ(item1, items->at(0)); |
| 245 | ASSERT_EQ(item2, items->at(1)); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 246 | |
| 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] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 249 | ExtensionMenuItem* item3 = CreateTestItem(extension1); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 250 | |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 251 | ASSERT_TRUE(manager_.AddChildItem(item1->id(), item3)); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 252 | ASSERT_EQ(1, item1->child_count()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 253 | ASSERT_EQ(item3, item1->children()[0]); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 254 | |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 255 | ASSERT_TRUE(manager_.ChangeParent(item3->id(), &item2->id())); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 256 | ASSERT_EQ(0, item1->child_count()); |
| 257 | ASSERT_EQ(1, item2->child_count()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 258 | ASSERT_EQ(item3, item2->children()[0]); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 259 | |
| 260 | // Move item2 to be a child of item1. |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 261 | ASSERT_TRUE(manager_.ChangeParent(item2->id(), &item1->id())); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 262 | ASSERT_EQ(1, item1->child_count()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 263 | ASSERT_EQ(item2, item1->children()[0]); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 264 | ASSERT_EQ(1, item2->child_count()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 265 | ASSERT_EQ(item3, item2->children()[0]); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 266 | |
| 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] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 270 | ASSERT_EQ(1u, items->size()); |
| 271 | ASSERT_EQ(item1, items->at(0)); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 272 | |
| 273 | // Move item3 back to being a child of item1, so it's now a sibling of item2. |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 274 | ASSERT_TRUE(manager_.ChangeParent(item3->id(), &item1->id())); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 275 | ASSERT_EQ(2, item1->child_count()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 276 | ASSERT_EQ(item2, item1->children()[0]); |
| 277 | ASSERT_EQ(item3, item1->children()[1]); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 278 | |
| 279 | // Try switching item3 to be the parent of item1 - this should fail. |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 280 | ASSERT_FALSE(manager_.ChangeParent(item1->id(), &item3->id())); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 281 | ASSERT_EQ(0, item3->child_count()); |
| 282 | ASSERT_EQ(2, item1->child_count()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 283 | ASSERT_EQ(item2, item1->children()[0]); |
| 284 | ASSERT_EQ(item3, item1->children()[1]); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 285 | items = manager_.MenuItems(item1->extension_id()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 286 | ASSERT_EQ(1u, items->size()); |
| 287 | ASSERT_EQ(item1, items->at(0)); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 288 | |
| 289 | // Move item2 to be a top-level item. |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 290 | ASSERT_TRUE(manager_.ChangeParent(item2->id(), NULL)); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 291 | items = manager_.MenuItems(item1->extension_id()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 292 | ASSERT_EQ(2u, items->size()); |
| 293 | ASSERT_EQ(item1, items->at(0)); |
| 294 | ASSERT_EQ(item2, items->at(1)); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 295 | ASSERT_EQ(1, item1->child_count()); |
[email protected] | 63a414b5 | 2010-06-03 23:20:49 | [diff] [blame] | 296 | ASSERT_EQ(item3, item1->children()[0]); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 297 | |
| 298 | // Make sure you can't move a node to be a child of another extension's item. |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 299 | Extension* extension2 = AddExtension("2222"); |
| 300 | ExtensionMenuItem* item4 = CreateTestItem(extension2); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 301 | 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] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 304 | |
| 305 | // Make sure you can't make an item be it's own parent. |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 306 | ASSERT_FALSE(manager_.ChangeParent(item1->id(), &item1->id())); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 307 | } |
| 308 | |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 309 | // Tests that we properly remove an extension's menu item when that extension is |
| 310 | // unloaded. |
| 311 | TEST_F(ExtensionMenuManagerTest, ExtensionUnloadRemovesMenuItems) { |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 312 | NotificationService* notifier = NotificationService::current(); |
| 313 | ASSERT_TRUE(notifier != NULL); |
| 314 | |
| 315 | // Create a test extension. |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 316 | Extension* extension1 = AddExtension("1111"); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 317 | |
| 318 | // Create an ExtensionMenuItem and put it into the manager. |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 319 | ExtensionMenuItem* item1 = CreateTestItem(extension1); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 320 | ExtensionMenuItem::Id id1 = item1->id(); |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 321 | ASSERT_EQ(extension1->id(), item1->extension_id()); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 322 | ASSERT_TRUE(manager_.AddContextItem(extension1, item1)); |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 323 | ASSERT_EQ(1u, manager_.MenuItems(extension1->id())->size()); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 324 | |
| 325 | // Create a menu item with a different extension id and add it to the manager. |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 326 | Extension* extension2 = AddExtension("2222"); |
| 327 | ExtensionMenuItem* item2 = CreateTestItem(extension2); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 328 | ASSERT_NE(item1->extension_id(), item2->extension_id()); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 329 | ASSERT_TRUE(manager_.AddContextItem(extension2, item2)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 330 | |
| 331 | // Notify that the extension was unloaded, and make sure the right item is |
| 332 | // gone. |
[email protected] | 814a7bf0f | 2011-08-13 05:30:59 | [diff] [blame] | 333 | UnloadedExtensionInfo details( |
| 334 | extension1, extension_misc::UNLOAD_REASON_DISABLE); |
[email protected] | 43211582 | 2011-07-10 15:52:27 | [diff] [blame] | 335 | notifier->Notify(chrome::NOTIFICATION_EXTENSION_UNLOADED, |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 336 | Source<Profile>(NULL), |
[email protected] | a9f39a31 | 2010-12-23 22:14:27 | [diff] [blame] | 337 | Details<UnloadedExtensionInfo>(&details)); |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 338 | ASSERT_EQ(NULL, manager_.MenuItems(extension1->id())); |
| 339 | ASSERT_EQ(1u, manager_.MenuItems(extension2->id())->size()); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 340 | ASSERT_TRUE(manager_.GetItemById(id1) == NULL); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 341 | ASSERT_TRUE(manager_.GetItemById(item2->id()) != NULL); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 342 | } |
| 343 | |
| 344 | // A mock message service for tests of ExtensionMenuManager::ExecuteCommand. |
[email protected] | 2c69965 | 2010-10-15 18:22:41 | [diff] [blame] | 345 | class MockExtensionEventRouter : public ExtensionEventRouter { |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 346 | public: |
[email protected] | 2c69965 | 2010-10-15 18:22:41 | [diff] [blame] | 347 | explicit MockExtensionEventRouter(Profile* profile) : |
| 348 | ExtensionEventRouter(profile) {} |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 349 | |
[email protected] | f72d0c6 | 2011-08-31 16:27:44 | [diff] [blame^] | 350 | 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] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 356 | |
| 357 | private: |
[email protected] | 2c69965 | 2010-10-15 18:22:41 | [diff] [blame] | 358 | DISALLOW_COPY_AND_ASSIGN(MockExtensionEventRouter); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 359 | }; |
| 360 | |
| 361 | // A mock profile for tests of ExtensionMenuManager::ExecuteCommand. |
| 362 | class MockTestingProfile : public TestingProfile { |
| 363 | public: |
| 364 | MockTestingProfile() {} |
[email protected] | 2c69965 | 2010-10-15 18:22:41 | [diff] [blame] | 365 | MOCK_METHOD0(GetExtensionEventRouter, ExtensionEventRouter*()); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 366 | MOCK_METHOD0(IsOffTheRecord, bool()); |
| 367 | |
| 368 | private: |
| 369 | DISALLOW_COPY_AND_ASSIGN(MockTestingProfile); |
| 370 | }; |
| 371 | |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 372 | // Tests the RemoveAll functionality. |
| 373 | TEST_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] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 377 | // 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] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 382 | ASSERT_TRUE(manager_.AddContextItem(extension1, item1)); |
| 383 | ASSERT_TRUE(manager_.AddContextItem(extension1, item2)); |
| 384 | ASSERT_TRUE(manager_.AddChildItem(item1->id(), item3)); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 385 | |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 386 | // Add one top-level item for extension 2. |
| 387 | Extension* extension2 = AddExtension("2222"); |
| 388 | ExtensionMenuItem* item4 = CreateTestItem(extension2); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 389 | ASSERT_TRUE(manager_.AddContextItem(extension2, item4)); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 390 | |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 391 | EXPECT_EQ(2u, manager_.MenuItems(extension1->id())->size()); |
| 392 | EXPECT_EQ(1u, manager_.MenuItems(extension2->id())->size()); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 393 | |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 394 | // 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] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 398 | |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 399 | // Remove extension1's items. |
| 400 | manager_.RemoveAllContextItems(extension1->id()); |
| 401 | EXPECT_EQ(NULL, manager_.MenuItems(extension1->id())); |
[email protected] | 66dbfb2c | 2010-05-12 20:20:15 | [diff] [blame] | 402 | } |
| 403 | |
[email protected] | f50da859 | 2010-10-28 23:39:32 | [diff] [blame] | 404 | // Tests that removing all items one-by-one doesn't leave an entry around. |
| 405 | TEST_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] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 421 | TEST_F(ExtensionMenuManagerTest, ExecuteCommand) { |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 422 | MockTestingProfile profile; |
| 423 | |
[email protected] | 2c69965 | 2010-10-15 18:22:41 | [diff] [blame] | 424 | scoped_ptr<MockExtensionEventRouter> mock_event_router( |
| 425 | new MockExtensionEventRouter(&profile)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 426 | |
| 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] | 944b421 | 2010-12-14 00:00:33 | [diff] [blame] | 431 | params.selection_text = ASCIIToUTF16("Hello World"); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 432 | params.is_editable = false; |
| 433 | |
[email protected] | 052c9270 | 2010-06-25 07:25:52 | [diff] [blame] | 434 | Extension* extension = AddExtension("test"); |
| 435 | ExtensionMenuItem* item = CreateTestItem(extension); |
[email protected] | f4f0459 | 2010-07-14 20:40:13 | [diff] [blame] | 436 | ExtensionMenuItem::Id id = item->id(); |
| 437 | ASSERT_TRUE(manager_.AddContextItem(extension, item)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 438 | |
[email protected] | 2c69965 | 2010-10-15 18:22:41 | [diff] [blame] | 439 | EXPECT_CALL(profile, GetExtensionEventRouter()) |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 440 | .Times(1) |
[email protected] | 2c69965 | 2010-10-15 18:22:41 | [diff] [blame] | 441 | .WillOnce(Return(mock_event_router.get())); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 442 | |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 443 | // Use the magic of googlemock to save a parameter to our mock's |
[email protected] | 0a184b5 | 2011-06-23 00:41:13 | [diff] [blame] | 444 | // DispatchEventToExtension method into event_args. |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 445 | std::string event_args; |
[email protected] | a7ab1b78 | 2010-10-21 23:24:16 | [diff] [blame] | 446 | std::string expected_event_name = "contextMenus"; |
[email protected] | 2c69965 | 2010-10-15 18:22:41 | [diff] [blame] | 447 | EXPECT_CALL(*mock_event_router.get(), |
[email protected] | f72d0c6 | 2011-08-31 16:27:44 | [diff] [blame^] | 448 | DispatchEventToExtension(item->extension_id(), |
| 449 | expected_event_name, |
| 450 | _, |
| 451 | &profile, |
| 452 | GURL())) |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 453 | .Times(1) |
[email protected] | a7ab1b78 | 2010-10-21 23:24:16 | [diff] [blame] | 454 | .WillOnce(SaveArg<2>(&event_args)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 455 | |
| 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] | 88dc069 | 2010-08-14 16:29:42 | [diff] [blame] | 472 | ASSERT_TRUE(info->GetInteger("menuItemId", &tmp_id)); |
[email protected] | 5a7b5eaf | 2010-11-02 20:52:19 | [diff] [blame] | 473 | ASSERT_EQ(id.uid, tmp_id); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 474 | |
| 475 | std::string tmp; |
[email protected] | 88dc069 | 2010-08-14 16:29:42 | [diff] [blame] | 476 | ASSERT_TRUE(info->GetString("mediaType", &tmp)); |
[email protected] | 1741b97 | 2010-08-04 23:47:41 | [diff] [blame] | 477 | ASSERT_EQ("image", tmp); |
[email protected] | 88dc069 | 2010-08-14 16:29:42 | [diff] [blame] | 478 | ASSERT_TRUE(info->GetString("srcUrl", &tmp)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 479 | ASSERT_EQ(params.src_url.spec(), tmp); |
[email protected] | 88dc069 | 2010-08-14 16:29:42 | [diff] [blame] | 480 | ASSERT_TRUE(info->GetString("pageUrl", &tmp)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 481 | ASSERT_EQ(params.page_url.spec(), tmp); |
| 482 | |
[email protected] | 944b421 | 2010-12-14 00:00:33 | [diff] [blame] | 483 | string16 tmp16; |
| 484 | ASSERT_TRUE(info->GetString("selectionText", &tmp16)); |
| 485 | ASSERT_EQ(params.selection_text, tmp16); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 486 | |
| 487 | bool bool_tmp = true; |
[email protected] | 88dc069 | 2010-08-14 16:29:42 | [diff] [blame] | 488 | ASSERT_TRUE(info->GetBoolean("editable", &bool_tmp)); |
[email protected] | 2e3b520 | 2010-03-23 06:52:41 | [diff] [blame] | 489 | ASSERT_EQ(params.is_editable, bool_tmp); |
| 490 | } |