Bug 800247: Add disconnect events to UnixSocket, update Bluetooth*Manager; r=echou r=cjones
authorKyle Machulis <kyle@nonpolynomial.com>
Fri, 12 Oct 2012 11:38:14 -0700
changeset 110294 9d5627f5882bea4e60bdc44ad3bf157c42ccbdd5
parent 110293 42e029cb8b33f02d2a4a3dc090f1eff3d405f583
child 110295 34b1f3ed81136a0810d2f936b78ec75d9df50e2f
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersechou, cjones
bugs800247
milestone19.0a1
Bug 800247: Add disconnect events to UnixSocket, update Bluetooth*Manager; r=echou r=cjones
dom/bluetooth/BluetoothHfpManager.cpp
dom/bluetooth/BluetoothHfpManager.h
dom/bluetooth/BluetoothOppManager.cpp
dom/bluetooth/BluetoothOppManager.h
dom/bluetooth/BluetoothScoManager.cpp
dom/bluetooth/BluetoothScoManager.h
ipc/unixsocket/UnixSocket.cpp
ipc/unixsocket/UnixSocket.h
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -778,8 +778,14 @@ BluetoothHfpManager::OnConnectSuccess()
 
 void
 BluetoothHfpManager::OnConnectError()
 {
   CloseSocket();
   // If connecting for some reason didn't work, restart listening
   Listen();
 }
+
+void
+BluetoothHfpManager::OnDisconnect()
+{
+  NS_WARNING("GOT DISCONNECT!");
+}
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -41,16 +41,17 @@ private:
   nsresult HandleVolumeChanged(const nsAString& aData);
   nsresult HandleShutdown();
   bool Init();
   void Cleanup();
   void NotifyDialer(const nsAString& aCommand);
   void NotifySettings(const bool aConnected);
   virtual void OnConnectSuccess() MOZ_OVERRIDE;
   virtual void OnConnectError() MOZ_OVERRIDE;
+  virtual void OnDisconnect() MOZ_OVERRIDE;
 
   int mCurrentVgs;
   int mCurrentCallIndex;
   int mCurrentCallState;
   int mCall;
   int mCallSetup;
   int mCallHeld;
   nsAutoPtr<BluetoothRilListener> mListener;
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -651,8 +651,13 @@ void
 BluetoothOppManager::OnConnectSuccess()
 {
 }
 
 void
 BluetoothOppManager::OnConnectError()
 {
 }
+
+void
+BluetoothOppManager::OnDisconnect()
+{
+}
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -75,16 +75,17 @@ private:
                       bool aReceived,
                       uint32_t aProcessedLength,
                       uint32_t aFileLength);
   void ReplyToConnect();
   void ReplyToDisconnect();
   void ReplyToPut(bool aFinal);
   virtual void OnConnectSuccess() MOZ_OVERRIDE;
   virtual void OnConnectError() MOZ_OVERRIDE;
+  virtual void OnDisconnect() MOZ_OVERRIDE;
 
   bool mConnected;
   int mConnectionId;
   int mLastCommand;
   uint8_t mRemoteObexVersion;
   uint8_t mRemoteConnectionFlags;
   int mRemoteMaxPacketLength;
   bool mAbortFlag;
--- a/dom/bluetooth/BluetoothScoManager.cpp
+++ b/dom/bluetooth/BluetoothScoManager.cpp
@@ -213,8 +213,13 @@ void
 BluetoothScoManager::OnConnectSuccess()
 {
 }
 
 void
 BluetoothScoManager::OnConnectError()
 {
 }
+
+void
+BluetoothScoManager::OnDisconnect()
+{
+}
--- a/dom/bluetooth/BluetoothScoManager.h
+++ b/dom/bluetooth/BluetoothScoManager.h
@@ -34,14 +34,15 @@ private:
   friend class BluetoothScoManagerObserver;
   BluetoothScoManager();
   bool Init();
   void Cleanup();
   nsresult HandleShutdown();
   void CreateScoSocket(const nsAString& aDevicePath);
   virtual void OnConnectSuccess() MOZ_OVERRIDE;
   virtual void OnConnectError() MOZ_OVERRIDE;
+  virtual void OnDisconnect() MOZ_OVERRIDE;
   bool mConnected;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/ipc/unixsocket/UnixSocket.cpp
+++ b/ipc/unixsocket/UnixSocket.cpp
@@ -260,16 +260,18 @@ public:
       // Since we've already explicitly closed and the close happened before
       // this, this isn't really an error. Since we've warned, return OK.
       return NS_OK;
     }
     if (mEvent == CONNECT_SUCCESS) {
       mImpl->mConsumer->NotifySuccess();
     } else if (mEvent == CONNECT_ERROR) {
       mImpl->mConsumer->NotifyError();
+    } else if (mEvent == DISCONNECT) {
+      mImpl->mConsumer->NotifyDisconnect();
     }
     return NS_OK;
   }
 private:
   UnixSocketImpl* mImpl;
   SocketEvent mEvent;
 };
 
@@ -321,16 +323,36 @@ public:
   }
 
 private:
   nsRefPtr<UnixSocketConsumer> mConsumer;
   UnixSocketImpl* mImpl;
   UnixSocketRawData* mData;
 };
 
+class SocketCloseTask : public nsRunnable
+{
+public:
+  SocketCloseTask(UnixSocketImpl* aImpl)
+    : mImpl(aImpl)
+  {
+    MOZ_ASSERT(aImpl);
+  }
+
+  NS_IMETHOD
+  Run()
+  {
+    mImpl->mConsumer->CloseSocket();
+    return NS_OK;
+  }
+
+private:
+  UnixSocketImpl* mImpl;
+};
+
 class StartImplReadingTask : public Task
 {
 public:
   StartImplReadingTask(UnixSocketImpl* aImpl)
     : mImpl(aImpl)
   {
   }
 
@@ -554,29 +576,31 @@ UnixSocketConsumer::SendSocketData(const
   XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
                                    new SocketSendTask(this, mImpl, d));
   return true;
 }
 
 void
 UnixSocketConsumer::CloseSocket()
 {
+  // Needed due to refcount change
+  MOZ_ASSERT(NS_IsMainThread());
   if (!mImpl) {
     return;
   }
   UnixSocketImpl* impl = mImpl;
+  // To make sure the owner doesn't die on the IOThread, remove pointer here
   mImpl = nullptr;
+  // Line it up to be destructed on the IO Thread
   impl->mConsumer.forget();
   impl->StopTask();
-  // To make sure the owner doesn't die on the IOThread, remove pointer here
-  // Line it up to be destructed on the IO Thread
-  // Kill our pointer to it
   XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
                                    NewRunnableFunction(DestroyImpl,
                                                        impl));
+  NotifyDisconnect();
 }
 
 void
 UnixSocketImpl::OnFileCanReadWithoutBlocking(int aFd)
 {
   // Keep reading data until either
   //
   //   - mIncoming is completely read
@@ -603,17 +627,18 @@ UnixSocketImpl::OnFileCanReadWithoutBloc
 #ifdef DEBUG
         NS_WARNING("Cannot read from network");
 #endif
         // At this point, assume that we can't actually access
         // the socket anymore
         mIncoming.forget();
         mReadWatcher.StopWatchingFileDescriptor();
         mWriteWatcher.StopWatchingFileDescriptor();
-        mConsumer->CloseSocket();
+        nsRefPtr<SocketCloseTask> t = new SocketCloseTask(this);
+        NS_DispatchToMainThread(t);
         return;
       }
       mIncoming->mData[ret] = 0;
       mIncoming->mSize = ret;
       nsRefPtr<SocketReceiveTask> t =
         new SocketReceiveTask(this, mIncoming.forget());
       NS_DispatchToMainThread(t);
       if (ret < ssize_t(UnixSocketRawData::MAX_DATA_SIZE)) {
@@ -678,16 +703,25 @@ UnixSocketConsumer::NotifySuccess()
 
 void
 UnixSocketConsumer::NotifyError()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mConnectionStatus = SOCKET_DISCONNECTED;
   OnConnectError();
 }
+
+void
+UnixSocketConsumer::NotifyDisconnect()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mConnectionStatus = SOCKET_DISCONNECTED;
+  OnDisconnect();
+}
+
 bool
 UnixSocketConsumer::ConnectSocket(UnixSocketConnector* aConnector,
                                   const char* aAddress)
 {
   MOZ_ASSERT(aConnector);
   MOZ_ASSERT(NS_IsMainThread());
   if (mImpl) {
     NS_WARNING("Socket already connecting/connected!");
--- a/ipc/unixsocket/UnixSocket.h
+++ b/ipc/unixsocket/UnixSocket.h
@@ -188,27 +188,35 @@ public:
    */
   virtual void OnConnectSuccess() = 0;
 
   /** 
    * Callback for socket connect/accept error. Will be run on main thread.
    */
   virtual void OnConnectError() = 0;
 
+  /** 
+   * Callback for socket disconnect. Will be run on main thread.
+   */
+  virtual void OnDisconnect() = 0;
 
   /** 
    * Called by implementation to notify consumer of success.
    */
   void NotifySuccess();
 
   /** 
    * Called by implementation to notify consumer of error.
    */
   void NotifyError();
 
+  /** 
+   * Called by implementation to notify consumer of disconnect.
+   */
+  void NotifyDisconnect();
 private:
   UnixSocketImpl* mImpl;
   SocketConnectionStatus mConnectionStatus;
 };
 
 } // namespace ipc
 } // namepsace mozilla