merge b2g-inbound to mozilla-central
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 18 Oct 2013 11:39:28 +0200
changeset 165990 b082b86b2cacb56a7e27c789afbfd764fa447234
parent 165950 2def80d5a106187ddd2d19bcd8efe975edd46e7f (current diff)
parent 165989 ae5e6dc9bce92cf626de6a8b1065ad49d90f22d1 (diff)
child 166016 4e7d1e2c93a639296f661b77898d049040cdcd80
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.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
merge b2g-inbound to mozilla-central
configure.in
dom/base/Navigator.cpp
dom/bluetooth/BluetoothAdapter.cpp
dom/bluetooth/ipc/BluetoothParent.cpp
dom/tests/mochitest/general/test_interfaces.html
modules/libpref/src/init/all.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -355,16 +355,17 @@ pref("content.ime.strict_policy", true);
 //
 // $ adb shell stop
 // $ adb shell setprop log.redirect-stdio true
 // $ adb shell start
 pref("browser.dom.window.dump.enabled", false);
 
 // Default Content Security Policy to apply to privileged and certified apps
 pref("security.apps.privileged.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'");
+// If you change this CSP, make sure to update the fast path in nsCSPService.cpp
 pref("security.apps.certified.CSP.default", "default-src *; script-src 'self'; object-src 'none'; style-src 'self'");
 
 // Temporarily force-enable GL compositing.  This is default-disabled
 // deep within the bowels of the widgetry system.  Remove me when GL
 // compositing isn't default disabled in widget/android.
 pref("layers.acceleration.force-enabled", true);
 
 // handle links targeting new windows
@@ -383,19 +384,16 @@ pref("dom.mozBrowserFramesEnabled", true
 // Enable a (virtually) unlimited number of mozbrowser processes.
 // We'll run out of PIDs on UNIX-y systems before we hit this limit.
 pref("dom.ipc.processCount", 100000);
 
 pref("dom.ipc.browser_frames.oop_by_default", false);
 
 // SMS/MMS
 pref("dom.sms.enabled", true);
-pref("dom.sms.strict7BitEncoding", false); // Disabled by default.
-pref("dom.sms.requestStatusReport", true); // Enabled by default.
-pref("dom.mms.requestStatusReport", true); // Enabled by default.
 
 //The waiting time in network manager.
 pref("network.gonk.ms-release-mms-connection", 30000);
 
 // WebContacts
 pref("dom.mozContacts.enabled", true);
 pref("dom.navigator-property.disable.mozContacts", false);
 pref("dom.global-constructor.disable.mozContact", false);
@@ -429,17 +427,16 @@ pref("services.push.pingInterval", 18000
 // How long before a DOMRequest errors as timeout
 pref("services.push.requestTimeout", 10000);
 // enable udp wakeup support
 pref("services.push.udp.wakeupEnabled", true);
 
 // NetworkStats
 #ifdef MOZ_B2G_RIL
 pref("dom.mozNetworkStats.enabled", true);
-pref("ril.cellbroadcast.disabled", false);
 pref("dom.webapps.firstRunWithSIM", true);
 #endif
 
 // WebSettings
 pref("dom.mozSettings.enabled", true);
 pref("dom.navigator-property.disable.mozSettings", false);
 pref("dom.mozPermissionSettings.enabled", true);
 
@@ -725,20 +722,16 @@ pref("jsloader.reuseGlobal", true);
 pref("font.size.inflation.minTwips", 120);
 // And disable it for lingering master-process UI.
 pref("font.size.inflation.disabledInMasterProcess", true);
 
 // Enable freeing dirty pages when minimizing memory; this reduces memory
 // consumption when applications are sent to the background.
 pref("memory.free_dirty_pages", true);
 
-// UAProfile settings
-pref("wap.UAProf.url", "");
-pref("wap.UAProf.tagname", "x-wap-profile");
-
 pref("layout.imagevisibility.enabled", false);
 pref("layout.imagevisibility.numscrollportwidths", 1);
 pref("layout.imagevisibility.numscrollportheights", 1);
 
 // Enable native identity (persona/browserid)
 pref("dom.identity.enabled", true);
 
 // Wait up to this much milliseconds when orientation changed
@@ -819,13 +812,26 @@ pref("devtools.debugger.unix-domain-sock
 // enable Skia/GL (OpenGL-accelerated 2D drawing) for large enough 2d canvases,
 // falling back to Skia/software for smaller canvases
 pref("gfx.canvas.azure.backends", "skia");
 pref("gfx.canvas.azure.accelerated", true);
 
 // Enable Telephony API
 pref("dom.telephony.enabled", true);
 
+// Cell Broadcast API
+pref("dom.cellbroadcast.enabled", true);
+pref("ril.cellbroadcast.disabled", false);
+
+// ICC API
+pref("dom.icc.enabled", true);
+
+// Mobile Connection API
+pref("dom.mobileconnection.enabled", true);
+
+// Voice Mail API
+pref("dom.voicemail.enabled", true);
+
 // The url of the page used to display network error details.
 pref("b2g.neterror.url", "app://system.gaiamobile.org/net_error.html");
 
 // Enable Web Speech synthesis API
 pref("media.webspeech.synth.enabled", true);
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "563d1aa93586165246ab2ab9d40566a598f56387", 
+    "revision": "154bb18c48ff06e41fb7ba24d8f72d520919646f", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/config.json
+++ b/b2g/config/hamachi/config.json
@@ -15,18 +15,17 @@
         ["{workdir}/boot.img", "out/target/product/hamachi/"],
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
         "{workdir}/.config",
         "{workdir}/sources.xml"
     ],
     "env": {
         "VARIANT": "user",
-        "MOZILLA_OFFICIAL": "1",
-        "B2GUPDATER": "1"
+        "MOZILLA_OFFICIAL": "1"
     },
     "b2g_manifest": "hamachi.xml",
     "b2g_manifest_branch": "master",
     "additional_source_tarballs": ["backup-hamachi.tar.xz"],
     "gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
     "gaia": {
         "l10n": {
             "vcs": "hgtool",
--- a/b2g/config/helix/config.json
+++ b/b2g/config/helix/config.json
@@ -15,17 +15,16 @@
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
         "{workdir}/.config",
         "{workdir}/sources.xml"
     ],
     "env": {
         "VARIANT": "user",
         "MOZILLA_OFFICIAL": "1",
-        "B2GUPDATER": "1",
         "ANDROIDFS_DIR": "{workdir}/helix-ics"
     },
     "b2g_manifest": "helix.xml",
     "b2g_manifest_branch": "master",
     "additional_source_tarballs": ["helix-ics.tar.xz"],
     "gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
     "gaia": {
         "l10n": {
--- a/b2g/config/inari/config.json
+++ b/b2g/config/inari/config.json
@@ -15,18 +15,17 @@
         ["{workdir}/boot.img", "out/target/product/inari/"],
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
         "{workdir}/.config",
         "{workdir}/sources.xml"
     ],
     "env": {
         "VARIANT": "user",
-        "MOZILLA_OFFICIAL": "1",
-        "B2GUPDATER": "1"
+        "MOZILLA_OFFICIAL": "1"
     },
     "b2g_manifest": "inari.xml",
     "b2g_manifest_branch": "master",
     "additional_source_tarballs": ["backup-inari.tar.xz"],
     "gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
     "gaia": {
         "l10n": {
             "vcs": "hgtool",
--- a/b2g/config/leo/config.json
+++ b/b2g/config/leo/config.json
@@ -15,18 +15,17 @@
         ["{workdir}/boot.img", "out/target/product/leo/"],
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
         "{workdir}/.config",
         "{workdir}/sources.xml"
     ],
     "env": {
         "VARIANT": "user",
-        "MOZILLA_OFFICIAL": "1",
-        "B2GUPDATER": "1"
+        "MOZILLA_OFFICIAL": "1"
     },
     "b2g_manifest": "leo.xml",
     "b2g_manifest_branch": "master",
     "additional_source_tarballs": ["backup-leo.tar.xz"],
     "gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
     "gaia": {
         "l10n": {
             "vcs": "hgtool",
--- a/b2g/config/mako/config.json
+++ b/b2g/config/mako/config.json
@@ -15,18 +15,17 @@
         ["{workdir}/boot.img", "out/target/product/mako/"],
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
         "{workdir}/.config",
         "{workdir}/sources.xml"
     ],
     "env": {
         "VARIANT": "user",
-        "MOZILLA_OFFICIAL": "1",
-        "B2GUPDATER": "1"
+        "MOZILLA_OFFICIAL": "1"
     },
     "b2g_manifest": "nexus-4.xml",
     "b2g_manifest_branch": "master",
     "additional_source_tarballs": [],
     "gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
     "gaia": {
         "l10n": {
             "vcs": "hgtool",
--- a/b2g/config/unagi/config.json
+++ b/b2g/config/unagi/config.json
@@ -17,18 +17,17 @@
         ["{workdir}/boot.img", "out/target/product/unagi/"],
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
         "{workdir}/.config",
         "{workdir}/sources.xml"
     ],
     "env": {
         "VARIANT": "user",
-        "MOZILLA_OFFICIAL": "1",
-        "B2GUPDATER": "1"
+        "MOZILLA_OFFICIAL": "1"
     },
     "gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
     "gaia": {
         "l10n": {
             "vcs": "hgtool",
             "root": "http://hg.mozilla.org/gaia-l10n"
         }
     }
--- a/configure.in
+++ b/configure.in
@@ -217,27 +217,34 @@ if test -n "$gonkdir" ; then
         ARCH_DIR=arch-x86
         ;;
     esac
 
     case "$ANDROID_VERSION" in
     15)
         GONK_INCLUDES="-I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/frameworks/base/include -I$gonkdir/frameworks/base/services/camera -I$gonkdir/frameworks/base/include/media/stagefright -I$gonkdir/frameworks/base/include/media/stagefright/openmax -I$gonkdir/frameworks/base/media/libstagefright/rtsp -I$gonkdir/frameworks/base/media/libstagefright/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib -I$gonkdir/dalvik/libnativehelper/include/nativehelper"
         MOZ_B2G_BT=1
+        MOZ_B2G_BT_BLUEZ=1
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         MOZ_RTSP=1
         ;;
     18)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
         if test -d "$gonkdir/external/bluetooth/bluez"; then
-            GONK_INCLUDES+=" -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
+            GONK_INCLUDES="$GONK_INCLUDES -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
             MOZ_B2G_BT=1
+            MOZ_B2G_BT_BLUEZ=1
         fi
+        if test -d "$gonkdir/external/bluetooth/bluedroid"; then
+            MOZ_B2G_BT=1
+            MOZ_B2G_BT_BLUEDROID=1
+        fi
+
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         ;;
     *)
         AC_MSG_ERROR([Unsupported platform version: $ANDROID_VERSION])
         ;;
     esac
@@ -7283,16 +7290,18 @@ dnl ====================================
 MOZ_ARG_ENABLE_BOOL(b2g-bt,
 [  --enable-b2g-bt      Set compile flags necessary for compiling Bluetooth API for B2G ],
     MOZ_B2G_BT=1,
     MOZ_B2G_BT= )
 if test -n "$MOZ_B2G_BT"; then
     AC_DEFINE(MOZ_B2G_BT)
 fi
 AC_SUBST(MOZ_B2G_BT)
+AC_SUBST(MOZ_B2G_BT_BLUEZ)
+AC_SUBST(MOZ_B2G_BT_BLUEDROID)
 
 dnl ========================================================
 dnl = Enable Pico Speech Synthesis (Gonk usually)
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(synth-pico,
 [  --enable-synth-pico  Set compile flags necessary for compiling Pico Web Speech API ],
     MOZ_SYNTH_PICO=1,
     MOZ_SYNTH_PICO= )
--- a/content/base/src/nsCSPService.cpp
+++ b/content/base/src/nsCSPService.cpp
@@ -40,16 +40,17 @@ CSPService::CSPService()
 #ifdef PR_LOGGING
   if (!gCspPRLog)
     gCspPRLog = PR_NewLogModule("CSP");
 #endif
 }
 
 CSPService::~CSPService()
 {
+  mAppStatusCache.Clear();
 }
 
 NS_IMPL_ISUPPORTS2(CSPService, nsIContentPolicy, nsIChannelEventSink)
 
 /* nsIContentPolicy implementation */
 NS_IMETHODIMP
 CSPService::ShouldLoad(uint32_t aContentType,
                        nsIURI *aContentLocation,
@@ -100,16 +101,65 @@ CSPService::ShouldLoad(uint32_t aContent
   // TYPE_CSP_REPORT, TYPE_REFRESH, TYPE_DOCUMENT
   // (their mappings are null in contentSecurityPolicy.js)
   if (aContentType == nsIContentPolicy::TYPE_CSP_REPORT ||
     aContentType == nsIContentPolicy::TYPE_REFRESH ||
     aContentType == nsIContentPolicy::TYPE_DOCUMENT) {
     return NS_OK;
   }
 
+  // ----- THIS IS A TEMPORARY FAST PATH FOR CERTIFIED APPS. -----
+  // ----- PLEASE REMOVE ONCE bug 925004 LANDS.              -----
+
+  // Cache the app status for this origin.
+  uint16_t status = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
+  nsAutoCString contentOrigin;
+  aContentLocation->GetPrePath(contentOrigin);
+  if (aRequestPrincipal && !mAppStatusCache.Get(contentOrigin, &status)) {
+    aRequestPrincipal->GetAppStatus(&status);
+    mAppStatusCache.Put(contentOrigin, status);
+  }
+
+  if (status == nsIPrincipal::APP_STATUS_CERTIFIED) {
+    // The CSP for certified apps is :
+    // "default-src *; script-src 'self'; object-src 'none'; style-src 'self'"
+    // That means we can optimize for this case by:
+    // - loading only same origin scripts and stylesheets.
+    // - never loading objects.
+    // - accepting everything else.
+
+    switch (aContentType) {
+      case nsIContentPolicy::TYPE_SCRIPT:
+      case nsIContentPolicy::TYPE_STYLESHEET:
+        {
+          nsAutoCString sourceOrigin;
+          aRequestOrigin->GetPrePath(sourceOrigin);
+          if (!sourceOrigin.Equals(contentOrigin)) {
+            *aDecision = nsIContentPolicy::REJECT_SERVER;
+          }
+        }
+        break;
+
+      case nsIContentPolicy::TYPE_OBJECT:
+        *aDecision = nsIContentPolicy::REJECT_SERVER;
+        break;
+
+      default:
+        *aDecision = nsIContentPolicy::ACCEPT;
+    }
+
+    // Only cache and return if we are successful. If not, we want the error
+    // to be reported, and thus fallback to the slow path.
+    if (*aDecision == nsIContentPolicy::ACCEPT) {
+      return NS_OK;
+    }
+  }
+
+  // ----- END OF TEMPORARY FAST PATH FOR CERTIFIED APPS. -----
+
   // find the principal of the document that initiated this request and see
   // if it has a CSP policy object
   nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));
   nsCOMPtr<nsIPrincipal> principal;
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   if (node) {
     principal = node->NodePrincipal();
     principal->GetCsp(getter_AddRefs(csp));
--- a/content/base/src/nsCSPService.h
+++ b/content/base/src/nsCSPService.h
@@ -18,9 +18,12 @@ class CSPService : public nsIContentPoli
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTENTPOLICY
   NS_DECL_NSICHANNELEVENTSINK
 
   CSPService();
   virtual ~CSPService();
   static bool sCSPEnabled;
+private:
+  // Maps origins to app status.
+  nsDataHashtable<nsCStringHashKey, uint16_t> mAppStatusCache;
 };
--- a/content/media/VideoFrameContainer.cpp
+++ b/content/media/VideoFrameContainer.cpp
@@ -80,17 +80,17 @@ void VideoFrameContainer::ClearCurrentFr
   MutexAutoLock lock(mMutex);
 
   // See comment in SetCurrentFrame for the reasoning behind
   // using a kungFuDeathGrip here.
   nsRefPtr<Image> kungFuDeathGrip;
   kungFuDeathGrip = mImageContainer->LockCurrentImage();
   mImageContainer->UnlockCurrentImage();
 
-  mImageContainer->SetCurrentImage(nullptr);
+  mImageContainer->ClearAllImages();
   mImageSizeChanged = aResetSize;
 }
 
 ImageContainer* VideoFrameContainer::GetImageContainer() {
   return mImageContainer;
 }
 
 
--- a/content/media/omx/MediaOmxReader.cpp
+++ b/content/media/omx/MediaOmxReader.cpp
@@ -340,16 +340,20 @@ bool MediaOmxReader::DecodeAudioData()
                                  frame.mAudioChannels));
   return true;
 }
 
 nsresult MediaOmxReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
+  VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
+  if (container && container->GetImageContainer()) {
+    container->GetImageContainer()->ClearAllImagesExceptFront();
+  }
   mVideoQueue.Reset();
   mAudioQueue.Reset();
 
   mAudioSeekTimeUs = mVideoSeekTimeUs = aTarget;
 
   return DecodeToTarget(aTarget);
 }
 
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1711,53 +1711,78 @@ Navigator::HasCameraSupport(JSContext* /
   return win && nsDOMCameraManager::CheckPermission(win);
 }
 
 #ifdef MOZ_B2G_RIL
 /* static */
 bool
 Navigator::HasTelephonySupport(JSContext* /* unused */, JSObject* aGlobal)
 {
+  // First of all, the general pref has to be turned on.
+  bool enabled = false;
+  Preferences::GetBool("dom.telephony.enabled", &enabled);
+  NS_ENSURE_TRUE(enabled, false);
+
   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
-  return win && Telephony::CheckPermission(win);
+  return win && CheckPermission(win, "telephony");
 }
 
 /* static */
 bool
 Navigator::HasMobileConnectionSupport(JSContext* /* unused */,
                                       JSObject* aGlobal)
 {
+  // First of all, the general pref has to be turned on.
+  bool enabled = false;
+  Preferences::GetBool("dom.mobileconnection.enabled", &enabled);
+  NS_ENSURE_TRUE(enabled, false);
+
   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
   return win && (CheckPermission(win, "mobileconnection") ||
                  CheckPermission(win, "mobilenetwork"));
 }
 
 /* static */
 bool
 Navigator::HasCellBroadcastSupport(JSContext* /* unused */,
                                    JSObject* aGlobal)
 {
+  // First of all, the general pref has to be turned on.
+  bool enabled = false;
+  Preferences::GetBool("dom.cellbroadcast.enabled", &enabled);
+  NS_ENSURE_TRUE(enabled, false);
+
   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
   return win && CheckPermission(win, "cellbroadcast");
 }
 
 /* static */
 bool
 Navigator::HasVoicemailSupport(JSContext* /* unused */,
                                JSObject* aGlobal)
 {
+  // First of all, the general pref has to be turned on.
+  bool enabled = false;
+  Preferences::GetBool("dom.voicemail.enabled", &enabled);
+  NS_ENSURE_TRUE(enabled, false);
+
   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
   return win && CheckPermission(win, "voicemail");
 }
 
 /* static */
 bool
 Navigator::HasIccManagerSupport(JSContext* /* unused */,
                                 JSObject* aGlobal)
 {
+  // First of all, the general pref has to be turned on.
+  bool enabled = false;
+  Preferences::GetBool("dom.icc.enabled", &enabled);
+  NS_ENSURE_TRUE(enabled, false);
+
   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
   return win && CheckPermission(win, "mobileconnection");
 }
 #endif // MOZ_B2G_RIL
 
 #ifdef MOZ_B2G_BT
 /* static */
 bool
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -874,16 +874,85 @@ BluetoothAdapter::IsScoConnected(ErrorRe
     return nullptr;
   }
   bs->IsScoConnected(results);
 
   return request.forget();
 }
 
 already_AddRefed<DOMRequest>
+BluetoothAdapter::AnswerWaitingCall(ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> win = GetOwner();
+  if (!win) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsRefPtr<DOMRequest> request = new DOMRequest(win);
+  nsRefPtr<BluetoothVoidReplyRunnable> results =
+    new BluetoothVoidReplyRunnable(request);
+
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+  bs->AnswerWaitingCall(results);
+
+  return request.forget();
+}
+
+already_AddRefed<DOMRequest>
+BluetoothAdapter::IgnoreWaitingCall(ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> win = GetOwner();
+  if (!win) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsRefPtr<DOMRequest> request = new DOMRequest(win);
+  nsRefPtr<BluetoothVoidReplyRunnable> results =
+    new BluetoothVoidReplyRunnable(request);
+
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+  bs->IgnoreWaitingCall(results);
+
+  return request.forget();
+}
+
+already_AddRefed<DOMRequest>
+BluetoothAdapter::ToggleCalls(ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> win = GetOwner();
+  if (!win) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsRefPtr<DOMRequest> request = new DOMRequest(win);
+  nsRefPtr<BluetoothVoidReplyRunnable> results =
+    new BluetoothVoidReplyRunnable(request);
+
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+  bs->ToggleCalls(results);
+
+  return request.forget();
+}
+
+already_AddRefed<DOMRequest>
 BluetoothAdapter::SendMediaMetaData(const MediaMetaData& aMediaMetaData, ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> win = GetOwner();
   if (!win) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
--- a/dom/bluetooth/BluetoothAdapter.h
+++ b/dom/bluetooth/BluetoothAdapter.h
@@ -132,16 +132,20 @@ public:
   already_AddRefed<DOMRequest>
     ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirmation,
                          ErrorResult& aRv);
 
   already_AddRefed<DOMRequest> ConnectSco(ErrorResult& aRv);
   already_AddRefed<DOMRequest> DisconnectSco(ErrorResult& aRv);
   already_AddRefed<DOMRequest> IsScoConnected(ErrorResult& aRv);
 
+  already_AddRefed<DOMRequest> AnswerWaitingCall(ErrorResult& aRv);
+  already_AddRefed<DOMRequest> IgnoreWaitingCall(ErrorResult& aRv);
+  already_AddRefed<DOMRequest> ToggleCalls(ErrorResult& aRv);
+
   already_AddRefed<DOMRequest>
     SendMediaMetaData(const MediaMetaData& aMediaMetaData, ErrorResult& aRv);
   already_AddRefed<DOMRequest>
     SendMediaPlayStatus(const MediaPlayStatus& aMediaPlayStatus, ErrorResult& aRv);
 
   IMPL_EVENT_HANDLER(devicefound);
   IMPL_EVENT_HANDLER(a2dpstatuschanged);
   IMPL_EVENT_HANDLER(hfpstatuschanged);
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -137,32 +137,16 @@ static CINDItem sCINDItems[] = {
   {"call", "0,1", CallState::NO_CALL, true},
   {"callheld", "0-2", CallHeldState::NO_CALLHELD, true},
   {"callsetup", "0-3", CallSetupState::NO_CALLSETUP, true},
   {"service", "0,1", 0, true},
   {"signal", "0-5", 0, true},
   {"roam", "0,1", 0, true}
 };
 
-class mozilla::dom::bluetooth::Call {
-  public:
-    Call(uint16_t aState = nsITelephonyProvider::CALL_STATE_DISCONNECTED,
-         bool aDirection = false,
-         const nsAString& aNumber = EmptyString(),
-         int aType = TOA_UNKNOWN)
-      : mState(aState), mDirection(aDirection), mNumber(aNumber), mType(aType)
-    {
-    }
-
-    uint16_t mState;
-    bool mDirection; // true: incoming call; false: outgoing call
-    nsString mNumber;
-    int mType;
-};
-
 class BluetoothHfpManager::GetVolumeTask : public nsISettingsServiceCallback
 {
 public:
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD
   Handle(const nsAString& aName, const JS::Value& aResult)
   {
@@ -308,29 +292,59 @@ IsValidDtmf(const char aChar) {
 
 static bool
 IsMandatoryIndicator(const CINDType aType) {
   return (aType == CINDType::CALL) ||
          (aType == CINDType::CALLHELD) ||
          (aType == CINDType::CALLSETUP);
 }
 
+/**
+ *  Call
+ */
+Call::Call()
+{
+  Reset();
+}
+
+void
+Call::Reset()
+{
+  mState = nsITelephonyProvider::CALL_STATE_DISCONNECTED;
+  mDirection = false;
+  mNumber.Truncate();
+  mType = TOA_UNKNOWN;
+}
+
+bool
+Call::IsActive()
+{
+  return (mState == nsITelephonyProvider::CALL_STATE_CONNECTED);
+}
+
+/**
+ *  BluetoothHfpManager
+ */
 BluetoothHfpManager::BluetoothHfpManager()
 {
   Reset();
 }
 
 void
 BluetoothHfpManager::ResetCallArray()
 {
   mCurrentCallArray.Clear();
   // Append a call object at the beginning of mCurrentCallArray since call
   // index from RIL starts at 1.
   Call call;
   mCurrentCallArray.AppendElement(call);
+
+  if (mPhoneType == PhoneType::CDMA) {
+    mCdmaSecondCall.Reset();
+  }
 }
 
 void
 BluetoothHfpManager::Reset()
 {
   sStopSendingRingFlag = true;
   sCINDItems[CINDType::CALL].value = CallState::NO_CALL;
   sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP;
@@ -545,16 +559,20 @@ BluetoothHfpManager::HandleVoiceConnecti
   nsCOMPtr<nsIMobileConnectionProvider> connection =
     do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
   NS_ENSURE_TRUE_VOID(connection);
 
   nsCOMPtr<nsIDOMMozMobileConnectionInfo> voiceInfo;
   connection->GetVoiceConnectionInfo(getter_AddRefs(voiceInfo));
   NS_ENSURE_TRUE_VOID(voiceInfo);
 
+  nsString type;
+  voiceInfo->GetType(type);
+  mPhoneType = GetPhoneType(type);
+
   bool roaming;
   voiceInfo->GetRoaming(&roaming);
   UpdateCIND(CINDType::ROAM, roaming);
 
   bool service = false;
   nsString regState;
   voiceInfo->GetState(regState);
   if (regState.EqualsLiteral("registered")) {
@@ -642,20 +660,25 @@ BluetoothHfpManager::ReceiveSocketData(B
   nsAutoCString msg((const char*)aMessage->mData.get(), aMessage->mSize);
   msg.StripWhitespace();
 
   nsTArray<nsCString> atCommandValues;
 
   // For more information, please refer to 4.34.1 "Bluetooth Defined AT
   // Capabilities" in Bluetooth hands-free profile 1.6
   if (msg.Find("AT+BRSF=") != -1) {
-    uint32_t brsf = BRSF_BIT_THREE_WAY_CALLING |
-                    BRSF_BIT_ABILITY_TO_REJECT_CALL |
+    uint32_t brsf = BRSF_BIT_ABILITY_TO_REJECT_CALL |
                     BRSF_BIT_ENHANCED_CALL_STATUS;
 
+    // No support for three way calling in CDMA since
+    // CDMA disallows to hang existing call for CHLD=1
+    if (mPhoneType != PhoneType::CDMA) {
+      brsf |= BRSF_BIT_THREE_WAY_CALLING;
+    }
+
     if (mBSIR) {
       brsf |= BRSF_BIT_IN_BAND_RING_TONE;
     }
 
     SendCommand("+BRSF: ", brsf);
   } else if (msg.Find("AT+CIND=?") != -1) {
     // Asking for CIND range
     SendCommand("+CIND: ", 0);
@@ -1071,16 +1094,78 @@ BluetoothHfpManager::Disconnect(Bluetoot
 
   MOZ_ASSERT(!mController);
 
   mController = aController;
   mSocket->Disconnect();
   mSocket = nullptr;
 }
 
+void
+BluetoothHfpManager::SendCCWA(const nsAString& aNumber, int aType)
+{
+  if (mCCWA) {
+    nsAutoCString ccwaMsg("+CCWA: \"");
+    ccwaMsg.Append(NS_ConvertUTF16toUTF8(aNumber));
+    ccwaMsg.AppendLiteral("\",");
+    ccwaMsg.AppendInt(aType);
+    SendLine(ccwaMsg.get());
+  }
+}
+
+bool
+BluetoothHfpManager::SendCLCC(const Call& aCall, int aIndex)
+{
+  if (aCall.mState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
+    return true;
+  }
+
+  nsAutoCString message("+CLCC: ");
+  message.AppendInt(aIndex);
+  message.AppendLiteral(",");
+  message.AppendInt(aCall.mDirection);
+  message.AppendLiteral(",");
+
+  int status = 0;
+  switch (aCall.mState) {
+    case nsITelephonyProvider::CALL_STATE_CONNECTED:
+      if (mPhoneType == PhoneType::CDMA && aIndex == 1) {
+        status = (mCdmaSecondCall.IsActive()) ? 1 : 0;
+      }
+      message.AppendInt(status);
+      break;
+    case nsITelephonyProvider::CALL_STATE_HELD:
+      message.AppendInt(1);
+      break;
+    case nsITelephonyProvider::CALL_STATE_DIALING:
+      message.AppendInt(2);
+      break;
+    case nsITelephonyProvider::CALL_STATE_ALERTING:
+      message.AppendInt(3);
+      break;
+    case nsITelephonyProvider::CALL_STATE_INCOMING:
+      if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+        message.AppendInt(4);
+      } else {
+        message.AppendInt(5);
+      }
+      break;
+    default:
+      BT_WARNING("Not handling call status for CLCC");
+      break;
+  }
+
+  message.AppendLiteral(",0,0,\"");
+  message.Append(NS_ConvertUTF16toUTF8(aCall.mNumber));
+  message.AppendLiteral("\",");
+  message.AppendInt(aCall.mType);
+
+  return SendLine(message.get());
+}
+
 bool
 BluetoothHfpManager::SendLine(const char* aMessage)
 {
   MOZ_ASSERT(mSocket);
 
   nsAutoCString msg;
 
   msg.AppendLiteral(kHfpCrlf);
@@ -1138,59 +1223,28 @@ BluetoothHfpManager::SendCommand(const c
           break;
         }
         message.AppendLiteral(",");
       }
     }
   } else if (!strcmp(aCommand, "+CLCC: ")) {
     bool rv = true;
     uint32_t callNumbers = mCurrentCallArray.Length();
-    for (uint32_t i = 1; i < callNumbers; i++) {
-      Call& call = mCurrentCallArray[i];
-      if (call.mState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
-        continue;
-      }
-
-      message.AssignLiteral("+CLCC: ");
-      message.AppendInt(i);
-      message.AppendLiteral(",");
-      message.AppendInt(call.mDirection);
-      message.AppendLiteral(",");
+    uint32_t i;
+    for (i = 1; i < callNumbers; i++) {
+      rv &= SendCLCC(mCurrentCallArray[i], i);
+    }
 
-      switch (call.mState) {
-        case nsITelephonyProvider::CALL_STATE_CONNECTED:
-          message.AppendInt(0);
-          break;
-        case nsITelephonyProvider::CALL_STATE_HELD:
-          message.AppendInt(1);
-          break;
-        case nsITelephonyProvider::CALL_STATE_DIALING:
-          message.AppendInt(2);
-          break;
-        case nsITelephonyProvider::CALL_STATE_ALERTING:
-          message.AppendInt(3);
-          break;
-        case nsITelephonyProvider::CALL_STATE_INCOMING:
-          if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
-            message.AppendInt(4);
-          } else {
-            message.AppendInt(5);
-          }
-          break;
-        default:
-          BT_WARNING("Not handling call status for CLCC");
-          break;
-      }
-      message.AppendLiteral(",0,0,\"");
-      message.Append(NS_ConvertUTF16toUTF8(call.mNumber));
-      message.AppendLiteral("\",");
-      message.AppendInt(call.mType);
+    if (!mCdmaSecondCall.mNumber.IsEmpty()) {
+      MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
+      MOZ_ASSERT(i == 2);
 
-      rv &= SendLine(message.get());
+      rv &= SendCLCC(mCdmaSecondCall, 2);
     }
+
     return rv;
   } else {
     message.AppendInt(aValue);
   }
 
   return SendLine(message.get());
 }
 
@@ -1271,23 +1325,17 @@ BluetoothHfpManager::HandleCallStateChan
         sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_NOACTIVE;
       } else {
         sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
       }
       SendCommand("+CIEV: ", CINDType::CALLHELD);
       break;
     case nsITelephonyProvider::CALL_STATE_INCOMING:
       if (FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
-        if (mCCWA) {
-          nsAutoCString ccwaMsg("+CCWA: \"");
-          ccwaMsg.Append(NS_ConvertUTF16toUTF8(aNumber));
-          ccwaMsg.AppendLiteral("\",");
-          ccwaMsg.AppendInt(mCurrentCallArray[aCallIndex].mType);
-          SendLine(ccwaMsg.get());
-        }
+        SendCCWA(aNumber, mCurrentCallArray[aCallIndex].mType);
         UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend);
       } else {
         // Start sending RING indicator to HF
         sStopSendingRingFlag = false;
         UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend);
 
         if (mBSIR) {
           // Setup audio connection for in-band ring tone
@@ -1405,16 +1453,87 @@ BluetoothHfpManager::HandleCallStateChan
       }
       break;
     default:
       BT_WARNING("Not handling state changed");
       break;
   }
 }
 
+PhoneType
+BluetoothHfpManager::GetPhoneType(const nsAString& aType)
+{
+  // FIXME: Query phone type from RIL after RIL implements new API (bug 912019)
+  if (aType.EqualsLiteral("gsm") || aType.EqualsLiteral("gprs") ||
+      aType.EqualsLiteral("edge") || aType.EqualsLiteral("umts") ||
+      aType.EqualsLiteral("hspa") || aType.EqualsLiteral("hsdpa") ||
+      aType.EqualsLiteral("hsupa") || aType.EqualsLiteral("hspa+")) {
+    return PhoneType::GSM;
+  } else if (aType.EqualsLiteral("is95a") || aType.EqualsLiteral("is95b") ||
+             aType.EqualsLiteral("1xrtt") || aType.EqualsLiteral("evdo0") ||
+             aType.EqualsLiteral("evdoa") || aType.EqualsLiteral("evdob")) {
+    return PhoneType::CDMA;
+  }
+
+  return PhoneType::NONE;
+}
+
+void
+BluetoothHfpManager::UpdateSecondNumber(const nsAString& aNumber)
+{
+  MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
+
+  // Always regard second call as incoming call since v1.2 RIL
+  // doesn't support outgoing second call in CDMA.
+  mCdmaSecondCall.mDirection = true;
+
+  mCdmaSecondCall.mNumber = aNumber;
+  mCdmaSecondCall.mType = (aNumber[0] == '+') ? TOA_INTERNATIONAL :
+                                                TOA_UNKNOWN;
+
+  SendCCWA(aNumber, mCdmaSecondCall.mType);
+  UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, true);
+}
+
+void
+BluetoothHfpManager::AnswerWaitingCall()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
+
+  // Pick up second call. First call is held now.
+  mCdmaSecondCall.mState = nsITelephonyProvider::CALL_STATE_CONNECTED;
+  UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, true);
+
+  sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
+  SendCommand("+CIEV: ", CINDType::CALLHELD);
+}
+
+void
+BluetoothHfpManager::IgnoreWaitingCall()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
+
+  mCdmaSecondCall.Reset();
+  UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, true);
+}
+
+void
+BluetoothHfpManager::ToggleCalls()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
+
+  // Toggle acitve and held calls
+  mCdmaSecondCall.mState = (mCdmaSecondCall.IsActive()) ?
+                             nsITelephonyProvider::CALL_STATE_HELD :
+                             nsITelephonyProvider::CALL_STATE_CONNECTED;
+}
+
 void
 BluetoothHfpManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
 {
   MOZ_ASSERT(aSocket);
   MOZ_ASSERT(mListener);
 
   // Success to create a SCO socket
   if (aSocket == mScoSocket) {
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -45,16 +45,34 @@ enum BluetoothCmeError {
   INVALID_CHARACTERS_IN_TEXT_STRING = 25,
   DIAL_STRING_TOO_LONG = 26,
   INVALID_CHARACTERS_IN_DIAL_STRING = 27,
   NO_NETWORK_SERVICE = 30,
   NETWORK_TIMEOUT = 31,
   NETWORK_NOT_ALLOWED = 32
 };
 
+enum PhoneType {
+  NONE, // no connection
+  GSM,
+  CDMA
+};
+
+class Call {
+public:
+  Call();
+  void Reset();
+  bool IsActive();
+
+  uint16_t mState;
+  bool mDirection; // true: incoming call; false: outgoing call
+  nsString mNumber;
+  int mType;
+};
+
 class BluetoothHfpManager : public BluetoothSocketObserver
                           , public BluetoothProfileManagerBase
                           , public BatteryObserver
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
@@ -98,16 +116,22 @@ public:
                               const nsAString& aError, const nsAString& aNumber,
                               const bool aIsOutgoing, bool aSend);
   void HandleIccInfoChanged();
   void HandleVoiceConnectionChanged();
 
   bool IsConnected();
   bool IsScoConnected();
 
+  // CDMA-specific functions
+  void UpdateSecondNumber(const nsAString& aNumber);
+  void AnswerWaitingCall();
+  void IgnoreWaitingCall();
+  void ToggleCalls();
+
 private:
   class CloseScoTask;
   class GetVolumeTask;
   class RespondToBLDNTask;
   class SendRingIndicatorTask;
 
   friend class CloseScoTask;
   friend class GetVolumeTask;
@@ -120,36 +144,40 @@ private:
   void HandleVolumeChanged(const nsAString& aData);
 
   bool Init();
   void Notify(const hal::BatteryInformation& aBatteryInfo);
   void Reset();
   void ResetCallArray();
   uint32_t FindFirstCall(uint16_t aState);
   uint32_t GetNumberOfCalls(uint16_t aState);
+  PhoneType GetPhoneType(const nsAString& aType);
 
   void NotifyConnectionStatusChanged(const nsAString& aType);
   void NotifyDialer(const nsAString& aCommand);
 
+  void SendCCWA(const nsAString& aNumber, int aType);
+  bool SendCLCC(const Call& aCall, int aIndex);
   bool SendCommand(const char* aCommand, uint32_t aValue = 0);
   bool SendLine(const char* aMessage);
   void UpdateCIND(uint8_t aType, uint8_t aValue, bool aSend = true);
   void OnScoConnectSuccess();
   void OnScoConnectError();
   void OnScoDisconnect();
 
   int mCurrentVgs;
   int mCurrentVgm;
   bool mBSIR;
   bool mCCWA;
   bool mCLIP;
   bool mCMEE;
   bool mCMER;
   bool mFirstCKPD;
   int mNetworkSelectionMode;
+  PhoneType mPhoneType;
   bool mReceiveVgsFlag;
   bool mDialingRequestProcessed;
   nsString mDeviceAddress;
   nsString mMsisdn;
   nsString mOperatorName;
 
   nsTArray<Call> mCurrentCallArray;
   nsAutoPtr<BluetoothRilListener> mListener;
@@ -165,13 +193,16 @@ private:
 
   // Server sockets. Once an inbound connection is established, it will hand
   // over the ownership to mSocket, and get a new server socket while Listen()
   // is called.
   nsRefPtr<BluetoothSocket> mHandsfreeSocket;
   nsRefPtr<BluetoothSocket> mHeadsetSocket;
   nsRefPtr<BluetoothSocket> mScoSocket;
   SocketConnectionStatus mScoSocketStatus;
+
+  // CDMA-specific variable
+  Call mCdmaSecondCall;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/BluetoothRilListener.cpp
+++ b/dom/bluetooth/BluetoothRilListener.cpp
@@ -209,16 +209,19 @@ TelephonyListener::SupplementaryServiceN
                                                     uint16_t aNotification)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TelephonyListener::NotifyCdmaCallWaiting(const nsAString& aNumber)
 {
+  BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
+  hfp->UpdateSecondNumber(aNumber);
+
   return NS_OK;
 }
 
 } // anonymous namespace
 
 /**
  *  BluetoothRilListener
  */
--- a/dom/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -39,17 +39,19 @@
 #include "nsXPCOM.h"
 
 #if defined(MOZ_WIDGET_GONK)
 #include "cutils/properties.h"
 #endif
 
 #if defined(MOZ_B2G_BT)
 # if defined(MOZ_BLUETOOTH_GONK)
-#  include "BluetoothGonkService.h"
+#ifndef MOZ_B2G_BT_BLUEDROID
+#include "BluetoothGonkService.h"
+#endif
 # elif defined(MOZ_BLUETOOTH_DBUS)
 #  include "BluetoothDBusService.h"
 # else
 #  error No_suitable_backend_for_bluetooth!
 # endif
 #endif
 
 #define MOZSETTINGS_CHANGED_ID      "mozsettings-changed"
@@ -299,20 +301,24 @@ BluetoothService::Create()
 {
 #if defined(MOZ_B2G_BT)
   if (!IsMainProcess()) {
     return BluetoothServiceChildProcess::Create();
   }
 #endif
 
 #if defined(MOZ_BLUETOOTH_GONK)
+#ifndef MOZ_B2G_BT_BLUEDROID
   return new BluetoothGonkService();
+#endif
 #elif defined(MOZ_BLUETOOTH_DBUS)
+#ifdef MOZ_B2G_BT_BLUEZ
   return new BluetoothDBusService();
 #endif
+#endif
   BT_WARNING("No platform support for bluetooth!");
   return nullptr;
 }
 
 bool
 BluetoothService::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -262,16 +262,25 @@ public:
 
   virtual void
   DisconnectSco(BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
   IsScoConnected(BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
+  AnswerWaitingCall(BluetoothReplyRunnable* aRunnable) = 0;
+
+  virtual void
+  IgnoreWaitingCall(BluetoothReplyRunnable* aRunnable) = 0;
+
+  virtual void
+  ToggleCalls(BluetoothReplyRunnable* aRunnable) = 0;
+
+  virtual void
   SendMetaData(const nsAString& aTitle,
                const nsAString& aArtist,
                const nsAString& aAlbum,
                int64_t aMediaNumber,
                int64_t aTotalMediaCount,
                int64_t aDuration,
                BluetoothReplyRunnable* aRunnable) = 0;
 
--- a/dom/bluetooth/BluetoothUnixSocketConnector.cpp
+++ b/dom/bluetooth/BluetoothUnixSocketConnector.cpp
@@ -22,32 +22,34 @@
  */
 
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
 
 #include <sys/socket.h>
+#ifdef MOZ_B2G_BT_BLUEZ
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/l2cap.h>
 #include <bluetooth/rfcomm.h>
 #include <bluetooth/sco.h>
-
+#endif
 #include "BluetoothUnixSocketConnector.h"
 #include "nsThreadUtils.h"
 
 using namespace mozilla::ipc;
 USING_BLUETOOTH_NAMESPACE
 
 static const int RFCOMM_SO_SNDBUF = 70 * 1024;  // 70 KB send buffer
 static const int L2CAP_SO_SNDBUF = 400 * 1024;  // 400 KB send buffer
 static const int L2CAP_SO_RCVBUF = 400 * 1024;  // 400 KB receive buffer
 static const int L2CAP_MAX_MTU = 65000;
 
+#ifdef MOZ_B2G_BT_BLUEZ
 static
 int get_bdaddr(const char *str, bdaddr_t *ba)
 {
   char *d = ((char*)ba) + 5, *endp;
   for (int i = 0; i < 6; i++) {
     *d-- = strtol(str, &endp, 16);
     MOZ_ASSERT(!(*endp != ':' && i != 5));
     str = endp + 1;
@@ -57,30 +59,33 @@ int get_bdaddr(const char *str, bdaddr_t
 
 static
 void get_bdaddr_as_string(const bdaddr_t *ba, char *str) {
     const uint8_t *b = (const uint8_t *)ba;
     sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
             b[5], b[4], b[3], b[2], b[1], b[0]);
 }
 
+#endif
+
 BluetoothUnixSocketConnector::BluetoothUnixSocketConnector(
   BluetoothSocketType aType,
   int aChannel,
   bool aAuth,
   bool aEncrypt) : mType(aType)
                  , mChannel(aChannel)
                  , mAuth(aAuth)
                  , mEncrypt(aEncrypt)
 {
 }
 
 bool
 BluetoothUnixSocketConnector::SetUp(int aFd)
 {
+#ifdef MOZ_B2G_BT_BLUEZ
   int lm = 0;
   int sndbuf, rcvbuf;
 
   /* kernel does not yet support LM for SCO */
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     lm |= mAuth ? RFCOMM_LM_AUTH : 0;
     lm |= mEncrypt ? RFCOMM_LM_ENCRYPT : 0;
@@ -152,26 +157,27 @@ BluetoothUnixSocketConnector::SetUp(int 
 
       rcvbuf = L2CAP_SO_RCVBUF;
       if (setsockopt(aFd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) {
         BT_WARNING("setsockopt(SO_RCVBUF) failed, throwing");
         return false;
       }
     }
   }
-
+#endif
   return true;
 }
 
 int
 BluetoothUnixSocketConnector::Create()
 {
   MOZ_ASSERT(!NS_IsMainThread());
   int fd = -1;
 
+#ifdef MOZ_B2G_BT_BLUEZ
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
     break;
   case BluetoothSocketType::SCO:
     fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
     break;
   case BluetoothSocketType::L2CAP:
@@ -188,26 +194,27 @@ BluetoothUnixSocketConnector::Create()
     BT_WARNING("Could not open bluetooth socket!");
     return -1;
   }
 
   if (!SetUp(fd)) {
     BT_WARNING("Could not set up socket!");
     return -1;
   }
-
+#endif
   return fd;
 }
 
 bool
 BluetoothUnixSocketConnector::CreateAddr(bool aIsServer,
                                          socklen_t& aAddrSize,
                                          sockaddr_any& aAddr,
                                          const char* aAddress)
 {
+#ifdef MOZ_B2G_BT_BLUEZ
   // Set to BDADDR_ANY, if it's not a server, we'll reset.
   bdaddr_t bd_address_obj = {{0, 0, 0, 0, 0, 0}};
 
   if (!aIsServer && aAddress && strlen(aAddress) > 0) {
     if (get_bdaddr(aAddress, &bd_address_obj)) {
       BT_WARNING("Can't get bluetooth address!");
       return false;
     }
@@ -237,32 +244,35 @@ BluetoothUnixSocketConnector::CreateAddr
     aAddrSize = sizeof(addr_sco);
     aAddr.sco.sco_family = AF_BLUETOOTH;
     memcpy(&aAddr.sco.sco_bdaddr, &bd_address_obj, sizeof(bd_address_obj));
     break;
   default:
     BT_WARNING("Socket type unknown!");
     return false;
   }
+#endif
   return true;
 }
 
 void
 BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr_any& aAddr,
                                             nsAString& aAddrStr)
 {
+#ifdef MOZ_B2G_BT_BLUEZ
   char addr[18];
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     get_bdaddr_as_string((bdaddr_t*)(&aAddr.rc.rc_bdaddr), addr);
     break;
   case BluetoothSocketType::SCO:
     get_bdaddr_as_string((bdaddr_t*)(&aAddr.sco.sco_bdaddr), addr);
     break;
   case BluetoothSocketType::L2CAP:
   case BluetoothSocketType::EL2CAP:
     get_bdaddr_as_string((bdaddr_t*)(&aAddr.l2.l2_bdaddr), addr);
     break;
   default:
     MOZ_CRASH("Socket should be either RFCOMM or SCO!");
   }
   aAddrStr.AssignASCII(addr);
+#endif
 }
--- a/dom/bluetooth/Makefile.in
+++ b/dom/bluetooth/Makefile.in
@@ -31,16 +31,24 @@ ifdef MOZ_ENABLE_DBUS
 VPATH += $(srcdir)/linux
 LOCAL_INCLUDES += $(MOZ_DBUS_CFLAGS)
 CFLAGS += $(MOZ_DBUS_GLIB_CFLAGS)
 CXXFLAGS += $(MOZ_DBUS_GLIB_CFLAGS) -DHAVE_PTHREADS
 DEFINES += -DMOZ_BLUETOOTH_DBUS
 endif
 endif
 
+ifdef MOZ_B2G_BT_BLUEZ
+DEFINES += -DMOZ_B2G_BT_BLUEZ
+endif
+
+ifdef MOZ_B2G_BT_BLUEDROID
+DEFINES += -DMOZ_B2G_BT_BLUEDROID
+endif
+
 # Add VPATH to LOCAL_INCLUDES so we are going to include the correct backend
 # subdirectory.
 LOCAL_INCLUDES += $(VPATH:%=-I%)
 
 endif # MOZ_B2G_BT
 
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
--- a/dom/bluetooth/ipc/BluetoothParent.cpp
+++ b/dom/bluetooth/ipc/BluetoothParent.cpp
@@ -221,16 +221,22 @@ BluetoothParent::RecvPBluetoothRequestCo
     case Request::TDenyReceivingFileRequest:
       return actor->DoRequest(aRequest.get_DenyReceivingFileRequest());
     case Request::TConnectScoRequest:
       return actor->DoRequest(aRequest.get_ConnectScoRequest());
     case Request::TDisconnectScoRequest:
       return actor->DoRequest(aRequest.get_DisconnectScoRequest());
     case Request::TIsScoConnectedRequest:
       return actor->DoRequest(aRequest.get_IsScoConnectedRequest());
+    case Request::TAnswerWaitingCallRequest:
+      return actor->DoRequest(aRequest.get_AnswerWaitingCallRequest());
+    case Request::TIgnoreWaitingCallRequest:
+      return actor->DoRequest(aRequest.get_IgnoreWaitingCallRequest());
+    case Request::TToggleCallsRequest:
+      return actor->DoRequest(aRequest.get_ToggleCallsRequest());
     case Request::TSendMetaDataRequest:
       return actor->DoRequest(aRequest.get_SendMetaDataRequest());
     case Request::TSendPlayStatusRequest:
       return actor->DoRequest(aRequest.get_SendPlayStatusRequest());
     default:
       MOZ_CRASH("Unknown type!");
   }
 
@@ -571,16 +577,49 @@ BluetoothRequestParent::DoRequest(const 
   MOZ_ASSERT(mService);
   MOZ_ASSERT(mRequestType == Request::TIsScoConnectedRequest);
 
   mService->IsScoConnected(mReplyRunnable.get());
   return true;
 }
 
 bool
+BluetoothRequestParent::DoRequest(const AnswerWaitingCallRequest& aRequest)
+{
+  MOZ_ASSERT(mService);
+  MOZ_ASSERT(mRequestType == Request::TAnswerWaitingCallRequest);
+
+  mService->AnswerWaitingCall(mReplyRunnable.get());
+
+  return true;
+}
+
+bool
+BluetoothRequestParent::DoRequest(const IgnoreWaitingCallRequest& aRequest)
+{
+  MOZ_ASSERT(mService);
+  MOZ_ASSERT(mRequestType == Request::TAnswerWaitingCallRequest);
+
+  mService->IgnoreWaitingCall(mReplyRunnable.get());
+
+  return true;
+}
+
+bool
+BluetoothRequestParent::DoRequest(const ToggleCallsRequest& aRequest)
+{
+  MOZ_ASSERT(mService);
+  MOZ_ASSERT(mRequestType == Request::TAnswerWaitingCallRequest);
+
+  mService->ToggleCalls(mReplyRunnable.get());
+
+  return true;
+}
+
+bool
 BluetoothRequestParent::DoRequest(const SendMetaDataRequest& aRequest)
 {
   MOZ_ASSERT(mService);
   MOZ_ASSERT(mRequestType == Request::TSendMetaDataRequest);
 
   mService->SendMetaData(aRequest.title(),
                          aRequest.artist(),
                          aRequest.album(),
--- a/dom/bluetooth/ipc/BluetoothParent.h
+++ b/dom/bluetooth/ipc/BluetoothParent.h
@@ -186,16 +186,25 @@ protected:
 
   bool
   DoRequest(const DisconnectScoRequest& aRequest);
 
   bool
   DoRequest(const IsScoConnectedRequest& aRequest);
 
   bool
+  DoRequest(const AnswerWaitingCallRequest& aRequest);
+
+  bool
+  DoRequest(const IgnoreWaitingCallRequest& aRequest);
+
+  bool
+  DoRequest(const ToggleCallsRequest& aRequest);
+
+  bool
   DoRequest(const SendMetaDataRequest& aRequest);
 
   bool
   DoRequest(const SendPlayStatusRequest& aRequest);
 };
 
 END_BLUETOOTH_NAMESPACE
 
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
@@ -324,16 +324,37 @@ BluetoothServiceChildProcess::Disconnect
 
 void
 BluetoothServiceChildProcess::IsScoConnected(BluetoothReplyRunnable* aRunnable)
 {
   SendRequest(aRunnable, IsScoConnectedRequest());
 }
 
 void
+BluetoothServiceChildProcess::AnswerWaitingCall(
+  BluetoothReplyRunnable* aRunnable)
+{
+  SendRequest(aRunnable, AnswerWaitingCallRequest());
+}
+
+void
+BluetoothServiceChildProcess::IgnoreWaitingCall(
+  BluetoothReplyRunnable* aRunnable)
+{
+  SendRequest(aRunnable, IgnoreWaitingCallRequest());
+}
+
+void
+BluetoothServiceChildProcess::ToggleCalls(
+  BluetoothReplyRunnable* aRunnable)
+{
+  SendRequest(aRunnable, ToggleCallsRequest());
+}
+
+void
 BluetoothServiceChildProcess::SendMetaData(const nsAString& aTitle,
                                            const nsAString& aArtist,
                                            const nsAString& aAlbum,
                                            int64_t aMediaNumber,
                                            int64_t aTotalMediaCount,
                                            int64_t aDuration,
                                            BluetoothReplyRunnable* aRunnable)
 {
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
@@ -145,16 +145,25 @@ public:
 
   virtual void
   DisconnectSco(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual void
   IsScoConnected(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual void
+  AnswerWaitingCall(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
+
+  virtual void
+  IgnoreWaitingCall(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
+
+  virtual void
+  ToggleCalls(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
+
+  virtual void
   SendMetaData(const nsAString& aTitle,
                const nsAString& aArtist,
                const nsAString& aAlbum,
                int64_t aMediaNumber,
                int64_t aTotalMediaCount,
                int64_t aDuration,
                BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
--- a/dom/bluetooth/ipc/PBluetooth.ipdl
+++ b/dom/bluetooth/ipc/PBluetooth.ipdl
@@ -129,16 +129,28 @@ struct ConnectScoRequest
 struct DisconnectScoRequest
 {
 };
 
 struct IsScoConnectedRequest
 {
 };
 
+struct AnswerWaitingCallRequest
+{
+};
+
+struct IgnoreWaitingCallRequest
+{
+};
+
+struct ToggleCallsRequest
+{
+};
+
 struct SendMetaDataRequest
 {
   nsString title;
   nsString artist;
   nsString album;
   int64_t mediaNumber;
   int64_t totalMediaCount;
   int64_t duration;
@@ -170,16 +182,19 @@ union Request
   DisconnectRequest;
   SendFileRequest;
   StopSendingFileRequest;
   ConfirmReceivingFileRequest;
   DenyReceivingFileRequest;
   ConnectScoRequest;
   DisconnectScoRequest;
   IsScoConnectedRequest;
+  AnswerWaitingCallRequest;
+  IgnoreWaitingCallRequest;
+  ToggleCallsRequest;
   SendMetaDataRequest;
   SendPlayStatusRequest;
 };
 
 protocol PBluetooth
 {
   manager PContent;
   manages PBluetoothRequest;
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -2626,16 +2626,49 @@ BluetoothDBusService::IsConnected(const 
     BT_WARNING(ERR_UNKNOWN_PROFILE);
     return false;
   }
 
   NS_ENSURE_TRUE(profile, false);
   return profile->IsConnected();
 }
 
+void
+BluetoothDBusService::AnswerWaitingCall(BluetoothReplyRunnable* aRunnable)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
+  hfp->AnswerWaitingCall();
+
+  DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
+}
+
+void
+BluetoothDBusService::IgnoreWaitingCall(BluetoothReplyRunnable* aRunnable)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
+  hfp->IgnoreWaitingCall();
+
+  DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
+}
+
+void
+BluetoothDBusService::ToggleCalls(BluetoothReplyRunnable* aRunnable)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
+  hfp->ToggleCalls();
+
+  DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
+}
+
 class OnUpdateSdpRecordsRunnable : public nsRunnable
 {
 public:
   OnUpdateSdpRecordsRunnable(const nsAString& aObjectPath,
                              BluetoothProfileManagerBase* aManager)
     : mManager(aManager)
   {
     MOZ_ASSERT(!aObjectPath.IsEmpty());
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -19,16 +19,19 @@ BEGIN_BLUETOOTH_NAMESPACE
 /**
  * BluetoothDBusService is the implementation of BluetoothService for DBus on
  * linux/android/B2G. Function comments are in BluetoothService.h
  */
 
 class BluetoothDBusService : public BluetoothService
 {
 public:
+  BluetoothDBusService();
+  ~BluetoothDBusService();
+
   bool IsReady();
 
   virtual nsresult StartInternal() MOZ_OVERRIDE;
 
   virtual nsresult StopInternal() MOZ_OVERRIDE;
 
   virtual bool IsEnabledInternal() MOZ_OVERRIDE;
 
@@ -128,16 +131,25 @@ public:
 
   virtual void
   DisconnectSco(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual void
   IsScoConnected(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual void
+  AnswerWaitingCall(BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  IgnoreWaitingCall(BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  ToggleCalls(BluetoothReplyRunnable* aRunnable);
+
+  virtual void
   SendMetaData(const nsAString& aTitle,
                const nsAString& aArtist,
                const nsAString& aAlbum,
                int64_t aMediaNumber,
                int64_t aTotalMediaCount,
                int64_t aDuration,
                BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
@@ -154,21 +166,16 @@ public:
 
   virtual nsresult
   SendSinkMessage(const nsAString& aDeviceAddresses,
                   const nsAString& aMessage) MOZ_OVERRIDE;
 
   virtual nsresult
   SendInputMessage(const nsAString& aDeviceAddresses,
                    const nsAString& aMessage) MOZ_OVERRIDE;
-
-protected:
-  BluetoothDBusService();
-  ~BluetoothDBusService();
-
 private:
   /**
    * For DBus Control method of "UpdateNotification", event id should be
    * specified as following:
    * (Please see specification of AVRCP 1.3, Table 5.28 for more details.)
    */
   enum ControlEventId {
     EVENT_PLAYBACK_STATUS_CHANGED            = 0x01,
--- a/dom/bluetooth/moz.build
+++ b/dom/bluetooth/moz.build
@@ -47,17 +47,17 @@ if CONFIG['MOZ_B2G_BT']:
         'BluetoothProfileController.cpp'
     ]
 
     if CONFIG['MOZ_B2G_RIL']:
         CPP_SOURCES += [
             'BluetoothRilListener.cpp',
         ]
 
-    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_BT_BLUEZ']:
         CPP_SOURCES += [
             'linux/BluetoothDBusService.cpp',
             'gonk/BluetoothGonkService.cpp',
         ]
     else:
         if CONFIG['MOZ_ENABLE_DBUS']:
             CPP_SOURCES += [
                 'linux/BluetoothDBusService.cpp',
--- a/dom/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -218,17 +218,18 @@ function checkBlobArray(aBlob) {
 function isVanillaObj(aObj) {
   return Object.prototype.toString.call(aObj) == "[object Object]";
 }
 
 function validateArrayField(data, createCb) {
   if (data) {
     data = Array.isArray(data) ? data : [data];
     let filtered = [];
-    for (let obj of data) {
+    for (let i = 0, n = data.length; i < n; ++i) {
+      let obj = data[i];
       if (obj && isVanillaObj(obj)) {
         filtered.push(createCb(obj));
       }
     }
     return filtered;
   }
   return undefined;
 }
--- a/dom/inputmethod/Keyboard.jsm
+++ b/dom/inputmethod/Keyboard.jsm
@@ -184,19 +184,25 @@ this.Keyboard = {
     ppmm.broadcastAsyncMessage(newEventName, msg.data);
   },
 
   handleFocusChange: function keyboardHandleFocusChange(msg) {
     this.forwardEvent('Keyboard:FocusChange', msg);
 
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
 
+    // Chrome event, used also to render value selectors; that's why we need
+    // the info about choices / min / max here as well...
     browser.shell.sendChromeEvent({
       type: 'inputmethod-contextchange',
-      inputType: msg.data.type
+      inputType: msg.data.type,
+      value: msg.data.value,
+      choices: JSON.stringify(msg.data.choices),
+      min: msg.data.min,
+      max: msg.data.max
     });
   },
 
   setSelectedOption: function keyboardSetSelectedOption(msg) {
     this.sendAsyncMessage('Forms:Select:Choice', msg.data);
   },
 
   setSelectedOptions: function keyboardSetSelectedOptions(msg) {
--- a/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl
+++ b/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl
@@ -37,17 +37,17 @@ interface nsIRilMobileMessageDatabaseSer
    *   - If |type| == "sms", we also need:
    *     - |messageClass| DOMString: the message class of received message
    *     - |receiver| DOMString: the phone number of receiver
    *
    *   - If |type| == "mms", we also need:
    *     - |delivery| DOMString: the delivery state of received message
    *     - |deliveryStatus| DOMString Array: the delivery status of received message
    *     - |receivers| DOMString Array: the phone numbers of receivers
-   *     - |msisdn| DOMString: [optional] my own phone number.
+   *     - |phoneNumber| DOMString: [optional] my own phone number.
    *     - |transactionId| DOMString: the transaction ID from MMS PDU header.
    *
    * Note: |deliveryStatus| should only contain single string to specify
    *       the delivery status of MMS message for the phone owner self.
    */
   long saveReceivedMessage(in jsval aMessage,
                 [optional] in nsIRilMobileMessageDatabaseCallback aCallback);
 
--- a/dom/mobilemessage/src/gonk/MmsService.js
+++ b/dom/mobilemessage/src/gonk/MmsService.js
@@ -1227,19 +1227,34 @@ MmsService.prototype = {
         || (config == CONFIG_SEND_REPORT_DEFAULT_YES)) {
       if (wish != null) {
         config += (wish ? 1 : -1);
       }
     }
     return config >= CONFIG_SEND_REPORT_DEFAULT_YES;
   },
 
-  getMsisdn: function getMsisdn() {
+  /**
+   * Get phone number from iccInfo.
+   *
+   * If the icc card is gsm card, the phone number is in msisdn.
+   * @see nsIDOMMozGsmIccInfo
+   *
+   * Otherwise, the phone number is in mdn.
+   * @see nsIDOMMozCdmaIccInfo
+   */
+  getPhoneNumber: function getPhoneNumber() {
     let iccInfo = gRadioInterface.rilContext.iccInfo;
-    let number = iccInfo ? iccInfo.msisdn : null;
+
+    if (!iccInfo) {
+      return null;
+    }
+
+    let number = (iccInfo instanceof Ci.nsIDOMMozGsmIccInfo)
+               ? iccInfo.msisdn : iccInfo.mdn;
 
     // Workaround an xpconnect issue with undefined string objects.
     // See bug 808220
     if (number === undefined || number === "undefined") {
       return null;
     }
     return number;
   },
@@ -1280,17 +1295,17 @@ MmsService.prototype = {
     intermediate.sender = null;
     intermediate.transactionId = intermediate.headers["x-mms-transaction-id"];
     if (intermediate.headers.from) {
       intermediate.sender = intermediate.headers.from.address;
     } else {
       intermediate.sender = "anonymous";
     }
     intermediate.receivers = [];
-    intermediate.msisdn = this.getMsisdn();
+    intermediate.phoneNumber = this.getPhoneNumber();
     return intermediate;
   },
 
   /**
    * Merge the retrieval confirmation into the savable message.
    *
    * @param intermediate
    *        Intermediate MMS message parsed from PDU, which carries
@@ -1766,17 +1781,17 @@ MmsService.prototype = {
         parts.push(part);
       }
     }
 
     // The following attributes are needed for saving message into DB.
     aMessage["type"] = "mms";
     aMessage["timestamp"] = Date.now();
     aMessage["receivers"] = receivers;
-    aMessage["sender"] = this.getMsisdn();
+    aMessage["sender"] = this.getPhoneNumber();
     try {
       aMessage["deliveryStatusRequested"] =
         Services.prefs.getBoolPref("dom.mms.requestStatusReport");
     } catch (e) {
       aMessage["deliveryStatusRequested"] = false;
     }
 
     if (DEBUG) debug("createSavableFromParams: aMessage: " +
--- a/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js
+++ b/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js
@@ -1368,28 +1368,29 @@ MobileMessageDatabaseService.prototype =
       //    If the receivers contain single phone number, we don't need to
       //    add it into participants because we know that number is our own.
       // 3. receivers.length >= 2
       //    If the receivers contain multiple phone numbers, we need to add all
       //    of them but not the user's own number into participants.
       if (receivers.length >= 2) {
         let isSuccess = false;
         let slicedReceivers = receivers.slice();
-        if (aMessage.msisdn) {
-          let found = slicedReceivers.indexOf(aMessage.msisdn);
+        if (aMessage.phoneNumber) {
+          let found = slicedReceivers.indexOf(aMessage.phoneNumber);
           if (found !== -1) {
             isSuccess = true;
             slicedReceivers.splice(found, 1);
           }
         }
 
         if (!isSuccess) {
-          // For some SIMs we cannot retrieve the vaild MSISDN (i.e. the user's
-          // own phone number), so we cannot correcly exclude the user's own
-          // number from the receivers, thus wrongly building the thread index.
+          // For some SIMs we cannot retrieve the vaild MSISDN or MDN (i.e. the
+          // user's own phone number), so we cannot correcly exclude the user's
+          // own number from the receivers, thus wrongly building the thread
+          // index.
           if (DEBUG) debug("Error! Cannot strip out user's own phone number!");
         }
 
         threadParticipants = threadParticipants.concat(slicedReceivers);
       }
     }
 
     let timestamp = aMessage.timestamp;
--- a/dom/system/gonk/AutoMounter.cpp
+++ b/dom/system/gonk/AutoMounter.cpp
@@ -83,16 +83,18 @@ using namespace mozilla::hal;
 #define DBG(args...)
 #endif
 
 namespace mozilla {
 namespace system {
 
 class AutoMounter;
 
+static void SetAutoMounterStatus(int32_t aStatus);
+
 /***************************************************************************/
 
 inline const char* SwitchStateStr(const SwitchEvent& aEvent)
 {
   return aEvent.status() == SWITCH_STATE_ON ? "plugged" : "unplugged";
 }
 
 /***************************************************************************/
@@ -371,16 +373,17 @@ AutoMounter::UpdateState()
       mMode = AUTOMOUNTER_DISABLE;
     }
   }
 
   bool tryToShare = (umsAvail && umsEnabled && enabled && usbCablePluggedIn);
   LOG("UpdateState: umsAvail:%d umsEnabled:%d mode:%d usbCablePluggedIn:%d tryToShare:%d",
       umsAvail, umsEnabled, mMode, usbCablePluggedIn, tryToShare);
 
+  bool filesOpen = false;
   VolumeArray::index_type volIndex;
   VolumeArray::size_type  numVolumes = VolumeManager::NumVolumes();
   for (volIndex = 0; volIndex < numVolumes; volIndex++) {
     RefPtr<Volume>  vol = VolumeManager::GetVolume(volIndex);
     Volume::STATE   volState = vol->State();
 
     if (vol->State() == nsIVolume::STATE_MOUNTED) {
       LOG("UpdateState: Volume %s is %s and %s @ %s gen %d locked %d sharing %c",
@@ -432,16 +435,17 @@ AutoMounter::UpdateState()
             // 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);
+            filesOpen = true;
             break;
           }
 
           // Volume is mounted, we need to unmount before
           // we can share.
           LOG("UpdateState: Unmounting %s", vol->NameStr());
           vol->SetIsSharing(true);
           vol->StartUnmount(mResponseCallback);
@@ -476,16 +480,24 @@ AutoMounter::UpdateState()
         }
         default: {
           // Not in a state that we can do anything about.
           break;
         }
       }
     }
   }
+
+  int32_t status = AUTOMOUNTER_STATUS_DISABLED;
+  if (filesOpen) {
+    status = AUTOMOUNTER_STATUS_FILES_OPEN;
+  } else if (enabled) {
+    status = AUTOMOUNTER_STATUS_ENABLED;
+  }
+  SetAutoMounterStatus(status);
 }
 
 /***************************************************************************/
 
 static void
 InitAutoMounterIOThread()
 {
   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
@@ -590,17 +602,17 @@ InitVolumeConfig()
   char line[255];
   char *command, *vol_name_cstr, *mount_point_cstr, *save_ptr;
   const char *filename = "/system/etc/volume.cfg";
   if (!(fp = fopen(filename, "r"))) {
     LOG("Unable to open volume configuration file '%s' - ignoring", filename);
     return;
   }
   while(fgets(line, sizeof(line), fp)) {
-    char *delim = " \t\n";
+    const char *delim = " \t\n";
     n++;
 
     if (line[0] == '#')
       continue;
     if (!(command = strtok_r(line, delim, &save_ptr))) {
       // Blank line - ignore
       continue;
     }
@@ -639,16 +651,34 @@ InitAutoMounter()
       NewRunnableFunction(InitAutoMounterIOThread));
 
   // Switch Observers need to run on the main thread, so we need to
   // start it here and have it send events to the AutoMounter running
   // on the IO Thread.
   sUsbCableObserver = new UsbCableObserver();
 }
 
+int32_t
+GetAutoMounterStatus()
+{
+  if (sAutoMounterSetting) {
+    return sAutoMounterSetting->GetStatus();
+  }
+  return AUTOMOUNTER_STATUS_DISABLED;
+}
+
+//static
+void
+SetAutoMounterStatus(int32_t aStatus)
+{
+  if (sAutoMounterSetting) {
+    sAutoMounterSetting->SetStatus(aStatus);
+  }
+}
+
 void
 SetAutoMounterMode(int32_t aMode)
 {
   XRE_GetIOMessageLoop()->PostTask(
       FROM_HERE,
       NewRunnableFunction(SetAutoMounterModeIOThread, aMode));
 }
 
--- a/dom/system/gonk/AutoMounter.h
+++ b/dom/system/gonk/AutoMounter.h
@@ -12,16 +12,21 @@ class nsCString;
 namespace mozilla {
 namespace system {
 
 // AutoMounter modes
 #define AUTOMOUNTER_DISABLE                 0
 #define AUTOMOUNTER_ENABLE                  1
 #define AUTOMOUNTER_DISABLE_WHEN_UNPLUGGED  2
 
+// Automounter statuses
+#define AUTOMOUNTER_STATUS_DISABLED         0
+#define AUTOMOUNTER_STATUS_ENABLED          1
+#define AUTOMOUNTER_STATUS_FILES_OPEN       2
+
 /**
  * Initialize the automounter. This causes some of the phone's
  * directories to show up on the host when the phone is plugged
  * into the host via USB.
  *
  * When the AutoMounter starts, it will poll the current state
  * of affairs (usb cable plugged in, automounter enabled, etc)
  * and try to make the state of the volumes match.
@@ -34,16 +39,22 @@ InitAutoMounter();
  *
  * This will in turn cause the automounter to re-evaluate
  * whether it should mount/unmount/share/unshare volumes.
  */
 void
 SetAutoMounterMode(int32_t aMode);
 
 /**
+ * Reports the status of the automounter.
+ */
+int32_t
+GetAutoMounterStatus();
+
+/**
  * Sets the sharing mode of an individual volume.
  *
  * If a volume is enabled for sharing, and the autmounter
  * is in a state to share, then the volume will be shared
  * with the PC.
  */
 void
 SetAutoMounterSharingMode(const nsCString& aVolumeName, bool aAllowSharing);
--- a/dom/system/gonk/AutoMounterSetting.cpp
+++ b/dom/system/gonk/AutoMounterSetting.cpp
@@ -21,16 +21,17 @@
 #include "xpcpublic.h"
 #include "mozilla/Attributes.h"
 
 #undef LOG
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "AutoMounterSetting" , ## args)
 #define ERR(args...)  __android_log_print(ANDROID_LOG_ERROR, "AutoMounterSetting" , ## args)
 
 #define UMS_MODE                  "ums.mode"
+#define UMS_STATUS                "ums.status"
 #define UMS_VOLUME_ENABLED_PREFIX "ums.volume."
 #define UMS_VOLUME_ENABLED_SUFFIX ".enabled"
 #define MOZSETTINGS_CHANGED       "mozsettings-changed"
 
 namespace mozilla {
 namespace system {
 
 class SettingsServiceCallback MOZ_FINAL : public nsISettingsServiceCallback
@@ -82,17 +83,20 @@ public:
   }
 private:
   nsCString mVolumeName;
 };
 
 NS_IMPL_ISUPPORTS1(CheckVolumeSettingsCallback, nsISettingsServiceCallback)
 
 AutoMounterSetting::AutoMounterSetting()
+  : mStatus(AUTOMOUNTER_STATUS_DISABLED)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   // Setup an observer to watch changes to the setting
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
   if (!observerService) {
     ERR("GetObserverService failed");
     return;
   }
   nsresult rv;
@@ -111,29 +115,41 @@ AutoMounterSetting::AutoMounterSetting()
   if (!settingsService) {
     ERR("Failed to get settingsLock service!");
     return;
   }
   nsCOMPtr<nsISettingsServiceLock> lock;
   settingsService->CreateLock(getter_AddRefs(lock));
   nsCOMPtr<nsISettingsServiceCallback> callback = new SettingsServiceCallback();
   lock->Set(UMS_MODE, INT_TO_JSVAL(AUTOMOUNTER_DISABLE), callback, nullptr);
+  lock->Set(UMS_STATUS, INT_TO_JSVAL(mStatus), nullptr, nullptr);
 }
 
 AutoMounterSetting::~AutoMounterSetting()
 {
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
   if (observerService) {
     observerService->RemoveObserver(this, MOZSETTINGS_CHANGED);
   }
 }
 
 NS_IMPL_ISUPPORTS1(AutoMounterSetting, nsIObserver)
 
+const char *
+AutoMounterSetting::StatusStr(int32_t aStatus)
+{
+  switch (aStatus) {
+    case AUTOMOUNTER_STATUS_DISABLED:   return "Disabled";
+    case AUTOMOUNTER_STATUS_ENABLED:    return "Enabled";
+    case AUTOMOUNTER_STATUS_FILES_OPEN: return "FilesOpen";
+  }
+  return "??? Unknown ???";
+}
+
 class CheckVolumeSettingsRunnable : public nsRunnable
 {
 public:
   CheckVolumeSettingsRunnable(const nsACString& aVolumeName)
     : mVolumeName(aVolumeName) {}
 
   NS_IMETHOD Run()
   {
@@ -157,16 +173,49 @@ private:
 
 //static
 void
 AutoMounterSetting::CheckVolumeSettings(const nsACString& aVolumeName)
 {
   NS_DispatchToMainThread(new CheckVolumeSettingsRunnable(aVolumeName));
 }
 
+class SetStatusRunnable : public nsRunnable
+{
+public:
+  SetStatusRunnable(int32_t aStatus) : mStatus(aStatus) {}
+
+  NS_IMETHOD Run()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    nsCOMPtr<nsISettingsService> settingsService =
+      do_GetService("@mozilla.org/settingsService;1");
+    NS_ENSURE_TRUE(settingsService, NS_ERROR_FAILURE);
+    nsCOMPtr<nsISettingsServiceLock> lock;
+    settingsService->CreateLock(getter_AddRefs(lock));
+    lock->Set(UMS_STATUS, INT_TO_JSVAL(mStatus), nullptr, nullptr);
+    return NS_OK;
+  }
+
+private:
+  int32_t mStatus;
+};
+
+//static
+void
+AutoMounterSetting::SetStatus(int32_t aStatus)
+{
+  if (aStatus != mStatus) {
+    LOG("Changing status from '%s' to '%s'",
+        StatusStr(mStatus), StatusStr(aStatus));
+    mStatus = aStatus;
+    NS_DispatchToMainThread(new SetStatusRunnable(aStatus));
+  }
+}
+
 NS_IMETHODIMP
 AutoMounterSetting::Observe(nsISupports* aSubject,
                             const char* aTopic,
                             const PRUnichar* aData)
 {
   if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
     return NS_OK;
   }
--- a/dom/system/gonk/AutoMounterSetting.h
+++ b/dom/system/gonk/AutoMounterSetting.h
@@ -17,15 +17,22 @@ class AutoMounterSetting : public nsIObs
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   AutoMounterSetting();
   virtual ~AutoMounterSetting();
 
   static void CheckVolumeSettings(const nsACString& aVolumeName);
+
+  int32_t GetStatus() { return mStatus; }
+  void SetStatus(int32_t aStatus);
+  const char *StatusStr(int32_t aStatus);
+
+private:
+  int32_t mStatus;
 };
 
 }   // namespace system
 }   // namespace mozilla
 
 #endif  // mozilla_system_automountersetting_h__
 
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -42,16 +42,20 @@ function debug(s) {
 }
 
 const RADIOINTERFACELAYER_CID =
   Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
 const RADIOINTERFACE_CID =
   Components.ID("{6a7c91f0-a2b3-4193-8562-8969296c0b54}");
 const RILNETWORKINTERFACE_CID =
   Components.ID("{3bdd52a9-3965-4130-b569-0ac5afed045e}");
+const GSMICCINFO_CID =
+  Components.ID("{d90c4261-a99d-47bc-8b05-b057bb7e8f8a}");
+const CDMAICCINFO_CID =
+  Components.ID("{39ba3c08-aacc-46d0-8c04-9b619c387061}");
 
 const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
 const kSmsReceivedObserverTopic          = "sms-received";
 const kSilentSmsReceivedObserverTopic    = "silent-sms-received";
 const kSmsSendingObserverTopic           = "sms-sending";
 const kSmsSentObserverTopic              = "sms-sent";
 const kSmsFailedObserverTopic            = "sms-failed";
 const kSmsDeliverySuccessObserverTopic   = "sms-delivery-success";
@@ -458,16 +462,62 @@ XPCOMUtils.defineLazyGetter(this, "gMess
       this._sendTargetMessage("icc", message, {
         clientId: clientId,
         data: data
       });
     }
   };
 });
 
+function IccInfo() {}
+IccInfo.prototype = {
+  iccType: null,
+  iccid: null,
+  mcc: null,
+  mnc: null,
+  spn: null,
+  isDisplayNetworkNameRequired: null,
+  isDisplaySpnRequired: null
+};
+
+function GsmIccInfo() {}
+GsmIccInfo.prototype = {
+  __proto__: IccInfo.prototype,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozGsmIccInfo]),
+  classID: GSMICCINFO_CID,
+  classInfo: XPCOMUtils.generateCI({
+    classID:          GSMICCINFO_CID,
+    classDescription: "MozGsmIccInfo",
+    flags:            Ci.nsIClassInfo.DOM_OBJECT,
+    interfaces:       [Ci.nsIDOMMozGsmIccInfo]
+  }),
+
+  // nsIDOMMozGsmIccInfo
+
+  msisdn: null
+};
+
+function CdmaIccInfo() {}
+CdmaIccInfo.prototype = {
+  __proto__: IccInfo.prototype,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCdmaIccInfo]),
+  classID: CDMAICCINFO_CID,
+  classInfo: XPCOMUtils.generateCI({
+    classID:          CDMAICCINFO_CID,
+    classDescription: "MozCdmaIccInfo",
+    flags:            Ci.nsIClassInfo.DOM_OBJECT,
+    interfaces:       [Ci.nsIDOMMozCdmaIccInfo]
+  }),
+
+  // nsIDOMMozCdmaIccInfo
+
+  mdn: null,
+  min: null
+};
+
 function RadioInterfaceLayer() {
   gMessageManager.init(this);
 
   let options = {
     debug: debugPref,
     cellBroadcastDisabled: false,
     clirMode: RIL.CLIR_DEFAULT
   };
@@ -1044,19 +1094,37 @@ RadioInterface.prototype = {
         gSystemMessenger.broadcastMessage("cdma-info-rec-received", message);
         break;
       default:
         throw new Error("Don't know about this message type: " +
                         message.rilMessageType);
     }
   },
 
-  getMsisdn: function getMsisdn() {
+  /**
+   * Get phone number from iccInfo.
+   *
+   * If the icc card is gsm card, the phone number is in msisdn.
+   * @see nsIDOMMozGsmIccInfo
+   *
+   * Otherwise, the phone number is in mdn.
+   * @see nsIDOMMozCdmaIccInfo
+   */
+  getPhoneNumber: function getPhoneNumber() {
     let iccInfo = this.rilContext.iccInfo;
-    let number = iccInfo ? iccInfo.msisdn : null;
+
+    if (!iccInfo) {
+      return null;
+    }
+
+    // After moving SMS code out of RadioInterfaceLayer, we could use
+    // |iccInfo instanceof Ci.nsIDOMMozGsmIccInfo| here.
+    // TODO: Bug 873351 - B2G SMS: move SMS code out of RadioInterfaceLayer to
+    //                    SmsService
+    let number = (iccInfo instanceof GsmIccInfo) ? iccInfo.msisdn : iccInfo.mdn;
 
     // Workaround an xpconnect issue with undefined string objects.
     // See bug 808220
     if (number === undefined || number === "undefined") {
       return null;
     }
     return number;
   },
@@ -1739,17 +1807,17 @@ RadioInterface.prototype = {
 
     if (message.encoding == RIL.PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
       // Don't know how to handle binary data yet.
       return true;
     }
 
     message.type = "sms";
     message.sender = message.sender || null;
-    message.receiver = this.getMsisdn();
+    message.receiver = this.getPhoneNumber();
     message.body = message.fullBody = message.fullBody || null;
     message.timestamp = Date.now();
 
     if (gSmsService.isSilentNumber(message.sender)) {
       message.id = -1;
       message.threadId = 0;
       message.delivery = DOM_MOBILE_MESSAGE_DELIVERY_RECEIVED;
       message.deliveryStatus = RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS;
@@ -1923,24 +1991,24 @@ RadioInterface.prototype = {
   },
 
   /**
    * Set the system time zone by NITZ.
    */
   setTimezoneByNitz: function setTimezoneByNitz(message) {
     // To set the sytem timezone. Note that we need to convert the time zone
     // value to a UTC repesentation string in the format of "UTC(+/-)hh:mm".
-    // Ex, time zone -480 is "UTC-08:00"; time zone 630 is "UTC+10:30".
+    // Ex, time zone -480 is "UTC+08:00"; time zone 630 is "UTC-10:30".
     //
     // We can unapply the DST correction if we want the raw time zone offset:
     // message.networkTimeZoneInMinutes -= message.networkDSTInMinutes;
     if (message.networkTimeZoneInMinutes != (new Date()).getTimezoneOffset()) {
       let absTimeZoneInMinutes = Math.abs(message.networkTimeZoneInMinutes);
       let timeZoneStr = "UTC";
-      timeZoneStr += (message.networkTimeZoneInMinutes >= 0 ? "+" : "-");
+      timeZoneStr += (message.networkTimeZoneInMinutes > 0 ? "-" : "+");
       timeZoneStr += ("0" + Math.floor(absTimeZoneInMinutes / 60)).slice(-2);
       timeZoneStr += ":";
       timeZoneStr += ("0" + absTimeZoneInMinutes % 60).slice(-2);
       gSettingsService.createLock().set("time.timezone", timeZoneStr, null);
     }
   },
 
   /**
@@ -1986,22 +2054,37 @@ RadioInterface.prototype = {
     voicemailInfo.number = message.number;
     voicemailInfo.displayName = message.alphaId;
 
     gMessageManager.sendVoicemailMessage("RIL:VoicemailInfoChanged",
                                          this.clientId, voicemailInfo);
   },
 
   handleIccInfoChange: function handleIccInfoChange(message) {
-    let oldIccInfo = this.rilContext.iccInfo;
-    this.rilContext.iccInfo = message;
-
-    if (!this.isInfoChanged(message, oldIccInfo)) {
-      return;
+    let oldSpn = this.rilContext.iccInfo ? this.rilContext.iccInfo.spn : null;
+
+    if (!message || !message.iccType) {
+      // Card is not detected, clear iccInfo to null.
+      this.rilContext.iccInfo = null;
+    } else {
+      if (!this.rilContext.iccInfo) {
+        if (message.iccType === "ruim" || message.iccType === "csim") {
+          this.rilContext.iccInfo = new CdmaIccInfo();
+        } else {
+          this.rilContext.iccInfo = new GsmIccInfo();
+        }
+      }
+
+      if (!this.isInfoChanged(message, this.rilContext.iccInfo)) {
+        return;
+      }
+
+      this.updateInfo(message, this.rilContext.iccInfo);
     }
+
     // RIL:IccInfoChanged corresponds to a DOM event that gets fired only
     // when iccInfo has changed.
     gMessageManager.sendIccMessage("RIL:IccInfoChanged",
                                    this.clientId,
                                    message.iccType ? message : null);
 
     // Update lastKnownSimMcc.
     if (message.mcc) {
@@ -2015,17 +2098,16 @@ RadioInterface.prototype = {
     if (message.mcc && message.mnc) {
       try {
         Services.prefs.setCharPref("ril.lastKnownHomeNetwork",
                                    message.mcc + "-" + message.mnc);
       } catch (e) {}
     }
 
     // If spn becomes available, we should check roaming again.
-    let oldSpn = oldIccInfo ? oldIccInfo.spn : null;
     if (!oldSpn && message.spn) {
       let voice = this.rilContext.voice;
       let data = this.rilContext.data;
       let voiceRoaming = voice.roaming;
       let dataRoaming = data.roaming;
       this.checkRoamingBetweenOperators(voice);
       this.checkRoamingBetweenOperators(data);
       if (voiceRoaming != voice.roaming) {
@@ -2940,17 +3022,17 @@ RadioInterface.prototype = {
 
         // Only keep current context if we have requested for delivery report.
         return context.requestStatusReport;
       }).bind(this, context)); // End of |workerMessenger.send| callback.
     }).bind(this); // End of DB saveSendingMessage callback.
 
     let sendingMessage = {
       type: "sms",
-      sender: this.getMsisdn(),
+      sender: this.getPhoneNumber(),
       receiver: number,
       body: message,
       deliveryStatusRequested: options.requestStatusReport,
       timestamp: Date.now()
     };
 
     if (silent) {
       let deliveryStatus = RIL.GECKO_SMS_DELIVERY_STATUS_PENDING;
--- a/dom/system/gonk/TimeZoneSettingObserver.cpp
+++ b/dom/system/gonk/TimeZoneSettingObserver.cpp
@@ -16,16 +16,17 @@
 #include "nsISettingsService.h"
 #include "nsJSUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 #include "TimeZoneSettingObserver.h"
 #include "xpcpublic.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
+#include "nsPrintfCString.h"
 
 #undef LOG
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Time Zone Setting" , ## args)
 #define ERR(args...)  __android_log_print(ANDROID_LOG_ERROR, "Time Zone Setting" , ## args)
 
 #define TIME_TIMEZONE       "time.timezone"
 #define MOZSETTINGS_CHANGED "mozsettings-changed"
 
@@ -56,19 +57,28 @@ public:
     JSContext *cx = nsContentUtils::GetCurrentJSContext();
     NS_ENSURE_TRUE(cx, NS_OK);
 
     // If we don't have time.timezone value in the settings, we need
     // to initialize the settings based on the current system timezone
     // to make settings consistent with system. This usually happens
     // at the very first boot. After that, settings must have a value.
     if (aResult.isNull()) {
-      // Get the current system timezone and convert it to a JS string.
-      nsCString curTimezone = hal::GetTimezone();
-      NS_ConvertUTF8toUTF16 utf16Str(curTimezone);
+      // Get the current system time zone offset. Note that we need to
+      // convert the value to a UTC representation in the format of
+      // "UTC{+,-}hh:mm", so that the Gaia end can know how to interpret.
+      // E.g., -480 is "UTC+08:00"; 630 is "UTC-10:30".
+      int32_t timeZoneOffset = hal::GetTimezoneOffset();
+      nsPrintfCString curTimeZone("UTC%+03d:%02d",
+                                  -timeZoneOffset / 60,
+                                  abs(timeZoneOffset) % 60);
+
+      // Convert it to a JS string.
+      NS_ConvertUTF8toUTF16 utf16Str(curTimeZone);
+
       JSString *jsStr = JS_NewUCStringCopyN(cx, utf16Str.get(), utf16Str.Length());
 
       // Set the settings based on the current system timezone.
       nsCOMPtr<nsISettingsServiceLock> lock;
       nsCOMPtr<nsISettingsService> settingsService =
         do_GetService("@mozilla.org/settingsService;1");
       if (!settingsService) {
         ERR("Failed to get settingsLock service!");
@@ -122,23 +132,36 @@ TimeZoneSettingObserver::TimeZoneSetting
   settingsService->CreateLock(getter_AddRefs(lock));
   nsCOMPtr<nsISettingsServiceCallback> callback = new TimeZoneSettingCb();
   lock->Get(TIME_TIMEZONE, callback);
 }
 
 nsresult TimeZoneSettingObserver::SetTimeZone(const JS::Value &aValue, JSContext *aContext)
 {
   // Convert the JS value to a nsCString type.
+  // The value should be a JS string like "America/Chicago" or "UTC-05:00".
   nsDependentJSString valueStr;
   if (!valueStr.init(aContext, aValue.toString())) {
     ERR("Failed to convert JS value to nsCString");
     return NS_ERROR_FAILURE;
   }
   NS_ConvertUTF16toUTF8 newTimezone(valueStr);
 
+  // Hal expects opposite sign from general notations,
+  // so we need to flip it.
+  if (newTimezone.Find(NS_LITERAL_CSTRING("UTC+")) == 0) {
+    if (!newTimezone.SetCharAt('-', 3)) {
+      return NS_ERROR_FAILURE;
+    }
+  } else if (newTimezone.Find(NS_LITERAL_CSTRING("UTC-")) == 0) {
+    if (!newTimezone.SetCharAt('+', 3)) {
+      return NS_ERROR_FAILURE;
+    }
+  }
+
   // Set the timezone only when the system timezone is not identical.
   nsCString curTimezone = hal::GetTimezone();
   if (!curTimezone.Equals(newTimezone)) {
     hal::SetTimezone(newTimezone);
   }
 
   return NS_OK;
 }
@@ -161,17 +184,18 @@ TimeZoneSettingObserver::Observe(nsISupp
   if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
     return NS_OK;
   }
 
   // Note that this function gets called for any and all settings changes,
   // so we need to carefully check if we have the one we're interested in.
   //
   // The string that we're interested in will be a JSON string that looks like:
-  // {"key":"time.timezone","value":"America/Chicago"}
+  // {"key":"time.timezone","value":"America/Chicago"} or
+  // {"key":"time.timezone","value":"UTC-05:00"}
 
   AutoSafeJSContext cx;
 
   // Parse the JSON value.
   nsDependentString dataStr(aData);
   JS::Rooted<JS::Value> val(cx);
   if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) ||
       !val.isObject()) {
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -714,30 +714,8 @@ Telephony::EnqueueEnumerationAck()
     return;
   }
 
   nsCOMPtr<nsIRunnable> task = new EnumerationAck(this);
   if (NS_FAILED(NS_DispatchToCurrentThread(task))) {
     NS_WARNING("Failed to dispatch to current thread!");
   }
 }
-
-/* static */
-bool
-Telephony::CheckPermission(nsPIDOMWindow* aWindow)
-{
-  MOZ_ASSERT(aWindow && aWindow->IsInnerWindow());
-
-  nsCOMPtr<nsIPermissionManager> permMgr =
-    do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
-  NS_ENSURE_TRUE(permMgr, false);
-
-  uint32_t permission;
-  nsresult rv =
-    permMgr->TestPermissionFromWindow(aWindow, "telephony", &permission);
-  NS_ENSURE_SUCCESS(rv, false);
-
-  if (permission != nsIPermissionManager::ALLOW_ACTION) {
-    return false;
-  }
-
-  return true;
-}
--- a/dom/telephony/Telephony.h
+++ b/dom/telephony/Telephony.h
@@ -101,18 +101,16 @@ public:
   IMPL_EVENT_HANDLER(incoming)
   IMPL_EVENT_HANDLER(callschanged)
   IMPL_EVENT_HANDLER(remoteheld)
   IMPL_EVENT_HANDLER(remoteresumed)
 
   static already_AddRefed<Telephony>
   Create(nsPIDOMWindow* aOwner, ErrorResult& aRv);
 
-  static bool CheckPermission(nsPIDOMWindow* aOwner);
-
   void
   AddCall(TelephonyCall* aCall)
   {
     NS_ASSERTION(!mCalls.Contains(aCall), "Already know about this one!");
     mCalls.AppendElement(aCall);
     UpdateActiveCall(aCall, true);
     NotifyCallsChanged(aCall);
   }
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -95,26 +95,26 @@ var interfaceNamesInGlobalScope =
     "BlobEvent",
     {name: "BluetoothAdapter", b2g: true},
     {name: "BluetoothDevice", b2g: true},
     {name: "BluetoothDeviceEvent", b2g: true},
     {name: "BluetoothManager", b2g: true},
     {name: "BluetoothStatusChangedEvent", b2g: true},
     {name: "BoxObject", xbl: true},
     {name: "BrowserFeedWriter", desktop: true},
-    {name: "CallEvent", b2g: true},
+    {name: "CallEvent", b2g: true, pref: "dom.telephony.enabled"},
     "CameraCapabilities",
     "CameraControl",
     "CameraManager",
     "CanvasGradient",
     "CanvasPattern",
     "CanvasRenderingContext2D",
     "CaretPosition",
     "CDATASection",
-    {name: "CFStateChangeEvent", b2g: true},
+    {name: "CFStateChangeEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
     "ChannelMergerNode",
     "ChannelSplitterNode",
     "CharacterData",
     {name: "ChromeWindow", xbl: true},
     "ClipboardEvent",
     "CloseEvent",
     "CommandEvent",
     "Comment",
@@ -142,17 +142,17 @@ var interfaceNamesInGlobalScope =
     "CSSStyleRule",
     "CSSStyleSheet",
     "CSSSupportsRule",
     "CSSValue",
     "CSSValueList",
     "CustomEvent",
     "DataChannel",
     "DataContainerEvent",
-    {name: "DataErrorEvent", b2g: true},
+    {name: "DataErrorEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
     {name: "DataStore", b2g: true, release: false},
     {name: "DataStoreChangeEvent", b2g: true, release: false},
     {name: "DataStoreCursor", b2g: true, release: false},
     "DataTransfer",
     "DelayNode",
     "DesktopNotification",
     "DesktopNotificationCenter",
     "DeviceAcceleration",
@@ -272,17 +272,17 @@ var interfaceNamesInGlobalScope =
     "HTMLTableSectionElement",
     "HTMLTemplateElement",
     "HTMLTextAreaElement",
     "HTMLTimeElement",
     "HTMLTitleElement",
     "HTMLUListElement",
     "HTMLUnknownElement",
     "HTMLVideoElement",
-    {name: "IccCardLockError", b2g: true},
+    {name: "IccCardLockError", b2g: true, pref: "dom.icc.enabled"},
     "IDBCursor",
     "IDBCursorWithValue",
     "IDBDatabase",
     "IDBFactory",
     "IDBFileHandle",
     "IDBIndex",
     "IDBKeyRange",
     "IDBObjectStore",
@@ -312,47 +312,47 @@ var interfaceNamesInGlobalScope =
     "MessageEvent",
     "MimeType",
     "MimeTypeArray",
     "ModalContentWindow",
     "MouseEvent",
     "MouseScrollEvent",
     {name: "MozActivity", b2g: true},
     "MozApplicationEvent",
-    {name: "MozCellBroadcast", b2g: true},
-    {name: "MozCellBroadcastEvent", b2g: true},
+    {name: "MozCellBroadcast", b2g: true, pref: "dom.cellbroadcast.enabled"},
+    {name: "MozCellBroadcastEvent", b2g: true, pref: "dom.cellbroadcast.enabled"},
     "MozConnection",
     "mozContact",
     "MozContactChangeEvent",
     "MozCSSKeyframeRule",
     "MozCSSKeyframesRule",
-    {name: "MozEmergencyCbModeEvent", b2g: true},
-    {name: "MozIccManager", b2g: true},
+    {name: "MozEmergencyCbModeEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
+    {name: "MozIccManager", b2g: true, pref: "dom.icc.enabled"},
     {name: "MozInputContext", b2g: true},
     {name: "MozInputMethodManager", b2g: true},
     "MozMmsEvent",
     "MozMmsMessage",
-    {name: "MozMobileConnection", b2g: true},
+    {name: "MozMobileConnection", b2g: true, pref: "dom.mobileconnection.enabled"},
     "MozMobileMessageManager",
     "MozMobileMessageThread",
     "MozNamedAttrMap",
-    {name: "MozOtaStatusEvent", b2g: true},
+    {name: "MozOtaStatusEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
     "MozPowerManager",
     "mozRTCIceCandidate",
     "mozRTCPeerConnection",
     "mozRTCSessionDescription",
     "MozSettingsEvent",
     "MozSmsEvent",
     "MozSmsFilter",
     "MozSmsMessage",
     "MozSmsSegmentInfo",
-    {name: "MozStkCommandEvent", b2g: true},
+    {name: "MozStkCommandEvent", b2g: true, pref: "dom.icc.enabled"},
     {name: "MozTimeManager", b2g: true},
-    {name: "MozVoicemail", b2g: true},
-    {name: "MozVoicemailEvent", b2g: true},
+    {name: "MozVoicemail", b2g: true, pref: "dom.voicemail.enabled"},
+    {name: "MozVoicemailEvent", b2g: true, pref: "dom.voicemail.enabled"},
     "MozWakeLock",
     {name: "MozWifiConnectionInfoEvent", b2g: true},
     {name: "MozWifiStatusChangeEvent", b2g: true},
     "MutationEvent",
     "MutationObserver",
     "MutationRecord",
     "Navigator",
     "Node",
@@ -526,19 +526,19 @@ var interfaceNamesInGlobalScope =
     "SVGTransform",
     "SVGTransformList",
     "SVGTSpanElement",
     "SVGUnitTypes",
     "SVGUseElement",
     "SVGViewElement",
     "SVGZoomAndPan",
     "SVGZoomEvent",
-    {name: "Telephony", b2g: true},
-    {name: "TelephonyCall", b2g: true},
-    {name: "TelephonyCallGroup", b2g: true},
+    {name: "Telephony", b2g: true, pref: "dom.telephony.enabled"},
+    {name: "TelephonyCall", b2g: true, pref: "dom.telephony.enabled"},
+    {name: "TelephonyCallGroup", b2g: true, pref: "dom.telephony.enabled"},
     "Text",
     "TextDecoder",
     "TextEncoder",
     "TextMetrics",
     "TimeEvent",
     "TimeRanges",
     "Touch",
     "TouchEvent",
@@ -550,17 +550,17 @@ var interfaceNamesInGlobalScope =
     {name: "TreeContentView", xbl: true},
     {name: "TreeSelection", xbl: true},
     "TreeWalker",
     "UIEvent",
     "UndoManager",
     "URL",
     {name: "UserDataHandler", xbl: true},
     "UserProximityEvent",
-    {name: "USSDReceivedEvent", b2g: true},
+    {name: "USSDReceivedEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
     "ValidityState",
     "VideoStreamTrack",
     "WaveShaperNode",
     "WebGLActiveInfo",
     "WebGLBuffer",
     "WebGLFramebuffer",
     "WebGLProgram",
     "WebGLRenderbuffer",
@@ -596,16 +596,17 @@ var interfaceNamesInGlobalScope =
     {name: "XULLabeledControlElement", xbl: true},
     {name: "XULPopupElement", xbl: true},
     {name: "XULTemplateBuilder", xbl: true},
     {name: "XULTreeBuilder", xbl: true},
   ]
 // IMPORTANT: Do not change this list without review from a DOM peer!
 
 function createInterfaceMap(isXBLScope) {
+  var prefs = SpecialPowers.Services.prefs;
   var version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
   var isNightly = version.endsWith("a1");
   var isRelease = !version.contains("a");
   var isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
   var isB2G = !isDesktop && !navigator.userAgent.contains("Android");
 
   var interfaceMap = {};
 
@@ -613,17 +614,18 @@ function createInterfaceMap(isXBLScope) 
   {
     for (var entry of interfaces) {
       if (typeof(entry) === "string") {
         interfaceMap[entry] = shouldExpect;
       } else if ((entry.nightly === !isNightly) ||
                  (entry.xbl === !isXBLScope) ||
                  (entry.desktop === !isDesktop) ||
                  (entry.b2g === !isB2G) ||
-                 (entry.release === !isRelease)) {
+                 (entry.release === !isRelease) ||
+                 (entry.pref && !prefs.getBoolPref(entry.pref))) {
         interfaceMap[entry.name] = false;
       } else {
         interfaceMap[entry.name] = shouldExpect;
       }
     }
   }
 
   // Standard ECMAScript global objects are not defined on the XBL scope, but
--- a/dom/wappush/src/gonk/CpPduHelper.jsm
+++ b/dom/wappush/src/gonk/CpPduHelper.jsm
@@ -6,16 +6,19 @@
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 let WSP = {};
 Cu.import("resource://gre/modules/WspPduHelper.jsm", WSP);
 let WBXML = {};
 Cu.import("resource://gre/modules/WbxmlPduHelper.jsm", WBXML);
 
+Cu.import("resource://services-crypto/utils.js");
+Cu.import("resource://services-common/utils.js");
+
 // set to true to see debug messages
 let DEBUG = WBXML.DEBUG_ALL | false;
 
 /**
  * Public identifier for CP
  *
  * @see http://technical.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.aspx
  */
@@ -79,16 +82,138 @@ this.PduHelper = {
       msg.content = data.array;
     }
     return msg;
 
   }
 };
 
 /**
+ * SEC type values
+ *
+ * @see WAP-183-ProvCont-20010724-A, clause 5.3
+ */
+const AUTH_SEC_TYPE = (function () {
+  let names = {};
+  function add(name, number) {
+    names[number] = name;
+  }
+
+  add("NETWPIN",      0);
+  add("USERPIN",      1);
+  add("USERNETWPIN",  2);
+  add("USERPINMAC",   3);
+
+  return names;
+})();
+
+this.Authenticator = {
+  /**
+   * Format IMSI string into GSM format
+   *
+   * @param imsi
+   *        IMSI string
+   *
+   * @return IMSI in GSM format as string object
+   */
+  formatImsi: function formatImsi(imsi) {
+    let parityByte = ((imsi.length & 1) ? 9 : 1);
+
+    // Make sure length of IMSI is 15 digits.
+    // @see GSM 11.11, clause 10.2.2
+    let i = 0;
+    for (i = 15 - imsi.length; i > 0; i--) {
+      imsi += "F";
+    }
+
+    // char-by-char atoi
+    let imsiValue = [];
+    imsiValue.push(parityByte);
+    for (i = 0; i < imsi.length; i++) {
+      imsiValue.push(parseInt(imsi.substr(i, 1), 10));
+    }
+
+    // encoded IMSI
+    let imsiEncoded = "";
+    for (i = 0; i < imsiValue.length; i += 2) {
+      imsiEncoded += String.fromCharCode(imsiValue[i] | (imsiValue[i+1] << 4));
+    }
+
+    return imsiEncoded;
+  },
+
+  /**
+   * Perform HMAC check
+   *
+   * @param wbxml
+   *        Uint8 typed array of raw WBXML data.
+   * @param key
+   *        key string for HMAC check.
+   * @param mac
+   *        Expected MAC value.
+   *
+   * @return true for valid, false for invalid.
+   */
+  isValid: function isValid(wbxml, key, mac) {
+    let hasher = CryptoUtils.makeHMACHasher(Ci.nsICryptoHMAC.SHA1,
+                                            CryptoUtils.makeHMACKey(key));
+    hasher.update(wbxml, wbxml.length);
+    let result = CommonUtils.bytesAsHex(hasher.finish(false)).toUpperCase();
+    return mac == result;
+  },
+
+  /**
+   * Perform HMAC authentication.
+   *
+   * @param wbxml
+   *        Uint8 typed array of raw WBXML data.
+   * @param sec
+   *        Security method for HMAC check.
+   * @param mac
+   *        Expected MAC value.
+   * @param getNetworkPin
+   *        Callback function for getting network pin.
+   *
+   * @return true for valid, false for invalid.
+   */
+  check: function check_hmac(wbxml, sec, mac, getNetworkPin) {
+    // No security set.
+    if (sec == null || !mac) {
+      return null;
+    }
+
+    let authInfo = {
+      pass: false,
+      checked: false,
+      sec: AUTH_SEC_TYPE[sec],
+      mac: mac.toUpperCase(),
+      dataLength: wbxml.length,
+      data: wbxml
+    };
+
+    switch (authInfo.sec) {
+      case "NETWPIN":
+        let key = getNetworkPin();
+        authInfo.pass = this.isValid(wbxml, key, authInfo.mac);
+        authInfo.checked = true;
+        return authInfo;
+
+      case "USERPIN":
+      case "USERPINMAC":
+        // We can't check without USER PIN
+        return authInfo;
+
+      case "USERNETWPIN":
+      default:
+        return null;
+    }
+  }
+};
+
+/**
   * Tag tokens
   *
   * @see WAP-183-ProvCont-20010724-A, clause 8.1 for code page 0
   * @see OMA-WAP-TS-ProvCont-V1_1-20090421-C, clause 7.1 for code page 1
   */
 const CP_TAG_FIELDS = (function () {
   let names = {};
   function add(name, codepage, number) {
@@ -342,9 +467,11 @@ if (DEBUG) {
   };
 } else {
   debug = function (s) {};
 }
 
 this.EXPORTED_SYMBOLS = [
   // Parser
   "PduHelper",
+  // HMAC Authenticator
+  "Authenticator",
 ];
--- a/dom/wappush/src/gonk/WapPushManager.js
+++ b/dom/wappush/src/gonk/WapPushManager.js
@@ -32,16 +32,19 @@ XPCOMUtils.defineLazyGetter(this, "CP", 
   let CP = {};
   Cu.import("resource://gre/modules/CpPduHelper.jsm", CP);
   return CP;
 });
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
                                    "@mozilla.org/system-message-internal;1",
                                    "nsISystemMessagesInternal");
+XPCOMUtils.defineLazyServiceGetter(this, "gRIL",
+                                   "@mozilla.org/ril;1",
+                                   "nsIRadioInterfaceLayer");
 
 /**
  * Helpers for WAP PDU processing.
  */
 this.WapPushManager = {
 
   /**
    * Parse raw PDU data and deliver to a proper target.
@@ -86,25 +89,38 @@ this.WapPushManager = {
     * SL(WBXML)           "application/vnd.wap.slc"                 "x-wap-application:wml.ua"
     * Provisioning        "text/vnd.wap.connectivity-xml"           "x-wap-application:wml.ua"
     * Provisioning(WBXML) "application/vnd.wap.connectivity-wbxml"  "x-wap-application:wml.ua"
     *
     * @see http://technical.openmobilealliance.org/tech/omna/omna-wsp-content-type.aspx
     */
     let contentType = options.headers["content-type"].media;
     let msg;
+    let authInfo = null;
 
     if (contentType === "text/vnd.wap.si" ||
         contentType === "application/vnd.wap.sic") {
       msg = SI.PduHelper.parse(data, contentType);
     } else if (contentType === "text/vnd.wap.sl" ||
                contentType === "application/vnd.wap.slc") {
       msg = SL.PduHelper.parse(data, contentType);
     } else if (contentType === "text/vnd.wap.connectivity-xml" ||
                contentType === "application/vnd.wap.connectivity-wbxml") {
+      // Apply HMAC authentication on WBXML encoded CP message.
+      if (contentType === "application/vnd.wap.connectivity-wbxml") {
+        let params = options.headers["content-type"].params;
+        let sec = params && params.sec;
+        let mac = params && params.mac;
+        authInfo = CP.Authenticator.check(data.array.subarray(data.offset),
+                                          sec, mac, function getNetworkPin() {
+          let imsi = gRIL.getRadioInterface(0).rilContext.imsi;
+          return CP.Authenticator.formatImsi(imsi);
+        });
+      }
+
       msg = CP.PduHelper.parse(data, contentType);
     } else {
       // Unsupported type, provide raw data.
       msg = {
         contentType: contentType,
         content: data.array
       };
     }
@@ -113,17 +129,18 @@ this.WapPushManager = {
     let parsedSender = PhoneNumberUtils.parse(sender);
     if (parsedSender && parsedSender.internationalNumber) {
       sender = parsedSender.internationalNumber;
     }
 
     gSystemMessenger.broadcastMessage("wappush-received", {
       sender:         sender,
       contentType:    msg.contentType,
-      content:        msg.content
+      content:        msg.content,
+      authInfo:       authInfo
     });
   },
 
   /**
    * @param array
    *        A Uint8Array or an octet array representing raw PDU data.
    * @param length
    *        Length of the array.
--- a/dom/wappush/tests/test_cp_pdu_helper.js
+++ b/dom/wappush/tests/test_cp_pdu_helper.js
@@ -11,16 +11,26 @@ function run_test() {
 
 function test_parser(rawDataArray, contentType, expectResult) {
   let data = { array: rawDataArray, offset: 0 };
   let msg = CP.PduHelper.parse(data, contentType);
   do_check_eq(msg.contentType, expectResult.contentType);
   do_check_eq(msg.content, expectResult.content);
 }
 
+function test_hmac(rawDataArray, mac, key, expectResult) {
+  let authInfo = CP.Authenticator.check(rawDataArray, 0, mac, function getNetworkPin() {
+    return key;
+  });
+  do_check_eq(authInfo.data, rawDataArray);
+  do_check_eq(authInfo.dataLength, rawDataArray.length);
+  do_check_eq(authInfo.checked, expectResult.checked);
+  do_check_eq(authInfo.pass, expectResult.pass);
+}
+
 /*
  * Test data from OMA-TS-WAP_ProvCont-V1_1-2009 0421-C.pdf, clause 6.1
  */
 let text_data_array = new Uint8Array([
   0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65,
   0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31,
   0x2E, 0x30, 0x22, 0x3F, 0x3E, 0x3C, 0x21, 0x44,
   0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x77,
@@ -260,16 +270,85 @@ let wbxml_data_array = new Uint8Array([
   0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x00, 0x01,
   0x01, 0xc6, 0x54, 0x01, 0x87, 0x12, 0x06, 0x03,
   0x32, 0x32, 0x38, 0x00, 0x01, 0x87, 0x13, 0x06,
   0x03, 0x30, 0x30, 0x31, 0x00, 0x01, 0x01, 0x01,
   0x01
 ]);
 
 /*
+ * Test data from CHT CP, with code page change
+ */
+let wbxml_code_page_data_array = new Uint8Array([
+  0x03, 0x0B, 0x6A, 0x00, 0x45, 0xC6, 0x56, 0x01,
+  0x87, 0x07, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F,
+  0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0x01,
+  0xC6, 0x00, 0x01, 0x55, 0x01, 0x87, 0x36, 0x00,
+  0x00, 0x06, 0x03, 0x77, 0x32, 0x00, 0x01, 0x87,
+  0x00, 0x01, 0x39, 0x00, 0x00, 0x06, 0x03, 0x57,
+  0x50, 0x52, 0x4F, 0x58, 0x59, 0x00, 0x01, 0x87,
+  0x07, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F, 0x65,
+  0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0xC6, 0x00,
+  0x01, 0x59, 0x01, 0x87, 0x3A, 0x00, 0x00, 0x06,
+  0x03, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F,
+  0x77, 0x61, 0x70, 0x2E, 0x65, 0x6D, 0x6F, 0x6D,
+  0x65, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x00, 0x01,
+  0x87, 0x07, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F,
+  0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0x87,
+  0x1C, 0x01, 0x01, 0x01, 0xC6, 0x00, 0x01, 0x55,
+  0x01, 0x87, 0x36, 0x00, 0x00, 0x06, 0x03, 0x77,
+  0x34, 0x00, 0x01, 0x87, 0x00, 0x01, 0x39, 0x00,
+  0x00, 0x06, 0x03, 0x4D, 0x50, 0x52, 0x4F, 0x58,
+  0x59, 0x00, 0x01, 0x87, 0x00, 0x01, 0x34, 0x00,
+  0x00, 0x06, 0x03, 0x68, 0x74, 0x74, 0x70, 0x3A,
+  0x2F, 0x2F, 0x6D, 0x6D, 0x73, 0x3A, 0x38, 0x30,
+  0x30, 0x32, 0x00, 0x01, 0x01, 0xC6, 0x51, 0x01,
+  0x87, 0x15, 0x06, 0x03, 0x57, 0x50, 0x52, 0x4F,
+  0x58, 0x59, 0x00, 0x01, 0x87, 0x07, 0x06, 0x03,
+  0x43, 0x48, 0x54, 0x5F, 0x65, 0x6D, 0x6F, 0x6D,
+  0x65, 0x00, 0x01, 0x87, 0x1C, 0x06, 0x03, 0x68,
+  0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x61,
+  0x70, 0x2E, 0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x2E,
+  0x6E, 0x65, 0x74, 0x2F, 0x00, 0x01, 0xC6, 0x52,
+  0x01, 0x87, 0x2F, 0x06, 0x03, 0x50, 0x52, 0x4F,
+  0x58, 0x59, 0x31, 0x00, 0x01, 0x87, 0x20, 0x06,
+  0x03, 0x31, 0x30, 0x2E, 0x31, 0x2E, 0x31, 0x2E,
+  0x31, 0x00, 0x01, 0x87, 0x21, 0x06, 0x85, 0x01,
+  0x87, 0x22, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F,
+  0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0xC6,
+  0x53, 0x01, 0x87, 0x23, 0x06, 0x03, 0x38, 0x30,
+  0x38, 0x30, 0x00, 0x01, 0x01, 0x01, 0x01, 0xC6,
+  0x51, 0x01, 0x87, 0x15, 0x06, 0x03, 0x4D, 0x50,
+  0x52, 0x4F, 0x58, 0x59, 0x00, 0x01, 0x87, 0x07,
+  0x06, 0x03, 0x43, 0x48, 0x54, 0x5F, 0x4D, 0x4D,
+  0x53, 0x00, 0x01, 0xC6, 0x52, 0x01, 0x87, 0x2F,
+  0x06, 0x03, 0x50, 0x52, 0x4F, 0x58, 0x59, 0x32,
+  0x00, 0x01, 0x87, 0x20, 0x06, 0x03, 0x31, 0x30,
+  0x2E, 0x31, 0x2E, 0x31, 0x2E, 0x31, 0x00, 0x01,
+  0x87, 0x21, 0x06, 0x85, 0x01, 0x87, 0x22, 0x06,
+  0x03, 0x43, 0x48, 0x54, 0x5F, 0x4D, 0x4D, 0x53,
+  0x00, 0x01, 0xC6, 0x53, 0x01, 0x87, 0x23, 0x06,
+  0x03, 0x38, 0x30, 0x38, 0x30, 0x00, 0x01, 0x01,
+  0x01, 0x01, 0xC6, 0x55, 0x01, 0x87, 0x11, 0x06,
+  0x03, 0x43, 0x48, 0x54, 0x5F, 0x65, 0x6D, 0x6F,
+  0x6D, 0x65, 0x00, 0x01, 0x87, 0x07, 0x06, 0x03,
+  0x43, 0x48, 0x54, 0x5F, 0x65, 0x6D, 0x6F, 0x6D,
+  0x65, 0x00, 0x01, 0x87, 0x10, 0x06, 0xAB, 0x01,
+  0x87, 0x08, 0x06, 0x03, 0x65, 0x6D, 0x6F, 0x6D,
+  0x65, 0x00, 0x01, 0x87, 0x09, 0x06, 0x89, 0x01,
+  0x01, 0xC6, 0x55, 0x01, 0x87, 0x11, 0x06, 0x03,
+  0x43, 0x48, 0x54, 0x5F, 0x4D, 0x4D, 0x53, 0x00,
+  0x01, 0x87, 0x07, 0x06, 0x03, 0x43, 0x48, 0x54,
+  0x5F, 0x4D, 0x4D, 0x53, 0x00, 0x01, 0x87, 0x10,
+  0x06, 0xAB, 0x01, 0x87, 0x08, 0x06, 0x03, 0x65,
+  0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0x87, 0x09,
+  0x06, 0x89, 0x01, 0x01, 0x01
+]);
+
+/*
  * Test data from OMA-TS-WAP_ProvCont-V1_1-20090421-C.pdf, clause 6.1
  */
 let xml_header =
   "<?xml version=\"1.0\"?>" +
   "<!DOCTYPE wap-provisioningdoc PUBLIC \"-//WAPFORUM//DTD PROV 1.0//EN\" \"http://www.wapforum.org/DTD/prov.dtd\">";
 
 let xml_body =
   "<wap-provisioningdoc version=\"1.0\">" +
@@ -308,131 +387,17 @@ let xml_body =
       "</characteristic>" +
       "<characteristic type=\"VALIDITY\">" +
         "<parm name=\"COUNTRY\" value=\"228\"/>" +
         "<parm name=\"NETWORK\" value=\"001\"/>" +
       "</characteristic>" +
     "</characteristic>" +
   "</wap-provisioningdoc>";
 
-/**
- * CP in plain text
- *
- * Test case from OMA-TS-WAP_ProvCont-V1_1-20090421-C.pdf, clause 6.1
- */
-add_test(function test_cp_parse_plain_text() {
-  test_parser(text_data_array, "text/vnd.wap.connectivity-xml", {
-    contentType: "text/vnd.wap.connectivity-xml",
-    content: xml_header + xml_body
-  });
-
-  run_next_test();
-});
-
-/**
- * CP compressed by WBXML
- *
- * Test case from OMA-TS-WAP_ProvCont-V1_1-20090421-C.pdf, Appendix C
- */
-add_test(function test_cp_parse_wbxml() {
-  test_parser(wbxml_data_array, "application/vnd.wap.connectivity-wbxml", {
-    contentType: "text/vnd.wap.connectivity-xml",
-    content: xml_body
-  });
-
-  run_next_test();
-});
-
-/**
- * CP compressed by WBXML with VENDORCONFIG
- */
-add_test(function test_cp_parse_wbxml() {
-  let wbxml_vendor_config_data_array = new Uint8Array([
-    0x03, 0x0b, 0x6a, 0x05, 0x4e, 0x41, 0x50, 0x31,
-    0x00, 0xC5, 0x46, 0x01, 0xc6, 0x57, 0x01, 0x01
-  ]);
-
-  test_parser(wbxml_vendor_config_data_array, "application/vnd.wap.connectivity-wbxml", {
-                contentType: "application/vnd.wap.connectivity-wbxml",
-                content: wbxml_vendor_config_data_array
-              });
-
-  run_next_test();
-});
-
-/**
- * CP compressed by WBXML with code page switch
- */
-add_test(function test_cp_parse_wbxml_code_page() {
-  let wbxml_code_page_data_array = new Uint8Array([
-    0x03, 0x0B, 0x6A, 0x00, 0x45, 0xC6, 0x56, 0x01,
-    0x87, 0x07, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F,
-    0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0x01,
-    0xC6, 0x00, 0x01, 0x55, 0x01, 0x87, 0x36, 0x00,
-    0x00, 0x06, 0x03, 0x77, 0x32, 0x00, 0x01, 0x87,
-    0x00, 0x01, 0x39, 0x00, 0x00, 0x06, 0x03, 0x57,
-    0x50, 0x52, 0x4F, 0x58, 0x59, 0x00, 0x01, 0x87,
-    0x07, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F, 0x65,
-    0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0xC6, 0x00,
-    0x01, 0x59, 0x01, 0x87, 0x3A, 0x00, 0x00, 0x06,
-    0x03, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F,
-    0x77, 0x61, 0x70, 0x2E, 0x65, 0x6D, 0x6F, 0x6D,
-    0x65, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x00, 0x01,
-    0x87, 0x07, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F,
-    0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0x87,
-    0x1C, 0x01, 0x01, 0x01, 0xC6, 0x00, 0x01, 0x55,
-    0x01, 0x87, 0x36, 0x00, 0x00, 0x06, 0x03, 0x77,
-    0x34, 0x00, 0x01, 0x87, 0x00, 0x01, 0x39, 0x00,
-    0x00, 0x06, 0x03, 0x4D, 0x50, 0x52, 0x4F, 0x58,
-    0x59, 0x00, 0x01, 0x87, 0x00, 0x01, 0x34, 0x00,
-    0x00, 0x06, 0x03, 0x68, 0x74, 0x74, 0x70, 0x3A,
-    0x2F, 0x2F, 0x6D, 0x6D, 0x73, 0x3A, 0x38, 0x30,
-    0x30, 0x32, 0x00, 0x01, 0x01, 0xC6, 0x51, 0x01,
-    0x87, 0x15, 0x06, 0x03, 0x57, 0x50, 0x52, 0x4F,
-    0x58, 0x59, 0x00, 0x01, 0x87, 0x07, 0x06, 0x03,
-    0x43, 0x48, 0x54, 0x5F, 0x65, 0x6D, 0x6F, 0x6D,
-    0x65, 0x00, 0x01, 0x87, 0x1C, 0x06, 0x03, 0x68,
-    0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x61,
-    0x70, 0x2E, 0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x2E,
-    0x6E, 0x65, 0x74, 0x2F, 0x00, 0x01, 0xC6, 0x52,
-    0x01, 0x87, 0x2F, 0x06, 0x03, 0x50, 0x52, 0x4F,
-    0x58, 0x59, 0x31, 0x00, 0x01, 0x87, 0x20, 0x06,
-    0x03, 0x31, 0x30, 0x2E, 0x31, 0x2E, 0x31, 0x2E,
-    0x31, 0x00, 0x01, 0x87, 0x21, 0x06, 0x85, 0x01,
-    0x87, 0x22, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F,
-    0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0xC6,
-    0x53, 0x01, 0x87, 0x23, 0x06, 0x03, 0x38, 0x30,
-    0x38, 0x30, 0x00, 0x01, 0x01, 0x01, 0x01, 0xC6,
-    0x51, 0x01, 0x87, 0x15, 0x06, 0x03, 0x4D, 0x50,
-    0x52, 0x4F, 0x58, 0x59, 0x00, 0x01, 0x87, 0x07,
-    0x06, 0x03, 0x43, 0x48, 0x54, 0x5F, 0x4D, 0x4D,
-    0x53, 0x00, 0x01, 0xC6, 0x52, 0x01, 0x87, 0x2F,
-    0x06, 0x03, 0x50, 0x52, 0x4F, 0x58, 0x59, 0x32,
-    0x00, 0x01, 0x87, 0x20, 0x06, 0x03, 0x31, 0x30,
-    0x2E, 0x31, 0x2E, 0x31, 0x2E, 0x31, 0x00, 0x01,
-    0x87, 0x21, 0x06, 0x85, 0x01, 0x87, 0x22, 0x06,
-    0x03, 0x43, 0x48, 0x54, 0x5F, 0x4D, 0x4D, 0x53,
-    0x00, 0x01, 0xC6, 0x53, 0x01, 0x87, 0x23, 0x06,
-    0x03, 0x38, 0x30, 0x38, 0x30, 0x00, 0x01, 0x01,
-    0x01, 0x01, 0xC6, 0x55, 0x01, 0x87, 0x11, 0x06,
-    0x03, 0x43, 0x48, 0x54, 0x5F, 0x65, 0x6D, 0x6F,
-    0x6D, 0x65, 0x00, 0x01, 0x87, 0x07, 0x06, 0x03,
-    0x43, 0x48, 0x54, 0x5F, 0x65, 0x6D, 0x6F, 0x6D,
-    0x65, 0x00, 0x01, 0x87, 0x10, 0x06, 0xAB, 0x01,
-    0x87, 0x08, 0x06, 0x03, 0x65, 0x6D, 0x6F, 0x6D,
-    0x65, 0x00, 0x01, 0x87, 0x09, 0x06, 0x89, 0x01,
-    0x01, 0xC6, 0x55, 0x01, 0x87, 0x11, 0x06, 0x03,
-    0x43, 0x48, 0x54, 0x5F, 0x4D, 0x4D, 0x53, 0x00,
-    0x01, 0x87, 0x07, 0x06, 0x03, 0x43, 0x48, 0x54,
-    0x5F, 0x4D, 0x4D, 0x53, 0x00, 0x01, 0x87, 0x10,
-    0x06, 0xAB, 0x01, 0x87, 0x08, 0x06, 0x03, 0x65,
-    0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0x87, 0x09,
-    0x06, 0x89, 0x01, 0x01, 0x01
-  ]);
-  let wbxml_content =
+let wbxml_code_page_content =
     "<wap-provisioningdoc>" +
     "<characteristic type=\"BOOTSTRAP\">" +
       "<parm name=\"NAME\" value=\"CHT_emome\"/>" +
     "</characteristic>" +
     "<characteristic type=\"APPLICATION\">" +
       "<parm name=\"APPID\" value=\"w2\"/>" +
       "<parm name=\"TO-PROXY\" value=\"WPROXY\"/>" +
       "<parm name=\"NAME\" value=\"CHT_emome\"/>" +
@@ -485,15 +450,95 @@ add_test(function test_cp_parse_wbxml_co
       "<parm name=\"NAPID\" value=\"CHT_MMS\"/>" +
       "<parm name=\"NAME\" value=\"CHT_MMS\"/>" +
       "<parm name=\"BEARER\" value=\"GSM-GPRS\"/>" +
       "<parm name=\"NAP-ADDRESS\" value=\"emome\"/>" +
       "<parm name=\"NAP-ADDRTYPE\" value=\"APN\"/>" +
     "</characteristic>" +
     "</wap-provisioningdoc>";
 
-  test_parser(wbxml_code_page_data_array, "application/vnd.wap.connectivity-wbxml", {
-                contentType: "text/vnd.wap.connectivity-xml",
-                content: wbxml_content
+/**
+ * CP in plain text
+ *
+ * Test case from OMA-TS-WAP_ProvCont-V1_1-20090421-C.pdf, clause 6.1
+ */
+add_test(function test_cp_parse_plain_text() {
+  test_parser(text_data_array, "text/vnd.wap.connectivity-xml", {
+    contentType: "text/vnd.wap.connectivity-xml",
+    content: xml_header + xml_body
+  });
+
+  run_next_test();
+});
+
+/**
+ * CP compressed by WBXML
+ *
+ * Test case from OMA-TS-WAP_ProvCont-V1_1-20090421-C.pdf, Appendix C
+ */
+add_test(function test_cp_parse_wbxml() {
+  test_parser(wbxml_data_array, "application/vnd.wap.connectivity-wbxml", {
+    contentType: "text/vnd.wap.connectivity-xml",
+    content: xml_body
+  });
+
+  run_next_test();
+});
+
+/**
+ * CP compressed by WBXML with VENDORCONFIG
+ */
+add_test(function test_cp_parse_wbxml() {
+  let wbxml_vendor_config_data_array = new Uint8Array([
+    0x03, 0x0b, 0x6a, 0x05, 0x4e, 0x41, 0x50, 0x31,
+    0x00, 0xC5, 0x46, 0x01, 0xc6, 0x57, 0x01, 0x01
+  ]);
+
+  test_parser(wbxml_vendor_config_data_array, "application/vnd.wap.connectivity-wbxml", {
+                contentType: "application/vnd.wap.connectivity-wbxml",
+                content: wbxml_vendor_config_data_array
               });
 
   run_next_test();
 });
+
+/**
+ * CP compressed by WBXML with code page switch
+ */
+add_test(function test_cp_parse_wbxml_code_page() {
+  test_parser(wbxml_code_page_data_array, "application/vnd.wap.connectivity-wbxml", {
+                contentType: "text/vnd.wap.connectivity-xml",
+                content: wbxml_code_page_content
+              });
+
+  run_next_test();
+});
+
+/**
+ * HMAC test
+ */
+add_test(function test_cp_hmac_userpin() {
+  test_hmac(wbxml_code_page_data_array,
+            "AA2DC41FC48AEEF3FED7351B1EE704461A8894D4",
+            "0000",
+            {
+              checked: true,
+              pass: true
+            });
+
+  run_next_test();
+});
+
+add_test(function test_cp_hmac_networkpin() {
+  let wbxml_empty_data_array = new Uint8Array([
+    0x03, 0x0b, 0x6a, 0x00, 0x45, 0x01
+  ]);
+
+  test_hmac(wbxml_empty_data_array,
+            "1AF545FE2823DC9347064450F90FF1BBF957E146",
+            CP.Authenticator.formatImsi("466923103145252"),
+            {
+              checked: true,
+              pass: true
+            });
+
+  run_next_test();
+});
--- a/dom/webidl/BluetoothAdapter.webidl
+++ b/dom/webidl/BluetoothAdapter.webidl
@@ -124,14 +124,31 @@ interface BluetoothAdapter : EventTarget
   // Connect/Disconnect SCO (audio) connection
   [Creator, Throws]
   DOMRequest connectSco();
   [Creator, Throws]
   DOMRequest disconnectSco();
   [Creator, Throws]
   DOMRequest isScoConnected();
 
+  /**
+   * Additional HFP methods to handle CDMA network.
+   *
+   * In GSM network we observe call operations from RIL call state changes;
+   * however in CDMA network RIL call states do not change under some call
+   * operations, so we need these additional methods to be informed of these
+   * operations from dialer.
+   *
+   * For more information please refer to bug 912005 and 925638.
+   */
+  [Creator, Throws]
+  DOMRequest answerWaitingCall();
+  [Creator, Throws]
+  DOMRequest ignoreWaitingCall();
+  [Creator, Throws]
+  DOMRequest toggleCalls();
+
   // AVRCP 1.3 methods
   [Creator,Throws]
   DOMRequest sendMediaMetaData(optional MediaMetaData mediaMetaData);
   [Creator,Throws]
   DOMRequest sendMediaPlayStatus(optional MediaPlayStatus mediaPlayStatus);
 };
--- a/dom/webidl/MozCellBroadcast.webidl
+++ b/dom/webidl/MozCellBroadcast.webidl
@@ -3,15 +3,16 @@
  * 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/. */
 
 /**
  * Cell Broadcast short message service (CBS) permits a number of
  * unacknowledged general CBS messages to be broadcast to all receivers within
  * a particular region.
  */
+[Pref="dom.cellbroadcast.enabled"]
 interface MozCellBroadcast : EventTarget
 {
   /**
    * Cell Broadcast messages received.
    */
   attribute EventHandler onreceived;
 };
--- a/dom/webidl/MozCellBroadcastEvent.webidl
+++ b/dom/webidl/MozCellBroadcastEvent.webidl
@@ -1,16 +1,16 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/.
  */
 interface MozCellBroadcastMessage;
 
-[Constructor(DOMString type, optional MozCellBroadcastEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
+[Constructor(DOMString type, optional MozCellBroadcastEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h", Pref="dom.cellbroadcast.enabled"]
 interface MozCellBroadcastEvent : Event
 {
   readonly attribute MozCellBroadcastMessage? message;
 };
 
 dictionary MozCellBroadcastEventInit : EventInit
 {
   MozCellBroadcastMessage? message = null;
--- a/dom/webidl/MozVoicemail.webidl
+++ b/dom/webidl/MozVoicemail.webidl
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=40: */
 /* 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/. */
 
 // nsIDOMMozVoicemailStatus
 interface MozVoicemailStatus;
 
+[Pref="dom.voicemail.enabled"]
 interface MozVoicemail : EventTarget
 {
   /**
    * The current voicemail status, or null when the status is unknown
    */
   [GetterThrows]
   readonly attribute MozVoicemailStatus? status;
 
--- a/dom/webidl/MozVoicemailEvent.webidl
+++ b/dom/webidl/MozVoicemailEvent.webidl
@@ -1,16 +1,16 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/.
  */
 interface MozVoicemailStatus;
 
-[Constructor(DOMString type, optional MozVoicemailEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
+[Constructor(DOMString type, optional MozVoicemailEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h", Pref="dom.voicemail.enabled"]
 interface MozVoicemailEvent : Event
 {
   readonly attribute MozVoicemailStatus? status;
 };
 
 dictionary MozVoicemailEventInit : EventInit
 {
   MozVoicemailStatus? status = null;
--- a/dom/webidl/USSDReceivedEvent.webidl
+++ b/dom/webidl/USSDReceivedEvent.webidl
@@ -1,15 +1,15 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/.
  */
 
-[Constructor(DOMString type, optional USSDReceivedEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"]
+[Constructor(DOMString type, optional USSDReceivedEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h", Pref="dom.icc.enabled"]
 interface USSDReceivedEvent : Event
 {
   readonly attribute DOMString? message;
   readonly attribute boolean sessionEnded;
 };
 
 dictionary USSDReceivedEventInit : EventInit
 {
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -181,29 +181,49 @@ ImageContainer::ClearCurrentImage()
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   SetCurrentImageInternal(nullptr);
 }
 
 void
 ImageContainer::SetCurrentImage(Image *aImage)
 {
-  if (IsAsync() && !aImage) {
-    // Let ImageClient to release all TextureClients.
-    ImageBridgeChild::FlushImage(mImageClient, this);
+  if (!aImage) {
+    ClearAllImages();
     return;
   }
 
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   if (IsAsync()) {
     ImageBridgeChild::DispatchImageClientUpdate(mImageClient, this);
   }
   SetCurrentImageInternal(aImage);
 }
 
+ void
+ImageContainer::ClearAllImages()
+{
+  if (IsAsync()) {
+    // Let ImageClient release all TextureClients.
+    ImageBridgeChild::FlushAllImages(mImageClient, this, false);
+    return;
+  }
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+  SetCurrentImageInternal(nullptr);
+}
+
+void
+ImageContainer::ClearAllImagesExceptFront()
+{
+  if (IsAsync()) {
+    // Let ImageClient release all TextureClients except front one.
+    ImageBridgeChild::FlushAllImages(mImageClient, this, true);
+  }
+}
+
 void
 ImageContainer::SetCurrentImageInTransaction(Image *aImage)
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   NS_ASSERTION(!mImageClient, "Should use async image transfer with ImageBridge.");
 
   SetCurrentImageInternal(aImage);
 }
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -380,16 +380,27 @@ public:
    *
    * If this ImageContainer has an ImageClient for async video:
    * Schelude a task to send the image to the compositor using the 
    * PImageBridge protcol without using the main thread.
    */
   void SetCurrentImage(Image* aImage);
 
   /**
+   * Clear all images. Let ImageClient release all TextureClients.
+   */
+  void ClearAllImages();
+
+  /**
+   * Clear all images except current one.
+   * Let ImageClient release all TextureClients except front one.
+   */
+  void ClearAllImagesExceptFront();
+
+  /**
    * Clear the current image.
    * This function is expect to be called only from a CompositableClient
    * that belongs to ImageBridgeChild. Created to prevent dead lock.
    * See Bug 901224.
    */
   void ClearCurrentImage();
 
   /**
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -93,28 +93,28 @@ ImageClientBuffered::ImageClientBuffered
 }
 
 TextureInfo ImageClientSingle::GetTextureInfo() const
 {
   return TextureInfo(COMPOSITABLE_IMAGE);
 }
 
 void
-ImageClientSingle::FlushImage()
+ImageClientSingle::FlushAllImages(bool aExceptFront)
 {
-  if (mFrontBuffer) {
+  if (!aExceptFront && mFrontBuffer) {
     RemoveTextureClient(mFrontBuffer);
     mFrontBuffer = nullptr;
   }
 }
 
 void
-ImageClientBuffered::FlushImage()
+ImageClientBuffered::FlushAllImages(bool aExceptFront)
 {
-  if (mFrontBuffer) {
+  if (!aExceptFront && mFrontBuffer) {
     RemoveTextureClient(mFrontBuffer);
     mFrontBuffer = nullptr;
   }
   if (mBackBuffer) {
     RemoveTextureClient(mBackBuffer);
     mBackBuffer = nullptr;
   }
 }
--- a/gfx/layers/client/ImageClient.h
+++ b/gfx/layers/client/ImageClient.h
@@ -60,17 +60,17 @@ public:
   virtual void UpdatePictureRect(nsIntRect aPictureRect);
 
   virtual already_AddRefed<Image> CreateImage(const uint32_t *aFormats,
                                               uint32_t aNumFormats) = 0;
 
   /**
    * Synchronously remove all the textures used by the image client.
    */
-  virtual void FlushImage() {}
+  virtual void FlushAllImages(bool aExceptFront) {}
 
 protected:
   ImageClient(CompositableForwarder* aFwd, CompositableType aType);
 
   CompositableType mType;
   int32_t mLastPaintedImageSerial;
   nsIntRect mPictureRect;
 };
@@ -95,17 +95,17 @@ public:
   CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
                             TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT) MOZ_OVERRIDE;
 
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE;
 
   virtual already_AddRefed<Image> CreateImage(const uint32_t *aFormats,
                                               uint32_t aNumFormats) MOZ_OVERRIDE;
 
-  virtual void FlushImage() MOZ_OVERRIDE;
+  virtual void FlushAllImages(bool aExceptFront) MOZ_OVERRIDE;
 
 protected:
   RefPtr<TextureClient> mFrontBuffer;
   // Some layers may want to enforce some flags to all their textures
   // (like disallowing tiling)
   TextureFlags mTextureFlags;
 };
 
@@ -118,17 +118,17 @@ public:
   ImageClientBuffered(CompositableForwarder* aFwd,
                       TextureFlags aFlags,
                       CompositableType aType);
 
   virtual bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags);
 
   virtual void OnDetach() MOZ_OVERRIDE;
 
-  virtual void FlushImage() MOZ_OVERRIDE;
+  virtual void FlushAllImages(bool aExceptFront) MOZ_OVERRIDE;
 
 protected:
   RefPtr<TextureClient> mBackBuffer;
 };
 
 /**
  * An image client which uses a single texture client, may be single or double
  * buffered. (As opposed to using two texture clients for buffering, as in
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -71,16 +71,19 @@ CompositableHost::RemoveTextureHost(uint
     if (it->GetNextSibling() &&
         it->GetNextSibling()->GetID() == aTextureID) {
       RefPtr<TextureHost> toRemove = it->GetNextSibling();
       it->SetNextSibling(it->GetNextSibling()->GetNextSibling());
       toRemove->SetNextSibling(nullptr);
     }
     it = it->GetNextSibling();
   }
+  if (!mFirstTexture && mBackendData) {
+    mBackendData->ClearData();
+  }
 }
 
 TextureHost*
 CompositableHost::GetTextureHost(uint64_t aTextureID)
 {
   RefPtr<TextureHost> it = mFirstTexture;
   while (it) {
     if (it->GetID() == aTextureID) {
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -67,16 +67,17 @@ public:
   {
     MOZ_COUNT_CTOR(CompositableBackendSpecificData);
   }
   virtual ~CompositableBackendSpecificData()
   {
     MOZ_COUNT_DTOR(CompositableBackendSpecificData);
   }
   virtual void SetCompositor(Compositor* aCompositor) {}
+  virtual void ClearData() {}
 };
 
 /**
  * The compositor-side counterpart to CompositableClient. Responsible for
  * updating textures and data about textures from IPC and how textures are
  * composited (tiling, double buffering, etc.).
  *
  * Update (for images/canvases) and UpdateThebes (for Thebes) are called during
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -417,57 +417,57 @@ void ImageBridgeChild::DispatchImageClie
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     FROM_HERE,
     NewRunnableFunction<
       void (*)(ImageClient*, ImageContainer*),
       ImageClient*,
       nsRefPtr<ImageContainer> >(&UpdateImageClientNow, aClient, aContainer));
 }
 
-static void FlushImageSync(ImageClient* aClient, ImageContainer* aContainer, ReentrantMonitor* aBarrier, bool* aDone)
+static void FlushAllImagesSync(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront, ReentrantMonitor* aBarrier, bool* aDone)
 {
-  ImageBridgeChild::FlushImageNow(aClient, aContainer);
+  ImageBridgeChild::FlushAllImagesNow(aClient, aContainer, aExceptFront);
 
   ReentrantMonitorAutoEnter autoMon(*aBarrier);
   *aDone = true;
   aBarrier->NotifyAll();
 }
 
 //static
-void ImageBridgeChild::FlushImage(ImageClient* aClient, ImageContainer* aContainer)
+void ImageBridgeChild::FlushAllImages(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront)
 {
   if (InImageBridgeChildThread()) {
-    FlushImageNow(aClient, aContainer);
+    FlushAllImagesNow(aClient, aContainer, aExceptFront);
     return;
   }
 
   ReentrantMonitor barrier("CreateImageClient Lock");
   ReentrantMonitorAutoEnter autoMon(barrier);
   bool done = false;
 
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     FROM_HERE,
-    NewRunnableFunction(&FlushImageSync, aClient, aContainer, &barrier, &done));
+    NewRunnableFunction(&FlushAllImagesSync, aClient, aContainer, aExceptFront, &barrier, &done));
 
   // should stop the thread until the ImageClient has been created on
   // the other thread
   while (!done) {
     barrier.Wait();
   }
 }
 
 //static
-void ImageBridgeChild::FlushImageNow(ImageClient* aClient, ImageContainer* aContainer)
+void ImageBridgeChild::FlushAllImagesNow(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront)
 {
   MOZ_ASSERT(aClient);
   sImageBridgeChildSingleton->BeginTransaction();
-  if (aContainer) {
+  if (aContainer && !aExceptFront) {
     aContainer->ClearCurrentImage();
   }
-  aClient->FlushImage();
+  aClient->FlushAllImages(aExceptFront);
   aClient->OnTransaction();
   sImageBridgeChildSingleton->EndTransaction();
   aClient->FlushTexturesToRemoveCallbacks();
 }
 
 void
 ImageBridgeChild::BeginTransaction()
 {
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -238,22 +238,22 @@ public:
 
   static void DispatchReleaseImageClient(ImageClient* aClient);
   static void DispatchReleaseTextureClient(TextureClient* aClient);
   static void DispatchImageClientUpdate(ImageClient* aClient, ImageContainer* aContainer);
 
   /**
    * Flush all Images sent to CompositableHost.
    */
-  static void FlushImage(ImageClient* aClient, ImageContainer* aContainer);
+  static void FlushAllImages(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront);
 
   /**
    * Must be called on the ImageBridgeChild's thread.
    */
-  static void FlushImageNow(ImageClient* aClient, ImageContainer* aContainer);
+  static void FlushAllImagesNow(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront);
 
   // CompositableForwarder
 
   virtual void Connect(CompositableClient* aCompositable) MOZ_OVERRIDE;
 
   /**
    * See CompositableForwarder::AddTexture
    */
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -181,16 +181,21 @@ CompositableDataGonkOGL::gl() const
   return mCompositor ? mCompositor->gl() : nullptr;
 }
 
 void CompositableDataGonkOGL::SetCompositor(Compositor* aCompositor)
 {
   mCompositor = static_cast<CompositorOGL*>(aCompositor);
 }
 
+void CompositableDataGonkOGL::ClearData()
+{
+  DeleteTextureIfPresent();
+}
+
 GLuint CompositableDataGonkOGL::GetTexture()
 {
   if (!mTexture) {
     gl()->MakeCurrent();
     gl()->fGenTextures(1, &mTexture);
   }
   return mTexture;
 }
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -65,16 +65,17 @@ class TextureImageDeprecatedTextureHostO
  */
 class CompositableDataGonkOGL : public CompositableBackendSpecificData
 {
 public:
   CompositableDataGonkOGL();
   virtual ~CompositableDataGonkOGL();
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+  virtual void ClearData() MOZ_OVERRIDE;
   GLuint GetTexture();
   void DeleteTextureIfPresent();
   gl::GLContext* gl() const;
 protected:
   RefPtr<CompositorOGL> mCompositor;
   GLuint mTexture;
 };
 
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -498,16 +498,23 @@ AdjustSystemClock(int64_t aDeltaMillisec
 
 void 
 SetTimezone(const nsCString& aTimezoneSpec)
 {
   AssertMainThread();
   PROXY_IF_SANDBOXED(SetTimezone(aTimezoneSpec));
 }
 
+int32_t
+GetTimezoneOffset()
+{
+  AssertMainThread();
+  RETURN_PROXY_IF_SANDBOXED(GetTimezoneOffset(), 0);
+}
+
 nsCString
 GetTimezone()
 {
   AssertMainThread();
   RETURN_PROXY_IF_SANDBOXED(GetTimezone(), nsCString(""));
 }
 
 void
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -255,16 +255,22 @@ void SetTimezone(const nsCString& aTimez
 
 /**
  * Get timezone
  * http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  */
 nsCString GetTimezone();
 
 /**
+ * Get timezone offset
+ * returns the timezone offset relative to UTC in minutes (DST effect included)
+ */
+int32_t GetTimezoneOffset();
+
+/**
  * Register observer for system clock changed notification.
  * @param aObserver The observer that should be added.
  */
 void RegisterSystemClockChangeObserver(
   hal::SystemClockChangeObserver* aObserver);
 
 /**
  * Unregister the observer for system clock changed.
--- a/hal/fallback/FallbackTime.cpp
+++ b/hal/fallback/FallbackTime.cpp
@@ -19,16 +19,22 @@ SetTimezone(const nsCString& aTimezoneSp
 {}
 
 nsCString
 GetTimezone()
 {
   return EmptyCString();
 }
 
+int32_t
+GetTimezoneOffset()
+{
+  return 0;
+}
+
 void
 EnableSystemClockChangeNotifications()
 {
 }
 
 void
 DisableSystemClockChangeNotifications()
 {
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -737,17 +737,17 @@ AdjustSystemClock(int64_t aDeltaMillisec
 
   if (ioctl(fd, ANDROID_ALARM_SET_RTC, &now) < 0) {
     HAL_LOG(("ANDROID_ALARM_SET_RTC failed: %s", strerror(errno)));
   }
 
   hal::NotifySystemClockChange(aDeltaMilliseconds);
 }
 
-static int32_t
+int32_t
 GetTimezoneOffset()
 {
   PRExplodedTime prTime;
   PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prTime);
 
   // Daylight saving time (DST) will be taken into account.
   int32_t offset = prTime.tm_params.tp_gmt_offset;
   offset += prTime.tm_params.tp_dst_offset;
--- a/hal/sandbox/PHal.ipdl
+++ b/hal/sandbox/PHal.ipdl
@@ -138,16 +138,18 @@ parent:
 
     sync GetScreenBrightness() returns (double brightness);
     SetScreenBrightness(double brightness);
 
     AdjustSystemClock(int64_t aDeltaMilliseconds);
     SetTimezone(nsCString aTimezoneSpec);
     sync GetTimezone()
       returns (nsCString aTimezoneSpec);
+    sync GetTimezoneOffset()
+      returns (int32_t aTimezoneOffset);
     EnableSystemClockChangeNotifications();
     DisableSystemClockChangeNotifications();
     EnableSystemTimezoneChangeNotifications();
     DisableSystemTimezoneChangeNotifications();
 
     sync SetLight(LightType light, LightConfiguration aConfig)
       returns (bool status);
     sync GetLight(LightType light)
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -207,16 +207,24 @@ SetTimezone(const nsCString& aTimezoneSp
 nsCString
 GetTimezone()
 {
   nsCString timezone;
   Hal()->SendGetTimezone(&timezone);
   return timezone;
 }
 
+int32_t
+GetTimezoneOffset()
+{
+  int32_t timezoneOffset;
+  Hal()->SendGetTimezoneOffset(&timezoneOffset);
+  return timezoneOffset;
+}
+
 void
 EnableSystemClockChangeNotifications()
 {
   Hal()->SendEnableSystemClockChangeNotifications();
 }
 
 void
 DisableSystemClockChangeNotifications()
@@ -680,16 +688,26 @@ public:
     if (!AssertAppProcessPermission(this, "time")) {
       return false;
     }
     *aTimezoneSpec = hal::GetTimezone();
     return true;
   }
 
   virtual bool
+  RecvGetTimezoneOffset(int32_t *aTimezoneOffset) MOZ_OVERRIDE
+  {
+    if (!AssertAppProcessPermission(this, "time")) {
+      return false;
+    }
+    *aTimezoneOffset = hal::GetTimezoneOffset();
+    return true;
+  }
+
+  virtual bool
   RecvEnableSystemClockChangeNotifications() MOZ_OVERRIDE
   {
     hal::RegisterSystemClockChangeObserver(this);
     return true;
   }
 
   virtual bool
   RecvDisableSystemClockChangeNotifications() MOZ_OVERRIDE
--- a/ipc/moz.build
+++ b/ipc/moz.build
@@ -9,17 +9,17 @@ DIRS += [
     'glue',
     'ipdl',
     'testshell',
 ]
 
 if CONFIG['MOZ_B2G_RIL']:
     DIRS += ['ril']
 
-if CONFIG['MOZ_B2G_BT']:
+if CONFIG['MOZ_B2G_BT_BLUEZ']:
     DIRS += ['dbus']
 
 if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT']:
     DIRS += ['unixsocket', 'keystore']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DIRS += ['netd']
 
--- a/ipc/unixsocket/UnixSocket.h
+++ b/ipc/unixsocket/UnixSocket.h
@@ -7,17 +7,17 @@
 #ifndef mozilla_ipc_UnixSocket_h
 #define mozilla_ipc_UnixSocket_h
 
 
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
 #include <netinet/in.h>
-#ifdef MOZ_B2G_BT
+#ifdef MOZ_B2G_BT_BLUEZ
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/sco.h>
 #include <bluetooth/l2cap.h>
 #include <bluetooth/rfcomm.h>
 #endif
 #include <stdlib.h>
 #include "nsString.h"
 #include "nsAutoPtr.h"
@@ -26,17 +26,17 @@
 namespace mozilla {
 namespace ipc {
 
 union sockaddr_any {
   sockaddr_storage storage; // address-family only
   sockaddr_un un;
   sockaddr_in in;
   sockaddr_in6 in6;
-#ifdef MOZ_B2G_BT
+#ifdef MOZ_B2G_BT_BLUEZ
   sockaddr_sco sco;
   sockaddr_rc rc;
   sockaddr_l2 l2;
 #endif
   // ... others
 };
 
 class UnixSocketRawData
--- a/layout/base/PositionedEventTargeting.cpp
+++ b/layout/base/PositionedEventTargeting.cpp
@@ -122,28 +122,53 @@ HasMouseListener(nsIContent* aContent)
   if (!elm) {
     return false;
   }
   return elm->HasListenersFor(nsGkAtoms::onclick) ||
          elm->HasListenersFor(nsGkAtoms::onmousedown) ||
          elm->HasListenersFor(nsGkAtoms::onmouseup);
 }
 
+static bool gTouchEventsRegistered = false;
+static int32_t gTouchEventsEnabled = 0;
+
+static bool
+HasTouchListener(nsIContent* aContent)
+{
+  nsEventListenerManager* elm = aContent->GetListenerManager(false);
+  if (!elm) {
+    return false;
+  }
+
+  if (!gTouchEventsRegistered) {
+    Preferences::AddIntVarCache(&gTouchEventsEnabled,
+      "dom.w3c_touch_events.enabled", gTouchEventsEnabled);
+    gTouchEventsRegistered = true;
+  }
+
+  if (!gTouchEventsEnabled) {
+    return false;
+  }
+
+  return elm->HasListenersFor(nsGkAtoms::ontouchstart) ||
+         elm->HasListenersFor(nsGkAtoms::ontouchend);
+}
+
 static bool
 IsElementClickable(nsIFrame* aFrame, nsIAtom* stopAt = nullptr)
 {
   // Input events propagate up the content tree so we'll follow the content
   // ancestors to look for elements accepting the click.
   for (nsIContent* content = aFrame->GetContent(); content;
        content = content->GetFlattenedTreeParent()) {
     nsIAtom* tag = content->Tag();
     if (content->IsHTML() && stopAt && tag == stopAt) {
       break;
     }
-    if (HasMouseListener(content)) {
+    if (HasTouchListener(content) || HasMouseListener(content)) {
       return true;
     }
     if (content->IsHTML()) {
       if (tag == nsGkAtoms::button ||
           tag == nsGkAtoms::input ||
           tag == nsGkAtoms::select ||
           tag == nsGkAtoms::textarea ||
           tag == nsGkAtoms::label) {
--- a/layout/base/tests/test_event_target_radius.html
+++ b/layout/base/tests/test_event_target_radius.html
@@ -40,16 +40,18 @@ https://bugzilla.mozilla.org/show_bug.cg
     <div id="t6_inner" style="position:absolute; left:-20px; top:20px; width:60px; height:60px; background:yellow;"></div>
   </div>
 
   <div class="target" id="t7" onmousedown="x=1" hidden></div>
   <div class="target" id="t7_over" hidden></div>
 
   <div id="t8" contenteditable="true" class="target" hidden></div>
 
+  <div id="t9" class="target" ontouchend="x=1" hidden></div>
+
 </div>
 <pre id="test">
 <script type="application/javascript">
 function startTest() {
   SpecialPowers.pushPrefEnv({"set": [["ui.mouse.radius.enabled", true],
                                      ["ui.mouse.radius.inputSource.touchOnly", false],
                                      ["ui.mouse.radius.leftmm", 12],
                                      ["ui.mouse.radius.topmm", 8],
@@ -198,16 +200,25 @@ function test3() {
   setShowing("t8", true);
   var rect = document.getElementById("t8").getBoundingClientRect();
   testMouseClick("t8", rect.left + 1, rect.top + 1, "t8", "content editable enabled for mouse input");
   testMouseClick("t8", rect.left + 1, rect.top + 1, "t8", "content editable enabled for touch input", {
     inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
   });
   setShowing("t8", false);
 
+  // Check that elements are touchable
+  setShowing("t9", true);
+  var rect = document.getElementById("t9").getBoundingClientRect();
+  testMouseClick("t9", rect.left + 1, rect.top + 1, "t9", "div enabled with mouse input");
+  testMouseClick("t9", rect.left + 1, rect.top + 1, "t9", "div enabled with touch input", {
+    inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+  });
+  setShowing("t9", false);
+
   // Not yet tested:
   // -- visited link weight
   // -- "Closest" using Euclidean distance
   endTest();
 }
 </script>
 </pre>
 </body>
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -4276,16 +4276,17 @@ pref("dom.vibrator.max_vibrate_list_len"
 pref("dom.battery.enabled", true);
 
 // WebSMS
 pref("dom.sms.enabled", false);
 // Enable Latin characters replacement with corresponding ones in GSM SMS
 // 7-bit default alphabet.
 pref("dom.sms.strict7BitEncoding", false);
 pref("dom.sms.requestStatusReport", true);
+pref("dom.mms.requestStatusReport", true);
 
 // WebContacts
 pref("dom.mozContacts.enabled", false);
 pref("dom.navigator-property.disable.mozContacts", true);
 pref("dom.global-constructor.disable.mozContact", true);
 
 // WebAlarms
 pref("dom.mozAlarms.enabled", false);
@@ -4392,17 +4393,17 @@ pref("jsloader.reuseGlobal", false);
 
 // When we're asked to take a screenshot, don't wait more than 2000ms for the
 // event loop to become idle before actually taking the screenshot.
 pref("dom.browserElement.maxScreenshotDelayMS", 2000);
 
 // Whether we should show the placeholder when the element is focused but empty.
 pref("dom.placeholder.show_on_focus", true);
 
-// UAProfile settings
+// MMS UA Profile settings
 pref("wap.UAProf.url", "");
 pref("wap.UAProf.tagname", "x-wap-profile");
 
 // MMS version 1.1 = 0x11 (or decimal 17)
 // MMS version 1.3 = 0x13 (or decimal 19)
 // @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.34
 pref("dom.mms.version", 19);
 
@@ -4453,16 +4454,28 @@ pref("dom.forms.inputmode", true);
 pref("dom.mozInputMethod.enabled", false);
 
 // DataStore is disabled by default
 pref("dom.datastore.enabled", false);
 
 // Telephony API
 pref("dom.telephony.enabled", false);
 
+// Cell Broadcast API
+pref("dom.cellbroadcast.enabled", false);
+
+// ICC API
+pref("dom.icc.enabled", false);
+
+// Mobile Connection API
+pref("dom.mobileconnection.enabled", false);
+
+// Voice Mail API
+pref("dom.voicemail.enabled", false);
+
 // DOM Inter-App Communication API.
 pref("dom.inter-app-communication-api.enabled", false);
 
 // The tables used for Safebrowsing phishing and malware checks.
 pref("urlclassifier.malware_table", "goog-malware-shavar");
 pref("urlclassifier.phish_table", "goog-phish-shavar");
 pref("urlclassifier.download_block_table", "goog-badbinurl-shavar");
 pref("urlclassifier.download_allow_table", "goog-downloadwhite-digest256");
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -84,17 +84,17 @@ STATIC_LIBS += \
 ifdef MOZ_CONTENT_SANDBOX #{
 STATIC_LIBS += sandbox_s
 endif #}
 
 ifdef MOZ_B2G_RIL #{
 STATIC_LIBS += mozril_s
 endif #}
 
-ifdef MOZ_B2G_BT #{
+ifdef MOZ_B2G_BT_BLUEZ #{
 STATIC_LIBS += mozdbus_s
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 OS_LIBS += -ldbus
 endif
 endif #}
 
 ifneq ($(strip $(MOZ_B2G_RIL)$(MOZ_B2G_BT)),) #{
 STATIC_LIBS += mozipcunixsocket_s mozkeystore_s