Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: chrome/browser/extensions/api/mdns/mdns_api.cc

Issue 1040773002: Limit number of service instances passed to onServiceList listeners. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Modify GetValidOnServiceListListeners logic Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "chrome/browser/extensions/api/mdns/mdns_api.h" 5 #include "chrome/browser/extensions/api/mdns/mdns_api.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "chrome/browser/extensions/extension_service.h" 10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/common/extensions/api/mdns.h" 11 #include "chrome/common/extensions/api/mdns.h"
12 #include "content/public/browser/render_process_host.h"
13 #include "content/public/browser/render_view_host.h"
14 #include "extensions/browser/extension_host.h"
12 #include "extensions/browser/extension_registry.h" 15 #include "extensions/browser/extension_registry.h"
16 #include "extensions/common/extension_messages.h"
13 17
14 namespace extensions { 18 namespace extensions {
15 19
16 namespace mdns = api::mdns; 20 namespace mdns = api::mdns;
17 21
18 namespace { 22 namespace {
19 23
20 // Whitelisted mDNS service types. 24 // Whitelisted mDNS service types.
21 const char kCastServiceType[] = "_googlecast._tcp.local"; 25 const char kCastServiceType[] = "_googlecast._tcp.local";
22 const char kPrivetServiceType[] = "_privet._tcp.local"; 26 const char kPrivetServiceType[] = "_privet._tcp.local";
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 UpdateMDnsListeners(details); 81 UpdateMDnsListeners(details);
78 } 82 }
79 83
80 void MDnsAPI::OnListenerRemoved(const EventListenerInfo& details) { 84 void MDnsAPI::OnListenerRemoved(const EventListenerInfo& details) {
81 DCHECK(thread_checker_.CalledOnValidThread()); 85 DCHECK(thread_checker_.CalledOnValidThread());
82 UpdateMDnsListeners(details); 86 UpdateMDnsListeners(details);
83 } 87 }
84 88
85 void MDnsAPI::UpdateMDnsListeners(const EventListenerInfo& details) { 89 void MDnsAPI::UpdateMDnsListeners(const EventListenerInfo& details) {
86 std::set<std::string> new_service_types; 90 std::set<std::string> new_service_types;
87 91 GetValidOnServiceListListeners("" /* sevice_type_filter */,
mark a. foltz 2015/04/07 22:43:32 What does an empty filter mean? Please document.
mark a. foltz 2015/04/07 22:43:32 service_type_filter
Red Daly 2015/04/07 23:16:56 Done.
Red Daly 2015/04/07 23:16:57 Done. Added explanation to inline comment; there
88 // Check all listeners for service type filters. 92 nullptr /* extension_ids */,
89 const EventListenerMap::ListenerList& listeners = 93 &new_service_types);
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());
96
97 std::string filter_value;
98 filter->GetStringASCII(kEventFilterServiceTypeKey, &filter_value);
99 if (filter_value.empty())
100 continue;
101
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;
107
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;
113
114 new_service_types.insert(filter_value);
115 }
116 94
117 // Find all the added and removed service types since last update. 95 // Find all the added and removed service types since last update.
118 std::set<std::string> added_service_types = 96 std::set<std::string> added_service_types =
119 base::STLSetDifference<std::set<std::string> >( 97 base::STLSetDifference<std::set<std::string> >(
120 new_service_types, service_types_); 98 new_service_types, service_types_);
121 std::set<std::string> removed_service_types = 99 std::set<std::string> removed_service_types =
122 base::STLSetDifference<std::set<std::string> >( 100 base::STLSetDifference<std::set<std::string> >(
123 service_types_, new_service_types); 101 service_types_, new_service_types);
124 102
125 // Update the registry. 103 // Update the registry.
126 DnsSdRegistry* registry = dns_sd_registry(); 104 DnsSdRegistry* registry = dns_sd_registry();
127 for (const auto& srv : added_service_types) { 105 for (const auto& srv : added_service_types) {
128 registry->RegisterDnsSdListener(srv); 106 registry->RegisterDnsSdListener(srv);
129 } 107 }
130 for (const auto& srv : removed_service_types) { 108 for (const auto& srv : removed_service_types) {
131 registry->UnregisterDnsSdListener(srv); 109 registry->UnregisterDnsSdListener(srv);
132 } 110 }
133 service_types_ = new_service_types; 111 service_types_ = new_service_types;
134 } 112 }
135 113
136 void MDnsAPI::OnDnsSdEvent(const std::string& service_type, 114 void MDnsAPI::OnDnsSdEvent(const std::string& service_type,
137 const DnsSdRegistry::DnsSdServiceList& services) { 115 const DnsSdRegistry::DnsSdServiceList& services) {
138 DCHECK(thread_checker_.CalledOnValidThread()); 116 DCHECK(thread_checker_.CalledOnValidThread());
139 117
140 std::vector<linked_ptr<mdns::MDnsService> > args; 118 std::vector<linked_ptr<mdns::MDnsService> > args;
141 for (DnsSdRegistry::DnsSdServiceList::const_iterator it = services.begin(); 119 for (DnsSdRegistry::DnsSdServiceList::const_iterator it = services.begin();
142 it != services.end(); ++it) { 120 it != services.end(); ++it) {
121 if (static_cast<long>(args.size()) ==
122 api::mdns::MAX_SERVICE_INSTANCES_PER_EVENT) {
123 // TODO(reddaly): This is not the most meaningful way of notifying the
124 // application that something bad happened. It will go to the user's
125 // console (which most users don't look at)and the developer will be none
126 // the wiser. Instead, changing the event to pass the number of
127 // discovered instances would allow the caller to know when the list is
128 // truncated and tell the user something meaningful in the extension/app.
129 WriteToConsole(service_type,
130 content::CONSOLE_MESSAGE_LEVEL_WARNING,
131 base::StringPrintf(
132 "Truncating number of service instances in "
133 "onServiceList to maximum allowed: %d",
134 api::mdns::MAX_SERVICE_INSTANCES_PER_EVENT));
135 break;
136 }
143 linked_ptr<mdns::MDnsService> mdns_service = 137 linked_ptr<mdns::MDnsService> mdns_service =
144 make_linked_ptr(new mdns::MDnsService); 138 make_linked_ptr(new mdns::MDnsService);
145 mdns_service->service_name = (*it).service_name; 139 mdns_service->service_name = (*it).service_name;
146 mdns_service->service_host_port = (*it).service_host_port; 140 mdns_service->service_host_port = (*it).service_host_port;
147 mdns_service->ip_address = (*it).ip_address; 141 mdns_service->ip_address = (*it).ip_address;
148 mdns_service->service_data = (*it).service_data; 142 mdns_service->service_data = (*it).service_data;
149 args.push_back(mdns_service); 143 args.push_back(mdns_service);
150 } 144 }
151 145
152 scoped_ptr<base::ListValue> results = mdns::OnServiceList::Create(args); 146 scoped_ptr<base::ListValue> results = mdns::OnServiceList::Create(args);
153 scoped_ptr<Event> event( 147 scoped_ptr<Event> event(
154 new Event(mdns::OnServiceList::kEventName, results.Pass())); 148 new Event(mdns::OnServiceList::kEventName, results.Pass()));
155 event->restrict_to_browser_context = browser_context_; 149 event->restrict_to_browser_context = browser_context_;
156 event->filter_info.SetServiceType(service_type); 150 event->filter_info.SetServiceType(service_type);
157 151
158 // TODO(justinlin): To avoid having listeners without filters getting all 152 // TODO(justinlin): To avoid having listeners without filters getting all
159 // events, modify API to have this event require filters. 153 // events, modify API to have this event require filters.
160 // TODO(reddaly): If event isn't on whitelist, ensure it does not get 154 // TODO(reddaly): If event isn't on whitelist, ensure it does not get
161 // broadcast to extensions. 155 // broadcast to extensions.
162 extensions::EventRouter::Get(browser_context_)->BroadcastEvent(event.Pass()); 156 extensions::EventRouter::Get(browser_context_)->BroadcastEvent(event.Pass());
163 } 157 }
164 158
159 void MDnsAPI::GetValidOnServiceListListeners(
160 const std::string& service_type_filter,
161 std::set<std::string>* extension_ids,
162 std::set<std::string>* service_types) {
163 for (const auto& listener :
164 extensions::EventRouter::Get(browser_context_)->listeners()
mark a. foltz 2015/04/07 22:43:33 This indentation looks funny, but might be right.
Red Daly 2015/04/07 23:16:56 Acknowledged - changed to 2 spaces for indentation
165 .GetEventListenersByName(mdns::OnServiceList::kEventName)) {
166 base::DictionaryValue* filter = (listener->filter());
mark a. foltz 2015/04/07 22:43:33 Extra ( )
Red Daly 2015/04/07 23:16:56 Done.
167
168 std::string service_type;
169 filter->GetStringASCII(kEventFilterServiceTypeKey, &service_type);
170 if (service_type.empty())
171 continue;
172
173 // Match service type when filter isn't ""
174 if (!service_type_filter.empty() && service_type_filter != service_type)
175 continue;
176
177 const Extension* extension = ExtensionRegistry::Get(browser_context_)->
178 enabled_extensions().GetByID(listener->extension_id());
179 // Don't listen for services associated only with disabled extensions.
180 if (!extension)
181 continue;
182
183 // Platform apps may query for all services; other types of extensions are
184 // restricted to a whitelist.
185 if (!extension->is_platform_app() &&
186 !IsServiceTypeWhitelisted(service_type))
187 continue;
188
189 if (extension_ids)
190 extension_ids->insert(listener->extension_id());
191 if (service_types)
192 service_types->insert(service_type);
193 }
194 }
195
196 void MDnsAPI::WriteToConsole(const std::string& service_type,
197 content::ConsoleMessageLevel level,
198 const std::string& message) {
199 // Get all the extensions with an onServiceList listener for a particular
200 // service type.
201 std::set<std::string> extension_ids;
202 GetValidOnServiceListListeners(service_type,
203 &extension_ids,
204 nullptr /* service_types */);
205
206 std::string logged_message(std::string("[chrome.mdns] ") + message);
207
208 // Log to the consoles of the background pages for those extensions.
209 for (const std::string& extension_id : extension_ids) {
210 extensions::ExtensionHost* host =
211 extensions::ProcessManager::Get(browser_context_)
212 ->GetBackgroundHostForExtension(extension_id);
213 if (!host)
214 continue;
215 content::RenderViewHost* rvh = host->render_view_host();
216 if (!rvh)
217 continue;
218 rvh->Send(new ExtensionMsg_AddMessageToConsole(
219 rvh->GetRoutingID(),
220 level,
221 logged_message));
222 }
223 }
224
165 } // namespace extensions 225 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/api/mdns/mdns_api.h ('k') | chrome/browser/extensions/api/mdns/mdns_api_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698