Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / extensions / api / mdns / mdns_api.cc
blob2a7c41d210931d1540e61b8cb89fe402a203e1e8
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
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/mdns/mdns_api.h"
7 #include <vector>
9 #include "base/lazy_instance.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/common/extensions/api/mdns.h"
12 #include "extensions/browser/extension_registry.h"
14 namespace extensions {
16 namespace mdns = api::mdns;
18 namespace {
20 // Whitelisted mDNS service types.
21 const char kCastServiceType[] = "_googlecast._tcp.local";
22 const char kPrivetServiceType[] = "_privet._tcp.local";
23 const char kTestServiceType[] = "_testing._tcp.local";
25 bool IsServiceTypeWhitelisted(const std::string& service_type) {
26 return service_type == kCastServiceType ||
27 service_type == kPrivetServiceType ||
28 service_type == kTestServiceType;
31 } // namespace
33 MDnsAPI::MDnsAPI(content::BrowserContext* context) : browser_context_(context) {
34 DCHECK(browser_context_);
35 extensions::EventRouter* event_router = EventRouter::Get(context);
36 DCHECK(event_router);
37 event_router->RegisterObserver(this, mdns::OnServiceList::kEventName);
40 MDnsAPI::~MDnsAPI() {
41 if (dns_sd_registry_.get()) {
42 dns_sd_registry_->RemoveObserver(this);
46 // static
47 MDnsAPI* MDnsAPI::Get(content::BrowserContext* context) {
48 return BrowserContextKeyedAPIFactory<MDnsAPI>::Get(context);
51 static base::LazyInstance<BrowserContextKeyedAPIFactory<MDnsAPI> > g_factory =
52 LAZY_INSTANCE_INITIALIZER;
54 // static
55 BrowserContextKeyedAPIFactory<MDnsAPI>* MDnsAPI::GetFactoryInstance() {
56 return g_factory.Pointer();
59 void MDnsAPI::SetDnsSdRegistryForTesting(
60 scoped_ptr<DnsSdRegistry> dns_sd_registry) {
61 dns_sd_registry_ = dns_sd_registry.Pass();
62 if (dns_sd_registry_.get())
63 dns_sd_registry_.get()->AddObserver(this);
66 DnsSdRegistry* MDnsAPI::dns_sd_registry() {
67 DCHECK(thread_checker_.CalledOnValidThread());
68 if (!dns_sd_registry_.get()) {
69 dns_sd_registry_.reset(new extensions::DnsSdRegistry());
70 dns_sd_registry_->AddObserver(this);
72 return dns_sd_registry_.get();
75 void MDnsAPI::OnListenerAdded(const EventListenerInfo& details) {
76 DCHECK(thread_checker_.CalledOnValidThread());
77 UpdateMDnsListeners(details);
80 void MDnsAPI::OnListenerRemoved(const EventListenerInfo& details) {
81 DCHECK(thread_checker_.CalledOnValidThread());
82 UpdateMDnsListeners(details);
85 void MDnsAPI::UpdateMDnsListeners(const EventListenerInfo& details) {
86 std::set<std::string> new_service_types;
88 // Check all listeners for service type filters.
89 const EventListenerMap::ListenerList& listeners =
90 extensions::EventRouter::Get(browser_context_)
91 ->listeners()
92 .GetEventListenersByName(details.event_name);
93 for (EventListenerMap::ListenerList::const_iterator it = listeners.begin();
94 it != listeners.end(); ++it) {
95 base::DictionaryValue* filter = ((*it)->filter());
97 std::string filter_value;
98 filter->GetStringASCII(kEventFilterServiceTypeKey, &filter_value);
99 if (filter_value.empty())
100 continue;
102 const Extension* extension = ExtensionRegistry::Get(browser_context_)->
103 enabled_extensions().GetByID((*it)->extension_id());
104 // Don't listen for services associated only with disabled extensions.
105 if (!extension)
106 continue;
108 // Platform apps may query for all services; other types of extensions are
109 // restricted to a whitelist.
110 if (!extension->is_platform_app() &&
111 !IsServiceTypeWhitelisted(filter_value))
112 continue;
114 new_service_types.insert(filter_value);
117 // Find all the added and removed service types since last update.
118 std::set<std::string> added_service_types =
119 base::STLSetDifference<std::set<std::string> >(
120 new_service_types, service_types_);
121 std::set<std::string> removed_service_types =
122 base::STLSetDifference<std::set<std::string> >(
123 service_types_, new_service_types);
125 // Update the registry.
126 DnsSdRegistry* registry = dns_sd_registry();
127 for (const auto& srv : added_service_types) {
128 registry->RegisterDnsSdListener(srv);
130 for (const auto& srv : removed_service_types) {
131 registry->UnregisterDnsSdListener(srv);
133 service_types_ = new_service_types;
136 void MDnsAPI::OnDnsSdEvent(const std::string& service_type,
137 const DnsSdRegistry::DnsSdServiceList& services) {
138 DCHECK(thread_checker_.CalledOnValidThread());
140 std::vector<linked_ptr<mdns::MDnsService> > args;
141 for (DnsSdRegistry::DnsSdServiceList::const_iterator it = services.begin();
142 it != services.end(); ++it) {
143 linked_ptr<mdns::MDnsService> mdns_service =
144 make_linked_ptr(new mdns::MDnsService);
145 mdns_service->service_name = (*it).service_name;
146 mdns_service->service_host_port = (*it).service_host_port;
147 mdns_service->ip_address = (*it).ip_address;
148 mdns_service->service_data = (*it).service_data;
149 args.push_back(mdns_service);
152 scoped_ptr<base::ListValue> results = mdns::OnServiceList::Create(args);
153 scoped_ptr<Event> event(
154 new Event(mdns::OnServiceList::kEventName, results.Pass()));
155 event->restrict_to_browser_context = browser_context_;
156 event->filter_info.SetServiceType(service_type);
158 // TODO(justinlin): To avoid having listeners without filters getting all
159 // events, modify API to have this event require filters.
160 // TODO(reddaly): If event isn't on whitelist, ensure it does not get
161 // broadcast to extensions.
162 extensions::EventRouter::Get(browser_context_)->BroadcastEvent(event.Pass());
165 } // namespace extensions