Coverage Report

Created: 2018-09-25 14:53

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