diff options
Diffstat (limited to 'dom/presentation/provider/DisplayDeviceProvider.cpp')
-rw-r--r-- | dom/presentation/provider/DisplayDeviceProvider.cpp | 580 |
1 files changed, 0 insertions, 580 deletions
diff --git a/dom/presentation/provider/DisplayDeviceProvider.cpp b/dom/presentation/provider/DisplayDeviceProvider.cpp deleted file mode 100644 index 3f88aba5e..000000000 --- a/dom/presentation/provider/DisplayDeviceProvider.cpp +++ /dev/null @@ -1,580 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=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 "DisplayDeviceProvider.h" - -#include "DeviceProviderHelpers.h" -#include "mozilla/Logging.h" -#include "mozilla/Preferences.h" -#include "mozilla/Services.h" -#include "mozilla/Unused.h" -#include "nsIObserverService.h" -#include "nsIServiceManager.h" -#include "nsIWindowWatcher.h" -#include "nsNetUtil.h" -#include "nsPIDOMWindow.h" -#include "nsSimpleURI.h" -#include "nsTCPDeviceInfo.h" -#include "nsThreadUtils.h" - -static mozilla::LazyLogModule gDisplayDeviceProviderLog("DisplayDeviceProvider"); - -#define LOG(format) MOZ_LOG(gDisplayDeviceProviderLog, mozilla::LogLevel::Debug, format) - -#define DISPLAY_CHANGED_NOTIFICATION "display-changed" -#define DEFAULT_CHROME_FEATURES_PREF "toolkit.defaultChromeFeatures" -#define CHROME_REMOTE_URL_PREF "b2g.multiscreen.chrome_remote_url" -#define PREF_PRESENTATION_DISCOVERABLE_RETRY_MS "dom.presentation.discoverable.retry_ms" - -namespace mozilla { -namespace dom { -namespace presentation { - -/** - * This wrapper is used to break circular-reference problem. - */ -class DisplayDeviceProviderWrappedListener final - : public nsIPresentationControlServerListener -{ -public: - NS_DECL_ISUPPORTS - NS_FORWARD_SAFE_NSIPRESENTATIONCONTROLSERVERLISTENER(mListener) - - explicit DisplayDeviceProviderWrappedListener() = default; - - nsresult SetListener(DisplayDeviceProvider* aListener) - { - mListener = aListener; - return NS_OK; - } - -private: - virtual ~DisplayDeviceProviderWrappedListener() = default; - - DisplayDeviceProvider* mListener = nullptr; -}; - -NS_IMPL_ISUPPORTS(DisplayDeviceProviderWrappedListener, - nsIPresentationControlServerListener) - -NS_IMPL_ISUPPORTS(DisplayDeviceProvider::HDMIDisplayDevice, - nsIPresentationDevice, - nsIPresentationLocalDevice) - -// nsIPresentationDevice -NS_IMETHODIMP -DisplayDeviceProvider::HDMIDisplayDevice::GetId(nsACString& aId) -{ - aId = mWindowId; - return NS_OK; -} - -NS_IMETHODIMP -DisplayDeviceProvider::HDMIDisplayDevice::GetName(nsACString& aName) -{ - aName = mName; - return NS_OK; -} - -NS_IMETHODIMP -DisplayDeviceProvider::HDMIDisplayDevice::GetType(nsACString& aType) -{ - aType = mType; - return NS_OK; -} - -NS_IMETHODIMP -DisplayDeviceProvider::HDMIDisplayDevice::GetWindowId(nsACString& aWindowId) -{ - aWindowId = mWindowId; - return NS_OK; -} - -NS_IMETHODIMP -DisplayDeviceProvider::HDMIDisplayDevice - ::EstablishControlChannel(nsIPresentationControlChannel** aControlChannel) -{ - nsresult rv = OpenTopLevelWindow(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - RefPtr<DisplayDeviceProvider> provider = mProvider.get(); - if (NS_WARN_IF(!provider)) { - return NS_ERROR_FAILURE; - } - return provider->Connect(this, aControlChannel); -} - -NS_IMETHODIMP -DisplayDeviceProvider::HDMIDisplayDevice::Disconnect() -{ - nsresult rv = CloseTopLevelWindow(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - return NS_OK;; -} - -NS_IMETHODIMP -DisplayDeviceProvider::HDMIDisplayDevice::IsRequestedUrlSupported( - const nsAString& aRequestedUrl, - bool* aRetVal) -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!aRetVal) { - return NS_ERROR_INVALID_POINTER; - } - - // 1-UA device only supports HTTP/HTTPS hosted receiver page. - *aRetVal = DeviceProviderHelpers::IsCommonlySupportedScheme(aRequestedUrl); - - return NS_OK; -} - -nsresult -DisplayDeviceProvider::HDMIDisplayDevice::OpenTopLevelWindow() -{ - MOZ_ASSERT(!mWindow); - - nsresult rv; - nsAutoCString flags(Preferences::GetCString(DEFAULT_CHROME_FEATURES_PREF)); - if (flags.IsEmpty()) { - return NS_ERROR_NOT_AVAILABLE; - } - flags.AppendLiteral(",mozDisplayId="); - flags.AppendInt(mScreenId); - - nsAutoCString remoteShellURLString(Preferences::GetCString(CHROME_REMOTE_URL_PREF)); - remoteShellURLString.AppendLiteral("#"); - remoteShellURLString.Append(mWindowId); - - // URI validation - nsCOMPtr<nsIURI> remoteShellURL; - rv = NS_NewURI(getter_AddRefs(remoteShellURL), remoteShellURLString); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = remoteShellURL->GetSpec(remoteShellURLString); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsCOMPtr<nsIWindowWatcher> ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID); - MOZ_ASSERT(ww); - - rv = ww->OpenWindow(nullptr, - remoteShellURLString.get(), - "_blank", - flags.get(), - nullptr, - getter_AddRefs(mWindow)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -nsresult -DisplayDeviceProvider::HDMIDisplayDevice::CloseTopLevelWindow() -{ - MOZ_ASSERT(mWindow); - - nsCOMPtr<nsPIDOMWindowOuter> piWindow = nsPIDOMWindowOuter::From(mWindow); - nsresult rv = piWindow->Close(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -NS_IMPL_ISUPPORTS(DisplayDeviceProvider, - nsIObserver, - nsIPresentationDeviceProvider, - nsIPresentationControlServerListener) - -DisplayDeviceProvider::~DisplayDeviceProvider() -{ - Uninit(); -} - -nsresult -DisplayDeviceProvider::Init() -{ - // Provider must be initialized only once. - if (mInitialized) { - return NS_OK; - } - - nsresult rv; - - mServerRetryMs = Preferences::GetUint(PREF_PRESENTATION_DISCOVERABLE_RETRY_MS); - mServerRetryTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); - MOZ_ASSERT(obs); - - obs->AddObserver(this, DISPLAY_CHANGED_NOTIFICATION, false); - - mDevice = new HDMIDisplayDevice(this); - - mWrappedListener = new DisplayDeviceProviderWrappedListener(); - rv = mWrappedListener->SetListener(this); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mPresentationService = do_CreateInstance(PRESENTATION_CONTROL_SERVICE_CONTACT_ID, - &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = StartTCPService(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mInitialized = true; - return NS_OK; -} - -nsresult -DisplayDeviceProvider::Uninit() -{ - // Provider must be deleted only once. - if (!mInitialized) { - return NS_OK; - } - - nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); - if (obs) { - obs->RemoveObserver(this, DISPLAY_CHANGED_NOTIFICATION); - } - - // Remove device from device manager when the provider is uninit - RemoveExternalScreen(); - - AbortServerRetry(); - - mInitialized = false; - mWrappedListener->SetListener(nullptr); - return NS_OK; -} - -nsresult -DisplayDeviceProvider::StartTCPService() -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsresult rv; - rv = mPresentationService->SetId(NS_LITERAL_CSTRING("DisplayDeviceProvider")); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - uint16_t servicePort; - rv = mPresentationService->GetPort(&servicePort); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - /* - * If |servicePort| is non-zero, it means PresentationServer is running. - * Otherwise, we should make it start serving. - */ - if (servicePort) { - mPort = servicePort; - return NS_OK; - } - - rv = mPresentationService->SetListener(mWrappedListener); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - AbortServerRetry(); - - // 1-UA doesn't need encryption. - rv = mPresentationService->StartServer(/* aEncrypted = */ false, - /* aPort = */ 0); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -void -DisplayDeviceProvider::AbortServerRetry() -{ - if (mIsServerRetrying) { - mIsServerRetrying = false; - mServerRetryTimer->Cancel(); - } -} - -nsresult -DisplayDeviceProvider::AddExternalScreen() -{ - MOZ_ASSERT(mDeviceListener); - - nsresult rv; - nsCOMPtr<nsIPresentationDeviceListener> listener; - rv = GetListener(getter_AddRefs(listener)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = listener->AddDevice(mDevice); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -nsresult -DisplayDeviceProvider::RemoveExternalScreen() -{ - MOZ_ASSERT(mDeviceListener); - - nsresult rv; - nsCOMPtr<nsIPresentationDeviceListener> listener; - rv = GetListener(getter_AddRefs(listener)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - rv = listener->RemoveDevice(mDevice); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mDevice->Disconnect(); - return NS_OK; -} - -// nsIPresentationDeviceProvider -NS_IMETHODIMP -DisplayDeviceProvider::GetListener(nsIPresentationDeviceListener** aListener) -{ - if (NS_WARN_IF(!aListener)) { - return NS_ERROR_INVALID_POINTER; - } - - nsresult rv; - nsCOMPtr<nsIPresentationDeviceListener> listener = - do_QueryReferent(mDeviceListener, &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - listener.forget(aListener); - - return NS_OK; -} - -NS_IMETHODIMP -DisplayDeviceProvider::SetListener(nsIPresentationDeviceListener* aListener) -{ - mDeviceListener = do_GetWeakReference(aListener); - nsresult rv = mDeviceListener ? Init() : Uninit(); - if(NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - return NS_OK; -} - -NS_IMETHODIMP -DisplayDeviceProvider::ForceDiscovery() -{ - return NS_OK; -} - -// nsIPresentationControlServerListener -NS_IMETHODIMP -DisplayDeviceProvider::OnServerReady(uint16_t aPort, - const nsACString& aCertFingerprint) -{ - MOZ_ASSERT(NS_IsMainThread()); - mPort = aPort; - - return NS_OK; -} - -NS_IMETHODIMP -DisplayDeviceProvider::OnServerStopped(nsresult aResult) -{ - MOZ_ASSERT(NS_IsMainThread()); - - // Try restart server if it is stopped abnormally. - if (NS_FAILED(aResult)) { - mIsServerRetrying = true; - mServerRetryTimer->Init(this, mServerRetryMs, nsITimer::TYPE_ONE_SHOT); - } - - return NS_OK; -} - -NS_IMETHODIMP -DisplayDeviceProvider::OnSessionRequest(nsITCPDeviceInfo* aDeviceInfo, - const nsAString& aUrl, - const nsAString& aPresentationId, - nsIPresentationControlChannel* aControlChannel) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(aDeviceInfo); - MOZ_ASSERT(aControlChannel); - - nsresult rv; - - nsCOMPtr<nsIPresentationDeviceListener> listener; - rv = GetListener(getter_AddRefs(listener)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - MOZ_ASSERT(!listener); - - rv = listener->OnSessionRequest(mDevice, - aUrl, - aPresentationId, - aControlChannel); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -NS_IMETHODIMP -DisplayDeviceProvider::OnTerminateRequest(nsITCPDeviceInfo* aDeviceInfo, - const nsAString& aPresentationId, - nsIPresentationControlChannel* aControlChannel, - bool aIsFromReceiver) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(aDeviceInfo); - MOZ_ASSERT(aControlChannel); - - nsresult rv; - - nsCOMPtr<nsIPresentationDeviceListener> listener; - rv = GetListener(getter_AddRefs(listener)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - MOZ_ASSERT(!listener); - - rv = listener->OnTerminateRequest(mDevice, - aPresentationId, - aControlChannel, - aIsFromReceiver); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -NS_IMETHODIMP -DisplayDeviceProvider::OnReconnectRequest(nsITCPDeviceInfo* aDeviceInfo, - const nsAString& aUrl, - const nsAString& aPresentationId, - nsIPresentationControlChannel* aControlChannel) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(aDeviceInfo); - MOZ_ASSERT(aControlChannel); - - nsresult rv; - - nsCOMPtr<nsIPresentationDeviceListener> listener; - rv = GetListener(getter_AddRefs(listener)); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - MOZ_ASSERT(!listener); - - rv = listener->OnReconnectRequest(mDevice, - aUrl, - aPresentationId, - aControlChannel); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - return NS_OK; -} - -// nsIObserver -NS_IMETHODIMP -DisplayDeviceProvider::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) -{ - if (!strcmp(aTopic, DISPLAY_CHANGED_NOTIFICATION)) { - nsCOMPtr<nsIDisplayInfo> displayInfo = do_QueryInterface(aSubject); - MOZ_ASSERT(displayInfo); - - int32_t type; - bool isConnected; - displayInfo->GetConnected(&isConnected); - // XXX The ID is as same as the type of display. - // See Bug 1138287 and nsScreenManagerGonk::AddScreen() for more detail. - displayInfo->GetId(&type); - - if (type == DisplayType::DISPLAY_EXTERNAL) { - nsresult rv = isConnected ? AddExternalScreen() : RemoveExternalScreen(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - } else if (!strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC)) { - nsCOMPtr<nsITimer> timer = do_QueryInterface(aSubject); - if (!timer) { - return NS_ERROR_UNEXPECTED; - } - - if (timer == mServerRetryTimer) { - mIsServerRetrying = false; - StartTCPService(); - } - } - - return NS_OK; -} - -nsresult -DisplayDeviceProvider::Connect(HDMIDisplayDevice* aDevice, - nsIPresentationControlChannel** aControlChannel) -{ - MOZ_ASSERT(aDevice); - MOZ_ASSERT(mPresentationService); - NS_ENSURE_ARG_POINTER(aControlChannel); - *aControlChannel = nullptr; - - nsCOMPtr<nsITCPDeviceInfo> deviceInfo = new TCPDeviceInfo(aDevice->Id(), - aDevice->Address(), - mPort, - EmptyCString()); - - return mPresentationService->Connect(deviceInfo, aControlChannel); -} - -} // namespace presentation -} // namespace dom -} // namespace mozilla |