diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /dom/presentation/PresentationDeviceManager.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | uxp-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz |
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/presentation/PresentationDeviceManager.cpp')
-rw-r--r-- | dom/presentation/PresentationDeviceManager.cpp | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/dom/presentation/PresentationDeviceManager.cpp b/dom/presentation/PresentationDeviceManager.cpp new file mode 100644 index 0000000000..7e5a4700c8 --- /dev/null +++ b/dom/presentation/PresentationDeviceManager.cpp @@ -0,0 +1,336 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "PresentationDeviceManager.h" + +#include "mozilla/Services.h" +#include "MainThreadUtils.h" +#include "nsArrayUtils.h" +#include "nsCategoryCache.h" +#include "nsCOMPtr.h" +#include "nsIMutableArray.h" +#include "nsIObserverService.h" +#include "nsXULAppAPI.h" +#include "PresentationSessionRequest.h" +#include "PresentationTerminateRequest.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_ISUPPORTS(PresentationDeviceManager, + nsIPresentationDeviceManager, + nsIPresentationDeviceListener, + nsIObserver, + nsISupportsWeakReference) + +PresentationDeviceManager::PresentationDeviceManager() +{ +} + +PresentationDeviceManager::~PresentationDeviceManager() +{ + UnloadDeviceProviders(); + mDevices.Clear(); +} + +void +PresentationDeviceManager::Init() +{ + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (obs) { + obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); + } + + LoadDeviceProviders(); +} + +void +PresentationDeviceManager::Shutdown() +{ + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (obs) { + obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); + } + + UnloadDeviceProviders(); +} + +void +PresentationDeviceManager::LoadDeviceProviders() +{ + MOZ_ASSERT(mProviders.IsEmpty()); + + nsCategoryCache<nsIPresentationDeviceProvider> providerCache(PRESENTATION_DEVICE_PROVIDER_CATEGORY); + providerCache.GetEntries(mProviders); + + for (uint32_t i = 0; i < mProviders.Length(); ++i) { + mProviders[i]->SetListener(this); + } +} + +void +PresentationDeviceManager::UnloadDeviceProviders() +{ + for (uint32_t i = 0; i < mProviders.Length(); ++i) { + mProviders[i]->SetListener(nullptr); + } + + mProviders.Clear(); +} + +void +PresentationDeviceManager::NotifyDeviceChange(nsIPresentationDevice* aDevice, + const char16_t* aType) +{ + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + if (obs) { + obs->NotifyObservers(aDevice, + PRESENTATION_DEVICE_CHANGE_TOPIC, + aType); + } +} + +// nsIPresentationDeviceManager +NS_IMETHODIMP +PresentationDeviceManager::ForceDiscovery() +{ + MOZ_ASSERT(NS_IsMainThread()); + + for (uint32_t i = 0; i < mProviders.Length(); ++i) { + mProviders[i]->ForceDiscovery(); + } + + return NS_OK; +} + +NS_IMETHODIMP +PresentationDeviceManager::AddDeviceProvider(nsIPresentationDeviceProvider* aProvider) +{ + NS_ENSURE_ARG(aProvider); + MOZ_ASSERT(NS_IsMainThread()); + + if (NS_WARN_IF(mProviders.Contains(aProvider))) { + return NS_OK; + } + + mProviders.AppendElement(aProvider); + aProvider->SetListener(this); + + return NS_OK; +} + +NS_IMETHODIMP +PresentationDeviceManager::RemoveDeviceProvider(nsIPresentationDeviceProvider* aProvider) +{ + NS_ENSURE_ARG(aProvider); + MOZ_ASSERT(NS_IsMainThread()); + + if (NS_WARN_IF(!mProviders.RemoveElement(aProvider))) { + return NS_ERROR_FAILURE; + } + + aProvider->SetListener(nullptr); + + return NS_OK; +} + +NS_IMETHODIMP +PresentationDeviceManager::GetDeviceAvailable(bool* aRetVal) +{ + NS_ENSURE_ARG_POINTER(aRetVal); + MOZ_ASSERT(NS_IsMainThread()); + + *aRetVal = !mDevices.IsEmpty(); + + return NS_OK; +} + +NS_IMETHODIMP +PresentationDeviceManager::GetAvailableDevices(nsIArray* aPresentationUrls, nsIArray** aRetVal) +{ + NS_ENSURE_ARG_POINTER(aRetVal); + MOZ_ASSERT(NS_IsMainThread()); + + // Bug 1194049: some providers may discontinue discovery after timeout. + // Call |ForceDiscovery()| here to make sure device lists are updated. + NS_DispatchToMainThread( + NewRunnableMethod(this, &PresentationDeviceManager::ForceDiscovery)); + + nsTArray<nsString> presentationUrls; + if (aPresentationUrls) { + uint32_t length; + nsresult rv = aPresentationUrls->GetLength(&length); + if (NS_SUCCEEDED(rv)) { + for (uint32_t i = 0; i < length; ++i) { + nsCOMPtr<nsISupportsString> isupportStr = + do_QueryElementAt(aPresentationUrls, i); + + nsAutoString presentationUrl; + rv = isupportStr->GetData(presentationUrl); + if (NS_WARN_IF(NS_FAILED(rv))) { + continue; + } + + presentationUrls.AppendElement(presentationUrl); + } + } + } + + nsCOMPtr<nsIMutableArray> devices = do_CreateInstance(NS_ARRAY_CONTRACTID); + for (uint32_t i = 0; i < mDevices.Length(); ++i) { + if (presentationUrls.IsEmpty()) { + devices->AppendElement(mDevices[i], false); + continue; + } + + for (uint32_t j = 0; j < presentationUrls.Length(); ++j) { + bool isSupported; + if (NS_SUCCEEDED(mDevices[i]->IsRequestedUrlSupported(presentationUrls[j], + &isSupported)) && + isSupported) { + devices->AppendElement(mDevices[i], false); + break; + } + } + } + + devices.forget(aRetVal); + + return NS_OK; +} + +// nsIPresentationDeviceListener +NS_IMETHODIMP +PresentationDeviceManager::AddDevice(nsIPresentationDevice* aDevice) +{ + NS_ENSURE_ARG(aDevice); + MOZ_ASSERT(NS_IsMainThread()); + + if (NS_WARN_IF(mDevices.Contains(aDevice))) { + return NS_ERROR_FAILURE; + } + + mDevices.AppendElement(aDevice); + + NotifyDeviceChange(aDevice, u"add"); + + return NS_OK; +} + +NS_IMETHODIMP +PresentationDeviceManager::RemoveDevice(nsIPresentationDevice* aDevice) +{ + NS_ENSURE_ARG(aDevice); + MOZ_ASSERT(NS_IsMainThread()); + + int32_t index = mDevices.IndexOf(aDevice); + if (NS_WARN_IF(index < 0)) { + return NS_ERROR_FAILURE; + } + + mDevices.RemoveElementAt(index); + + NotifyDeviceChange(aDevice, u"remove"); + + return NS_OK; +} + +NS_IMETHODIMP +PresentationDeviceManager::UpdateDevice(nsIPresentationDevice* aDevice) +{ + NS_ENSURE_ARG(aDevice); + MOZ_ASSERT(NS_IsMainThread()); + + if (NS_WARN_IF(!mDevices.Contains(aDevice))) { + return NS_ERROR_FAILURE; + } + + NotifyDeviceChange(aDevice, u"update"); + + return NS_OK; +} + +NS_IMETHODIMP +PresentationDeviceManager::OnSessionRequest(nsIPresentationDevice* aDevice, + const nsAString& aUrl, + const nsAString& aPresentationId, + nsIPresentationControlChannel* aControlChannel) +{ + NS_ENSURE_ARG(aDevice); + NS_ENSURE_ARG(aControlChannel); + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE); + + RefPtr<PresentationSessionRequest> request = + new PresentationSessionRequest(aDevice, aUrl, aPresentationId, aControlChannel); + obs->NotifyObservers(request, + PRESENTATION_SESSION_REQUEST_TOPIC, + nullptr); + + return NS_OK; +} + +NS_IMETHODIMP +PresentationDeviceManager::OnTerminateRequest(nsIPresentationDevice* aDevice, + const nsAString& aPresentationId, + nsIPresentationControlChannel* aControlChannel, + bool aIsFromReceiver) +{ + NS_ENSURE_ARG(aDevice); + NS_ENSURE_ARG(aControlChannel); + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE); + + RefPtr<PresentationTerminateRequest> request = + new PresentationTerminateRequest(aDevice, aPresentationId, + aControlChannel, aIsFromReceiver); + obs->NotifyObservers(request, + PRESENTATION_TERMINATE_REQUEST_TOPIC, + nullptr); + + return NS_OK; +} + +NS_IMETHODIMP +PresentationDeviceManager::OnReconnectRequest(nsIPresentationDevice* aDevice, + const nsAString& aUrl, + const nsAString& aPresentationId, + nsIPresentationControlChannel* aControlChannel) +{ + NS_ENSURE_ARG(aDevice); + NS_ENSURE_ARG(aControlChannel); + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE); + + RefPtr<PresentationSessionRequest> request = + new PresentationSessionRequest(aDevice, aUrl, aPresentationId, aControlChannel); + obs->NotifyObservers(request, + PRESENTATION_RECONNECT_REQUEST_TOPIC, + nullptr); + + return NS_OK; +} + +// nsIObserver +NS_IMETHODIMP +PresentationDeviceManager::Observe(nsISupports *aSubject, + const char *aTopic, + const char16_t *aData) +{ + if (!strcmp(aTopic, "profile-after-change")) { + Init(); + } else if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { + Shutdown(); + } + + return NS_OK; +} + +} // namespace dom +} // namespace mozilla |