☠☠ backed out by 1450d0e37119 ☠ ☠ | |
author | Tommy Kuo <kuoe0.tw@gmail.com> |
Mon, 21 Mar 2016 01:52:00 +0100 | |
changeset 328839 | f74a43d0b9eb6b7a3ae5e03c508eab14ac01620e |
parent 328838 | 2ba85d06b69b916f1e65c946a022b617b74ffb27 |
child 328840 | 75aff80f34a50705e0d0bed418ba7ff546869e49 |
push id | 6048 |
push user | kmoir@mozilla.com |
push date | Mon, 06 Jun 2016 19:02:08 +0000 |
treeherder | mozilla-beta@46d72a56c57d [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug |
bugs | 1234492 |
milestone | 48.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -1695,17 +1695,17 @@ ContentChild::RecvNotifyPresentationRece bool ContentChild::RecvNotifyPresentationReceiverCleanUp(const nsString& aSessionId) { nsCOMPtr<nsIPresentationService> service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); NS_WARN_IF(!service); - NS_WARN_IF(NS_FAILED(service->UntrackSessionInfo(aSessionId))); + NS_WARN_IF(NS_FAILED(service->UntrackSessionInfo(aSessionId, nsIPresentationService::ROLE_RECEIVER))); return true; } bool ContentChild::RecvNotifyGMPsChanged() { GMPDecoderModule::UpdateUsableCodecs();
--- a/dom/presentation/PresentationCallbacks.cpp +++ b/dom/presentation/PresentationCallbacks.cpp @@ -45,16 +45,17 @@ NS_IMETHODIMP PresentationRequesterCallback::NotifySuccess() { MOZ_ASSERT(NS_IsMainThread()); // At the sender side, this function must get called after the transport // channel is ready. So we simply set the connection state as connected. RefPtr<PresentationConnection> connection = PresentationConnection::Create(mRequest->GetOwner(), mSessionId, + nsIPresentationService::ROLE_CONTROLLER, PresentationConnectionState::Connected); if (NS_WARN_IF(!connection)) { mPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR); return NS_OK; } mPromise->MaybeResolve(connection);
--- a/dom/presentation/PresentationConnection.cpp +++ b/dom/presentation/PresentationConnection.cpp @@ -30,68 +30,75 @@ NS_IMPL_ADDREF_INHERITED(PresentationCon NS_IMPL_RELEASE_INHERITED(PresentationConnection, DOMEventTargetHelper) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationConnection) NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionListener) NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) PresentationConnection::PresentationConnection(nsPIDOMWindowInner* aWindow, const nsAString& aId, + const uint8_t aRole, PresentationConnectionState aState) : DOMEventTargetHelper(aWindow) , mId(aId) , mState(aState) { + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); + mRole = aRole; } /* virtual */ PresentationConnection::~PresentationConnection() { } /* static */ already_AddRefed<PresentationConnection> PresentationConnection::Create(nsPIDOMWindowInner* aWindow, const nsAString& aId, + const uint8_t aRole, PresentationConnectionState aState) { + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); RefPtr<PresentationConnection> connection = - new PresentationConnection(aWindow, aId, aState); + new PresentationConnection(aWindow, aId, aRole, aState); return NS_WARN_IF(!connection->Init()) ? nullptr : connection.forget(); } bool PresentationConnection::Init() { if (NS_WARN_IF(mId.IsEmpty())) { return false; } nsCOMPtr<nsIPresentationService> service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); if(NS_WARN_IF(!service)) { return false; } - nsresult rv = service->RegisterSessionListener(mId, this); + nsresult rv = service->RegisterSessionListener(mId, mRole, this); if(NS_WARN_IF(NS_FAILED(rv))) { return false; } return true; } void PresentationConnection::Shutdown() { nsCOMPtr<nsIPresentationService> service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); if (NS_WARN_IF(!service)) { return; } - nsresult rv = service->UnregisterSessionListener(mId); + nsresult rv = service->UnregisterSessionListener(mId, mRole); NS_WARN_IF(NS_FAILED(rv)); } /* virtual */ void PresentationConnection::DisconnectFromOwner() { Shutdown(); DOMEventTargetHelper::DisconnectFromOwner(); @@ -143,17 +150,17 @@ PresentationConnection::Send(const nsASt nsCOMPtr<nsIPresentationService> service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); if(NS_WARN_IF(!service)) { aRv.Throw(NS_ERROR_DOM_OPERATION_ERR); return; } - rv = service->SendSessionMessage(mId, stream); + rv = service->SendSessionMessage(mId, mRole, stream); if(NS_WARN_IF(NS_FAILED(rv))) { aRv.Throw(NS_ERROR_DOM_OPERATION_ERR); } } void PresentationConnection::Close(ErrorResult& aRv) { @@ -176,17 +183,17 @@ PresentationConnection::Terminate(ErrorR nsCOMPtr<nsIPresentationService> service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); if(NS_WARN_IF(!service)) { aRv.Throw(NS_ERROR_DOM_OPERATION_ERR); return; } - NS_WARN_IF(NS_FAILED(service->TerminateSession(mId))); + NS_WARN_IF(NS_FAILED(service->TerminateSession(mId, mRole))); } NS_IMETHODIMP PresentationConnection::NotifyStateChange(const nsAString& aSessionId, uint16_t aState) { if (!aSessionId.Equals(mId)) { return NS_ERROR_INVALID_ARG; @@ -217,17 +224,17 @@ PresentationConnection::NotifyStateChang // Unregister session listener if the session is no longer connected. if (mState == PresentationConnectionState::Terminated) { nsCOMPtr<nsIPresentationService> service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); if (NS_WARN_IF(!service)) { return NS_ERROR_NOT_AVAILABLE; } - nsresult rv = service->UnregisterSessionListener(mId); + nsresult rv = service->UnregisterSessionListener(mId, mRole); if(NS_WARN_IF(NS_FAILED(rv))) { return rv; } } return DispatchStateChangeEvent(); }
--- a/dom/presentation/PresentationConnection.h +++ b/dom/presentation/PresentationConnection.h @@ -20,16 +20,17 @@ class PresentationConnection final : pub public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationConnection, DOMEventTargetHelper) NS_DECL_NSIPRESENTATIONSESSIONLISTENER static already_AddRefed<PresentationConnection> Create(nsPIDOMWindowInner* aWindow, const nsAString& aId, + const uint8_t aRole, PresentationConnectionState aState); virtual void DisconnectFromOwner() override; virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; // WebIDL (public APIs) @@ -45,28 +46,30 @@ public: void Terminate(ErrorResult& aRv); IMPL_EVENT_HANDLER(statechange); IMPL_EVENT_HANDLER(message); private: PresentationConnection(nsPIDOMWindowInner* aWindow, const nsAString& aId, + const uint8_t aRole, PresentationConnectionState aState); ~PresentationConnection(); bool Init(); void Shutdown(); nsresult DispatchStateChangeEvent(); nsresult DispatchMessageEvent(JS::Handle<JS::Value> aData); nsString mId; + uint8_t mRole; PresentationConnectionState mState; }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_PresentationConnection_h
--- a/dom/presentation/PresentationReceiver.cpp +++ b/dom/presentation/PresentationReceiver.cpp @@ -167,16 +167,17 @@ PresentationReceiver::NotifySessionConne } if (NS_WARN_IF(aWindowId != GetOwner()->WindowID())) { return NS_ERROR_INVALID_ARG; } RefPtr<PresentationConnection> connection = PresentationConnection::Create(GetOwner(), aSessionId, + nsIPresentationService::ROLE_RECEIVER, PresentationConnectionState::Closed); if (NS_WARN_IF(!connection)) { return NS_ERROR_NOT_AVAILABLE; } mConnections.AppendElement(connection); // Resolve pending |GetConnection| promises if any. if (!mPendingGetConnectionPromises.IsEmpty()) {
--- a/dom/presentation/PresentationService.cpp +++ b/dom/presentation/PresentationService.cpp @@ -1,9 +1,10 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 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 "ipc/PresentationIPCService.h" #include "mozilla/Services.h" #include "mozIApplication.h" #include "nsIAppsService.h" @@ -95,17 +96,18 @@ PresentationDeviceRequest::Select(nsIPre nsCOMPtr<nsIPresentationService> service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); if (NS_WARN_IF(!service)) { return NS_ERROR_NOT_AVAILABLE; } // Update device in the session info. RefPtr<PresentationSessionInfo> info = - static_cast<PresentationService*>(service.get())->GetSessionInfo(mId); + static_cast<PresentationService*>(service.get())-> + GetSessionInfo(mId, nsIPresentationService::ROLE_CONTROLLER); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } info->SetDevice(aDevice); // Establish a control channel. If we failed to do so, the callback is called // with an error message. nsCOMPtr<nsIPresentationControlChannel> ctrlChannel; @@ -128,17 +130,18 @@ PresentationDeviceRequest::Cancel() { nsCOMPtr<nsIPresentationService> service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); if (NS_WARN_IF(!service)) { return NS_ERROR_NOT_AVAILABLE; } RefPtr<PresentationSessionInfo> info = - static_cast<PresentationService*>(service.get())->GetSessionInfo(mId); + static_cast<PresentationService*>(service.get())-> + GetSessionInfo(mId, nsIPresentationService::ROLE_CONTROLLER); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } return info->ReplyError(NS_ERROR_DOM_ABORT_ERR); } /* @@ -219,17 +222,18 @@ PresentationService::Observe(nsISupports void PresentationService::HandleShutdown() { MOZ_ASSERT(NS_IsMainThread()); mAvailabilityListeners.Clear(); mRespondingListeners.Clear(); - mSessionInfo.Clear(); + mSessionInfoAtController.Clear(); + mSessionInfoAtReceiver.Clear(); mRespondingSessionIds.Clear(); nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); if (obs) { obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); obs->RemoveObserver(this, PRESENTATION_DEVICE_CHANGE_TOPIC); obs->RemoveObserver(this, PRESENTATION_SESSION_REQUEST_TOPIC); } @@ -306,31 +310,32 @@ PresentationService::HandleSessionReques if (NS_WARN_IF(isApp && !IsAppInstalled(uri))) { ctrlChannel->Close(NS_ERROR_DOM_NOT_FOUND_ERR); return NS_OK; } #endif // Create or reuse session info. - RefPtr<PresentationSessionInfo> info = GetSessionInfo(sessionId); + RefPtr<PresentationSessionInfo> info = + GetSessionInfo(sessionId, nsIPresentationService::ROLE_RECEIVER); if (NS_WARN_IF(info)) { // TODO Bug 1195605. Update here after session join/resume becomes supported. ctrlChannel->Close(NS_ERROR_DOM_OPERATION_ERR); return NS_ERROR_DOM_ABORT_ERR; } info = new PresentationPresentingInfo(url, sessionId, device); rv = info->Init(ctrlChannel); if (NS_WARN_IF(NS_FAILED(rv))) { ctrlChannel->Close(rv); return rv; } - mSessionInfo.Put(sessionId, info); + mSessionInfoAtReceiver.Put(sessionId, info); // Notify the receiver to launch. nsCOMPtr<nsIPresentationRequestUIGlue> glue = do_CreateInstance(PRESENTATION_REQUEST_UI_GLUE_CONTRACTID); if (NS_WARN_IF(!glue)) { ctrlChannel->Close(NS_ERROR_DOM_OPERATION_ERR); return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR); } @@ -393,17 +398,17 @@ PresentationService::StartSession(const MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aCallback); MOZ_ASSERT(!aSessionId.IsEmpty()); // Create session info and set the callback. The callback is called when the // request is finished. RefPtr<PresentationSessionInfo> info = new PresentationControllingInfo(aUrl, aSessionId, aCallback); - mSessionInfo.Put(aSessionId, info); + mSessionInfoAtController.Put(aSessionId, info); nsCOMPtr<nsIPresentationDeviceRequest> request = new PresentationDeviceRequest(aUrl, aSessionId, aOrigin); if (aDeviceId.IsVoid()) { // Pop up a prompt and ask user to select a device. nsCOMPtr<nsIPresentationDevicePrompt> prompt = do_GetService(PRESENTATION_DEVICE_PROMPT_CONTRACTID); @@ -455,51 +460,60 @@ PresentationService::StartSession(const } // Reject if designated device is not available. return info->ReplyError(NS_ERROR_DOM_NOT_FOUND_ERR); } NS_IMETHODIMP PresentationService::SendSessionMessage(const nsAString& aSessionId, + uint8_t aRole, nsIInputStream* aStream) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aStream); MOZ_ASSERT(!aSessionId.IsEmpty()); + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); - RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId); + RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } return info->Send(aStream); } NS_IMETHODIMP -PresentationService::CloseSession(const nsAString& aSessionId) +PresentationService::CloseSession(const nsAString& aSessionId, + uint8_t aRole) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aSessionId.IsEmpty()); + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); - RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId); + RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } return info->Close(NS_OK, nsIPresentationSessionListener::STATE_CLOSED); } NS_IMETHODIMP -PresentationService::TerminateSession(const nsAString& aSessionId) +PresentationService::TerminateSession(const nsAString& aSessionId, + uint8_t aRole) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!aSessionId.IsEmpty()); + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); - RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId); + RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } return info->Close(NS_OK, nsIPresentationSessionListener::STATE_TERMINATED); } NS_IMETHODIMP @@ -521,22 +535,25 @@ PresentationService::UnregisterAvailabil MOZ_ASSERT(NS_IsMainThread()); mAvailabilityListeners.RemoveElement(aListener); return NS_OK; } NS_IMETHODIMP PresentationService::RegisterSessionListener(const nsAString& aSessionId, + uint8_t aRole, nsIPresentationSessionListener* aListener) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aListener); + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); - RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId); + RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { // Notify the listener of TERMINATED since no correspondent session info is // available possibly due to establishment failure. This would be useful at // the receiver side, since a presentation session is created at beginning // and here is the place to realize the underlying establishment fails. nsresult rv = aListener->NotifyStateChange(aSessionId, nsIPresentationSessionListener::STATE_TERMINATED); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -544,24 +561,27 @@ PresentationService::RegisterSessionList } return NS_ERROR_NOT_AVAILABLE; } return info->SetListener(aListener); } NS_IMETHODIMP -PresentationService::UnregisterSessionListener(const nsAString& aSessionId) +PresentationService::UnregisterSessionListener(const nsAString& aSessionId, + uint8_t aRole) { MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); - RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId); + RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (info) { NS_WARN_IF(NS_FAILED(info->Close(NS_OK, nsIPresentationSessionListener::STATE_TERMINATED))); - UntrackSessionInfo(aSessionId); + UntrackSessionInfo(aSessionId, aRole); return info->SetListener(nullptr); } return NS_OK; } NS_IMETHODIMP PresentationService::RegisterRespondingListener(uint64_t aWindowId, nsIPresentationRespondingListener* aListener) @@ -601,52 +621,63 @@ PresentationService::GetExistentSessionI } return NS_OK; } NS_IMETHODIMP PresentationService::NotifyReceiverReady(const nsAString& aSessionId, uint64_t aWindowId) { - RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId); + RefPtr<PresentationSessionInfo> info = + GetSessionInfo(aSessionId, nsIPresentationService::ROLE_RECEIVER); if (NS_WARN_IF(!info)) { return NS_ERROR_NOT_AVAILABLE; } // Only track the responding info when an actual window ID, which would never // be 0, is provided (for an in-process receiver page). if (aWindowId != 0) { mRespondingSessionIds.Put(aWindowId, new nsAutoString(aSessionId)); mRespondingWindowIds.Put(aSessionId, aWindowId); } return static_cast<PresentationPresentingInfo*>(info.get())->NotifyResponderReady(); } NS_IMETHODIMP -PresentationService::UntrackSessionInfo(const nsAString& aSessionId) +PresentationService::UntrackSessionInfo(const nsAString& aSessionId, + uint8_t aRole) { + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); // Remove the session info. - mSessionInfo.Remove(aSessionId); + if (nsIPresentationService::ROLE_CONTROLLER == aRole) { + mSessionInfoAtController.Remove(aSessionId); + } else { + mSessionInfoAtReceiver.Remove(aSessionId); + } // Remove the in-process responding info if there's still any. uint64_t windowId = 0; if(mRespondingWindowIds.Get(aSessionId, &windowId)) { mRespondingWindowIds.Remove(aSessionId); mRespondingSessionIds.Remove(windowId); } return NS_OK; } bool PresentationService::IsSessionAccessible(const nsAString& aSessionId, + const uint8_t aRole, base::ProcessId aProcessId) { - RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId); + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); + RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole); if (NS_WARN_IF(!info)) { return false; } return info->IsAccessible(aProcessId); } already_AddRefed<nsIPresentationService> NS_CreatePresentationService()
--- a/dom/presentation/PresentationService.h +++ b/dom/presentation/PresentationService.h @@ -28,24 +28,33 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER NS_DECL_NSIPRESENTATIONSERVICE PresentationService(); bool Init(); already_AddRefed<PresentationSessionInfo> - GetSessionInfo(const nsAString& aSessionId) + GetSessionInfo(const nsAString& aSessionId, const uint8_t aRole) { + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); + RefPtr<PresentationSessionInfo> info; - return mSessionInfo.Get(aSessionId, getter_AddRefs(info)) ? - info.forget() : nullptr; + if (aRole == nsIPresentationService::ROLE_CONTROLLER) { + return mSessionInfoAtController.Get(aSessionId, getter_AddRefs(info)) ? + info.forget() : nullptr; + } else { + return mSessionInfoAtReceiver.Get(aSessionId, getter_AddRefs(info)) ? + info.forget() : nullptr; + } } bool IsSessionAccessible(const nsAString& aSessionId, + const uint8_t aRole, base::ProcessId aProcessId); private: ~PresentationService(); void HandleShutdown(); nsresult HandleDeviceChange(); nsresult HandleSessionRequest(nsIPresentationSessionRequest* aRequest); void NotifyAvailableChange(bool aIsAvailable); @@ -56,17 +65,18 @@ private: // Store the responding listener based on the window ID of the (in-process or // OOP) receiver page. // TODO Bug 1195605 - Support many-to-one session. // So far responding listeners are registered but |notifySessionConnect| hasn't // been called in any place until many-to-one session becomes supported. nsRefPtrHashtable<nsUint64HashKey, nsIPresentationRespondingListener> mRespondingListeners; - nsRefPtrHashtable<nsStringHashKey, PresentationSessionInfo> mSessionInfo; + nsRefPtrHashtable<nsStringHashKey, PresentationSessionInfo> mSessionInfoAtController; + nsRefPtrHashtable<nsStringHashKey, PresentationSessionInfo> mSessionInfoAtReceiver; // Store the mapping between the window ID of the in-process page and the ID // of the responding session. It's used for an in-process receiver page to // retrieve the correspondent session ID. Besides, also keep the mapping // between the responding session ID and the window ID to help look up the // window ID. nsClassHashtable<nsUint64HashKey, nsString> mRespondingSessionIds; nsDataHashtable<nsStringHashKey, uint64_t> mRespondingWindowIds;
--- a/dom/presentation/PresentationSessionInfo.cpp +++ b/dom/presentation/PresentationSessionInfo.cpp @@ -322,17 +322,17 @@ PresentationSessionInfo::ReplyError(nsre /* virtual */ nsresult PresentationSessionInfo::UntrackFromService() { nsCOMPtr<nsIPresentationService> service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); if (NS_WARN_IF(!service)) { return NS_ERROR_NOT_AVAILABLE; } - static_cast<PresentationService*>(service.get())->UntrackSessionInfo(mSessionId); + static_cast<PresentationService*>(service.get())->UntrackSessionInfo(mSessionId, mRole); return NS_OK; } /* virtual */ bool PresentationSessionInfo::IsAccessible(base::ProcessId aProcessId) { // No restriction by default. @@ -799,17 +799,17 @@ PresentationPresentingInfo::UntrackFromS } // Remove the session info (and the in-process responding info if there's any). nsCOMPtr<nsIPresentationService> service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); if (NS_WARN_IF(!service)) { return NS_ERROR_NOT_AVAILABLE; } - static_cast<PresentationService*>(service.get())->UntrackSessionInfo(mSessionId); + static_cast<PresentationService*>(service.get())->UntrackSessionInfo(mSessionId, mRole); return NS_OK; } bool PresentationPresentingInfo::IsAccessible(base::ProcessId aProcessId) { // Only the specific content process should access the responder info.
--- a/dom/presentation/PresentationSessionInfo.h +++ b/dom/presentation/PresentationSessionInfo.h @@ -30,40 +30,49 @@ class PresentationSessionInfo : public n , public nsIPresentationControlChannelListener { public: NS_DECL_ISUPPORTS NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTCALLBACK PresentationSessionInfo(const nsAString& aUrl, const nsAString& aSessionId, + const uint8_t aRole, nsIPresentationServiceCallback* aCallback) : mUrl(aUrl) , mSessionId(aSessionId) , mIsResponderReady(false) , mIsTransportReady(false) , mState(nsIPresentationSessionListener::STATE_CLOSED) , mCallback(aCallback) { MOZ_ASSERT(!mUrl.IsEmpty()); MOZ_ASSERT(!mSessionId.IsEmpty()); + MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || + aRole == nsIPresentationService::ROLE_RECEIVER); + mRole = aRole; } virtual nsresult Init(nsIPresentationControlChannel* aControlChannel); const nsAString& GetUrl() const { return mUrl; } const nsAString& GetSessionId() const { return mSessionId; } + uint8_t GetRole() const + { + return mRole; + } + void SetCallback(nsIPresentationServiceCallback* aCallback) { mCallback = aCallback; } nsresult SetListener(nsIPresentationSessionListener* aListener); void SetDevice(nsIPresentationDevice* aDevice) @@ -127,16 +136,19 @@ protected: if (mListener) { nsresult rv = mListener->NotifyStateChange(mSessionId, mState); NS_WARN_IF(NS_FAILED(rv)); } } nsString mUrl; nsString mSessionId; + // mRole should be nsIPresentationService::ROLE_CONTROLLER + // or nsIPresentationService::ROLE_RECEIVER. + uint8_t mRole; bool mIsResponderReady; bool mIsTransportReady; uint32_t mState; // CONNECTED, CLOSED, TERMINATED nsCOMPtr<nsIPresentationServiceCallback> mCallback; nsCOMPtr<nsIPresentationSessionListener> mListener; nsCOMPtr<nsIPresentationDevice> mDevice; nsCOMPtr<nsIPresentationSessionTransport> mTransport; nsCOMPtr<nsIPresentationControlChannel> mControlChannel; @@ -149,17 +161,20 @@ class PresentationControllingInfo final public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIPRESENTATIONCONTROLCHANNELLISTENER NS_DECL_NSISERVERSOCKETLISTENER PresentationControllingInfo(const nsAString& aUrl, const nsAString& aSessionId, nsIPresentationServiceCallback* aCallback) - : PresentationSessionInfo(aUrl, aSessionId, aCallback) + : PresentationSessionInfo(aUrl, + aSessionId, + nsIPresentationService::ROLE_CONTROLLER, + aCallback) { MOZ_ASSERT(mCallback); } nsresult Init(nsIPresentationControlChannel* aControlChannel) override; private: ~PresentationControllingInfo() @@ -184,20 +199,22 @@ class PresentationPresentingInfo final : public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIPRESENTATIONCONTROLCHANNELLISTENER NS_DECL_NSITIMERCALLBACK PresentationPresentingInfo(const nsAString& aUrl, const nsAString& aSessionId, nsIPresentationDevice* aDevice) - : PresentationSessionInfo(aUrl, aSessionId, nullptr) + : PresentationSessionInfo(aUrl, + aSessionId, + nsIPresentationService::ROLE_RECEIVER, + nullptr) { MOZ_ASSERT(aDevice); - SetDevice(aDevice); } nsresult Init(nsIPresentationControlChannel* aControlChannel) override; nsresult NotifyResponderReady(); void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
--- a/dom/presentation/interfaces/nsIPresentationService.idl +++ b/dom/presentation/interfaces/nsIPresentationService.idl @@ -28,19 +28,22 @@ interface nsIPresentationServiceCallback /* * Called when the operation fails. * * @param error: error message. */ void notifyError(in nsresult error); }; -[scriptable, uuid(2e360359-c45c-4949-bf95-410242ce483f)] +[scriptable, uuid(5cac5d1f-f996-4d9a-b1fa-f2c7adbe02ca)] interface nsIPresentationService : nsISupports { + const unsigned short ROLE_CONTROLLER = 0x1; + const unsigned short ROLE_RECEIVER = 0x2; + /* * Start a new presentation session and display a prompt box which asks users * to select a device. * * @param url: The url of presenting page. * @param sessionId: An ID to identify presentation session. * @param origin: The url of requesting page. * @param deviceId: The specified device of handling this request, null string @@ -55,34 +58,40 @@ interface nsIPresentationService : nsISu in DOMString origin, in DOMString deviceId, in nsIPresentationServiceCallback callback); /* * Send the message wrapped with an input stream to the session. * * @param sessionId: An ID to identify presentation session. + * @param role: Identify the function called by controller or receiver. * @param stream: The message is converted to an input stream. */ void sendSessionMessage(in DOMString sessionId, + in uint8_t role, in nsIInputStream stream); /* * Close the session. * * @param sessionId: An ID to identify presentation session. + * @param role: Identify the function called by controller or receiver. */ - void closeSession(in DOMString sessionId); + void closeSession(in DOMString sessionId, + in uint8_t role); /* * Terminate the session. * * @param sessionId: An ID to identify presentation session. + * @param role: Identify the function called by controller or receiver. */ - void terminateSession(in DOMString sessionId); + void terminateSession(in DOMString sessionId, + in uint8_t role); /* * Register an availability listener. Must be called from the main thread. * * @param listener: The listener to register. */ void registerAvailabilityListener(in nsIPresentationAvailabilityListener listener); @@ -91,27 +100,31 @@ interface nsIPresentationService : nsISu * @param listener: The listener to unregister. */ void unregisterAvailabilityListener(in nsIPresentationAvailabilityListener listener); /* * Register a session listener. Must be called from the main thread. * * @param sessionId: An ID to identify presentation session. + * @param role: Identify the function called by controller or receiver. * @param listener: The listener to register. */ void registerSessionListener(in DOMString sessionId, + in uint8_t role, in nsIPresentationSessionListener listener); /* * Unregister a session listener. Must be called from the main thread. * * @param sessionId: An ID to identify presentation session. + * @param role: Identify the function called by controller or receiver. */ - void unregisterSessionListener(in DOMString sessionId); + void unregisterSessionListener(in DOMString sessionId, + in uint8_t role); /* * Register a responding listener. Must be called from the main thread. * * @param windowId: The window ID associated with the listener. * @param listener: The listener to register. */ void registerRespondingListener(in uint64_t windowId, @@ -143,11 +156,12 @@ interface nsIPresentationService : nsISu */ void notifyReceiverReady(in DOMString sessionId, [optional] in uint64_t windowId); /* * Untrack the relevant info about the presentation session if there's any. * * @param sessionId: An ID to identify presentation session. + * @param role: Identify the function called by controller or receiver. */ - void untrackSessionInfo(in DOMString sessionId); + void untrackSessionInfo(in DOMString sessionId, in uint8_t role); };
--- a/dom/presentation/ipc/PPresentation.ipdl +++ b/dom/presentation/ipc/PPresentation.ipdl @@ -18,27 +18,30 @@ struct StartSessionRequest nsString sessionId; nsString origin; nsString deviceId; }; struct SendSessionMessageRequest { nsString sessionId; + uint8_t role; InputStreamParams data; }; struct CloseSessionRequest { nsString sessionId; + uint8_t role; }; struct TerminateSessionRequest { nsString sessionId; + uint8_t role; }; union PresentationIPCRequest { StartSessionRequest; SendSessionMessageRequest; CloseSessionRequest; TerminateSessionRequest; @@ -56,18 +59,18 @@ child: async NotifySessionConnect(uint64_t aWindowId, nsString aSessionId); parent: async __delete__(); async RegisterAvailabilityHandler(); async UnregisterAvailabilityHandler(); - async RegisterSessionHandler(nsString aSessionId); - async UnregisterSessionHandler(nsString aSessionId); + async RegisterSessionHandler(nsString aSessionId, uint8_t aRole); + async UnregisterSessionHandler(nsString aSessionId, uint8_t aRole); async RegisterRespondingHandler(uint64_t aWindowId); async UnregisterRespondingHandler(uint64_t aWindowId); async PPresentationRequest(PresentationIPCRequest aRequest); async NotifyReceiverReady(nsString aSessionId); };
--- a/dom/presentation/ipc/PresentationIPCService.cpp +++ b/dom/presentation/ipc/PresentationIPCService.cpp @@ -55,43 +55,46 @@ PresentationIPCService::StartSession(con return SendRequest(aCallback, StartSessionRequest(nsAutoString(aUrl), nsAutoString(aSessionId), nsAutoString(aOrigin), nsAutoString(aDeviceId))); } NS_IMETHODIMP PresentationIPCService::SendSessionMessage(const nsAString& aSessionId, + uint8_t aRole, nsIInputStream* aStream) { MOZ_ASSERT(!aSessionId.IsEmpty()); MOZ_ASSERT(aStream); mozilla::ipc::OptionalInputStreamParams stream; nsTArray<mozilla::ipc::FileDescriptor> fds; SerializeInputStream(aStream, stream, fds); MOZ_ASSERT(fds.IsEmpty()); - return SendRequest(nullptr, SendSessionMessageRequest(nsAutoString(aSessionId), stream)); + return SendRequest(nullptr, SendSessionMessageRequest(nsAutoString(aSessionId), aRole, stream)); } NS_IMETHODIMP -PresentationIPCService::CloseSession(const nsAString& aSessionId) +PresentationIPCService::CloseSession(const nsAString& aSessionId, + uint8_t aRole) { MOZ_ASSERT(!aSessionId.IsEmpty()); - return SendRequest(nullptr, CloseSessionRequest(nsAutoString(aSessionId))); + return SendRequest(nullptr, CloseSessionRequest(nsAutoString(aSessionId), aRole)); } NS_IMETHODIMP -PresentationIPCService::TerminateSession(const nsAString& aSessionId) +PresentationIPCService::TerminateSession(const nsAString& aSessionId, + uint8_t aRole) { MOZ_ASSERT(!aSessionId.IsEmpty()); - return SendRequest(nullptr, TerminateSessionRequest(nsAutoString(aSessionId))); + return SendRequest(nullptr, TerminateSessionRequest(nsAutoString(aSessionId), aRole)); } nsresult PresentationIPCService::SendRequest(nsIPresentationServiceCallback* aCallback, const PresentationIPCRequest& aRequest) { if (sPresentationChild) { PresentationRequestChild* actor = new PresentationRequestChild(aCallback); @@ -123,38 +126,40 @@ PresentationIPCService::UnregisterAvaila if (sPresentationChild) { NS_WARN_IF(!sPresentationChild->SendUnregisterAvailabilityHandler()); } return NS_OK; } NS_IMETHODIMP PresentationIPCService::RegisterSessionListener(const nsAString& aSessionId, + uint8_t aRole, nsIPresentationSessionListener* aListener) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aListener); mSessionListeners.Put(aSessionId, aListener); if (sPresentationChild) { - NS_WARN_IF(!sPresentationChild->SendRegisterSessionHandler(nsAutoString(aSessionId))); + NS_WARN_IF(!sPresentationChild->SendRegisterSessionHandler(nsAutoString(aSessionId), aRole)); } return NS_OK; } NS_IMETHODIMP -PresentationIPCService::UnregisterSessionListener(const nsAString& aSessionId) +PresentationIPCService::UnregisterSessionListener(const nsAString& aSessionId, + uint8_t aRole) { MOZ_ASSERT(NS_IsMainThread()); - UntrackSessionInfo(aSessionId); + UntrackSessionInfo(aSessionId, aRole); mSessionListeners.Remove(aSessionId); if (sPresentationChild) { - NS_WARN_IF(!sPresentationChild->SendUnregisterSessionHandler(nsAutoString(aSessionId))); + NS_WARN_IF(!sPresentationChild->SendUnregisterSessionHandler(nsAutoString(aSessionId), aRole)); } return NS_OK; } NS_IMETHODIMP PresentationIPCService::RegisterRespondingListener(uint64_t aWindowId, nsIPresentationRespondingListener* aListener) { @@ -261,17 +266,18 @@ PresentationIPCService::NotifyReceiverRe // Release mCallback after using aSessionId // because aSessionId is held by mCallback. mCallback = nullptr; return NS_OK; } NS_IMETHODIMP -PresentationIPCService::UntrackSessionInfo(const nsAString& aSessionId) +PresentationIPCService::UntrackSessionInfo(const nsAString& aSessionId, + uint8_t aRole) { // Remove the OOP responding info (if it has never been used). uint64_t windowId = 0; if(mRespondingWindowIds.Get(aSessionId, &windowId)) { mRespondingWindowIds.Remove(aSessionId); mRespondingSessionIds.Remove(windowId); }
--- a/dom/presentation/ipc/PresentationParent.cpp +++ b/dom/presentation/ipc/PresentationParent.cpp @@ -40,20 +40,27 @@ PresentationParent::Init() return NS_WARN_IF(!mService) ? false : true; } void PresentationParent::ActorDestroy(ActorDestroyReason aWhy) { mActorDestroyed = true; - for (uint32_t i = 0; i < mSessionIds.Length(); i++) { - NS_WARN_IF(NS_FAILED(mService->UnregisterSessionListener(mSessionIds[i]))); + for (uint32_t i = 0; i < mSessionIdsAtController.Length(); i++) { + NS_WARN_IF(NS_FAILED(mService-> + UnregisterSessionListener(mSessionIdsAtController[i], nsIPresentationService::ROLE_CONTROLLER))); } - mSessionIds.Clear(); + mSessionIdsAtController.Clear(); + + for (uint32_t i = 0; i < mSessionIdsAtReceiver.Length(); i++) { + NS_WARN_IF(NS_FAILED(mService-> + UnregisterSessionListener(mSessionIdsAtReceiver[i], nsIPresentationService::ROLE_RECEIVER))); + } + mSessionIdsAtReceiver.Clear(); for (uint32_t i = 0; i < mWindowIds.Length(); i++) { NS_WARN_IF(NS_FAILED(mService->UnregisterRespondingListener(mWindowIds[i]))); } mWindowIds.Clear(); mService->UnregisterAvailabilityListener(this); mService = nullptr; @@ -123,38 +130,48 @@ bool PresentationParent::RecvUnregisterAvailabilityHandler() { MOZ_ASSERT(mService); NS_WARN_IF(NS_FAILED(mService->UnregisterAvailabilityListener(this))); return true; } /* virtual */ bool -PresentationParent::RecvRegisterSessionHandler(const nsString& aSessionId) +PresentationParent::RecvRegisterSessionHandler(const nsString& aSessionId, + const uint8_t& aRole) { MOZ_ASSERT(mService); // Validate the accessibility (primarily for receiver side) so that a // compromised child process can't fake the ID. if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())-> - IsSessionAccessible(aSessionId, OtherPid()))) { + IsSessionAccessible(aSessionId, aRole, OtherPid()))) { return true; } - mSessionIds.AppendElement(aSessionId); - NS_WARN_IF(NS_FAILED(mService->RegisterSessionListener(aSessionId, this))); + if (nsIPresentationService::ROLE_CONTROLLER == aRole) { + mSessionIdsAtController.AppendElement(aSessionId); + } else { + mSessionIdsAtReceiver.AppendElement(aSessionId); + } + NS_WARN_IF(NS_FAILED(mService->RegisterSessionListener(aSessionId, aRole, this))); return true; } /* virtual */ bool -PresentationParent::RecvUnregisterSessionHandler(const nsString& aSessionId) +PresentationParent::RecvUnregisterSessionHandler(const nsString& aSessionId, + const uint8_t& aRole) { MOZ_ASSERT(mService); - mSessionIds.RemoveElement(aSessionId); - NS_WARN_IF(NS_FAILED(mService->UnregisterSessionListener(aSessionId))); + if (nsIPresentationService::ROLE_CONTROLLER == aRole) { + mSessionIdsAtController.RemoveElement(aSessionId); + } else { + mSessionIdsAtReceiver.RemoveElement(aSessionId); + } + NS_WARN_IF(NS_FAILED(mService->UnregisterSessionListener(aSessionId, aRole))); return true; } /* virtual */ bool PresentationParent::RecvRegisterRespondingHandler(const uint64_t& aWindowId) { MOZ_ASSERT(mService); @@ -258,65 +275,65 @@ PresentationRequestParent::DoRequest(con nsresult PresentationRequestParent::DoRequest(const SendSessionMessageRequest& aRequest) { MOZ_ASSERT(mService); // Validate the accessibility (primarily for receiver side) so that a // compromised child process can't fake the ID. if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())-> - IsSessionAccessible(aRequest.sessionId(), OtherPid()))) { + IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) { return NotifyError(NS_ERROR_DOM_SECURITY_ERR); } nsTArray<mozilla::ipc::FileDescriptor> fds; nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(aRequest.data(), fds); if(NS_WARN_IF(!stream)) { return NotifyError(NS_ERROR_NOT_AVAILABLE); } - nsresult rv = mService->SendSessionMessage(aRequest.sessionId(), stream); + nsresult rv = mService->SendSessionMessage(aRequest.sessionId(), aRequest.role(), stream); if (NS_WARN_IF(NS_FAILED(rv))) { return NotifyError(rv); } return NotifySuccess(); } nsresult PresentationRequestParent::DoRequest(const CloseSessionRequest& aRequest) { MOZ_ASSERT(mService); // Validate the accessibility (primarily for receiver side) so that a // compromised child process can't fake the ID. if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())-> - IsSessionAccessible(aRequest.sessionId(), OtherPid()))) { + IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) { return NotifyError(NS_ERROR_DOM_SECURITY_ERR); } - nsresult rv = mService->CloseSession(aRequest.sessionId()); + nsresult rv = mService->CloseSession(aRequest.sessionId(), aRequest.role()); if (NS_WARN_IF(NS_FAILED(rv))) { return NotifyError(rv); } return NotifySuccess(); } nsresult PresentationRequestParent::DoRequest(const TerminateSessionRequest& aRequest) { MOZ_ASSERT(mService); // Validate the accessibility (primarily for receiver side) so that a // compromised child process can't fake the ID. if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())-> - IsSessionAccessible(aRequest.sessionId(), OtherPid()))) { + IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) { return NotifyError(NS_ERROR_DOM_SECURITY_ERR); } - nsresult rv = mService->TerminateSession(aRequest.sessionId()); + nsresult rv = mService->TerminateSession(aRequest.sessionId(), aRequest.role()); if (NS_WARN_IF(NS_FAILED(rv))) { return NotifyError(rv); } return NotifySuccess(); } NS_IMETHODIMP PresentationRequestParent::NotifySuccess()
--- a/dom/presentation/ipc/PresentationParent.h +++ b/dom/presentation/ipc/PresentationParent.h @@ -43,32 +43,35 @@ public: DeallocPPresentationRequestParent(PPresentationRequestParent* aActor) override; virtual bool Recv__delete__() override; virtual bool RecvRegisterAvailabilityHandler() override; virtual bool RecvUnregisterAvailabilityHandler() override; - virtual bool RecvRegisterSessionHandler(const nsString& aSessionId) override; + virtual bool RecvRegisterSessionHandler(const nsString& aSessionId, + const uint8_t& aRole) override; - virtual bool RecvUnregisterSessionHandler(const nsString& aSessionId) override; + virtual bool RecvUnregisterSessionHandler(const nsString& aSessionId, + const uint8_t& aRole) override; virtual bool RecvRegisterRespondingHandler(const uint64_t& aWindowId) override; virtual bool RecvUnregisterRespondingHandler(const uint64_t& aWindowId) override; virtual bool RecvNotifyReceiverReady(const nsString& aSessionId) override; private: virtual ~PresentationParent(); bool mActorDestroyed; nsCOMPtr<nsIPresentationService> mService; - nsTArray<nsString> mSessionIds; + nsTArray<nsString> mSessionIdsAtController; + nsTArray<nsString> mSessionIdsAtReceiver; nsTArray<uint64_t> mWindowIds; }; class PresentationRequestParent final : public PPresentationRequestParent , public nsIPresentationServiceCallback { friend class PresentationParent;