Home | History | Annotate | Download | only in browser
      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