// Copyright 2013 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/browser/event_router.h" #include <string> #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/values.h" #include "extensions/browser/event_listener_map.h" #include "testing/gtest/include/gtest/gtest.h" namespace extensions { namespace { // A simple mock to keep track of listener additions and removals. class MockEventRouterObserver : public EventRouter::Observer { public: MockEventRouterObserver() : listener_added_count_(0), listener_removed_count_(0) {} virtual ~MockEventRouterObserver() {} int listener_added_count() const { return listener_added_count_; } int listener_removed_count() const { return listener_removed_count_; } const std::string& last_event_name() const { return last_event_name_; } void Reset() { listener_added_count_ = 0; listener_removed_count_ = 0; last_event_name_.clear(); } // EventRouter::Observer overrides: virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE { listener_added_count_++; last_event_name_ = details.event_name; } virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE { listener_removed_count_++; last_event_name_ = details.event_name; } private: int listener_added_count_; int listener_removed_count_; std::string last_event_name_; DISALLOW_COPY_AND_ASSIGN(MockEventRouterObserver); }; } // namespace typedef testing::Test EventRouterTest; TEST_F(EventRouterTest, GetBaseEventName) { // Normal event names are passed through unchanged. EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar")); // Sub-events are converted to the part before the slash. EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar/123")); } // Tests adding and removing observers from EventRouter. TEST_F(EventRouterTest, EventRouterObserver) { EventRouter router(NULL, NULL); EventListener listener( "event_name", "extension_id", NULL, scoped_ptr<DictionaryValue>()); // Add/remove works without any observers. router.OnListenerAdded(&listener); router.OnListenerRemoved(&listener); // Register observers that both match and don't match the event above. MockEventRouterObserver matching_observer; router.RegisterObserver(&matching_observer, "event_name"); MockEventRouterObserver non_matching_observer; router.RegisterObserver(&non_matching_observer, "other"); // Adding a listener notifies the appropriate observers. router.OnListenerAdded(&listener); EXPECT_EQ(1, matching_observer.listener_added_count()); EXPECT_EQ(0, non_matching_observer.listener_added_count()); // Removing a listener notifies the appropriate observers. router.OnListenerRemoved(&listener); EXPECT_EQ(1, matching_observer.listener_removed_count()); EXPECT_EQ(0, non_matching_observer.listener_removed_count()); // Adding the listener again notifies again. router.OnListenerAdded(&listener); EXPECT_EQ(2, matching_observer.listener_added_count()); EXPECT_EQ(0, non_matching_observer.listener_added_count()); // Removing the listener again notifies again. router.OnListenerRemoved(&listener); EXPECT_EQ(2, matching_observer.listener_removed_count()); EXPECT_EQ(0, non_matching_observer.listener_removed_count()); // Adding a listener with a sub-event notifies the main observer with // proper details. matching_observer.Reset(); EventListener sub_event_listener( "event_name/1", "extension_id", NULL, scoped_ptr<DictionaryValue>()); router.OnListenerAdded(&sub_event_listener); EXPECT_EQ(1, matching_observer.listener_added_count()); EXPECT_EQ(0, matching_observer.listener_removed_count()); EXPECT_EQ("event_name/1", matching_observer.last_event_name()); // Ditto for removing the listener. matching_observer.Reset(); router.OnListenerRemoved(&sub_event_listener); EXPECT_EQ(0, matching_observer.listener_added_count()); EXPECT_EQ(1, matching_observer.listener_removed_count()); EXPECT_EQ("event_name/1", matching_observer.last_event_name()); } } // namespace extensions