LCOV - code coverage report
Current view: top level - dom/presentation/provider - MulticastDNSDeviceProvider.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 530 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 82 0.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.13