Bug 851046: Patch 4 - Apply BluetoothSocket to BluetoothOppManager; r=mrbkap
authorEric Chou <echou@mozilla.com>
Thu, 04 Apr 2013 17:25:44 -0700
changeset 138672 16108b4d0213f15614cc3bb93b5edaa3e8e1ba1c
parent 138671 9b22106f5492e10522296e22104076024ce935d8
child 138673 a18acbecddaa81e73f8b6748494a7040b5c74e3f
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs851046
milestone23.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
Bug 851046: Patch 4 - Apply BluetoothSocket to BluetoothOppManager; r=mrbkap
dom/bluetooth/BluetoothOppManager.cpp
dom/bluetooth/BluetoothOppManager.h
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -4,16 +4,17 @@
  * 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 "base/basictypes.h"
 #include "BluetoothOppManager.h"
 
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
+#include "BluetoothSocket.h"
 #include "BluetoothUtils.h"
 #include "BluetoothUuid.h"
 #include "ObexBase.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
@@ -79,17 +80,17 @@ namespace {
 static const uint32_t kUpdateProgressBase = 50 * 1024;
 
 /*
  * The format of the header of an PUT request is
  * [opcode:1][packet length:2][headerId:1][header length:2]
  */
 static const uint32_t kPutRequestHeaderSize = 6;
 
-StaticRefPtr<BluetoothOppManager> sInstance;
+StaticAutoPtr<BluetoothOppManager> sInstance;
 StaticRefPtr<BluetoothOppManagerObserver> sOppObserver;
 
 /*
  * FIXME / Bug 806749
  *
  * Currently Bluetooth*Manager inherits mozilla::ipc::UnixSocketConsumer,
  * which means that each Bluetooth*Manager can handle only one socket
  * connection at a time. We need to support concurrent multiple socket
@@ -189,28 +190,33 @@ public:
 private:
   nsCOMPtr<nsIInputStream> mInputStream;
   uint32_t mAvailablePacketSize;
 };
 
 class CloseSocketTask : public Task
 {
 public:
+  CloseSocketTask(BluetoothSocket* aSocket) : mSocket(aSocket)
+  {
+    MOZ_ASSERT(aSocket);
+  }
+
   void Run() MOZ_OVERRIDE
   {
-    if (!sInstance) {
-      NS_WARNING("BluetoothOppManager no longer exists, cannot close socket!");
-      return;
-    }
+    MOZ_ASSERT(NS_IsMainThread());
 
-    if (sInstance->GetConnectionStatus() ==
-          SocketConnectionStatus::SOCKET_CONNECTED) {
-      sInstance->CloseSocket();
+    if (mSocket->GetConnectionStatus() ==
+        SocketConnectionStatus::SOCKET_CONNECTED) {
+      mSocket->Disconnect();
     }
   }
+
+private:
+  nsRefPtr<BluetoothSocket> mSocket;
 };
 
 BluetoothOppManager::BluetoothOppManager() : mConnected(false)
                                            , mRemoteObexVersion(0)
                                            , mRemoteConnectionFlags(0)
                                            , mRemoteMaxPacketLength(0)
                                            , mLastCommand(0)
                                            , mPacketLeftLength(0)
@@ -218,50 +224,57 @@ BluetoothOppManager::BluetoothOppManager
                                            , mReceivedDataBufferOffset(0)
                                            , mAbortFlag(false)
                                            , mNewFileFlag(false)
                                            , mPutFinalFlag(false)
                                            , mSendTransferCompleteFlag(false)
                                            , mSuccessFlag(false)
                                            , mWaitingForConfirmationFlag(false)
 {
-  mConnectedDeviceAddress.AssignLiteral("00:00:00:00:00:00");
-  mSocketStatus = GetConnectionStatus();
+  mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
+
+  mSocket = new BluetoothSocket(this,
+                                BluetoothSocketType::RFCOMM,
+                                true,
+                                true);
+  mSocketStatus = mSocket->GetConnectionStatus();
 }
 
 BluetoothOppManager::~BluetoothOppManager()
 {
 }
 
 //static
 BluetoothOppManager*
 BluetoothOppManager::Get()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (sInstance == nullptr) {
+  if (!sInstance) {
     sInstance = new BluetoothOppManager();
   }
 
   return sInstance;
 }
 
 bool
 BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
                              BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED ||
-      GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTING) {
+  SocketConnectionStatus s = mSocket->GetConnectionStatus();
+
+  if (s == SocketConnectionStatus::SOCKET_CONNECTED ||
+      s == SocketConnectionStatus::SOCKET_CONNECTING) {
     NS_WARNING("BluetoothOppManager has been already connected");
     return false;
   }
 
-  CloseSocket();
+  Disconnect();
 
   BluetoothService* bs = BluetoothService::Get();
   if (!bs) {
     NS_WARNING("BluetoothService not available!");
     return false;
   }
 
   nsString uuid;
@@ -269,70 +282,58 @@ BluetoothOppManager::Connect(const nsASt
 
   mRunnable = aRunnable;
 
   nsresult rv = bs->GetSocketViaService(aDeviceObjectPath,
                                         uuid,
                                         BluetoothSocketType::RFCOMM,
                                         true,
                                         true,
-                                        this,
+                                        mSocket,
                                         mRunnable);
 
   return NS_FAILED(rv) ? false : true;
 }
 
 void
 BluetoothOppManager::Disconnect()
 {
-  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) {
-    NS_WARNING("BluetoothOppManager has been disconnected!");
-    return;
-  }
-
-  CloseSocket();
+  mSocket->Disconnect();
 }
 
 nsresult
 BluetoothOppManager::HandleShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   sInShutdown = true;
-  CloseSocket();
+  Disconnect();
   sInstance = nullptr;
   return NS_OK;
 }
 
 bool
 BluetoothOppManager::Listen()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_LISTENING) {
+  if (mSocket->GetConnectionStatus() ==
+      SocketConnectionStatus::SOCKET_LISTENING) {
     NS_WARNING("BluetoothOppManager has been already listening");
     return true;
   }
 
-  CloseSocket();
+  Disconnect();
 
-  BluetoothService* bs = BluetoothService::Get();
-  if (!bs) {
-    NS_WARNING("BluetoothService not available!");
+  if (!mSocket->Listen(BluetoothReservedChannels::CHANNEL_OPUSH)) {
+    NS_WARNING("[OPP] Can't listen on socket!");
     return false;
   }
 
-  nsresult rv =
-    bs->ListenSocketViaService(BluetoothReservedChannels::CHANNEL_OPUSH,
-                               BluetoothSocketType::RFCOMM,
-                               true,
-                               true,
-                               this);
-  mSocketStatus = GetConnectionStatus();
-
-  return NS_FAILED(rv) ? false : true;
+  mSocketStatus = mSocket->GetConnectionStatus();
+  return true;
 }
 
 bool
 BluetoothOppManager::SendFile(BlobParent* aActor)
 {
   if (mBlob) {
     // Means there's a sending process. Reply error.
     return false;
@@ -686,17 +687,18 @@ BluetoothOppManager::ServerDataHandler(U
     packetLength = mPacketLeftLength;
   } else {
     opCode = aMessage->mData[0];
     packetLength = (((int)aMessage->mData[1]) << 8) | aMessage->mData[2];
 
     // When there's a Put packet right after a PutFinal packet,
     // which means it's the start point of a new file.
     if (mPutFinalFlag &&
-        (opCode == ObexRequestCode::Put || opCode == ObexRequestCode::PutFinal)) {
+        (opCode == ObexRequestCode::Put ||
+         opCode == ObexRequestCode::PutFinal)) {
       mNewFileFlag = true;
       AfterFirstPut();
     }
   }
 
   ObexHeaderSet pktHeaders(opCode);
   if (opCode == ObexRequestCode::Connect) {
     // Section 3.3.1 "Connect", IrOBEX 1.2
@@ -859,17 +861,17 @@ BluetoothOppManager::ClientDataHandler(U
     SendDisconnectRequest();
     FileTransferComplete();
   } else if (mLastCommand == ObexRequestCode::Disconnect) {
     AfterOppDisconnected();
     // Most devices will directly terminate connection after receiving
     // Disconnect request, so we make a delay here. If the socket hasn't been
     // disconnected, we will close it.
     MessageLoop::current()->
-      PostDelayedTask(FROM_HERE, new CloseSocketTask(), 1000);
+      PostDelayedTask(FROM_HERE, new CloseSocketTask(mSocket), 1000);
   } else if (mLastCommand == ObexRequestCode::Connect) {
     MOZ_ASSERT(!sFileName.IsEmpty());
     MOZ_ASSERT(mBlob);
 
     AfterOppConnected();
 
     // Keep remote information
     mRemoteObexVersion = aMessage->mData[3];
@@ -952,17 +954,17 @@ BluetoothOppManager::SendConnectRequest(
   req[5] = BluetoothOppManager::MAX_PACKET_LENGTH >> 8;
   req[6] = (uint8_t)BluetoothOppManager::MAX_PACKET_LENGTH;
 
   SetObexPacketInfo(req, ObexRequestCode::Connect, index);
   mLastCommand = ObexRequestCode::Connect;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  SendSocketData(s);
+  mSocket->SendSocketData(s);
 }
 
 void
 BluetoothOppManager::SendPutHeaderRequest(const nsAString& aFileName,
                                           int aFileSize)
 {
   uint8_t* req = new uint8_t[mRemoteMaxPacketLength];
 
@@ -982,17 +984,17 @@ BluetoothOppManager::SendPutHeaderReques
   index += AppendHeaderName(&req[index], (char*)fileName, (len + 1) * 2);
   index += AppendHeaderLength(&req[index], aFileSize);
 
   SetObexPacketInfo(req, ObexRequestCode::Put, index);
   mLastCommand = ObexRequestCode::Put;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  SendSocketData(s);
+  mSocket->SendSocketData(s);
 
   delete [] fileName;
   delete [] req;
 }
 
 void
 BluetoothOppManager::SendPutRequest(uint8_t* aFileBody,
                                     int aFileBodyLength)
@@ -1012,17 +1014,17 @@ BluetoothOppManager::SendPutRequest(uint
   int index = 3;
   index += AppendHeaderBody(&req[index], aFileBody, aFileBodyLength);
 
   SetObexPacketInfo(req, ObexRequestCode::Put, index);
   mLastCommand = ObexRequestCode::Put;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  SendSocketData(s);
+  mSocket->SendSocketData(s);
 
   delete [] req;
 }
 
 void
 BluetoothOppManager::SendPutFinalRequest()
 {
   if (!mConnected) return;
@@ -1038,17 +1040,17 @@ BluetoothOppManager::SendPutFinalRequest
   int index = 3;
   uint8_t* req = new uint8_t[mRemoteMaxPacketLength];
   index += AppendHeaderEndOfBody(&req[index]);
   SetObexPacketInfo(req, ObexRequestCode::PutFinal, index);
   mLastCommand = ObexRequestCode::PutFinal;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  SendSocketData(s);
+  mSocket->SendSocketData(s);
 
   sWaitingToSendPutFinal = false;
 
   delete [] req;
 }
 
 void
 BluetoothOppManager::SendDisconnectRequest()
@@ -1058,33 +1060,33 @@ BluetoothOppManager::SendDisconnectReque
   uint8_t req[255];
   int index = 3;
 
   SetObexPacketInfo(req, ObexRequestCode::Disconnect, index);
   mLastCommand = ObexRequestCode::Disconnect;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  SendSocketData(s);
+  mSocket->SendSocketData(s);
 }
 
 void
 BluetoothOppManager::SendAbortRequest()
 {
   // Section 3.3.5 "Abort", IrOBEX 1.2
   // [opcode:1][length:2][Headers:var]
   uint8_t req[255];
   int index = 3;
 
   SetObexPacketInfo(req, ObexRequestCode::Abort, index);
   mLastCommand = ObexRequestCode::Abort;
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  SendSocketData(s);
+  mSocket->SendSocketData(s);
 }
 
 bool
 BluetoothOppManager::IsTransferring()
 {
   return (mConnected && !mSendTransferCompleteFlag);
 }
 
@@ -1104,17 +1106,17 @@ BluetoothOppManager::ReplyToConnect()
   req[4] = 0x00; // flag=0x00
   req[5] = BluetoothOppManager::MAX_PACKET_LENGTH >> 8;
   req[6] = (uint8_t)BluetoothOppManager::MAX_PACKET_LENGTH;
 
   SetObexPacketInfo(req, ObexResponseCode::Success, index);
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  SendSocketData(s);
+  mSocket->SendSocketData(s);
 }
 
 void
 BluetoothOppManager::ReplyToDisconnect()
 {
   if (!mConnected) return;
   mConnected = false;
 
@@ -1122,17 +1124,17 @@ BluetoothOppManager::ReplyToDisconnect()
   // [opcode:1][length:2][Headers:var]
   uint8_t req[255];
   int index = 3;
 
   SetObexPacketInfo(req, ObexResponseCode::Success, index);
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  SendSocketData(s);
+  mSocket->SendSocketData(s);
 }
 
 void
 BluetoothOppManager::ReplyToPut(bool aFinal, bool aContinue)
 {
   if (!mConnected) return;
 
   // Section 3.3.2 "Disconnect", IrOBEX 1.2
@@ -1153,17 +1155,17 @@ BluetoothOppManager::ReplyToPut(bool aFi
       SetObexPacketInfo(req,
                         ObexResponseCode::Unauthorized & (~FINAL_BIT),
                         index);
     }
   }
 
   UnixSocketRawData* s = new UnixSocketRawData(index);
   memcpy(s->mData, req, s->mSize);
-  SendSocketData(s);
+  mSocket->SendSocketData(s);
 }
 
 void
 BluetoothOppManager::FileTransferComplete()
 {
   if (mSendTransferCompleteFlag) {
     return;
   }
@@ -1308,37 +1310,36 @@ BluetoothOppManager::OnConnectSuccess()
     if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
       NS_WARNING("Failed to dispatch to main thread!");
     }
     mRunnable.forget();
   }
 
   // Cache device address since we can't get socket address when a remote
   // device disconnect with us.
-  GetSocketAddr(mConnectedDeviceAddress);
-
-  mSocketStatus = GetConnectionStatus();
+  mSocket->GetAddress(mConnectedDeviceAddress);
+  mSocketStatus = mSocket->GetConnectionStatus();
 }
 
 void
 BluetoothOppManager::OnConnectError()
 {
   if (mRunnable) {
     nsString errorStr;
     errorStr.AssignLiteral("Failed to connect with a bluetooth opp manager!");
     BluetoothReply* reply = new BluetoothReply(BluetoothReplyError(errorStr));
     mRunnable->SetReply(reply);
     if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) {
       NS_WARNING("Failed to dispatch to main thread!");
     }
     mRunnable.forget();
   }
 
-  CloseSocket();
-  mSocketStatus = GetConnectionStatus();
+  mSocket->Disconnect();
+  mSocketStatus = mSocket->GetConnectionStatus();
   Listen();
 }
 
 void
 BluetoothOppManager::OnDisconnect()
 {
   /**
    * It is valid for a bluetooth device which is transfering file via OPP
@@ -1350,28 +1351,29 @@ BluetoothOppManager::OnDisconnect()
   if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
     if (mTransferMode) {
       if (!mSuccessFlag) {
         DeleteReceivedFile();
       } else if (mDsFile) {
         nsString data;
         CopyASCIItoUTF16("modified", data);
 
-        nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+        nsCOMPtr<nsIObserverService> obs =
+          mozilla::services::GetObserverService();
         if (obs) {
           obs->NotifyObservers(mDsFile, "file-watcher-notify", data.get());
         }
       }
     }
 
     if (!mSuccessFlag) {
       FileTransferComplete();
     }
 
     Listen();
   } else if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) {
     NS_WARNING("BluetoothOppManager got unexpected socket status!");
   }
 
   AfterOppDisconnected();
-  mConnectedDeviceAddress.AssignLiteral("00:00:00:00:00:00");
+  mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
   mSuccessFlag = false;
 }
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -3,43 +3,43 @@
 /* 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/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothoppmanager_h__
 #define mozilla_dom_bluetooth_bluetoothoppmanager_h__
 
 #include "BluetoothCommon.h"
+#include "BluetoothSocketObserver.h"
 #include "mozilla/dom/ipc/Blob.h"
 #include "mozilla/ipc/UnixSocket.h"
 #include "DeviceStorage.h"
 
 class nsIOutputStream;
 class nsIInputStream;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothReplyRunnable;
+class BluetoothSocket;
 class ObexHeaderSet;
 
-class BluetoothOppManager : public mozilla::ipc::UnixSocketConsumer
+class BluetoothOppManager : public BluetoothSocketObserver
 {
 public:
   /*
    * Channel of reserved services are fixed values, please check
    * function add_reserved_service_records() in
    * external/bluetooth/bluez/src/adapter.c for more information.
    */
   static const int DEFAULT_OPP_CHANNEL = 10;
   static const int MAX_PACKET_LENGTH = 0xFFFE;
 
   ~BluetoothOppManager();
   static BluetoothOppManager* Get();
-  void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage)
-    MOZ_OVERRIDE;
   void ClientDataHandler(mozilla::ipc::UnixSocketRawData* aMessage);
   void ServerDataHandler(mozilla::ipc::UnixSocketRawData* aMessage);
 
   /*
    * If a application wnats to send a file, first, it needs to
    * call Connect() to create a valid RFCOMM connection. After
    * that, call SendFile()/StopSendingFile() to control file-sharing
    * process. During the file transfering process, the application
@@ -67,16 +67,24 @@ public:
 
   void ExtractPacketHeaders(const ObexHeaderSet& aHeader);
   bool ExtractBlobHeaders();
   nsresult HandleShutdown();
 
   // Return true if there is an ongoing file-transfer session, please see
   // Bug 827267 for more information.
   bool IsTransferring();
+
+  // Implement interface BluetoothSocketObserver
+  void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage)
+    MOZ_OVERRIDE;
+  void OnConnectSuccess() MOZ_OVERRIDE;
+  void OnConnectError() MOZ_OVERRIDE;
+  void OnDisconnect() MOZ_OVERRIDE;
+
 private:
   BluetoothOppManager();
   void StartFileTransfer();
   void FileTransferComplete();
   void UpdateProgress();
   void ReceivingFileConfirmation();
   bool CreateFile();
   bool WriteToFile(const uint8_t* aData, int aDataLength);
@@ -85,20 +93,16 @@ private:
   void ReplyToDisconnect();
   void ReplyToPut(bool aFinal, bool aContinue);
   void AfterOppConnected();
   void AfterFirstPut();
   void AfterOppDisconnected();
   void ValidateFileName();
   bool IsReservedChar(PRUnichar c);
 
-  virtual void OnConnectSuccess() MOZ_OVERRIDE;
-  virtual void OnConnectError() MOZ_OVERRIDE;
-  virtual void OnDisconnect() MOZ_OVERRIDE;
-
   /**
    * RFCOMM socket status.
    */
   enum mozilla::ipc::SocketConnectionStatus mSocketStatus;
 
   /**
    * OBEX session status.
    * Set when OBEX session is established.
@@ -168,13 +172,14 @@ private:
 
   nsCOMPtr<nsIDOMBlob> mBlob;
   nsCOMPtr<nsIThread> mReadFileThread;
   nsCOMPtr<nsIOutputStream> mOutputStream;
   nsCOMPtr<nsIInputStream> mInputStream;
 
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
   nsRefPtr<DeviceStorageFile> mDsFile;
+  nsRefPtr<BluetoothSocket> mSocket;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif