| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "extensions/browser/event_router.h" | 5 #include "extensions/browser/event_router.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/test/histogram_tester.h" | 15 #include "base/test/histogram_tester.h" |
| 16 #include "base/values.h" | 16 #include "base/values.h" |
| 17 #include "components/pref_registry/pref_registry_syncable.h" |
| 18 #include "components/prefs/pref_service_factory.h" |
| 19 #include "components/prefs/testing_pref_store.h" |
| 20 #include "content/public/browser/browser_context.h" |
| 21 #include "content/public/test/mock_render_process_host.h" |
| 17 #include "content/public/test/test_browser_thread_bundle.h" | 22 #include "content/public/test/test_browser_thread_bundle.h" |
| 18 #include "extensions/browser/event_listener_map.h" | 23 #include "extensions/browser/event_listener_map.h" |
| 24 #include "extensions/browser/extension_pref_value_map.h" |
| 25 #include "extensions/browser/extension_prefs.h" |
| 26 #include "extensions/browser/extension_prefs_factory.h" |
| 19 #include "extensions/browser/extensions_test.h" | 27 #include "extensions/browser/extensions_test.h" |
| 20 #include "extensions/common/extension_builder.h" | 28 #include "extensions/common/extension_builder.h" |
| 21 #include "extensions/common/test_util.h" | 29 #include "extensions/common/test_util.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 30 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 31 |
| 32 using base::DictionaryValue; |
| 33 using base::ListValue; |
| 34 using base::StringValue; |
| 35 |
| 24 namespace extensions { | 36 namespace extensions { |
| 25 | 37 |
| 26 namespace { | 38 namespace { |
| 27 | 39 |
| 28 // A simple mock to keep track of listener additions and removals. | 40 // A simple mock to keep track of listener additions and removals. |
| 29 class MockEventRouterObserver : public EventRouter::Observer { | 41 class MockEventRouterObserver : public EventRouter::Observer { |
| 30 public: | 42 public: |
| 31 MockEventRouterObserver() | 43 MockEventRouterObserver() |
| 32 : listener_added_count_(0), | 44 : listener_added_count_(0), |
| 33 listener_removed_count_(0) {} | 45 listener_removed_count_(0) {} |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 manifest->SetInteger("manifest_version", 2); | 111 manifest->SetInteger("manifest_version", 2); |
| 100 manifest->SetString("background.page", "background.html"); | 112 manifest->SetString("background.page", "background.html"); |
| 101 manifest->SetBoolean("background.persistent", persistent); | 113 manifest->SetBoolean("background.persistent", persistent); |
| 102 builder.SetManifest(std::move(manifest)); | 114 builder.SetManifest(std::move(manifest)); |
| 103 if (component) | 115 if (component) |
| 104 builder.SetLocation(Manifest::Location::COMPONENT); | 116 builder.SetLocation(Manifest::Location::COMPONENT); |
| 105 | 117 |
| 106 return builder.Build(); | 118 return builder.Build(); |
| 107 } | 119 } |
| 108 | 120 |
| 121 std::unique_ptr<DictionaryValue> CreateHostSuffixFilter( |
| 122 const std::string& suffix) { |
| 123 std::unique_ptr<DictionaryValue> filter(new DictionaryValue()); |
| 124 std::unique_ptr<ListValue> filter_list(new ListValue()); |
| 125 std::unique_ptr<DictionaryValue> filter_dict(new DictionaryValue()); |
| 126 |
| 127 filter_dict->Set("hostSuffix", base::MakeUnique<StringValue>(suffix)); |
| 128 filter_list->Append(std::move(filter_dict)); |
| 129 filter->Set("url", std::move(filter_list)); |
| 130 |
| 131 return filter; |
| 132 } |
| 133 |
| 109 } // namespace | 134 } // namespace |
| 110 | 135 |
| 111 class EventRouterTest : public ExtensionsTest { | 136 class EventRouterTest : public ExtensionsTest { |
| 112 public: | 137 public: |
| 113 EventRouterTest() {} | 138 EventRouterTest() {} |
| 114 | 139 |
| 115 protected: | 140 protected: |
| 116 // Tests adding and removing observers from EventRouter. | 141 // Tests adding and removing observers from EventRouter. |
| 117 void RunEventRouterObserverTest(const EventListenerConstructor& constructor); | 142 void RunEventRouterObserverTest(const EventListenerConstructor& constructor); |
| 118 | 143 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 } | 181 } |
| 157 } | 182 } |
| 158 | 183 |
| 159 private: | 184 private: |
| 160 content::TestBrowserThreadBundle thread_bundle_; | 185 content::TestBrowserThreadBundle thread_bundle_; |
| 161 base::HistogramTester histogram_tester_; | 186 base::HistogramTester histogram_tester_; |
| 162 | 187 |
| 163 DISALLOW_COPY_AND_ASSIGN(EventRouterTest); | 188 DISALLOW_COPY_AND_ASSIGN(EventRouterTest); |
| 164 }; | 189 }; |
| 165 | 190 |
| 191 class EventRouterFilterTest : public ExtensionsTest { |
| 192 public: |
| 193 EventRouterFilterTest() {} |
| 194 |
| 195 void SetUp() override { |
| 196 ExtensionsTest::SetUp(); |
| 197 |
| 198 render_process_host_.reset( |
| 199 new content::MockRenderProcessHost(browser_context())); |
| 200 |
| 201 // Set up all the dependencies of ExtensionPrefs. |
| 202 extension_pref_value_map_.reset(new ExtensionPrefValueMap()); |
| 203 PrefServiceFactory factory; |
| 204 factory.set_user_prefs(new TestingPrefStore()); |
| 205 factory.set_extension_prefs(new TestingPrefStore()); |
| 206 user_prefs::PrefRegistrySyncable* pref_registry = |
| 207 new user_prefs::PrefRegistrySyncable(); |
| 208 // Prefs should be registered before the PrefService is created. |
| 209 ExtensionPrefs::RegisterProfilePrefs(pref_registry); |
| 210 pref_service_ = factory.Create(pref_registry); |
| 211 |
| 212 std::unique_ptr<ExtensionPrefs> extension_prefs(ExtensionPrefs::Create( |
| 213 browser_context(), pref_service_.get(), |
| 214 browser_context()->GetPath().AppendASCII("Extensions"), |
| 215 extension_pref_value_map_.get(), false /* extensions_disabled */, |
| 216 std::vector<ExtensionPrefsObserver*>())); |
| 217 |
| 218 ExtensionPrefsFactory::GetInstance()->SetInstanceForTesting( |
| 219 browser_context(), std::move(extension_prefs)); |
| 220 |
| 221 ASSERT_TRUE(EventRouter::Get(browser_context())); // constructs EventRouter |
| 222 } |
| 223 |
| 224 void TearDown() override { |
| 225 render_process_host_.reset(); |
| 226 ExtensionsTest::TearDown(); |
| 227 } |
| 228 |
| 229 content::RenderProcessHost* render_process_host() const { |
| 230 return render_process_host_.get(); |
| 231 } |
| 232 |
| 233 EventRouter* event_router() { return EventRouter::Get(browser_context()); } |
| 234 |
| 235 const DictionaryValue* GetFilteredEvents(const std::string& extension_id) { |
| 236 return event_router()->GetFilteredEvents(extension_id); |
| 237 } |
| 238 |
| 239 bool ContainsFilter(const std::string& extension_id, |
| 240 const std::string& event_name, |
| 241 const DictionaryValue& to_check) { |
| 242 const ListValue* filter_list = GetFilterList(extension_id, event_name); |
| 243 if (!filter_list) { |
| 244 ADD_FAILURE(); |
| 245 return false; |
| 246 } |
| 247 |
| 248 for (size_t i = 0; i < filter_list->GetSize(); ++i) { |
| 249 const DictionaryValue* filter = nullptr; |
| 250 if (!filter_list->GetDictionary(i, &filter)) { |
| 251 ADD_FAILURE(); |
| 252 return false; |
| 253 } |
| 254 if (filter->Equals(&to_check)) |
| 255 return true; |
| 256 } |
| 257 return false; |
| 258 } |
| 259 |
| 260 private: |
| 261 const ListValue* GetFilterList(const std::string& extension_id, |
| 262 const std::string& event_name) { |
| 263 const base::DictionaryValue* filtered_events = |
| 264 GetFilteredEvents(extension_id); |
| 265 DictionaryValue::Iterator iter(*filtered_events); |
| 266 if (iter.key() != event_name) |
| 267 return nullptr; |
| 268 |
| 269 const base::ListValue* filter_list = nullptr; |
| 270 iter.value().GetAsList(&filter_list); |
| 271 return filter_list; |
| 272 } |
| 273 |
| 274 std::unique_ptr<content::RenderProcessHost> render_process_host_; |
| 275 std::unique_ptr<ExtensionPrefValueMap> extension_pref_value_map_; |
| 276 std::unique_ptr<PrefService> pref_service_; |
| 277 |
| 278 DISALLOW_COPY_AND_ASSIGN(EventRouterFilterTest); |
| 279 }; |
| 280 |
| 166 TEST_F(EventRouterTest, GetBaseEventName) { | 281 TEST_F(EventRouterTest, GetBaseEventName) { |
| 167 // Normal event names are passed through unchanged. | 282 // Normal event names are passed through unchanged. |
| 168 EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar")); | 283 EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar")); |
| 169 | 284 |
| 170 // Sub-events are converted to the part before the slash. | 285 // Sub-events are converted to the part before the slash. |
| 171 EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar/123")); | 286 EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar/123")); |
| 172 } | 287 } |
| 173 | 288 |
| 174 // Tests adding and removing observers from EventRouter. | 289 // Tests adding and removing observers from EventRouter. |
| 175 void EventRouterTest::RunEventRouterObserverTest( | 290 void EventRouterTest::RunEventRouterObserverTest( |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 | 383 |
| 269 scoped_refptr<Extension> component_event = CreateExtension(true, false); | 384 scoped_refptr<Extension> component_event = CreateExtension(true, false); |
| 270 router.ReportEvent(events::HistogramValue::FOR_TEST, component_event.get(), | 385 router.ReportEvent(events::HistogramValue::FOR_TEST, component_event.get(), |
| 271 false /** did_enqueue */); | 386 false /** did_enqueue */); |
| 272 ExpectHistogramCounts(6, 2, 2, 1, 0, 2); | 387 ExpectHistogramCounts(6, 2, 2, 1, 0, 2); |
| 273 router.ReportEvent(events::HistogramValue::FOR_TEST, component_event.get(), | 388 router.ReportEvent(events::HistogramValue::FOR_TEST, component_event.get(), |
| 274 true /** did_enqueue */); | 389 true /** did_enqueue */); |
| 275 ExpectHistogramCounts(7, 3, 2, 2, 1, 2); | 390 ExpectHistogramCounts(7, 3, 2, 2, 1, 2); |
| 276 } | 391 } |
| 277 | 392 |
| 393 // Tests adding and removing events with filters. |
| 394 TEST_F(EventRouterFilterTest, Basic) { |
| 395 // For the purpose of this test, "." is important in |event_name| as it |
| 396 // exercises the code path that uses |event_name| as a key in DictionaryValue. |
| 397 const std::string kEventName = "webNavigation.onBeforeNavigate"; |
| 398 |
| 399 const std::string kExtensionId = "mbflcebpggnecokmikipoihdbecnjfoj"; |
| 400 const std::string kHostSuffixes[] = {"foo.com", "bar.com", "baz.com"}; |
| 401 std::vector<std::unique_ptr<DictionaryValue>> filters; |
| 402 for (size_t i = 0; i < arraysize(kHostSuffixes); ++i) { |
| 403 std::unique_ptr<base::DictionaryValue> filter = |
| 404 CreateHostSuffixFilter(kHostSuffixes[i]); |
| 405 EventRouter::Get(browser_context()) |
| 406 ->AddFilteredEventListener(kEventName, render_process_host(), |
| 407 kExtensionId, *filter, true); |
| 408 filters.push_back(std::move(filter)); |
| 409 } |
| 410 |
| 411 const base::DictionaryValue* filtered_events = |
| 412 GetFilteredEvents(kExtensionId); |
| 413 ASSERT_TRUE(filtered_events); |
| 414 ASSERT_EQ(1u, filtered_events->size()); |
| 415 |
| 416 DictionaryValue::Iterator iter(*filtered_events); |
| 417 ASSERT_EQ(kEventName, iter.key()); |
| 418 const base::ListValue* filter_list = nullptr; |
| 419 ASSERT_TRUE(iter.value().GetAsList(&filter_list)); |
| 420 ASSERT_TRUE(filter_list); |
| 421 ASSERT_EQ(3u, filter_list->GetSize()); |
| 422 |
| 423 ASSERT_TRUE(ContainsFilter(kExtensionId, kEventName, *filters[0])); |
| 424 ASSERT_TRUE(ContainsFilter(kExtensionId, kEventName, *filters[1])); |
| 425 ASSERT_TRUE(ContainsFilter(kExtensionId, kEventName, *filters[2])); |
| 426 |
| 427 // Remove the second filter. |
| 428 event_router()->RemoveFilteredEventListener(kEventName, render_process_host(), |
| 429 kExtensionId, *filters[1], true); |
| 430 ASSERT_TRUE(ContainsFilter(kExtensionId, kEventName, *filters[0])); |
| 431 ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[1])); |
| 432 ASSERT_TRUE(ContainsFilter(kExtensionId, kEventName, *filters[2])); |
| 433 |
| 434 // Remove the first filter. |
| 435 event_router()->RemoveFilteredEventListener(kEventName, render_process_host(), |
| 436 kExtensionId, *filters[0], true); |
| 437 ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[0])); |
| 438 ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[1])); |
| 439 ASSERT_TRUE(ContainsFilter(kExtensionId, kEventName, *filters[2])); |
| 440 |
| 441 // Remove the third filter. |
| 442 event_router()->RemoveFilteredEventListener(kEventName, render_process_host(), |
| 443 kExtensionId, *filters[2], true); |
| 444 ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[0])); |
| 445 ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[1])); |
| 446 ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[2])); |
| 447 } |
| 448 |
| 278 } // namespace extensions | 449 } // namespace extensions |
| OLD | NEW |