diff --git a/b2g/chrome/content/settings.js b/b2g/chrome/content/settings.js
index f14de8c78102..26d002db1d7f 100644
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -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 ====================
diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json
index 0e3cb4ed25d4..aab0deaa31d2 100644
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "c59267134f80ccb38353a46c51b210009dba0391", 
+    "revision": "61262845a414403a1507ceb1afebfd4f8139e0f5", 
     "repo_path": "/integration/gaia-central"
 }
diff --git a/dom/bluetooth/BluetoothOppManager.cpp b/dom/bluetooth/BluetoothOppManager.cpp
index 61048c565ee6..016f99b538b0 100644
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -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)) {
diff --git a/dom/bluetooth/BluetoothOppManager.h b/dom/bluetooth/BluetoothOppManager.h
index aa63d2c5d84f..490e756ed18c 100644
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -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;
diff --git a/dom/contacts/fallback/ContactDB.jsm b/dom/contacts/fallback/ContactDB.jsm
index f1d6b15558fc..9ff4fc2339b7 100644
--- a/dom/contacts/fallback/ContactDB.jsm
+++ b/dom/contacts/fallback/ContactDB.jsm
@@ -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);
   },
diff --git a/dom/system/gonk/AutoMounter.cpp b/dom/system/gonk/AutoMounter.cpp
index 5406d42068ec..e9af00c8c7f0 100644
--- a/dom/system/gonk/AutoMounter.cpp
+++ b/dom/system/gonk/AutoMounter.cpp
@@ -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
         }
diff --git a/dom/system/gonk/OpenFileFinder.cpp b/dom/system/gonk/OpenFileFinder.cpp
new file mode 100644
index 000000000000..32a4f122b319
--- /dev/null
+++ b/dom/system/gonk/OpenFileFinder.cpp
@@ -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
diff --git a/dom/system/gonk/OpenFileFinder.h b/dom/system/gonk/OpenFileFinder.h
new file mode 100644
index 000000000000..e00404248de4
--- /dev/null
+++ b/dom/system/gonk/OpenFileFinder.h
@@ -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__
diff --git a/dom/system/gonk/moz.build b/dom/system/gonk/moz.build
index 3f2cc95630bf..eeb9a109a5a7 100644
--- a/dom/system/gonk/moz.build
+++ b/dom/system/gonk/moz.build
@@ -52,6 +52,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
         'nsVolumeMountLock.cpp',
         'nsVolumeService.cpp',
         'nsVolumeStat.cpp',
+        'OpenFileFinder.cpp',
         'TimeZoneSettingObserver.cpp',
         'Volume.cpp',
         'VolumeCommand.cpp',
diff --git a/widget/gonk/libdisplay/GonkDisplay.h b/widget/gonk/libdisplay/GonkDisplay.h
index f883dba5b7f9..ab8bd13cf7e7 100644
--- a/widget/gonk/libdisplay/GonkDisplay.h
+++ b/widget/gonk/libdisplay/GonkDisplay.h
@@ -41,7 +41,7 @@ public:
 
     virtual bool QueueBuffer(ANativeWindowBuffer* buf) = 0;
 
-    uint32_t xdpi;
+    float xdpi;
     uint32_t surfaceformat;
 };
 
diff --git a/widget/gonk/libdisplay/GonkDisplayJB.cpp b/widget/gonk/libdisplay/GonkDisplayJB.cpp
index 8337ff2d8db2..ce826e92f550 100644
--- a/widget/gonk/libdisplay/GonkDisplayJB.cpp
+++ b/widget/gonk/libdisplay/GonkDisplayJB.cpp
@@ -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;
     }