Backed out changeset dfe4cc7062d1 (bug 1148307)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Mon, 11 Apr 2016 13:12:26 +0200
changeset 292602 721b3076b9656e03904cd56acb619a45979f1d7a
parent 292601 699007f8060a82578d0f19afbe18093387e4c92a
child 292603 6004772c0cf42aefff66ed2213bb07ec53fee761
push idunknown
push userunknown
push dateunknown
bugs1148307
milestone48.0a1
backs outdfe4cc7062d1954f3ce54a5e330375442766f9bd
Backed out changeset dfe4cc7062d1 (bug 1148307)
dom/presentation/PresentationConnection.cpp
dom/presentation/PresentationService.cpp
dom/presentation/PresentationSessionInfo.cpp
dom/presentation/PresentationSessionInfo.h
dom/presentation/PresentationTCPSessionTransport.cpp
dom/presentation/interfaces/nsIPresentationService.idl
dom/presentation/interfaces/nsIPresentationSessionTransport.idl
dom/presentation/ipc/PPresentation.ipdl
dom/presentation/ipc/PresentationIPCService.cpp
dom/presentation/ipc/PresentationParent.cpp
dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
dom/presentation/tests/xpcshell/test_presentation_session_transport.js
--- a/dom/presentation/PresentationConnection.cpp
+++ b/dom/presentation/PresentationConnection.cpp
@@ -113,32 +113,47 @@ PresentationConnection::GetId(nsAString&
 PresentationConnectionState
 PresentationConnection::State() const
 {
   return mState;
 }
 
 void
 PresentationConnection::Send(const nsAString& aData,
-                             ErrorResult& aRv)
+                          ErrorResult& aRv)
 {
   // Sending is not allowed if the session is not connected.
   if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
+  nsresult rv;
+  nsCOMPtr<nsIStringInputStream> stream =
+    do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
+  if(NS_WARN_IF(NS_FAILED(rv))) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
+
+  NS_ConvertUTF16toUTF8 msgString(aData);
+  rv = stream->SetData(msgString.BeginReading(), msgString.Length());
+  if(NS_WARN_IF(NS_FAILED(rv))) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
+
   nsCOMPtr<nsIPresentationService> service =
     do_GetService(PRESENTATION_SERVICE_CONTRACTID);
   if(NS_WARN_IF(!service)) {
     aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
     return;
   }
 
-  nsresult rv = service->SendSessionMessage(mId, aData);
+  rv = service->SendSessionMessage(mId, stream);
   if(NS_WARN_IF(NS_FAILED(rv))) {
     aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
   }
 }
 
 void
 PresentationConnection::Close(ErrorResult& aRv)
 {
@@ -166,17 +181,17 @@ PresentationConnection::Terminate(ErrorR
     return;
   }
 
   NS_WARN_IF(NS_FAILED(service->TerminateSession(mId)));
 }
 
 NS_IMETHODIMP
 PresentationConnection::NotifyStateChange(const nsAString& aSessionId,
-                                          uint16_t aState)
+                                       uint16_t aState)
 {
   if (!aSessionId.Equals(mId)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   PresentationConnectionState state;
   switch (aState) {
     case nsIPresentationSessionListener::STATE_CONNECTED:
@@ -213,17 +228,17 @@ PresentationConnection::NotifyStateChang
     }
   }
 
   return DispatchStateChangeEvent();
 }
 
 NS_IMETHODIMP
 PresentationConnection::NotifyMessage(const nsAString& aSessionId,
-                                      const nsACString& aData)
+                                   const nsACString& aData)
 {
   if (!aSessionId.Equals(mId)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // No message should be expected when the session is not connected.
   if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
--- a/dom/presentation/PresentationService.cpp
+++ b/dom/presentation/PresentationService.cpp
@@ -455,28 +455,28 @@ 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,
-                                        const nsAString& aData)
+                                        nsIInputStream* aStream)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!aData.IsEmpty());
+  MOZ_ASSERT(aStream);
   MOZ_ASSERT(!aSessionId.IsEmpty());
 
   RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId);
   if (NS_WARN_IF(!info)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  return info->Send(aData);
+  return info->Send(aStream);
 }
 
 NS_IMETHODIMP
 PresentationService::CloseSession(const nsAString& aSessionId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!aSessionId.IsEmpty());
 
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -261,17 +261,17 @@ PresentationSessionInfo::SetListener(nsI
     // the listener has registered. So notify the listener of the state change.
     return mListener->NotifyStateChange(mSessionId, mState);
   }
 
   return NS_OK;
 }
 
 nsresult
-PresentationSessionInfo::Send(const nsAString& aData)
+PresentationSessionInfo::Send(nsIInputStream* aData)
 {
   if (NS_WARN_IF(!IsSessionReady())) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
--- a/dom/presentation/PresentationSessionInfo.h
+++ b/dom/presentation/PresentationSessionInfo.h
@@ -87,17 +87,17 @@ public:
     }
 
     mControlChannel = aControlChannel;
     if (mControlChannel) {
       mControlChannel->SetListener(this);
     }
   }
 
-  nsresult Send(const nsAString& aData);
+  nsresult Send(nsIInputStream* aData);
 
   nsresult Close(nsresult aReason,
                  uint32_t aState);
 
   nsresult ReplyError(nsresult aReason);
 
   virtual bool IsAccessible(base::ProcessId aProcessId);
 
--- a/dom/presentation/PresentationTCPSessionTransport.cpp
+++ b/dom/presentation/PresentationTCPSessionTransport.cpp
@@ -102,33 +102,31 @@ PresentationTCPSessionTransport::BuildTC
   }
   mListener = aListener;
 
   nsresult rv = CreateStream();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
+  SetReadyState(ReadyState::OPEN);
+
+  if (IsReadyToNotifyData()) {
+    return CreateInputStreamPump();
+  }
+
   mType = nsIPresentationSessionTransportBuilder::TYPE_SENDER;
 
   nsCOMPtr<nsIPresentationSessionTransport> sessionTransport = do_QueryObject(this);
-  nsCOMPtr<nsIRunnable> onSessionTransportRunnable =
+  nsCOMPtr<nsIRunnable> runnable =
     NS_NewRunnableMethodWithArgs
       <nsIPresentationSessionTransport*>(mListener,
                                          &nsIPresentationSessionTransportBuilderListener::OnSessionTransport,
                                          sessionTransport);
-
-  NS_DispatchToCurrentThread(onSessionTransportRunnable);
-
-
-  nsCOMPtr<nsIRunnable> setReadyStateRunnable =
-    NS_NewRunnableMethodWithArgs<ReadyState>(this,
-                                             &PresentationTCPSessionTransport::SetReadyState,
-                                             ReadyState::OPEN);
-  return NS_DispatchToCurrentThread(setReadyStateRunnable);
+  return NS_DispatchToCurrentThread(runnable);
 }
 
 NS_IMETHODIMP
 PresentationTCPSessionTransport::BuildTCPReceiverTransport(nsIPresentationChannelDescription* aDescription,
                                                            nsIPresentationSessionTransportBuilderListener* aListener)
 {
   if (NS_WARN_IF(!aDescription)) {
     return NS_ERROR_INVALID_ARG;
@@ -269,20 +267,16 @@ PresentationTCPSessionTransport::CreateS
   }
 
   return NS_OK;
 }
 
 nsresult
 PresentationTCPSessionTransport::CreateInputStreamPump()
 {
-  if (NS_WARN_IF(mInputStreamPump)) {
-    return NS_OK;
-  }
-
   nsresult rv;
   mInputStreamPump = do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = mInputStreamPump->Init(mSocketInputStream, -1, -1, 0, 0, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -382,36 +376,23 @@ PresentationTCPSessionTransport::NotifyC
   if (mReadyState == ReadyState::CLOSING) {
     mSocketOutputStream->Close();
     mCloseStatus = NS_OK;
     SetReadyState(ReadyState::CLOSED);
   }
 }
 
 NS_IMETHODIMP
-PresentationTCPSessionTransport::Send(const nsAString& aData)
+PresentationTCPSessionTransport::Send(nsIInputStream* aData)
 {
   if (NS_WARN_IF(mReadyState != ReadyState::OPEN)) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
-  nsresult rv;
-  nsCOMPtr<nsIStringInputStream> stream =
-    do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
-  if(NS_WARN_IF(NS_FAILED(rv))) {
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
-  }
-
-  NS_ConvertUTF16toUTF8 msgString(aData);
-  rv = stream->SetData(msgString.BeginReading(), msgString.Length());
-  if(NS_WARN_IF(NS_FAILED(rv))) {
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
-  }
-
-  mMultiplexStream->AppendStream(stream);
+  mMultiplexStream->AppendStream(aData);
 
   EnsureCopying();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationTCPSessionTransport::Close(nsresult aReason)
@@ -439,32 +420,20 @@ PresentationTCPSessionTransport::Close(n
   return NS_OK;
 }
 
 void
 PresentationTCPSessionTransport::SetReadyState(ReadyState aReadyState)
 {
   mReadyState = aReadyState;
 
-  if (mReadyState == ReadyState::OPEN) {
-    if (IsReadyToNotifyData()) {
-      CreateInputStreamPump();
-    }
-
-    if (NS_WARN_IF(!mCallback)) {
-      return;
-    }
-
+  if (mReadyState == ReadyState::OPEN && mCallback) {
     // Notify the transport channel is ready.
     NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportReady()));
   } else if (mReadyState == ReadyState::CLOSED && mCallback) {
-    if (NS_WARN_IF(!mCallback)) {
-      return;
-    }
-
     // Notify the transport channel has been shut down.
     NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportClosed(mCloseStatus)));
     mCallback = nullptr;
   }
 }
 
 // nsITransportEventSink
 NS_IMETHODIMP
@@ -478,16 +447,20 @@ PresentationTCPSessionTransport::OnTrans
   MOZ_ASSERT(NS_IsMainThread());
 
   if (aStatus != NS_NET_STATUS_CONNECTED_TO) {
     return NS_OK;
   }
 
   SetReadyState(ReadyState::OPEN);
 
+  if (IsReadyToNotifyData()) {
+    return CreateInputStreamPump();
+  }
+
   return NS_OK;
 }
 
 // nsIInputStreamCallback
 NS_IMETHODIMP
 PresentationTCPSessionTransport::OnInputStreamReady(nsIAsyncInputStream* aStream)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/presentation/interfaces/nsIPresentationService.idl
+++ b/dom/presentation/interfaces/nsIPresentationService.idl
@@ -28,17 +28,17 @@ interface nsIPresentationServiceCallback
   /*
    * Called when the operation fails.
    *
    * @param error: error message.
    */
   void notifyError(in nsresult error);
 };
 
-[scriptable, uuid(61864149-9838-4aa1-a21a-63eaf0b84a8c)]
+[scriptable, uuid(2e360359-c45c-4949-bf95-410242ce483f)]
 interface nsIPresentationService : nsISupports
 {
   /*
    * 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.
@@ -52,23 +52,23 @@ interface nsIPresentationService : nsISu
    */
   void startSession(in DOMString url,
                     in DOMString sessionId,
                     in DOMString origin,
                     in DOMString deviceId,
                     in nsIPresentationServiceCallback callback);
 
   /*
-   * Send the message to the session.
+   * Send the message wrapped with an input stream to the session.
    *
    * @param sessionId: An ID to identify presentation session.
-   * @param data: the message being sent out.
+   * @param stream: The message is converted to an input stream.
    */
   void sendSessionMessage(in DOMString sessionId,
-                          in DOMString data);
+                          in nsIInputStream stream);
 
   /*
    * Close the session.
    *
    * @param sessionId: An ID to identify presentation session.
    */
   void closeSession(in DOMString sessionId);
 
--- a/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
+++ b/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
@@ -21,17 +21,17 @@ interface nsIPresentationSessionTranspor
   void notifyTransportReady();
   void notifyTransportClosed(in nsresult reason);
   void notifyData(in ACString data);
 };
 
 /*
  * App-to-App transport channel for the presentation session.
  */
-[scriptable, uuid(670b7e1b-65be-42b6-a596-be571907fa18)]
+[scriptable, uuid(7af8556e-e37b-4ca1-a5dd-029567172863)]
 interface nsIPresentationSessionTransport : nsISupports
 {
   // Should be set once the underlying session transport is built
   attribute nsIPresentationSessionTransportCallback callback;
 
   // valid for TCP session transport
   readonly attribute nsINetAddr selfAddress;
 
@@ -41,16 +41,16 @@ interface nsIPresentationSessionTranspor
    * Should set callback before |enableDataNotification| is called.
    */
   void enableDataNotification();
 
   /*
    * Send message to the remote endpoint.
    * @param data The message to send.
    */
-  void send(in DOMString data);
+  void send(in nsIInputStream data);
 
   /*
    * Close this session transport.
    * @param reason The reason for closing this session transport.
    */
   void close(in nsresult reason);
 };
--- a/dom/presentation/ipc/PPresentation.ipdl
+++ b/dom/presentation/ipc/PPresentation.ipdl
@@ -18,17 +18,17 @@ struct StartSessionRequest
   nsString sessionId;
   nsString origin;
   nsString deviceId;
 };
 
 struct SendSessionMessageRequest
 {
   nsString sessionId;
-  nsString data;
+  InputStreamParams data;
 };
 
 struct CloseSessionRequest
 {
   nsString sessionId;
 };
 
 struct TerminateSessionRequest
--- a/dom/presentation/ipc/PresentationIPCService.cpp
+++ b/dom/presentation/ipc/PresentationIPCService.cpp
@@ -55,23 +55,27 @@ PresentationIPCService::StartSession(con
   return SendRequest(aCallback, StartSessionRequest(nsAutoString(aUrl),
                                                     nsAutoString(aSessionId),
                                                     nsAutoString(aOrigin),
                                                     nsAutoString(aDeviceId)));
 }
 
 NS_IMETHODIMP
 PresentationIPCService::SendSessionMessage(const nsAString& aSessionId,
-                                           const nsAString& aData)
+                                           nsIInputStream* aStream)
 {
   MOZ_ASSERT(!aSessionId.IsEmpty());
-  MOZ_ASSERT(!aData.IsEmpty());
+  MOZ_ASSERT(aStream);
 
-  return SendRequest(nullptr, SendSessionMessageRequest(nsAutoString(aSessionId),
-                                                        nsAutoString(aData)));
+  mozilla::ipc::OptionalInputStreamParams stream;
+  nsTArray<mozilla::ipc::FileDescriptor> fds;
+  SerializeInputStream(aStream, stream, fds);
+  MOZ_ASSERT(fds.IsEmpty());
+
+  return SendRequest(nullptr, SendSessionMessageRequest(nsAutoString(aSessionId), stream));
 }
 
 NS_IMETHODIMP
 PresentationIPCService::CloseSession(const nsAString& aSessionId)
 {
   MOZ_ASSERT(!aSessionId.IsEmpty());
 
   return SendRequest(nullptr, CloseSessionRequest(nsAutoString(aSessionId)));
--- a/dom/presentation/ipc/PresentationParent.cpp
+++ b/dom/presentation/ipc/PresentationParent.cpp
@@ -262,18 +262,23 @@ PresentationRequestParent::DoRequest(con
 
   // 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()))) {
     return NotifyError(NS_ERROR_DOM_SECURITY_ERR);
   }
 
-  nsresult rv = mService->SendSessionMessage(aRequest.sessionId(),
-                                             aRequest.data());
+  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);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return NotifyError(rv);
   }
   return NotifySuccess();
 }
 
 nsresult
 PresentationRequestParent::DoRequest(const CloseSessionRequest& aRequest)
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
@@ -239,17 +239,21 @@ const mockedSessionTransport = {
 
     this._listener.onSessionTransport(this);
     this._listener = null;
   },
   enableDataNotification: function() {
     sendAsyncMessage('data-transport-notification-enabled');
   },
   send: function(data) {
-    sendAsyncMessage('message-sent', data);
+    var binaryStream = Cc["@mozilla.org/binaryinputstream;1"].
+                       createInstance(Ci.nsIBinaryInputStream);
+    binaryStream.setInputStream(data);
+    var message = binaryStream.readBytes(binaryStream.available());
+    sendAsyncMessage('message-sent', message);
   },
   close: function(reason) {
     sendAsyncMessage('data-transport-closed', reason);
     this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportClosed(reason);
   },
   simulateTransportReady: function() {
     this._callback.QueryInterface(Ci.nsIPresentationSessionTransportCallback).notifyTransportReady();
   },
--- a/dom/presentation/tests/xpcshell/test_presentation_session_transport.js
+++ b/dom/presentation/tests/xpcshell/test_presentation_session_transport.js
@@ -156,23 +156,29 @@ function selfAddress() {
   Assert.ok(clientSelfAddress.port, "The port of client transport should be set.");
 
   run_next_test();
 }
 
 // Test the client sends a message and then a corresponding notification gets
 // triggered at the server side.
 function clientSendMessage() {
-  clientTransport.send(clientMessage);
+  var stream = Cc["@mozilla.org/io/string-input-stream;1"]
+                 .createInstance(Ci.nsIStringInputStream);
+  stream.setData(clientMessage, clientMessage.length);
+  clientTransport.send(stream);
 }
 
 // Test the server sends a message an then a corresponding notification gets
 // triggered at the client side.
 function serverSendMessage() {
-  serverTransport.send(serverMessage);
+  var stream = Cc["@mozilla.org/io/string-input-stream;1"]
+                 .createInstance(Ci.nsIStringInputStream);
+  stream.setData(serverMessage, serverMessage.length);
+  serverTransport.send(stream);
   // The client enables data notification even after the incoming message has
   // been sent, and should still be able to consume it.
   clientTransport.enableDataNotification();
 }
 
 function transportClose() {
   clientTransport.close(Cr.NS_OK);
 }