mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-04-02 12:32:55 +00:00
Merge latest green inbound changeset and mozilla-central
This commit is contained in:
commit
35e2bbbc95
@ -179,6 +179,16 @@ SettingsListener.observe('language.current', 'en-US', function(value) {
|
||||
function(value) {
|
||||
Services.prefs.setBoolPref('ril.radio.disabled', value);
|
||||
});
|
||||
|
||||
SettingsListener.observe('wap.UAProf.url', '',
|
||||
function(value) {
|
||||
Services.prefs.setCharPref('wap.UAProf.url', value);
|
||||
});
|
||||
|
||||
SettingsListener.observe('wap.UAProf.tagname', 'x-wap-profile',
|
||||
function(value) {
|
||||
Services.prefs.setCharPref('wap.UAProf.tagname', value);
|
||||
});
|
||||
})();
|
||||
|
||||
//=================== DeviceInfo ====================
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "c59267134f80ccb38353a46c51b210009dba0391",
|
||||
"revision": "61262845a414403a1507ceb1afebfd4f8139e0f5",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -47,22 +47,7 @@ static const uint32_t kUpdateProgressBase = 50 * 1024;
|
||||
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
|
||||
@ -96,7 +81,6 @@ public:
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
sInstance->SendPutRequest(mStream, mSize);
|
||||
sSentFileLength += mSize;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -133,9 +117,7 @@ public:
|
||||
}
|
||||
|
||||
if (numRead > 0) {
|
||||
if (sSentFileLength + numRead >= sFileLength) {
|
||||
sWaitingToSendPutFinal = true;
|
||||
}
|
||||
sInstance->CheckPutFinal(numRead);
|
||||
|
||||
nsRefPtr<SendSocketDataTask> task =
|
||||
new SendSocketDataTask((uint8_t*)buf.forget(), numRead);
|
||||
@ -190,6 +172,9 @@ BluetoothOppManager::BluetoothOppManager() : mConnected(false)
|
||||
, mSuccessFlag(false)
|
||||
, mIsServer(true)
|
||||
, mWaitingForConfirmationFlag(false)
|
||||
, mFileLength(0)
|
||||
, mSentFileLength(0)
|
||||
, mWaitingToSendPutFinal(false)
|
||||
, mCurrentBlobIndex(-1)
|
||||
{
|
||||
mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
|
||||
@ -363,7 +348,7 @@ BluetoothOppManager::StartSendingNextFile()
|
||||
// file at the head of queue.
|
||||
SendConnectRequest();
|
||||
} else {
|
||||
SendPutHeaderRequest(sFileName, sFileLength);
|
||||
SendPutHeaderRequest(mFileName, mFileLength);
|
||||
AfterFirstPut();
|
||||
}
|
||||
}
|
||||
@ -431,8 +416,8 @@ BluetoothOppManager::AfterFirstPut()
|
||||
mPutFinalFlag = false;
|
||||
mReceivedDataBufferOffset = 0;
|
||||
mSendTransferCompleteFlag = false;
|
||||
sSentFileLength = 0;
|
||||
sWaitingToSendPutFinal = false;
|
||||
mSentFileLength = 0;
|
||||
mWaitingToSendPutFinal = false;
|
||||
mSuccessFlag = false;
|
||||
mBodySegmentLength = 0;
|
||||
}
|
||||
@ -516,7 +501,7 @@ BluetoothOppManager::CreateFile()
|
||||
|
||||
nsString path;
|
||||
path.AssignLiteral(TARGET_SUBDIR);
|
||||
path.Append(sFileName);
|
||||
path.Append(mFileName);
|
||||
|
||||
mDsFile = DeviceStorageFile::CreateUnique(path, nsIFile::NORMAL_FILE_TYPE, 0644);
|
||||
if (!mDsFile) {
|
||||
@ -526,13 +511,13 @@ BluetoothOppManager::CreateFile()
|
||||
|
||||
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);
|
||||
@ -557,15 +542,15 @@ 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) ||
|
||||
@ -583,7 +568,7 @@ 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();
|
||||
@ -609,7 +594,7 @@ BluetoothOppManager::ExtractBlobHeaders()
|
||||
return false;
|
||||
}
|
||||
|
||||
sFileLength = fileLength;
|
||||
mFileLength = fileLength;
|
||||
rv = NS_NewThread(getter_AddRefs(mReadFileThread));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Can't create thread");
|
||||
@ -623,11 +608,11 @@ BluetoothOppManager::ExtractBlobHeaders()
|
||||
void
|
||||
BluetoothOppManager::RetrieveSentFileName()
|
||||
{
|
||||
sFileName.Truncate();
|
||||
mFileName.Truncate();
|
||||
|
||||
nsCOMPtr<nsIDOMFile> file = do_QueryInterface(mBlob);
|
||||
if (file) {
|
||||
file->GetName(sFileName);
|
||||
file->GetName(mFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -636,16 +621,16 @@ BluetoothOppManager::RetrieveSentFileName()
|
||||
* 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);
|
||||
|
||||
@ -659,8 +644,8 @@ BluetoothOppManager::RetrieveSentFileName()
|
||||
EmptyCString(),
|
||||
extension);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
sFileName.AppendLiteral(".");
|
||||
AppendUTF8toUTF16(extension, sFileName);
|
||||
mFileName.AppendLiteral(".");
|
||||
AppendUTF8toUTF16(extension, mFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -678,12 +663,12 @@ BluetoothOppManager::IsReservedChar(PRUnichar c)
|
||||
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('_'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -786,7 +771,7 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
|
||||
// When we cancel the transfer, delete the file and notify completion
|
||||
if (mAbortFlag) {
|
||||
ReplyToPut(mPutFinalFlag, false);
|
||||
sSentFileLength += mBodySegmentLength;
|
||||
mSentFileLength += mBodySegmentLength;
|
||||
DeleteReceivedFile();
|
||||
FileTransferComplete();
|
||||
return;
|
||||
@ -795,7 +780,7 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
|
||||
// Wait until get confirmation from user, then create file and write to it
|
||||
if (mWaitingForConfirmationFlag) {
|
||||
ReceivingFileConfirmation();
|
||||
sSentFileLength += mBodySegmentLength;
|
||||
mSentFileLength += mBodySegmentLength;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -818,10 +803,10 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
|
||||
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
|
||||
@ -830,8 +815,14 @@ BluetoothOppManager::ServerDataHandler(UnixSocketRawData* aMessage)
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -909,7 +900,7 @@ BluetoothOppManager::ClientDataHandler(UnixSocketRawData* aMessage)
|
||||
PostDelayedTask(FROM_HERE, new CloseSocketTask(mSocket), 1000);
|
||||
}
|
||||
} else if (mLastCommand == ObexRequestCode::Connect) {
|
||||
MOZ_ASSERT(!sFileName.IsEmpty());
|
||||
MOZ_ASSERT(!mFileName.IsEmpty());
|
||||
MOZ_ASSERT(mBlob);
|
||||
|
||||
AfterOppConnected();
|
||||
@ -920,9 +911,9 @@ BluetoothOppManager::ClientDataHandler(UnixSocketRawData* aMessage)
|
||||
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;
|
||||
}
|
||||
@ -932,9 +923,9 @@ BluetoothOppManager::ClientDataHandler(UnixSocketRawData* aMessage)
|
||||
return;
|
||||
}
|
||||
|
||||
if (kUpdateProgressBase * mUpdateProgressCounter < sSentFileLength) {
|
||||
if (kUpdateProgressBase * mUpdateProgressCounter < mSentFileLength) {
|
||||
UpdateProgress();
|
||||
mUpdateProgressCounter = sSentFileLength / kUpdateProgressBase + 1;
|
||||
mUpdateProgressCounter = mSentFileLength / kUpdateProgressBase + 1;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
@ -1040,8 +1031,9 @@ BluetoothOppManager::SendPutRequest(uint8_t* aFileBody,
|
||||
index += AppendHeaderBody(&req[index], aFileBody, aFileBodyLength);
|
||||
|
||||
SendObexData(req, ObexRequestCode::Put, index);
|
||||
|
||||
delete [] req;
|
||||
|
||||
mSentFileLength += aFileBodyLength;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1062,10 +1054,9 @@ BluetoothOppManager::SendPutFinalRequest()
|
||||
index += AppendHeaderEndOfBody(&req[index]);
|
||||
|
||||
SendObexData(req, ObexRequestCode::PutFinal, index);
|
||||
|
||||
sWaitingToSendPutFinal = false;
|
||||
|
||||
delete [] req;
|
||||
|
||||
mWaitingToSendPutFinal = false;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1094,6 +1085,14 @@ BluetoothOppManager::SendAbortRequest()
|
||||
SendObexData(req, ObexRequestCode::Abort, index);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothOppManager::CheckPutFinal(uint32_t aNumRead)
|
||||
{
|
||||
if (mSentFileLength + aNumRead >= mFileLength) {
|
||||
mWaitingToSendPutFinal = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothOppManager::IsTransferring()
|
||||
{
|
||||
@ -1161,6 +1160,19 @@ BluetoothOppManager::ReplyToPut(bool aFinal, bool aContinue)
|
||||
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)
|
||||
{
|
||||
@ -1200,15 +1212,15 @@ BluetoothOppManager::FileTransferComplete()
|
||||
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)) {
|
||||
@ -1236,15 +1248,15 @@ BluetoothOppManager::StartFileTransfer()
|
||||
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)) {
|
||||
@ -1270,11 +1282,11 @@ BluetoothOppManager::UpdateProgress()
|
||||
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)) {
|
||||
@ -1296,15 +1308,15 @@ BluetoothOppManager::ReceivingFileConfirmation()
|
||||
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)) {
|
||||
|
@ -74,6 +74,7 @@ public:
|
||||
|
||||
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.
|
||||
@ -109,6 +110,7 @@ private:
|
||||
void ReplyToConnect();
|
||||
void ReplyToDisconnectOrAbort();
|
||||
void ReplyToPut(bool aFinal, bool aContinue);
|
||||
void ReplyError(uint8_t aError);
|
||||
void AfterOppConnected();
|
||||
void AfterFirstPut();
|
||||
void AfterOppDisconnected();
|
||||
@ -190,6 +192,12 @@ private:
|
||||
*/
|
||||
bool mWaitingForConfirmationFlag;
|
||||
|
||||
nsString mFileName;
|
||||
nsString mContentType;
|
||||
uint32_t mFileLength;
|
||||
uint32_t mSentFileLength;
|
||||
bool mWaitingToSendPutFinal;
|
||||
|
||||
nsAutoArrayPtr<uint8_t> mBodySegment;
|
||||
nsAutoArrayPtr<uint8_t> mReceivedDataBuffer;
|
||||
|
||||
@ -200,7 +208,6 @@ private:
|
||||
/**
|
||||
* 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;
|
||||
|
@ -25,6 +25,19 @@ const CHUNK_SIZE = 20;
|
||||
const REVISION_STORE = "revision";
|
||||
const REVISION_KEY = "revision";
|
||||
|
||||
function exportContact(aRecord) {
|
||||
let contact = {};
|
||||
contact.properties = aRecord.properties;
|
||||
|
||||
for (let field in aRecord.properties)
|
||||
contact.properties[field] = aRecord.properties[field];
|
||||
|
||||
contact.updated = aRecord.updated;
|
||||
contact.published = aRecord.published;
|
||||
contact.id = aRecord.id;
|
||||
return contact;
|
||||
}
|
||||
|
||||
function ContactDispatcher(aContacts, aFullContacts, aCallback, aNewTxn, aClearDispatcher, aFailureCb) {
|
||||
let nextIndex = 0;
|
||||
|
||||
@ -54,7 +67,7 @@ function ContactDispatcher(aContacts, aFullContacts, aCallback, aNewTxn, aClearD
|
||||
aNewTxn("readonly", STORE_NAME, function(txn, store) {
|
||||
for (let i = start; i < Math.min(start+CHUNK_SIZE, aContacts.length); ++i) {
|
||||
store.get(aContacts[i]).onsuccess = function(e) {
|
||||
chunk.push(e.target.result);
|
||||
chunk.push(exportContact(e.target.result));
|
||||
count++;
|
||||
if (count === aContacts.length) {
|
||||
aCallback(chunk);
|
||||
@ -590,19 +603,6 @@ ContactDB.prototype = {
|
||||
return contact;
|
||||
},
|
||||
|
||||
makeExport: function makeExport(aRecord) {
|
||||
let contact = {};
|
||||
contact.properties = aRecord.properties;
|
||||
|
||||
for (let field in aRecord.properties)
|
||||
contact.properties[field] = aRecord.properties[field];
|
||||
|
||||
contact.updated = aRecord.updated;
|
||||
contact.published = aRecord.published;
|
||||
contact.id = aRecord.id;
|
||||
return contact;
|
||||
},
|
||||
|
||||
updateRecordMetadata: function updateRecordMetadata(record) {
|
||||
if (!record.id) {
|
||||
Cu.reportError("Contact without ID");
|
||||
@ -979,7 +979,7 @@ ContactDB.prototype = {
|
||||
if (DEBUG) debug("Request successful. Record count: " + event.target.result.length);
|
||||
this.sortResults(event.target.result, options);
|
||||
for (let i in event.target.result)
|
||||
txn.result[event.target.result[i].id] = this.makeExport(event.target.result[i]);
|
||||
txn.result[event.target.result[i].id] = exportContact(event.target.result[i]);
|
||||
}.bind(this);
|
||||
}
|
||||
},
|
||||
@ -994,7 +994,7 @@ ContactDB.prototype = {
|
||||
if (DEBUG) debug("Request successful. Record count:" + event.target.result.length);
|
||||
this.sortResults(event.target.result, options);
|
||||
for (let i in event.target.result) {
|
||||
txn.result[event.target.result[i].id] = this.makeExport(event.target.result[i]);
|
||||
txn.result[event.target.result[i].id] = exportContact(event.target.result[i]);
|
||||
}
|
||||
}.bind(this);
|
||||
},
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "OpenFileFinder.h"
|
||||
#include "Volume.h"
|
||||
#include "VolumeManager.h"
|
||||
|
||||
@ -71,8 +72,9 @@ using namespace mozilla::hal;
|
||||
#define USE_DEBUG 0
|
||||
|
||||
#undef LOG
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AutoMounter" , ## args)
|
||||
#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "AutoMounter" , ## args)
|
||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AutoMounter", ## args)
|
||||
#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "AutoMounter", ## args)
|
||||
#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "AutoMounter", ## args)
|
||||
|
||||
#if USE_DEBUG
|
||||
#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "AutoMounter" , ## args)
|
||||
@ -402,19 +404,50 @@ AutoMounter::UpdateState()
|
||||
if (vol->IsMountLocked()) {
|
||||
// The volume is currently locked, so leave it in the mounted
|
||||
// state.
|
||||
DBG("UpdateState: Mounted volume %s is locked, leaving",
|
||||
vol->NameStr());
|
||||
LOGW("UpdateState: Mounted volume %s is locked, not sharing",
|
||||
vol->NameStr());
|
||||
break;
|
||||
}
|
||||
|
||||
// Check to see if there are any open files on the volume and
|
||||
// don't initiate the unmount while there are open files.
|
||||
OpenFileFinder::Info fileInfo;
|
||||
OpenFileFinder fileFinder(vol->MountPoint());
|
||||
if (fileFinder.First(&fileInfo)) {
|
||||
LOGW("The following files are open under '%s'",
|
||||
vol->MountPoint().get());
|
||||
do {
|
||||
LOGW(" PID: %d file: '%s' app: '%s' comm: '%s' exe: '%s'\n",
|
||||
fileInfo.mPid,
|
||||
fileInfo.mFileName.get(),
|
||||
fileInfo.mAppName.get(),
|
||||
fileInfo.mComm.get(),
|
||||
fileInfo.mExe.get());
|
||||
} while (fileFinder.Next(&fileInfo));
|
||||
LOGW("UpdateState: Mounted volume %s has open files, not sharing",
|
||||
vol->NameStr());
|
||||
|
||||
// Check again in 5 seconds to see if the files are closed. Since
|
||||
// we're trying to share the volume, this implies that we're
|
||||
// plugged into the PC via USB and this in turn implies that the
|
||||
// battery is charging, so we don't need to be too concerned about
|
||||
// wasting battery here.
|
||||
MessageLoopForIO::current()->
|
||||
PostDelayedTask(FROM_HERE,
|
||||
NewRunnableMethod(this, &AutoMounter::UpdateState),
|
||||
5000);
|
||||
break;
|
||||
}
|
||||
|
||||
// Volume is mounted, we need to unmount before
|
||||
// we can share.
|
||||
DBG("UpdateState: Unmounting %s", vol->NameStr());
|
||||
LOG("UpdateState: Unmounting %s", vol->NameStr());
|
||||
vol->StartUnmount(mResponseCallback);
|
||||
return; // UpdateState will be called again when the Unmount command completes
|
||||
}
|
||||
case nsIVolume::STATE_IDLE: {
|
||||
// Volume is unmounted. We can go ahead and share.
|
||||
DBG("UpdateState: Sharing %s", vol->NameStr());
|
||||
LOG("UpdateState: Sharing %s", vol->NameStr());
|
||||
vol->StartShare(mResponseCallback);
|
||||
return; // UpdateState will be called again when the Share command completes
|
||||
}
|
||||
@ -428,14 +461,14 @@ AutoMounter::UpdateState()
|
||||
switch (volState) {
|
||||
case nsIVolume::STATE_SHARED: {
|
||||
// Volume is shared. We can go ahead and unshare.
|
||||
DBG("UpdateState: Unsharing %s", vol->NameStr());
|
||||
LOG("UpdateState: Unsharing %s", vol->NameStr());
|
||||
vol->StartUnshare(mResponseCallback);
|
||||
return; // UpdateState will be called again when the Unshare command completes
|
||||
}
|
||||
case nsIVolume::STATE_IDLE: {
|
||||
// Volume is unmounted, try to mount.
|
||||
|
||||
DBG("UpdateState: Mounting %s", vol->NameStr());
|
||||
LOG("UpdateState: Mounting %s", vol->NameStr());
|
||||
vol->StartMount(mResponseCallback);
|
||||
return; // UpdateState will be called again when Mount command completes
|
||||
}
|
||||
|
195
dom/system/gonk/OpenFileFinder.cpp
Normal file
195
dom/system/gonk/OpenFileFinder.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
/* 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/. */
|
||||
|
||||
#include "OpenFileFinder.h"
|
||||
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
OpenFileFinder::OpenFileFinder(const nsACString& aPath)
|
||||
: mPath(aPath),
|
||||
mProcDir(nullptr),
|
||||
mFdDir(nullptr),
|
||||
mPid(0)
|
||||
{
|
||||
}
|
||||
|
||||
OpenFileFinder::~OpenFileFinder()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool
|
||||
OpenFileFinder::First(OpenFileFinder::Info* aInfo)
|
||||
{
|
||||
Close();
|
||||
|
||||
mProcDir = opendir("/proc");
|
||||
if (!mProcDir) {
|
||||
return false;
|
||||
}
|
||||
mState = NEXT_PID;
|
||||
return Next(aInfo);
|
||||
}
|
||||
|
||||
bool
|
||||
OpenFileFinder::Next(OpenFileFinder::Info* aInfo)
|
||||
{
|
||||
// NOTE: This function calls readdir and readlink, neither of which should
|
||||
// block since we're using the proc filesystem, which is a purely
|
||||
// kernel in-memory filesystem and doesn't depend on external driver
|
||||
// behaviour.
|
||||
while (mState != DONE) {
|
||||
switch (mState) {
|
||||
case NEXT_PID: {
|
||||
struct dirent *pidEntry;
|
||||
pidEntry = readdir(mProcDir);
|
||||
if (!pidEntry) {
|
||||
mState = DONE;
|
||||
break;
|
||||
}
|
||||
char *endPtr;
|
||||
mPid = strtol(pidEntry->d_name, &endPtr, 10);
|
||||
if (mPid == 0 || *endPtr != '\0') {
|
||||
// Not a +ve number - ignore
|
||||
continue;
|
||||
}
|
||||
// We've found a /proc/PID directory. Scan open file descriptors.
|
||||
if (mFdDir) {
|
||||
closedir(mFdDir);
|
||||
}
|
||||
nsPrintfCString fdDirPath("/proc/%d/fd", mPid);
|
||||
mFdDir = opendir(fdDirPath.get());
|
||||
if (!mFdDir) {
|
||||
continue;
|
||||
}
|
||||
mState = CHECK_FDS;
|
||||
}
|
||||
// Fall through
|
||||
case CHECK_FDS: {
|
||||
struct dirent *fdEntry;
|
||||
while((fdEntry = readdir(mFdDir))) {
|
||||
if (!strcmp(fdEntry->d_name, ".") ||
|
||||
!strcmp(fdEntry->d_name, "..")) {
|
||||
continue;
|
||||
}
|
||||
nsPrintfCString fdSymLink("/proc/%d/fd/%s", mPid, fdEntry->d_name);
|
||||
nsCString resolvedPath;
|
||||
if (ReadSymLink(fdSymLink, resolvedPath) && PathMatches(resolvedPath)) {
|
||||
// We found an open file contained within the directory tree passed
|
||||
// into the constructor.
|
||||
FillInfo(aInfo, resolvedPath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// We've checked all of the files for this pid, move onto the next one.
|
||||
mState = NEXT_PID;
|
||||
continue;
|
||||
}
|
||||
case DONE:
|
||||
default:
|
||||
mState = DONE; // covers the default case
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileFinder::Close()
|
||||
{
|
||||
if (mFdDir) {
|
||||
closedir(mFdDir);
|
||||
}
|
||||
if (mProcDir) {
|
||||
closedir(mProcDir);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileFinder::FillInfo(OpenFileFinder::Info* aInfo, const nsACString& aPath)
|
||||
{
|
||||
aInfo->mFileName = aPath;
|
||||
aInfo->mPid = mPid;
|
||||
nsPrintfCString exePath("/proc/%d/exe", mPid);
|
||||
ReadSymLink(exePath, aInfo->mExe);
|
||||
aInfo->mComm.Truncate();
|
||||
aInfo->mAppName.Truncate();
|
||||
nsPrintfCString statPath("/proc/%d/stat", mPid);
|
||||
nsCString statString;
|
||||
statString.SetLength(200);
|
||||
char *stat = statString.BeginWriting();
|
||||
if (!stat) {
|
||||
return;
|
||||
}
|
||||
ReadSysFile(statPath.get(), stat, statString.Length());
|
||||
// The stat line includes the comm field, surrounded by parenthesis.
|
||||
// However, the contents of the comm field itself is arbitrary and
|
||||
// and can include ')', so we search for the rightmost ) as being
|
||||
// the end of the comm field.
|
||||
char *closeParen = strrchr(stat, ')');
|
||||
if (!closeParen) {
|
||||
return;
|
||||
}
|
||||
char *openParen = strchr(stat, '(');
|
||||
if (!openParen) {
|
||||
return;
|
||||
}
|
||||
if (openParen >= closeParen) {
|
||||
return;
|
||||
}
|
||||
nsDependentCSubstring comm(&openParen[1], closeParen - openParen - 1);
|
||||
aInfo->mComm = comm;
|
||||
// There is a single character field after the comm and then
|
||||
// the parent pid (the field we're interested in).
|
||||
// ) X ppid
|
||||
// 01234
|
||||
int ppid = atoi(&closeParen[4]);
|
||||
// We assume that we're running in the parent process
|
||||
if (ppid != getpid()) {
|
||||
return;
|
||||
}
|
||||
// This looks like a content process. The comm field will be the
|
||||
// app name.
|
||||
aInfo->mAppName = aInfo->mComm;
|
||||
}
|
||||
|
||||
bool
|
||||
OpenFileFinder::ReadSymLink(const nsACString& aSymLink, nsACString& aOutPath)
|
||||
{
|
||||
aOutPath.Truncate();
|
||||
const char *symLink = aSymLink.BeginReading();
|
||||
|
||||
// Verify that we actually have a symlink.
|
||||
struct stat st;
|
||||
if (lstat(symLink, &st)) {
|
||||
return false;
|
||||
}
|
||||
if ((st.st_mode & S_IFMT) != S_IFLNK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Contrary to the documentation st.st_size doesn't seem to be a reliable
|
||||
// indication of the length when reading from /proc, so we use a fixed
|
||||
// size buffer instead.
|
||||
|
||||
char resolvedSymLink[PATH_MAX];
|
||||
ssize_t pathLength = readlink(symLink, resolvedSymLink,
|
||||
sizeof(resolvedSymLink) - 1);
|
||||
if (pathLength <= 0) {
|
||||
return false;
|
||||
}
|
||||
resolvedSymLink[pathLength] = '\0';
|
||||
aOutPath.Assign(resolvedSymLink);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // system
|
||||
} // mozilla
|
60
dom/system/gonk/OpenFileFinder.h
Normal file
60
dom/system/gonk/OpenFileFinder.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* 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_system_openfilefinder_h__
|
||||
#define mozilla_system_openfilefinder_h__
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
class OpenFileFinder
|
||||
{
|
||||
public:
|
||||
enum State
|
||||
{
|
||||
NEXT_PID,
|
||||
CHECK_FDS,
|
||||
DONE
|
||||
};
|
||||
class Info
|
||||
{
|
||||
public:
|
||||
nsCString mFileName; // name of the the open file
|
||||
nsCString mAppName; // App which has the file open (if it's a b2g app)
|
||||
pid_t mPid; // pid of the process which has the file open
|
||||
nsCString mComm; // comm associated with pid
|
||||
nsCString mExe; // executable name associated with pid
|
||||
};
|
||||
|
||||
OpenFileFinder(const nsACString& aPath);
|
||||
~OpenFileFinder();
|
||||
|
||||
bool First(Info* aInfo); // Return the first open file
|
||||
bool Next(Info* aInfo); // Return the next open file
|
||||
void Close();
|
||||
|
||||
private:
|
||||
|
||||
void FillInfo(Info *aInfo, const nsACString& aPath);
|
||||
bool ReadSymLink(const nsACString& aSymLink, nsACString& aOutPath);
|
||||
bool PathMatches(const nsACString& aPath)
|
||||
{
|
||||
return Substring(aPath, 0, mPath.Length()).Equals(mPath);
|
||||
}
|
||||
|
||||
State mState; // Keeps track of what we're doing.
|
||||
nsCString mPath; // Only report files contained within this directory tree
|
||||
DIR* mProcDir; // Used for scanning /proc
|
||||
DIR* mFdDir; // Used for scanning /proc/PID/fd
|
||||
int mPid; // PID currently being processed
|
||||
};
|
||||
|
||||
} // system
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_system_nsvolume_h__
|
@ -52,6 +52,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
'nsVolumeMountLock.cpp',
|
||||
'nsVolumeService.cpp',
|
||||
'nsVolumeStat.cpp',
|
||||
'OpenFileFinder.cpp',
|
||||
'TimeZoneSettingObserver.cpp',
|
||||
'Volume.cpp',
|
||||
'VolumeCommand.cpp',
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
|
||||
virtual bool QueueBuffer(ANativeWindowBuffer* buf) = 0;
|
||||
|
||||
uint32_t xdpi;
|
||||
float xdpi;
|
||||
uint32_t surfaceformat;
|
||||
};
|
||||
|
||||
|
@ -86,7 +86,7 @@ GonkDisplayJB::GonkDisplayJB()
|
||||
|
||||
mWidth = values[0];
|
||||
mHeight = values[1];
|
||||
xdpi = values[2];
|
||||
xdpi = values[2] / 1000.0f;
|
||||
surfaceformat = HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user