| Index: chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
|
| diff --git a/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc b/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ede2a2b50d4a03491f54e9f4e8e34ff72d3e852d
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
|
| @@ -0,0 +1,217 @@
|
| +// Copyright 2015 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 "chrome/browser/extensions/api/mdns/mdns_api.h"
|
| +#include "chrome/browser/extensions/extension_service.h"
|
| +#include "chrome/browser/extensions/extension_service_test_base.h"
|
| +#include "chrome/browser/extensions/test_extension_system.h"
|
| +#include "chrome/common/extensions/api/mdns.h"
|
| +#include "content/public/browser/browser_context.h"
|
| +#include "content/public/test/mock_render_process_host.h"
|
| +#include "extensions/browser/extension_prefs_factory.h"
|
| +#include "extensions/browser/extension_registry.h"
|
| +#include "extensions/common/manifest_constants.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace extensions {
|
| +
|
| +namespace {
|
| +
|
| +KeyedService* MDnsAPITestingFactoryFunction(content::BrowserContext* context) {
|
| + return new MDnsAPI(context);
|
| +}
|
| +
|
| +// For ExtensionService interface when it requires a path that is not used.
|
| +base::FilePath bogus_file_pathname(const std::string& name) {
|
| + return base::FilePath(FILE_PATH_LITERAL("//foobar_nonexistent"))
|
| + .AppendASCII(name);
|
| +}
|
| +
|
| +class MockDnsSdRegistry : public DnsSdRegistry {
|
| + public:
|
| + explicit MockDnsSdRegistry(extensions::MDnsAPI* api) : api_(api) {}
|
| + virtual ~MockDnsSdRegistry() {}
|
| +
|
| + MOCK_METHOD1(AddObserver, void(DnsSdObserver* observer));
|
| + MOCK_METHOD1(RemoveObserver, void(DnsSdObserver* observer));
|
| + MOCK_METHOD1(RegisterDnsSdListener, void(std::string service_type));
|
| + MOCK_METHOD1(UnregisterDnsSdListener, void(std::string service_type));
|
| +
|
| + void DispatchMDnsEvent(const std::string& service_type,
|
| + const DnsSdServiceList& services) {
|
| + api_->OnDnsSdEvent(service_type, services);
|
| + }
|
| +
|
| + private:
|
| + extensions::DnsSdRegistry::DnsSdObserver* api_;
|
| +};
|
| +
|
| +class MDnsAPITest : public extensions::ExtensionServiceTestBase {
|
| + public:
|
| + void SetUp() override {
|
| + extensions::ExtensionServiceTestBase::SetUp();
|
| +
|
| + // Set up browser_context().
|
| + InitializeEmptyExtensionService();
|
| +
|
| + // A custom TestingFactoryFunction is required for an MDnsAPI to actually be
|
| + // constructed.
|
| + MDnsAPI::GetFactoryInstance()->SetTestingFactory(
|
| + browser_context(),
|
| + MDnsAPITestingFactoryFunction);
|
| +
|
| + // Create an event router and associate it with the context.
|
| + extensions::EventRouter* event_router = new extensions::EventRouter(
|
| + browser_context(),
|
| + ExtensionPrefsFactory::GetInstance()->GetForBrowserContext(
|
| + browser_context()));
|
| + static_cast<TestExtensionSystem*>(
|
| + ExtensionSystem::Get(browser_context()))->SetEventRouter(
|
| + scoped_ptr<extensions::EventRouter>(event_router));
|
| +
|
| + // Do some sanity checking
|
| + ASSERT_EQ(event_router, EventRouter::Get(browser_context()));
|
| + ASSERT_TRUE(MDnsAPI::Get(browser_context())); // constructs MDnsAPI
|
| +
|
| + registry_ = new MockDnsSdRegistry(MDnsAPI::Get(browser_context()));
|
| + EXPECT_CALL(*dns_sd_registry(),
|
| + AddObserver(MDnsAPI::Get(browser_context())))
|
| + .Times(1);
|
| + MDnsAPI::Get(browser_context())->SetDnsSdRegistryForTesting(
|
| + scoped_ptr<DnsSdRegistry>(registry_));
|
| +
|
| + render_process_host_.reset(
|
| + new content::MockRenderProcessHost(browser_context()));
|
| + }
|
| +
|
| + void TearDown() override {
|
| + EXPECT_CALL(*dns_sd_registry(),
|
| + RemoveObserver(MDnsAPI::Get(browser_context())))
|
| + .Times(1);
|
| + render_process_host_.reset();
|
| + extensions::ExtensionServiceTestBase::TearDown();
|
| + MDnsAPI::GetFactoryInstance()->SetTestingFactory(
|
| + browser_context(),
|
| + nullptr);
|
| +
|
| + registry_ = nullptr;
|
| + }
|
| +
|
| + virtual MockDnsSdRegistry* dns_sd_registry() {
|
| + return registry_;
|
| + }
|
| +
|
| + // Constructs an extension according to the parameters that matter most to
|
| + // MDnsAPI the local unit tests.
|
| + const scoped_refptr<extensions::Extension> CreateExtension(
|
| + std::string name,
|
| + bool is_platform_app,
|
| + std::string extension_id) {
|
| + base::DictionaryValue manifest;
|
| + manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0");
|
| + manifest.SetString(extensions::manifest_keys::kName, name);
|
| + if (is_platform_app) {
|
| + // Setting app.background.page = "background.html" is sufficient to make
|
| + // the extension type TYPE_PLATFORM_APP.
|
| + manifest.Set(extensions::manifest_keys::kPlatformAppBackgroundPage,
|
| + new base::StringValue("background.html"));
|
| + }
|
| +
|
| + std::string error;
|
| + return extensions::Extension::Create(
|
| + bogus_file_pathname(name),
|
| + extensions::Manifest::INVALID_LOCATION,
|
| + manifest,
|
| + Extension::NO_FLAGS,
|
| + extension_id,
|
| + &error);
|
| + }
|
| +
|
| + content::RenderProcessHost* render_process_host() const {
|
| + return render_process_host_.get();
|
| + }
|
| +
|
| + private:
|
| + // The registry is owned by MDnsAPI, but MDnsAPI does not have an accessor
|
| + // for it, so use a private member.
|
| + MockDnsSdRegistry* registry_;
|
| +
|
| + scoped_ptr<content::RenderProcessHost> render_process_host_;
|
| +
|
| +};
|
| +
|
| +TEST_F(MDnsAPITest, ExtensionRespectsWhitelist) {
|
| + const std::string ext_id("mbflcebpggnecokmikipoihdbecnjfoj");
|
| + scoped_refptr<extensions::Extension> extension =
|
| + CreateExtension("Dinosaur networker", false, ext_id);
|
| + ExtensionRegistry::Get(browser_context())->AddEnabled(extension);
|
| + ASSERT_EQ(Manifest::TYPE_EXTENSION, extension.get()->GetType());
|
| +
|
| + // There is a whitelist of mdns service types extensions may access, which
|
| + // includes "_testing._tcp.local" and exludes "_trex._tcp.local"
|
| + {
|
| + base::DictionaryValue filter;
|
| + filter.SetString(kEventFilterServiceTypeKey, "_trex._tcp.local");
|
| +
|
| + ASSERT_TRUE(dns_sd_registry());
|
| + // Test that the extension is able to listen to a non-whitelisted service
|
| + EXPECT_CALL(*dns_sd_registry(), RegisterDnsSdListener("_trex._tcp.local"))
|
| + .Times(0);
|
| + EventRouter::Get(browser_context())->AddFilteredEventListener(
|
| + api::mdns::OnServiceList::kEventName, render_process_host(), ext_id,
|
| + filter, false);
|
| +
|
| + EXPECT_CALL(*dns_sd_registry(), UnregisterDnsSdListener("_trex._tcp.local"))
|
| + .Times(0);
|
| + EventRouter::Get(browser_context())->RemoveFilteredEventListener(
|
| + api::mdns::OnServiceList::kEventName, render_process_host(), ext_id,
|
| + filter, false);
|
| + }
|
| + {
|
| + base::DictionaryValue filter;
|
| + filter.SetString(kEventFilterServiceTypeKey, "_testing._tcp.local");
|
| +
|
| + ASSERT_TRUE(dns_sd_registry());
|
| + // Test that the extension is able to listen to a whitelisted service
|
| + EXPECT_CALL(*dns_sd_registry(),
|
| + RegisterDnsSdListener("_testing._tcp.local"));
|
| + EventRouter::Get(browser_context())->AddFilteredEventListener(
|
| + api::mdns::OnServiceList::kEventName, render_process_host(), ext_id,
|
| + filter, false);
|
| +
|
| + EXPECT_CALL(*dns_sd_registry(),
|
| + UnregisterDnsSdListener("_testing._tcp.local"));
|
| + EventRouter::Get(browser_context())->RemoveFilteredEventListener(
|
| + api::mdns::OnServiceList::kEventName, render_process_host(),
|
| + ext_id, filter, false);
|
| + }
|
| +}
|
| +
|
| +TEST_F(MDnsAPITest, PlatformAppsNotSubjectToWhitelist) {
|
| + const std::string ext_id("mbflcebpggnecokmikipoihdbecnjfoj");
|
| + scoped_refptr<extensions::Extension> extension =
|
| + CreateExtension("Dinosaur networker", true, ext_id);
|
| + ExtensionRegistry::Get(browser_context())->AddEnabled(extension);
|
| + ASSERT_TRUE(extension.get()->is_platform_app());
|
| +
|
| + base::DictionaryValue filter;
|
| + filter.SetString(kEventFilterServiceTypeKey, "_trex._tcp.local");
|
| +
|
| + ASSERT_TRUE(dns_sd_registry());
|
| + // Test that the extension is able to listen to a non-whitelisted service
|
| + EXPECT_CALL(*dns_sd_registry(), RegisterDnsSdListener("_trex._tcp.local"));
|
| + EventRouter::Get(browser_context())->AddFilteredEventListener(
|
| + api::mdns::OnServiceList::kEventName, render_process_host(), ext_id,
|
| + filter, false);
|
| +
|
| + EXPECT_CALL(*dns_sd_registry(), UnregisterDnsSdListener("_trex._tcp.local"));
|
| + EventRouter::Get(browser_context())->RemoveFilteredEventListener(
|
| + api::mdns::OnServiceList::kEventName, render_process_host(), ext_id,
|
| + filter, false);
|
| +}
|
| +
|
| +} // empty namespace
|
| +
|
| +} // namespace extensions
|
|
|