Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "MulticastDNSDeviceProvider.h"
7 :
8 : #include "DeviceProviderHelpers.h"
9 : #include "MainThreadUtils.h"
10 : #include "mozilla/IntegerPrintfMacros.h"
11 : #include "mozilla/Logging.h"
12 : #include "mozilla/Preferences.h"
13 : #include "mozilla/Services.h"
14 : #include "mozilla/SizePrintfMacros.h"
15 : #include "mozilla/Unused.h"
16 : #include "nsComponentManagerUtils.h"
17 : #include "nsIObserverService.h"
18 : #include "nsIWritablePropertyBag2.h"
19 : #include "nsServiceManagerUtils.h"
20 : #include "nsTCPDeviceInfo.h"
21 : #include "nsThreadUtils.h"
22 :
23 : #ifdef MOZ_WIDGET_ANDROID
24 : #include "nsIPropertyBag2.h"
25 : #endif // MOZ_WIDGET_ANDROID
26 :
27 : #define PREF_PRESENTATION_DISCOVERY "dom.presentation.discovery.enabled"
28 : #define PREF_PRESENTATION_DISCOVERY_TIMEOUT_MS "dom.presentation.discovery.timeout_ms"
29 : #define PREF_PRESENTATION_DISCOVERABLE "dom.presentation.discoverable"
30 : #define PREF_PRESENTATION_DISCOVERABLE_ENCRYPTED "dom.presentation.discoverable.encrypted"
31 : #define PREF_PRESENTATION_DISCOVERABLE_RETRY_MS "dom.presentation.discoverable.retry_ms"
32 : #define PREF_PRESENTATION_DEVICE_NAME "dom.presentation.device.name"
33 :
34 : #define SERVICE_TYPE "_presentation-ctrl._tcp"
35 : #define PROTOCOL_VERSION_TAG "version"
36 : #define CERT_FINGERPRINT_TAG "certFingerprint"
37 :
38 : static mozilla::LazyLogModule sMulticastDNSProviderLogModule("MulticastDNSDeviceProvider");
39 :
40 : #undef LOG_I
41 : #define LOG_I(...) MOZ_LOG(sMulticastDNSProviderLogModule, mozilla::LogLevel::Debug, (__VA_ARGS__))
42 : #undef LOG_E
43 : #define LOG_E(...) MOZ_LOG(sMulticastDNSProviderLogModule, mozilla::LogLevel::Error, (__VA_ARGS__))
44 :
45 : namespace mozilla {
46 : namespace dom {
47 : namespace presentation {
48 :
49 : static const char* kObservedPrefs[] = {
50 : PREF_PRESENTATION_DISCOVERY,
51 : PREF_PRESENTATION_DISCOVERY_TIMEOUT_MS,
52 : PREF_PRESENTATION_DISCOVERABLE,
53 : PREF_PRESENTATION_DEVICE_NAME,
54 : nullptr
55 : };
56 :
57 : namespace {
58 :
59 : #ifdef MOZ_WIDGET_ANDROID
60 : static void
61 : GetAndroidDeviceName(nsACString& aRetVal)
62 : {
63 : nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
64 : MOZ_ASSERT(infoService, "Could not find a system info service");
65 :
66 : Unused << NS_WARN_IF(NS_FAILED(infoService->GetPropertyAsACString(
67 : NS_LITERAL_STRING("device"), aRetVal)));
68 : }
69 : #endif // MOZ_WIDGET_ANDROID
70 :
71 : } //anonymous namespace
72 :
73 : /**
74 : * This wrapper is used to break circular-reference problem.
75 : */
76 : class DNSServiceWrappedListener final
77 : : public nsIDNSServiceDiscoveryListener
78 : , public nsIDNSRegistrationListener
79 : , public nsIDNSServiceResolveListener
80 : , public nsIPresentationControlServerListener
81 : {
82 : public:
83 : NS_DECL_ISUPPORTS
84 0 : NS_FORWARD_SAFE_NSIDNSSERVICEDISCOVERYLISTENER(mListener)
85 0 : NS_FORWARD_SAFE_NSIDNSREGISTRATIONLISTENER(mListener)
86 0 : NS_FORWARD_SAFE_NSIDNSSERVICERESOLVELISTENER(mListener)
87 0 : NS_FORWARD_SAFE_NSIPRESENTATIONCONTROLSERVERLISTENER(mListener)
88 :
89 0 : explicit DNSServiceWrappedListener() = default;
90 :
91 0 : nsresult SetListener(MulticastDNSDeviceProvider* aListener)
92 : {
93 0 : mListener = aListener;
94 0 : return NS_OK;
95 : }
96 :
97 : private:
98 0 : virtual ~DNSServiceWrappedListener() = default;
99 :
100 : MulticastDNSDeviceProvider* mListener = nullptr;
101 : };
102 :
103 0 : NS_IMPL_ISUPPORTS(DNSServiceWrappedListener,
104 : nsIDNSServiceDiscoveryListener,
105 : nsIDNSRegistrationListener,
106 : nsIDNSServiceResolveListener,
107 : nsIPresentationControlServerListener)
108 :
109 0 : NS_IMPL_ISUPPORTS(MulticastDNSDeviceProvider,
110 : nsIPresentationDeviceProvider,
111 : nsIDNSServiceDiscoveryListener,
112 : nsIDNSRegistrationListener,
113 : nsIDNSServiceResolveListener,
114 : nsIPresentationControlServerListener,
115 : nsIObserver)
116 :
117 0 : MulticastDNSDeviceProvider::~MulticastDNSDeviceProvider()
118 : {
119 0 : Uninit();
120 0 : }
121 :
122 : nsresult
123 0 : MulticastDNSDeviceProvider::Init()
124 : {
125 0 : MOZ_ASSERT(NS_IsMainThread());
126 :
127 0 : if (mInitialized) {
128 0 : return NS_OK;
129 : }
130 :
131 : nsresult rv;
132 :
133 0 : mMulticastDNS = do_GetService(DNSSERVICEDISCOVERY_CONTRACT_ID, &rv);
134 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
135 0 : return rv;
136 : }
137 :
138 0 : mWrappedListener = new DNSServiceWrappedListener();
139 0 : if (NS_WARN_IF(NS_FAILED(rv = mWrappedListener->SetListener(this)))) {
140 0 : return rv;
141 : }
142 :
143 0 : mPresentationService = do_CreateInstance(PRESENTATION_CONTROL_SERVICE_CONTACT_ID, &rv);
144 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
145 0 : return rv;
146 : }
147 :
148 0 : mDiscoveryTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
149 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
150 0 : return rv;
151 : }
152 :
153 0 : mServerRetryTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
154 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
155 0 : return rv;
156 : }
157 0 : Preferences::AddStrongObservers(this, kObservedPrefs);
158 :
159 0 : mDiscoveryEnabled = Preferences::GetBool(PREF_PRESENTATION_DISCOVERY);
160 0 : mDiscoveryTimeoutMs = Preferences::GetUint(PREF_PRESENTATION_DISCOVERY_TIMEOUT_MS);
161 0 : mDiscoverable = Preferences::GetBool(PREF_PRESENTATION_DISCOVERABLE);
162 0 : mDiscoverableEncrypted = Preferences::GetBool(PREF_PRESENTATION_DISCOVERABLE_ENCRYPTED);
163 0 : mServerRetryMs = Preferences::GetUint(PREF_PRESENTATION_DISCOVERABLE_RETRY_MS);
164 0 : mServiceName = Preferences::GetCString(PREF_PRESENTATION_DEVICE_NAME);
165 :
166 : #ifdef MOZ_WIDGET_ANDROID
167 : // FIXME: Bug 1185806 - Provide a common device name setting.
168 : if (mServiceName.IsEmpty()) {
169 : GetAndroidDeviceName(mServiceName);
170 : Unused << Preferences::SetCString(PREF_PRESENTATION_DEVICE_NAME, mServiceName);
171 : }
172 : #endif // MOZ_WIDGET_ANDROID
173 :
174 0 : Unused << mPresentationService->SetId(mServiceName);
175 :
176 0 : if (mDiscoveryEnabled && NS_WARN_IF(NS_FAILED(rv = ForceDiscovery()))) {
177 0 : return rv;
178 : }
179 :
180 0 : if (mDiscoverable && NS_WARN_IF(NS_FAILED(rv = StartServer()))) {
181 0 : return rv;
182 : }
183 :
184 0 : mInitialized = true;
185 0 : return NS_OK;
186 : }
187 :
188 : nsresult
189 0 : MulticastDNSDeviceProvider::Uninit()
190 : {
191 0 : MOZ_ASSERT(NS_IsMainThread());
192 :
193 0 : if (!mInitialized) {
194 0 : return NS_OK;
195 : }
196 :
197 0 : ClearDevices();
198 :
199 0 : Preferences::RemoveObservers(this, kObservedPrefs);
200 :
201 0 : StopDiscovery(NS_OK);
202 0 : StopServer();
203 :
204 0 : mMulticastDNS = nullptr;
205 :
206 0 : if (mWrappedListener) {
207 0 : mWrappedListener->SetListener(nullptr);
208 0 : mWrappedListener = nullptr;
209 : }
210 :
211 0 : mInitialized = false;
212 0 : return NS_OK;
213 : }
214 :
215 : nsresult
216 0 : MulticastDNSDeviceProvider::StartServer()
217 : {
218 0 : LOG_I("StartServer: %s (%d)", mServiceName.get(), mDiscoverable);
219 0 : MOZ_ASSERT(NS_IsMainThread());
220 :
221 0 : if (!mDiscoverable) {
222 0 : return NS_OK;
223 : }
224 :
225 : nsresult rv;
226 :
227 : uint16_t servicePort;
228 0 : if (NS_WARN_IF(NS_FAILED(rv = mPresentationService->GetPort(&servicePort)))) {
229 0 : return rv;
230 : }
231 :
232 : /**
233 : * If |servicePort| is non-zero, it means PresentationControlService is running.
234 : * Otherwise, we should make it start serving.
235 : */
236 0 : if (servicePort) {
237 0 : return RegisterMDNSService();
238 : }
239 :
240 0 : if (NS_WARN_IF(NS_FAILED(rv = mPresentationService->SetListener(mWrappedListener)))) {
241 0 : return rv;
242 : }
243 :
244 0 : AbortServerRetry();
245 :
246 0 : if (NS_WARN_IF(NS_FAILED(rv = mPresentationService->StartServer(mDiscoverableEncrypted, 0)))) {
247 0 : return rv;
248 : }
249 :
250 0 : return NS_OK;
251 : }
252 :
253 : nsresult
254 0 : MulticastDNSDeviceProvider::StopServer()
255 : {
256 0 : LOG_I("StopServer: %s", mServiceName.get());
257 0 : MOZ_ASSERT(NS_IsMainThread());
258 :
259 0 : UnregisterMDNSService(NS_OK);
260 :
261 0 : AbortServerRetry();
262 :
263 0 : if (mPresentationService) {
264 0 : mPresentationService->SetListener(nullptr);
265 0 : mPresentationService->Close();
266 : }
267 :
268 0 : return NS_OK;
269 : }
270 :
271 : void
272 0 : MulticastDNSDeviceProvider::AbortServerRetry()
273 : {
274 0 : if (mIsServerRetrying) {
275 0 : mIsServerRetrying = false;
276 0 : mServerRetryTimer->Cancel();
277 : }
278 0 : }
279 :
280 : nsresult
281 0 : MulticastDNSDeviceProvider::RegisterMDNSService()
282 : {
283 0 : LOG_I("RegisterMDNSService: %s", mServiceName.get());
284 :
285 0 : if (!mDiscoverable) {
286 0 : return NS_OK;
287 : }
288 :
289 : // Cancel on going service registration.
290 0 : UnregisterMDNSService(NS_OK);
291 :
292 : nsresult rv;
293 :
294 : uint16_t servicePort;
295 0 : if (NS_FAILED(rv = mPresentationService->GetPort(&servicePort)) ||
296 0 : !servicePort) {
297 : // Abort service registration if server port is not available.
298 0 : return rv;
299 : }
300 :
301 : /**
302 : * Register the presentation control channel server as an mDNS service.
303 : */
304 : nsCOMPtr<nsIDNSServiceInfo> serviceInfo =
305 0 : do_CreateInstance(DNSSERVICEINFO_CONTRACT_ID, &rv);
306 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
307 0 : return rv;
308 : }
309 0 : if (NS_WARN_IF(NS_FAILED(rv = serviceInfo->SetServiceType(
310 : NS_LITERAL_CSTRING(SERVICE_TYPE))))) {
311 0 : return rv;
312 : }
313 0 : if (NS_WARN_IF(NS_FAILED(rv = serviceInfo->SetServiceName(mServiceName)))) {
314 0 : return rv;
315 : }
316 0 : if (NS_WARN_IF(NS_FAILED(rv = serviceInfo->SetPort(servicePort)))) {
317 0 : return rv;
318 : }
319 :
320 : nsCOMPtr<nsIWritablePropertyBag2> propBag =
321 0 : do_CreateInstance("@mozilla.org/hash-property-bag;1");
322 0 : MOZ_ASSERT(propBag);
323 :
324 : uint32_t version;
325 0 : rv = mPresentationService->GetVersion(&version);
326 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
327 :
328 0 : rv = propBag->SetPropertyAsUint32(NS_LITERAL_STRING(PROTOCOL_VERSION_TAG),
329 0 : version);
330 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
331 :
332 0 : if (mDiscoverableEncrypted) {
333 0 : nsAutoCString certFingerprint;
334 0 : rv = mPresentationService->GetCertFingerprint(certFingerprint);
335 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
336 :
337 0 : rv = propBag->SetPropertyAsACString(NS_LITERAL_STRING(CERT_FINGERPRINT_TAG),
338 0 : certFingerprint);
339 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
340 : }
341 :
342 0 : if (NS_WARN_IF(NS_FAILED(rv = serviceInfo->SetAttributes(propBag)))) {
343 0 : return rv;
344 : }
345 :
346 0 : return mMulticastDNS->RegisterService(serviceInfo,
347 : mWrappedListener,
348 0 : getter_AddRefs(mRegisterRequest));
349 : }
350 :
351 : nsresult
352 0 : MulticastDNSDeviceProvider::UnregisterMDNSService(nsresult aReason)
353 : {
354 0 : LOG_I("UnregisterMDNSService: %s (0x%08" PRIx32 ")", mServiceName.get(),
355 : static_cast<uint32_t>(aReason));
356 0 : MOZ_ASSERT(NS_IsMainThread());
357 :
358 0 : if (mRegisterRequest) {
359 0 : mRegisterRequest->Cancel(aReason);
360 0 : mRegisterRequest = nullptr;
361 : }
362 :
363 0 : return NS_OK;
364 : }
365 :
366 : nsresult
367 0 : MulticastDNSDeviceProvider::StopDiscovery(nsresult aReason)
368 : {
369 0 : LOG_I("StopDiscovery (0x%08" PRIx32 ")", static_cast<uint32_t>(aReason));
370 :
371 0 : MOZ_ASSERT(NS_IsMainThread());
372 0 : MOZ_ASSERT(mDiscoveryTimer);
373 :
374 0 : Unused << mDiscoveryTimer->Cancel();
375 :
376 0 : if (mDiscoveryRequest) {
377 0 : mDiscoveryRequest->Cancel(aReason);
378 0 : mDiscoveryRequest = nullptr;
379 : }
380 :
381 0 : return NS_OK;
382 : }
383 :
384 : nsresult
385 0 : MulticastDNSDeviceProvider::Connect(Device* aDevice,
386 : nsIPresentationControlChannel** aRetVal)
387 : {
388 0 : MOZ_ASSERT(aDevice);
389 0 : MOZ_ASSERT(mPresentationService);
390 :
391 0 : RefPtr<TCPDeviceInfo> deviceInfo = new TCPDeviceInfo(aDevice->Id(),
392 0 : aDevice->Address(),
393 0 : aDevice->Port(),
394 0 : aDevice->CertFingerprint());
395 :
396 0 : return mPresentationService->Connect(deviceInfo, aRetVal);
397 : }
398 :
399 : bool
400 0 : MulticastDNSDeviceProvider::IsCompatibleServer(nsIDNSServiceInfo* aServiceInfo)
401 : {
402 0 : MOZ_ASSERT(aServiceInfo);
403 :
404 0 : nsCOMPtr<nsIPropertyBag2> propBag;
405 0 : if (NS_WARN_IF(NS_FAILED(
406 0 : aServiceInfo->GetAttributes(getter_AddRefs(propBag)))) || !propBag) {
407 0 : return false;
408 : }
409 :
410 : uint32_t remoteVersion;
411 0 : if (NS_WARN_IF(NS_FAILED(
412 : propBag->GetPropertyAsUint32(NS_LITERAL_STRING(PROTOCOL_VERSION_TAG),
413 : &remoteVersion)))) {
414 0 : return false;
415 : }
416 :
417 0 : bool isCompatible = false;
418 0 : Unused << NS_WARN_IF(NS_FAILED(
419 : mPresentationService->IsCompatibleServer(remoteVersion,
420 : &isCompatible)));
421 :
422 0 : return isCompatible;
423 : }
424 :
425 : nsresult
426 0 : MulticastDNSDeviceProvider::AddDevice(const nsACString& aId,
427 : const nsACString& aServiceName,
428 : const nsACString& aServiceType,
429 : const nsACString& aAddress,
430 : const uint16_t aPort,
431 : const nsACString& aCertFingerprint)
432 : {
433 0 : MOZ_ASSERT(NS_IsMainThread());
434 0 : MOZ_ASSERT(mPresentationService);
435 :
436 : RefPtr<Device> device = new Device(aId, /* ID */
437 : aServiceName,
438 : aServiceType,
439 : aAddress,
440 : aPort,
441 : aCertFingerprint,
442 : DeviceState::eActive,
443 0 : this);
444 :
445 0 : nsCOMPtr<nsIPresentationDeviceListener> listener;
446 0 : if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
447 0 : Unused << listener->AddDevice(device);
448 : }
449 :
450 0 : mDevices.AppendElement(device);
451 :
452 0 : return NS_OK;
453 : }
454 :
455 : nsresult
456 0 : MulticastDNSDeviceProvider::UpdateDevice(const uint32_t aIndex,
457 : const nsACString& aServiceName,
458 : const nsACString& aServiceType,
459 : const nsACString& aAddress,
460 : const uint16_t aPort,
461 : const nsACString& aCertFingerprint)
462 : {
463 0 : MOZ_ASSERT(NS_IsMainThread());
464 0 : MOZ_ASSERT(mPresentationService);
465 :
466 0 : if (NS_WARN_IF(aIndex >= mDevices.Length())) {
467 0 : return NS_ERROR_INVALID_ARG;
468 : }
469 :
470 0 : RefPtr<Device> device = mDevices[aIndex];
471 0 : device->Update(aServiceName, aServiceType, aAddress, aPort, aCertFingerprint);
472 0 : device->ChangeState(DeviceState::eActive);
473 :
474 0 : nsCOMPtr<nsIPresentationDeviceListener> listener;
475 0 : if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
476 0 : Unused << listener->UpdateDevice(device);
477 : }
478 :
479 0 : return NS_OK;
480 : }
481 :
482 : nsresult
483 0 : MulticastDNSDeviceProvider::RemoveDevice(const uint32_t aIndex)
484 : {
485 0 : MOZ_ASSERT(NS_IsMainThread());
486 0 : MOZ_ASSERT(mPresentationService);
487 :
488 0 : if (NS_WARN_IF(aIndex >= mDevices.Length())) {
489 0 : return NS_ERROR_INVALID_ARG;
490 : }
491 :
492 0 : RefPtr<Device> device = mDevices[aIndex];
493 :
494 0 : LOG_I("RemoveDevice: %s", device->Id().get());
495 0 : mDevices.RemoveElementAt(aIndex);
496 :
497 0 : nsCOMPtr<nsIPresentationDeviceListener> listener;
498 0 : if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
499 0 : Unused << listener->RemoveDevice(device);
500 : }
501 :
502 0 : return NS_OK;
503 : }
504 :
505 : bool
506 0 : MulticastDNSDeviceProvider::FindDeviceById(const nsACString& aId,
507 : uint32_t& aIndex)
508 : {
509 0 : MOZ_ASSERT(NS_IsMainThread());
510 :
511 : RefPtr<Device> device = new Device(aId,
512 0 : /* aName = */ EmptyCString(),
513 0 : /* aType = */ EmptyCString(),
514 0 : /* aHost = */ EmptyCString(),
515 : /* aPort = */ 0,
516 0 : /* aCertFingerprint */ EmptyCString(),
517 : /* aState = */ DeviceState::eUnknown,
518 0 : /* aProvider = */ nullptr);
519 0 : size_t index = mDevices.IndexOf(device, 0, DeviceIdComparator());
520 :
521 0 : if (index == mDevices.NoIndex) {
522 0 : return false;
523 : }
524 :
525 0 : aIndex = index;
526 0 : return true;
527 : }
528 :
529 : bool
530 0 : MulticastDNSDeviceProvider::FindDeviceByAddress(const nsACString& aAddress,
531 : uint32_t& aIndex)
532 : {
533 0 : MOZ_ASSERT(NS_IsMainThread());
534 :
535 0 : RefPtr<Device> device = new Device(/* aId = */ EmptyCString(),
536 0 : /* aName = */ EmptyCString(),
537 0 : /* aType = */ EmptyCString(),
538 : aAddress,
539 : /* aPort = */ 0,
540 0 : /* aCertFingerprint */ EmptyCString(),
541 : /* aState = */ DeviceState::eUnknown,
542 0 : /* aProvider = */ nullptr);
543 0 : size_t index = mDevices.IndexOf(device, 0, DeviceAddressComparator());
544 :
545 0 : if (index == mDevices.NoIndex) {
546 0 : return false;
547 : }
548 :
549 0 : aIndex = index;
550 0 : return true;
551 : }
552 :
553 : void
554 0 : MulticastDNSDeviceProvider::MarkAllDevicesUnknown()
555 : {
556 0 : MOZ_ASSERT(NS_IsMainThread());
557 :
558 0 : for (auto& device : mDevices) {
559 0 : device->ChangeState(DeviceState::eUnknown);
560 : }
561 0 : }
562 :
563 : void
564 0 : MulticastDNSDeviceProvider::ClearUnknownDevices()
565 : {
566 0 : MOZ_ASSERT(NS_IsMainThread());
567 :
568 0 : size_t i = mDevices.Length();
569 0 : while (i > 0) {
570 0 : --i;
571 0 : if (mDevices[i]->State() == DeviceState::eUnknown) {
572 0 : Unused << NS_WARN_IF(NS_FAILED(RemoveDevice(i)));
573 : }
574 : }
575 0 : }
576 :
577 : void
578 0 : MulticastDNSDeviceProvider::ClearDevices()
579 : {
580 0 : MOZ_ASSERT(NS_IsMainThread());
581 :
582 0 : size_t i = mDevices.Length();
583 0 : while (i > 0) {
584 0 : --i;
585 0 : Unused << NS_WARN_IF(NS_FAILED(RemoveDevice(i)));
586 : }
587 0 : }
588 :
589 : // nsIPresentationDeviceProvider
590 : NS_IMETHODIMP
591 0 : MulticastDNSDeviceProvider::GetListener(nsIPresentationDeviceListener** aListener)
592 : {
593 0 : MOZ_ASSERT(NS_IsMainThread());
594 :
595 0 : if (NS_WARN_IF(!aListener)) {
596 0 : return NS_ERROR_INVALID_POINTER;
597 : }
598 :
599 : nsresult rv;
600 : nsCOMPtr<nsIPresentationDeviceListener> listener =
601 0 : do_QueryReferent(mDeviceListener, &rv);
602 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
603 0 : return rv;
604 : }
605 :
606 0 : listener.forget(aListener);
607 :
608 0 : return NS_OK;
609 : }
610 :
611 : NS_IMETHODIMP
612 0 : MulticastDNSDeviceProvider::SetListener(nsIPresentationDeviceListener* aListener)
613 : {
614 0 : MOZ_ASSERT(NS_IsMainThread());
615 :
616 0 : mDeviceListener = do_GetWeakReference(aListener);
617 :
618 : nsresult rv;
619 0 : if (mDeviceListener) {
620 0 : if (NS_WARN_IF(NS_FAILED(rv = Init()))) {
621 0 : return rv;
622 : }
623 : } else {
624 0 : if (NS_WARN_IF(NS_FAILED(rv = Uninit()))) {
625 0 : return rv;
626 : }
627 : }
628 :
629 0 : return NS_OK;
630 : }
631 :
632 : NS_IMETHODIMP
633 0 : MulticastDNSDeviceProvider::ForceDiscovery()
634 : {
635 0 : LOG_I("ForceDiscovery (%d)", mDiscoveryEnabled);
636 0 : MOZ_ASSERT(NS_IsMainThread());
637 :
638 0 : if (!mDiscoveryEnabled) {
639 0 : return NS_OK;
640 : }
641 :
642 0 : MOZ_ASSERT(mDiscoveryTimer);
643 0 : MOZ_ASSERT(mMulticastDNS);
644 :
645 : // if it's already discovering, extend existing discovery timeout.
646 : nsresult rv;
647 0 : if (mIsDiscovering) {
648 0 : Unused << mDiscoveryTimer->Cancel();
649 :
650 0 : if (NS_WARN_IF(NS_FAILED( rv = mDiscoveryTimer->Init(this,
651 : mDiscoveryTimeoutMs,
652 : nsITimer::TYPE_ONE_SHOT)))) {
653 0 : return rv;
654 : }
655 0 : return NS_OK;
656 : }
657 :
658 0 : StopDiscovery(NS_OK);
659 :
660 0 : if (NS_WARN_IF(NS_FAILED(rv = mMulticastDNS->StartDiscovery(
661 : NS_LITERAL_CSTRING(SERVICE_TYPE),
662 : mWrappedListener,
663 : getter_AddRefs(mDiscoveryRequest))))) {
664 0 : return rv;
665 : }
666 :
667 0 : return NS_OK;
668 : }
669 :
670 : // nsIDNSServiceDiscoveryListener
671 : NS_IMETHODIMP
672 0 : MulticastDNSDeviceProvider::OnDiscoveryStarted(const nsACString& aServiceType)
673 : {
674 0 : LOG_I("OnDiscoveryStarted");
675 0 : MOZ_ASSERT(NS_IsMainThread());
676 0 : MOZ_ASSERT(mDiscoveryTimer);
677 :
678 0 : MarkAllDevicesUnknown();
679 :
680 : nsresult rv;
681 0 : if (NS_WARN_IF(NS_FAILED(rv = mDiscoveryTimer->Init(this,
682 : mDiscoveryTimeoutMs,
683 : nsITimer::TYPE_ONE_SHOT)))) {
684 0 : return rv;
685 : }
686 :
687 0 : mIsDiscovering = true;
688 :
689 0 : return NS_OK;
690 : }
691 :
692 : NS_IMETHODIMP
693 0 : MulticastDNSDeviceProvider::OnDiscoveryStopped(const nsACString& aServiceType)
694 : {
695 0 : LOG_I("OnDiscoveryStopped");
696 0 : MOZ_ASSERT(NS_IsMainThread());
697 :
698 0 : ClearUnknownDevices();
699 :
700 0 : mIsDiscovering = false;
701 :
702 0 : return NS_OK;
703 : }
704 :
705 : NS_IMETHODIMP
706 0 : MulticastDNSDeviceProvider::OnServiceFound(nsIDNSServiceInfo* aServiceInfo)
707 : {
708 0 : MOZ_ASSERT(NS_IsMainThread());
709 :
710 0 : if (NS_WARN_IF(!aServiceInfo)) {
711 0 : return NS_ERROR_INVALID_ARG;
712 : }
713 :
714 : nsresult rv ;
715 :
716 0 : nsAutoCString serviceName;
717 0 : if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(serviceName)))) {
718 0 : return rv;
719 : }
720 :
721 0 : LOG_I("OnServiceFound: %s", serviceName.get());
722 :
723 0 : if (mMulticastDNS) {
724 0 : if (NS_WARN_IF(NS_FAILED(rv = mMulticastDNS->ResolveService(
725 : aServiceInfo, mWrappedListener)))) {
726 0 : return rv;
727 : }
728 : }
729 :
730 0 : return NS_OK;
731 : }
732 :
733 : NS_IMETHODIMP
734 0 : MulticastDNSDeviceProvider::OnServiceLost(nsIDNSServiceInfo* aServiceInfo)
735 : {
736 0 : MOZ_ASSERT(NS_IsMainThread());
737 :
738 0 : if (NS_WARN_IF(!aServiceInfo)) {
739 0 : return NS_ERROR_INVALID_ARG;
740 : }
741 :
742 : nsresult rv;
743 :
744 0 : nsAutoCString serviceName;
745 0 : if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(serviceName)))) {
746 0 : return rv;
747 : }
748 :
749 0 : LOG_I("OnServiceLost: %s", serviceName.get());
750 :
751 0 : nsAutoCString host;
752 0 : if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetHost(host)))) {
753 0 : return rv;
754 : }
755 :
756 : uint32_t index;
757 0 : if (!FindDeviceById(host, index)) {
758 : // given device was not found
759 0 : return NS_OK;
760 : }
761 :
762 0 : if (NS_WARN_IF(NS_FAILED(rv = RemoveDevice(index)))) {
763 0 : return rv;
764 : }
765 :
766 0 : return NS_OK;
767 : }
768 :
769 : NS_IMETHODIMP
770 0 : MulticastDNSDeviceProvider::OnStartDiscoveryFailed(const nsACString& aServiceType,
771 : int32_t aErrorCode)
772 : {
773 0 : LOG_E("OnStartDiscoveryFailed: %d", aErrorCode);
774 0 : MOZ_ASSERT(NS_IsMainThread());
775 :
776 0 : return NS_OK;
777 : }
778 :
779 : NS_IMETHODIMP
780 0 : MulticastDNSDeviceProvider::OnStopDiscoveryFailed(const nsACString& aServiceType,
781 : int32_t aErrorCode)
782 : {
783 0 : LOG_E("OnStopDiscoveryFailed: %d", aErrorCode);
784 0 : MOZ_ASSERT(NS_IsMainThread());
785 :
786 0 : return NS_OK;
787 : }
788 :
789 : // nsIDNSRegistrationListener
790 : NS_IMETHODIMP
791 0 : MulticastDNSDeviceProvider::OnServiceRegistered(nsIDNSServiceInfo* aServiceInfo)
792 : {
793 0 : MOZ_ASSERT(NS_IsMainThread());
794 :
795 0 : if (NS_WARN_IF(!aServiceInfo)) {
796 0 : return NS_ERROR_INVALID_ARG;
797 : }
798 : nsresult rv;
799 :
800 0 : nsAutoCString name;
801 0 : if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(name)))) {
802 0 : return rv;
803 : }
804 :
805 0 : LOG_I("OnServiceRegistered (%s)", name.get());
806 0 : mRegisteredName = name;
807 :
808 0 : if (mMulticastDNS) {
809 0 : if (NS_WARN_IF(NS_FAILED(rv = mMulticastDNS->ResolveService(
810 : aServiceInfo, mWrappedListener)))) {
811 0 : return rv;
812 : }
813 : }
814 :
815 0 : return NS_OK;
816 : }
817 :
818 : NS_IMETHODIMP
819 0 : MulticastDNSDeviceProvider::OnServiceUnregistered(nsIDNSServiceInfo* aServiceInfo)
820 : {
821 0 : LOG_I("OnServiceUnregistered");
822 0 : MOZ_ASSERT(NS_IsMainThread());
823 :
824 0 : return NS_OK;
825 : }
826 :
827 : NS_IMETHODIMP
828 0 : MulticastDNSDeviceProvider::OnRegistrationFailed(nsIDNSServiceInfo* aServiceInfo,
829 : int32_t aErrorCode)
830 : {
831 0 : LOG_E("OnRegistrationFailed: %d", aErrorCode);
832 0 : MOZ_ASSERT(NS_IsMainThread());
833 :
834 0 : mRegisterRequest = nullptr;
835 :
836 0 : if (aErrorCode == nsIDNSRegistrationListener::ERROR_SERVICE_NOT_RUNNING) {
837 0 : return NS_DispatchToMainThread(NewRunnableMethod(
838 : "dom::presentation::MulticastDNSDeviceProvider::RegisterMDNSService",
839 : this,
840 0 : &MulticastDNSDeviceProvider::RegisterMDNSService));
841 : }
842 :
843 0 : return NS_OK;
844 : }
845 :
846 : NS_IMETHODIMP
847 0 : MulticastDNSDeviceProvider::OnUnregistrationFailed(nsIDNSServiceInfo* aServiceInfo,
848 : int32_t aErrorCode)
849 : {
850 0 : LOG_E("OnUnregistrationFailed: %d", aErrorCode);
851 0 : MOZ_ASSERT(NS_IsMainThread());
852 :
853 0 : return NS_OK;
854 : }
855 :
856 : // nsIDNSServiceResolveListener
857 : NS_IMETHODIMP
858 0 : MulticastDNSDeviceProvider::OnServiceResolved(nsIDNSServiceInfo* aServiceInfo)
859 : {
860 0 : MOZ_ASSERT(NS_IsMainThread());
861 :
862 0 : if (NS_WARN_IF(!aServiceInfo)) {
863 0 : return NS_ERROR_INVALID_ARG;
864 : }
865 :
866 : nsresult rv;
867 :
868 0 : nsAutoCString serviceName;
869 0 : if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(serviceName)))) {
870 0 : return rv;
871 : }
872 :
873 0 : LOG_I("OnServiceResolved: %s", serviceName.get());
874 :
875 0 : nsAutoCString host;
876 0 : if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetHost(host)))) {
877 0 : return rv;
878 : }
879 :
880 0 : if (mRegisteredName == serviceName) {
881 0 : LOG_I("ignore self");
882 :
883 0 : if (NS_WARN_IF(NS_FAILED(rv = mPresentationService->SetId(host)))) {
884 0 : return rv;
885 : }
886 :
887 0 : return NS_OK;
888 : }
889 :
890 0 : if (!IsCompatibleServer(aServiceInfo)) {
891 0 : LOG_I("ignore incompatible service: %s", serviceName.get());
892 0 : return NS_OK;
893 : }
894 :
895 0 : nsAutoCString address;
896 0 : if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetAddress(address)))) {
897 0 : return rv;
898 : }
899 :
900 : uint16_t port;
901 0 : if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetPort(&port)))) {
902 0 : return rv;
903 : }
904 :
905 0 : nsAutoCString serviceType;
906 0 : if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceType(serviceType)))) {
907 0 : return rv;
908 : }
909 :
910 0 : nsCOMPtr<nsIPropertyBag2> propBag;
911 0 : if (NS_WARN_IF(NS_FAILED(
912 0 : aServiceInfo->GetAttributes(getter_AddRefs(propBag)))) || !propBag) {
913 0 : return rv;
914 : }
915 :
916 0 : nsAutoCString certFingerprint;
917 0 : Unused << propBag->GetPropertyAsACString(NS_LITERAL_STRING(CERT_FINGERPRINT_TAG),
918 0 : certFingerprint);
919 :
920 : uint32_t index;
921 0 : if (FindDeviceById(host, index)) {
922 0 : return UpdateDevice(index,
923 : serviceName,
924 : serviceType,
925 : address,
926 : port,
927 0 : certFingerprint);
928 : } else {
929 0 : return AddDevice(host,
930 : serviceName,
931 : serviceType,
932 : address,
933 : port,
934 0 : certFingerprint);
935 : }
936 :
937 : return NS_OK;
938 : }
939 :
940 : NS_IMETHODIMP
941 0 : MulticastDNSDeviceProvider::OnResolveFailed(nsIDNSServiceInfo* aServiceInfo,
942 : int32_t aErrorCode)
943 : {
944 0 : LOG_E("OnResolveFailed: %d", aErrorCode);
945 0 : MOZ_ASSERT(NS_IsMainThread());
946 :
947 0 : return NS_OK;
948 : }
949 :
950 : // nsIPresentationControlServerListener
951 : NS_IMETHODIMP
952 0 : MulticastDNSDeviceProvider::OnServerReady(uint16_t aPort,
953 : const nsACString& aCertFingerprint)
954 : {
955 0 : LOG_I("OnServerReady: %d, %s", aPort, PromiseFlatCString(aCertFingerprint).get());
956 0 : MOZ_ASSERT(NS_IsMainThread());
957 :
958 0 : if (mDiscoverable) {
959 0 : RegisterMDNSService();
960 : }
961 :
962 0 : return NS_OK;
963 : }
964 :
965 : NS_IMETHODIMP
966 0 : MulticastDNSDeviceProvider::OnServerStopped(nsresult aResult)
967 : {
968 0 : LOG_I("OnServerStopped: (0x%08" PRIx32 ")", static_cast<uint32_t>(aResult));
969 :
970 0 : UnregisterMDNSService(aResult);
971 :
972 : // Try restart server if it is stopped abnormally.
973 0 : if (NS_FAILED(aResult) && mDiscoverable) {
974 0 : mIsServerRetrying = true;
975 0 : mServerRetryTimer->Init(this, mServerRetryMs, nsITimer::TYPE_ONE_SHOT);
976 : }
977 :
978 0 : return NS_OK;
979 : }
980 :
981 : // Create a new device if we were unable to find one with the address.
982 : already_AddRefed<MulticastDNSDeviceProvider::Device>
983 0 : MulticastDNSDeviceProvider::GetOrCreateDevice(nsITCPDeviceInfo* aDeviceInfo)
984 : {
985 0 : nsAutoCString address;
986 0 : Unused << aDeviceInfo->GetAddress(address);
987 :
988 0 : RefPtr<Device> device;
989 : uint32_t index;
990 0 : if (FindDeviceByAddress(address, index)) {
991 0 : device = mDevices[index];
992 : } else {
993 : // Create a one-time device object for non-discoverable controller.
994 : // This device will not be in the list of available devices and cannot
995 : // be used for requesting session.
996 0 : nsAutoCString id;
997 0 : Unused << aDeviceInfo->GetId(id);
998 : uint16_t port;
999 0 : Unused << aDeviceInfo->GetPort(&port);
1000 :
1001 : device = new Device(id,
1002 : /* aName = */ id,
1003 0 : /* aType = */ EmptyCString(),
1004 : address,
1005 : port,
1006 0 : /* aCertFingerprint */ EmptyCString(),
1007 : DeviceState::eActive,
1008 0 : /* aProvider = */ nullptr);
1009 : }
1010 :
1011 0 : return device.forget();
1012 : }
1013 :
1014 : NS_IMETHODIMP
1015 0 : MulticastDNSDeviceProvider::OnSessionRequest(nsITCPDeviceInfo* aDeviceInfo,
1016 : const nsAString& aUrl,
1017 : const nsAString& aPresentationId,
1018 : nsIPresentationControlChannel* aControlChannel)
1019 : {
1020 0 : MOZ_ASSERT(NS_IsMainThread());
1021 :
1022 0 : nsAutoCString address;
1023 0 : Unused << aDeviceInfo->GetAddress(address);
1024 :
1025 0 : LOG_I("OnSessionRequest: %s", address.get());
1026 :
1027 0 : RefPtr<Device> device = GetOrCreateDevice(aDeviceInfo);
1028 0 : nsCOMPtr<nsIPresentationDeviceListener> listener;
1029 0 : if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
1030 0 : Unused << listener->OnSessionRequest(device, aUrl, aPresentationId,
1031 0 : aControlChannel);
1032 : }
1033 :
1034 0 : return NS_OK;
1035 : }
1036 :
1037 : NS_IMETHODIMP
1038 0 : MulticastDNSDeviceProvider::OnTerminateRequest(nsITCPDeviceInfo* aDeviceInfo,
1039 : const nsAString& aPresentationId,
1040 : nsIPresentationControlChannel* aControlChannel,
1041 : bool aIsFromReceiver)
1042 : {
1043 0 : MOZ_ASSERT(NS_IsMainThread());
1044 :
1045 0 : nsAutoCString address;
1046 0 : Unused << aDeviceInfo->GetAddress(address);
1047 :
1048 0 : LOG_I("OnTerminateRequest: %s", address.get());
1049 :
1050 0 : RefPtr<Device> device = GetOrCreateDevice(aDeviceInfo);
1051 0 : nsCOMPtr<nsIPresentationDeviceListener> listener;
1052 0 : if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
1053 0 : Unused << listener->OnTerminateRequest(device, aPresentationId,
1054 0 : aControlChannel, aIsFromReceiver);
1055 : }
1056 :
1057 0 : return NS_OK;
1058 : }
1059 :
1060 : NS_IMETHODIMP
1061 0 : MulticastDNSDeviceProvider::OnReconnectRequest(nsITCPDeviceInfo* aDeviceInfo,
1062 : const nsAString& aUrl,
1063 : const nsAString& aPresentationId,
1064 : nsIPresentationControlChannel* aControlChannel)
1065 : {
1066 0 : MOZ_ASSERT(NS_IsMainThread());
1067 :
1068 0 : nsAutoCString address;
1069 0 : Unused << aDeviceInfo->GetAddress(address);
1070 :
1071 0 : LOG_I("OnReconnectRequest: %s", address.get());
1072 :
1073 0 : RefPtr<Device> device = GetOrCreateDevice(aDeviceInfo);
1074 0 : nsCOMPtr<nsIPresentationDeviceListener> listener;
1075 0 : if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
1076 0 : Unused << listener->OnReconnectRequest(device, aUrl, aPresentationId,
1077 0 : aControlChannel);
1078 : }
1079 :
1080 0 : return NS_OK;
1081 : }
1082 :
1083 : // nsIObserver
1084 : NS_IMETHODIMP
1085 0 : MulticastDNSDeviceProvider::Observe(nsISupports* aSubject,
1086 : const char* aTopic,
1087 : const char16_t* aData)
1088 : {
1089 0 : MOZ_ASSERT(NS_IsMainThread());
1090 :
1091 0 : NS_ConvertUTF16toUTF8 data(aData);
1092 0 : LOG_I("Observe: topic = %s, data = %s", aTopic, data.get());
1093 :
1094 0 : if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
1095 0 : if (data.EqualsLiteral(PREF_PRESENTATION_DISCOVERY)) {
1096 0 : OnDiscoveryChanged(Preferences::GetBool(PREF_PRESENTATION_DISCOVERY));
1097 0 : } else if (data.EqualsLiteral(PREF_PRESENTATION_DISCOVERY_TIMEOUT_MS)) {
1098 0 : OnDiscoveryTimeoutChanged(Preferences::GetUint(PREF_PRESENTATION_DISCOVERY_TIMEOUT_MS));
1099 0 : } else if (data.EqualsLiteral(PREF_PRESENTATION_DISCOVERABLE)) {
1100 0 : OnDiscoverableChanged(Preferences::GetBool(PREF_PRESENTATION_DISCOVERABLE));
1101 0 : } else if (data.EqualsLiteral(PREF_PRESENTATION_DEVICE_NAME)) {
1102 0 : nsAdoptingCString newServiceName = Preferences::GetCString(PREF_PRESENTATION_DEVICE_NAME);
1103 0 : if (!mServiceName.Equals(newServiceName)) {
1104 0 : OnServiceNameChanged(newServiceName);
1105 : }
1106 : }
1107 0 : } else if (!strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC)) {
1108 0 : nsCOMPtr<nsITimer> timer = do_QueryInterface(aSubject);
1109 0 : if (!timer) {
1110 0 : return NS_ERROR_UNEXPECTED;
1111 : }
1112 :
1113 0 : if (timer == mDiscoveryTimer) {
1114 0 : StopDiscovery(NS_OK);
1115 0 : } else if (timer == mServerRetryTimer) {
1116 0 : mIsServerRetrying = false;
1117 0 : StartServer();
1118 : }
1119 : }
1120 :
1121 0 : return NS_OK;
1122 : }
1123 :
1124 : nsresult
1125 0 : MulticastDNSDeviceProvider::OnDiscoveryChanged(bool aEnabled)
1126 : {
1127 0 : LOG_I("DiscoveryEnabled = %d\n", aEnabled);
1128 0 : MOZ_ASSERT(NS_IsMainThread());
1129 :
1130 0 : mDiscoveryEnabled = aEnabled;
1131 :
1132 0 : if (mDiscoveryEnabled) {
1133 0 : return ForceDiscovery();
1134 : }
1135 :
1136 0 : return StopDiscovery(NS_OK);
1137 : }
1138 :
1139 : nsresult
1140 0 : MulticastDNSDeviceProvider::OnDiscoveryTimeoutChanged(uint32_t aTimeoutMs)
1141 : {
1142 0 : LOG_I("OnDiscoveryTimeoutChanged = %d\n", aTimeoutMs);
1143 0 : MOZ_ASSERT(NS_IsMainThread());
1144 :
1145 0 : mDiscoveryTimeoutMs = aTimeoutMs;
1146 :
1147 0 : return NS_OK;
1148 : }
1149 :
1150 : nsresult
1151 0 : MulticastDNSDeviceProvider::OnDiscoverableChanged(bool aEnabled)
1152 : {
1153 0 : LOG_I("Discoverable = %d\n", aEnabled);
1154 0 : MOZ_ASSERT(NS_IsMainThread());
1155 :
1156 0 : mDiscoverable = aEnabled;
1157 :
1158 0 : if (mDiscoverable) {
1159 0 : return StartServer();
1160 : }
1161 :
1162 0 : return StopServer();
1163 : }
1164 :
1165 : nsresult
1166 0 : MulticastDNSDeviceProvider::OnServiceNameChanged(const nsACString& aServiceName)
1167 : {
1168 0 : LOG_I("serviceName = %s\n", PromiseFlatCString(aServiceName).get());
1169 0 : MOZ_ASSERT(NS_IsMainThread());
1170 :
1171 0 : mServiceName = aServiceName;
1172 :
1173 : nsresult rv;
1174 0 : if (NS_WARN_IF(NS_FAILED(rv = UnregisterMDNSService(NS_OK)))) {
1175 0 : return rv;
1176 : }
1177 :
1178 0 : if (mDiscoverable) {
1179 0 : return RegisterMDNSService();
1180 : }
1181 :
1182 0 : return NS_OK;
1183 : }
1184 :
1185 : // MulticastDNSDeviceProvider::Device
1186 0 : NS_IMPL_ISUPPORTS(MulticastDNSDeviceProvider::Device,
1187 : nsIPresentationDevice)
1188 :
1189 : // nsIPresentationDevice
1190 : NS_IMETHODIMP
1191 0 : MulticastDNSDeviceProvider::Device::GetId(nsACString& aId)
1192 : {
1193 0 : aId = mId;
1194 :
1195 0 : return NS_OK;
1196 : }
1197 :
1198 : NS_IMETHODIMP
1199 0 : MulticastDNSDeviceProvider::Device::GetName(nsACString& aName)
1200 : {
1201 0 : aName = mName;
1202 :
1203 0 : return NS_OK;
1204 : }
1205 :
1206 : NS_IMETHODIMP
1207 0 : MulticastDNSDeviceProvider::Device::GetType(nsACString& aType)
1208 : {
1209 0 : aType = mType;
1210 :
1211 0 : return NS_OK;
1212 : }
1213 :
1214 : NS_IMETHODIMP
1215 0 : MulticastDNSDeviceProvider::Device::EstablishControlChannel(
1216 : nsIPresentationControlChannel** aRetVal)
1217 : {
1218 0 : if (!mProvider) {
1219 0 : return NS_ERROR_FAILURE;
1220 : }
1221 :
1222 0 : return mProvider->Connect(this, aRetVal);
1223 : }
1224 :
1225 : NS_IMETHODIMP
1226 0 : MulticastDNSDeviceProvider::Device::Disconnect()
1227 : {
1228 : // No need to do anything when disconnect.
1229 0 : return NS_OK;
1230 : }
1231 :
1232 : NS_IMETHODIMP
1233 0 : MulticastDNSDeviceProvider::Device::IsRequestedUrlSupported(
1234 : const nsAString& aRequestedUrl,
1235 : bool* aRetVal)
1236 : {
1237 0 : MOZ_ASSERT(NS_IsMainThread());
1238 :
1239 0 : if (!aRetVal) {
1240 0 : return NS_ERROR_INVALID_POINTER;
1241 : }
1242 :
1243 : // TV 2.6 also supports presentation Apps and HTTP/HTTPS hosted receiver page.
1244 0 : if (DeviceProviderHelpers::IsFxTVSupportedAppUrl(aRequestedUrl) ||
1245 0 : DeviceProviderHelpers::IsCommonlySupportedScheme(aRequestedUrl)) {
1246 0 : *aRetVal = true;
1247 : }
1248 :
1249 0 : return NS_OK;
1250 : }
1251 :
1252 : } // namespace presentation
1253 : } // namespace dom
1254 : } // namespace mozilla
|