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