Bug 891210 - [Bluetooth][OPP cleanup] Move file-transfer related static variables into class BluetoothOppManager, r=echou
authorBen Tian <btian@mozilla.com>
Mon, 15 Jul 2013 12:10:32 +0800
changeset 151056 e86ca7a31c709ff848247527dbd16b43d1eadfc0
parent 151055 56c849c40fcf77ac2bc0dc6283f179fb4d26687a
child 151057 84172c0f17896bd8547e6f8167756871403e2029
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechou
bugs891210
milestone25.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 891210 - [Bluetooth][OPP cleanup] Move file-transfer related static variables into class BluetoothOppManager, r=echou
dom/bluetooth/BluetoothOppManager.cpp
dom/bluetooth/BluetoothOppManager.h
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -42,32 +42,17 @@ static const uint32_t kUpdateProgressBas
 
 /*
  * 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;
-
-/*
- * 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
- * connections, and then we will be able to have multiple file transferring
- * sessions at a time.
- */
-static uint32_t sSentFileLength = 0;
-static nsString sFileName;
-static uint32_t sFileLength = 0;
-static nsString sContentType;
 static bool sInShutdown = false;
-static bool sWaitingToSendPutFinal = false;
 }
 
 NS_IMETHODIMP
 BluetoothOppManager::Observe(nsISupports* aSubject,
                              const char* aTopic,
                              const PRUnichar* aData)
 {
   MOZ_ASSERT(sInstance);
@@ -91,17 +76,16 @@ public:
     MOZ_ASSERT(!NS_IsMainThread());
   }
 
   NS_IMETHOD Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     sInstance->SendPutRequest(mStream, mSize);
-    sSentFileLength += mSize;
 
     return NS_OK;
   }
 
 private:
   nsAutoArrayPtr<uint8_t> mStream;
   uint32_t mSize;
 };
@@ -128,19 +112,17 @@ public:
     nsresult rv = mInputStream->Read(buf, mAvailablePacketSize, &numRead);
     if (NS_FAILED(rv)) {
       // Needs error handling here
       NS_WARNING("Failed to read from input stream");
       return NS_ERROR_FAILURE;
     }
 
     if (numRead > 0) {
-      if (sSentFileLength + numRead >= sFileLength) {
-        sWaitingToSendPutFinal = true;
-      }
+      sInstance->CheckPutFinal(numRead);
 
       nsRefPtr<SendSocketDataTask> task =
         new SendSocketDataTask((uint8_t*)buf.forget(), numRead);
       if (NS_FAILED(NS_DispatchToMainThread(task))) {
         NS_WARNING("Failed to dispatch to main thread!");
         return NS_ERROR_FAILURE;
       }
     }
@@ -185,16 +167,19 @@ BluetoothOppManager::BluetoothOppManager
                                            , mReceivedDataBufferOffset(0)
                                            , mAbortFlag(false)
                                            , mNewFileFlag(false)
                                            , mPutFinalFlag(false)
                                            , mSendTransferCompleteFlag(false)
                                            , mSuccessFlag(false)
                                            , mIsServer(true)
                                            , mWaitingForConfirmationFlag(false)
+                                           , mFileLength(0)
+                                           , mSentFileLength(0)
+                                           , mWaitingToSendPutFinal(false)
                                            , mCurrentBlobIndex(-1)
 {
   mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
   Init();
 }
 
 BluetoothOppManager::~BluetoothOppManager()
 {
@@ -358,17 +343,17 @@ BluetoothOppManager::StartSendingNextFil
   StartFileTransfer();
 
   if (mCurrentBlobIndex == 0) {
     // We may have more than one file waiting for transferring, but only one
     // CONNECT request would be sent. Therefore check if this is the very first
     // file at the head of queue.
     SendConnectRequest();
   } else {
-    SendPutHeaderRequest(sFileName, sFileLength);
+    SendPutHeaderRequest(mFileName, mFileLength);
     AfterFirstPut();
   }
 }
 
 bool
 BluetoothOppManager::SendFile(const nsAString& aDeviceAddress,
                               BlobParent* aActor)
 {
@@ -426,18 +411,18 @@ BluetoothOppManager::ConfirmReceivingFil
 
 void
 BluetoothOppManager::AfterFirstPut()
 {
   mUpdateProgressCounter = 1;
   mPutFinalFlag = false;
   mReceivedDataBufferOffset = 0;
   mSendTransferCompleteFlag = false;
-  sSentFileLength = 0;
-  sWaitingToSendPutFinal = false;
+  mSentFileLength = 0;
+  mWaitingToSendPutFinal = false;
   mSuccessFlag = false;
   mBodySegmentLength = 0;
 }
 
 void
 BluetoothOppManager::AfterOppConnected()
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -511,33 +496,33 @@ BluetoothOppManager::DeleteReceivedFile(
 
 bool
 BluetoothOppManager::CreateFile()
 {
   MOZ_ASSERT(mPacketLeftLength == 0);
 
   nsString path;
   path.AssignLiteral(TARGET_SUBDIR);
-  path.Append(sFileName);
+  path.Append(mFileName);
 
   mDsFile = DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644);
   if (!mDsFile) {
     NS_WARNING("Couldn't create the file");
     return false;
   }
 
   nsCOMPtr<nsIFile> f;
   mDsFile->mFile->Clone(getter_AddRefs(f));
-  
+
   /*
    * The function CreateUnique() may create a file with a different file
-   * name from the original sFileName. Therefore we have to retrieve
+   * name from the original mFileName. Therefore we have to retrieve
    * the file name again.
    */
-  f->GetLeafName(sFileName);
+  f->GetLeafName(mFileName);
 
   NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), f);
   NS_ENSURE_TRUE(mOutputStream, false);
 
   return true;
 }
 
 bool
@@ -552,25 +537,25 @@ BluetoothOppManager::WriteToFile(const u
   return true;
 }
 
 // Virtual function of class SocketConsumer
 void
 BluetoothOppManager::ExtractPacketHeaders(const ObexHeaderSet& aHeader)
 {
   if (aHeader.Has(ObexHeaderId::Name)) {
-    aHeader.GetName(sFileName);
+    aHeader.GetName(mFileName);
   }
 
   if (aHeader.Has(ObexHeaderId::Type)) {
-    aHeader.GetContentType(sContentType);
+    aHeader.GetContentType(mContentType);
   }
 
   if (aHeader.Has(ObexHeaderId::Length)) {
-    aHeader.GetLength(&sFileLength);
+    aHeader.GetLength(&mFileLength);
   }
 
   if (aHeader.Has(ObexHeaderId::Body) ||
       aHeader.Has(ObexHeaderId::EndOfBody)) {
     uint8_t* bodyPtr;
     aHeader.GetBody(&bodyPtr);
     mBodySegment = bodyPtr;
 
@@ -578,17 +563,17 @@ BluetoothOppManager::ExtractPacketHeader
   }
 }
 
 bool
 BluetoothOppManager::ExtractBlobHeaders()
 {
   RetrieveSentFileName();
 
-  nsresult rv = mBlob->GetType(sContentType);
+  nsresult rv = mBlob->GetType(mContentType);
   if (NS_FAILED(rv)) {
     NS_WARNING("Can't get content type");
     SendDisconnectRequest();
     return false;
   }
 
   uint64_t fileLength;
   rv = mBlob->GetSize(&fileLength);
@@ -604,68 +589,68 @@ BluetoothOppManager::ExtractBlobHeaders(
   // larger than UINT32_MAX, it needs to parse another OBEX Header
   // and I would like to leave it as a feature.
   if (fileLength > (uint64_t)UINT32_MAX) {
     NS_WARNING("The file size is too large for now");
     SendDisconnectRequest();
     return false;
   }
 
-  sFileLength = fileLength;
+  mFileLength = fileLength;
   rv = NS_NewThread(getter_AddRefs(mReadFileThread));
   if (NS_FAILED(rv)) {
     NS_WARNING("Can't create thread");
     SendDisconnectRequest();
     return false;
   }
 
   return true;
 }
 
 void
 BluetoothOppManager::RetrieveSentFileName()
 {
-  sFileName.Truncate();
+  mFileName.Truncate();
 
   nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob);
   if (file) {
-    file->GetName(sFileName);
+    file->GetName(mFileName);
   }
 
   /**
    * We try our best to get the file extention to avoid interoperability issues.
    * However, once we found that we are unable to get suitable extension or
    * information about the content type, sending a pre-defined file name without
    * extension would be fine.
    */
-  if (sFileName.IsEmpty()) {
-    sFileName.AssignLiteral("Unknown");
+  if (mFileName.IsEmpty()) {
+    mFileName.AssignLiteral("Unknown");
   }
 
-  int32_t offset = sFileName.RFindChar('/');
+  int32_t offset = mFileName.RFindChar('/');
   if (offset != kNotFound) {
-    sFileName = Substring(sFileName, offset + 1);
+    mFileName = Substring(mFileName, offset + 1);
   }
 
-  offset = sFileName.RFindChar('.');
+  offset = mFileName.RFindChar('.');
   if (offset == kNotFound) {
     nsCOMPtr<nsIMIMEService> mimeSvc = do_GetService(NS_MIMESERVICE_CONTRACTID);
 
     if (mimeSvc) {
       nsString mimeType;
       mBlob->GetType(mimeType);
 
       nsCString extension;
       nsresult rv =
         mimeSvc->GetPrimaryExtension(NS_LossyConvertUTF16toASCII(mimeType),
                                      EmptyCString(),
                                      extension);
       if (NS_SUCCEEDED(rv)) {
-        sFileName.AppendLiteral(".");
-        AppendUTF8toUTF16(extension, sFileName);
+        mFileName.AppendLiteral(".");
+        AppendUTF8toUTF16(extension, mFileName);
       }
     }
   }
 }
 
 bool
 BluetoothOppManager::IsReservedChar(PRUnichar c)
 {
@@ -673,22 +658,22 @@ BluetoothOppManager::IsReservedChar(PRUn
           c == PRUnichar('?') || c == PRUnichar('|') || c == PRUnichar('<') ||
           c == PRUnichar('>') || c == PRUnichar('"') || c == PRUnichar(':') ||
           c == PRUnichar('/') || c == PRUnichar('*') || c == PRUnichar('\\'));
 }
 
 void
 BluetoothOppManager::ValidateFileName()
 {
-  int length = sFileName.Length();
+  int length = mFileName.Length();
 
   for (int i = 0; i < length; ++i) {
     // Replace reserved char of fat file system with '_'
-    if (IsReservedChar(sFileName.CharAt(i))) {
-      sFileName.Replace(i, 1, PRUnichar('_'));
+    if (IsReservedChar(mFileName.CharAt(i))) {
+      mFileName.Replace(i, 1, PRUnichar('_'));
     }
   }
 }
 
 void
 BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
 {
   uint8_t opCode;
@@ -781,26 +766,26 @@ BluetoothOppManager::ServerDataHandler(U
     ExtractPacketHeaders(pktHeaders);
     ValidateFileName();
 
     mReceivedDataBufferOffset = 0;
 
     // When we cancel the transfer, delete the file and notify completion
     if (mAbortFlag) {
       ReplyToPut(mPutFinalFlag, false);
-      sSentFileLength += mBodySegmentLength;
+      mSentFileLength += mBodySegmentLength;
       DeleteReceivedFile();
       FileTransferComplete();
       return;
     }
 
     // Wait until get confirmation from user, then create file and write to it
     if (mWaitingForConfirmationFlag) {
       ReceivingFileConfirmation();
-      sSentFileLength += mBodySegmentLength;
+      mSentFileLength += mBodySegmentLength;
       return;
     }
 
     // Already get confirmation from user, create a new file if needed and
     // write to output stream
     if (mNewFileFlag) {
       StartFileTransfer();
       if (!CreateFile()) {
@@ -813,30 +798,36 @@ BluetoothOppManager::ServerDataHandler(U
     if (!WriteToFile(mBodySegment.get(), mBodySegmentLength)) {
       ReplyToPut(mPutFinalFlag, false);
       return;
     }
 
     ReplyToPut(mPutFinalFlag, true);
 
     // Send progress update
-    sSentFileLength += mBodySegmentLength;
-    if (sSentFileLength > kUpdateProgressBase * mUpdateProgressCounter) {
+    mSentFileLength += mBodySegmentLength;
+    if (mSentFileLength > kUpdateProgressBase * mUpdateProgressCounter) {
       UpdateProgress();
-      mUpdateProgressCounter = sSentFileLength / kUpdateProgressBase + 1;
+      mUpdateProgressCounter = mSentFileLength / kUpdateProgressBase + 1;
     }
 
     // Success to receive a file and notify completion
     if (mPutFinalFlag) {
       mSuccessFlag = true;
       FileTransferComplete();
       NotifyAboutFileChange();
     }
+  } else if (opCode == ObexRequestCode::Get ||
+             opCode == ObexRequestCode::GetFinal ||
+             opCode == ObexRequestCode::SetPath) {
+    ReplyError(ObexResponseCode::BadRequest);
+    NS_WARNING("Unsupported ObexRequestCode");
   } else {
-    NS_WARNING("Unhandled ObexRequestCode");
+    ReplyError(ObexResponseCode::NotImplemented);
+    NS_WARNING("Unrecognized ObexRequestCode");
   }
 }
 
 void
 BluetoothOppManager::ClearQueue()
 {
   mCurrentBlobIndex = -1;
   mBlob = nullptr;
@@ -904,42 +895,42 @@ BluetoothOppManager::ClientDataHandler(U
     // 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.
     if (mSocket) {
       MessageLoop::current()->
         PostDelayedTask(FROM_HERE, new CloseSocketTask(mSocket), 1000);
     }
   } else if (mLastCommand == ObexRequestCode::Connect) {
-    MOZ_ASSERT(!sFileName.IsEmpty());
+    MOZ_ASSERT(!mFileName.IsEmpty());
     MOZ_ASSERT(mBlob);
 
     AfterOppConnected();
 
     // Keep remote information
     mRemoteObexVersion = aMessage->mData[3];
     mRemoteConnectionFlags = aMessage->mData[4];
     mRemoteMaxPacketLength =
       (((int)(aMessage->mData[5]) << 8) | aMessage->mData[6]);
 
-    sInstance->SendPutHeaderRequest(sFileName, sFileLength);
+    sInstance->SendPutHeaderRequest(mFileName, mFileLength);
   } else if (mLastCommand == ObexRequestCode::Put) {
-    if (sWaitingToSendPutFinal) {
+    if (mWaitingToSendPutFinal) {
       SendPutFinalRequest();
       return;
     }
 
     if (mAbortFlag) {
       SendAbortRequest();
       return;
     }
 
-    if (kUpdateProgressBase * mUpdateProgressCounter < sSentFileLength) {
+    if (kUpdateProgressBase * mUpdateProgressCounter < mSentFileLength) {
       UpdateProgress();
-      mUpdateProgressCounter = sSentFileLength / kUpdateProgressBase + 1;
+      mUpdateProgressCounter = mSentFileLength / kUpdateProgressBase + 1;
     }
 
     nsresult rv;
     if (!mInputStream) {
       rv = mBlob->GetInternalStream(getter_AddRefs(mInputStream));
       if (NS_FAILED(rv)) {
         NS_WARNING("Can't get internal stream of blob");
         SendDisconnectRequest();
@@ -1035,18 +1026,19 @@ BluetoothOppManager::SendPutRequest(uint
   // Section 3.3.3 "Put", IrOBEX 1.2
   // [opcode:1][length:2][Headers:var]
   uint8_t* req = new uint8_t[mRemoteMaxPacketLength];
 
   int index = 3;
   index += AppendHeaderBody(&req[index], aFileBody, aFileBodyLength);
 
   SendObexData(req, ObexRequestCode::Put, index);
+  delete [] req;
 
-  delete [] req;
+  mSentFileLength += aFileBodyLength;
 }
 
 void
 BluetoothOppManager::SendPutFinalRequest()
 {
   if (!mConnected) return;
 
   /**
@@ -1057,20 +1049,19 @@ BluetoothOppManager::SendPutFinalRequest
    */
 
   // [opcode:1][length:2]
   int index = 3;
   uint8_t* req = new uint8_t[mRemoteMaxPacketLength];
   index += AppendHeaderEndOfBody(&req[index]);
 
   SendObexData(req, ObexRequestCode::PutFinal, index);
+  delete [] req;
 
-  sWaitingToSendPutFinal = false;
-
-  delete [] req;
+  mWaitingToSendPutFinal = false;
 }
 
 void
 BluetoothOppManager::SendDisconnectRequest()
 {
   if (!mConnected) return;
 
   // Section 3.3.2 "Disconnect", IrOBEX 1.2
@@ -1089,16 +1080,24 @@ BluetoothOppManager::SendAbortRequest()
   // Section 3.3.5 "Abort", IrOBEX 1.2
   // [opcode:1][length:2][Headers:var]
   uint8_t req[255];
   int index = 3;
 
   SendObexData(req, ObexRequestCode::Abort, index);
 }
 
+void
+BluetoothOppManager::CheckPutFinal(uint32_t aNumRead)
+{
+  if (mSentFileLength + aNumRead >= mFileLength) {
+    mWaitingToSendPutFinal = true;
+  }
+}
+
 bool
 BluetoothOppManager::IsTransferring()
 {
   return (mConnected && !mSendTransferCompleteFlag);
 }
 
 void
 BluetoothOppManager::GetAddress(nsAString& aDeviceAddress)
@@ -1157,16 +1156,29 @@ BluetoothOppManager::ReplyToPut(bool aFi
     opcode = (aFinal)? ObexResponseCode::Unauthorized :
                        ObexResponseCode::Unauthorized & (~FINAL_BIT);
   }
 
   SendObexData(req, opcode, index);
 }
 
 void
+BluetoothOppManager::ReplyError(uint8_t aError)
+{
+  if (!mConnected) return;
+
+  // Section 3.2 "Response Format", IrOBEX 1.2
+  // [opcode:1][length:2][Headers:var]
+  uint8_t req[255];
+  int index = 3;
+
+  SendObexData(req, aError, index);
+}
+
+void
 BluetoothOppManager::SendObexData(uint8_t* aData, uint8_t aOpcode, int aSize)
 {
   SetObexPacketInfo(aData, aOpcode, aSize);
 
   if (!mIsServer) {
     mLastCommand = aOpcode;
   }
 
@@ -1195,25 +1207,25 @@ BluetoothOppManager::FileTransferComplet
   v = mSuccessFlag;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("received");
   v = mIsServer;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("fileName");
-  v = sFileName;
+  v = mFileName;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("fileLength");
-  v = sSentFileLength;
+  v = mSentFileLength;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("contentType");
-  v = sContentType;
+  v = mContentType;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   if (!BroadcastSystemMessage(type, parameters)) {
     NS_WARNING("Failed to broadcast [bluetooth-opp-transfer-complete]");
     return;
   }
 
   mSendTransferCompleteFlag = true;
@@ -1231,25 +1243,25 @@ BluetoothOppManager::StartFileTransfer()
   v = mConnectedDeviceAddress;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("received");
   v = mIsServer;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("fileName");
-  v = sFileName;
+  v = mFileName;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("fileLength");
-  v = sFileLength;
+  v = mFileLength;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("contentType");
-  v = sContentType;
+  v = mContentType;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   if (!BroadcastSystemMessage(type, parameters)) {
     NS_WARNING("Failed to broadcast [bluetooth-opp-transfer-start]");
     return;
   }
 }
 
@@ -1265,21 +1277,21 @@ BluetoothOppManager::UpdateProgress()
   v = mConnectedDeviceAddress;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("received");
   v = mIsServer;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("processedLength");
-  v = sSentFileLength;
+  v = mSentFileLength;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("fileLength");
-  v = sFileLength;
+  v = mFileLength;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   if (!BroadcastSystemMessage(type, parameters)) {
     NS_WARNING("Failed to broadcast [bluetooth-opp-update-progress]");
     return;
   }
 }
 
@@ -1291,25 +1303,25 @@ BluetoothOppManager::ReceivingFileConfir
   InfallibleTArray<BluetoothNamedValue> parameters;
   type.AssignLiteral("bluetooth-opp-receiving-file-confirmation");
 
   name.AssignLiteral("address");
   v = mConnectedDeviceAddress;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("fileName");
-  v = sFileName;
+  v = mFileName;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("fileLength");
-  v = sFileLength;
+  v = mFileLength;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("contentType");
-  v = sContentType;
+  v = mContentType;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   if (!BroadcastSystemMessage(type, parameters)) {
     NS_WARNING("Failed to send [bluetooth-opp-receiving-file-confirmation]");
     return;
   }
 }
 
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -69,16 +69,17 @@ public:
   void SendPutHeaderRequest(const nsAString& aFileName, int aFileSize);
   void SendPutRequest(uint8_t* aFileBody, int aFileBodyLength);
   void SendPutFinalRequest();
   void SendDisconnectRequest();
   void SendAbortRequest();
 
   void ExtractPacketHeaders(const ObexHeaderSet& aHeader);
   bool ExtractBlobHeaders();
+  void CheckPutFinal(uint32_t aNumRead);
 
   // Return true if there is an ongoing file-transfer session, please see
   // Bug 827267 for more information.
   bool IsTransferring();
 
   // Implement interface BluetoothSocketObserver
   void ReceiveSocketData(
     BluetoothSocket* aSocket,
@@ -104,16 +105,17 @@ private:
   void UpdateProgress();
   void ReceivingFileConfirmation();
   bool CreateFile();
   bool WriteToFile(const uint8_t* aData, int aDataLength);
   void DeleteReceivedFile();
   void ReplyToConnect();
   void ReplyToDisconnectOrAbort();
   void ReplyToPut(bool aFinal, bool aContinue);
+  void ReplyError(uint8_t aError);
   void AfterOppConnected();
   void AfterFirstPut();
   void AfterOppDisconnected();
   void ValidateFileName();
   bool IsReservedChar(PRUnichar c);
   void ClearQueue();
   void RetrieveSentFileName();
   void NotifyAboutFileChange();
@@ -185,27 +187,32 @@ private:
   bool mIsServer;
 
   /**
    * Set when receiving the first PUT packet and wait for
    * ConfirmReceivingFile() to be called.
    */
   bool mWaitingForConfirmationFlag;
 
+  nsString mFileName;
+  nsString mContentType;
+  uint32_t mFileLength;
+  uint32_t mSentFileLength;
+  bool mWaitingToSendPutFinal;
+
   nsAutoArrayPtr<uint8_t> mBodySegment;
   nsAutoArrayPtr<uint8_t> mReceivedDataBuffer;
 
   int mCurrentBlobIndex;
   nsCOMPtr<nsIDOMBlob> mBlob;
   nsCOMArray<nsIDOMBlob> mBlobs;
 
   /**
    * A seperate member thread is required because our read calls can block
    * execution, which is not allowed to happen on the IOThread.
-   * 
    */
   nsCOMPtr<nsIThread> mReadFileThread;
   nsCOMPtr<nsIOutputStream> mOutputStream;
   nsCOMPtr<nsIInputStream> mInputStream;
   nsCOMPtr<nsIVolumeMountLock> mMountLock;
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
   nsRefPtr<DeviceStorageFile> mDsFile;