зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1079649: Use a temporary (.part) file to store incoming file. (bluetooth2/bluez) r=btian
This commit is contained in:
Родитель
b99f40c9ca
Коммит
0fb740de24
|
@ -553,6 +553,7 @@ BluetoothOppManager::AfterOppDisconnected()
|
|||
mLastCommand = 0;
|
||||
mPutPacketReceivedLength = 0;
|
||||
mDsFile = nullptr;
|
||||
mDummyDsFile = nullptr;
|
||||
|
||||
// We can't reset mSuccessFlag here since this function may be called
|
||||
// before we send system message of transfer complete
|
||||
|
@ -579,6 +580,34 @@ BluetoothOppManager::AfterOppDisconnected()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::RecoverFileName()
|
||||
{
|
||||
// Remove the trailing ".part" file name from mDsFile by two steps
|
||||
// 1. mDsFile->SetPath() so that the notification sent to Gaia will carry
|
||||
// correct information of the file.
|
||||
// 2. mDsFile->mFile->RenameTo() so that the file name would actually be
|
||||
// changed in file system.
|
||||
if (mDsFile && mDsFile->mFile) {
|
||||
nsString path;
|
||||
path.AssignLiteral(TARGET_SUBDIR);
|
||||
path.Append(mFileName);
|
||||
|
||||
mDsFile->SetPath(path);
|
||||
mDsFile->mFile->RenameTo(nullptr, mFileName);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::DeleteDummyFile()
|
||||
{
|
||||
// Remove the empty temp file
|
||||
if (mDummyDsFile && mDummyDsFile->mFile) {
|
||||
mDummyDsFile->mFile->Remove(false);
|
||||
mDummyDsFile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::DeleteReceivedFile()
|
||||
{
|
||||
|
@ -591,6 +620,8 @@ BluetoothOppManager::DeleteReceivedFile()
|
|||
mDsFile->mFile->Remove(false);
|
||||
mDsFile = nullptr;
|
||||
}
|
||||
|
||||
DeleteDummyFile();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -598,25 +629,39 @@ BluetoothOppManager::CreateFile()
|
|||
{
|
||||
MOZ_ASSERT(mPutPacketReceivedLength == mPacketLength);
|
||||
|
||||
// Create one dummy file to be a placeholder for the target file name, and
|
||||
// create another file with a meaningless file extension to write the received
|
||||
// data. By doing this, we can prevent applications from parsing incomplete
|
||||
// data in the middle of the receiving process.
|
||||
nsString path;
|
||||
path.AssignLiteral(TARGET_SUBDIR);
|
||||
path.Append(mFileName);
|
||||
|
||||
mDsFile = DeviceStorageFile::CreateUnique(
|
||||
path, nsIFile::NORMAL_FILE_TYPE, 0644);
|
||||
// Use an empty dummy file object to occupy the file name, so that after the
|
||||
// whole file has been received successfully by using mDsFile, we could just
|
||||
// remove mDummyDsFile and rename mDsFile to the file name of mDummyDsFile.
|
||||
mDummyDsFile =
|
||||
DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644);
|
||||
NS_ENSURE_TRUE(mDummyDsFile, false);
|
||||
|
||||
// The function CreateUnique() may create a file with a different file
|
||||
// name from the original mFileName. Therefore we have to retrieve
|
||||
// the file name again.
|
||||
mDummyDsFile->mFile->GetLeafName(mFileName);
|
||||
|
||||
BT_LOGR("mFileName: %s", NS_ConvertUTF16toUTF8(mFileName).get());
|
||||
|
||||
// Prepare the entire file path for the .part file
|
||||
path.Truncate();
|
||||
path.AssignLiteral(TARGET_SUBDIR);
|
||||
path.Append(mFileName);
|
||||
path.AppendLiteral(".part");
|
||||
|
||||
mDsFile =
|
||||
DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644);
|
||||
NS_ENSURE_TRUE(mDsFile, 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 mFileName. Therefore we have to retrieve
|
||||
* the file name again.
|
||||
*/
|
||||
f->GetLeafName(mFileName);
|
||||
|
||||
NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), f);
|
||||
NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), mDsFile->mFile);
|
||||
NS_ENSURE_TRUE(mOutputStream, false);
|
||||
|
||||
return true;
|
||||
|
@ -932,6 +977,10 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
|
|||
// Success to receive a file and notify completion
|
||||
if (mPutFinalFlag) {
|
||||
mSuccessFlag = true;
|
||||
|
||||
DeleteDummyFile();
|
||||
RecoverFileName();
|
||||
|
||||
FileTransferComplete();
|
||||
NotifyAboutFileChange();
|
||||
}
|
||||
|
|
|
@ -85,6 +85,8 @@ private:
|
|||
void ReceivingFileConfirmation();
|
||||
bool CreateFile();
|
||||
bool WriteToFile(const uint8_t* aData, int aDataLength);
|
||||
void RecoverFileName();
|
||||
void DeleteDummyFile();
|
||||
void DeleteReceivedFile();
|
||||
void ReplyToConnect();
|
||||
void ReplyToDisconnectOrAbort();
|
||||
|
@ -209,6 +211,7 @@ private:
|
|||
nsCOMPtr<nsIInputStream> mInputStream;
|
||||
nsCOMPtr<nsIVolumeMountLock> mMountLock;
|
||||
nsRefPtr<DeviceStorageFile> mDsFile;
|
||||
nsRefPtr<DeviceStorageFile> mDummyDsFile;
|
||||
|
||||
// If a connection has been established, mSocket will be the socket
|
||||
// communicating with the remote socket. We maintain the invariant that if
|
||||
|
|
Загрузка…
Ссылка в новой задаче