1 // Copyright 2013 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 "extensions/browser/event_listener_map.h" 6 7 #include "content/public/test/mock_render_process_host.h" 8 #include "content/public/test/test_browser_context.h" 9 #include "extensions/browser/event_router.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 using base::DictionaryValue; 13 using base::ListValue; 14 using base::StringValue; 15 16 namespace extensions { 17 18 namespace { 19 20 const char kExt1Id[] = "extension_1"; 21 const char kExt2Id[] = "extension_2"; 22 const char kEvent1Name[] = "event1"; 23 const char kEvent2Name[] = "event2"; 24 25 class EmptyDelegate : public EventListenerMap::Delegate { 26 virtual void OnListenerAdded(const EventListener* listener) OVERRIDE {}; 27 virtual void OnListenerRemoved(const EventListener* listener) OVERRIDE {}; 28 }; 29 30 class EventListenerMapUnittest : public testing::Test { 31 public: 32 EventListenerMapUnittest() 33 : delegate_(new EmptyDelegate), 34 listeners_(new EventListenerMap(delegate_.get())), 35 browser_context_(new content::TestBrowserContext), 36 process_(new content::MockRenderProcessHost(browser_context_.get())) { 37 } 38 39 scoped_ptr<DictionaryValue> CreateHostSuffixFilter( 40 const std::string& suffix) { 41 scoped_ptr<DictionaryValue> filter(new DictionaryValue); 42 scoped_ptr<ListValue> filter_list(new ListValue); 43 scoped_ptr<DictionaryValue> filter_dict(new DictionaryValue); 44 45 filter_dict->Set("hostSuffix", new StringValue(suffix)); 46 47 filter_list->Append(filter_dict.release()); 48 filter->Set("url", filter_list.release()); 49 return filter.Pass(); 50 } 51 52 scoped_ptr<Event> CreateNamedEvent(const std::string& event_name) { 53 return CreateEvent(event_name, GURL()); 54 } 55 56 scoped_ptr<Event> CreateEvent(const std::string& event_name, 57 const GURL& url) { 58 EventFilteringInfo info; 59 info.SetURL(url); 60 scoped_ptr<Event> result(new Event(event_name, 61 make_scoped_ptr(new ListValue()), NULL, GURL(), 62 EventRouter::USER_GESTURE_UNKNOWN, info)); 63 return result.Pass(); 64 } 65 66 protected: 67 scoped_ptr<EventListenerMap::Delegate> delegate_; 68 scoped_ptr<EventListenerMap> listeners_; 69 scoped_ptr<content::TestBrowserContext> browser_context_; 70 scoped_ptr<content::MockRenderProcessHost> process_; 71 }; 72 73 TEST_F(EventListenerMapUnittest, UnfilteredEventsGoToAllListeners) { 74 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 75 kEvent1Name, kExt1Id, NULL, scoped_ptr<DictionaryValue>()))); 76 77 scoped_ptr<Event> event(CreateNamedEvent(kEvent1Name)); 78 std::set<const EventListener*> targets(listeners_->GetEventListeners(*event)); 79 ASSERT_EQ(1u, targets.size()); 80 } 81 82 TEST_F(EventListenerMapUnittest, FilteredEventsGoToAllMatchingListeners) { 83 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 84 kEvent1Name, kExt1Id, NULL, CreateHostSuffixFilter("google.com")))); 85 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 86 kEvent1Name, kExt1Id, NULL, scoped_ptr<DictionaryValue>( 87 new DictionaryValue)))); 88 89 scoped_ptr<Event> event(CreateNamedEvent(kEvent1Name)); 90 event->filter_info.SetURL(GURL("http://www.google.com")); 91 std::set<const EventListener*> targets(listeners_->GetEventListeners(*event)); 92 ASSERT_EQ(2u, targets.size()); 93 } 94 95 TEST_F(EventListenerMapUnittest, FilteredEventsOnlyGoToMatchingListeners) { 96 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 97 kEvent1Name, kExt1Id, NULL, CreateHostSuffixFilter("google.com")))); 98 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 99 kEvent1Name, kExt1Id, NULL, CreateHostSuffixFilter("yahoo.com")))); 100 101 scoped_ptr<Event> event(CreateNamedEvent(kEvent1Name)); 102 event->filter_info.SetURL(GURL("http://www.google.com")); 103 std::set<const EventListener*> targets(listeners_->GetEventListeners(*event)); 104 ASSERT_EQ(1u, targets.size()); 105 } 106 107 TEST_F(EventListenerMapUnittest, LazyAndUnlazyListenersGetReturned) { 108 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 109 kEvent1Name, kExt1Id, NULL, CreateHostSuffixFilter("google.com")))); 110 111 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 112 kEvent1Name, kExt1Id, process_.get(), 113 CreateHostSuffixFilter("google.com")))); 114 115 scoped_ptr<Event> event(CreateNamedEvent(kEvent1Name)); 116 event->filter_info.SetURL(GURL("http://www.google.com")); 117 std::set<const EventListener*> targets(listeners_->GetEventListeners(*event)); 118 ASSERT_EQ(2u, targets.size()); 119 } 120 121 TEST_F(EventListenerMapUnittest, TestRemovingByProcess) { 122 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 123 kEvent1Name, kExt1Id, NULL, CreateHostSuffixFilter("google.com")))); 124 125 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 126 kEvent1Name, kExt1Id, process_.get(), 127 CreateHostSuffixFilter("google.com")))); 128 129 listeners_->RemoveListenersForProcess(process_.get()); 130 131 scoped_ptr<Event> event(CreateNamedEvent(kEvent1Name)); 132 event->filter_info.SetURL(GURL("http://www.google.com")); 133 std::set<const EventListener*> targets(listeners_->GetEventListeners(*event)); 134 ASSERT_EQ(1u, targets.size()); 135 } 136 137 TEST_F(EventListenerMapUnittest, TestRemovingByListener) { 138 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 139 kEvent1Name, kExt1Id, NULL, CreateHostSuffixFilter("google.com")))); 140 141 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 142 kEvent1Name, kExt1Id, process_.get(), 143 CreateHostSuffixFilter("google.com")))); 144 145 scoped_ptr<EventListener> listener(new EventListener(kEvent1Name, kExt1Id, 146 process_.get(), CreateHostSuffixFilter("google.com"))); 147 listeners_->RemoveListener(listener.get()); 148 149 scoped_ptr<Event> event(CreateNamedEvent(kEvent1Name)); 150 event->filter_info.SetURL(GURL("http://www.google.com")); 151 std::set<const EventListener*> targets(listeners_->GetEventListeners(*event)); 152 ASSERT_EQ(1u, targets.size()); 153 } 154 155 TEST_F(EventListenerMapUnittest, TestLazyDoubleAddIsUndoneByRemove) { 156 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 157 kEvent1Name, kExt1Id, NULL, CreateHostSuffixFilter("google.com")))); 158 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 159 kEvent1Name, kExt1Id, NULL, CreateHostSuffixFilter("google.com")))); 160 161 scoped_ptr<EventListener> listener(new EventListener( 162 kEvent1Name, kExt1Id, NULL, CreateHostSuffixFilter("google.com"))); 163 listeners_->RemoveListener(listener.get()); 164 165 scoped_ptr<Event> event(CreateNamedEvent(kEvent1Name)); 166 event->filter_info.SetURL(GURL("http://www.google.com")); 167 std::set<const EventListener*> targets(listeners_->GetEventListeners(*event)); 168 ASSERT_EQ(0u, targets.size()); 169 } 170 171 TEST_F(EventListenerMapUnittest, HostSuffixFilterEquality) { 172 scoped_ptr<DictionaryValue> filter1(CreateHostSuffixFilter("google.com")); 173 scoped_ptr<DictionaryValue> filter2(CreateHostSuffixFilter("google.com")); 174 ASSERT_TRUE(filter1->Equals(filter2.get())); 175 } 176 177 TEST_F(EventListenerMapUnittest, RemoveLazyListenersForExtension) { 178 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 179 kEvent1Name, kExt1Id, NULL, CreateHostSuffixFilter("google.com")))); 180 listeners_->AddListener(scoped_ptr<EventListener>(new EventListener( 181 kEvent2Name, kExt1Id, NULL, CreateHostSuffixFilter("google.com")))); 182 183 listeners_->RemoveLazyListenersForExtension(kExt1Id); 184 185 scoped_ptr<Event> event(CreateNamedEvent(kEvent1Name)); 186 event->filter_info.SetURL(GURL("http://www.google.com")); 187 std::set<const EventListener*> targets(listeners_->GetEventListeners(*event)); 188 ASSERT_EQ(0u, targets.size()); 189 190 event->event_name = kEvent2Name; 191 targets = listeners_->GetEventListeners(*event); 192 ASSERT_EQ(0u, targets.size()); 193 } 194 195 TEST_F(EventListenerMapUnittest, AddExistingFilteredListener) { 196 bool first_new = listeners_->AddListener(scoped_ptr<EventListener>( 197 new EventListener(kEvent1Name, kExt1Id, NULL, 198 CreateHostSuffixFilter("google.com")))); 199 bool second_new = listeners_->AddListener(scoped_ptr<EventListener>( 200 new EventListener(kEvent1Name, kExt1Id, NULL, 201 CreateHostSuffixFilter("google.com")))); 202 203 ASSERT_TRUE(first_new); 204 ASSERT_FALSE(second_new); 205 } 206 207 TEST_F(EventListenerMapUnittest, AddExistingUnfilteredListener) { 208 bool first_add = listeners_->AddListener(scoped_ptr<EventListener>( 209 new EventListener(kEvent1Name, kExt1Id, NULL, 210 scoped_ptr<DictionaryValue>()))); 211 bool second_add = listeners_->AddListener(scoped_ptr<EventListener>( 212 new EventListener(kEvent1Name, kExt1Id, NULL, 213 scoped_ptr<DictionaryValue>()))); 214 215 scoped_ptr<EventListener> listener( 216 new EventListener(kEvent1Name, kExt1Id, NULL, 217 scoped_ptr<DictionaryValue>())); 218 bool first_remove = listeners_->RemoveListener(listener.get()); 219 bool second_remove = listeners_->RemoveListener(listener.get()); 220 221 ASSERT_TRUE(first_add); 222 ASSERT_FALSE(second_add); 223 ASSERT_TRUE(first_remove); 224 ASSERT_FALSE(second_remove); 225 } 226 227 TEST_F(EventListenerMapUnittest, RemovingRouters) { 228 listeners_->AddListener(scoped_ptr<EventListener>( 229 new EventListener(kEvent1Name, kExt1Id, process_.get(), 230 scoped_ptr<DictionaryValue>()))); 231 listeners_->RemoveListenersForProcess(process_.get()); 232 ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent1Name)); 233 } 234 235 TEST_F(EventListenerMapUnittest, HasListenerForEvent) { 236 ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent1Name)); 237 238 listeners_->AddListener(scoped_ptr<EventListener>( 239 new EventListener(kEvent1Name, kExt1Id, process_.get(), 240 scoped_ptr<DictionaryValue>()))); 241 242 ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent2Name)); 243 ASSERT_TRUE(listeners_->HasListenerForEvent(kEvent1Name)); 244 listeners_->RemoveListenersForProcess(process_.get()); 245 ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent1Name)); 246 } 247 248 TEST_F(EventListenerMapUnittest, HasListenerForExtension) { 249 ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name)); 250 251 // Non-lazy listener. 252 listeners_->AddListener(scoped_ptr<EventListener>( 253 new EventListener(kEvent1Name, kExt1Id, process_.get(), 254 scoped_ptr<DictionaryValue>()))); 255 // Lazy listener. 256 listeners_->AddListener(scoped_ptr<EventListener>( 257 new EventListener(kEvent1Name, kExt1Id, NULL, 258 scoped_ptr<DictionaryValue>()))); 259 260 ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent2Name)); 261 ASSERT_TRUE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name)); 262 ASSERT_FALSE(listeners_->HasListenerForExtension(kExt2Id, kEvent1Name)); 263 listeners_->RemoveListenersForProcess(process_.get()); 264 ASSERT_TRUE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name)); 265 listeners_->RemoveLazyListenersForExtension(kExt1Id); 266 ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name)); 267 } 268 269 TEST_F(EventListenerMapUnittest, AddLazyListenersFromPreferences) { 270 scoped_ptr<DictionaryValue> filter1(CreateHostSuffixFilter("google.com")); 271 scoped_ptr<DictionaryValue> filter2(CreateHostSuffixFilter("yahoo.com")); 272 273 DictionaryValue filtered_listeners; 274 ListValue* filter_list = new ListValue(); 275 filtered_listeners.Set(kEvent1Name, filter_list); 276 277 filter_list->Append(filter1.release()); 278 filter_list->Append(filter2.release()); 279 280 listeners_->LoadFilteredLazyListeners(kExt1Id, filtered_listeners); 281 282 scoped_ptr<Event> event(CreateEvent(kEvent1Name, 283 GURL("http://www.google.com"))); 284 std::set<const EventListener*> targets(listeners_->GetEventListeners(*event)); 285 ASSERT_EQ(1u, targets.size()); 286 scoped_ptr<EventListener> listener(new EventListener(kEvent1Name, kExt1Id, 287 NULL, CreateHostSuffixFilter("google.com"))); 288 ASSERT_TRUE((*targets.begin())->Equals(listener.get())); 289 } 290 291 TEST_F(EventListenerMapUnittest, CorruptedExtensionPrefsShouldntCrash) { 292 scoped_ptr<DictionaryValue> filter1(CreateHostSuffixFilter("google.com")); 293 294 DictionaryValue filtered_listeners; 295 // kEvent1Name should be associated with a list, not a dictionary. 296 filtered_listeners.Set(kEvent1Name, filter1.release()); 297 298 listeners_->LoadFilteredLazyListeners(kExt1Id, filtered_listeners); 299 300 scoped_ptr<Event> event(CreateEvent(kEvent1Name, 301 GURL("http://www.google.com"))); 302 std::set<const EventListener*> targets(listeners_->GetEventListeners(*event)); 303 ASSERT_EQ(0u, targets.size()); 304 } 305 306 } // namespace 307 308 } // namespace extensions 309