зеркало из https://github.com/mozilla/gecko-dev.git
Bug 809781 - Fixed sending file failure. r=gyeh, a=blocking-basecamp
This commit is contained in:
Родитель
e3e53e6f1d
Коммит
b375b149ee
|
@ -128,6 +128,14 @@ BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED ||
|
||||
GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTING) {
|
||||
NS_WARNING("BluetoothOppManager has been already connected");
|
||||
return false;
|
||||
}
|
||||
|
||||
CloseSocket();
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
if (!bs) {
|
||||
NS_WARNING("BluetoothService not available!");
|
||||
|
@ -137,7 +145,7 @@ BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
|
|||
nsString serviceUuidStr =
|
||||
NS_ConvertUTF8toUTF16(BluetoothServiceUuidStr::ObjectPush);
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
|
||||
mRunnable = aRunnable;
|
||||
|
||||
nsresult rv = bs->GetSocketViaService(aDeviceObjectPath,
|
||||
serviceUuidStr,
|
||||
|
@ -145,15 +153,19 @@ BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath,
|
|||
true,
|
||||
true,
|
||||
this,
|
||||
runnable);
|
||||
mRunnable);
|
||||
|
||||
runnable.forget();
|
||||
return NS_FAILED(rv) ? false : true;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::Disconnect()
|
||||
{
|
||||
if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) {
|
||||
NS_WARNING("BluetoothOppManager has been disconnected!");
|
||||
return;
|
||||
}
|
||||
|
||||
CloseSocket();
|
||||
}
|
||||
|
||||
|
@ -196,6 +208,15 @@ BluetoothOppManager::SendFile(BlobParent* aActor)
|
|||
*/
|
||||
mBlob = aActor->GetBlob();
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob);
|
||||
if (file) {
|
||||
file->GetName(sFileName);
|
||||
}
|
||||
|
||||
if (sFileName.IsEmpty()) {
|
||||
sFileName.AssignLiteral("Unknown");
|
||||
}
|
||||
|
||||
SendConnectRequest();
|
||||
|
||||
return true;
|
||||
|
@ -390,57 +411,51 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
|||
mRemoteMaxPacketLength =
|
||||
(((int)(aMessage->mData[5]) << 8) | aMessage->mData[6]);
|
||||
|
||||
if (mBlob) {
|
||||
/*
|
||||
* Before sending content, we have to send a header including
|
||||
* information such as file name, file length and content type.
|
||||
*/
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob);
|
||||
if (file) {
|
||||
rv = file->GetName(sFileName);
|
||||
}
|
||||
|
||||
if (!file || sFileName.IsEmpty()) {
|
||||
sFileName.AssignLiteral("Unknown");
|
||||
}
|
||||
|
||||
rv = mBlob->GetType(sContentType);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get content type");
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t fileLength;
|
||||
rv = mBlob->GetSize(&fileLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get file size");
|
||||
return;
|
||||
}
|
||||
|
||||
// Currently we keep the size of files which were sent/received via
|
||||
// Bluetooth not exceed UINT32_MAX because the Length header in OBEX
|
||||
// is only 4-byte long. Although it is possible to transfer a file
|
||||
// larger than UINT32_MAX, it needs to parse another OBEX Header
|
||||
// and I would like to leave it as a feature.
|
||||
if (fileLength <= UINT32_MAX) {
|
||||
NS_WARNING("The file size is too large for now");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
sFileLength = fileLength;
|
||||
|
||||
if (NS_FAILED(NS_NewThread(getter_AddRefs(mReadFileThread)))) {
|
||||
NS_WARNING("Can't create thread");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
sInstance->SendPutHeaderRequest(sFileName, sFileLength);
|
||||
StartFileTransfer(mConnectedDeviceAddress, false,
|
||||
sFileName, sFileLength, sContentType);
|
||||
MOZ_ASSERT(!sFileName.IsEmpty());
|
||||
MOZ_ASSERT(mBlob);
|
||||
/*
|
||||
* Before sending content, we have to send a header including
|
||||
* information such as file name, file length and content type.
|
||||
*/
|
||||
nsresult rv = mBlob->GetType(sContentType);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get content type");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t fileLength;
|
||||
rv = mBlob->GetSize(&fileLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get file size");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
// Currently we keep the size of files which were sent/received via
|
||||
// Bluetooth not exceed UINT32_MAX because the Length header in OBEX
|
||||
// is only 4-byte long. Although it is possible to transfer a file
|
||||
// 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;
|
||||
}
|
||||
|
||||
sFileLength = fileLength;
|
||||
|
||||
if (NS_FAILED(NS_NewThread(getter_AddRefs(mReadFileThread)))) {
|
||||
NS_WARNING("Can't create thread");
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
sInstance->SendPutHeaderRequest(sFileName, sFileLength);
|
||||
StartFileTransfer(mConnectedDeviceAddress, false,
|
||||
sFileName, sFileLength, sContentType);
|
||||
} else {
|
||||
SendDisconnectRequest();
|
||||
}
|
||||
} else if (mLastCommand == ObexRequestCode::Disconnect) {
|
||||
if (opCode != ObexResponseCode::Success) {
|
||||
|
@ -451,12 +466,14 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
|||
AfterOppDisconnected();
|
||||
} else if (mLastCommand == ObexRequestCode::Put) {
|
||||
if (opCode != ObexResponseCode::Continue) {
|
||||
// FIXME: Needs error handling here
|
||||
NS_WARNING("[OPP] Put failed");
|
||||
FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
|
||||
sSentFileLength, sContentType);
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAbortFlag || mReadFileThread) {
|
||||
if (mAbortFlag) {
|
||||
SendAbortRequest();
|
||||
return;
|
||||
}
|
||||
|
@ -467,10 +484,13 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
|||
mUpdateProgressCounter = sSentFileLength / kUpdateProgressBase + 1;
|
||||
}
|
||||
|
||||
if (mInputStream) {
|
||||
if (!mInputStream) {
|
||||
nsresult rv = mBlob->GetInternalStream(getter_AddRefs(mInputStream));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't get internal stream of blob");
|
||||
FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
|
||||
sSentFileLength, sContentType);
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -478,11 +498,16 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
|||
nsRefPtr<ReadFileTask> task = new ReadFileTask(mInputStream);
|
||||
if (NS_FAILED(mReadFileThread->Dispatch(task, NS_DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Cannot dispatch ring task!");
|
||||
FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
|
||||
sSentFileLength, sContentType);
|
||||
SendDisconnectRequest();
|
||||
}
|
||||
} else if (mLastCommand == ObexRequestCode::PutFinal) {
|
||||
if (opCode != ObexResponseCode::Success) {
|
||||
// FIXME: Needs error handling here
|
||||
NS_WARNING("[OPP] PutFinal failed");
|
||||
FileTransferComplete(mConnectedDeviceAddress, false, false, sFileName,
|
||||
sSentFileLength, sContentType);
|
||||
SendDisconnectRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -968,6 +993,15 @@ BluetoothOppManager::ReceivingFileConfirmation(const nsString& aAddress,
|
|||
void
|
||||
BluetoothOppManager::OnConnectSuccess()
|
||||
{
|
||||
if (mRunnable) {
|
||||
BluetoothReply* reply = new BluetoothReply(BluetoothReplySuccess(true));
|
||||
mRunnable->SetReply(reply);
|
||||
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);
|
||||
|
@ -978,6 +1012,17 @@ BluetoothOppManager::OnConnectSuccess()
|
|||
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();
|
||||
Listen();
|
||||
|
|
|
@ -117,6 +117,8 @@ private:
|
|||
nsCOMPtr<nsIThread> mReadFileThread;
|
||||
nsCOMPtr<nsIOutputStream> mOutputStream;
|
||||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
|
|
@ -148,8 +148,14 @@ public:
|
|||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (mHeaders[i]->mId == ObexHeaderId::Name) {
|
||||
/*
|
||||
* According to section 2.2.2 [Name] of IrOBEX spec, we know that
|
||||
* the Name header is "a null terminated Unicode text string describing
|
||||
* the name of the object.", and that's the reason why we need to minus
|
||||
* 1 to get the real length of the file name.
|
||||
*/
|
||||
int nameLength = mHeaders[i]->mDataLength / 2 - 1;
|
||||
uint8_t* ptr = mHeaders[i]->mData.get();
|
||||
int nameLength = mHeaders[i]->mDataLength / 2;
|
||||
|
||||
for (int j = 0; j < nameLength; ++j) {
|
||||
PRUnichar c = ((((uint32_t)ptr[j * 2]) << 8) | ptr[j * 2 + 1]);
|
||||
|
|
Загрузка…
Ссылка в новой задаче