Chromium Code Reviews| 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" #include "base/macros.h" |
|
Devlin
2016/12/02 21:41:24
typo
lazyboy
2016/12/03 00:12:25
Done.
| |
| 13 #include "base/macros.h" | |
| 14 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 15 #include "base/test/histogram_tester.h" | 14 #include "base/test/histogram_tester.h" |
| 16 #include "base/values.h" | 15 #include "base/values.h" |
| 16 #include "components/pref_registry/pref_registry_syncable.h" | |
| 17 #include "components/prefs/pref_service_factory.h" | |
| 18 #include "components/prefs/testing_pref_store.h" | |
| 19 #include "content/public/browser/browser_context.h" | |
| 20 #include "content/public/test/mock_render_process_host.h" | |
| 17 #include "content/public/test/test_browser_thread_bundle.h" | 21 #include "content/public/test/test_browser_thread_bundle.h" |
| 18 #include "extensions/browser/event_listener_map.h" | 22 #include "extensions/browser/event_listener_map.h" |
| 23 #include "extensions/browser/extension_pref_value_map.h" | |
| 24 #include "extensions/browser/extension_prefs.h" | |
| 25 #include "extensions/browser/extension_prefs_factory.h" | |
| 19 #include "extensions/browser/extensions_test.h" | 26 #include "extensions/browser/extensions_test.h" |
| 20 #include "extensions/common/extension_builder.h" | 27 #include "extensions/common/extension_builder.h" |
| 21 #include "extensions/common/test_util.h" | 28 #include "extensions/common/test_util.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 29 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 30 |
| 31 using base::DictionaryValue; | |
| 32 using base::ListValue; | |
| 33 using base::StringValue; | |
| 34 | |
| 24 namespace extensions { | 35 namespace extensions { |
| 25 | 36 |
| 26 namespace { | 37 namespace { |
| 27 | 38 |
| 28 // A simple mock to keep track of listener additions and removals. | 39 // A simple mock to keep track of listener additions and removals. |
| 29 class MockEventRouterObserver : public EventRouter::Observer { | 40 class MockEventRouterObserver : public EventRouter::Observer { |
| 30 public: | 41 public: |
| 31 MockEventRouterObserver() | 42 MockEventRouterObserver() |
| 32 : listener_added_count_(0), | 43 : listener_added_count_(0), |
| 33 listener_removed_count_(0) {} | 44 listener_removed_count_(0) {} |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 manifest->SetInteger("manifest_version", 2); | 110 manifest->SetInteger("manifest_version", 2); |
| 100 manifest->SetString("background.page", "background.html"); | 111 manifest->SetString("background.page", "background.html"); |
| 101 manifest->SetBoolean("background.persistent", persistent); | 112 manifest->SetBoolean("background.persistent", persistent); |
| 102 builder.SetManifest(std::move(manifest)); | 113 builder.SetManifest(std::move(manifest)); |
| 103 if (component) | 114 if (component) |
| 104 builder.SetLocation(Manifest::Location::COMPONENT); | 115 builder.SetLocation(Manifest::Location::COMPONENT); |
| 105 | 116 |
| 106 return builder.Build(); | 117 return builder.Build(); |
| 107 } | 118 } |
| 108 | 119 |
| 120 std::unique_ptr<DictionaryValue> CreateHostSuffixFilter( | |
| 121 const std::string& suffix) { | |
| 122 std::unique_ptr<DictionaryValue> filter(new DictionaryValue()); | |
| 123 std::unique_ptr<ListValue> filter_list(new ListValue()); | |
| 124 std::unique_ptr<DictionaryValue> filter_dict(new DictionaryValue()); | |
| 125 | |
| 126 filter_dict->Set("hostSuffix", new StringValue(suffix)); | |
|
Devlin
2016/12/02 21:41:25
ditto with line 128
lazyboy
2016/12/03 00:12:25
Done.
| |
| 127 filter_list->Append(std::move(filter_dict)); | |
| 128 filter->Set("url", filter_list.release()); | |
|
Devlin
2016/12/02 21:41:25
nit: DictionaryValue::Set() can take a unique_ptr
lazyboy
2016/12/03 00:12:25
Done.
| |
| 129 | |
| 130 return filter; | |
| 131 } | |
| 132 | |
| 109 } // namespace | 133 } // namespace |
| 110 | 134 |
| 111 class EventRouterTest : public ExtensionsTest { | 135 class EventRouterTest : public ExtensionsTest { |
| 112 public: | 136 public: |
| 113 EventRouterTest() {} | 137 EventRouterTest() {} |
| 114 | 138 |
| 115 protected: | 139 protected: |
| 116 // Tests adding and removing observers from EventRouter. | 140 // Tests adding and removing observers from EventRouter. |
| 117 void RunEventRouterObserverTest(const EventListenerConstructor& constructor); | 141 void RunEventRouterObserverTest(const EventListenerConstructor& constructor); |
| 118 | 142 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 } | 180 } |
| 157 } | 181 } |
| 158 | 182 |
| 159 private: | 183 private: |
| 160 content::TestBrowserThreadBundle thread_bundle_; | 184 content::TestBrowserThreadBundle thread_bundle_; |
| 161 base::HistogramTester histogram_tester_; | 185 base::HistogramTester histogram_tester_; |
| 162 | 186 |
| 163 DISALLOW_COPY_AND_ASSIGN(EventRouterTest); | 187 DISALLOW_COPY_AND_ASSIGN(EventRouterTest); |
| 164 }; | 188 }; |
| 165 | 189 |
| 190 class EventRouterFilterTest : public ExtensionsTest { | |
| 191 public: | |
| 192 EventRouterFilterTest() {} | |
| 193 | |
| 194 void SetUp() override { | |
| 195 // extensions::ExtensionServiceTestBase::SetUp(); | |
|
Devlin
2016/12/02 21:41:24
dd
lazyboy
2016/12/03 00:12:25
Done.
| |
| 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) | |
|
Devlin
2016/12/02 21:41:25
This confuses me. Why do we only check one entry?
lazyboy
2016/12/03 00:12:25
The pref dictionary value looks like this:
{
"on
| |
| 267 return nullptr; | |
| 268 | |
| 269 const base::ListValue* filter_list = nullptr; | |
| 270 if (!iter.value().GetAsList(&filter_list)) | |
| 271 return nullptr; | |
|
Devlin
2016/12/02 21:41:24
assuming we keep this impl, we could just ignore t
lazyboy
2016/12/03 00:12:25
Done.
| |
| 272 | |
| 273 return filter_list; | |
| 274 } | |
| 275 | |
| 276 std::unique_ptr<content::RenderProcessHost> render_process_host_; | |
| 277 std::unique_ptr<ExtensionPrefValueMap> extension_pref_value_map_; | |
| 278 std::unique_ptr<PrefService> pref_service_; | |
| 279 | |
| 280 DISALLOW_COPY_AND_ASSIGN(EventRouterFilterTest); | |
| 281 }; | |
| 282 | |
| 166 TEST_F(EventRouterTest, GetBaseEventName) { | 283 TEST_F(EventRouterTest, GetBaseEventName) { |
| 167 // Normal event names are passed through unchanged. | 284 // Normal event names are passed through unchanged. |
| 168 EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar")); | 285 EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar")); |
| 169 | 286 |
| 170 // Sub-events are converted to the part before the slash. | 287 // Sub-events are converted to the part before the slash. |
| 171 EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar/123")); | 288 EXPECT_EQ("foo.onBar", EventRouter::GetBaseEventName("foo.onBar/123")); |
| 172 } | 289 } |
| 173 | 290 |
| 174 // Tests adding and removing observers from EventRouter. | 291 // Tests adding and removing observers from EventRouter. |
| 175 void EventRouterTest::RunEventRouterObserverTest( | 292 void EventRouterTest::RunEventRouterObserverTest( |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 | 385 |
| 269 scoped_refptr<Extension> component_event = CreateExtension(true, false); | 386 scoped_refptr<Extension> component_event = CreateExtension(true, false); |
| 270 router.ReportEvent(events::HistogramValue::FOR_TEST, component_event.get(), | 387 router.ReportEvent(events::HistogramValue::FOR_TEST, component_event.get(), |
| 271 false /** did_enqueue */); | 388 false /** did_enqueue */); |
| 272 ExpectHistogramCounts(6, 2, 2, 1, 0, 2); | 389 ExpectHistogramCounts(6, 2, 2, 1, 0, 2); |
| 273 router.ReportEvent(events::HistogramValue::FOR_TEST, component_event.get(), | 390 router.ReportEvent(events::HistogramValue::FOR_TEST, component_event.get(), |
| 274 true /** did_enqueue */); | 391 true /** did_enqueue */); |
| 275 ExpectHistogramCounts(7, 3, 2, 2, 1, 2); | 392 ExpectHistogramCounts(7, 3, 2, 2, 1, 2); |
| 276 } | 393 } |
| 277 | 394 |
| 395 // Tests adding and removing events with filters. | |
| 396 TEST_F(EventRouterFilterTest, Basic) { | |
| 397 // For the purpose of this test, "." is important in |event_name| as it | |
| 398 // exercises the code path that uses |event_name| as a key in DictionaryValue. | |
| 399 const std::string event_name = "chrome.onMyEvent"; | |
|
Devlin
2016/12/02 21:41:24
nit: prefer kEventName, kExtensionId, etc for cons
Devlin
2016/12/02 21:41:24
Just for test clarity, it might be better to use a
lazyboy
2016/12/03 00:12:25
Done.
lazyboy
2016/12/03 00:12:25
Done.
| |
| 400 | |
| 401 const std::string extension_id = "mbflcebpggnecokmikipoihdbecnjfoj"; | |
| 402 std::string host_suffixes[] = {"foo.com", "bar.com", "baz.com"}; | |
| 403 std::vector<std::unique_ptr<DictionaryValue>> filters; | |
| 404 for (size_t i = 0; i < arraysize(host_suffixes); ++i) { | |
| 405 std::unique_ptr<base::DictionaryValue> filter1 = | |
| 406 CreateHostSuffixFilter(host_suffixes[i]); | |
| 407 EventRouter::Get(browser_context()) | |
| 408 ->AddFilteredEventListener(event_name, render_process_host(), | |
| 409 extension_id, *filter1.get(), true); | |
|
Devlin
2016/12/02 21:41:25
*foo.get() is redundant; -> *foo.
lazyboy
2016/12/03 00:12:25
Done.
| |
| 410 filters.push_back(std::move(filter1)); | |
| 411 } | |
| 412 | |
| 413 const base::DictionaryValue* filtered_events = | |
| 414 GetFilteredEvents(extension_id); | |
| 415 ASSERT_TRUE(filtered_events); | |
| 416 ASSERT_EQ(1u, filtered_events->size()); | |
| 417 | |
| 418 DictionaryValue::Iterator iter(*filtered_events); | |
| 419 ASSERT_EQ(event_name, iter.key()); | |
| 420 const base::ListValue* filter_list = nullptr; | |
| 421 ASSERT_TRUE(iter.value().GetAsList(&filter_list)); | |
| 422 ASSERT_TRUE(filter_list); | |
| 423 ASSERT_EQ(3u, filter_list->GetSize()); | |
| 424 | |
| 425 ASSERT_TRUE(ContainsFilter(extension_id, event_name, *filters[0].get())); | |
| 426 ASSERT_TRUE(ContainsFilter(extension_id, event_name, *filters[1].get())); | |
| 427 ASSERT_TRUE(ContainsFilter(extension_id, event_name, *filters[2].get())); | |
| 428 | |
| 429 // Remove the second filter. | |
| 430 event_router()->RemoveFilteredEventListener( | |
| 431 event_name, render_process_host(), extension_id, *filters[1].get(), true); | |
| 432 ASSERT_TRUE(ContainsFilter(extension_id, event_name, *filters[0].get())); | |
| 433 ASSERT_FALSE(ContainsFilter(extension_id, event_name, *filters[1].get())); | |
| 434 ASSERT_TRUE(ContainsFilter(extension_id, event_name, *filters[2].get())); | |
| 435 | |
| 436 // Remove the first filter. | |
| 437 event_router()->RemoveFilteredEventListener( | |
| 438 event_name, render_process_host(), extension_id, *filters[0].get(), true); | |
| 439 ASSERT_FALSE(ContainsFilter(extension_id, event_name, *filters[0].get())); | |
| 440 ASSERT_FALSE(ContainsFilter(extension_id, event_name, *filters[1].get())); | |
| 441 ASSERT_TRUE(ContainsFilter(extension_id, event_name, *filters[2].get())); | |
| 442 | |
| 443 // Remove the third filter. | |
| 444 event_router()->RemoveFilteredEventListener( | |
| 445 event_name, render_process_host(), extension_id, *filters[2].get(), true); | |
| 446 ASSERT_FALSE(ContainsFilter(extension_id, event_name, *filters[0].get())); | |
| 447 ASSERT_FALSE(ContainsFilter(extension_id, event_name, *filters[1].get())); | |
| 448 ASSERT_FALSE(ContainsFilter(extension_id, event_name, *filters[2].get())); | |
| 449 } | |
| 450 | |
| 278 } // namespace extensions | 451 } // namespace extensions |
| OLD | NEW |