blob: af2fb43d4dfc2212f77496efb0d69c34c21da46e [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/renderer/bindings/listener_tracker.h"
#include <memory>
#include "base/values.h"
#include "extensions/renderer/bindings/api_binding_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
namespace {
constexpr char kEvent1[] = "Event1";
constexpr char kEvent2[] = "Event2";
constexpr char kOwner1[] = "Owner1";
constexpr char kOwner2[] = "Owner2";
constexpr int kRoutingId = 0;
} // namespace
TEST(ListenerTrackerTest, UnfilteredListeners) {
ListenerTracker tracker;
// Add two listeners for the same event with the same owner. Only the
// first added should return true.
EXPECT_TRUE(tracker.AddUnfilteredListener(kOwner1, kEvent1));
EXPECT_FALSE(tracker.AddUnfilteredListener(kOwner1, kEvent1));
EXPECT_TRUE(tracker.AddUnfilteredListener(kOwner1, kEvent2));
EXPECT_TRUE(tracker.AddUnfilteredListener(kOwner2, kEvent1));
EXPECT_FALSE(tracker.RemoveUnfilteredListener(kOwner1, kEvent1));
EXPECT_TRUE(tracker.RemoveUnfilteredListener(kOwner1, kEvent1));
EXPECT_TRUE(tracker.RemoveUnfilteredListener(kOwner1, kEvent2));
EXPECT_TRUE(tracker.RemoveUnfilteredListener(kOwner2, kEvent1));
}
TEST(ListenerTrackerTest, FilteredListenersWithMultipleFilters) {
std::unique_ptr<base::DictionaryValue> filter1 =
DictionaryValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
std::unique_ptr<base::DictionaryValue> filter2 =
DictionaryValueFromString(R"({"url": [{"hostSuffix": "google.com"}]})");
ListenerTracker tracker;
int filter_id1 = -1;
bool was_first_of_kind = false;
std::tie(was_first_of_kind, filter_id1) = tracker.AddFilteredListener(
kOwner1, kEvent1, filter1->CreateDeepCopy(), kRoutingId);
EXPECT_TRUE(was_first_of_kind);
EXPECT_NE(-1, filter_id1);
int filter_id2 = -1;
std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
kOwner1, kEvent1, filter1->CreateDeepCopy(), kRoutingId);
EXPECT_FALSE(was_first_of_kind);
EXPECT_NE(-1, filter_id2);
EXPECT_NE(filter_id1, filter_id2);
int filter_id3 = -1;
std::tie(was_first_of_kind, filter_id3) = tracker.AddFilteredListener(
kOwner1, kEvent1, filter2->CreateDeepCopy(), kRoutingId);
EXPECT_TRUE(was_first_of_kind);
EXPECT_NE(-1, filter_id3);
std::unique_ptr<base::DictionaryValue> removed_filter;
bool was_last_of_kind = false;
std::tie(was_last_of_kind, removed_filter) =
tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id1);
EXPECT_FALSE(was_last_of_kind);
ASSERT_TRUE(removed_filter);
EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter1));
std::tie(was_last_of_kind, removed_filter) =
tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id2);
EXPECT_TRUE(was_last_of_kind);
ASSERT_TRUE(removed_filter);
EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter1));
std::tie(was_last_of_kind, removed_filter) =
tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id3);
EXPECT_TRUE(was_last_of_kind);
ASSERT_TRUE(removed_filter);
EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter2));
}
TEST(ListenerTrackerTest, FilteredListenersWithMultipleOwners) {
std::unique_ptr<base::DictionaryValue> filter =
DictionaryValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
ListenerTracker tracker;
int filter_id1 = -1;
bool was_first_of_kind = false;
std::tie(was_first_of_kind, filter_id1) = tracker.AddFilteredListener(
kOwner1, kEvent1, filter->CreateDeepCopy(), kRoutingId);
EXPECT_TRUE(was_first_of_kind);
EXPECT_NE(-1, filter_id1);
int filter_id2 = -1;
std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
kOwner2, kEvent1, filter->CreateDeepCopy(), kRoutingId);
EXPECT_TRUE(was_first_of_kind);
EXPECT_NE(-1, filter_id2);
EXPECT_NE(filter_id1, filter_id2);
std::unique_ptr<base::DictionaryValue> removed_filter;
bool was_last_of_kind = false;
std::tie(was_last_of_kind, removed_filter) =
tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id1);
EXPECT_TRUE(was_last_of_kind);
ASSERT_TRUE(removed_filter);
EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
std::tie(was_last_of_kind, removed_filter) =
tracker.RemoveFilteredListener(kOwner2, kEvent1, filter_id2);
EXPECT_TRUE(was_last_of_kind);
ASSERT_TRUE(removed_filter);
EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
}
TEST(ListenerTrackerTest, FilteredListenersWithMultipleEvents) {
std::unique_ptr<base::DictionaryValue> filter =
DictionaryValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
ListenerTracker tracker;
int filter_id1 = -1;
bool was_first_of_kind = false;
std::tie(was_first_of_kind, filter_id1) = tracker.AddFilteredListener(
kOwner1, kEvent1, filter->CreateDeepCopy(), kRoutingId);
EXPECT_TRUE(was_first_of_kind);
EXPECT_NE(-1, filter_id1);
int filter_id2 = -1;
std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
kOwner1, kEvent2, filter->CreateDeepCopy(), kRoutingId);
EXPECT_TRUE(was_first_of_kind);
EXPECT_NE(-1, filter_id2);
EXPECT_NE(filter_id1, filter_id2);
std::unique_ptr<base::DictionaryValue> removed_filter;
bool was_last_of_kind = false;
std::tie(was_last_of_kind, removed_filter) =
tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id1);
EXPECT_TRUE(was_last_of_kind);
ASSERT_TRUE(removed_filter);
EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
std::tie(was_last_of_kind, removed_filter) =
tracker.RemoveFilteredListener(kOwner1, kEvent2, filter_id2);
EXPECT_TRUE(was_last_of_kind);
ASSERT_TRUE(removed_filter);
EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
}
TEST(ListenerTrackerTest, InvalidFilteredListener) {
ListenerTracker tracker;
std::unique_ptr<base::DictionaryValue> filter =
DictionaryValueFromString(R"({"url": ["Not a dictionary"]})");
int filter_id = 0;
bool was_first_of_kind = false;
std::tie(was_first_of_kind, filter_id) = tracker.AddFilteredListener(
kOwner1, kEvent1, std::move(filter), kRoutingId);
EXPECT_EQ(-1, filter_id);
EXPECT_FALSE(was_first_of_kind);
}
TEST(ListenerTrackerTest, GetMatchingFilters) {
std::unique_ptr<base::DictionaryValue> filter1 =
DictionaryValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
std::unique_ptr<base::DictionaryValue> filter2 =
DictionaryValueFromString(R"({"url": [{"hostContains": "google"}]})");
std::unique_ptr<base::DictionaryValue> filter3 =
DictionaryValueFromString(R"({"url": [{"hostContains": "example"}]})");
ListenerTracker tracker;
int filter_id1 = -1;
bool was_first_of_kind = false;
std::tie(was_first_of_kind, filter_id1) = tracker.AddFilteredListener(
kOwner1, kEvent1, filter1->CreateDeepCopy(), kRoutingId);
EXPECT_NE(-1, filter_id1);
int filter_id2 = -1;
std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
kOwner1, kEvent1, filter2->CreateDeepCopy(), kRoutingId);
EXPECT_NE(-1, filter_id2);
int filter_id3 = -1;
std::tie(was_first_of_kind, filter_id3) = tracker.AddFilteredListener(
kOwner2, kEvent1, filter3->CreateDeepCopy(), kRoutingId);
EXPECT_NE(-1, filter_id3);
EventFilteringInfo filtering_info;
filtering_info.url = GURL("https://example.com/foo");
std::set<int> matching_filters =
tracker.GetMatchingFilteredListeners(kEvent1, filtering_info, kRoutingId);
EXPECT_THAT(matching_filters,
testing::UnorderedElementsAre(filter_id1, filter_id3));
}
} // namespace extensions