1 // Copyright 2018 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/renderer/bindings/listener_tracker.h"
6 
7 #include <memory>
8 
9 #include "base/values.h"
10 #include "extensions/renderer/bindings/api_binding_test_util.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace extensions {
15 namespace {
16 
17 constexpr char kEvent1[] = "Event1";
18 constexpr char kEvent2[] = "Event2";
19 constexpr char kOwner1[] = "Owner1";
20 constexpr char kOwner2[] = "Owner2";
21 constexpr int kRoutingId = 0;
22 
23 }  // namespace
24 
TEST(ListenerTrackerTest,UnfilteredListeners)25 TEST(ListenerTrackerTest, UnfilteredListeners) {
26   ListenerTracker tracker;
27 
28   // Add two listeners for the same event with the same owner. Only the
29   // first added should return true.
30   EXPECT_TRUE(tracker.AddUnfilteredListener(kOwner1, kEvent1));
31   EXPECT_FALSE(tracker.AddUnfilteredListener(kOwner1, kEvent1));
32 
33   EXPECT_TRUE(tracker.AddUnfilteredListener(kOwner1, kEvent2));
34   EXPECT_TRUE(tracker.AddUnfilteredListener(kOwner2, kEvent1));
35 
36   EXPECT_FALSE(tracker.RemoveUnfilteredListener(kOwner1, kEvent1));
37   EXPECT_TRUE(tracker.RemoveUnfilteredListener(kOwner1, kEvent1));
38 
39   EXPECT_TRUE(tracker.RemoveUnfilteredListener(kOwner1, kEvent2));
40   EXPECT_TRUE(tracker.RemoveUnfilteredListener(kOwner2, kEvent1));
41 }
42 
TEST(ListenerTrackerTest,FilteredListenersWithMultipleFilters)43 TEST(ListenerTrackerTest, FilteredListenersWithMultipleFilters) {
44   std::unique_ptr<base::DictionaryValue> filter1 =
45       DictionaryValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
46   std::unique_ptr<base::DictionaryValue> filter2 =
47       DictionaryValueFromString(R"({"url": [{"hostSuffix": "google.com"}]})");
48 
49   ListenerTracker tracker;
50   int filter_id1 = -1;
51   bool was_first_of_kind = false;
52   std::tie(was_first_of_kind, filter_id1) = tracker.AddFilteredListener(
53       kOwner1, kEvent1, filter1->CreateDeepCopy(), kRoutingId);
54   EXPECT_TRUE(was_first_of_kind);
55   EXPECT_NE(-1, filter_id1);
56 
57   int filter_id2 = -1;
58   std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
59       kOwner1, kEvent1, filter1->CreateDeepCopy(), kRoutingId);
60   EXPECT_FALSE(was_first_of_kind);
61   EXPECT_NE(-1, filter_id2);
62   EXPECT_NE(filter_id1, filter_id2);
63 
64   int filter_id3 = -1;
65   std::tie(was_first_of_kind, filter_id3) = tracker.AddFilteredListener(
66       kOwner1, kEvent1, filter2->CreateDeepCopy(), kRoutingId);
67   EXPECT_TRUE(was_first_of_kind);
68   EXPECT_NE(-1, filter_id3);
69 
70   std::unique_ptr<base::DictionaryValue> removed_filter;
71   bool was_last_of_kind = false;
72   std::tie(was_last_of_kind, removed_filter) =
73       tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id1);
74   EXPECT_FALSE(was_last_of_kind);
75   ASSERT_TRUE(removed_filter);
76   EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter1));
77 
78   std::tie(was_last_of_kind, removed_filter) =
79       tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id2);
80   EXPECT_TRUE(was_last_of_kind);
81   ASSERT_TRUE(removed_filter);
82   EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter1));
83 
84   std::tie(was_last_of_kind, removed_filter) =
85       tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id3);
86   EXPECT_TRUE(was_last_of_kind);
87   ASSERT_TRUE(removed_filter);
88   EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter2));
89 }
90 
TEST(ListenerTrackerTest,FilteredListenersWithMultipleOwners)91 TEST(ListenerTrackerTest, FilteredListenersWithMultipleOwners) {
92   std::unique_ptr<base::DictionaryValue> filter =
93       DictionaryValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
94 
95   ListenerTracker tracker;
96   int filter_id1 = -1;
97   bool was_first_of_kind = false;
98   std::tie(was_first_of_kind, filter_id1) = tracker.AddFilteredListener(
99       kOwner1, kEvent1, filter->CreateDeepCopy(), kRoutingId);
100   EXPECT_TRUE(was_first_of_kind);
101   EXPECT_NE(-1, filter_id1);
102 
103   int filter_id2 = -1;
104   std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
105       kOwner2, kEvent1, filter->CreateDeepCopy(), kRoutingId);
106   EXPECT_TRUE(was_first_of_kind);
107   EXPECT_NE(-1, filter_id2);
108   EXPECT_NE(filter_id1, filter_id2);
109 
110   std::unique_ptr<base::DictionaryValue> removed_filter;
111   bool was_last_of_kind = false;
112   std::tie(was_last_of_kind, removed_filter) =
113       tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id1);
114   EXPECT_TRUE(was_last_of_kind);
115   ASSERT_TRUE(removed_filter);
116   EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
117 
118   std::tie(was_last_of_kind, removed_filter) =
119       tracker.RemoveFilteredListener(kOwner2, kEvent1, filter_id2);
120   EXPECT_TRUE(was_last_of_kind);
121   ASSERT_TRUE(removed_filter);
122   EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
123 }
124 
TEST(ListenerTrackerTest,FilteredListenersWithMultipleEvents)125 TEST(ListenerTrackerTest, FilteredListenersWithMultipleEvents) {
126   std::unique_ptr<base::DictionaryValue> filter =
127       DictionaryValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
128 
129   ListenerTracker tracker;
130   int filter_id1 = -1;
131   bool was_first_of_kind = false;
132   std::tie(was_first_of_kind, filter_id1) = tracker.AddFilteredListener(
133       kOwner1, kEvent1, filter->CreateDeepCopy(), kRoutingId);
134   EXPECT_TRUE(was_first_of_kind);
135   EXPECT_NE(-1, filter_id1);
136 
137   int filter_id2 = -1;
138   std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
139       kOwner1, kEvent2, filter->CreateDeepCopy(), kRoutingId);
140   EXPECT_TRUE(was_first_of_kind);
141   EXPECT_NE(-1, filter_id2);
142   EXPECT_NE(filter_id1, filter_id2);
143 
144   std::unique_ptr<base::DictionaryValue> removed_filter;
145   bool was_last_of_kind = false;
146   std::tie(was_last_of_kind, removed_filter) =
147       tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id1);
148   EXPECT_TRUE(was_last_of_kind);
149   ASSERT_TRUE(removed_filter);
150   EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
151 
152   std::tie(was_last_of_kind, removed_filter) =
153       tracker.RemoveFilteredListener(kOwner1, kEvent2, filter_id2);
154   EXPECT_TRUE(was_last_of_kind);
155   ASSERT_TRUE(removed_filter);
156   EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
157 }
158 
TEST(ListenerTrackerTest,InvalidFilteredListener)159 TEST(ListenerTrackerTest, InvalidFilteredListener) {
160   ListenerTracker tracker;
161 
162   std::unique_ptr<base::DictionaryValue> filter =
163       DictionaryValueFromString(R"({"url": ["Not a dictionary"]})");
164   int filter_id = 0;
165   bool was_first_of_kind = false;
166   std::tie(was_first_of_kind, filter_id) = tracker.AddFilteredListener(
167       kOwner1, kEvent1, std::move(filter), kRoutingId);
168   EXPECT_EQ(-1, filter_id);
169   EXPECT_FALSE(was_first_of_kind);
170 }
171 
TEST(ListenerTrackerTest,GetMatchingFilters)172 TEST(ListenerTrackerTest, GetMatchingFilters) {
173   std::unique_ptr<base::DictionaryValue> filter1 =
174       DictionaryValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
175   std::unique_ptr<base::DictionaryValue> filter2 =
176       DictionaryValueFromString(R"({"url": [{"hostContains": "google"}]})");
177   std::unique_ptr<base::DictionaryValue> filter3 =
178       DictionaryValueFromString(R"({"url": [{"hostContains": "example"}]})");
179 
180   ListenerTracker tracker;
181   int filter_id1 = -1;
182   bool was_first_of_kind = false;
183   std::tie(was_first_of_kind, filter_id1) = tracker.AddFilteredListener(
184       kOwner1, kEvent1, filter1->CreateDeepCopy(), kRoutingId);
185   EXPECT_NE(-1, filter_id1);
186 
187   int filter_id2 = -1;
188   std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
189       kOwner1, kEvent1, filter2->CreateDeepCopy(), kRoutingId);
190   EXPECT_NE(-1, filter_id2);
191 
192   int filter_id3 = -1;
193   std::tie(was_first_of_kind, filter_id3) = tracker.AddFilteredListener(
194       kOwner2, kEvent1, filter3->CreateDeepCopy(), kRoutingId);
195   EXPECT_NE(-1, filter_id3);
196 
197   EventFilteringInfo filtering_info;
198   filtering_info.url = GURL("https://example.com/foo");
199   std::set<int> matching_filters =
200       tracker.GetMatchingFilteredListeners(kEvent1, filtering_info, kRoutingId);
201   EXPECT_THAT(matching_filters,
202               testing::UnorderedElementsAre(filter_id1, filter_id3));
203 }
204 
205 }  // namespace extensions
206