1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/mdns/mdns_api.h"
6 #include "chrome/browser/extensions/extension_service.h"
7 #include "chrome/browser/extensions/extension_service_test_base.h"
8 #include "chrome/browser/extensions/test_extension_system.h"
9 #include "chrome/common/extensions/api/mdns.h"
10 #include "content/public/browser/browser_context.h"
11 #include "content/public/test/mock_render_process_host.h"
12 #include "extensions/browser/extension_prefs_factory.h"
13 #include "extensions/browser/extension_registry.h"
14 #include "extensions/common/manifest_constants.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 namespace extensions
{
22 KeyedService
* MDnsAPITestingFactoryFunction(content::BrowserContext
* context
) {
23 return new MDnsAPI(context
);
26 // For ExtensionService interface when it requires a path that is not used.
27 base::FilePath
bogus_file_pathname(const std::string
& name
) {
28 return base::FilePath(FILE_PATH_LITERAL("//foobar_nonexistent"))
32 class MockDnsSdRegistry
: public DnsSdRegistry
{
34 explicit MockDnsSdRegistry(extensions::MDnsAPI
* api
) : api_(api
) {}
35 virtual ~MockDnsSdRegistry() {}
37 MOCK_METHOD1(AddObserver
, void(DnsSdObserver
* observer
));
38 MOCK_METHOD1(RemoveObserver
, void(DnsSdObserver
* observer
));
39 MOCK_METHOD1(RegisterDnsSdListener
, void(std::string service_type
));
40 MOCK_METHOD1(UnregisterDnsSdListener
, void(std::string service_type
));
42 void DispatchMDnsEvent(const std::string
& service_type
,
43 const DnsSdServiceList
& services
) {
44 api_
->OnDnsSdEvent(service_type
, services
);
48 extensions::DnsSdRegistry::DnsSdObserver
* api_
;
51 class MDnsAPITest
: public extensions::ExtensionServiceTestBase
{
53 void SetUp() override
{
54 extensions::ExtensionServiceTestBase::SetUp();
56 // Set up browser_context().
57 InitializeEmptyExtensionService();
59 // A custom TestingFactoryFunction is required for an MDnsAPI to actually be
61 MDnsAPI::GetFactoryInstance()->SetTestingFactory(
63 MDnsAPITestingFactoryFunction
);
65 // Create an event router and associate it with the context.
66 extensions::EventRouter
* event_router
= new extensions::EventRouter(
68 ExtensionPrefsFactory::GetInstance()->GetForBrowserContext(
70 static_cast<TestExtensionSystem
*>(
71 ExtensionSystem::Get(browser_context()))->SetEventRouter(
72 scoped_ptr
<extensions::EventRouter
>(event_router
));
74 // Do some sanity checking
75 ASSERT_EQ(event_router
, EventRouter::Get(browser_context()));
76 ASSERT_TRUE(MDnsAPI::Get(browser_context())); // constructs MDnsAPI
78 registry_
= new MockDnsSdRegistry(MDnsAPI::Get(browser_context()));
79 EXPECT_CALL(*dns_sd_registry(),
80 AddObserver(MDnsAPI::Get(browser_context())))
82 MDnsAPI::Get(browser_context())->SetDnsSdRegistryForTesting(
83 scoped_ptr
<DnsSdRegistry
>(registry_
));
85 render_process_host_
.reset(
86 new content::MockRenderProcessHost(browser_context()));
89 void TearDown() override
{
90 EXPECT_CALL(*dns_sd_registry(),
91 RemoveObserver(MDnsAPI::Get(browser_context())))
93 render_process_host_
.reset();
94 extensions::ExtensionServiceTestBase::TearDown();
95 MDnsAPI::GetFactoryInstance()->SetTestingFactory(
102 virtual MockDnsSdRegistry
* dns_sd_registry() {
106 // Constructs an extension according to the parameters that matter most to
107 // MDnsAPI the local unit tests.
108 const scoped_refptr
<extensions::Extension
> CreateExtension(
110 bool is_platform_app
,
111 std::string extension_id
) {
112 base::DictionaryValue manifest
;
113 manifest
.SetString(extensions::manifest_keys::kVersion
, "1.0.0.0");
114 manifest
.SetString(extensions::manifest_keys::kName
, name
);
115 if (is_platform_app
) {
116 // Setting app.background.page = "background.html" is sufficient to make
117 // the extension type TYPE_PLATFORM_APP.
118 manifest
.Set(extensions::manifest_keys::kPlatformAppBackgroundPage
,
119 new base::StringValue("background.html"));
123 return extensions::Extension::Create(
124 bogus_file_pathname(name
),
125 extensions::Manifest::INVALID_LOCATION
,
132 content::RenderProcessHost
* render_process_host() const {
133 return render_process_host_
.get();
137 // The registry is owned by MDnsAPI, but MDnsAPI does not have an accessor
138 // for it, so use a private member.
139 MockDnsSdRegistry
* registry_
;
141 scoped_ptr
<content::RenderProcessHost
> render_process_host_
;
145 TEST_F(MDnsAPITest
, ExtensionRespectsWhitelist
) {
146 const std::string
ext_id("mbflcebpggnecokmikipoihdbecnjfoj");
147 scoped_refptr
<extensions::Extension
> extension
=
148 CreateExtension("Dinosaur networker", false, ext_id
);
149 ExtensionRegistry::Get(browser_context())->AddEnabled(extension
);
150 ASSERT_EQ(Manifest::TYPE_EXTENSION
, extension
.get()->GetType());
152 // There is a whitelist of mdns service types extensions may access, which
153 // includes "_testing._tcp.local" and exludes "_trex._tcp.local"
155 base::DictionaryValue filter
;
156 filter
.SetString(kEventFilterServiceTypeKey
, "_trex._tcp.local");
158 ASSERT_TRUE(dns_sd_registry());
159 // Test that the extension is able to listen to a non-whitelisted service
160 EXPECT_CALL(*dns_sd_registry(), RegisterDnsSdListener("_trex._tcp.local"))
162 EventRouter::Get(browser_context())->AddFilteredEventListener(
163 api::mdns::OnServiceList::kEventName
, render_process_host(), ext_id
,
166 EXPECT_CALL(*dns_sd_registry(), UnregisterDnsSdListener("_trex._tcp.local"))
168 EventRouter::Get(browser_context())->RemoveFilteredEventListener(
169 api::mdns::OnServiceList::kEventName
, render_process_host(), ext_id
,
173 base::DictionaryValue filter
;
174 filter
.SetString(kEventFilterServiceTypeKey
, "_testing._tcp.local");
176 ASSERT_TRUE(dns_sd_registry());
177 // Test that the extension is able to listen to a whitelisted service
178 EXPECT_CALL(*dns_sd_registry(),
179 RegisterDnsSdListener("_testing._tcp.local"));
180 EventRouter::Get(browser_context())->AddFilteredEventListener(
181 api::mdns::OnServiceList::kEventName
, render_process_host(), ext_id
,
184 EXPECT_CALL(*dns_sd_registry(),
185 UnregisterDnsSdListener("_testing._tcp.local"));
186 EventRouter::Get(browser_context())->RemoveFilteredEventListener(
187 api::mdns::OnServiceList::kEventName
, render_process_host(),
188 ext_id
, filter
, false);
192 TEST_F(MDnsAPITest
, PlatformAppsNotSubjectToWhitelist
) {
193 const std::string
ext_id("mbflcebpggnecokmikipoihdbecnjfoj");
194 scoped_refptr
<extensions::Extension
> extension
=
195 CreateExtension("Dinosaur networker", true, ext_id
);
196 ExtensionRegistry::Get(browser_context())->AddEnabled(extension
);
197 ASSERT_TRUE(extension
.get()->is_platform_app());
199 base::DictionaryValue filter
;
200 filter
.SetString(kEventFilterServiceTypeKey
, "_trex._tcp.local");
202 ASSERT_TRUE(dns_sd_registry());
203 // Test that the extension is able to listen to a non-whitelisted service
204 EXPECT_CALL(*dns_sd_registry(), RegisterDnsSdListener("_trex._tcp.local"));
205 EventRouter::Get(browser_context())->AddFilteredEventListener(
206 api::mdns::OnServiceList::kEventName
, render_process_host(), ext_id
,
209 EXPECT_CALL(*dns_sd_registry(), UnregisterDnsSdListener("_trex._tcp.local"));
210 EventRouter::Get(browser_context())->RemoveFilteredEventListener(
211 api::mdns::OnServiceList::kEventName
, render_process_host(), ext_id
,
217 } // namespace extensions