Merge m-c to fx-team, a=merge
authorWes Kocher <wkocher@mozilla.com>
Wed, 29 Jul 2015 20:22:12 -0700
changeset 286969 785f60f45b98bfef0b2565cfdeced581617c53eb
parent 286968 c6f672a41983709d5096d7c9cbf438bf75fab85c (current diff)
parent 286964 62469b20ec842c2399c409bdc2af0f5e5d3facd2 (diff)
child 286970 50eefd290385d410e17b28a00b00ff79a4e24841
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone42.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 m-c to fx-team, a=merge
security/manager/ssl/tests/unit/test_ev_certs/cert9.db
security/manager/ssl/tests/unit/test_ev_certs/ev-valid-anypolicy-int.der
security/manager/ssl/tests/unit/test_ev_certs/ev-valid.der
security/manager/ssl/tests/unit/test_ev_certs/ev_root_generate.py
security/manager/ssl/tests/unit/test_ev_certs/evroot.csr
security/manager/ssl/tests/unit/test_ev_certs/evroot.der
security/manager/ssl/tests/unit/test_ev_certs/evroot.key
security/manager/ssl/tests/unit/test_ev_certs/evroot.p12
security/manager/ssl/tests/unit/test_ev_certs/generate.py
security/manager/ssl/tests/unit/test_ev_certs/int-ev-valid-anypolicy-int.der
security/manager/ssl/tests/unit/test_ev_certs/int-ev-valid.der
security/manager/ssl/tests/unit/test_ev_certs/int-non-ev-root.der
security/manager/ssl/tests/unit/test_ev_certs/key4.db
security/manager/ssl/tests/unit/test_ev_certs/no-ocsp-url-cert.der
security/manager/ssl/tests/unit/test_ev_certs/non-ev-root.der
security/manager/ssl/tests/unit/test_ev_certs/non-evroot-ca.der
security/manager/ssl/tests/unit/test_ev_certs/pkcs11.txt
security/manager/ssl/tests/unit/test_keysize/ev_ee_rsa_2040-ev_int_rsa_2048-evroot.der
security/manager/ssl/tests/unit/test_keysize/ev_ee_rsa_2048-ev_int_rsa_2040-evroot.der
security/manager/ssl/tests/unit/test_keysize/ev_ee_rsa_2048-ev_int_rsa_2048-ev_root_rsa_2040.der
security/manager/ssl/tests/unit/test_keysize/ev_ee_rsa_2048-ev_int_rsa_2048-evroot.der
security/manager/ssl/tests/unit/test_keysize/ev_int_rsa_2040-evroot.der
security/manager/ssl/tests/unit/test_keysize/ev_int_rsa_2048-ev_root_rsa_2040.der
security/manager/ssl/tests/unit/test_keysize/ev_int_rsa_2048-evroot.der
security/manager/ssl/tests/unit/test_keysize/ev_root_rsa_2040.der
security/manager/ssl/tests/unit/test_validity/cert9.db
security/manager/ssl/tests/unit/test_validity/ev_ee_39_months-ev_int_60_months-evroot.der
security/manager/ssl/tests/unit/test_validity/ev_ee_40_months-ev_int_60_months-evroot.der
security/manager/ssl/tests/unit/test_validity/ev_int_60_months-evroot.der
security/manager/ssl/tests/unit/test_validity/generate_ev.py
security/manager/ssl/tests/unit/test_validity/key4.db
security/manager/ssl/tests/unit/test_validity/pkcs11.txt
xpcom/base/nsRefPtr.h
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -1155,10 +1155,13 @@ pref("dom.activities.developer_mode_only
 
 // mulet apparently loads firefox.js as well as b2g.js, so we have to explicitly
 // disable serviceworkers here to get them disabled in mulet.
 pref("dom.serviceWorkers.enabled", false);
 
 // Retain at most 10 processes' layers buffers
 pref("layers.compositor-lru-size", 10);
 
+// Enable Cardboard VR on mobile, assuming VR at all is enabled
+pref("dom.vr.cardboard.enabled", true);
+
 // In B2G by deafult any AudioChannelAgent is muted when created.
 pref("dom.audiochannel.mutedByDefault", true);
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -196,19 +196,19 @@ var shell = {
     if (this.onlineForCrashReport()) {
       this.submitQueuedCrashes();
       return;
     }
 
     debugCrashReport('Not online, postponing.');
 
     Services.obs.addObserver(function observer(subject, topic, state) {
-      let network = subject.QueryInterface(Ci.nsINetworkInterface);
-      if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED
-          && network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+      let network = subject.QueryInterface(Ci.nsINetworkInfo);
+      if (network.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED
+          && network.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) {
         shell.submitQueuedCrashes();
 
         Services.obs.removeObserver(observer, topic);
       }
     }, "network-connection-state-changed", false);
   },
 
   get homeURL() {
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="088f350b39baf8f86c7c1161fd4be178ce822b7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="088f350b39baf8f86c7c1161fd4be178ce822b7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="088f350b39baf8f86c7c1161fd4be178ce822b7b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="088f350b39baf8f86c7c1161fd4be178ce822b7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="088f350b39baf8f86c7c1161fd4be178ce822b7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="07c383a786f188904311a37f6062c2cb84c9b61d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="088f350b39baf8f86c7c1161fd4be178ce822b7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="088f350b39baf8f86c7c1161fd4be178ce822b7b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="088f350b39baf8f86c7c1161fd4be178ce822b7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "088f350b39baf8f86c7c1161fd4be178ce822b7b", 
+        "git_revision": "bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "97666dae0fe5da2a0da4f57f41fcb12e9c2fe709", 
+    "revision": "3b5be8b229de20ea6cdcd3089558bf631c184c58", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="088f350b39baf8f86c7c1161fd4be178ce822b7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="07c383a786f188904311a37f6062c2cb84c9b61d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="088f350b39baf8f86c7c1161fd4be178ce822b7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bf8565e0c3ad216ccb3f109c17f8a2eb2c42f6b8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3427,16 +3427,23 @@
             startTabSwitch: function () {
               TelemetryStopwatch.cancel("FX_TAB_SWITCH_TOTAL_E10S_MS", window);
               TelemetryStopwatch.start("FX_TAB_SWITCH_TOTAL_E10S_MS", window);
               this.addMarker("AsyncTabSwitch:Start");
             },
 
             finishTabSwitch: function () {
               if (this.requestedTab && this.getTabState(this.requestedTab) == this.STATE_LOADED) {
+                // After this point the tab has switched from the content thread's point of view.
+                // The changes will be visible after the next refresh driver tick + composite.
+                let event = new CustomEvent("TabSwitched", {
+                  bubbles: true,
+                  cancelable: true
+                });
+                this.tabbrowser.dispatchEvent(event);
                 let time = TelemetryStopwatch.timeElapsed("FX_TAB_SWITCH_TOTAL_E10S_MS", window);
                 if (time != -1) {
                   TelemetryStopwatch.finish("FX_TAB_SWITCH_TOTAL_E10S_MS", window);
                   this.log("DEBUG: tab switch time = " + time);
                   this.addMarker("AsyncTabSwitch:Finish");
                 }
               }
             },
--- a/browser/base/content/test/plugins/browser.ini
+++ b/browser/base/content/test/plugins/browser.ini
@@ -51,17 +51,16 @@ support-files =
 [browser_CTP_context_menu.js]
 skip-if = toolkit == "gtk2" || toolkit == "gtk3"   # fails intermittently on Linux (bug 909342)
 [browser_CTP_crashreporting.js]
 skip-if = !crashreporter
 [browser_CTP_data_urls.js]
 [browser_CTP_drag_drop.js]
 [browser_CTP_hide_overlay.js]
 [browser_CTP_iframe.js]
-skip-if = os == 'linux' || os == 'mac' # Bug 984821
 [browser_CTP_multi_allow.js]
 [browser_CTP_nonplugins.js]
 [browser_CTP_notificationBar.js]
 [browser_CTP_outsideScrollArea.js]
 [browser_CTP_remove_navigate.js]
 [browser_CTP_resize.js]
 [browser_CTP_zoom.js]
 [browser_blocking.js]
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -2071,18 +2071,16 @@ this.UITour = {
   },
 };
 
 this.UITour.init();
 
 /**
  * UITour Health Report
  */
-const DAILY_DISCRETE_TEXT_FIELD = Metrics.Storage.FIELD_DAILY_DISCRETE_TEXT;
-
 /**
  * Public API to be called by the UITour code
  */
 const UITourHealthReport = {
   recordTreatmentTag: function(tag, value) {
   TelemetryController.submitExternalPing("uitour-tag",
     {
       version: 1,
@@ -2110,16 +2108,19 @@ const UITourHealthReport = {
 
       // Get the UITourMetricsProvider instance from the Health Reporter
       reporter.getProvider("org.mozilla.uitour").recordTreatmentTag(tag, value);
     });
 #endif
   }
 };
 
+#ifdef MOZ_SERVICES_HEALTHREPORT
+const DAILY_DISCRETE_TEXT_FIELD = Metrics.Storage.FIELD_DAILY_DISCRETE_TEXT;
+
 this.UITourMetricsProvider = function() {
   Metrics.Provider.call(this);
 }
 
 UITourMetricsProvider.prototype = Object.freeze({
   __proto__: Metrics.Provider.prototype,
 
   name: "org.mozilla.uitour",
@@ -2179,8 +2180,9 @@ UITourTreatmentMeasurement1.prototype = 
 
     for (let [field, data] of data) {
       result[field] = data;
     }
 
     return result;
   }
 });
+#endif
--- a/build/annotationProcessors/AnnotationProcessor.java
+++ b/build/annotationProcessors/AnnotationProcessor.java
@@ -111,28 +111,25 @@ public class AnnotationProcessor {
             }
 
             headerFile.append(generatorInstance.getHeaderFileContents());
             implementationFile.append(generatorInstance.getWrapperFileContents());
             nativesFile.append(generatorInstance.getNativesFileContents());
         }
 
         implementationFile.append(
-                "\n" +
                 "} /* widget */\n" +
                 "} /* mozilla */\n");
 
         headerFile.append(
-                "\n" +
                 "} /* widget */\n" +
                 "} /* mozilla */\n" +
                 "#endif // " + getHeaderGuardName(HEADER_FILE) + "\n");
 
         nativesFile.append(
-                "\n" +
                 "} /* widget */\n" +
                 "} /* mozilla */\n" +
                 "#endif // " + getHeaderGuardName(NATIVES_FILE) + "\n");
 
         writeOutputFile(SOURCE_FILE, implementationFile);
         writeOutputFile(HEADER_FILE, headerFile);
         writeOutputFile(NATIVES_FILE, nativesFile);
         long e = System.currentTimeMillis();
--- a/build/annotationProcessors/CodeGenerator.java
+++ b/build/annotationProcessors/CodeGenerator.java
@@ -522,12 +522,13 @@ public class CodeGenerator {
         }
         natives.append(
                 "public:\n" +
                 "    static constexpr JNINativeMethod methods[] = {" + nativesInits + '\n' +
                 "    };\n" +
                 "};\n" +
                 "\n" +
                 "template<class Impl>\n" +
-                "constexpr JNINativeMethod " + clsName + "::Natives<Impl>::methods[];\n");
+                "constexpr JNINativeMethod " + clsName + "::Natives<Impl>::methods[];\n" +
+                "\n");
         return natives.toString();
     }
 }
--- a/build/annotationProcessors/SDKProcessor.java
+++ b/build/annotationProcessors/SDKProcessor.java
@@ -120,40 +120,47 @@ public class SDKProcessor {
                 "} /* mozilla */\n" +
                 "#endif\n");
 
         writeOutputFiles(outdir, generatedFilePrefix, headerFile, implementationFile);
         long e = System.currentTimeMillis();
         System.out.println("SDK processing complete in " + (e - s) + "ms");
     }
 
-    private static Member[] sortAndFilterMembers(Member[] members) {
+    private static int getAPIVersion(Class<?> cls, Member m) {
+        if (m instanceof Method || m instanceof Constructor) {
+            return sApiLookup.getCallVersion(
+                    cls.getName().replace('.', '/'),
+                    Utils.getMemberName(m),
+                    Utils.getSignature(m));
+        } else if (m instanceof Field) {
+            return sApiLookup.getFieldVersion(
+                    Utils.getClassDescriptor(m.getDeclaringClass()), m.getName());
+        } else {
+            throw new IllegalArgumentException("expected member to be Method, Constructor, or Field");
+        }
+    }
+
+    private static Member[] sortAndFilterMembers(Class<?> cls, Member[] members) {
         Arrays.sort(members, new Comparator<Member>() {
             @Override
             public int compare(Member a, Member b) {
                 return a.getName().compareTo(b.getName());
             }
         });
 
         ArrayList<Member> list = new ArrayList<>();
         for (Member m : members) {
-            int version = 0;
-
-            if (m instanceof Method || m instanceof Constructor) {
-                version = sApiLookup.getCallVersion(
-                        Utils.getClassDescriptor(m.getDeclaringClass()),
-                        m.getName(),
-                        Utils.getSignature(m));
-            } else if (m instanceof Field) {
-                version = sApiLookup.getFieldVersion(
-                        Utils.getClassDescriptor(m.getDeclaringClass()), m.getName());
-            } else {
-                throw new IllegalArgumentException("expected member to be Method, Constructor, or Field");
+            // Sometimes (e.g. Bundle) has methods that moved to/from a superclass in a later SDK
+            // version, so we check for both classes and see if we can find a minimum SDK version.
+            int version = getAPIVersion(cls, m);
+            final int version2 = getAPIVersion(m.getDeclaringClass(), m);
+            if (version2 > 0 && version2 < version) {
+                version = version2;
             }
-
             if (version > sMaxSdkVersion) {
                 System.out.println("Skipping " + m.getDeclaringClass().getName() + "." + m.getName() +
                     ", version " + version + " > " + sMaxSdkVersion);
                 continue;
             }
 
             list.add(m);
         }
@@ -163,19 +170,19 @@ public class SDKProcessor {
 
     private static void generateClass(Class<?> clazz,
                                       StringBuilder implementationFile,
                                       StringBuilder headerFile) {
         String generatedName = clazz.getSimpleName();
 
         CodeGenerator generator = new CodeGenerator(new ClassWithOptions(clazz, generatedName));
 
-        generator.generateMembers(sortAndFilterMembers(clazz.getDeclaredConstructors()));
-        generator.generateMembers(sortAndFilterMembers(clazz.getDeclaredMethods()));
-        generator.generateMembers(sortAndFilterMembers(clazz.getDeclaredFields()));
+        generator.generateMembers(sortAndFilterMembers(clazz, clazz.getConstructors()));
+        generator.generateMembers(sortAndFilterMembers(clazz, clazz.getMethods()));
+        generator.generateMembers(sortAndFilterMembers(clazz, clazz.getFields()));
 
         headerFile.append(generator.getHeaderFileContents());
         implementationFile.append(generator.getWrapperFileContents());
     }
 
     private static Vector<String> getClassList(String path) {
         Scanner scanner = null;
         try {
--- a/build/annotationProcessors/utils/GeneratableElementIterator.java
+++ b/build/annotationProcessors/utils/GeneratableElementIterator.java
@@ -26,17 +26,17 @@ public class GeneratableElementIterator 
     private int mElementIndex;
 
     private boolean mIterateEveryEntry;
 
     public GeneratableElementIterator(Class<?> aClass) {
         // Get all the elements of this class as AccessibleObjects.
         Member[] aMethods = aClass.getDeclaredMethods();
         Member[] aFields = aClass.getDeclaredFields();
-        Member[] aCtors = aClass.getConstructors();
+        Member[] aCtors = aClass.getDeclaredConstructors();
 
         // Shove them all into one buffer.
         Member[] objs = new Member[aMethods.length + aFields.length + aCtors.length];
 
         int offset = 0;
         System.arraycopy(aMethods, 0, objs, 0, aMethods.length);
         offset += aMethods.length;
         System.arraycopy(aFields, 0, objs, offset, aFields.length);
--- a/configure.in
+++ b/configure.in
@@ -1706,56 +1706,16 @@ if test "$GNU_CXX"; then
         _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-c++0x-extensions"
         MOZ_CXX_SUPPORTS_WARNING(-Wno-, extended-offsetof, ac_cxx_has_wno_extended_offsetof)
     fi
 
 else
     _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_MOZILLA_CONFIG_H_ $(ACDEFINES)'
 fi
 
-dnl gcc can come with its own linker so it is better to use the pass-thru calls
-dnl MKSHLIB_FORCE_ALL is used to force the linker to include all object
-dnl files present in an archive. MKSHLIB_UNFORCE_ALL reverts the linker to
-dnl normal behavior.
-dnl ========================================================
-MKSHLIB_FORCE_ALL=
-MKSHLIB_UNFORCE_ALL=
-
-if test "$COMPILE_ENVIRONMENT"; then
-if test "$GNU_CC"; then
-  AC_MSG_CHECKING(whether ld has archive extraction flags)
-  AC_CACHE_VAL(ac_cv_mkshlib_force_and_unforce,
-   [_SAVE_LDFLAGS=$LDFLAGS; _SAVE_LIBS=$LIBS
-    ac_cv_mkshlib_force_and_unforce="no"
-    exec 3<&0 <<LOOP_INPUT
-  force="-Wl,--whole-archive";   unforce="-Wl,--no-whole-archive"
-  force="-Wl,-z -Wl,allextract"; unforce="-Wl,-z -Wl,defaultextract"
-  force="-Wl,-all";              unforce="-Wl,-none"
-LOOP_INPUT
-    while read line
-    do
-      eval $line
-      LDFLAGS=$force
-      LIBS=$unforce
-      AC_TRY_LINK(,, ac_cv_mkshlib_force_and_unforce=$line; break)
-    done
-    exec 0<&3 3<&-
-    LDFLAGS=$_SAVE_LDFLAGS; LIBS=$_SAVE_LIBS
-   ])
-  if test "$ac_cv_mkshlib_force_and_unforce" = "no"; then
-    AC_MSG_RESULT(no)
-  else
-    AC_MSG_RESULT(yes)
-    eval $ac_cv_mkshlib_force_and_unforce
-    MKSHLIB_FORCE_ALL=$force
-    MKSHLIB_UNFORCE_ALL=$unforce
-  fi
-fi # GNU_CC
-fi # COMPILE_ENVIRONMENT
-
 dnl ========================================================
 dnl Checking for 64-bit OS
 dnl ========================================================
 if test "$COMPILE_ENVIRONMENT"; then
 AC_LANG_SAVE
 AC_LANG_C
 AC_MSG_CHECKING(for 64-bit OS)
 AC_TRY_COMPILE([$configure_static_assert_macros],
@@ -2271,18 +2231,16 @@ ia64*-hpux*)
         ASM_SUFFIX=asm
         OBJ_SUFFIX=obj
         LIB_SUFFIX=lib
         DLL_PREFIX=
         LIB_PREFIX=
         IMPORT_LIB_SUFFIX=lib
         MKSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
         MKCSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
-        MKSHLIB_FORCE_ALL=
-        MKSHLIB_UNFORCE_ALL=
         dnl Set subsystem version 5 for Windows XP.
         if test "$CPU_ARCH" = "x86"; then
             WIN32_SUBSYSTEM_VERSION=5.01
         else
             WIN32_SUBSYSTEM_VERSION=6.01
         fi
         WIN32_CONSOLE_EXE_LDFLAGS=-SUBSYSTEM:CONSOLE,$WIN32_SUBSYSTEM_VERSION
         WIN32_GUI_EXE_LDFLAGS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
@@ -2451,18 +2409,16 @@ ia64*-hpux*)
         DSO_LDOPTS='-shared'
         BIN_FLAGS='-Wl,--export-dynamic'
     else
         DSO_PIC_CFLAGS='-fPIC -DPIC'
         DLL_SUFFIX=".so.1.0"
         DSO_LDOPTS='-shared'
     fi
     # This will fail on a.out systems prior to 1.5.1_ALPHA.
-    MKSHLIB_FORCE_ALL='-Wl,--whole-archive'
-    MKSHLIB_UNFORCE_ALL='-Wl,--no-whole-archive'
     if test "$LIBRUNPATH"; then
         DSO_LDOPTS="-Wl,-R$LIBRUNPATH $DSO_LDOPTS"
     fi
     MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,$(DSO_SONAME) -o $@'
     MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,$(DSO_SONAME) -o $@'
     ;;
 
 *-openbsd*)
@@ -2502,18 +2458,16 @@ ia64*-hpux*)
            AC_TRY_LINK([#include <stdio.h>],
                        [printf("Hello World\n");],
                        ,
                        [LDFLAGS=$_SAVE_LDFLAGS])
        fi
        MOZ_OPTIMIZE_FLAGS="-xO4"
        MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $(DSO_SONAME) -o $@'
        MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $(DSO_SONAME) -o $@'
-       MKSHLIB_FORCE_ALL='-z allextract'
-       MKSHLIB_UNFORCE_ALL='-z defaultextract'
        DSO_LDOPTS='-G'
        AR_LIST="$AR t"
        AR_EXTRACT="$AR x"
        AR_DELETE="$AR d"
        AR='$(CXX) -xar'
        AR_FLAGS='-o $@'
        AS='/usr/ccs/bin/as'
        ASFLAGS="$ASFLAGS -K PIC -L -P -D_ASM -D__STDC__=0"
@@ -2544,18 +2498,16 @@ ia64*-hpux*)
            # disable xannotate
            CXXFLAGS="$CXXFLAGS -xannotate=no"
        fi
        AC_MSG_RESULT([$_res])
        AC_LANG_RESTORE
     else
        LDFLAGS="$LDFLAGS -Wl,-z,ignore -Wl,-R,'\$\$ORIGIN:\$\$ORIGIN/..' -Wl,-z,lazyload -Wl,-z,combreloc -Wl,-z,muldefs"
        LIBS="-lc $LIBS"
-       MKSHLIB_FORCE_ALL='-Wl,-z -Wl,allextract'
-       MKSHLIB_UNFORCE_ALL='-Wl,-z -Wl,defaultextract'
        ASFLAGS="$ASFLAGS -fPIC"
        DSO_LDOPTS='-shared'
        WARNINGS_AS_ERRORS='-Werror'
        _WARNINGS_CFLAGS=''
        _WARNINGS_CXXFLAGS=''
        if test "$OS_RELEASE" = "5.3"; then
            AC_DEFINE(MUST_UNDEF_HAVE_BOOLEAN_AFTER_INCLUDES)
        fi
@@ -2596,41 +2548,16 @@ if test -n "$MOZ_LINKER"; then
   AC_DEFINE(MOZ_LINKER)
 fi
 
 dnl Only one oddball right now (QNX), but this gives us flexibility
 dnl if any other platforms need to override this in the future.
 AC_DEFINE_UNQUOTED(D_INO,$DIRENT_INO)
 
 dnl ========================================================
-dnl Any platform that doesn't have MKSHLIB_FORCE_ALL defined
-dnl by now will not have any way to link most binaries (tests
-dnl as well as viewer, apprunner, etc.), because some symbols
-dnl will be left out of the "composite" .so's by ld as unneeded.
-dnl So, by defining NO_LD_ARCHIVE_FLAGS for these platforms,
-dnl they can link in the static libs that provide the missing
-dnl symbols.
-dnl ========================================================
-NO_LD_ARCHIVE_FLAGS=
-if test -z "$MKSHLIB_FORCE_ALL" -o -z "$MKSHLIB_UNFORCE_ALL"; then
-    NO_LD_ARCHIVE_FLAGS=1
-fi
-case "$target" in
-*-aix4.3*|*-aix5*)
-    NO_LD_ARCHIVE_FLAGS=
-    ;;
-*-mingw*)
-    if test -z "$GNU_CC"; then
-        NO_LD_ARCHIVE_FLAGS=
-    fi
-    ;;
-esac
-AC_SUBST(NO_LD_ARCHIVE_FLAGS)
-
-dnl ========================================================
 dnl = Flags to strip unused symbols from .so components and
 dnl = to export jemalloc symbols when linking a program
 dnl ========================================================
 case "$target" in
     *-linux*|*-kfreebsd*-gnu|*-gnu*)
         MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,--version-script -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-version-script'
         ;;
     *-solaris*)
@@ -8998,18 +8925,16 @@ AC_SUBST(HAVE_TOOLCHAIN_SUPPORT_MSSE4_1)
 AC_SUBST(HAVE_X86_AVX2)
 AC_SUBST(GCC_USE_GNU_LD)
 
 AC_SUBST(MOZ_CHROME_FILE_FORMAT)
 
 AC_SUBST(WRAP_LDFLAGS)
 AC_SUBST(MKSHLIB)
 AC_SUBST(MKCSHLIB)
-AC_SUBST(MKSHLIB_FORCE_ALL)
-AC_SUBST(MKSHLIB_UNFORCE_ALL)
 AC_SUBST(DSO_CFLAGS)
 AC_SUBST(DSO_PIC_CFLAGS)
 AC_SUBST(DSO_LDOPTS)
 AC_SUBST(LIB_PREFIX)
 AC_SUBST(DLL_PREFIX)
 AC_SUBST(DLL_SUFFIX)
 AC_DEFINE_UNQUOTED(MOZ_DLL_SUFFIX, "$DLL_SUFFIX")
 AC_SUBST(LIB_SUFFIX)
--- a/docshell/base/timeline/AutoGlobalTimelineMarker.h
+++ b/docshell/base/timeline/AutoGlobalTimelineMarker.h
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_AutoGlobalTimelineMarker_h_
 #define mozilla_AutoGlobalTimelineMarker_h_
 
 #include "mozilla/GuardObjects.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 class nsDocShell;
 
 namespace mozilla {
 
 // # AutoGlobalTimelineMarker
 //
 // Similar to `AutoTimelineMarker`, but adds its traced marker to all docshells,
--- a/docshell/base/timeline/AutoTimelineMarker.h
+++ b/docshell/base/timeline/AutoTimelineMarker.h
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_AutoTimelineMarker_h_
 #define mozilla_AutoTimelineMarker_h_
 
 #include "mozilla/GuardObjects.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 class nsIDocShell;
 class nsDocShell;
 
 namespace mozilla {
 
 // # AutoTimelineMarker
 //
--- a/docshell/base/timeline/ObservedDocShell.h
+++ b/docshell/base/timeline/ObservedDocShell.h
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ObservedDocShell_h_
 #define ObservedDocShell_h_
 
 #include "GeckoProfiler.h"
 #include "nsTArray.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 class nsDocShell;
 class TimelineMarker;
 
 namespace mozilla {
 namespace dom {
 struct ProfileTimelineMarker;
 }
--- a/dom/base/PostMessageEvent.h
+++ b/dom/base/PostMessageEvent.h
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_PostMessageEvent_h
 #define mozilla_dom_PostMessageEvent_h
 
 #include "mozilla/dom/StructuredCloneHelper.h"
 #include "nsCOMPtr.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 
 class nsGlobalWindow;
 class nsIPrincipal;
 class nsPIDOMWindow;
 
 namespace mozilla {
--- a/dom/base/SameProcessMessageQueue.h
+++ b/dom/base/SameProcessMessageQueue.h
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SameProcessMessageQueue_h
 #define mozilla_dom_SameProcessMessageQueue_h
 
 #include "nsIRunnable.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace dom {
 
 class CancelableRunnable;
 
 class SameProcessMessageQueue
--- a/dom/bindings/OwningNonNull.h
+++ b/dom/bindings/OwningNonNull.h
@@ -142,17 +142,17 @@ nsCOMPtr<T>::nsCOMPtr(const mozilla::dom
 
 template<class T> template<class U>
 nsCOMPtr<T>&
 nsCOMPtr<T>::operator=(const mozilla::dom::OwningNonNull<U>& aOther)
 {
   return operator=(aOther.get());
 }
 
-// Declared in nsRefPtr.h
+// Declared in mozilla/nsRefPtr.h
 template<class T> template<class U>
 nsRefPtr<T>::nsRefPtr(const mozilla::dom::OwningNonNull<U>& aOther)
   : nsRefPtr(aOther.get())
 {}
 
 template<class T> template<class U>
 nsRefPtr<T>&
 nsRefPtr<T>::operator=(const mozilla::dom::OwningNonNull<U>& aOther)
--- a/dom/broadcastchannel/BroadcastChannel.h
+++ b/dom/broadcastchannel/BroadcastChannel.h
@@ -7,17 +7,17 @@
 #ifndef mozilla_dom_BroadcastChannel_h
 #define mozilla_dom_BroadcastChannel_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
 #include "nsIObserver.h"
 #include "nsTArray.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 
 namespace ipc {
 class PrincipalInfo;
 } // namespace ipc
--- a/dom/cache/ActorChild.h
+++ b/dom/cache/ActorChild.h
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_cache_ActioChild_h
 #define mozilla_dom_cache_ActioChild_h
 
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 class Feature;
 
 class ActorChild
--- a/dom/cache/CacheOpChild.h
+++ b/dom/cache/CacheOpChild.h
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_cache_CacheOpChild_h
 #define mozilla_dom_cache_CacheOpChild_h
 
 #include "mozilla/dom/cache/ActorChild.h"
 #include "mozilla/dom/cache/PCacheOpChild.h"
 #include "mozilla/dom/cache/TypeUtils.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 class nsIGlobalObject;
 
 namespace mozilla {
 namespace dom {
 
 class Promise;
 
--- a/dom/cache/DBAction.h
+++ b/dom/cache/DBAction.h
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_cache_DBAction_h
 #define mozilla_dom_cache_DBAction_h
 
 #include "mozilla/dom/cache/Action.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsString.h"
 
 class mozIStorageConnection;
 class nsIFile;
 
 namespace mozilla {
 namespace dom {
 namespace cache {
--- a/dom/cache/Manager.h
+++ b/dom/cache/Manager.h
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_cache_Manager_h
 #define mozilla_dom_cache_Manager_h
 
 #include "mozilla/dom/cache/Types.h"
 #include "nsCOMPtr.h"
 #include "nsISupportsImpl.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 class nsIInputStream;
 class nsIThread;
 
 namespace mozilla {
 
--- a/dom/cache/ManagerId.cpp
+++ b/dom/cache/ManagerId.cpp
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/cache/ManagerId.h"
 #include "nsIPrincipal.h"
 #include "nsProxyRelease.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 // static
 nsresult
--- a/dom/cache/ReadStream.h
+++ b/dom/cache/ReadStream.h
@@ -7,17 +7,17 @@
 #ifndef mozilla_dom_cache_ReadStream_h
 #define mozilla_dom_cache_ReadStream_h
 
 #include "mozilla/ipc/FileDescriptor.h"
 #include "nsCOMPtr.h"
 #include "nsID.h"
 #include "nsIInputStream.h"
 #include "nsISupportsImpl.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsTArrayForwardDeclare.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 class CacheReadStream;
 class CacheReadStreamOrVoid;
--- a/dom/cache/StreamControl.h
+++ b/dom/cache/StreamControl.h
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_cache_StreamControl_h
 #define mozilla_dom_cache_StreamControl_h
 
 #include "mozilla/dom/cache/ReadStream.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsTObserverArray.h"
 
 struct nsID;
 
 namespace mozilla {
 namespace ipc {
  class FileDescriptor;
 } // namespace ipc
--- a/dom/cache/StreamList.h
+++ b/dom/cache/StreamList.h
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_cache_StreamList_h
 #define mozilla_dom_cache_StreamList_h
 
 #include "mozilla/dom/cache/Context.h"
 #include "mozilla/dom/cache/Types.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsTArray.h"
 
 class nsIInputStream;
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
--- a/dom/canvas/WebGL2ContextUniforms.cpp
+++ b/dom/canvas/WebGL2ContextUniforms.cpp
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGL2Context.h"
 
 #include "GLContext.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "WebGLBuffer.h"
 #include "WebGLContext.h"
 #include "WebGLProgram.h"
 #include "WebGLVertexArray.h"
 #include "WebGLVertexAttribData.h"
 
 namespace mozilla {
 
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -16,17 +16,16 @@
 #include "WebGLRenderbuffer.h"
 #include "WebGLShaderPrecisionFormat.h"
 #include "WebGLTexture.h"
 #include "WebGLExtensions.h"
 #include "WebGLVertexArray.h"
 
 #include "nsDebug.h"
 #include "nsReadableUtils.h"
-#include "../../xpcom/base/nsRefPtr.h"
 #include "nsString.h"
 
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "GLContext.h"
 
 #include "nsContentUtils.h"
 #include "nsError.h"
@@ -46,16 +45,17 @@
 #include "nsCocoaFeatures.h"
 #endif
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/Endian.h"
+#include "mozilla/nsRefPtr.h"
 
 namespace mozilla {
 
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
 static const WebGLRectangleObject*
--- a/dom/canvas/WebGLContextUnchecked.h
+++ b/dom/canvas/WebGLContextUnchecked.h
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef WEBGLCONTEXTUNCHECKED_H
 #define WEBGLCONTEXTUNCHECKED_H
 
 #include "GLDefs.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "WebGLTypes.h"
 
 namespace mozilla {
 
 class WebGLBuffer;
 class WebGLSampler;
 namespace gl {
     class GLContext;
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLProgram.h"
 
 #include "GLContext.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "WebGLActiveInfo.h"
 #include "WebGLContext.h"
 #include "WebGLShader.h"
 #include "WebGLUniformLocation.h"
 #include "WebGLValidateStrings.h"
 
 namespace mozilla {
 
--- a/dom/fetch/FetchDriver.h
+++ b/dom/fetch/FetchDriver.h
@@ -7,17 +7,17 @@
 #ifndef mozilla_dom_FetchDriver_h
 #define mozilla_dom_FetchDriver_h
 
 #include "nsAutoPtr.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIChannelEventSink.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIStreamListener.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
 class nsIDocument;
 class nsIOutputStream;
 class nsILoadGroup;
 class nsIPrincipal;
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -22,16 +22,17 @@
 #include "mozilla/plugins/PluginWidgetChild.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/ipc/DocumentRendererChild.h"
 #include "mozilla/ipc/FileDescriptorUtils.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/APZEventState.h"
 #include "mozilla/layers/CompositorChild.h"
+#include "mozilla/layers/DoubleTapToZoom.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "mozilla/layout/RenderFrameChild.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
@@ -111,17 +112,16 @@ using namespace mozilla::layout;
 using namespace mozilla::docshell;
 using namespace mozilla::widget;
 using namespace mozilla::jsipc;
 
 NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener)
 
 static const CSSSize kDefaultViewportSize(980, 480);
 
-static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect";
 static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
 
 typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
 static TabChildMap* sTabChildren;
 
 class TabChild::DelayedFireContextMenuEvent final : public nsITimerCallback
 {
 public:
@@ -278,49 +278,16 @@ void
 TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
 {
     if (!mGlobal || !mTabChildGlobal) {
         return;
     }
 
     FrameMetrics newMetrics = aFrameMetrics;
     APZCCallbackHelper::UpdateRootFrame(newMetrics);
-
-    CSSSize cssCompositedSize = newMetrics.CalculateCompositedSizeInCssPixels();
-    // The BrowserElementScrolling helper must know about these updated metrics
-    // for other functions it performs, such as double tap handling.
-    // Note, %f must not be used because it is locale specific!
-    nsString data;
-    data.AppendPrintf("{ \"x\" : %d", NS_lround(newMetrics.GetScrollOffset().x));
-    data.AppendPrintf(", \"y\" : %d", NS_lround(newMetrics.GetScrollOffset().y));
-    data.AppendLiteral(", \"viewport\" : ");
-        data.AppendLiteral("{ \"width\" : ");
-        data.AppendFloat(newMetrics.GetViewport().width);
-        data.AppendLiteral(", \"height\" : ");
-        data.AppendFloat(newMetrics.GetViewport().height);
-        data.AppendLiteral(" }");
-    data.AppendLiteral(", \"cssPageRect\" : ");
-        data.AppendLiteral("{ \"x\" : ");
-        data.AppendFloat(newMetrics.GetScrollableRect().x);
-        data.AppendLiteral(", \"y\" : ");
-        data.AppendFloat(newMetrics.GetScrollableRect().y);
-        data.AppendLiteral(", \"width\" : ");
-        data.AppendFloat(newMetrics.GetScrollableRect().width);
-        data.AppendLiteral(", \"height\" : ");
-        data.AppendFloat(newMetrics.GetScrollableRect().height);
-        data.AppendLiteral(" }");
-    data.AppendLiteral(", \"cssCompositedRect\" : ");
-        data.AppendLiteral("{ \"width\" : ");
-        data.AppendFloat(cssCompositedSize.width);
-        data.AppendLiteral(", \"height\" : ");
-        data.AppendFloat(cssCompositedSize.height);
-        data.AppendLiteral(" }");
-    data.AppendLiteral(" }");
-
-    DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
 }
 
 NS_IMETHODIMP
 ContentListener::HandleEvent(nsIDOMEvent* aEvent)
 {
   RemoteDOMEvent remoteEvent;
   remoteEvent.mEvent = do_QueryInterface(aEvent);
   NS_ENSURE_STATE(remoteEvent.mEvent);
@@ -633,33 +600,17 @@ TabChild::TabChild(nsIContentChild* aMan
   }
 }
 
 NS_IMETHODIMP
 TabChild::Observe(nsISupports *aSubject,
                   const char *aTopic,
                   const char16_t *aData)
 {
-  if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) {
-    nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
-    nsCOMPtr<nsITabChild> tabChild(TabChild::GetFrom(docShell));
-    if (tabChild == this) {
-      nsCOMPtr<nsIDocument> doc(GetDocument());
-      uint32_t presShellId;
-      ViewID viewId;
-      if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(doc->GetDocumentElement(),
-                                                           &presShellId, &viewId)) {
-        CSSRect rect;
-        sscanf(NS_ConvertUTF16toUTF8(aData).get(),
-               "{\"x\":%f,\"y\":%f,\"w\":%f,\"h\":%f}",
-               &rect.x, &rect.y, &rect.width, &rect.height);
-        SendZoomToRect(presShellId, viewId, rect);
-      }
-    }
-  } else if (!strcmp(aTopic, BEFORE_FIRST_PAINT)) {
+  if (!strcmp(aTopic, BEFORE_FIRST_PAINT)) {
     if (AsyncPanZoomEnabled()) {
       nsCOMPtr<nsIDocument> subject(do_QueryInterface(aSubject));
       nsCOMPtr<nsIDocument> doc(GetDocument());
 
       if (SameCOMIdentity(subject, doc)) {
         nsCOMPtr<nsIPresShell> shell(doc->GetShell());
         if (shell) {
           shell->SetIsFirstPaint(true);
@@ -1759,24 +1710,28 @@ TabChild::RecvHandleDoubleTap(const CSSP
 
     if (!mGlobal || !mTabChildGlobal) {
         return true;
     }
 
     // Note: there is nothing to do with the modifiers here, as we are not
     // synthesizing any sort of mouse event.
     CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
-    nsString data;
-    data.AppendLiteral("{ \"x\" : ");
-    data.AppendFloat(point.x);
-    data.AppendLiteral(", \"y\" : ");
-    data.AppendFloat(point.y);
-    data.AppendLiteral(" }");
-
-    DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data);
+    nsCOMPtr<nsIDocument> document = GetDocument();
+    CSSRect zoomToRect = CalculateRectToZoomTo(document, point);
+    // The double-tap can be dispatched by any scroll frame (so |aGuid| could be
+    // the guid of any scroll frame), but the zoom-to-rect operation must be
+    // performed by the root content scroll frame, so query its identifiers
+    // for the SendZoomToRect() call rather than using the ones from |aGuid|.
+    uint32_t presShellId;
+    ViewID viewId;
+    if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
+        document->GetDocumentElement(), &presShellId, &viewId)) {
+      SendZoomToRect(presShellId, viewId, zoomToRect);
+    }
 
     return true;
 }
 
 bool
 TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid)
 {
   if (mGlobal && mTabChildGlobal) {
@@ -2449,17 +2404,16 @@ TabChild::RecvDestroy()
     // run script.
     MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
     mTabChildGlobal->DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
   }
 
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
 
-  observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT);
   observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
 
   const nsAttrValue::EnumTable* table =
     AudioChannelService::GetAudioChannelTable();
 
   nsAutoCString topic;
   for (uint32_t i = 0; table[i].tag; ++i) {
     topic.Assign("audiochannel-activity-");
@@ -2652,19 +2606,16 @@ TabChild::InitRenderingState(const Textu
       mLayersId = aLayersId;
     }
 
     nsCOMPtr<nsIObserverService> observerService =
         mozilla::services::GetObserverService();
 
     if (observerService) {
         observerService->AddObserver(this,
-                                     BROWSER_ZOOM_TO_RECT,
-                                     false);
-        observerService->AddObserver(this,
                                      BEFORE_FIRST_PAINT,
                                      false);
     }
     return true;
 }
 
 void
 TabChild::SetBackgroundColor(const nscolor& aColor)
--- a/dom/media/AbstractThread.h
+++ b/dom/media/AbstractThread.h
@@ -6,17 +6,17 @@
 
 #if !defined(AbstractThread_h_)
 #define AbstractThread_h_
 
 #include "nscore.h"
 #include "nsIRunnable.h"
 #include "nsISupportsImpl.h"
 #include "nsIThread.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 #include "mozilla/ThreadLocal.h"
 
 namespace mozilla {
 
 class TaskQueue;
 class TaskDispatcher;
 
--- a/dom/media/AudioSink.h
+++ b/dom/media/AudioSink.h
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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/. */
 #if !defined(AudioSink_h__)
 #define AudioSink_h__
 
 #include "MediaInfo.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsISupportsImpl.h"
 
 #include "mozilla/dom/AudioChannelBinding.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/ReentrantMonitor.h"
 
--- a/dom/media/DecodedStream.h
+++ b/dom/media/DecodedStream.h
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef DecodedStream_h_
 #define DecodedStream_h_
 
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsTArray.h"
 #include "MediaInfo.h"
 
 #include "mozilla/UniquePtr.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/Maybe.h"
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -7,17 +7,17 @@
 #define MediaData_h
 
 #include "nsSize.h"
 #include "mozilla/gfx/Rect.h"
 #include "nsRect.h"
 #include "AudioSampleFormat.h"
 #include "nsIMemoryReporter.h"
 #include "SharedBuffer.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 
 namespace layers {
 class Image;
 class ImageContainer;
 } // namespace layers
--- a/dom/media/MediaDataDemuxer.h
+++ b/dom/media/MediaDataDemuxer.h
@@ -9,17 +9,17 @@
 
 #include "mozilla/MozPromise.h"
 #include "mozilla/UniquePtr.h"
 
 #include "MediaData.h"
 #include "MediaInfo.h"
 #include "TimeUnits.h"
 #include "nsISupportsImpl.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 
 class MediaTrackDemuxer;
 class TrackMetadataHolder;
 
 enum class DemuxerFailureReason : int8_t
--- a/dom/media/MediaInfo.h
+++ b/dom/media/MediaInfo.h
@@ -3,17 +3,17 @@
 /* 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/. */
 #if !defined(MediaInfo_h)
 #define MediaInfo_h
 
 #include "mozilla/UniquePtr.h"
 #include "nsRect.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsSize.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "ImageTypes.h"
 #include "MediaData.h"
 #include "StreamBuffer.h" // for TrackID
 #include "TimeUnits.h"
 
--- a/dom/media/MediaStreamError.h
+++ b/dom/media/MediaStreamError.h
@@ -7,17 +7,17 @@
 #ifndef mozilla_dom_MediaStreamError_h
 #define mozilla_dom_MediaStreamError_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
 #include "nsWrapperCache.h"
 #include "js/TypeDecls.h"
 #include "nsPIDOMWindow.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 #if defined(XP_WIN) && defined(GetMessage)
 #undef GetMessage
 #endif
 
 namespace mozilla {
 namespace dom {
 
--- a/dom/media/MediaTimer.h
+++ b/dom/media/MediaTimer.h
@@ -9,17 +9,17 @@
 
 #include "mozilla/Monitor.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/TimeStamp.h"
 
 #include <queue>
 
 #include "nsITimer.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 namespace mozilla {
 
 extern PRLogModuleInfo* gMediaTimerLog;
 
 #define TIMER_LOG(x, ...) \
   MOZ_ASSERT(gMediaTimerLog); \
   MOZ_LOG(gMediaTimerLog, LogLevel::Debug, ("[MediaTimer=%p relative_t=%lld]" x, this, \
--- a/dom/media/mediasource/ContainerParser.h
+++ b/dom/media/mediasource/ContainerParser.h
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_CONTAINERPARSER_H_
 #define MOZILLA_CONTAINERPARSER_H_
 
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsString.h"
 #include "MediaResource.h"
 
 namespace mozilla {
 
 class MediaByteBuffer;
 class SourceBufferResource;
 
--- a/dom/media/omx/MediaCodecProxy.h
+++ b/dom/media/omx/MediaCodecProxy.h
@@ -9,17 +9,17 @@
 
 #include <nsString.h>
 #include <stagefright/MediaCodec.h>
 #include <stagefright/MediaBuffer.h>
 #include <utils/threads.h>
 
 #include "mozilla/media/MediaSystemResourceClient.h"
 #include "mozilla/Monitor.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 namespace android {
 // This class is intended to be a proxy for MediaCodec with codec resource
 // management. Basically user can use it like MediaCodec, but need to handle
 // the listener when Codec is reserved for Async case. A good example is
 // MediaCodecReader.cpp. Another useage is to use configure(), Prepare(),
 // Input(), and Output(). It is used in GonkVideoDecoderManager.cpp which
 // doesn't need to handle the buffers for codec.
--- a/dom/media/omx/OMXCodecProxy.h
+++ b/dom/media/omx/OMXCodecProxy.h
@@ -9,17 +9,17 @@
 
 #include <android/native_window.h>
 #include <media/IOMX.h>
 #include <stagefright/MediaBuffer.h>
 #include <stagefright/MediaSource.h>
 #include <utils/threads.h>
 
 #include "mozilla/media/MediaSystemResourceClient.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 namespace android {
 
 struct MetaData;
 
 class OMXCodecProxy : public MediaSource
                     , public mozilla::MediaSystemResourceReservationListener
 {
--- a/dom/media/omx/OMXCodecWrapper.h
+++ b/dom/media/omx/OMXCodecWrapper.h
@@ -11,17 +11,17 @@
 #include <stagefright/foundation/ABuffer.h>
 #include <stagefright/foundation/AMessage.h>
 #include <stagefright/MediaCodec.h>
 
 #include "AudioSegment.h"
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
 #include "mozilla/media/MediaSystemResourceClient.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 #include <speex/speex_resampler.h>
 
 namespace android {
 
 // Wrapper class for managing HW codec reservations
 class OMXCodecReservation : public RefBase
 {
--- a/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.h
+++ b/dom/media/platforms/agnostic/gmp/MediaDataDecoderProxy.h
@@ -3,17 +3,17 @@
 /* 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/. */
 
 #if !defined(MediaDataDecoderProxy_h_)
 #define MediaDataDecoderProxy_h_
 
 #include "PlatformDecoderModule.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsThreadUtils.h"
 #include "nscore.h"
 
 namespace mozilla {
 
 class InputTask : public nsRunnable {
 public:
   InputTask(MediaDataDecoder* aDecoder,
--- a/dom/media/systemservices/MediaSystemResourceClient.h
+++ b/dom/media/systemservices/MediaSystemResourceClient.h
@@ -7,17 +7,17 @@
 #if !defined(MediaSystemResourceClient_h_)
 #define MediaSystemResourceClient_h_
 
 #include "MediaSystemResourceManager.h"
 #include "MediaSystemResourceTypes.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/media/MediaSystemResourceTypes.h"
 #include "mozilla/Monitor.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 namespace mozilla {
 
 class MediaSystemResourceManager;
 
 
 /**
  * This is a base class for listener callbacks.
--- a/dom/media/tests/mochitest/network.js
+++ b/dom/media/tests/mochitest/network.js
@@ -20,17 +20,17 @@ function isNetworkReady() {
           SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_SUPL_INTERFACES |
           SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_IMS_INTERFACES |
           SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_DUN_INTERFACES |
           SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_FOTA_INTERFACES);
     var num = itfList.getNumberOfInterface();
     for (var i = 0; i < num; i++) {
       var ips = {};
       var prefixLengths = {};
-      var length = itfList.getInterface(i).getAddresses(ips, prefixLengths);
+      var length = itfList.getInterfaceInfo(i).getAddresses(ips, prefixLengths);
 
       for (var j = 0; j < length; j++) {
         var ip = ips.value[j];
         // skip IPv6 address until bug 797262 is implemented
         if (ip.indexOf(":") < 0) {
           info("Network interface is ready with address: " + ip);
           return true;
         }
--- a/dom/media/webrtc/RTCIdentityProviderRegistrar.h
+++ b/dom/media/webrtc/RTCIdentityProviderRegistrar.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; 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/. */
 
 #ifndef RTCIDENTITYPROVIDER_H_
 #define RTCIDENTITYPROVIDER_H_
 
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsCOMPtr.h"
 #include "nsISupportsImpl.h"
 #include "nsIGlobalObject.h"
 #include "nsWrapperCache.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/BindingDeclarations.h"
 
--- a/dom/mobileconnection/gonk/MobileConnectionService.js
+++ b/dom/mobileconnection/gonk/MobileConnectionService.js
@@ -703,20 +703,20 @@ MobileConnectionProvider.prototype = {
     if (isUpdated && !aBatch) {
       this.deliverListenerEvent("notifyVoiceChanged");
     }
   },
 
   updateDataInfo: function(aNewInfo, aBatch = false) {
     // For the data connection, the `connected` flag indicates whether
     // there's an active data call. We get correct `connected` state here.
-    let active = gNetworkManager.active;
+    let active = gNetworkManager.activeNetworkInfo;
     aNewInfo.connected = false;
     if (active &&
-        active.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE &&
+        active.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE &&
         active.serviceId === this._clientId) {
       aNewInfo.connected = true;
     }
 
     let isUpdated = this._updateConnectionInfo(this.data, aNewInfo);
     if (isUpdated && !aBatch) {
       this.deliverListenerEvent("notifyDataChanged");
     }
@@ -1594,21 +1594,20 @@ MobileConnectionService.prototype = {
       case NS_NETWORK_ACTIVE_CHANGED_TOPIC_ID:
         for (let i = 0; i < this.numItems; i++) {
           let provider = this._providers[i];
           // Update connected flag only.
           provider.updateDataInfo({});
         }
         break;
       case NS_DATA_CALL_ERROR_TOPIC_ID:
-        let network = aSubject;
         try {
-          if (network instanceof Ci.nsIRilNetworkInterface) {
-            let rilNetwork = network.QueryInterface(Ci.nsIRilNetworkInterface);
-            this.notifyDataError(rilNetwork.serviceId, rilNetwork);
+          if (aSubject instanceof Ci.nsIRilNetworkInfo) {
+            let rilInfo = aSubject.QueryInterface(Ci.nsIRilNetworkInfo);
+            this.notifyDataError(rilInfo.serviceId, aData);
           }
         } catch (e) {}
         break;
       case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
         if (aData === kPrefRilDebuggingEnabled) {
           this._updateDebugFlag();
         }
         break;
--- a/dom/mobilemessage/gonk/MmsService.js
+++ b/dom/mobilemessage/gonk/MmsService.js
@@ -222,20 +222,20 @@ function MmsConnection(aServiceId) {
 MmsConnection.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
 
   /** MMS proxy settings. */
   mmsc:     "",
   mmsProxy: "",
   mmsPort:  -1,
 
-  setApnSetting: function(network) {
-    this.mmsc = network.mmsc;
-    this.mmsProxy = network.mmsProxy;
-    this.mmsPort = network.mmsPort;
+  setApnSetting: function(networkInfo) {
+    this.mmsc = networkInfo.mmsc;
+    this.mmsProxy = networkInfo.mmsProxy;
+    this.mmsPort = networkInfo.mmsPort;
   },
 
   get proxyInfo() {
     if (!this.mmsProxy) {
       if (DEBUG) debug("getProxyInfo: MMS proxy is not available.");
       return null;
     }
 
@@ -263,18 +263,18 @@ MmsConnection.prototype = {
   pendingCallbacks: null,
 
   /** MMS network connection reference count. */
   refCount: 0,
 
   // cache of hosts to be accessed when this connection is alive.
   hostsToRoute: null,
 
-  // cache of the networkInterface acquired during this connection.
-  networkInterface: null,
+  // cache of the networkInfo acquired during this connection.
+  networkInfo: null,
 
   connectTimer: null,
 
   disconnectTimer: null,
 
   /**
    * Callback when |connectTimer| is timeout or cancelled by shutdown.
    */
@@ -298,24 +298,24 @@ MmsConnection.prototype = {
       return;
     }
 
     let deactivateMmsDataCall = (aError) => {
       if (aError) debug("Failed to removeHostRoute: " + aError);
 
       // Clear cache.
       this.hostsToRoute = [];
-      this.networkInterface = null;
+      this.networkInfo = null;
 
-      this.radioInterface.deactivateDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS);
+      this.radioInterface.deactivateDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS);
     };
 
     let promises =
       this.hostsToRoute.map((aHost) => {
-        return gNetworkManager.removeHostRoute(this.networkInterface, aHost);
+        return gNetworkManager.removeHostRoute(this.networkInfo, aHost);
       });
 
     return Promise.all(promises)
       .then(() => deactivateMmsDataCall(),
             (aError) => deactivateMmsDataCall(aError));
   },
 
   init: function() {
@@ -437,17 +437,17 @@ MmsConnection.prototype = {
       // MMS network fails to be connected within a time period.
       this.connectTimer.
         initWithCallback(() => this.flushPendingCallbacks(_HTTP_STATUS_ACQUIRE_TIMEOUT),
                          TIME_TO_BUFFER_MMS_REQUESTS,
                          Ci.nsITimer.TYPE_ONE_SHOT);
 
       // Bug 1059110: Ensure all the initialization are done before setup data call.
       if (DEBUG) debug("acquire: buffer the MMS request and setup the MMS data call.");
-      this.radioInterface.setupDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS);
+      this.radioInterface.setupDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS);
 
       return false;
     }
 
     callback(true, _HTTP_STATUS_ACQUIRE_CONNECTION_SUCCESS);
     return true;
   },
 
@@ -489,17 +489,17 @@ MmsConnection.prototype = {
       host = url;
     }
 
     try {
       let uri = Services.io.newURI(host, null, null);
       host = uri.host;
     } catch (e) {}
 
-    return gNetworkManager.addHostRoute(this.networkInterface, host)
+    return gNetworkManager.addHostRoute(this.networkInfo, host)
       .then(() => {
         if (this.hostsToRoute.indexOf(host) < 0) {
           this.hostsToRoute.push(host);
         }
       });
   },
 
   shutdown: function() {
@@ -512,50 +512,50 @@ MmsConnection.prototype = {
     this.onDisconnectTimerTimeout();
   },
 
   // nsIObserver
 
   observe: function(subject, topic, data) {
     switch (topic) {
       case kNetworkConnStateChangedTopic: {
-        // The network for MMS connection must be nsIRilNetworkInterface.
-        if (!(subject instanceof Ci.nsIRilNetworkInterface)) {
+        // The network info for MMS connection must be nsIRilNetworkInfo.
+        if (!(subject instanceof Ci.nsIRilNetworkInfo)) {
           return;
         }
 
         // Check if the network state change belongs to this service.
-        let network = subject.QueryInterface(Ci.nsIRilNetworkInterface);
-        if (network.serviceId != this.serviceId ||
-            network.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS) {
+        let networkInfo = subject.QueryInterface(Ci.nsIRilNetworkInfo);
+        if (networkInfo.serviceId != this.serviceId ||
+            networkInfo.type != Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS) {
           return;
         }
 
         let connected =
-          network.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED;
+          networkInfo.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
 
         // Return if the MMS network state doesn't change, where the network
         // state change can come from other non-MMS networks.
         if (connected == this.connected) {
           return;
         }
 
         this.connected = connected;
         if (!this.connected) {
           this.hostsToRoute = [];
-          this.networkInterface = null;
+          this.networkInfo = null;
           return;
         }
 
         // Set up the MMS APN setting based on the connected MMS network,
         // which is going to be used for the HTTP requests later.
-        this.setApnSetting(network);
+        this.setApnSetting(networkInfo);
 
-        // Cache connected network.
-        this.networkInterface = network;
+        // Cache connected network info.
+        this.networkInfo = networkInfo;
 
         if (DEBUG) debug("Got the MMS network connected! Resend the buffered " +
                          "MMS requests: number: " + this.pendingCallbacks.length);
         this.connectTimer.cancel();
         this.flushPendingCallbacks(_HTTP_STATUS_ACQUIRE_CONNECTION_SUCCESS);
         break;
       }
       case NS_XPCOM_SHUTDOWN_OBSERVER_ID: {
@@ -740,17 +740,17 @@ XPCOMUtils.defineLazyGetter(this, "gMmsT
           debug('Failed to start a transaction: ' + aReason);
           mmsConnection.release();
           cancellable.done(_HTTP_STATUS_FAILED_TO_ROUTE, null);
         };
 
         // TODO: |getNetId| will be implemented as a sync call in nsINetworkManager
         //       once Bug 1141903 is landed.
         mmsConnection.ensureRouting(url)
-          .then(() => gNetworkService.getNetId(mmsConnection.networkInterface.name))
+          .then(() => gNetworkService.getNetId(mmsConnection.networkInfo.name))
           .then((netId) => startTransaction(netId))
           .catch((aReason) => onRejected(aReason));
       });
 
       return cancellable;
     },
 
     sendHttpRequest: function(mmsConnection, method, url, istream, proxyFilter,
--- a/dom/network/NetworkStatsService.jsm
+++ b/dom/network/NetworkStatsService.jsm
@@ -21,18 +21,18 @@ Cu.import("resource://gre/modules/Networ
 Cu.import("resource://gre/modules/Timer.jsm");
 
 const NET_NETWORKSTATSSERVICE_CONTRACTID = "@mozilla.org/network/netstatsservice;1";
 const NET_NETWORKSTATSSERVICE_CID = Components.ID("{18725604-e9ac-488a-8aa0-2471e7f6c0a4}");
 
 const TOPIC_BANDWIDTH_CONTROL = "netd-bandwidth-control"
 
 const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
-const NET_TYPE_WIFI = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
-const NET_TYPE_MOBILE = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
+const NET_TYPE_WIFI = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI;
+const NET_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
 
 // Networks have different status that NetworkStats API needs to be aware of.
 // Network is present and ready, so NetworkManager provides the whole info.
 const NETWORK_STATUS_READY   = 0;
 // Network is present but hasn't established a connection yet (e.g. SIM that has not
 // enabled 3G since boot).
 const NETWORK_STATUS_STANDBY = 1;
 // Network is not present, but stored in database by the previous connections.
@@ -187,20 +187,20 @@ this.NetworkStatsService = {
   observe: function observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case TOPIC_CONNECTION_STATE_CHANGED:
 
         // If new interface is registered (notified from NetworkService),
         // the stats are updated for the new interface without waiting to
         // complete the updating period.
 
-        let network = aSubject.QueryInterface(Ci.nsINetworkInterface);
-        debug("Network " + network.name + " of type " + network.type + " status change");
+        let networkInfo = aSubject.QueryInterface(Ci.nsINetworkInfo);
+        debug("Network " + networkInfo.name + " of type " + networkInfo.type + " status change");
 
-        let netId = this.convertNetworkInterface(network);
+        let netId = this.convertNetworkInfo(networkInfo);
         if (!netId) {
           break;
         }
 
         this._updateCurrentAlarm(netId);
 
         debug("NetId: " + netId);
         this.updateStats(netId);
@@ -264,43 +264,43 @@ this.NetworkStatsService = {
                                       NET_TYPE_MOBILE);
         networks[netId] = { id : icc.iccInfo.iccid,
                             type: NET_TYPE_MOBILE };
       }
     }
     return networks;
   },
 
-  convertNetworkInterface: function(aNetwork) {
-    if (aNetwork.type != NET_TYPE_MOBILE &&
-        aNetwork.type != NET_TYPE_WIFI) {
+  convertNetworkInfo: function(aNetworkInfo) {
+    if (aNetworkInfo.type != NET_TYPE_MOBILE &&
+        aNetworkInfo.type != NET_TYPE_WIFI) {
       return null;
     }
 
     let id = '0';
-    if (aNetwork.type == NET_TYPE_MOBILE) {
-      if (!(aNetwork instanceof Ci.nsIRilNetworkInterface)) {
-        debug("Error! Mobile network should be an nsIRilNetworkInterface!");
+    if (aNetworkInfo.type == NET_TYPE_MOBILE) {
+      if (!(aNetworkInfo instanceof Ci.nsIRilNetworkInfo)) {
+        debug("Error! Mobile network should be an nsIRilNetworkInfo!");
         return null;
       }
 
-      let rilNetwork = aNetwork.QueryInterface(Ci.nsIRilNetworkInterface);
+      let rilNetwork = aNetworkInfo.QueryInterface(Ci.nsIRilNetworkInfo);
       id = rilNetwork.iccId;
     }
 
-    let netId = this.getNetworkId(id, aNetwork.type);
+    let netId = this.getNetworkId(id, aNetworkInfo.type);
 
     if (!this._networks[netId]) {
       this._networks[netId] = Object.create(null);
       this._networks[netId].network = { id: id,
-                                        type: aNetwork.type };
+                                        type: aNetworkInfo.type };
     }
 
     this._networks[netId].status = NETWORK_STATUS_READY;
-    this._networks[netId].interfaceName = aNetwork.name;
+    this._networks[netId].interfaceName = aNetworkInfo.name;
     return netId;
   },
 
   getNetworkId: function getNetworkId(aIccId, aNetworkType) {
     return aIccId + '' + aNetworkType;
   },
 
   /* Function to ensure that one network is valid. The network is valid if its status is
@@ -733,20 +733,20 @@ this.NetworkStatsService = {
         aCallback(true, "OK");
       }
     });
   },
 
   /*
    * Function responsible for receiving stats which are not from netd.
    */
-  saveStats: function saveStats(aAppId, aIsInBrowser, aServiceType, aNetwork,
+  saveStats: function saveStats(aAppId, aIsInBrowser, aServiceType, aNetworkInfo,
                                 aTimeStamp, aRxBytes, aTxBytes, aIsAccumulative,
                                 aCallback) {
-    let netId = this.convertNetworkInterface(aNetwork);
+    let netId = this.convertNetworkInfo(aNetworkInfo);
     if (!netId) {
       if (aCallback) {
         aCallback(false, "Invalid network type");
       }
       return;
     }
 
     // Check if |aConnectionType|, |aAppId| and |aServiceType| are valid.
--- a/dom/network/NetworkStatsServiceProxy.js
+++ b/dom/network/NetworkStatsServiceProxy.js
@@ -24,66 +24,66 @@ function NetworkStatsServiceProxy() {
   }
 }
 
 NetworkStatsServiceProxy.prototype = {
   /*
    * Function called in the protocol layer (HTTP, FTP, WebSocket ...etc)
    * to pass the per-app stats to NetworkStatsService.
    */
-  saveAppStats: function saveAppStats(aAppId, aIsInBrowser, aNetwork, aTimeStamp,
+  saveAppStats: function saveAppStats(aAppId, aIsInBrowser, aNetworkInfo, aTimeStamp,
                                       aRxBytes, aTxBytes, aIsAccumulative,
                                       aCallback) {
-    if (!aNetwork) {
+    if (!aNetworkInfo) {
       if (DEBUG) {
-        debug("|aNetwork| is not specified. Failed to save stats. Returning.");
+        debug("|aNetworkInfo| is not specified. Failed to save stats. Returning.");
       }
       return;
     }
 
     if (DEBUG) {
       debug("saveAppStats: " + aAppId + " " + aIsInBrowser + " " +
-            aNetwork.type + " " + aTimeStamp + " " +
+            aNetworkInfo.type + " " + aTimeStamp + " " +
             aRxBytes + " " + aTxBytes + " " + aIsAccumulative);
     }
 
     if (aCallback) {
       aCallback = aCallback.notify;
     }
 
-    NetworkStatsService.saveStats(aAppId, aIsInBrowser, "", aNetwork,
+    NetworkStatsService.saveStats(aAppId, aIsInBrowser, "", aNetworkInfo,
                                   aTimeStamp, aRxBytes, aTxBytes,
                                   aIsAccumulative, aCallback);
   },
 
   /*
    * Function called in the points of different system services
    * to pass the per-service stats to NetworkStatsService.
    */
-  saveServiceStats: function saveServiceStats(aServiceType, aNetwork,
+  saveServiceStats: function saveServiceStats(aServiceType, aNetworkInfo,
                                               aTimeStamp, aRxBytes, aTxBytes,
                                               aIsAccumulative, aCallback) {
-    if (!aNetwork) {
+    if (!aNetworkInfo) {
       if (DEBUG) {
-        debug("|aNetwork| is not specified. Failed to save stats. Returning.");
+        debug("|aNetworkInfo| is not specified. Failed to save stats. Returning.");
       }
       return;
     }
 
     if (DEBUG) {
-      debug("saveServiceStats: " + aServiceType + " " + aNetwork.type + " " +
+      debug("saveServiceStats: " + aServiceType + " " + aNetworkInfo.type + " " +
             aTimeStamp + " " + aRxBytes + " " + aTxBytes + " " +
             aIsAccumulative);
     }
 
     if (aCallback) {
       aCallback = aCallback.notify;
     }
 
-    NetworkStatsService.saveStats(0, false, aServiceType ,aNetwork, aTimeStamp,
+    NetworkStatsService.saveStats(0, false, aServiceType , aNetworkInfo, aTimeStamp,
                                   aRxBytes, aTxBytes, aIsAccumulative,
                                   aCallback);
   },
 
   classID : NETWORKSTATSSERVICEPROXY_CID,
   QueryInterface : XPCOMUtils.generateQI([nsINetworkStatsServiceProxy]),
 }
 
--- a/dom/network/TCPSocket.js
+++ b/dom/network/TCPSocket.js
@@ -180,17 +180,17 @@ TCPSocket.prototype = {
   _trackingNumber: 0,
 
 #ifdef MOZ_WIDGET_GONK
   // Network statistics (Gonk-specific feature)
   _txBytes: 0,
   _rxBytes: 0,
   _appId: Ci.nsIScriptSecurityManager.NO_APP_ID,
   _inBrowser: false,
-  _activeNetwork: null,
+  _activeNetworkInfo: null,
 #endif
 
   // Public accessors.
   get readyState() {
     return this._readyState;
   },
   get binaryType() {
     return this._binaryType;
@@ -369,17 +369,17 @@ TCPSocket.prototype = {
     }
 
     let nssProxy = Cc["@mozilla.org/networkstatsServiceProxy;1"]
                      .getService(Ci.nsINetworkStatsServiceProxy);
     if (!nssProxy) {
       LOG("Error: Ci.nsINetworkStatsServiceProxy service is not available.");
       return;
     }
-    nssProxy.saveAppStats(this._appId, this._inBrowser, this._activeNetwork,
+    nssProxy.saveAppStats(this._appId, this._inBrowser, this._activeNetworkInfo,
                           Date.now(), this._rxBytes, this._txBytes, false);
 
     // Reset the counters once the statistics is saved to NetworkStatsServiceProxy.
     this._txBytes = this._rxBytes = 0;
   },
   // End of helper method for network statistics.
 #endif
 
@@ -611,22 +611,22 @@ TCPSocket.prototype = {
       return that;
     }
 
     let transport = that._transport = this._createTransport(host, port, that._ssl);
     transport.setEventSink(that, Services.tm.currentThread);
     that._initStream(that._binaryType);
 
 #ifdef MOZ_WIDGET_GONK
-    // Set _activeNetwork, which is only required for network statistics.
+    // Set _activeNetworkInfo, which is only required for network statistics.
     // Note that nsINetworkManager, as well as nsINetworkStatsServiceProxy, is
     // Gonk-specific.
     let networkManager = Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
     if (networkManager) {
-      that._activeNetwork = networkManager.active;
+      that._activeNetworkInfo = networkManager.activeNetworkInfo;
     }
 #endif
 
     return that;
   },
 
   upgradeToSecure: function ts_upgradeToSecure() {
     if (this._readyState !== kOPEN) {
--- a/dom/network/interfaces/nsINetworkStatsServiceProxy.idl
+++ b/dom/network/interfaces/nsINetworkStatsServiceProxy.idl
@@ -1,43 +1,43 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-interface nsINetworkInterface;
+interface nsINetworkInfo;
 
 [scriptable, function, uuid(5f821529-1d80-4ab5-a933-4e1b3585b6bc)]
 interface nsINetworkStatsServiceProxyCallback : nsISupports
 {
   /*
    * @param aResult callback result with boolean value
    * @param aMessage message
    */
   void notify(in boolean aResult, in jsval aMessage);
 };
 
-[scriptable, uuid(98fd8f69-784e-4626-aa59-56d6436a3c24)]
+[scriptable, uuid(f4f3e901-e102-499d-9d37-dc9951f52df7)]
 interface nsINetworkStatsServiceProxy : nsISupports
 {
   /*
    * An interface used to record per-app traffic data.
    * @param aAppId app id
    * @param aIsInBrowser true if the iframe element is mozbrowser
    * @param aNetworkInterface network
    * @param aTimeStamp time stamp
    * @param aRxBytes received data amount
    * @param aTxBytes transmitted data amount
    * @param aIsAccumulative is stats accumulative
    * @param aCallback an optional callback
    */
   void saveAppStats(in unsigned long aAppId,
                     in boolean aIsInBrowser,
-                    in nsINetworkInterface aNetwork,
+                    in nsINetworkInfo aNetworkInfo,
                     in unsigned long long aTimeStamp,
                     in unsigned long long aRxBytes,
                     in unsigned long long aTxBytes,
                     in boolean aIsAccumulative,
          [optional] in nsINetworkStatsServiceProxyCallback aCallback);
 
   /*
    * An interface used to record per-system service traffic data.
@@ -45,15 +45,15 @@ interface nsINetworkStatsServiceProxy : 
    * @param aNetworkInterface network
    * @param aTimeStamp time stamp
    * @param aRxBytes received data amount
    * @param aTxBytes transmitted data amount
    * @param aIsAccumulative is stats accumulative
    * @param aCallback an optional callback
    */
   void saveServiceStats(in string aServiceType,
-                        in nsINetworkInterface aNetwork,
+                        in nsINetworkInfo aNetworkInfo,
                         in unsigned long long aTimeStamp,
                         in unsigned long long aRxBytes,
                         in unsigned long long aTxBytes,
                         in boolean aIsAccumulative,
              [optional] in nsINetworkStatsServiceProxyCallback aCallback);
 };
--- a/dom/network/tests/unit_stats/test_networkstats_db.js
+++ b/dom/network/tests/unit_stats/test_networkstats_db.js
@@ -931,17 +931,17 @@ var alarms = [{ id:                null,
 var alarmsDbId = 1;
 
 add_test(function test_addAlarm() {
   // Add alarms[0] -> DB: [ alarms[0] (id: 1) ]
   // Check the insertion is OK.
   netStatsDb.addAlarm(alarms[0], function(error, result) {
     do_check_eq(error, null);
     alarmsDbId = result;
-    netStatsDb.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI, exampleManifestURL, function(error, result) {
+    netStatsDb.getAlarms(Ci.nsINetworkInfo.NETWORK_TYPE_WIFI, exampleManifestURL, function(error, result) {
       do_check_eq(error, null);
       do_check_eq(result.length, 1);
       do_check_eq(result[0].id, alarmsDbId);
       do_check_eq(result[0].networkId, alarms[0].networkId);
       do_check_eq(result[0].absoluteThreshold, alarms[0].absoluteThreshold);
       do_check_eq(result[0].relativeThreshold, alarms[0].relativeThreshold);
       do_check_eq(result[0].data.foo, alarms[0].data.foo);
       run_next_test();
--- a/dom/network/tests/unit_stats/test_networkstats_service.js
+++ b/dom/network/tests/unit_stats/test_networkstats_service.js
@@ -255,29 +255,29 @@ add_test(function test_fireAlarm() {
                 data: null,
                 pageURL: testPageURL,
                 manifestURL: testManifestURL };
 
   // Set wifi status to standby to avoid connecting to netd when adding an alarm.
   NetworkStatsService._networks[wifiId].status = NETWORK_STATUS_STANDBY;
 
   NetworkStatsService._db.addAlarm(alarm, function addSuccessCb(error, newId) {
-    NetworkStatsService._db.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
+    NetworkStatsService._db.getAlarms(Ci.nsINetworkInfo.NETWORK_TYPE_WIFI,
                                       testManifestURL, function onGet(error, result) {
       do_check_eq(error, null);
       do_check_eq(result.length, 1);
 
       // Result of getAlarms is based on expected child's data format, so
       // some changes are needed to be able to use it.
       result[0].networkId = wifiId;
       result[0].pageURL = testPageURL;
       result[0].manifestURL = testManifestURL;
 
       NetworkStatsService._fireAlarm(result[0], false);
-      NetworkStatsService._db.getAlarms(Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
+      NetworkStatsService._db.getAlarms(Ci.nsINetworkInfo.NETWORK_TYPE_WIFI,
                                         testManifestURL, function onGet(error, result) {
         do_check_eq(error, undefined);
         do_check_eq(result.length, 0);
         run_next_test();
       });
     });
   });
 });
--- a/dom/network/tests/unit_stats/test_networkstats_service_proxy.js
+++ b/dom/network/tests/unit_stats/test_networkstats_service_proxy.js
@@ -4,51 +4,50 @@
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "nssProxy",
                                    "@mozilla.org/networkstatsServiceProxy;1",
                                    "nsINetworkStatsServiceProxy");
 
-function mokConvertNetworkInterface() {
-  NetworkStatsService.convertNetworkInterface = function(aNetwork) {
-    if (aNetwork.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE &&
-        aNetwork.type != Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+function mokConvertNetworkInfo() {
+  NetworkStatsService.convertNetworkInfo = function(aNetworkInfo) {
+    if (aNetworkInfo.type != Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE &&
+        aNetworkInfo.type != Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) {
       return null;
     }
 
     let id = '0';
-    if (aNetwork.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
+    if (aNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE) {
       id = '1234'
     }
 
-    let netId = this.getNetworkId(id, aNetwork.type);
+    let netId = this.getNetworkId(id, aNetworkInfo.type);
 
     if (!this._networks[netId]) {
       this._networks[netId] = Object.create(null);
       this._networks[netId].network = { id: id,
-                                        type: aNetwork.type };
+                                        type: aNetworkInfo.type };
     }
 
     return netId;
   };
 }
 
 add_test(function test_saveAppStats() {
   var cachedStats = NetworkStatsService.cachedStats;
   var timestamp = NetworkStatsService.cachedStatsDate.getTime();
 
-  // Create to fake nsINetworkInterfaces. As nsINetworkInterface can not
-  // be instantiated, these two vars will emulate it by filling the properties
-  // that will be used.
-  var wifi = {type: Ci.nsINetworkInterface.NETWORK_TYPE_WIFI, id: "0"};
-  var mobile = {type: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, id: "1234"};
+  // Create to fake nsINetworkInfos. As nsINetworkInfo can not be instantiated,
+  // these two vars will emulate it by filling the properties that will be used.
+  var wifi = {type: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI, id: "0"};
+  var mobile = {type: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, id: "1234"};
 
-  // Insert fake mobile network interface in NetworkStatsService
+  // Insert fake mobile network info in NetworkStatsService
   var mobileNetId = NetworkStatsService.getNetworkId(mobile.id, mobile.type);
 
   do_check_eq(Object.keys(cachedStats).length, 0);
 
   nssProxy.saveAppStats(1, false, wifi, timestamp, 10, 20, false,
                         function (success, message) {
     do_check_eq(success, true);
     nssProxy.saveAppStats(1, false, mobile, timestamp, 10, 20, false,
@@ -78,23 +77,22 @@ add_test(function test_saveAppStats() {
       run_next_test();
     });
   });
 });
 
 add_test(function test_saveServiceStats() {
   var timestamp = NetworkStatsService.cachedStatsDate.getTime();
 
-  // Create to fake nsINetworkInterfaces. As nsINetworkInterface can not
-  // be instantiated, these two vars will emulate it by filling the properties
-  // that will be used.
-  var wifi = {type: Ci.nsINetworkInterface.NETWORK_TYPE_WIFI, id: "0"};
-  var mobile = {type: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, id: "1234"};
+  // Create to fake nsINetworkInfos. As nsINetworkInfo can not be instantiated,
+  // these two vars will emulate it by filling the properties that will be used.
+  var wifi = {type: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI, id: "0"};
+  var mobile = {type: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, id: "1234"};
 
-  // Insert fake mobile network interface in NetworkStatsService
+  // Insert fake mobile network info in NetworkStatsService
   var mobileNetId = NetworkStatsService.getNetworkId(mobile.id, mobile.type);
 
   NetworkStatsService.updateCachedStats(function (success, msg) {
     do_check_eq(success, true);
 
     var cachedStats = NetworkStatsService.cachedStats;
     do_check_eq(Object.keys(cachedStats).length, 0);
 
@@ -133,17 +131,17 @@ add_test(function test_saveServiceStats(
     });
   });
 });
 
 add_test(function test_saveStatsWithDifferentDates() {
   var today = NetworkStatsService.cachedStatsDate;
   var tomorrow = new Date(today.getTime() + (24 * 60 * 60 * 1000));
 
-  var mobile = {type: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, id: "1234"};
+  var mobile = {type: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, id: "1234"};
 
   NetworkStatsService.updateCachedStats(function (success, message) {
     do_check_eq(success, true);
 
     do_check_eq(Object.keys(NetworkStatsService.cachedStats).length, 0);
     nssProxy.saveAppStats(1, false, mobile, today.getTime(), 10, 20, false,
                           function (success, message) {
       do_check_eq(success, true);
@@ -168,17 +166,17 @@ add_test(function test_saveStatsWithDiff
       });
     });
   });
 });
 
 add_test(function test_saveStatsWithMaxCachedTraffic() {
   var timestamp = NetworkStatsService.cachedStatsDate.getTime();
   var maxtraffic = NetworkStatsService.maxCachedTraffic;
-  var wifi = {type: Ci.nsINetworkInterface.NETWORK_TYPE_WIFI, id: "0"};
+  var wifi = {type: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI, id: "0"};
 
   NetworkStatsService.updateCachedStats(function (success, message) {
     do_check_eq(success, true);
 
     var cachedStats = NetworkStatsService.cachedStats;
     do_check_eq(Object.keys(cachedStats).length, 0);
     nssProxy.saveAppStats(1, false, wifi, timestamp, 10, 20, false,
                           function (success, message) {
@@ -194,21 +192,21 @@ add_test(function test_saveStatsWithMaxC
     });
   });
 });
 
 add_test(function test_saveAppStats() {
   var cachedStats = NetworkStatsService.cachedStats;
   var timestamp = NetworkStatsService.cachedStatsDate.getTime();
 
-  // Create to fake nsINetworkInterfaces. As nsINetworkInterface can not
+  // Create to fake nsINetworkInfo. As nsINetworkInfo can not
   // be instantiated, these two vars will emulate it by filling the properties
   // that will be used.
-  var wifi = {type: Ci.nsINetworkInterface.NETWORK_TYPE_WIFI, id: "0"};
-  var mobile = {type: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, id: "1234"};
+  var wifi = {type: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI, id: "0"};
+  var mobile = {type: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, id: "1234"};
 
   // Insert fake mobile network interface in NetworkStatsService
   var mobileNetId = NetworkStatsService.getNetworkId(mobile.id, mobile.type);
 
   do_check_eq(Object.keys(cachedStats).length, 0);
 
   nssProxy.saveAppStats(1, false, wifi, timestamp, 10, 20, false, { notify:
                         function (success, message) {
@@ -227,14 +225,14 @@ add_test(function test_saveAppStats() {
   }});
 });
 
 function run_test() {
   do_get_profile();
 
   Cu.import("resource://gre/modules/NetworkStatsService.jsm");
 
-  // Function convertNetworkInterface of NetworkStatsService causes errors when dealing
+  // Function convertNetworkInfo of NetworkStatsService causes errors when dealing
   // with RIL to get the iccid, so overwrite it.
-  mokConvertNetworkInterface();
+  mokConvertNetworkInfo();
 
   run_next_test();
 }
--- a/dom/presentation/provider/MulticastDNSDeviceProvider.h
+++ b/dom/presentation/provider/MulticastDNSDeviceProvider.h
@@ -6,17 +6,17 @@
 #ifndef mozilla_dom_presentation_provider_MulticastDNSDeviceProvider_h
 #define mozilla_dom_presentation_provider_MulticastDNSDeviceProvider_h
 
 #include "nsCOMPtr.h"
 #include "nsICancelable.h"
 #include "nsIDNSServiceDiscovery.h"
 #include "nsIPresentationDeviceProvider.h"
 #include "nsITCPPresentationServer.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsString.h"
 #include "nsWeakPtr.h"
 
 namespace mozilla {
 namespace dom {
 namespace presentation {
 
 class DNSServiceWrappedListener;
--- a/dom/promise/PromiseDebugging.h
+++ b/dom/promise/PromiseDebugging.h
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_PromiseDebugging_h
 #define mozilla_dom_PromiseDebugging_h
 
 #include "js/TypeDecls.h"
 #include "nsTArray.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 namespace workers {
 class WorkerPrivate;
--- a/dom/push/PushManager.h
+++ b/dom/push/PushManager.h
@@ -33,17 +33,17 @@
 
 #include "nsWrapperCache.h"
 
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
 
 #include "nsCOMPtr.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "jsapi.h"
 
 class nsIGlobalObject;
 class nsIPrincipal;
 
 namespace mozilla {
 namespace dom {
 
--- a/dom/push/PushServiceWebSocket.jsm
+++ b/dom/push/PushServiceWebSocket.jsm
@@ -1251,34 +1251,34 @@ let PushNetworkInfo = {
     try {
       if (!prefs.get("udp.wakeupEnabled")) {
         debug("UDP support disabled, we do not send any carrier info");
         throw new Error("UDP disabled");
       }
 
       let nm = Cc["@mozilla.org/network/manager;1"]
                  .getService(Ci.nsINetworkManager);
-      if (nm.active &&
-          nm.active.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
+      if (nm.activeNetworkInfo &&
+          nm.activeNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE) {
         let iccService = Cc["@mozilla.org/icc/iccservice;1"]
                            .getService(Ci.nsIIccService);
         // TODO: Bug 927721 - PushService for multi-sim
         // In Multi-sim, there is more than one client in iccService. Each
         // client represents a icc handle. To maintain backward compatibility
         // with single sim, we always use client 0 for now. Adding support
         // for multiple sim will be addressed in bug 927721, if needed.
         let clientId = 0;
         let icc = iccService.getIccByServiceId(clientId);
         let iccInfo = icc && icc.iccInfo;
         if (iccInfo) {
           debug("Running on mobile data");
 
           let ips = {};
           let prefixLengths = {};
-          nm.active.getAddresses(ips, prefixLengths);
+          nm.activeNetworkInfo.getAddresses(ips, prefixLengths);
 
           return {
             mcc: iccInfo.mcc,
             mnc: iccInfo.mnc,
             ip:  ips.value[0]
           };
         }
       }
--- a/dom/simplepush/PushService.jsm
+++ b/dom/simplepush/PushService.jsm
@@ -1769,32 +1769,33 @@ this.PushService = {
 
     try {
       if (!prefs.get("udp.wakeupEnabled")) {
         debug("UDP support disabled, we do not send any carrier info");
         throw new Error("UDP disabled");
       }
 
       let nm = Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
-      if (nm.active && nm.active.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
+      if (nm.activeNetworkInfo &&
+          nm.activeNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE) {
         let iccService = Cc["@mozilla.org/icc/iccservice;1"].getService(Ci.nsIIccService);
         // TODO: Bug 927721 - PushService for multi-sim
         // In Multi-sim, there is more than one client in iccService. Each
         // client represents a icc handle. To maintain backward compatibility
         // with single sim, we always use client 0 for now. Adding support
         // for multiple sim will be addressed in bug 927721, if needed.
         let clientId = 0;
         let icc = iccService.getIccByServiceId(clientId);
         let iccInfo = icc && icc.iccInfo;
         if (iccInfo) {
           debug("Running on mobile data");
 
           let ips = {};
           let prefixLengths = {};
-          nm.active.getAddresses(ips, prefixLengths);
+          nm.activeNetworkInfo.getAddresses(ips, prefixLengths);
 
           return {
             mcc: iccInfo.mcc,
             mnc: iccInfo.mnc,
             ip:  ips.value[0]
           }
         }
       }
--- a/dom/system/gonk/DataCallManager.js
+++ b/dom/system/gonk/DataCallManager.js
@@ -48,38 +48,40 @@ let RILQUIRKS_SUBSCRIPTION_CONTROL =
 let RILQUIRKS_HAVE_IPV6 =
   libcutils.property_get("ro.moz.ril.ipv6", "false") == "true";
 
 const DATACALLMANAGER_CID =
   Components.ID("{35b9efa2-e42c-45ce-8210-0a13e6f4aadc}");
 const DATACALLHANDLER_CID =
   Components.ID("{132b650f-c4d8-4731-96c5-83785cb31dee}");
 const RILNETWORKINTERFACE_CID =
-  Components.ID("{8c11bef9-9b4f-4d96-bed7-f5a1f48eabda}");
+  Components.ID("{9574ee84-5d0d-4814-b9e6-8b279e03dcf4}");
+const RILNETWORKINFO_CID =
+  Components.ID("{dd6cf2f0-f0e3-449f-a69e-7c34fdcb8d4b}");
 
 const TOPIC_XPCOM_SHUTDOWN      = "xpcom-shutdown";
 const TOPIC_MOZSETTINGS_CHANGED = "mozsettings-changed";
 const TOPIC_PREF_CHANGED        = "nsPref:changed";
 const TOPIC_DATA_CALL_ERROR     = "data-call-error";
 const PREF_RIL_DEBUG_ENABLED    = "ril.debugging.enabled";
 
-const NETWORK_TYPE_UNKNOWN     = Ci.nsINetworkInterface.NETWORK_TYPE_UNKNOWN;
-const NETWORK_TYPE_WIFI        = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
-const NETWORK_TYPE_MOBILE      = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
-const NETWORK_TYPE_MOBILE_MMS  = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS;
-const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL;
-const NETWORK_TYPE_MOBILE_IMS  = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS;
-const NETWORK_TYPE_MOBILE_DUN  = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN;
-const NETWORK_TYPE_MOBILE_FOTA = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_FOTA;
+const NETWORK_TYPE_UNKNOWN     = Ci.nsINetworkInfo.NETWORK_TYPE_UNKNOWN;
+const NETWORK_TYPE_WIFI        = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI;
+const NETWORK_TYPE_MOBILE      = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
+const NETWORK_TYPE_MOBILE_MMS  = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS;
+const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL;
+const NETWORK_TYPE_MOBILE_IMS  = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS;
+const NETWORK_TYPE_MOBILE_DUN  = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN;
+const NETWORK_TYPE_MOBILE_FOTA = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA;
 
-const NETWORK_STATE_UNKNOWN       = Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN;
-const NETWORK_STATE_CONNECTING    = Ci.nsINetworkInterface.NETWORK_STATE_CONNECTING;
-const NETWORK_STATE_CONNECTED     = Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED;
-const NETWORK_STATE_DISCONNECTING = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTING;
-const NETWORK_STATE_DISCONNECTED  = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED;
+const NETWORK_STATE_UNKNOWN       = Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN;
+const NETWORK_STATE_CONNECTING    = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTING;
+const NETWORK_STATE_CONNECTED     = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
+const NETWORK_STATE_DISCONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTING;
+const NETWORK_STATE_DISCONNECTED  = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
 
 const INT32_MAX = 2147483647;
 
 // set to true in ril_consts.js to see debug messages
 var DEBUG = RIL.DEBUG_RIL;
 
 function updateDebugFlag() {
   // Read debug setting from pref
@@ -410,17 +412,17 @@ DataCallHandler.prototype = {
       gNetworkManager.unregisterNetworkInterface(networkInterface);
       networkInterface.shutdown();
       networkInterface = null;
     });
     this.dataNetworkInterfaces.clear();
     this._dataCalls = [];
     this.clientId = null;
 
-    this.dataCallinterface.unregisterListener(this);
+    this.dataCallInterface.unregisterListener(this);
     this.dataCallInterface = null;
 
     let mobileConnection =
       gMobileConnectionService.getItemByServiceId(this.clientId);
     mobileConnection.unregisterListener(this);
   },
 
   /**
@@ -620,18 +622,18 @@ DataCallHandler.prototype = {
     if (!isRegistered || !haveDataConnection) {
       if (DEBUG) {
         this.debug("RIL is not ready for data connection: Phone's not " +
                    "registered or doesn't have data connection.");
       }
       return;
     }
     let wifi_active = false;
-    if (gNetworkManager.active &&
-        gNetworkManager.active.type == NETWORK_TYPE_WIFI) {
+    if (gNetworkManager.activeNetworkInfo &&
+        gNetworkManager.activeNetworkInfo.type == NETWORK_TYPE_WIFI) {
       wifi_active = true;
     }
 
     let defaultDataCallConnected = networkInterface.connected;
 
     // We have moved part of the decision making into DataCall, the rest will be
     // moved after Bug 904514 - [meta] NetworkManager enhancement.
     if (networkInterface.enabled &&
@@ -704,17 +706,17 @@ DataCallHandler.prototype = {
       if (DEBUG) this.debug(aNetworkType + " is not a mobile network type!");
       throw Cr.NS_ERROR_INVALID_ARG;
     }
 
     let networkInterface = this.dataNetworkInterfaces.get(aNetworkType);
     if (!networkInterface) {
       return NETWORK_STATE_UNKNOWN;
     }
-    return networkInterface.state;
+    return networkInterface.info.state;
   },
 
   setupDataCallByType: function(aNetworkType) {
     if (DEBUG) {
       this.debug("setupDataCallByType: " + aNetworkType);
     }
 
     if (!this._isMobileNetworkType(aNetworkType)) {
@@ -755,18 +757,18 @@ DataCallHandler.prototype = {
   },
 
   _deactivatingDataCalls: false,
 
   deactivateDataCalls: function(aCallback) {
     let dataDisconnecting = false;
     this.dataNetworkInterfaces.forEach(function(networkInterface) {
       if (networkInterface.enabled) {
-        if (networkInterface.state != NETWORK_STATE_UNKNOWN &&
-            networkInterface.state != NETWORK_STATE_DISCONNECTED) {
+        if (networkInterface.info.state != NETWORK_STATE_UNKNOWN &&
+            networkInterface.info.state != NETWORK_STATE_DISCONNECTED) {
           dataDisconnecting = true;
         }
         networkInterface.disconnect();
       }
     });
 
     this._deactivatingDataCalls = dataDisconnecting;
     if (!dataDisconnecting) {
@@ -831,33 +833,24 @@ DataCallHandler.prototype = {
     }
 
     return -1;
   },
 
   /**
    * Notify about data call setup error, called from DataCall.
    */
-  notifyDataCallError: function(aMessage) {
+  notifyDataCallError: function(aDataCall, aErrorMsg) {
     // Notify data call error only for data APN
     let networkInterface = this.dataNetworkInterfaces.get(NETWORK_TYPE_MOBILE);
     if (networkInterface && networkInterface.enabled) {
       let dataCall = networkInterface.dataCall;
-      // If there is a cid, compare cid; otherwise it is probably an error on
-      // data call setup.
-      if (aMessage.cid !== undefined) {
-        if (aMessage.linkInfo.cid == dataCall.linkInfo.cid) {
-          Services.obs.notifyObservers(networkInterface, TOPIC_DATA_CALL_ERROR,
-                                       null);
-        }
-      } else {
-        if (this._compareDataCallOptions(dataCall, aMessage)) {
-          Services.obs.notifyObservers(networkInterface, TOPIC_DATA_CALL_ERROR,
-                                       null);
-        }
+      if (this._compareDataCallOptions(dataCall, aDataCall)) {
+        Services.obs.notifyObservers(networkInterface.info,
+                                     TOPIC_DATA_CALL_ERROR, aErrorMsg);
       }
     }
   },
 
   /**
    * Notify about data call changed, called from DataCall.
    */
   notifyDataCallChanged: function(aUpdatedDataCall) {
@@ -1060,17 +1053,17 @@ DataCall.prototype = {
       this.state = NETWORK_STATE_DISCONNECTED;
 
       if (this.requestedNetworkIfaces.length === 0) {
         if (DEBUG) this.debug("This DataCall is not requested anymore.");
         return;
       }
 
       // Let DataCallHandler notify MobileConnectionService
-      this.dataCallHandler.notifyDataCallError(this);
+      this.dataCallHandler.notifyDataCallError(this, errorMsg);
 
       // For suggestedRetryTime, the value of INT32_MAX(0x7fffffff) means no retry.
       if (aDataCall.suggestedRetryTime === INT32_MAX ||
           this.isPermanentFail(aDataCall.failCause, errorMsg)) {
         if (DEBUG) this.debug("Data call error: no retry needed.");
         return;
       }
 
@@ -1237,17 +1230,17 @@ DataCall.prototype = {
       return true;
     }
 
     return false;
   },
 
   inRequestedTypes: function(aType) {
     for (let i = 0; i < this.requestedNetworkIfaces.length; i++) {
-      if (this.requestedNetworkIfaces[i].type == aType) {
+      if (this.requestedNetworkIfaces[i].info.type == aType) {
         return true;
       }
     }
     return false;
   },
 
   canHandleApn: function(aApnSetting) {
     let isIdentical = this.apnProfile.apn == aApnSetting.apn &&
@@ -1274,33 +1267,33 @@ DataCall.prototype = {
 
   reset: function() {
     this.resetLinkInfo();
 
     this.state = NETWORK_STATE_UNKNOWN;
   },
 
   connect: function(aNetworkInterface) {
-    if (DEBUG) this.debug("connect: " + aNetworkInterface.type);
+    if (DEBUG) this.debug("connect: " + aNetworkInterface.info.type);
 
     if (this.requestedNetworkIfaces.indexOf(aNetworkInterface) == -1) {
       this.requestedNetworkIfaces.push(aNetworkInterface);
     }
 
     if (this.state == NETWORK_STATE_CONNECTING ||
         this.state == NETWORK_STATE_DISCONNECTING) {
       return;
     }
     if (this.state == NETWORK_STATE_CONNECTED) {
       // This needs to run asynchronously, to behave the same way as the case of
       // non-shared apn, see bug 1059110.
       Services.tm.currentThread.dispatch(() => {
         // Do not notify if state changed while this event was being dispatched,
         // the state probably was notified already or need not to be notified.
-        if (aNetworkInterface.state == RIL.GECKO_NETWORK_STATE_CONNECTED) {
+        if (aNetworkInterface.info.state == RIL.GECKO_NETWORK_STATE_CONNECTED) {
           aNetworkInterface.notifyRILNetworkInterface();
         }
       }, Ci.nsIEventTarget.DISPATCH_NORMAL);
       return;
     }
 
     // If retry mechanism is running on background, stop it since we are going
     // to setup data call now.
@@ -1400,17 +1393,17 @@ DataCall.prototype = {
       // Event timer for connection retries
       this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     }
     this.timer.initWithCallback(this, apnRetryTimer * 1000,
                                 Ci.nsITimer.TYPE_ONE_SHOT);
   },
 
   disconnect: function(aNetworkInterface) {
-    if (DEBUG) this.debug("disconnect: " + aNetworkInterface.type);
+    if (DEBUG) this.debug("disconnect: " + aNetworkInterface.info.type);
 
     let index = this.requestedNetworkIfaces.indexOf(aNetworkInterface);
     if (index != -1) {
       this.requestedNetworkIfaces.splice(index, 1);
 
       if (this.state == NETWORK_STATE_DISCONNECTED ||
           this.state == NETWORK_STATE_UNKNOWN) {
         if (this.timer) {
@@ -1421,17 +1414,17 @@ DataCall.prototype = {
       }
 
       // Notify the DISCONNECTED event immediately after network interface is
       // removed from requestedNetworkIfaces, to make the DataCall, shared or
       // not, to have the same behavior.
       Services.tm.currentThread.dispatch(() => {
         // Do not notify if state changed while this event was being dispatched,
         // the state probably was notified already or need not to be notified.
-        if (aNetworkInterface.state == RIL.GECKO_NETWORK_STATE_DISCONNECTED) {
+        if (aNetworkInterface.info.state == RIL.GECKO_NETWORK_STATE_DISCONNECTED) {
           aNetworkInterface.notifyRILNetworkInterface();
 
           // Clear link info after notifying NetworkManager.
           if (this.requestedNetworkIfaces.length === 0) {
             this.resetLinkInfo();
           }
         }
       }, Ci.nsIEventTarget.DISPATCH_NORMAL);
@@ -1444,17 +1437,17 @@ DataCall.prototype = {
         this.state != NETWORK_STATE_CONNECTED) {
       return;
     }
 
     this.deactivate();
   },
 
   deactivate: function() {
-    let reason = Ci.nsINetworkInterface.DATACALL_DEACTIVATE_NO_REASON;
+    let reason = Ci.nsIDataCallInterface.DATACALL_DEACTIVATE_NO_REASON;
     if (DEBUG) {
       this.debug("Going to disconnect data connection cid " + this.linkInfo.cid);
     }
 
     let dcInterface = this.dataCallHandler.dataCallInterface;
     dcInterface.deactivateDataCall(this.linkInfo.cid, reason, {
       QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataCallCallback]),
       notifySuccess: () => {
@@ -1476,165 +1469,200 @@ DataCall.prototype = {
   shutdown: function() {
     if (this.timer) {
       this.timer.cancel();
       this.timer = null;
     }
   }
 };
 
-function RILNetworkInterface(aDataCallHandler, aType, aApnSetting, aDataCall) {
-  if (!aDataCall) {
-    throw new Error("No dataCall for RILNetworkInterface: " + type);
-  }
-
-  this.dataCallHandler = aDataCallHandler;
+function RILNetworkInfo(aClientId, aType, aNetworkInterface)
+{
+  this.serviceId = aClientId;
   this.type = aType;
-  this.apnSetting = aApnSetting;
-  this.dataCall = aDataCall;
-
-  this.enabled = false;
-}
 
-RILNetworkInterface.prototype = {
-  classID:   RILNETWORKINTERFACE_CID,
-  classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINTERFACE_CID,
-                                    classDescription: "RILNetworkInterface",
-                                    interfaces: [Ci.nsINetworkInterface,
-                                                 Ci.nsIRilNetworkInterface]}),
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface,
-                                         Ci.nsIRilNetworkInterface]),
+  this.networkInterface = aNetworkInterface;
+}
+RILNetworkInfo.prototype = {
+  classID:   RILNETWORKINFO_CID,
+  classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINFO_CID,
+                                    classDescription: "RILNetworkInfo",
+                                    interfaces: [Ci.nsINetworkInfo,
+                                                 Ci.nsIRilNetworkInfo]}),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo,
+                                         Ci.nsIRilNetworkInfo]),
+
+  networkInterface: null,
 
-  // Hold reference to DataCall object which is determined at initilization.
-  dataCall: null,
+  getDataCall: function() {
+    return this.networkInterface.dataCall;
+  },
 
-  // If this RILNetworkInterface type is enabled or not.
-  enabled: null,
+  getApnSetting: function() {
+    return this.networkInterface.apnSetting;
+  },
+
+  debug: function(aMsg) {
+    dump("-*- RILNetworkInfo[" + this.serviceId + ":" + this.type + "]: " +
+         aMsg + "\n");
+  },
 
   /**
-   * nsINetworkInterface Implementation
+   * nsINetworkInfo Implementation
    */
-
   get state() {
-    if (!this.dataCall.inRequestedTypes(this.type)) {
+    let dataCall = this.getDataCall();
+    if (!dataCall.inRequestedTypes(this.type)) {
       return NETWORK_STATE_DISCONNECTED;
     }
-    return this.dataCall.state;
+    return dataCall.state;
   },
 
   type: null,
 
   get name() {
-    return this.dataCall.linkInfo.ifname;
-  },
-
-  get httpProxyHost() {
-    return this.apnSetting.proxy || "";
-  },
-
-  get httpProxyPort() {
-    return this.apnSetting.port || "";
+    return this.getDataCall().linkInfo.ifname;
   },
 
   getAddresses: function(aIps, aPrefixLengths) {
-    let addresses = this.dataCall.linkInfo.addresses;
+    let addresses = this.getDataCall().linkInfo.addresses;
 
     let ips = [];
     let prefixLengths = [];
     for (let i = 0; i < addresses.length; i++) {
       let [ip, prefixLength] = addresses[i].split("/");
       ips.push(ip);
       prefixLengths.push(prefixLength);
     }
 
     aIps.value = ips.slice();
     aPrefixLengths.value = prefixLengths.slice();
 
     return ips.length;
   },
 
   getGateways: function(aCount) {
-    let linkInfo = this.dataCall.linkInfo;
+    let linkInfo = this.getDataCall().linkInfo;
 
     if (aCount) {
       aCount.value = linkInfo.gateways.length;
     }
+
     return linkInfo.gateways.slice();
   },
 
   getDnses: function(aCount) {
-    let linkInfo = this.dataCall.linkInfo;
+    let linkInfo = this.getDataCall().linkInfo;
 
     if (aCount) {
       aCount.value = linkInfo.dnses.length;
     }
+
     return linkInfo.dnses.slice();
   },
 
   /**
-   * nsIRilNetworkInterface Implementation
+   * nsIRilNetworkInfo Implementation
    */
 
-  get serviceId() {
-    return this.dataCallHandler.clientId;
-  },
+  serviceId: 0,
 
   get iccId() {
-    let icc = gIccService.getIccByServiceId(this.dataCallHandler.clientId);
+    let icc = gIccService.getIccByServiceId(this.serviceId);
     let iccInfo = icc && icc.iccInfo;
 
     return iccInfo && iccInfo.iccid;
   },
 
   get mmsc() {
     if (this.type != NETWORK_TYPE_MOBILE_MMS) {
       if (DEBUG) this.debug("Error! Only MMS network can get MMSC.");
       throw Cr.NS_ERROR_UNEXPECTED;
     }
 
-    return this.apnSetting.mmsc || "";
+    return this.getApnSetting().mmsc || "";
   },
 
   get mmsProxy() {
     if (this.type != NETWORK_TYPE_MOBILE_MMS) {
       if (DEBUG) this.debug("Error! Only MMS network can get MMS proxy.");
       throw Cr.NS_ERROR_UNEXPECTED;
     }
 
-    return this.apnSetting.mmsproxy || "";
+    return this.getApnSetting().mmsproxy || "";
   },
 
   get mmsPort() {
     if (this.type != NETWORK_TYPE_MOBILE_MMS) {
       if (DEBUG) this.debug("Error! Only MMS network can get MMS port.");
       throw Cr.NS_ERROR_UNEXPECTED;
     }
 
     // Note: Port 0 is reserved, so we treat it as invalid as well.
     // See http://www.iana.org/assignments/port-numbers
-    return this.apnSetting.mmsport || -1;
+    return this.getApnSetting().mmsport || -1;
+  },
+};
+
+function RILNetworkInterface(aDataCallHandler, aType, aApnSetting, aDataCall) {
+  if (!aDataCall) {
+    throw new Error("No dataCall for RILNetworkInterface: " + type);
+  }
+
+  this.dataCallHandler = aDataCallHandler;
+  this.enabled = false;
+  this.dataCall = aDataCall;
+  this.apnSetting = aApnSetting;
+
+  this.info = new RILNetworkInfo(aDataCallHandler.clientId, aType, this);
+}
+
+RILNetworkInterface.prototype = {
+  classID:   RILNETWORKINTERFACE_CID,
+  classInfo: XPCOMUtils.generateCI({classID: RILNETWORKINTERFACE_CID,
+                                    classDescription: "RILNetworkInterface",
+                                    interfaces: [Ci.nsINetworkInterface]}),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
+
+  // If this RILNetworkInterface type is enabled or not.
+  enabled: null,
+
+  apnSetting: null,
+
+  dataCall: null,
+
+  /**
+   * nsINetworkInterface Implementation
+   */
+
+  info: null,
+
+  get httpProxyHost() {
+    return this.apnSetting.proxy || "";
+  },
+
+  get httpProxyPort() {
+    return this.apnSetting.port || "";
   },
 
   // Helpers
 
   debug: function(aMsg) {
     dump("-*- RILNetworkInterface[" + this.dataCallHandler.clientId + ":" +
-         this.type + "]: " + aMsg + "\n");
+         this.info.type + "]: " + aMsg + "\n");
   },
 
-  apnSetting: null,
-
   get connected() {
-    return this.state == NETWORK_STATE_CONNECTED;
+    return this.info.state == NETWORK_STATE_CONNECTED;
   },
 
   notifyRILNetworkInterface: function() {
     if (DEBUG) {
-      this.debug("notifyRILNetworkInterface type: " + this.type + ", state: " +
-                 this.state);
+      this.debug("notifyRILNetworkInterface type: " + this.info.type +
+                 ", state: " + this.info.state);
     }
 
     gNetworkManager.updateNetworkInterface(this);
   },
 
   connect: function() {
     this.enabled = true;
 
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
@@ -20,17 +20,17 @@
 #include <hardware/gps.h>
 
 #include "mozilla/Constants.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "nsContentUtils.h"
 #include "nsGeoPosition.h"
 #include "nsIInterfaceRequestorUtils.h"
-#include "nsINetworkManager.h"
+#include "nsINetworkInterface.h"
 #include "nsIObserverService.h"
 #include "nsJSUtils.h"
 #include "nsPrintfCString.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "prtime.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ScriptSettings.h"
@@ -354,22 +354,22 @@ GonkGPSGeolocationProvider::GetGPSInterf
   return result;
 }
 
 #ifdef MOZ_B2G_RIL
 int32_t
 GonkGPSGeolocationProvider::GetDataConnectionState()
 {
   if (!mRadioInterface) {
-    return nsINetworkInterface::NETWORK_STATE_UNKNOWN;
+    return nsINetworkInfo::NETWORK_STATE_UNKNOWN;
   }
 
   int32_t state;
   mRadioInterface->GetDataCallStateByType(
-    nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL, &state);
+    nsINetworkInfo::NETWORK_TYPE_MOBILE_SUPL, &state);
   return state;
 }
 
 void
 GonkGPSGeolocationProvider::SetAGpsDataConn(nsAString& aApn)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mAGpsInterface);
@@ -378,34 +378,34 @@ GonkGPSGeolocationProvider::SetAGpsDataC
   if (mAGpsRilInterface &&
       mAGpsRilInterface->size >= sizeof(AGpsRilInterface) &&
       mAGpsRilInterface->update_network_availability) {
     hasUpdateNetworkAvailability = true;
   }
 
   int32_t connectionState = GetDataConnectionState();
   NS_ConvertUTF16toUTF8 apn(aApn);
-  if (connectionState == nsINetworkInterface::NETWORK_STATE_CONNECTED) {
+  if (connectionState == nsINetworkInfo::NETWORK_STATE_CONNECTED) {
     // The definition of availability is
     // 1. The device is connected to the home network
     // 2. The device is connected to a foreign network and data
     //    roaming is enabled
     // RIL turns on/off data connection automatically when the data
     // roaming setting changes.
     if (hasUpdateNetworkAvailability) {
       mAGpsRilInterface->update_network_availability(true, apn.get());
     }
 #ifdef AGPS_HAVE_DUAL_APN
     mAGpsInterface->data_conn_open(AGPS_TYPE_SUPL,
                                    apn.get(),
                                    AGPS_APN_BEARER_IPV4);
 #else
     mAGpsInterface->data_conn_open(apn.get());
 #endif
-  } else if (connectionState == nsINetworkInterface::NETWORK_STATE_DISCONNECTED) {
+  } else if (connectionState == nsINetworkInfo::NETWORK_STATE_DISCONNECTED) {
     if (hasUpdateNetworkAvailability) {
       mAGpsRilInterface->update_network_availability(false, apn.get());
     }
 #ifdef AGPS_HAVE_DUAL_APN
     mAGpsInterface->data_conn_closed(AGPS_TYPE_SUPL);
 #else
     mAGpsInterface->data_conn_closed();
 #endif
@@ -445,35 +445,35 @@ void
 GonkGPSGeolocationProvider::RequestDataConnection()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mRadioInterface) {
     return;
   }
 
-  if (GetDataConnectionState() == nsINetworkInterface::NETWORK_STATE_CONNECTED) {
+  if (GetDataConnectionState() == nsINetworkInfo::NETWORK_STATE_CONNECTED) {
     // Connection is already established, we don't need to setup again.
     // We just get supl APN and make AGPS data connection state updated.
     RequestSettingValue("ril.supl.apn");
   } else {
-    mRadioInterface->SetupDataCallByType(nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL);
+    mRadioInterface->SetupDataCallByType(nsINetworkInfo::NETWORK_TYPE_MOBILE_SUPL);
   }
 }
 
 void
 GonkGPSGeolocationProvider::ReleaseDataConnection()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mRadioInterface) {
     return;
   }
 
-  mRadioInterface->DeactivateDataCallByType(nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL);
+  mRadioInterface->DeactivateDataCallByType(nsINetworkInfo::NETWORK_TYPE_MOBILE_SUPL);
 }
 
 void
 GonkGPSGeolocationProvider::RequestSetID(uint32_t flags)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mRadioInterface ||
@@ -1005,25 +1005,25 @@ GonkGPSGeolocationProvider::SetHighAccur
   return NS_OK;
 }
 
 namespace {
 int
 ConvertToGpsNetworkType(int aNetworkInterfaceType)
 {
   switch (aNetworkInterfaceType) {
-    case nsINetworkInterface::NETWORK_TYPE_WIFI:
+    case nsINetworkInfo::NETWORK_TYPE_WIFI:
       return AGPS_RIL_NETWORK_TYPE_WIFI;
-    case nsINetworkInterface::NETWORK_TYPE_MOBILE:
+    case nsINetworkInfo::NETWORK_TYPE_MOBILE:
       return AGPS_RIL_NETWORK_TYPE_MOBILE;
-    case nsINetworkInterface::NETWORK_TYPE_MOBILE_MMS:
+    case nsINetworkInfo::NETWORK_TYPE_MOBILE_MMS:
       return AGPS_RIL_NETWORK_TYPE_MOBILE_MMS;
-    case nsINetworkInterface::NETWORK_TYPE_MOBILE_SUPL:
+    case nsINetworkInfo::NETWORK_TYPE_MOBILE_SUPL:
       return AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL;
-    case nsINetworkInterface::NETWORK_TYPE_MOBILE_DUN:
+    case nsINetworkInfo::NETWORK_TYPE_MOBILE_DUN:
       return AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN;
     default:
       NS_WARNING(nsPrintfCString("Unknown network type mapping %d",
                                  aNetworkInterfaceType).get());
       return -1;
   }
 }
 } // namespace
@@ -1032,31 +1032,31 @@ NS_IMETHODIMP
 GonkGPSGeolocationProvider::Observe(nsISupports* aSubject,
                                     const char* aTopic,
                                     const char16_t* aData)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
 #ifdef MOZ_B2G_RIL
   if (!strcmp(aTopic, kNetworkConnStateChangedTopic)) {
-    nsCOMPtr<nsINetworkInterface> iface = do_QueryInterface(aSubject);
-    if (!iface) {
+    nsCOMPtr<nsINetworkInfo> info = do_QueryInterface(aSubject);
+    if (!info) {
       return NS_OK;
     }
-    nsCOMPtr<nsIRilNetworkInterface> rilface = do_QueryInterface(aSubject);
+    nsCOMPtr<nsIRilNetworkInfo> rilInfo = do_QueryInterface(aSubject);
     if (mAGpsRilInterface && mAGpsRilInterface->update_network_state) {
       int32_t state;
       int32_t type;
-      iface->GetState(&state);
-      iface->GetType(&type);
-      bool connected = (state == nsINetworkInterface::NETWORK_STATE_CONNECTED);
+      info->GetState(&state);
+      info->GetType(&type);
+      bool connected = (state == nsINetworkInfo::NETWORK_STATE_CONNECTED);
       bool roaming = false;
       int gpsNetworkType = ConvertToGpsNetworkType(type);
       if (gpsNetworkType >= 0) {
-        if (rilface) {
+        if (rilInfo) {
           do {
             nsCOMPtr<nsIMobileConnectionService> service =
               do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID);
             if (!service) {
               break;
             }
 
             nsCOMPtr<nsIMobileConnection> connection;
@@ -1075,17 +1075,17 @@ GonkGPSGeolocationProvider::Observe(nsIS
         mAGpsRilInterface->update_network_state(
           connected,
           gpsNetworkType,
           roaming,
           /* extra_info = */ nullptr);
       }
     }
     // No data connection
-    if (!rilface) {
+    if (!rilInfo) {
       return NS_OK;
     }
 
     RequestSettingValue("ril.supl.apn");
   }
 #endif
 
   if (!strcmp(aTopic, kMozSettingsChangedTopic)) {
--- a/dom/system/gonk/NetworkInterfaceListService.js
+++ b/dom/system/gonk/NetworkInterfaceListService.js
@@ -45,29 +45,27 @@ NetworkInterfaceListService.prototype = 
           excludeFota: (aConditions &
                         Ci.nsINetworkInterfaceListService.
                         LIST_NOT_INCLUDE_FOTA_INTERFACES) != 0
         }
       )[0]);
   }
 };
 
-function FakeNetworkInterface(aAttributes) {
+function FakeNetworkInfo(aAttributes) {
   this.state = aAttributes.state;
   this.type = aAttributes.type;
   this.name = aAttributes.name;
   this.ips = aAttributes.ips;
   this.prefixLengths = aAttributes.prefixLengths;
   this.gateways = aAttributes.gateways;
   this.dnses = aAttributes.dnses;
-  this.httpProxyHost = aAttributes.httpProxyHost;
-  this.httpProxyPort = aAttributes.httpProxyPort;
 }
-FakeNetworkInterface.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
+FakeNetworkInfo.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo]),
 
   getAddresses: function (ips, prefixLengths) {
     ips.value = this.ips.slice();
     prefixLengths.value = this.prefixLengths.slice();
 
     return this.ips.length;
   },
 
@@ -84,28 +82,28 @@ FakeNetworkInterface.prototype = {
     }
     return this.dnses.slice();
   }
 };
 
 function NetworkInterfaceList (aInterfaceLiterals) {
   this._interfaces = [];
   for (let entry of aInterfaceLiterals) {
-    this._interfaces.push(new FakeNetworkInterface(entry));
+    this._interfaces.push(new FakeNetworkInfo(entry));
   }
 }
 
 NetworkInterfaceList.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterfaceList]),
 
   getNumberOfInterface: function() {
     return this._interfaces.length;
   },
 
-  getInterface: function(index) {
+  getInterfaceInfo: function(index) {
     if (!this._interfaces) {
       return null;
     }
     return this._interfaces[index];
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkInterfaceListService]);
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -11,17 +11,17 @@ Cu.import("resource://gre/modules/Servic
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/systemlibs.js");
 Cu.import("resource://gre/modules/Promise.jsm");
 
 const NETWORKMANAGER_CONTRACTID = "@mozilla.org/network/manager;1";
 const NETWORKMANAGER_CID =
   Components.ID("{33901e46-33b8-11e1-9869-f46d04d25bcc}");
 
-const DEFAULT_PREFERRED_NETWORK_TYPE = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
+const DEFAULT_PREFERRED_NETWORK_TYPE = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI;
 
 XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
   return Cc["@mozilla.org/parentprocessmessagemanager;1"]
          .getService(Ci.nsIMessageBroadcaster);
 });
 
 XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
                                    "@mozilla.org/network/dns-service;1",
@@ -80,52 +80,52 @@ updateDebug();
 
 function defineLazyRegExp(obj, name, pattern) {
   obj.__defineGetter__(name, function() {
     delete obj[name];
     return obj[name] = new RegExp(pattern);
   });
 }
 
-function NetworkInterface(aNetwork) {
+function ExtraNetworkInfo(aNetwork) {
   let ips = {};
   let prefixLengths = {};
-  aNetwork.getAddresses(ips, prefixLengths);
+  aNetwork.info.getAddresses(ips, prefixLengths);
 
-  this.state = aNetwork.state;
-  this.type = aNetwork.type;
-  this.name = aNetwork.name;
+  this.state = aNetwork.info.state;
+  this.type = aNetwork.info.type;
+  this.name = aNetwork.info.name;
   this.ips = ips.value;
   this.prefixLengths = prefixLengths.value;
-  this.gateways = aNetwork.getGateways();
-  this.dnses = aNetwork.getDnses();
+  this.gateways = aNetwork.info.getGateways();
+  this.dnses = aNetwork.info.getDnses();
   this.httpProxyHost = aNetwork.httpProxyHost;
   this.httpProxyPort = aNetwork.httpProxyPort;
 }
-NetworkInterface.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
-
+ExtraNetworkInfo.prototype = {
   getAddresses: function(aIps, aPrefixLengths) {
     aIps.value = this.ips.slice();
     aPrefixLengths.value = this.prefixLengths.slice();
 
     return this.ips.length;
   },
 
   getGateways: function(aCount) {
     if (aCount) {
       aCount.value = this.gateways.length;
     }
+
     return this.gateways.slice();
   },
 
   getDnses: function(aCount) {
     if (aCount) {
       aCount.value = this.dnses.length;
     }
+
     return this.dnses.slice();
   }
 };
 
 function NetworkInterfaceLinks()
 {
   this.resetLinks();
 }
@@ -226,74 +226,73 @@ NetworkManager.prototype = {
       case "NetworkInterfaceList:ListInterface": {
         let excludeMms = aMsg.json.excludeMms;
         let excludeSupl = aMsg.json.excludeSupl;
         let excludeIms = aMsg.json.excludeIms;
         let excludeDun = aMsg.json.excludeDun;
         let excludeFota = aMsg.json.excludeFota;
         let interfaces = [];
 
-        for each (let i in this.networkInterfaces) {
-          if ((i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS && excludeMms) ||
-              (i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL && excludeSupl) ||
-              (i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS && excludeIms) ||
-              (i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN && excludeDun) ||
-              (i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_FOTA && excludeFota)) {
+        for each (let network in this.networkInterfaces) {
+          let i = network.info;
+          if ((i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS && excludeMms) ||
+              (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL && excludeSupl) ||
+              (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS && excludeIms) ||
+              (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN && excludeDun) ||
+              (i.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA && excludeFota)) {
             continue;
           }
 
           let ips = {};
           let prefixLengths = {};
           i.getAddresses(ips, prefixLengths);
 
           interfaces.push({
             state: i.state,
             type: i.type,
             name: i.name,
             ips: ips.value,
             prefixLengths: prefixLengths.value,
             gateways: i.getGateways(),
-            dnses: i.getDnses(),
-            httpProxyHost: i.httpProxyHost,
-            httpProxyPort: i.httpProxyPort
+            dnses: i.getDnses()
           });
         }
         return interfaces;
       }
     }
   },
 
-  getNetworkId: function(network) {
+  getNetworkId: function(aNetworkInfo) {
     let id = "device";
     try {
-      if (network instanceof Ci.nsIRilNetworkInterface) {
-        let rilNetwork = network.QueryInterface(Ci.nsIRilNetworkInterface);
-        id = "ril" + rilNetwork.serviceId;
+      if (aNetworkInfo instanceof Ci.nsIRilNetworkInfo) {
+        let rilInfo = aNetworkInfo.QueryInterface(Ci.nsIRilNetworkInfo);
+        id = "ril" + rilInfo.serviceId;
       }
     } catch (e) {}
 
-    return id + "-" + network.type;
+    return id + "-" + aNetworkInfo.type;
   },
 
   // nsINetworkManager
 
   registerNetworkInterface: function(network) {
     if (!(network instanceof Ci.nsINetworkInterface)) {
       throw Components.Exception("Argument must be nsINetworkInterface.",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
-    let networkId = this.getNetworkId(network);
+    let networkId = this.getNetworkId(network.info);
     if (networkId in this.networkInterfaces) {
       throw Components.Exception("Network with that type already registered!",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
     this.networkInterfaces[networkId] = network;
     this.networkInterfaceLinks[networkId] = new NetworkInterfaceLinks();
 
-    Services.obs.notifyObservers(network, TOPIC_INTERFACE_REGISTERED, null);
+    Services.obs.notifyObservers(network.info, TOPIC_INTERFACE_REGISTERED, null);
     debug("Network '" + networkId + "' registered.");
   },
 
   _addSubnetRoutes: function(network) {
     let ips = {};
     let prefixLengths = {};
     let length = network.getAddresses(ips, prefixLengths);
     let promises = [];
@@ -311,201 +310,211 @@ NetworkManager.prototype = {
     return Promise.all(promises);
   },
 
   updateNetworkInterface: function(network) {
     if (!(network instanceof Ci.nsINetworkInterface)) {
       throw Components.Exception("Argument must be nsINetworkInterface.",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
-    let networkId = this.getNetworkId(network);
+    let networkId = this.getNetworkId(network.info);
     if (!(networkId in this.networkInterfaces)) {
       throw Components.Exception("No network with that type registered.",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
-    debug("Network " + network.type + "/" + network.name +
-          " changed state to " + network.state);
+    debug("Network " + network.info.type + "/" + network.info.name +
+          " changed state to " + network.info.state);
 
     // Keep a copy of network in case it is modified while we are updating.
-    let networkInterface = new NetworkInterface(network);
+    let extNetworkInfo = new ExtraNetworkInfo(network);
 
     // Note that since Lollipop we need to allocate and initialize
     // something through netd, so we add createNetwork/destroyNetwork
     // to deal with that explicitly.
 
-    switch (networkInterface.state) {
-      case Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED:
+    switch (extNetworkInfo.state) {
+      case Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED:
 
-        this._createNetwork(networkInterface.name)
+        this._createNetwork(extNetworkInfo.name)
           // Remove pre-created default route and let setAndConfigureActive()
           // to set default route only on preferred network
-          .then(() => this._removeDefaultRoute(networkInterface))
+          .then(() => this._removeDefaultRoute(extNetworkInfo))
           // Set DNS server as early as possible to prevent from
           // premature domain name lookup.
-          .then(() => this._setDNS(networkInterface))
+          .then(() => this._setDNS(extNetworkInfo))
           .then(() => {
             // Add host route for data calls
-            if (!this.isNetworkTypeMobile(networkInterface.type)) {
+            if (!this.isNetworkTypeMobile(extNetworkInfo.type)) {
               return;
             }
 
             let currentInterfaceLinks = this.networkInterfaceLinks[networkId];
-            let newLinkRoutes = networkInterface.getDnses().concat(
-              networkInterface.httpProxyHost);
+            let newLinkRoutes = extNetworkInfo.getDnses().concat(
+              extNetworkInfo.httpProxyHost);
             // If gateways have changed, remove all old routes first.
-            return this._handleGateways(networkId, networkInterface.getGateways())
+            return this._handleGateways(networkId, extNetworkInfo.getGateways())
               .then(() => this._updateRoutes(currentInterfaceLinks.linkRoutes,
                                              newLinkRoutes,
-                                             networkInterface.getGateways(),
-                                             networkInterface.name))
+                                             extNetworkInfo.getGateways(),
+                                             extNetworkInfo.name))
               .then(() => currentInterfaceLinks.setLinks(newLinkRoutes,
-                                                         networkInterface.getGateways(),
-                                                         networkInterface.name));
+                                                         extNetworkInfo.getGateways(),
+                                                         extNetworkInfo.name));
           })
           .then(() => {
-            if (networkInterface.type !=
-                Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
+            if (extNetworkInfo.type !=
+                Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) {
               return;
             }
             // Dun type is a special case where we add the default route to a
             // secondary table.
-            return this.setSecondaryDefaultRoute(networkInterface);
+            return this.setSecondaryDefaultRoute(extNetworkInfo);
           })
-          .then(() => this._addSubnetRoutes(networkInterface))
+          .then(() => this._addSubnetRoutes(extNetworkInfo))
           .then(() => this.setAndConfigureActive())
           .then(() => {
             // Update data connection when Wifi connected/disconnected
-            if (networkInterface.type ==
-                Ci.nsINetworkInterface.NETWORK_TYPE_WIFI && this.mRil) {
+            if (extNetworkInfo.type ==
+                Ci.nsINetworkInfo.NETWORK_TYPE_WIFI && this.mRil) {
               for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
                 this.mRil.getRadioInterface(i).updateRILNetworkInterface();
               }
             }
 
             // Probing the public network accessibility after routing table is ready
             CaptivePortalDetectionHelper
-              .notify(CaptivePortalDetectionHelper.EVENT_CONNECT, this.active);
+              .notify(CaptivePortalDetectionHelper.EVENT_CONNECT,
+                      this.activeNetworkInfo);
           })
           .then(() => {
             // Notify outer modules like MmsService to start the transaction after
             // the configuration of the network interface is done.
-            Services.obs.notifyObservers(network, TOPIC_CONNECTION_STATE_CHANGED,
-                                         this.convertConnectionType(network));
+            Services.obs.notifyObservers(network.info,
+                                         TOPIC_CONNECTION_STATE_CHANGED,
+                                         this.convertConnectionType(network.info));
           })
           .catch(aError => {
             debug("updateNetworkInterface error: " + aError);
           });
         break;
-      case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED:
+      case Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED:
         Promise.resolve()
           .then(() => {
-            if (!this.isNetworkTypeMobile(networkInterface.type)) {
+            if (!this.isNetworkTypeMobile(extNetworkInfo.type)) {
               return;
             }
             // Remove host route for data calls
             return this._cleanupAllHostRoutes(networkId);
           })
           .then(() => {
-            if (networkInterface.type !=
-                Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
+            if (extNetworkInfo.type !=
+                Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) {
               return;
             }
             // Remove secondary default route for dun.
-            return this.removeSecondaryDefaultRoute(networkInterface);
+            return this.removeSecondaryDefaultRoute(extNetworkInfo);
           })
           .then(() => {
-            if (networkInterface.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+            if (extNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) {
               // Remove routing table in /proc/net/route
-              return this._resetRoutingTable(networkInterface.name);
+              return this._resetRoutingTable(extNetworkInfo.name);
             }
-            if (networkInterface.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
-              return this._removeDefaultRoute(networkInterface)
+            if (extNetworkInfo.type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE) {
+              return this._removeDefaultRoute(extNetworkInfo)
             }
           })
           .then(() => {
             // Clear http proxy on active network.
-            if (this.active && networkInterface.type == this.active.type) {
+            if (this.activeNetworkInfo &&
+                extNetworkInfo.type == this.activeNetworkInfo.type) {
               this.clearNetworkProxy();
             }
 
             // Abort ongoing captive portal detection on the wifi interface
             CaptivePortalDetectionHelper
-              .notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, networkInterface);
+              .notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, extNetworkInfo);
           })
           .then(() => this.setAndConfigureActive())
           .then(() => {
             // Update data connection when Wifi connected/disconnected
-            if (networkInterface.type ==
-                Ci.nsINetworkInterface.NETWORK_TYPE_WIFI && this.mRil) {
+            if (extNetworkInfo.type ==
+                Ci.nsINetworkInfo.NETWORK_TYPE_WIFI && this.mRil) {
               for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
                 this.mRil.getRadioInterface(i).updateRILNetworkInterface();
               }
             }
           })
-          .then(() => this._destroyNetwork(networkInterface.name))
+          .then(() => this._destroyNetwork(extNetworkInfo.name))
           .then(() => {
             // Notify outer modules like MmsService to start the transaction after
             // the configuration of the network interface is done.
-            Services.obs.notifyObservers(network, TOPIC_CONNECTION_STATE_CHANGED,
-                                         this.convertConnectionType(network));
+            Services.obs.notifyObservers(network.info,
+                                         TOPIC_CONNECTION_STATE_CHANGED,
+                                         this.convertConnectionType(network.info));
           })
           .catch(aError => {
             debug("updateNetworkInterface error: " + aError);
           });
         break;
     }
   },
 
   unregisterNetworkInterface: function(network) {
     if (!(network instanceof Ci.nsINetworkInterface)) {
       throw Components.Exception("Argument must be nsINetworkInterface.",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
-    let networkId = this.getNetworkId(network);
+    let networkId = this.getNetworkId(network.info);
     if (!(networkId in this.networkInterfaces)) {
       throw Components.Exception("No network with that type registered.",
                                  Cr.NS_ERROR_INVALID_ARG);
     }
 
     // This is for in case a network gets unregistered without being
     // DISCONNECTED.
-    if (this.isNetworkTypeMobile(network.type)) {
+    if (this.isNetworkTypeMobile(network.info.type)) {
       this._cleanupAllHostRoutes(networkId);
     }
 
     delete this.networkInterfaces[networkId];
 
-    Services.obs.notifyObservers(network, TOPIC_INTERFACE_UNREGISTERED, null);
+    Services.obs.notifyObservers(network.info, TOPIC_INTERFACE_UNREGISTERED, null);
     debug("Network '" + networkId + "' unregistered.");
   },
 
   _manageOfflineStatus: true,
 
   networkInterfaces: null,
 
   networkInterfaceLinks: null,
 
   _preferredNetworkType: DEFAULT_PREFERRED_NETWORK_TYPE,
   get preferredNetworkType() {
     return this._preferredNetworkType;
   },
   set preferredNetworkType(val) {
-    if ([Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
-         Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE].indexOf(val) == -1) {
+    if ([Ci.nsINetworkInfo.NETWORK_TYPE_WIFI,
+         Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE].indexOf(val) == -1) {
       throw "Invalid network type";
     }
     this._preferredNetworkType = val;
   },
 
-  active: null,
+  _activeNetwork: null,
+
+  get activeNetworkInfo() {
+    return this._activeNetwork && this._activeNetwork.info;
+  },
+
   _overriddenActive: null,
 
   overrideActive: function(network) {
-    if ([Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
-         Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE].indexOf(val) == -1) {
+    let type = network.info.type;
+    if ([Ci.nsINetworkInfo.NETWORK_TYPE_WIFI,
+         Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE].indexOf(type) == -1) {
       throw "Invalid network type";
     }
 
     this._overriddenActive = network;
     this.setAndConfigureActive();
   },
 
   _updateRoutes: function(oldLinks, newLinks, gateways, interfaceName) {
@@ -543,90 +552,90 @@ NetworkManager.prototype = {
                                         networkName, aIpAddress,
                                         getMaxPrefixLength(aIpAddress), gateway));
       }
     });
 
     return Promise.all(promises);
   },
 
-  isValidatedNetwork: function(network) {
+  isValidatedNetwork: function(aNetworkInfo) {
     let isValid = false;
     try {
-      isValid = (this.getNetworkId(network) in this.networkInterfaces);
+      isValid = (this.getNetworkId(aNetworkInfo) in this.networkInterfaces);
     } catch (e) {
       debug("Invalid network interface: " + e);
     }
 
     return isValid;
   },
 
-  addHostRoute: function(network, host) {
-    if (!this.isValidatedNetwork(network)) {
-      return Promise.reject("Invalid network interface.");
+  addHostRoute: function(aNetworkInfo, aHost) {
+    if (!this.isValidatedNetwork(aNetworkInfo)) {
+      return Promise.reject("Invalid network info.");
     }
 
-    return this.resolveHostname(network, host)
+    return this.resolveHostname(aNetworkInfo, aHost)
       .then((ipAddresses) => {
         let promises = [];
-        let networkId = this.getNetworkId(network);
+        let networkId = this.getNetworkId(aNetworkInfo);
 
         ipAddresses.forEach((aIpAddress) => {
           let promise =
-            this._setHostRoutes(true, [aIpAddress], network.name, network.getGateways())
+            this._setHostRoutes(true, [aIpAddress], aNetworkInfo.name, aNetworkInfo.getGateways())
               .then(() => this.networkInterfaceLinks[networkId].extraRoutes.push(aIpAddress));
 
           promises.push(promise);
         });
 
         return Promise.all(promises);
       });
   },
 
-  removeHostRoute: function(network, host) {
-    if (!this.isValidatedNetwork(network)) {
-      return Promise.reject("Invalid network interface.");
+  removeHostRoute: function(aNetworkInfo, aHost) {
+    if (!this.isValidatedNetwork(aNetworkInfo)) {
+      return Promise.reject("Invalid network info.");
     }
 
-    return this.resolveHostname(network, host)
+    return this.resolveHostname(aNetworkInfo, aHost)
       .then((ipAddresses) => {
         let promises = [];
-        let networkId = this.getNetworkId(network);
+        let networkId = this.getNetworkId(aNetworkInfo);
 
         ipAddresses.forEach((aIpAddress) => {
           let found = this.networkInterfaceLinks[networkId].extraRoutes.indexOf(aIpAddress);
           if (found < 0) {
             return; // continue
           }
 
           let promise =
-            this._setHostRoutes(false, [aIpAddress], network.name, network.getGateways())
+            this._setHostRoutes(false, [aIpAddress], aNetworkInfo.name, aNetworkInfo.getGateways())
               .then(() => {
                 this.networkInterfaceLinks[networkId].extraRoutes.splice(found, 1);
               }, () => {
                 // We should remove it even if the operation failed.
                 this.networkInterfaceLinks[networkId].extraRoutes.splice(found, 1);
               });
           promises.push(promise);
         });
 
         return Promise.all(promises);
       });
   },
 
   isNetworkTypeSecondaryMobile: function(type) {
-    return (type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS ||
-            type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL ||
-            type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS ||
-            type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN ||
-            type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_FOTA);
+    return (type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS ||
+            type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL ||
+            type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS ||
+            type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN ||
+            type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA);
   },
 
   isNetworkTypeMobile: function(type) {
-    return (type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE ||
+    return (type == Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE ||
             this.isNetworkTypeSecondaryMobile(type));
   },
 
   _handleGateways: function(networkId, gateways) {
     let currentNetworkLinks = this.networkInterfaceLinks[networkId];
     if (currentNetworkLinks.gateways.length == 0 ||
         currentNetworkLinks.compareGateways(gateways)) {
       return Promise.resolve();
@@ -760,161 +769,163 @@ NetworkManager.prototype = {
     return Promise.all(promises);
   },
 
   /**
    * Determine the active interface and configure it.
    */
   setAndConfigureActive: function() {
     debug("Evaluating whether active network needs to be changed.");
-    let oldActive = this.active;
+    let oldActive = this._activeNetwork;
 
     if (this._overriddenActive) {
       debug("We have an override for the active network: " +
-            this._overriddenActive.name);
+            this._overriddenActive.info.name);
       // The override was just set, so reconfigure the network.
-      if (this.active != this._overriddenActive) {
-        this.active = this._overriddenActive;
-        this._setDefaultRouteAndProxy(this.active, oldActive);
-        Services.obs.notifyObservers(this.active, TOPIC_ACTIVE_CHANGED, null);
+      if (this._activeNetwork != this._overriddenActive) {
+        this._activeNetwork = this._overriddenActive;
+        this._setDefaultRouteAndProxy(this._activeNetwork, oldActive);
+        Services.obs.notifyObservers(this.activeNetworkInfo,
+                                     TOPIC_ACTIVE_CHANGED, null);
       }
       return;
     }
 
     // The active network is already our preferred type.
-    if (this.active &&
-        this.active.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED &&
-        this.active.type == this._preferredNetworkType) {
+    if (this.activeNetworkInfo &&
+        this.activeNetworkInfo.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED &&
+        this.activeNetworkInfo.type == this._preferredNetworkType) {
       debug("Active network is already our preferred type.");
-      return this._setDefaultRouteAndProxy(this.active, oldActive);
+      return this._setDefaultRouteAndProxy(this._activeNetwork, oldActive);
     }
 
     // Find a suitable network interface to activate.
-    this.active = null;
+    this._activeNetwork = null;
     let anyConnected = false;
 
     for each (let network in this.networkInterfaces) {
-      if (network.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
+      if (network.info.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
         continue;
       }
       anyConnected = true;
 
       // Set active only for default connections.
-      if (network.type != Ci.nsINetworkInterface.NETWORK_TYPE_WIFI &&
-          network.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
+      if (network.info.type != Ci.nsINetworkInfo.NETWORK_TYPE_WIFI &&
+          network.info.type != Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE) {
         continue;
       }
 
-      this.active = network;
-      if (network.type == this.preferredNetworkType) {
-        debug("Found our preferred type of network: " + network.name);
+      this._activeNetwork = network;
+      if (network.info.type == this.preferredNetworkType) {
+        debug("Found our preferred type of network: " + network.info.name);
         break;
       }
     }
 
     return Promise.resolve()
       .then(() => {
-        if (!this.active) {
+        if (!this._activeNetwork) {
           return Promise.resolve();
         }
 
-        return this._setDefaultRouteAndProxy(this.active, oldActive);
+        return this._setDefaultRouteAndProxy(this._activeNetwork, oldActive);
       })
       .then(() => {
-        if (this.active != oldActive) {
-          Services.obs.notifyObservers(this.active, TOPIC_ACTIVE_CHANGED, null);
+        if (this._activeNetwork != oldActive) {
+          Services.obs.notifyObservers(this.activeNetworkInfo,
+                                       TOPIC_ACTIVE_CHANGED, null);
         }
 
         if (this._manageOfflineStatus) {
           Services.io.offline = !anyConnected;
         }
       });
   },
 
-  resolveHostname: function(network, hostname) {
+  resolveHostname: function(aNetworkInfo, aHostname) {
     // Sanity check for null, undefined and empty string... etc.
-    if (!hostname) {
-      return Promise.reject(new Error("hostname is empty: " + hostname));
+    if (!aHostname) {
+      return Promise.reject(new Error("hostname is empty: " + aHostname));
     }
 
-    if (hostname.match(this.REGEXP_IPV4) ||
-        hostname.match(this.REGEXP_IPV6)) {
-      return Promise.resolve([hostname]);
+    if (aHostname.match(this.REGEXP_IPV4) ||
+        aHostname.match(this.REGEXP_IPV6)) {
+      return Promise.resolve([aHostname]);
     }
 
     // Wrap gDNSService.asyncResolveExtended to a promise, which
     // resolves with an array of ip addresses or rejects with
     // the reason otherwise.
     let hostResolveWrapper = aNetId => {
       return new Promise((aResolve, aReject) => {
         // Callback for gDNSService.asyncResolveExtended.
         let onLookupComplete = (aRequest, aRecord, aStatus) => {
           if (!Components.isSuccessCode(aStatus)) {
-            aReject(new Error("Failed to resolve '" + hostname +
+            aReject(new Error("Failed to resolve '" + aHostname +
                               "', with status: " + aStatus));
             return;
           }
 
           let retval = [];
           while (aRecord.hasMore()) {
             retval.push(aRecord.getNextAddrAsString());
           }
 
           if (!retval.length) {
             aReject(new Error("No valid address after DNS lookup!"));
             return;
           }
 
-          debug("hostname is resolved: " + hostname);
+          debug("hostname is resolved: " + aHostname);
           debug("Addresses: " + JSON.stringify(retval));
 
           aResolve(retval);
         };
 
-        debug('Calling gDNSService.asyncResolveExtended: ' + aNetId + ', ' + hostname);
-        gDNSService.asyncResolveExtended(hostname,
+        debug('Calling gDNSService.asyncResolveExtended: ' + aNetId + ', ' + aHostname);
+        gDNSService.asyncResolveExtended(aHostname,
                                          0,
                                          aNetId,
                                          onLookupComplete,
                                          Services.tm.mainThread);
       });
     };
 
     // TODO: |getNetId| will be implemented as a sync call in nsINetworkManager
     //       once Bug 1141903 is landed.
-    return gNetworkService.getNetId(network.name)
+    return gNetworkService.getNetId(aNetworkInfo.name)
       .then(aNetId => hostResolveWrapper(aNetId));
   },
 
-  convertConnectionType: function(network) {
+  convertConnectionType: function(aNetworkInfo) {
     // If there is internal interface change (e.g., MOBILE_MMS, MOBILE_SUPL),
     // the function will return null so that it won't trigger type change event
     // in NetworkInformation API.
-    if (network.type != Ci.nsINetworkInterface.NETWORK_TYPE_WIFI &&
-        network.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
+    if (aNetworkInfo.type != Ci.nsINetworkInfo.NETWORK_TYPE_WIFI &&
+        aNetworkInfo.type != Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE) {
       return null;
     }
 
-    if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED) {
+    if (aNetworkInfo.state == Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED) {
       return CONNECTION_TYPE_NONE;
     }
 
-    switch (network.type) {
-      case Ci.nsINetworkInterface.NETWORK_TYPE_WIFI:
+    switch (aNetworkInfo.type) {
+      case Ci.nsINetworkInfo.NETWORK_TYPE_WIFI:
         return CONNECTION_TYPE_WIFI;
-      case Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE:
+      case Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE:
         return CONNECTION_TYPE_CELLULAR;
     }
   },
 
-  _setDNS: function(aNetwork) {
+  _setDNS: function(aNetworkInfo) {
     return new Promise((aResolve, aReject) => {
-      let dnses = aNetwork.getDnses();
-      let gateways = aNetwork.getGateways();
-      gNetworkService.setDNS(aNetwork.name, dnses.length, dnses,
+      let dnses = aNetworkInfo.getDnses();
+      let gateways = aNetworkInfo.getGateways();
+      gNetworkService.setDNS(aNetworkInfo.name, dnses.length, dnses,
                              gateways.length, gateways, (aError) => {
         if (aError) {
           aReject("setDNS failed");
           return;
         }
         aResolve();
       });
     });
@@ -951,65 +962,66 @@ NetworkManager.prototype = {
           debug("resetRoutingTable failed");
         }
         // Always resolve.
         aResolve();
       });
     });
   },
 
-  _removeDefaultRoute: function(aNetwork) {
+  _removeDefaultRoute: function(aNetworkInfo) {
     return new Promise((aResolve, aReject) => {
-      let gateways = aNetwork.getGateways();
-      gNetworkService.removeDefaultRoute(aNetwork.name, gateways.length,
+      let gateways = aNetworkInfo.getGateways();
+      gNetworkService.removeDefaultRoute(aNetworkInfo.name, gateways.length,
                                          gateways, (aSuccess) => {
         if (!aSuccess) {
           debug("removeDefaultRoute failed");
         }
         // Always resolve.
         aResolve();
       });
     });
   },
 
   _setDefaultRouteAndProxy: function(aNetwork, aOldInterface) {
     return new Promise((aResolve, aReject) => {
-      let gateways = aNetwork.getGateways();
-      let oldInterfaceName = (aOldInterface ? aOldInterface.name : "");
-      gNetworkService.setDefaultRoute(aNetwork.name, gateways.length, gateways,
+      let networkInfo = aNetwork.info;
+      let gateways = networkInfo.getGateways();
+      let oldInterfaceName = (aOldInterface ? aOldInterface.info.name : "");
+      gNetworkService.setDefaultRoute(networkInfo.name, gateways.length, gateways,
                                       oldInterfaceName, (aSuccess) => {
         if (!aSuccess) {
-          gNetworkService.destroyNetwork(aNetwork, function() {
+          gNetworkService.destroyNetwork(networkInfo.name, function() {
             aReject("setDefaultRoute failed");
           });
           return;
         }
         this.setNetworkProxy(aNetwork);
         aResolve();
       });
     });
   },
 
-  setNetworkProxy: function(network) {
+  setNetworkProxy: function(aNetwork) {
     try {
-      if (!network.httpProxyHost || network.httpProxyHost === "") {
+      if (!aNetwork.httpProxyHost || aNetwork.httpProxyHost === "") {
         // Sets direct connection to internet.
         this.clearNetworkProxy();
 
-        debug("No proxy support for " + network.name + " network interface.");
+        debug("No proxy support for " + aNetwork.info.name + " network interface.");
         return;
       }
 
-      debug("Going to set proxy settings for " + network.name + " network interface.");
+      debug("Going to set proxy settings for " + aNetwork.info.name + " network interface.");
 
       // Do not use this proxy server for all protocols.
       Services.prefs.setBoolPref("network.proxy.share_proxy_settings", false);
-      Services.prefs.setCharPref("network.proxy.http", network.httpProxyHost);
-      Services.prefs.setCharPref("network.proxy.ssl", network.httpProxyHost);
-      let port = network.httpProxyPort === 0 ? 8080 : network.httpProxyPort;
+      Services.prefs.setCharPref("network.proxy.http", aNetwork.httpProxyHost);
+      Services.prefs.setCharPref("network.proxy.ssl", aNetwork.httpProxyHost);
+      let port = aNetwork.httpProxyPort === 0 ? 8080 : aNetwork.httpProxyPort;
       Services.prefs.setIntPref("network.proxy.http_port", port);
       Services.prefs.setIntPref("network.proxy.ssl_port", port);
 
       let usePAC;
       try {
         usePAC = Services.prefs.getBoolPref("network.proxy.pac_generator");
       } catch (ex) {}
 
@@ -1017,17 +1029,17 @@ NetworkManager.prototype = {
         Services.prefs.setCharPref("network.proxy.autoconfig_url",
                                    gPACGenerator.generate());
         Services.prefs.setIntPref("network.proxy.type", PROXY_TYPE_PAC);
       } else {
         Services.prefs.setIntPref("network.proxy.type", PROXY_TYPE_MANUAL);
       }
     } catch(ex) {
         debug("Exception " + ex + ". Unable to set proxy setting for " +
-              network.name + " network interface.");
+              aNetwork.info.name + " network interface.");
     }
   },
 
   clearNetworkProxy: function() {
     debug("Going to clear all network proxy.");
 
     Services.prefs.clearUserPref("network.proxy.share_proxy_settings");
     Services.prefs.clearUserPref("network.proxy.http");
@@ -1100,27 +1112,27 @@ let CaptivePortalDetectionHelper = (func
   return {
     EVENT_CONNECT: EVENT_CONNECT,
     EVENT_DISCONNECT: EVENT_DISCONNECT,
     notify: function(eventType, network) {
       switch (eventType) {
         case EVENT_CONNECT:
           // perform captive portal detection on wifi interface
           if (_available && network &&
-              network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+              network.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) {
             _performDetection(network.name, function() {
               // TODO: bug 837600
               // We can disconnect wifi in here if user abort the login procedure.
             });
           }
 
           break;
         case EVENT_DISCONNECT:
           if (_available &&
-              network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
+              network.type == Ci.nsINetworkInfo.NETWORK_TYPE_WIFI) {
             _abort(network.name);
           }
           break;
       }
     }
   };
 }());
 
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -55,18 +55,18 @@ const kSettingsTimezoneAutoUpdateAvailab
 const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
 
 const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
 const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
 
 const RADIO_POWER_OFF_TIMEOUT = 30000;
 const HW_DEFAULT_CLIENT_ID = 0;
 
-const NETWORK_TYPE_WIFI        = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
-const NETWORK_TYPE_MOBILE      = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
+const NETWORK_TYPE_WIFI        = Ci.nsINetworkInfo.NETWORK_TYPE_WIFI;
+const NETWORK_TYPE_MOBILE      = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
 
 // set to true in ril_consts.js to see debug messages
 var DEBUG = RIL.DEBUG_RIL;
 
 function updateDebugFlag() {
   // Read debug setting from pref
   let debugPref;
   try {
@@ -1143,31 +1143,31 @@ RadioInterface.prototype = {
       case kSysClockChangeObserverTopic:
         let offset = parseInt(data, 10);
         if (this._lastNitzMessage) {
           this._lastNitzMessage.receiveTimeInMS += offset;
         }
         this._sntp.updateOffset(offset);
         break;
       case kNetworkConnStateChangedTopic:
-        let network = subject.QueryInterface(Ci.nsINetworkInterface);
-        if (network.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
+        let networkInfo = subject.QueryInterface(Ci.nsINetworkInfo);
+        if (networkInfo.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
           return;
         }
 
         // SNTP can only update when we have mobile or Wifi connections.
-        if (network.type != NETWORK_TYPE_WIFI &&
-            network.type != NETWORK_TYPE_MOBILE) {
+        if (networkInfo.type != NETWORK_TYPE_WIFI &&
+            networkInfo.type != NETWORK_TYPE_MOBILE) {
           return;
         }
 
         // If the network comes from RIL, make sure the RIL service is matched.
-        if (subject instanceof Ci.nsIRilNetworkInterface) {
-          network = subject.QueryInterface(Ci.nsIRilNetworkInterface);
-          if (network.serviceId != this.clientId) {
+        if (subject instanceof Ci.nsIRilNetworkInfo) {
+          networkInfo = subject.QueryInterface(Ci.nsIRilNetworkInfo);
+          if (networkInfo.serviceId != this.clientId) {
             return;
           }
         }
 
         // SNTP won't update unless the SNTP is already expired.
         if (this._sntp.isExpired()) {
           this._sntp.request();
         }
@@ -1237,18 +1237,19 @@ RadioInterface.prototype = {
         this._clockAutoUpdateEnabled = aResult;
         if (!this._clockAutoUpdateEnabled) {
           break;
         }
 
         // Set the latest cached NITZ time if it's available.
         if (this._lastNitzMessage) {
           this.setClockByNitz(this._lastNitzMessage);
-        } else if (gNetworkManager.active && gNetworkManager.active.state ==
-                 Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
+        } else if (gNetworkManager.activeNetworkInfo &&
+                   gNetworkManager.activeNetworkInfo.state ==
+                   Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
           // Set the latest cached SNTP time if it's available.
           if (!this._sntp.isExpired()) {
             this.setClockBySntp(this._sntp.getOffset());
           } else {
             // Or refresh the SNTP.
             this._sntp.request();
           }
         } else {
--- a/dom/system/gonk/TetheringService.js
+++ b/dom/system/gonk/TetheringService.js
@@ -243,17 +243,17 @@ TetheringService.prototype = {
         break;
       case TOPIC_MOZSETTINGS_CHANGED:
         if ("wrappedJSObject" in aSubject) {
           aSubject = aSubject.wrappedJSObject;
         }
         this.handle(aSubject.key, aSubject.value);
         break;
       case TOPIC_CONNECTION_STATE_CHANGED:
-        network = aSubject.QueryInterface(Ci.nsINetworkInterface);
+        network = aSubject.QueryInterface(Ci.nsINetworkInfo);
         debug("Network " + network.type + "/" + network.name +
               " changed state to " + network.state);
         this.onConnectionChanged(network);
         break;
       case TOPIC_XPCOM_SHUTDOWN:
         Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
         Services.obs.removeObserver(this, TOPIC_MOZSETTINGS_CHANGED);
         Services.obs.removeObserver(this, TOPIC_CONNECTION_STATE_CHANGED);
@@ -333,28 +333,28 @@ TetheringService.prototype = {
 
     this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_STARTIP] = DEFAULT_WIFI_DHCPSERVER_STARTIP;
     this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP]   = DEFAULT_WIFI_DHCPSERVER_ENDIP;
 
     this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
       libcutils.property_get("ro.tethering.dun_required") === "1";
   },
 
-  getNetworkInterface: function(aType, aServiceId) {
-    for each (let network in gNetworkManager.networkInterfaces) {
-      if (network.type == aType) {
+  getNetworkInfo: function(aType, aServiceId) {
+    for each (let networkInfo in gNetworkManager.allNetworkInfo) {
+      if (networkInfo.type == aType) {
         try {
-          if (network instanceof Ci.nsIRilNetworkInterface) {
-            let rilNetwork = network.QueryInterface(Ci.nsIRilNetworkInterface);
+          if (networkInfo instanceof Ci.nsIRilNetworkInfo) {
+            let rilNetwork = networkInfo.QueryInterface(Ci.nsIRilNetworkInfo);
             if (rilNetwork.serviceId != aServiceId) {
               continue;
             }
           }
         } catch (e) {}
-        return network;
+        return networkInfo;
       }
     }
     return null;
   },
 
   handleLastUsbTetheringRequest: function() {
     debug('handleLastUsbTetheringRequest... ' + this._usbTetheringRequestCount);
 
@@ -400,17 +400,17 @@ TetheringService.prototype = {
     this.dunRetryTimer.cancel();
     let connection =
       gMobileConnectionService.getItemByServiceId(this._dataDefaultServiceId);
     let data = connection && connection.data;
     if (data && data.state === "registered") {
       let ril = gRil.getRadioInterface(this._dataDefaultServiceId);
 
       this.dunRetryTimes = 0;
-      ril.setupDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN);
+      ril.setupDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN);
       this.dunConnectTimer.cancel();
       this.dunConnectTimer.
         initWithCallback(this.onDunConnectTimerTimeout.bind(this),
                          MOBILE_DUN_CONNECT_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT);
       return;
     }
 
     if (this.dunRetryTimes++ >= this.MOBILE_DUN_MAX_RETRIES) {
@@ -425,40 +425,40 @@ TetheringService.prototype = {
     this.dunRetryTimer.
       initWithCallback(this.setupDunConnection.bind(this),
                        MOBILE_DUN_RETRY_INTERVAL, Ci.nsITimer.TYPE_ONE_SHOT);
   },
 
   _dunActiveUsers: 0,
   handleDunConnection: function(aEnable, aCallback) {
     debug("handleDunConnection: " + aEnable);
-    let dun = this.getNetworkInterface(
-      Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN, this._dataDefaultServiceId);
+    let dun = this.getNetworkInfo(
+      Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN, this._dataDefaultServiceId);
 
     if (!aEnable) {
       this._dunActiveUsers--;
       if (this._dunActiveUsers > 0) {
         debug("Dun still needed by others, do not disconnect.")
         return;
       }
 
       this.dunRetryTimes = 0;
       this.dunRetryTimer.cancel();
       this.dunConnectTimer.cancel();
       this._pendingTetheringRequests = [];
 
-      if (dun && (dun.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED)) {
+      if (dun && (dun.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED)) {
         gRil.getRadioInterface(this._dataDefaultServiceId)
-          .deactivateDataCallByType(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN);
+          .deactivateDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN);
       }
       return;
     }
 
     this._dunActiveUsers++;
-    if (!dun || (dun.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED)) {
+    if (!dun || (dun.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED)) {
       debug("DUN data call inactive, setup dun data call!")
       this._pendingTetheringRequests.push(aCallback);
       this.dunRetryTimes = 0;
       this.setupDunConnection();
 
       return;
     }
 
@@ -490,33 +490,34 @@ TetheringService.prototype = {
       gNetworkService.enableUsbRndis(false, this.enableUsbRndisResult.bind(this));
       return;
     }
 
     this.tetheringSettings[SETTINGS_USB_ENABLED] = true;
     this._usbTetheringAction = TETHERING_STATE_ONGOING;
 
     if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
-      this.handleDunConnection(true, (aNetwork) => {
-        if (!aNetwork){
+      this.handleDunConnection(true, (aNetworkInfo) => {
+        if (!aNetworkInfo){
           this.usbTetheringResultReport(aEnable, "Dun connection failed");
           return;
         }
-        this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = aNetwork.name;
+        this._tetheringInterface[TETHERING_TYPE_USB].externalInterface =
+          aNetworkInfo.name;
         gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this));
       });
       return;
     }
 
-    if (gNetworkManager.active) {
+    if (gNetworkManager.activeNetworkInfo) {
       this._tetheringInterface[TETHERING_TYPE_USB].externalInterface =
-        gNetworkManager.active.name;
+        gNetworkManager.activeNetworkInfo.name;
     } else {
-      let mobile = this.getNetworkInterface(
-        Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId);
+      let mobile = this.getNetworkInfo(
+        Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId);
       if (mobile && mobile.name) {
         this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = mobile.name;
       }
     }
     gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this));
   },
 
   getUSBTetheringParameters: function(aEnable, aTetheringInterface) {
@@ -594,20 +595,20 @@ TetheringService.prototype = {
       if (this._usbTetheringRequestCount > 0) {
         debug('Perform pending USB tethering requests.');
         this.handleLastUsbTetheringRequest();
       }
     });
   },
 
   // Enable/disable WiFi tethering by sending commands to netd.
-  setWifiTethering: function(aEnable, aNetwork, aConfig, aCallback) {
+  setWifiTethering: function(aEnable, aInterfaceName, aConfig, aCallback) {
     debug("setWifiTethering: " + aEnable);
-    if (!aNetwork) {
-      this.notifyError(true, aCallback, "invalid network information");
+    if (!aInterfaceName) {
+      this.notifyError(true, aCallback, "invalid network interface name");
       return;
     }
 
     if (!aConfig) {
       this.notifyError(true, aCallback, "invalid configuration");
       return;
     }
 
@@ -625,32 +626,34 @@ TetheringService.prototype = {
     this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
       libcutils.property_get("ro.tethering.dun_required") === "1";
 
     if (!aEnable) {
       this.enableWifiTethering(false, aConfig, aCallback);
       return;
     }
 
-    this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = aNetwork.name;
+    this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface =
+      aInterfaceName;
 
     if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
-      this.handleDunConnection(true, (aNetwork) => {
-        if (!aNetwork) {
+      this.handleDunConnection(true, (aNetworkInfo) => {
+        if (!aNetworkInfo) {
           this.notifyError(true, aCallback, "Dun connection failed");
           return;
         }
-        this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = aNetwork.name;
+        this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface =
+          aNetworkInfo.name;
         this.enableWifiTethering(true, aConfig, aCallback);
       });
       return;
     }
 
-    let mobile = this.getNetworkInterface(
-      Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId);
+    let mobile = this.getNetworkInfo(
+      Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId);
     // Update the real interface name
     if (mobile && mobile.name) {
       this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name;
     }
 
     this.enableWifiTethering(true, aConfig, aCallback);
   },
 
@@ -740,67 +743,67 @@ TetheringService.prototype = {
     if (aSuccess) {
       // Update the external interface.
       this._tetheringInterface[TETHERING_TYPE_USB].externalInterface =
         aExternalIfname;
       debug("Change the interface name to " + aExternalIfname);
     }
   },
 
-  onConnectionChanged: function(aNetwork) {
-    if (aNetwork.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
+  onConnectionChanged: function(aNetworkInfo) {
+    if (aNetworkInfo.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
       debug("We are only interested in CONNECTED event");
       return;
     }
 
     if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
-        aNetwork.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
+        aNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) {
       this.dunConnectTimer.cancel();
       debug("DUN data call connected, process callbacks.");
       while (this._pendingTetheringRequests.length > 0) {
         let callback = this._pendingTetheringRequests.shift();
         if (typeof callback === 'function') {
-          callback(aNetwork);
+          callback(aNetworkInfo);
         }
       }
       return;
     }
 
     if (!this.tetheringSettings[SETTINGS_USB_ENABLED]) {
       debug("Usb tethering settings is not enabled");
       return;
     }
 
     if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
-        aNetwork.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN &&
+        aNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN &&
         this._tetheringInterface[TETHERING_TYPE_USB].externalInterface ===
-        aNetwork.name) {
+        aNetworkInfo.name) {
       debug("Dun required and dun interface is the same");
       return;
     }
 
     if (this._tetheringInterface[TETHERING_TYPE_USB].externalInterface ===
-        gNetworkManager.active.name) {
+        gNetworkManager.activeNetworkInfo.name) {
       debug("The active interface is the same");
       return;
     }
 
     let previous = {
       internalIfname: this._tetheringInterface[TETHERING_TYPE_USB].internalInterface,
       externalIfname: this._tetheringInterface[TETHERING_TYPE_USB].externalInterface
     };
 
     let current = {
       internalIfname: this._tetheringInterface[TETHERING_TYPE_USB].internalInterface,
-      externalIfname: aNetwork.name
+      externalIfname: aNetworkInfo.name
     };
 
     let callback = (() => {
       // Update external network interface.
-      debug("Update upstream interface to " + aNetwork.name);
+      debug("Update upstream interface to " + aNetworkInfo.name);
       gNetworkService.updateUpStream(previous, current,
                                      this.onConnectionChangedReport.bind(this));
     });
 
     if (this._usbTetheringAction === TETHERING_STATE_ONGOING) {
       debug("Postpone the event and handle it when state is idle.");
       this.wantConnectionEvent = callback;
       return;
--- a/dom/system/gonk/moz.build
+++ b/dom/system/gonk/moz.build
@@ -11,16 +11,17 @@
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
 XPIDL_SOURCES += [
     'nsIAudioManager.idl',
+    'nsINetworkInterface.idl',
     'nsINetworkInterfaceListService.idl',
     'nsINetworkManager.idl',
     'nsINetworkService.idl',
     'nsINetworkWorker.idl',
     'nsISystemWorkerManager.idl',
     'nsITetheringService.idl',
     'nsIVolume.idl',
     'nsIVolumeMountLock.idl',
--- a/dom/system/gonk/nsIDataCallManager.idl
+++ b/dom/system/gonk/nsIDataCallManager.idl
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
-#include "nsINetworkManager.idl"
+#include "nsINetworkInterface.idl"
 
-[scriptable, uuid(b8ce8528-fce8-4b5e-9d0a-c3247296ccaf)]
-interface nsIRilNetworkInterface : nsINetworkInterface
+[scriptable, uuid(501b7041-0754-4ddb-9174-946e2c2ebd83)]
+interface nsIRilNetworkInfo : nsINetworkInfo
 {
   readonly attribute unsigned long serviceId;
   readonly attribute DOMString iccId;
 
   /* The following attributes are for MMS proxy settings. */
   readonly attribute DOMString mmsc;     // Empty string if not set.
   readonly attribute DOMString mmsProxy; // Empty string if not set.
   readonly attribute long      mmsPort;  // -1 if not set.
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/nsINetworkInterface.idl
@@ -0,0 +1,100 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(f439ab5d-64bd-4a6c-8863-30235fa784d2)]
+interface nsINetworkInfo : nsISupports
+{
+  const long NETWORK_STATE_UNKNOWN       = -1;
+  const long NETWORK_STATE_CONNECTING    = 0;
+  const long NETWORK_STATE_CONNECTED     = 1;
+  const long NETWORK_STATE_DISCONNECTING = 2;
+  const long NETWORK_STATE_DISCONNECTED  = 3;
+
+  /**
+   * Current network state, one of the NETWORK_STATE_* constants.
+   *
+   * When this changes, network interface implementations notify with
+   * updateNetworkInterface() API.
+   */
+  readonly attribute long state;
+
+  const long NETWORK_TYPE_UNKNOWN     = -1;
+  const long NETWORK_TYPE_WIFI        = 0;
+  const long NETWORK_TYPE_MOBILE      = 1;
+  const long NETWORK_TYPE_MOBILE_MMS  = 2;
+  const long NETWORK_TYPE_MOBILE_SUPL = 3;
+  const long NETWORK_TYPE_WIFI_P2P    = 4;
+  const long NETWORK_TYPE_MOBILE_IMS  = 5;
+  const long NETWORK_TYPE_MOBILE_DUN  = 6;
+  const long NETWORK_TYPE_MOBILE_FOTA = 7;
+
+  /**
+   * Network type. One of the NETWORK_TYPE_* constants.
+   */
+  readonly attribute long type;
+
+  /**
+   * Interface name of the network interface this network info belongs to.
+   */
+  readonly attribute DOMString name;
+
+  /**
+   * Get the list of ip addresses and prefix lengths, ip address could be IPv4
+   * or IPv6, typically 1 IPv4 or 1 IPv6 or one of each.
+   *
+   * @param ips
+   *        The list of ip addresses retrieved.
+   * @param prefixLengths
+   *        The list of prefix lengths retrieved.
+   *
+   * @returns the length of the lists.
+   */
+  void getAddresses([array, size_is(count)] out wstring ips,
+                    [array, size_is(count)] out unsigned long prefixLengths,
+                    [retval] out unsigned long count);
+
+  /**
+   * Get the list of gateways, could be IPv4 or IPv6, typically 1 IPv4 or 1
+   * IPv6 or one of each.
+   *
+   * @param count
+   *        The length of the list of gateways
+   *
+   * @returns the list of gateways.
+   */
+  void getGateways([optional] out unsigned long count,
+                   [array, size_is(count), retval] out wstring gateways);
+
+  /**
+   * Get the list of dnses, could be IPv4 or IPv6.
+   *
+   * @param count
+   *        The length of the list of dnses.
+   *
+   * @returns the list of dnses.
+   */
+  void getDnses([optional] out unsigned long count,
+                [array, size_is(count), retval] out wstring dnses);
+};
+
+[scriptable, uuid(9a025351-8684-4ab5-a0c1-f21a9f83d405)]
+interface nsINetworkInterface : nsISupports
+{
+  /**
+   * The network information about this network interface.
+   */
+  readonly attribute nsINetworkInfo info;
+
+  /**
+   * The host name of the http proxy server.
+   */
+  readonly attribute DOMString httpProxyHost;
+
+  /*
+   * The port number of the http proxy server.
+   */
+  readonly attribute long httpProxyPort;
+};
--- a/dom/system/gonk/nsINetworkInterfaceListService.idl
+++ b/dom/system/gonk/nsINetworkInterfaceListService.idl
@@ -1,28 +1,29 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsINetworkManager.idl"
 #include "nsISupports.idl"
 
-[scriptable, uuid(b44d74db-c9d6-41dd-98ae-a56918d6e6ad)]
+interface nsINetworkInfo;
+
+[scriptable, uuid(55779d32-1e28-4f43-af87-09d04bc3cce9)]
 interface nsINetworkInterfaceList : nsISupports
 {
   /**
    * Number of the network interfaces that is available.
    */
   long getNumberOfInterface();
 
   /**
-   * Get the i-th interface from the list.
+   * Get the i-th interface info info from the list.
    * @param interfaceIndex index of interface, from 0 to number of interface - 1.
    */
-  nsINetworkInterface getInterface(in long interfaceIndex);
+  nsINetworkInfo getInterfaceInfo(in long interfaceIndex);
 };
 
 [scriptable, uuid(21d7fc8b-28c4-4a4f-a15e-1f9defbc2cec)]
 interface nsINetworkInterfaceListService : nsISupports
 {
   const long LIST_NOT_INCLUDE_MMS_INTERFACES  = (1 << 0);
   const long LIST_NOT_INCLUDE_SUPL_INTERFACES = (1 << 1);
   const long LIST_NOT_INCLUDE_IMS_INTERFACES  = (1 << 2);
--- a/dom/system/gonk/nsINetworkManager.idl
+++ b/dom/system/gonk/nsINetworkManager.idl
@@ -1,107 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-/**
- * Information about networks that is exposed to network manager API consumers.
- */
-[scriptable, uuid(12da2bfd-0801-40d9-9c2e-768868526065)]
-interface nsINetworkInterface : nsISupports
-{
-  const long NETWORK_STATE_UNKNOWN = -1;
-  const long NETWORK_STATE_CONNECTING = 0;
-  const long NETWORK_STATE_CONNECTED = 1;
-  const long NETWORK_STATE_DISCONNECTING = 2;
-  const long NETWORK_STATE_DISCONNECTED = 3;
-
-  /**
-   * Current network state, one of the NETWORK_STATE_* constants.
-   *
-   * When this changes, network interface implementations notify with
-   * updateNetworkInterface() API.
-   */
-  readonly attribute long state;
-
-  const long NETWORK_TYPE_UNKNOWN     = -1;
-  const long NETWORK_TYPE_WIFI        = 0;
-  const long NETWORK_TYPE_MOBILE      = 1;
-  const long NETWORK_TYPE_MOBILE_MMS  = 2;
-  const long NETWORK_TYPE_MOBILE_SUPL = 3;
-  const long NETWORK_TYPE_WIFI_P2P    = 4;
-  const long NETWORK_TYPE_MOBILE_IMS  = 5;
-  const long NETWORK_TYPE_MOBILE_DUN  = 6;
-  const long NETWORK_TYPE_MOBILE_FOTA = 7;
-
-  /**
-   * Network type. One of the NETWORK_TYPE_* constants.
-   */
-  readonly attribute long type;
-
-  /**
-   * Name of the network interface. This identifier is unique.
-   */
-  readonly attribute DOMString name;
-
-  /**
-   * The host name of the http proxy server.
-   */
-  readonly attribute DOMString httpProxyHost;
-
-  /*
-   * The port number of the http proxy server.
-   */
-  readonly attribute long httpProxyPort;
-
-  /**
-   * Get the list of ip addresses and prefix lengths, ip address could be IPv4
-   * or IPv6, typically 1 IPv4 or 1 IPv6 or one of each.
-   *
-   * @param ips
-   *        The list of ip addresses retrieved.
-   * @param prefixLengths
-   *        The list of prefix lengths retrieved.
-   *
-   * @returns the length of the lists.
-   */
-  void getAddresses([array, size_is(count)] out wstring ips,
-                    [array, size_is(count)] out unsigned long prefixLengths,
-                    [retval] out unsigned long count);
-
-  /**
-   * Get the list of gateways, could be IPv4 or IPv6, typically 1 IPv4 or 1
-   * IPv6 or one of each.
-   *
-   * @param count
-   *        The length of the list of gateways
-   *
-   * @returns the list of gateways.
-   */
-  void getGateways([optional] out unsigned long count,
-                   [array, size_is(count), retval] out wstring gateways);
-
-  /**
-   * Get the list of dnses, could be IPv4 or IPv6.
-   *
-   * @param count
-   *        The length of the list of dnses.
-   *
-   * @returns the list of dnses.
-   */
-  void getDnses([optional] out unsigned long count,
-                [array, size_is(count), retval] out wstring dnses);
-};
+interface nsINetworkInfo;
+interface nsINetworkInterface;
 
 /**
  * Manage network interfaces.
  */
-[scriptable, uuid(b0ab71bf-4b38-4796-8a3c-4141255f4259)]
+[scriptable, uuid(e5ffe335-078e-4b25-87f1-02429bd2e458)]
 interface nsINetworkManager : nsISupports
 {
   /**
    * Register the given network interface with the network manager.
    *
    * Consumers will be notified with the 'network-interface-registered'
    * observer notification.
    *
@@ -136,40 +50,41 @@ interface nsINetworkManager : nsISupport
    * registered.
    *
    * @param network
    *        Network interface to unregister.
    */
   void unregisterNetworkInterface(in nsINetworkInterface network);
 
   /**
-   * Object containing all known network connections, keyed by their
+   * Object containing all known network information, keyed by their
    * network id. Network id is composed of a sub-id + '-' + network
    * type. For mobile network types, sub-id is 'ril' + service id; for
    * non-mobile network types, sub-id is always 'device'.
    */
-  readonly attribute jsval networkInterfaces;
+  readonly attribute jsval allNetworkInfo;
 
   /**
    * The preferred network type. One of the
    * nsINetworkInterface::NETWORK_TYPE_* constants.
    *
    * This attribute is used for setting default route to favor
    * interfaces with given type.  This can be overriden by calling
    * overrideDefaultRoute().
    */
   attribute long preferredNetworkType;
 
   /**
-   * The network interface handling all data traffic.
+   * The network information of the network interface handling all network
+   * traffic.
    *
    * When this changes, the 'network-active-changed' observer
    * notification is dispatched.
    */
-  readonly attribute nsINetworkInterface active;
+  readonly attribute nsINetworkInfo activeNetworkInfo;
 
   /**
    * Override the default behaviour for preferredNetworkType and route
    * all network traffic through the the specified interface.
    *
    * Consumers can observe changes to the active network by subscribing to
    * the 'network-active-changed' observer notification.
    *
@@ -178,34 +93,34 @@ interface nsINetworkManager : nsISupport
    *        a previous override is canceled.
    */
   long overrideActive(in nsINetworkInterface network);
 
   /**
    * Add host route to the specified network into routing table.
    *
    * @param network
-   *        The network interface where the host to be routed to.
+   *        The network information for the host to be routed to.
    * @param host
    *        The host to be added.
    *        The host will be resolved in advance if it's not an ip-address.
    *
    * @return a Promise
    *         resolved if added; rejected, otherwise.
    */
-  jsval addHostRoute(in nsINetworkInterface network,
+  jsval addHostRoute(in nsINetworkInfo network,
                      in DOMString host);
 
   /**
    * Remove host route to the specified network from routing table.
    *
    * @param network
-   *        The network interface where the routing to be removed from.
+   *        The network information for the routing to be removed from.
    * @param host
    *        The host routed to the network.
    *        The host will be resolved in advance if it's not an ip-address.
    *
    * @return a Promise
    *         resolved if removed; rejected, otherwise.
    */
-  jsval removeHostRoute(in nsINetworkInterface network,
+  jsval removeHostRoute(in nsINetworkInfo network,
                         in DOMString host);
 };
--- a/dom/system/gonk/nsITetheringService.idl
+++ b/dom/system/gonk/nsITetheringService.idl
@@ -2,29 +2,29 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsINetworkInterface;
 interface nsIWifiTetheringCallback;
 
-[scriptable, uuid(80d65940-bd99-458f-8529-e438c7348087)]
+[scriptable, uuid(993b79df-f10e-4697-a5dc-5981cf8ff7e6)]
 interface nsITetheringService : nsISupports
 {
   /**
    * Enable or disable Wifi Tethering
    *
    * @param enabled
    *        Boolean that indicates whether tethering should be enabled (true) or
    *        disabled (false).
-   * @param networkInterface
-   *        The Wifi network interface with at least name of network interface.
+   * @param interfaceName
+   *        The Wifi network interface name for internal interface.
    * @param config
    *        The Wifi Tethering configuration from settings db.
    * @param callback
    *        Callback function used to report status to WifiManager.
    */
   void setWifiTethering(in boolean enabled,
-                        in nsINetworkInterface networkInterface,
+                        in DOMString interfaceName,
                         in jsval config,
                         in nsIWifiTetheringCallback callback);
 };
\ No newline at end of file
--- a/dom/system/gonk/tests/marionette/head.js
+++ b/dom/system/gonk/tests/marionette/head.js
@@ -4,28 +4,28 @@
 MARIONETTE_CONTEXT = "chrome";
 
 const SETTINGS_KEY_DATA_ENABLED = "ril.data.enabled";
 const SETTINGS_KEY_DATA_APN_SETTINGS  = "ril.data.apnSettings";
 
 const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
 const TOPIC_NETWORK_ACTIVE_CHANGED = "network-active-changed";
 
-const NETWORK_STATE_UNKNOWN = Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN;
-const NETWORK_STATE_CONNECTING = Ci.nsINetworkInterface.NETWORK_STATE_CONNECTING;
-const NETWORK_STATE_CONNECTED = Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED;
-const NETWORK_STATE_DISCONNECTING = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTING;
-const NETWORK_STATE_DISCONNECTED = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED;
+const NETWORK_STATE_UNKNOWN = Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN;
+const NETWORK_STATE_CONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTING;
+const NETWORK_STATE_CONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
+const NETWORK_STATE_DISCONNECTING = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTING;
+const NETWORK_STATE_DISCONNECTED = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
 
-const NETWORK_TYPE_MOBILE = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
-const NETWORK_TYPE_MOBILE_MMS = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS;
-const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL;
-const NETWORK_TYPE_MOBILE_IMS = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS;
-const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN;
-const NETWORK_TYPE_MOBILE_FOTA = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_FOTA;
+const NETWORK_TYPE_MOBILE = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE;
+const NETWORK_TYPE_MOBILE_MMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS;
+const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL;
+const NETWORK_TYPE_MOBILE_IMS = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_IMS;
+const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN;
+const NETWORK_TYPE_MOBILE_FOTA = Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_FOTA;
 
 const networkTypes = [
   NETWORK_TYPE_MOBILE,
   NETWORK_TYPE_MOBILE_MMS,
   NETWORK_TYPE_MOBILE_SUPL,
   NETWORK_TYPE_MOBILE_IMS,
   NETWORK_TYPE_MOBILE_DUN,
   NETWORK_TYPE_MOBILE_FOTA
@@ -139,23 +139,23 @@ function waitForObserverEvent(aTopic) {
  *        A boolean state.
  *
  * @return A deferred promise.
  */
 function setDataEnabledAndWait(aEnabled) {
   let promises = [];
   promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
     .then(function(aSubject) {
-      ok(aSubject instanceof Ci.nsIRilNetworkInterface,
-         "subject should be an instance of nsIRILNetworkInterface");
+      ok(aSubject instanceof Ci.nsIRilNetworkInfo,
+         "subject should be an instance of nsIRilNetworkInfo");
       is(aSubject.type, NETWORK_TYPE_MOBILE,
          "subject.type should be " + NETWORK_TYPE_MOBILE);
       is(aSubject.state,
-         aEnabled ? Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED
-                  : Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED,
+         aEnabled ? Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED
+                  : Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED,
          "subject.state should be " + aEnabled ? "CONNECTED" : "DISCONNECTED");
     }));
   promises.push(setSettings(SETTINGS_KEY_DATA_ENABLED, aEnabled));
 
   return Promise.all(promises);
 }
 
 /**
@@ -170,21 +170,21 @@ function setDataEnabledAndWait(aEnabled)
  * @return A deferred promise.
  */
 function setupDataCallAndWait(aNetworkType) {
   log("setupDataCallAndWait: " + aNetworkType);
 
   let promises = [];
   promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
     .then(function(aSubject) {
-      ok(aSubject instanceof Ci.nsIRilNetworkInterface,
-         "subject should be an instance of nsIRILNetworkInterface");
+      ok(aSubject instanceof Ci.nsIRilNetworkInfo,
+         "subject should be an instance of nsIRilNetworkInfo");
       is(aSubject.type, aNetworkType,
          "subject.type should be " + aNetworkType);
-      is(aSubject.state, Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED,
+      is(aSubject.state, Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED,
          "subject.state should be CONNECTED");
     }));
   promises.push(radioInterface.setupDataCallByType(aNetworkType));
 
   return Promise.all(promises);
 }
 
 /**
@@ -199,21 +199,21 @@ function setupDataCallAndWait(aNetworkTy
  * @return A deferred promise.
  */
 function deactivateDataCallAndWait(aNetworkType) {
   log("deactivateDataCallAndWait: " + aNetworkType);
 
   let promises = [];
   promises.push(waitForObserverEvent(TOPIC_CONNECTION_STATE_CHANGED)
     .then(function(aSubject) {
-      ok(aSubject instanceof Ci.nsIRilNetworkInterface,
-         "subject should be an instance of nsIRILNetworkInterface");
+      ok(aSubject instanceof Ci.nsIRilNetworkInfo,
+         "subject should be an instance of nsIRilNetworkInfo");
       is(aSubject.type, aNetworkType,
          "subject.type should be " + aNetworkType);
-      is(aSubject.state, Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED,
+      is(aSubject.state, Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED,
          "subject.state should be DISCONNECTED");
     }));
   promises.push(radioInterface.deactivateDataCallByType(aNetworkType));
 
   return Promise.all(promises);
 }
 
 /**
--- a/dom/system/gonk/tests/marionette/test_network_active_changed.js
+++ b/dom/system/gonk/tests/marionette/test_network_active_changed.js
@@ -8,42 +8,42 @@ let networkManager =
   Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
 ok(networkManager,
    "networkManager.constructor is " + networkManager.constructor);
 
 function testInitialState() {
   return getSettings(SETTINGS_KEY_DATA_ENABLED)
     .then((enabled) => {
       is(enabled, false, "data should be off by default");
-      is(networkManager.active, null,
-         "networkManager.active should be null by default");
+      is(networkManager.activeNetworkInfo, null,
+         "networkManager.activeNetworkInfo should be null by default");
     });
 }
 
 function testActiveNetworkChangedBySwitchingDataCall(aDataCallEnabled) {
   log("Test active network by switching dataCallEnabled to " + aDataCallEnabled);
 
   let promises = [];
   promises.push(waitForObserverEvent(TOPIC_NETWORK_ACTIVE_CHANGED));
   promises.push(setSettings(SETTINGS_KEY_DATA_ENABLED, aDataCallEnabled));
 
   return Promise.all(promises).then(function(results) {
     let subject = results[0];
 
     if (aDataCallEnabled) {
-      ok(subject instanceof Ci.nsINetworkInterface,
-         "subject should be an instance of nsINetworkInterface");
-      ok(subject instanceof Ci.nsIRilNetworkInterface,
-         "subject should be an instance of nsIRILNetworkInterface");
+      ok(subject instanceof Ci.nsINetworkInfo,
+         "subject should be an instance of nsINetworkInfo");
+      ok(subject instanceof Ci.nsIRilNetworkInfo,
+         "subject should be an instance of nsIRilNetworkInfo");
       is(subject.type, NETWORK_TYPE_MOBILE,
          "subject.type should be NETWORK_TYPE_MOBILE");
     }
 
-    is(subject, networkManager.active,
-       "subject should be equal with networkManager.active");
+    is(subject, networkManager.activeNetworkInfo,
+       "subject should be equal with networkManager.activeNetworkInfo");
   });
 }
 
 // Start test
 startTestBase(function() {
   return testInitialState()
     // Test active network changed by enabling data call.
     .then(() => testActiveNetworkChangedBySwitchingDataCall(true))
--- a/dom/system/gonk/tests/marionette/test_network_interface_list_service.js
+++ b/dom/system/gonk/tests/marionette/test_network_interface_list_service.js
@@ -1,71 +1,71 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = "head.js";
 
-function getNetworkInterface(aType) {
+function getNetworkInfo(aType) {
   let networkListService =
     Cc["@mozilla.org/network/interface-list-service;1"].
       getService(Ci.nsINetworkInterfaceListService);
   // Get all available interfaces
   let networkList = networkListService.getDataInterfaceList(0);
 
   // Try to get nsINetworkInterface for aType.
   let numberOfInterface = networkList.getNumberOfInterface();
   for (let i = 0; i < numberOfInterface; i++) {
-    let iface = networkList.getInterface(i);
-    if (iface.type === aType) {
-      return iface;
+    let info = networkList.getInterfaceInfo(i);
+    if (info.type === aType) {
+      return info;
     }
   }
 
   return null;
 }
 
 // Test getDataInterfaceList by enabling/disabling mobile data.
 function testGetDataInterfaceList(aMobileDataEnabled) {
   log("Test getDataInterfaceList with mobile data " +
       aMobileDataEnabled ? "enabled" : "disabled");
 
   return setDataEnabledAndWait(aMobileDataEnabled)
-    .then(() => getNetworkInterface(NETWORK_TYPE_MOBILE))
-    .then((networkInterface) => {
-      if (!networkInterface) {
-        ok(false, "Should get an valid nsINetworkInterface for mobile");
+    .then(() => getNetworkInfo(NETWORK_TYPE_MOBILE))
+    .then((networkInfo) => {
+      if (!networkInfo) {
+        ok(false, "Should get an valid nsINetworkInfo for mobile");
         return;
       }
 
-      ok(networkInterface instanceof Ci.nsINetworkInterface,
-         "networkInterface should be an instance of nsINetworkInterface");
+      ok(networkInfo instanceof Ci.nsINetworkInfo,
+         "networkInfo should be an instance of nsINetworkInfo");
 
       let ipAddresses = {};
       let prefixs = {};
       let numOfGateways = {};
       let numOfDnses = {};
-      let numOfIpAddresses = networkInterface.getAddresses(ipAddresses, prefixs);
-      let gateways = networkInterface.getGateways(numOfGateways);
-      let dnses = networkInterface.getDnses(numOfDnses);
+      let numOfIpAddresses = networkInfo.getAddresses(ipAddresses, prefixs);
+      let gateways = networkInfo.getGateways(numOfGateways);
+      let dnses = networkInfo.getDnses(numOfDnses);
 
       if (aMobileDataEnabled) {
         // Mobile data is enabled.
-        is(networkInterface.state, NETWORK_STATE_CONNECTED, "check state");
+        is(networkInfo.state, NETWORK_STATE_CONNECTED, "check state");
         ok(numOfIpAddresses > 0, "check number of ipAddresses");
         ok(ipAddresses.value.length > 0, "check ipAddresses.length");
         ok(prefixs.value.length > 0, "check prefixs.length");
         ok(numOfGateways.value > 0, "check number of gateways");
         ok(prefixs.value.length > 0, "check prefixs.length");
         ok(gateways.length > 0, "check gateways.length");
         ok(numOfDnses.value > 0, "check number of dnses");
         ok(dnses.length > 0, "check dnses.length");
       } else {
         // Mobile data is disabled.
-        is(networkInterface.state, NETWORK_STATE_DISCONNECTED, "check state");
+        is(networkInfo.state, NETWORK_STATE_DISCONNECTED, "check state");
         is(numOfIpAddresses, 0, "check number of ipAddresses");
         is(ipAddresses.value.length, 0, "check ipAddresses.length");
         is(prefixs.value.length, 0, "check prefixs.length");
         is(numOfGateways.value, 0, "check number of gateways");
         is(prefixs.value.length, 0, "check prefixs.length");
         is(gateways.length, 0, "check gateways.length");
         is(numOfDnses.value, 0, "check number of dnses");
         is(dnses.length, 0, "check dnses.length");
--- a/dom/wifi/WifiP2pManager.jsm
+++ b/dom/wifi/WifiP2pManager.jsm
@@ -485,49 +485,54 @@ function P2pStateMachine(aP2pCommand, aN
     address: "",
     deviceName: DEFAULT_P2P_DEVICE_NAME + "_" + libcutils.property_get("ro.build.product"),
     wpsCapabilities: [WPS_METHOD_PBC, WPS_METHOD_KEYPAD, WPS_METHOD_DISPLAY]
   };
 
   let _p2pNetworkInterface = {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
 
-    state: Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED,
-    type: Ci.nsINetworkInterface.NETWORK_TYPE_WIFI_P2P,
-    name: P2P_INTERFACE_NAME,
-    ips: [],
-    prefixLengths: [],
-    dnses: [],
-    gateways: [],
+    info: {
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo]),
+
+      state: Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED,
+      type: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI_P2P,
+      name: P2P_INTERFACE_NAME,
+      ips: [],
+      prefixLengths: [],
+      dnses: [],
+      gateways: [],
+
+      getAddresses: function (ips, prefixLengths) {
+        ips.value = this.ips.slice();
+        prefixLengths.value = this.prefixLengths.slice();
+
+        return this.ips.length;
+      },
+
+      getGateways: function (count) {
+        if (count) {
+          count.value = this.gateways.length;
+        }
+        return this.gateways.slice();
+      },
+
+      getDnses: function (count) {
+        if (count) {
+          count.value = this.dnses.length;
+        }
+        return this.dnses.slice();
+      }
+    },
+
     httpProxyHost: null,
     httpProxyPort: null,
 
     // help
-    registered: false,
-
-    getAddresses: function (ips, prefixLengths) {
-      ips.value = this.ips.slice();
-      prefixLengths.value = this.prefixLengths.slice();
-
-      return this.ips.length;
-    },
-
-    getGateways: function (count) {
-      if (count) {
-        count.value = this.gateways.length;
-      }
-      return this.gateways.slice();
-    },
-
-    getDnses: function (count) {
-      if (count) {
-        count.value = this.dnses.length;
-      }
-      return this.dnses.slice();
-    }
+    registered: false
   };
 
   //---------------------------------------------------------
   // State machine APIs.
   //---------------------------------------------------------
 
   // Register the observer which is implemented in WifiP2pWorkerObserver.jsm.
   //
@@ -1414,20 +1419,20 @@ function P2pStateMachine(aP2pCommand, aN
       aNetUtil.startDhcpServer(dhcpServerConfig, function (success) {
         if (!success) {
           debug('Failed to start DHCP server');
           onFailure();
           return;
         }
 
         // Update p2p network interface.
-        _p2pNetworkInterface.state = Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED;
-        _p2pNetworkInterface.ips = [GO_NETWORK_INTERFACE.ip];
-        _p2pNetworkInterface.prefixLengths = [GO_NETWORK_INTERFACE.maskLength];
-        _p2pNetworkInterface.gateways = [GO_NETWORK_INTERFACE.ip];
+        _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
+        _p2pNetworkInterface.info.ips = [GO_NETWORK_INTERFACE.ip];
+        _p2pNetworkInterface.info.prefixLengths = [GO_NETWORK_INTERFACE.maskLength];
+        _p2pNetworkInterface.info.gateways = [GO_NETWORK_INTERFACE.ip];
         handleP2pNetworkInterfaceStateChanged();
 
         _groupInfo.networkInterface = _p2pNetworkInterface;
 
         debug('Everything is done. Happy p2p GO~');
         onSuccess();
       });
 
@@ -1449,43 +1454,43 @@ function P2pStateMachine(aP2pCommand, aN
       debug("DHCP request success: " + JSON.stringify(dhcpData.info));
 
       // Update p2p network interface.
       let maskLength =
         netHelpers.getMaskLength(netHelpers.stringToIP(dhcpData.info.mask_str));
       if (!maskLength) {
         maskLength = 32; // max prefix for IPv4.
       }
-      _p2pNetworkInterface.state = Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED;
-      _p2pNetworkInterface.ips = [dhcpData.info.ipaddr_str];
-      _p2pNetworkInterface.prefixLengths = [maskLength];
+      _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
+      _p2pNetworkInterface.info.ips = [dhcpData.info.ipaddr_str];
+      _p2pNetworkInterface.info.prefixLengths = [maskLength];
       if (typeof dhcpData.info.dns1_str == "string" &&
           dhcpData.info.dns1_str.length) {
-        _p2pNetworkInterface.dnses.push(dhcpData.info.dns1_str);
+        _p2pNetworkInterface.info.dnses.push(dhcpData.info.dns1_str);
       }
       if (typeof dhcpData.info.dns2_str == "string" &&
           dhcpData.info.dns2_str.length) {
-        _p2pNetworkInterface.dnses.push(dhcpData.info.dns2_str);
+        _p2pNetworkInterface.info.dnses.push(dhcpData.info.dns2_str);
       }
-      _p2pNetworkInterface.gateways = [dhcpData.info.gateway_str];
+      _p2pNetworkInterface.info.gateways = [dhcpData.info.gateway_str];
       handleP2pNetworkInterfaceStateChanged();
 
       _groupInfo.networkInterface = _p2pNetworkInterface;
 
       debug('Happy p2p client~');
       onSuccess();
     });
   }
 
   function resetP2pNetworkInterface() {
-    _p2pNetworkInterface.state = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED;
-    _p2pNetworkInterface.ips = [];
-    _p2pNetworkInterface.prefixLengths = [];
-    _p2pNetworkInterface.dnses = [];
-    _p2pNetworkInterface.gateways = [];
+    _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
+    _p2pNetworkInterface.info.ips = [];
+    _p2pNetworkInterface.info.prefixLengths = [];
+    _p2pNetworkInterface.info.dnses = [];
+    _p2pNetworkInterface.info.gateways = [];
   }
 
   function registerP2pNetworkInteface() {
     if (!_p2pNetworkInterface.registered) {
       resetP2pNetworkInterface();
       gNetworkManager.registerNetworkInterface(_p2pNetworkInterface);
       _p2pNetworkInterface.registered = true;
     }
@@ -1518,17 +1523,17 @@ function P2pStateMachine(aP2pCommand, aN
     }
     if (_groupInfo.ifname !== aInfo.ifname ||
         _groupInfo.role   !== aInfo.role) {
       debug('Unmatched group info: ' + JSON.stringify(_groupInfo) +
             ' v.s. ' + JSON.stringify(aInfo));
     }
 
     // Update p2p network interface.
-    _p2pNetworkInterface.state = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED;
+    _p2pNetworkInterface.info.state = Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
     handleP2pNetworkInterfaceStateChanged();
 
     if (P2P_ROLE_GO === aInfo.role) {
       aNetUtil.stopDhcpServer(function(success) {
         debug('Stop DHCP server result: ' + success);
         aCallback(true);
       });
     } else {
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -398,18 +398,18 @@ var WifiManager = (function() {
     if (!network)
       return;
 
     // If we got here, arg network must be the currentNetwork, so we just update
     // WifiNetworkInterface correspondingly and notify NetworkManager.
     WifiNetworkInterface.httpProxyHost = network.httpProxyHost;
     WifiNetworkInterface.httpProxyPort = network.httpProxyPort;
 
-    if (WifiNetworkInterface.state ==
-        Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
+    if (WifiNetworkInterface.info.state ==
+        Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) {
       gNetworkManager.updateNetworkInterface(WifiNetworkInterface);
     }
   }
 
   var staticIpConfig = Object.create(null);
   function setStaticIpMode(network, info, callback) {
     let setNetworkKey = getNetworkKey(network);
     let curNetworkKey = null;
@@ -1009,26 +1009,27 @@ var WifiManager = (function() {
     if (enabled === manager.isWifiEnabled(manager.state)) {
       callback("no change");
       return;
     }
 
     if (enabled) {
       manager.state = "INITIALIZING";
       // Register as network interface.
-      WifiNetworkInterface.name = manager.ifname;
+      WifiNetworkInterface.info.name = manager.ifname;
       if (!WifiNetworkInterface.registered) {
         gNetworkManager.registerNetworkInterface(WifiNetworkInterface);
         WifiNetworkInterface.registered = true;
       }
-      WifiNetworkInterface.state = Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED;
-      WifiNetworkInterface.ips = [];
-      WifiNetworkInterface.prefixLengths = [];
-      WifiNetworkInterface.gateways = [];
-      WifiNetworkInterface.dnses = [];
+      WifiNetworkInterface.info.state =
+        Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
+      WifiNetworkInterface.info.ips = [];
+      WifiNetworkInterface.info.prefixLengths = [];
+      WifiNetworkInterface.info.gateways = [];
+      WifiNetworkInterface.info.dnses = [];
       gNetworkManager.updateNetworkInterface(WifiNetworkInterface);
 
       prepareForStartup(function() {
         loadDriver(function (status) {
           if (status < 0) {
             callback(status);
             manager.state = "UNINITIALIZED";
             return;
@@ -1163,18 +1164,20 @@ var WifiManager = (function() {
         function getWifiHotspotStatus() {
           wifiCommand.hostapdGetStations(function(result) {
             notify("stationinfoupdate", {station: result});
           });
         }
 
         function doStartWifiTethering() {
           cancelWaitForDriverReadyTimer();
-          WifiNetworkInterface.name = libcutils.property_get("wifi.tethering.interface", manager.ifname);
-          gTetheringService.setWifiTethering(enabled, WifiNetworkInterface,
+          WifiNetworkInterface.info.name =
+            libcutils.property_get("wifi.tethering.interface", manager.ifname);
+          gTetheringService.setWifiTethering(enabled,
+                                             WifiNetworkInterface.info.name,
                                              configuration, function(result) {
             if (result) {
               manager.tetheringState = "UNINITIALIZED";
             } else {
               manager.tetheringState = "COMPLETED";
               wifiCommand.connectToHostapd(function(result) {
                 if (result) {
                   return;
@@ -1778,65 +1781,69 @@ function isWepHexKey(s) {
 let WifiNetworkInterface = {
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterface]),
 
   registered: false,
 
   // nsINetworkInterface
 
-  NETWORK_STATE_UNKNOWN:       Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN,
-  NETWORK_STATE_CONNECTING:    Ci.nsINetworkInterface.CONNECTING,
-  NETWORK_STATE_CONNECTED:     Ci.nsINetworkInterface.CONNECTED,
-  NETWORK_STATE_DISCONNECTING: Ci.nsINetworkInterface.DISCONNECTING,
-  NETWORK_STATE_DISCONNECTED:  Ci.nsINetworkInterface.DISCONNECTED,
-
-  state: Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN,
-
-  NETWORK_TYPE_WIFI:        Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
-  NETWORK_TYPE_MOBILE:      Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
-  NETWORK_TYPE_MOBILE_MMS:  Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS,
-  NETWORK_TYPE_MOBILE_SUPL: Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL,
-
-  type: Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
-
-  name: null,
-
-  ips: [],
-
-  prefixLengths: [],
-
-  dnses: [],
-
-  gateways: [],
+  NETWORK_STATE_UNKNOWN:       Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN,
+  NETWORK_STATE_CONNECTING:    Ci.nsINetworkInfo.CONNECTING,
+  NETWORK_STATE_CONNECTED:     Ci.nsINetworkInfo.CONNECTED,
+  NETWORK_STATE_DISCONNECTING: Ci.nsINetworkInfo.DISCONNECTING,
+  NETWORK_STATE_DISCONNECTED:  Ci.nsINetworkInfo.DISCONNECTED,
+
+  NETWORK_TYPE_WIFI:        Ci.nsINetworkInfo.NETWORK_TYPE_WIFI,
+  NETWORK_TYPE_MOBILE:      Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE,
+  NETWORK_TYPE_MOBILE_MMS:  Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_MMS,
+  NETWORK_TYPE_MOBILE_SUPL: Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_SUPL,
+
+  info: {
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInfo]),
+
+    state: Ci.nsINetworkInfo.NETWORK_STATE_UNKNOWN,
+
+    type: Ci.nsINetworkInfo.NETWORK_TYPE_WIFI,
+
+    name: null,
+
+    ips: [],
+
+    prefixLengths: [],
+
+    dnses: [],
+
+    gateways: [],
+
+    getAddresses: function (ips, prefixLengths) {
+      ips.value = this.ips.slice();
+      prefixLengths.value = this.prefixLengths.slice();
+
+      return this.ips.length;
+    },
+
+    getGateways: function (count) {
+      if (count) {
+        count.value = this.gateways.length;
+      }
+      return this.gateways.slice();
+    },
+
+    getDnses: function (count) {
+      if (count) {
+        count.value = this.dnses.length;
+      }
+      return this.dnses.slice();
+    }
+  },
 
   httpProxyHost: null,
 
-  httpProxyPort: null,
-
-  getAddresses: function (ips, prefixLengths) {
-    ips.value = this.ips.slice();
-    prefixLengths.value = this.prefixLengths.slice();
-
-    return this.ips.length;
-  },
-
-  getGateways: function (count) {
-    if (count) {
-      count.value = this.gateways.length;
-    }
-    return this.gateways.slice();
-  },
-
-  getDnses: function (count) {
-    if (count) {
-      count.value = this.dnses.length;
-    }
-    return this.dnses.slice();
-  }
+  httpProxyPort: null
 };
 
 function WifiScanResult() {}
 
 // TODO Make the difference between a DOM-based network object and our
 // networks objects much clearer.
 let netToDOM;
 let netFromDOM;
@@ -2247,18 +2254,18 @@ function WifiWorker() {
         // wifi connection complete, turn on the power saving mode.
         WifiManager.setPowerSavingMode(true);
         // BSSID is read after connected, update it.
         self.currentNetwork.bssid = WifiManager.connectionInfo.bssid;
         break;
       case "DISCONNECTED":
         // wpa_supplicant may give us a "DISCONNECTED" event even if
         // we are already in "DISCONNECTED" state.
-        if ((WifiNetworkInterface.state ===
-             Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED) &&
+        if ((WifiNetworkInterface.info.state ===
+             Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED) &&
              (this.prevState === "INITIALIZING" ||
               this.prevState === "DISCONNECTED" ||
               this.prevState === "INTERFACE_DISABLED" ||
               this.prevState === "INACTIVE" ||
               this.prevState === "UNINITIALIZED")) {
           // When in disconnected mode, need to turn on wifi power saving mode.
           WifiManager.setPowerSavingMode(true);
           return;
@@ -2280,23 +2287,26 @@ function WifiWorker() {
           // We've disconnected from a network because of a call to forgetNetwork.
           // Reconnect to the next available network (if any).
           if (self._reconnectOnDisconnect) {
             self._reconnectOnDisconnect = false;
             WifiManager.reconnect(function(){});
           }
         });
 
-        WifiNetworkInterface.state =
-          Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED;
-        WifiNetworkInterface.ips = [];
-        WifiNetworkInterface.prefixLengths = [];
-        WifiNetworkInterface.gateways = [];
-        WifiNetworkInterface.dnses = [];
+        WifiNetworkInterface.info.state =
+          Ci.nsINetworkInfo.NETWORK_STATE_DISCONNECTED;
+
+        // Update network infterface first then clear properties.
         gNetworkManager.updateNetworkInterface(WifiNetworkInterface);
+        WifiNetworkInterface.info.ips = [];
+        WifiNetworkInterface.info.prefixLengths = [];
+        WifiNetworkInterface.info.gateways = [];
+        WifiNetworkInterface.info.dnses = [];
+
 
         break;
       case "WPS_TIMEOUT":
         self._fireEvent("onwpstimeout", {});
         break;
       case "WPS_FAIL":
         self._fireEvent("onwpsfail", {});
         break;
@@ -2328,28 +2338,28 @@ function WifiWorker() {
     }
 
     let netConnect = WifiManager.getHttpProxyNetwork(self.currentNetwork);
     if (netConnect) {
       WifiNetworkInterface.httpProxyHost = netConnect.httpProxyHost;
       WifiNetworkInterface.httpProxyPort = netConnect.httpProxyPort;
     }
 
-    WifiNetworkInterface.state =
-      Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED;
-    WifiNetworkInterface.ips = [this.info.ipaddr_str];
-    WifiNetworkInterface.prefixLengths = [maskLength];
-    WifiNetworkInterface.gateways = [this.info.gateway_str];
+    WifiNetworkInterface.info.state =
+      Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED;
+    WifiNetworkInterface.info.ips = [this.info.ipaddr_str];
+    WifiNetworkInterface.info.prefixLengths = [maskLength];
+    WifiNetworkInterface.info.gateways = [this.info.gateway_str];
     if (typeof this.info.dns1_str == "string" &&
         this.info.dns1_str.length) {
-      WifiNetworkInterface.dnses.push(this.info.dns1_str);
+      WifiNetworkInterface.info.dnses.push(this.info.dns1_str);
     }
     if (typeof this.info.dns2_str == "string" &&
         this.info.dns2_str.length) {
-      WifiNetworkInterface.dnses.push(this.info.dns2_str);
+      WifiNetworkInterface.info.dnses.push(this.info.dns2_str);
     }
     gNetworkManager.updateNetworkInterface(WifiNetworkInterface);
 
     self.ipAddress = this.info.ipaddr_str;
 
     // We start the connection information timer when we associate, but
     // don't have our IP address until here. Make sure that we fire a new
     // connectionInformation event with the IP address the next time the
--- a/dom/workers/WorkerThread.h
+++ b/dom/workers/WorkerThread.h
@@ -6,17 +6,17 @@
 
 #ifndef mozilla_dom_workers_WorkerThread_h__
 #define mozilla_dom_workers_WorkerThread_h__
 
 #include "mozilla/Attributes.h"
 #include "mozilla/CondVar.h"
 #include "mozilla/DebugOnly.h"
 #include "nsISupportsImpl.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "nsThread.h"
 
 class nsIRunnable;
 
 namespace mozilla {
 namespace dom {
 namespace workers {
 
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -98,42 +98,42 @@ public:
   nsCOMPtr<nsIEventTarget> mSyncEventResponseTarget;
   uint32_t mInnerEventStreamId;
   uint32_t mInnerChannelId;
   uint32_t mOutstandingSendCount;
 
   // Only touched on the worker thread.
   uint32_t mOuterEventStreamId;
   uint32_t mOuterChannelId;
+  uint32_t mOpenCount;
   uint64_t mLastLoaded;
   uint64_t mLastTotal;
   uint64_t mLastUploadLoaded;
   uint64_t mLastUploadTotal;
   bool mIsSyncXHR;
   bool mLastLengthComputable;
   bool mLastUploadLengthComputable;
   bool mSeenLoadStart;
   bool mSeenUploadLoadStart;
-  bool mOpening;
 
   // Only touched on the main thread.
   bool mUploadEventListenersAttached;
   bool mMainThreadSeenLoadStart;
   bool mInOpen;
   bool mArrayBufferResponseWasTransferred;
 
 public:
   Proxy(XMLHttpRequest* aXHRPrivate, bool aMozAnon, bool aMozSystem)
   : mWorkerPrivate(nullptr), mXMLHttpRequestPrivate(aXHRPrivate),
     mMozAnon(aMozAnon), mMozSystem(aMozSystem),
     mInnerEventStreamId(0), mInnerChannelId(0), mOutstandingSendCount(0),
-    mOuterEventStreamId(0), mOuterChannelId(0), mLastLoaded(0), mLastTotal(0),
-    mLastUploadLoaded(0), mLastUploadTotal(0), mIsSyncXHR(false),
+    mOuterEventStreamId(0), mOuterChannelId(0), mOpenCount(0), mLastLoaded(0),
+    mLastTotal(0), mLastUploadLoaded(0), mLastUploadTotal(0), mIsSyncXHR(false),
     mLastLengthComputable(false), mLastUploadLengthComputable(false),
-    mSeenLoadStart(false), mSeenUploadLoadStart(false), mOpening(false),
+    mSeenLoadStart(false), mSeenUploadLoadStart(false),
     mUploadEventListenersAttached(false), mMainThreadSeenLoadStart(false),
     mInOpen(false), mArrayBufferResponseWasTransferred(false)
   { }
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIDOMEVENTLISTENER
 
   bool
@@ -1854,17 +1854,17 @@ void
 XMLHttpRequest::SendInternal(const nsAString& aStringBody,
                              JSAutoStructuredCloneBuffer&& aBody,
                              WorkerStructuredCloneClosure& aClosure,
                              ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   // No send() calls when open is running.
-  if (mProxy->mOpening) {
+  if (mProxy->mOpenCount) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   bool hasUploadListeners = mUpload ? mUpload->HasListeners() : false;
 
   MaybePin(aRv);
   if (aRv.Failed()) {
@@ -1949,25 +1949,27 @@ XMLHttpRequest::Open(const nsACString& a
 
   mProxy->mOuterEventStreamId++;
 
   nsRefPtr<OpenRunnable> runnable =
     new OpenRunnable(mWorkerPrivate, mProxy, aMethod, aUrl, aUser, aPassword,
                      mBackgroundRequest, mWithCredentials,
                      mTimeout);
 
-  mProxy->mOpening = true;
+  ++mProxy->mOpenCount;
   if (!runnable->Dispatch(mWorkerPrivate->GetJSContext())) {
-    mProxy->mOpening = false;
-    ReleaseProxy();
+    if (!--mProxy->mOpenCount) {
+      ReleaseProxy();
+    }
+
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  mProxy->mOpening = false;
+  --mProxy->mOpenCount;
   mProxy->mIsSyncXHR = !aAsync;
 }
 
 void
 XMLHttpRequest::SetRequestHeader(const nsACString& aHeader,
                                  const nsACString& aValue, ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
--- a/gfx/2d/Quaternion.h
+++ b/gfx/2d/Quaternion.h
@@ -87,14 +87,24 @@ public:
     }
     return *this;
   }
 
   Quaternion& Invert()
   {
     return Conjugate().Normalize();
   }
+
+  Point3D RotatePoint(const Point3D& aPoint) {
+    Float uvx = Float(2.0) * (y*aPoint.z - z*aPoint.y);
+    Float uvy = Float(2.0) * (z*aPoint.x - x*aPoint.z);
+    Float uvz = Float(2.0) * (x*aPoint.y - y*aPoint.x);
+
+    return Point3D(aPoint.x + w*uvx + y*uvz - z*uvy,
+                   aPoint.y + w*uvy + z*uvx - x*uvz,
+                   aPoint.z + w*uvz + x*uvy - y*uvx);
+  }
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -380,26 +380,16 @@ public:
   /**
    * Post-rendering stuff if the rendering is done outside of this Compositor
    * e.g., by Composer2D.
    * aTransform is the transform from user space to window space.
    */
   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) = 0;
 
   /**
-   * Setup the viewport and projection matrix for rendering to a target of the
-   * given dimensions. The size and transform here will override those set in
-   * BeginFrame. BeginFrame sets a size and transform for the default render
-   * target, usually the screen. Calling this method prepares the compositor to
-   * render using a different viewport (that is, size and transform), usually
-   * associated with a new render target.
-   */
-  virtual void PrepareViewport(const gfx::IntSize& aSize) = 0;
-
-  /**
    * Whether textures created by this compositor can receive partial updates.
    */
   virtual bool SupportsPartialTextureUpdate() = 0;
 
   void SetDiagnosticTypes(DiagnosticTypes aDiagnostics)
   {
     mDiagnosticTypes = aDiagnostics;
   }
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -382,23 +382,16 @@ public:
    * NONE: No hint.
    * SCROLLABLE: This layer may represent scrollable content.
    */
   enum PaintedLayerCreationHint {
     NONE, SCROLLABLE
   };
 
   /**
-   * Returns true if aLayer is optimized for the given PaintedLayerCreationHint.
-   */
-  virtual bool IsOptimizedFor(PaintedLayer* aLayer,
-                              PaintedLayerCreationHint aCreationHint)
-  { return true; }
-
-  /**
    * CONSTRUCTION PHASE ONLY
    * Create a PaintedLayer for this manager's layer tree.
    */
   virtual already_AddRefed<PaintedLayer> CreatePaintedLayer() = 0;
   /**
    * CONSTRUCTION PHASE ONLY
    * Create a PaintedLayer for this manager's layer tree, with a creation hint
    * parameter to help optimise the type of layer created.
@@ -1669,16 +1662,30 @@ public:
    */
   void ClearExtraDumpInfo()
   {
 #ifdef MOZ_DUMP_PAINTING
      mExtraDumpInfo.Clear();
 #endif
   }
 
+  /**
+   * Replace the current effective transform with the given one,
+   * returning the old one.  This is currently added as a hack for VR
+   * rendering, and might go away if we find a better way to do this.
+   * If you think you have a need for this method, talk with
+   * vlad/mstange/mwoodrow first.
+   */
+  virtual gfx::Matrix4x4 ReplaceEffectiveTransform(const gfx::Matrix4x4& aNewEffectiveTransform) {
+    gfx::Matrix4x4 old = mEffectiveTransform;
+    mEffectiveTransform = aNewEffectiveTransform;
+    ComputeEffectiveTransformForMaskLayers(mEffectiveTransform);
+    return old;
+  }
+
 protected:
   Layer(LayerManager* aManager, void* aImplData);
 
   // Protected destructor, to discourage deletion outside of Release():
   virtual ~Layer();
 
   /**
    * We can snap layer transforms for two reasons:
@@ -1842,16 +1849,23 @@ public:
     }
     ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
   }
 
   LayerManager::PaintedLayerCreationHint GetCreationHint() const { return mCreationHint; }
 
   bool UsedForReadback() { return mUsedForReadback; }
   void SetUsedForReadback(bool aUsed) { mUsedForReadback = aUsed; }
+
+  /**
+   * Returns true if aLayer is optimized for the given PaintedLayerCreationHint.
+   */
+  virtual bool IsOptimizedFor(LayerManager::PaintedLayerCreationHint aCreationHint)
+  { return true; }
+
   /**
    * Returns the residual translation. Apply this translation when drawing
    * into the PaintedLayer so that when mEffectiveTransform is applied afterwards
    * by layer compositing, the results exactly match the "ideal transform"
    * (the product of the transform of this layer and its ancestors).
    * Returns 0,0 unless SetAllowResidualTranslation(true) has been called.
    * The residual translation components are always in the range [-0.5, 0.5).
    */
@@ -2048,16 +2062,31 @@ public:
   }
 
   /**
    * VR
    */
   void SetVRHMDInfo(gfx::VRHMDInfo* aHMD) { mHMDInfo = aHMD; }
   gfx::VRHMDInfo* GetVRHMDInfo() { return mHMDInfo; }
 
+  /**
+   * Replace the current effective transform with the given one,
+   * returning the old one.  This is currently added as a hack for VR
+   * rendering, and might go away if we find a better way to do this.
+   * If you think you have a need for this method, talk with
+   * vlad/mstange/mwoodrow first.
+   */
+  gfx::Matrix4x4 ReplaceEffectiveTransform(const gfx::Matrix4x4& aNewEffectiveTransform) override {
+    gfx::Matrix4x4 old = mEffectiveTransform;
+    mEffectiveTransform = aNewEffectiveTransform;
+    ComputeEffectiveTransformsForChildren(mEffectiveTransform);
+    ComputeEffectiveTransformForMaskLayers(mEffectiveTransform);
+    return old;
+  }
+
 protected:
   friend class ReadbackProcessor;
 
   void DidInsertChild(Layer* aLayer);
   void DidRemoveChild(Layer* aLayer);
 
   ContainerLayer(LayerManager* aManager, void* aImplData);
 
@@ -2253,16 +2282,18 @@ public:
    */
   typedef void PreTransactionCallback(void* closureData);
   void SetPreTransactionCallback(PreTransactionCallback* callback, void* closureData)
   {
     mPreTransCallback = callback;
     mPreTransCallbackData = closureData;
   }
 
+  const nsIntRect& GetBounds() const { return mBounds; }
+
 protected:
   void FirePreTransactionCallback()
   {
     if (mPreTransCallback) {
       mPreTransCallback(mPreTransCallbackData);
     }
   }
 
--- a/gfx/layers/TiledLayerBuffer.h
+++ b/gfx/layers/TiledLayerBuffer.h
@@ -145,17 +145,17 @@ public:
                 gfxPlatform::GetPlatform()->GetTileHeight())
   {}
 
   ~TiledLayerBuffer() {}
 
   gfx::IntPoint GetTileOffset(TileIntPoint aPosition) const {
     gfx::IntSize scaledTileSize = GetScaledTileSize();
     return gfx::IntPoint(aPosition.x * scaledTileSize.width,
-                         aPosition.y * scaledTileSize.height);
+                         aPosition.y * scaledTileSize.height) + mTileOrigin;
   }
 
   const TilesPlacement& GetPlacement() const { return mTiles; }
 
   const gfx::IntSize& GetTileSize() const { return mTileSize; }
 
   gfx::IntSize GetScaledTileSize() const { return RoundedToInt(gfx::Size(mTileSize) / mResolution); }
 
@@ -189,16 +189,17 @@ protected:
    * Only the region intersecting with mValidRegion should be read from a tile,
    * another other region is assumed to be uninitialized. The contents of the
    * tiles is scaled by mResolution.
    */
   nsTArray<Tile>  mRetainedTiles;
   TilesPlacement  mTiles;
   float           mResolution;
   gfx::IntSize    mTileSize;
+  gfx::IntPoint   mTileOrigin;
 };
 
 template<typename Derived, typename Tile> void
 TiledLayerBuffer<Derived, Tile>::Dump(std::stringstream& aStream,
                                       const char* aPrefix,
                                       bool aDumpHtml)
 {
   for (size_t i = 0; i < mRetainedTiles.Length(); ++i) {
--- a/gfx/layers/apz/src/Axis.cpp
+++ b/gfx/layers/apz/src/Axis.cpp
@@ -134,17 +134,17 @@ bool Axis::AdjustDisplacement(ParentLaye
     return false;
   }
   if (aForceOverscroll) {
     aOverscrollAmountOut = aDisplacement;
     aDisplacementOut = 0;
     return false;
   }
 
-  ClearOverscrollAnimationState();
+  EndOverscrollAnimation();
 
   ParentLayerCoord displacement = aDisplacement;
 
   // First consume any overscroll in the opposite direction along this axis.
   ParentLayerCoord consumedOverscroll = 0;
   if (mOverscroll > 0 && aDisplacement < 0) {
     consumedOverscroll = std::min(mOverscroll, -aDisplacement);
   } else if (mOverscroll < 0 && aDisplacement > 0) {
@@ -181,17 +181,17 @@ ParentLayerCoord Axis::ApplyResistance(P
 
 void Axis::OverscrollBy(ParentLayerCoord aOverscroll) {
   MOZ_ASSERT(CanScroll());
   // We can get some spurious calls to OverscrollBy() with near-zero values
   // due to rounding error. Ignore those (they might trip the asserts below.)
   if (FuzzyEqualsAdditive(aOverscroll.value, 0.0f, COORDINATE_EPSILON)) {
     return;
   }
-  ClearOverscrollAnimationState();
+  EndOverscrollAnimation();
   aOverscroll = ApplyResistance(aOverscroll);
   if (aOverscroll > 0) {
 #ifdef DEBUG
     if (!FuzzyEqualsCoordinate(GetCompositionEnd().value, GetPageEnd().value)) {
       nsPrintfCString message("composition end (%f) is not equal (within error) to page end (%f)\n",
                               GetCompositionEnd().value, GetPageEnd().value);
       NS_ASSERTION(false, message.get());
       MOZ_CRASH();
@@ -233,23 +233,21 @@ void Axis::StartOverscrollAnimation(floa
   MOZ_ASSERT(mFirstOverscrollAnimationSample == 0 &&
              mLastOverscrollPeak == 0 &&
              mOverscrollScale == 1);
 
   SetVelocity(aVelocity);
 }
 
 void Axis::EndOverscrollAnimation() {
-  ClearOverscrollAnimationState();
-}
-
-void Axis::ClearOverscrollAnimationState() {
+  ParentLayerCoord overscroll = GetOverscroll();
   mFirstOverscrollAnimationSample = 0;
   mLastOverscrollPeak = 0;
   mOverscrollScale = 1.0f;
+  mOverscroll = overscroll;
 }
 
 void Axis::StepOverscrollAnimation(double aStepDurationMilliseconds) {
   // Apply spring physics to the overscroll as time goes on.
   // Note: this method of sampling isn't perfectly smooth, as it assumes
   // a constant velocity over 'aDelta', instead of an accelerating velocity.
   // (The way we applying friction to flings has the same issue.)
   // Hooke's law with damping:
@@ -359,17 +357,17 @@ bool Axis::SampleOverscrollAnimation(con
   return true;
 }
 
 bool Axis::IsOverscrolled() const {
   return mOverscroll != 0.f;
 }
 
 void Axis::ClearOverscroll() {
-  ClearOverscrollAnimationState();
+  EndOverscrollAnimation();
   mOverscroll = 0;
 }
 
 ParentLayerCoord Axis::PanStart() const {
   return mStartPos;
 }
 
 ParentLayerCoord Axis::PanDistance() const {
--- a/gfx/layers/apz/src/Axis.h
+++ b/gfx/layers/apz/src/Axis.h
@@ -273,19 +273,16 @@ protected:
   nsTArray<std::pair<uint32_t, float> > mVelocityQueue;
 
   const FrameMetrics& GetFrameMetrics() const;
 
   // Adjust a requested overscroll amount for resistance, yielding a smaller
   // actual overscroll amount.
   ParentLayerCoord ApplyResistance(ParentLayerCoord aOverscroll) const;
 
-  // Clear the state associated with an overscroll animation.
-  void ClearOverscrollAnimationState();
-
   // Helper function for SampleOverscrollAnimation().
   void StepOverscrollAnimation(double aStepDurationMilliseconds);
 
   // Convert a velocity from global inches/ms into ParentLayerCoords/ms.
   float ToLocalVelocity(float aVelocityInchesPerMs) const;
 };
 
 class AxisX : public Axis {
--- a/gfx/layers/apz/src/HitTestingTreeNode.h
+++ b/gfx/layers/apz/src/HitTestingTreeNode.h
@@ -7,17 +7,17 @@
 #ifndef mozilla_layers_HitTestingTreeNode_h
 #define mozilla_layers_HitTestingTreeNode_h
 
 #include "APZUtils.h"                       // for HitTestResult
 #include "FrameMetrics.h"                   // for ScrollableLayerGuid
 #include "mozilla/gfx/Matrix.h"             // for Matrix4x4
 #include "mozilla/layers/LayersTypes.h"     // for EventRegions
 #include "mozilla/Maybe.h"                  // for Maybe
-#include "nsRefPtr.h"                       // for nsRefPtr
+#include "mozilla/nsRefPtr.h"                       // for nsRefPtr
 
 namespace mozilla {
 namespace layers {
 
 class AsyncPanZoomController;
 
 /**
  * This class represents a node in a tree that is used by the APZCTreeManager
--- a/gfx/layers/apz/util/APZEventState.h
+++ b/gfx/layers/apz/util/APZEventState.h
@@ -10,17 +10,17 @@
 
 #include "FrameMetrics.h"     // for ScrollableLayerGuid
 #include "Units.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/layers/GeckoContentController.h"  // for APZStateChange
 #include "nsCOMPtr.h"
 #include "nsISupportsImpl.h"  // for NS_INLINE_DECL_REFCOUNTING
 #include "nsIWeakReferenceUtils.h"  // for nsWeakPtr
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 template <class> class nsCOMPtr;
 class nsIDocument;
 class nsIPresShell;
 class nsIWidget;
 
 namespace mozilla {
 namespace layers {
--- a/gfx/layers/apz/util/ChromeProcessController.h
+++ b/gfx/layers/apz/util/ChromeProcessController.h
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_ChromeProcessController_h
 #define mozilla_layers_ChromeProcessController_h
 
 #include "mozilla/layers/GeckoContentController.h"
 #include "nsCOMPtr.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 class nsIDOMWindowUtils;
 class nsIDocument;
 class nsIPresShell;
 class nsIWidget;
 
 class MessageLoop;
 
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/util/DoubleTapToZoom.cpp
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; 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/. */
+
+#include "DoubleTapToZoom.h"
+
+#include <algorithm>  // for std::min, std::max
+
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/dom/Element.h"
+#include "nsCOMPtr.h"
+#include "nsIContent.h"
+#include "nsIDocument.h"
+#include "nsIDOMHTMLLIElement.h"
+#include "nsIDOMHTMLQuoteElement.h"
+#include "nsIDOMWindow.h"
+#include "nsIFrame.h"
+#include "nsIFrameInlines.h"
+#include "nsIPresShell.h"
+#include "nsLayoutUtils.h"
+#include "nsStyleConsts.h"
+
+namespace mozilla {
+namespace layers {
+
+// Returns the DOM element found at |aPoint|, interpreted as being relative to
+// the root frame of |aShell|. If the point is inside a subdocument, returns
+// an element inside the subdocument, rather than the subdocument element
+// (and does so recursively).
+// The implementation was adapted from nsDocument::ElementFromPoint(), with
+// the notable exception that we don't pass nsLayoutUtils::IGNORE_CROSS_DOC
+// to GetFrameForPoint(), so as to get the behaviour described above in the
+// presence of subdocuments.
+static already_AddRefed<dom::Element>
+ElementFromPoint(const nsCOMPtr<nsIPresShell>& aShell,
+                 const CSSPoint& aPoint)
+{
+  if (nsIFrame* rootFrame = aShell->GetRootFrame()) {
+    if (nsIFrame* frame = nsLayoutUtils::GetFrameForPoint(rootFrame,
+          CSSPoint::ToAppUnits(aPoint),
+          nsLayoutUtils::IGNORE_PAINT_SUPPRESSION |
+          nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME)) {
+      while (frame && (!frame->GetContent() || frame->GetContent()->IsInAnonymousSubtree())) {
+        frame = nsLayoutUtils::GetParentOrPlaceholderFor(frame);
+      }
+      nsIContent* content = frame->GetContent();
+      if (content && !content->IsElement()) {
+        content = content->GetParent();
+      }
+      if (content) {
+        nsCOMPtr<dom::Element> result = content->AsElement();
+        return result.forget();
+      }
+    }
+  }
+  return nullptr;
+}
+
+static bool
+ShouldZoomToElement(const nsCOMPtr<dom::Element>& aElement) {
+  if (nsIFrame* frame = aElement->GetPrimaryFrame()) {
+    if (frame->GetDisplay() == NS_STYLE_DISPLAY_INLINE) {
+      return false;
+    }
+  }
+  if (aElement->IsAnyOfHTMLElements(nsGkAtoms::li, nsGkAtoms::q)) {
+    return false;
+  }
+  return true;
+}
+
+// Calculate the bounding rect of |aElement|, relative to the origin
+// of the document associated with |aShell|.
+// |aRootScrollFrame| should be the root scroll frame of the document in
+// question.
+// The implementation is adapted from Element::GetBoundingClientRect().
+static CSSRect
+GetBoundingContentRect(const nsCOMPtr<nsIPresShell>& aShell,
+                       const nsCOMPtr<dom::Element>& aElement,
+                       const nsIScrollableFrame* aRootScrollFrame) {
+  if (nsIFrame* frame = aElement->GetPrimaryFrame()) {
+    return CSSRect::FromAppUnits(
+        nsLayoutUtils::GetAllInFlowRectsUnion(
+            frame,
+            aShell->GetRootFrame(),
+            nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS)
+      + aRootScrollFrame->GetScrollPosition());
+  }
+  return CSSRect();
+}
+
+static bool
+IsRectZoomedIn(const CSSRect& aRect, const CSSRect& aCompositedArea)
+{
+  // This functions checks to see if the area of the rect visible in the
+  // composition bounds (i.e. the overlapArea variable below) is approximately
+  // the max area of the rect we can show.
+  CSSRect overlap = aCompositedArea.Intersect(aRect);
+  float overlapArea = overlap.width * overlap.height;
+  float availHeight = std::min(aRect.width * aCompositedArea.height / aCompositedArea.width,
+                               aRect.height);
+  float showing = overlapArea / (aRect.width * availHeight);
+  float ratioW = aRect.width / aCompositedArea.width;
+  float ratioH = aRect.height / aCompositedArea.height;
+
+  return showing > 0.9 && (ratioW > 0.9 || ratioH > 0.9);
+}
+
+CSSRect
+CalculateRectToZoomTo(const nsCOMPtr<nsIDocument>& aRootContentDocument,
+                      const CSSPoint& aPoint)
+{
+  // Ensure the layout information we get is up-to-date.
+  aRootContentDocument->FlushPendingNotifications(Flush_Layout);
+
+  // An empty rect as return value is interpreted as "zoom out".
+  const CSSRect zoomOut;
+
+  nsCOMPtr<nsIPresShell> shell = aRootContentDocument->GetShell();
+  if (!shell) {
+    return zoomOut;
+  }
+
+  nsIScrollableFrame* rootScrollFrame = shell->GetRootScrollFrameAsScrollable();
+  if (!rootScrollFrame) {
+    return zoomOut;
+  }
+
+  nsCOMPtr<dom::Element> element = ElementFromPoint(shell, aPoint);
+  if (!element) {
+    return zoomOut;
+  }
+
+  while (element && !ShouldZoomToElement(element)) {
+    element = element->GetParentElement();
+  }
+
+  if (!element) {
+    return zoomOut;
+  }
+
+  FrameMetrics metrics = nsLayoutUtils::CalculateBasicFrameMetrics(rootScrollFrame);
+  CSSRect compositedArea(metrics.GetScrollOffset(), metrics.CalculateCompositedSizeInCssPixels());
+  const CSSCoord margin = 15;
+  CSSRect rect = GetBoundingContentRect(shell, element, rootScrollFrame);
+  rect = CSSRect(std::max(metrics.GetScrollableRect().x, rect.x - margin),
+                 rect.y,
+                 rect.width + 2 * margin,
+                 rect.height);
+  // Constrict the rect to the screen's right edge
+  rect.width = std::min(rect.width, metrics.GetScrollableRect().XMost() - rect.x);
+
+  // If the rect is already taking up most of the visible area and is
+  // stretching the width of the page, then we want to zoom out instead.
+  if (IsRectZoomedIn(rect, compositedArea)) {
+    return zoomOut;
+  }
+
+  CSSRect rounded(rect);
+  rounded.Round();
+
+  // If the block we're zooming to is really tall, and the user double-tapped
+  // more than a screenful of height from the top of it, then adjust the
+  // y-coordinate so that we center the actual point the user double-tapped
+  // upon. This prevents flying to the top of the page when double-tapping
+  // to zoom in (bug 761721). The 1.2 multiplier is just a little fuzz to
+  // compensate for 'rect' including horizontal margins but not vertical ones.
+  CSSCoord cssTapY = metrics.GetScrollOffset().y + aPoint.y;
+  if ((rect.height > rounded.height) && (cssTapY > rounded.y + (rounded.height * 1.2))) {
+    rounded.y = cssTapY - (rounded.height / 2);
+  }
+
+  return rounded;
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/util/DoubleTapToZoom.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; 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/. */
+
+#ifndef mozilla_layers_DoubleTapToZoom_h
+#define mozilla_layers_DoubleTapToZoom_h
+
+#include "Units.h"
+
+class nsIDocument;
+template<class T> class nsCOMPtr;
+
+namespace mozilla {
+namespace layers {
+
+/**
+ * For a double tap at |aPoint|, return the rect to which the browser
+ * should zoom in response, or an empty rect if the browser should zoom out.
+ * |aDocument| should be the root content document for the content that was
+ * tapped.
+ */
+CSSRect CalculateRectToZoomTo(const nsCOMPtr<nsIDocument>& aRootContentDocument,
+                              const CSSPoint& aPoint);
+
+}
+}
+
+#endif /* mozilla_layers_DoubleTapToZoom_h */
--- a/gfx/layers/basic/BasicCompositor.h
+++ b/gfx/layers/basic/BasicCompositor.h
@@ -105,18 +105,16 @@ public:
   virtual int32_t GetMaxTextureSize() const override;
   virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override { }
   
   virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) override {
   }
 
   virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) override { }
 
-  virtual void PrepareViewport(const gfx::IntSize& aSize) override { }
-
 #ifdef MOZ_DUMP_PAINTING
   virtual const char* Name() const override { return "Basic"; }
 #endif // MOZ_DUMP_PAINTING
 
   virtual LayersBackend GetBackendType() const override {
     return LayersBackend::LAYERS_BASIC;
   }
 
--- a/gfx/layers/client/ClientLayerManager.h
+++ b/gfx/layers/client/ClientLayerManager.h
@@ -83,18 +83,16 @@ public:
   }
   virtual void GetBackendName(nsAString& name) override;
   virtual const char* Name() const override { return "Client"; }
 
   virtual void SetRoot(Layer* aLayer) override;
 
   virtual void Mutated(Layer* aLayer) override;
 
-  virtual bool IsOptimizedFor(PaintedLayer* aLayer, PaintedLayerCreationHint aHint) override;
-
   virtual already_AddRefed<PaintedLayer> CreatePaintedLayer() override;
   virtual already_AddRefed<PaintedLayer> CreatePaintedLayerWithHint(PaintedLayerCreationHint aHint) override;
   virtual already_AddRefed<ContainerLayer> CreateContainerLayer() override;
   virtual already_AddRefed<ImageLayer> CreateImageLayer() override;
   virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() override;
   virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer() override;
   virtual already_AddRefed<ColorLayer> CreateColorLayer() override;
   virtual already_AddRefed<RefLayer> CreateRefLayer() override;
--- a/gfx/layers/client/ClientPaintedLayer.cpp
+++ b/gfx/layers/client/ClientPaintedLayer.cpp
@@ -137,47 +137,27 @@ ClientPaintedLayer::RenderLayerWithReadb
   }
 
   IntPoint origin(mVisibleRegion.GetBounds().x, mVisibleRegion.GetBounds().y);
   mContentClient->BeginPaint();
   PaintThebes();
   mContentClient->EndPaint(&readbackUpdates);
 }
 
-bool
-ClientLayerManager::IsOptimizedFor(PaintedLayer* aLayer, PaintedLayerCreationHint aHint)
-{
-#ifdef MOZ_B2G
-  // The only creation hint is whether the layer is scrollable or not, and this
-  // is only respected on B2G, where it's used to determine whether to use
-  // tiled layers or not.
-  // There are pretty nasty performance consequences for not using tiles on
-  // large, scrollable layers, so we want the layer to be recreated in this
-  // situation.
-  return aHint == aLayer->GetCreationHint();
-#else
-  return LayerManager::IsOptimizedFor(aLayer, aHint);
-#endif
-}
-
 already_AddRefed<PaintedLayer>
 ClientLayerManager::CreatePaintedLayer()
 {
   return CreatePaintedLayerWithHint(NONE);
 }
 
 already_AddRefed<PaintedLayer>
 ClientLayerManager::CreatePaintedLayerWithHint(PaintedLayerCreationHint aHint)
 {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
-  if (
-#ifdef MOZ_B2G
-      aHint == SCROLLABLE &&
-#endif
-      gfxPrefs::LayersTilesEnabled()
+  if (gfxPrefs::LayersTilesEnabled()
 #ifndef MOZ_X11
       && (AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL ||
           AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D9 ||
           AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D11)
 #endif
   ) {
     nsRefPtr<ClientTiledPaintedLayer> layer = new ClientTiledPaintedLayer(this, aHint);
     CREATE_SHADOW(Painted);
--- a/gfx/layers/client/ClientTiledPaintedLayer.cpp
+++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp
@@ -14,16 +14,17 @@
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/gfx/Rect.h"           // for Rect, RectTyped
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
 #include "mozilla/layers/LayersMessages.h"
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "LayersLogging.h"
+#include "mozilla/layers/SingleTiledContentClient.h"
 
 namespace mozilla {
 namespace layers {
 
 ClientTiledPaintedLayer::ClientTiledPaintedLayer(ClientLayerManager* const aManager,
                                                ClientLayerManager::PaintedLayerCreationHint aCreationHint)
   : PaintedLayer(aManager, static_cast<ClientLayer*>(this), aCreationHint)
   , mContentClient()
@@ -164,17 +165,18 @@ ClientTiledPaintedLayer::BeginPaint()
     GetTransformToAncestorsParentLayer(this, displayPortAncestor);
   transformDisplayPortToLayer.Invert();
 
   // Compute the critical display port that applies to this layer in the
   // LayoutDevice space of this layer, but only if there is no OMT animation
   // on this layer. If there is an OMT animation then we need to draw the whole
   // visible region of this layer as determined by layout, because we don't know
   // what parts of it might move into view in the compositor.
-  if (!hasTransformAnimation) {
+  if (!hasTransformAnimation &&
+      mContentClient->GetLowPrecisionTiledBuffer()) {
     ParentLayerRect criticalDisplayPort =
       (displayportMetrics.GetCriticalDisplayPort() * displayportMetrics.GetZoom())
       + displayportMetrics.GetCompositionBounds().TopLeft();
     mPaintData.mCriticalDisplayPort = RoundedToInt(
       ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort));
   }
   TILING_LOG("TILING %p: Critical displayport %s\n", this, Stringify(mPaintData.mCriticalDisplayPort).c_str());
 
@@ -229,16 +231,20 @@ ClientTiledPaintedLayer::IsScrollingOnCo
 
 bool
 ClientTiledPaintedLayer::UseProgressiveDraw() {
   if (!gfxPlatform::GetPlatform()->UseProgressivePaint()) {
     // pref is disabled, so never do progressive
     return false;
   }
 
+  if (!mContentClient->GetTiledBuffer()->SupportsProgressiveUpdate()) {
+    return false;
+  }
+
   if (ClientManager()->HasShadowTarget()) {
     // This condition is true when we are in a reftest scenario. We don't want
     // to draw progressively here because it can cause intermittent reftest
     // failures because the harness won't wait for all the tiles to be drawn.
     return false;
   }
 
   if (mPaintData.mCriticalDisplayPort.IsEmpty()) {
@@ -279,73 +285,73 @@ ClientTiledPaintedLayer::RenderHighPreci
   // If we have no high-precision stuff to draw, or we have started drawing low-precision
   // already, then we shouldn't do anything there.
   if (aInvalidRegion.IsEmpty() || mPaintData.mLowPrecisionPaintCount != 0) {
     return false;
   }
 
   // Only draw progressively when the resolution is unchanged
   if (UseProgressiveDraw() &&
-      mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) {
+      mContentClient->GetTiledBuffer()->GetFrameResolution() == mPaintData.mResolution) {
     // Store the old valid region, then clear it before painting.
     // We clip the old valid region to the visible region, as it only gets
     // used to decide stale content (currently valid and previously visible)
-    nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
+    nsIntRegion oldValidRegion = mContentClient->GetTiledBuffer()->GetValidRegion();
     oldValidRegion.And(oldValidRegion, aVisibleRegion);
     if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
       oldValidRegion.And(oldValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
     }
 
     TILING_LOG("TILING %p: Progressive update with old valid region %s\n", this, Stringify(oldValidRegion).c_str());
 
-    return mContentClient->mTiledBuffer.ProgressiveUpdate(mValidRegion, aInvalidRegion,
+    return mContentClient->GetTiledBuffer()->ProgressiveUpdate(mValidRegion, aInvalidRegion,
                       oldValidRegion, &mPaintData, aCallback, aCallbackData);
   }
 
   // Otherwise do a non-progressive paint
 
   mValidRegion = aVisibleRegion;
   if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
     mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
   }
 
   TILING_LOG("TILING %p: Non-progressive paint invalid region %s\n", this, Stringify(aInvalidRegion).c_str());
   TILING_LOG("TILING %p: Non-progressive paint new valid region %s\n", this, Stringify(mValidRegion).c_str());
 
-  mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
-  mContentClient->mTiledBuffer.PaintThebes(mValidRegion, aInvalidRegion, aInvalidRegion,
-                                           aCallback, aCallbackData);
+  mContentClient->GetTiledBuffer()->SetFrameResolution(mPaintData.mResolution);
+  mContentClient->GetTiledBuffer()->PaintThebes(mValidRegion, aInvalidRegion, aInvalidRegion,
+                                                aCallback, aCallbackData);
   mPaintData.mPaintFinished = true;
   return true;
 }
 
 bool
 ClientTiledPaintedLayer::RenderLowPrecision(nsIntRegion& aInvalidRegion,
                                            const nsIntRegion& aVisibleRegion,
                                            LayerManager::DrawPaintedLayerCallback aCallback,
                                            void* aCallbackData)
 {
   // Render the low precision buffer, if the visible region is larger than the
   // critical display port.
   if (!nsIntRegion(LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)).Contains(aVisibleRegion)) {
-    nsIntRegion oldValidRegion = mContentClient->mLowPrecisionTiledBuffer.GetValidRegion();
+    nsIntRegion oldValidRegion = mContentClient->GetLowPrecisionTiledBuffer()->GetValidRegion();
     oldValidRegion.And(oldValidRegion, aVisibleRegion);
 
     bool updatedBuffer = false;
 
     // If the frame resolution or format have changed, invalidate the buffer
-    if (mContentClient->mLowPrecisionTiledBuffer.GetFrameResolution() != mPaintData.mResolution ||
-        mContentClient->mLowPrecisionTiledBuffer.HasFormatChanged()) {
+    if (mContentClient->GetLowPrecisionTiledBuffer()->GetFrameResolution() != mPaintData.mResolution ||
+        mContentClient->GetLowPrecisionTiledBuffer()->HasFormatChanged()) {
       if (!mLowPrecisionValidRegion.IsEmpty()) {
         updatedBuffer = true;
       }
       oldValidRegion.SetEmpty();
       mLowPrecisionValidRegion.SetEmpty();
-      mContentClient->mLowPrecisionTiledBuffer.ResetPaintedAndValidState();
-      mContentClient->mLowPrecisionTiledBuffer.SetFrameResolution(mPaintData.mResolution);
+      mContentClient->GetLowPrecisionTiledBuffer()->ResetPaintedAndValidState();
+      mContentClient->GetLowPrecisionTiledBuffer()->SetFrameResolution(mPaintData.mResolution);
       aInvalidRegion = aVisibleRegion;
     }
 
     // Invalidate previously valid content that is no longer visible
     if (mPaintData.mLowPrecisionPaintCount == 1) {
       mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, aVisibleRegion);
     }
     mPaintData.mLowPrecisionPaintCount++;
@@ -353,29 +359,29 @@ ClientTiledPaintedLayer::RenderLowPrecis
     // Remove the valid high-precision region from the invalid low-precision
     // region. We don't want to spend time drawing things twice.
     aInvalidRegion.Sub(aInvalidRegion, mValidRegion);
 
     TILING_LOG("TILING %p: Progressive paint: low-precision invalid region is %s\n", this, Stringify(aInvalidRegion).c_str());
     TILING_LOG("TILING %p: Progressive paint: low-precision old valid region is %s\n", this, Stringify(oldValidRegion).c_str());
 
     if (!aInvalidRegion.IsEmpty()) {
-      updatedBuffer = mContentClient->mLowPrecisionTiledBuffer.ProgressiveUpdate(
+      updatedBuffer = mContentClient->GetLowPrecisionTiledBuffer()->ProgressiveUpdate(
                             mLowPrecisionValidRegion, aInvalidRegion, oldValidRegion,
                             &mPaintData, aCallback, aCallbackData);
     }
 
     TILING_LOG("TILING %p: Progressive paint: low-precision new valid region is %s\n", this, Stringify(mLowPrecisionValidRegion).c_str());
     return updatedBuffer;
   }
   if (!mLowPrecisionValidRegion.IsEmpty()) {
     TILING_LOG("TILING %p: Clearing low-precision buffer\n", this);
     // Clear the low precision tiled buffer.
     mLowPrecisionValidRegion.SetEmpty();
-    mContentClient->mLowPrecisionTiledBuffer.ResetPaintedAndValidState();
+    mContentClient->GetLowPrecisionTiledBuffer()->ResetPaintedAndValidState();
     // Return true here so we send a Painted callback after clearing the valid
     // region of the low precision buffer. This allows the shadow buffer's valid
     // region to be updated and the associated resources to be freed.
     return true;
   }
   return false;
 }
 
@@ -391,26 +397,33 @@ ClientTiledPaintedLayer::EndPaint()
 void
 ClientTiledPaintedLayer::RenderLayer()
 {
   LayerManager::DrawPaintedLayerCallback callback =
     ClientManager()->GetPaintedLayerCallback();
   void *data = ClientManager()->GetPaintedLayerCallbackData();
 
   if (!mContentClient) {
-    mContentClient = new TiledContentClient(this, ClientManager());
+#if defined(MOZ_B2G) || defined(XP_MACOSX)
+    if (mCreationHint == LayerManager::NONE) {
+      mContentClient = new SingleTiledContentClient(this, ClientManager());
+    } else
+#endif
+    {
+      mContentClient = new MultiTiledContentClient(this, ClientManager());
+    }
 
     mContentClient->Connect();
     ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
     MOZ_ASSERT(mContentClient->GetForwarder());
   }
 
-  if (mContentClient->mTiledBuffer.HasFormatChanged()) {
+  if (mContentClient->GetTiledBuffer()->HasFormatChanged()) {
     mValidRegion = nsIntRegion();
-    mContentClient->mTiledBuffer.ResetPaintedAndValidState();
+    mContentClient->GetTiledBuffer()->ResetPaintedAndValidState();
   }
 
   TILING_LOG("TILING %p: Initial visible region %s\n", this, Stringify(mVisibleRegion).c_str());
   TILING_LOG("TILING %p: Initial valid region %s\n", this, Stringify(mValidRegion).c_str());
   TILING_LOG("TILING %p: Initial low-precision valid region %s\n", this, Stringify(mLowPrecisionValidRegion).c_str());
 
   nsIntRegion neededRegion = mVisibleRegion;
 #ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
@@ -469,30 +482,30 @@ ClientTiledPaintedLayer::RenderLayer()
   } else {
     if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
       invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
     }
     TILING_LOG("TILING %p: Repeat-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
   }
 
   nsIntRegion lowPrecisionInvalidRegion;
-  if (gfxPrefs::UseLowPrecisionBuffer()) {
+  if (mContentClient->GetLowPrecisionTiledBuffer()) {
     // Calculate the invalid region for the low precision buffer. Make sure
     // to remove the valid high-precision area so we don't double-paint it.
     lowPrecisionInvalidRegion.Sub(neededRegion, mLowPrecisionValidRegion);
     lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, mValidRegion);
   }
   TILING_LOG("TILING %p: Low-precision invalid region %s\n", this, Stringify(lowPrecisionInvalidRegion).c_str());
 
   bool updatedHighPrecision = RenderHighPrecision(invalidRegion,
                                                   neededRegion,
                                                   callback, data);
   if (updatedHighPrecision) {
     ClientManager()->Hold(this);
-    mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
+    mContentClient->UpdatedBuffer(TiledContentClient::TILED_BUFFER);
 
     if (!mPaintData.mPaintFinished) {
       // There is still more high-res stuff to paint, so we're not
       // done yet. A subsequent transaction will take care of this.
       ClientManager()->SetRepeatTransaction();
       return;
     }
   }
@@ -515,31 +528,47 @@ ClientTiledPaintedLayer::RenderLayer()
     return;
   }
 
   bool updatedLowPrecision = RenderLowPrecision(lowPrecisionInvalidRegion,
                                                 neededRegion,
                                                 callback, data);
   if (updatedLowPrecision) {
     ClientManager()->Hold(this);
-    mContentClient->UseTiledLayerBuffer(TiledContentClient::LOW_PRECISION_TILED_BUFFER);
+    mContentClient->UpdatedBuffer(TiledContentClient::LOW_PRECISION_TILED_BUFFER);
 
     if (!mPaintData.mPaintFinished) {
       // There is still more low-res stuff to paint, so we're not
       // done yet. A subsequent transaction will take care of this.
       ClientManager()->SetRepeatTransaction();
       return;
     }
   }
 
   // If we get here, we've done all the high- and low-precision
   // paints we wanted to do, so we can finish the paint and chill.
   EndPaint();
 }
 
+bool
+ClientTiledPaintedLayer::IsOptimizedFor(LayerManager::PaintedLayerCreationHint aHint)
+{
+#if defined(MOZ_B2G) || defined(XP_MACOSX)
+  // The only creation hint is whether the layer is scrollable or not, and this
+  // is only respected on B2G and OSX, where it's used to determine whether to
+  // use a tiled content client or not.
+  // There are pretty nasty performance consequences for not using tiles on
+  // large, scrollable layers, so we want the layer to be recreated in this
+  // situation.
+  return aHint == GetCreationHint();
+#else
+  return true;
+#endif
+}
+
 void
 ClientTiledPaintedLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
 {
   PaintedLayer::PrintInfo(aStream, aPrefix);
   if (mContentClient) {
     aStream << "\n";
     nsAutoCString pfx(aPrefix);
     pfx += "  ";
--- a/gfx/layers/client/ClientTiledPaintedLayer.h
+++ b/gfx/layers/client/ClientTiledPaintedLayer.h
@@ -77,16 +77,18 @@ public:
    * Helper method to find the nearest ancestor layers which
    * scroll and have a displayport. The parameters are out-params
    * which hold the return values; the values passed in may be null.
    */
   void GetAncestorLayers(LayerMetricsWrapper* aOutScrollAncestor,
                          LayerMetricsWrapper* aOutDisplayPortAncestor,
                          bool* aOutHasTransformAnimation);
 
+  virtual bool IsOptimizedFor(LayerManager::PaintedLayerCreationHint aCreationHint) override;
+
 private:
   ClientLayerManager* ClientManager()
   {
     return static_cast<ClientLayerManager*>(mManager);
   }
 
   /**
    * For the initial PaintThebes of a transaction, calculates all the data
new file mode 100644
--- /dev/null
+++ b/gfx/layers/client/SingleTiledContentClient.cpp
@@ -0,0 +1,211 @@
+/* -*- Mode: C++; tab-width: 20; 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/. */
+
+#include "mozilla/layers/SingleTiledContentClient.h"
+
+namespace mozilla {
+
+using namespace gfx;
+
+namespace layers {
+
+
+SingleTiledContentClient::SingleTiledContentClient(ClientTiledPaintedLayer* aPaintedLayer,
+                                                   ClientLayerManager* aManager)
+  : TiledContentClient(aManager)
+{
+  MOZ_COUNT_CTOR(SingleTiledContentClient);
+
+  mTiledBuffer = new ClientSingleTiledLayerBuffer(aPaintedLayer, this, aManager);
+}
+
+void
+SingleTiledContentClient::ClearCachedResources()
+{
+  CompositableClient::ClearCachedResources();
+  mTiledBuffer->DiscardBuffers();
+}
+
+void
+SingleTiledContentClient::UpdatedBuffer(TiledBufferType aType)
+{
+  // Take a ReadLock on behalf of the TiledContentHost. This
+  // reference will be adopted when the descriptor is opened in
+  // TiledLayerBufferComposite.
+  mTiledBuffer->ReadLock();
+
+  mForwarder->UseTiledLayerBuffer(this, mTiledBuffer->GetSurfaceDescriptorTiles());
+  mTiledBuffer->ClearPaintedRegion();
+}
+
+ClientSingleTiledLayerBuffer::ClientSingleTiledLayerBuffer(ClientTiledPaintedLayer* aPaintedLayer,
+                                                           CompositableClient* aCompositableClient,
+                                                           ClientLayerManager* aManager)
+  : ClientTiledLayerBuffer(aPaintedLayer, aCompositableClient)
+  , mManager(aManager)
+{
+}
+
+void
+ClientSingleTiledLayerBuffer::ReadLock() {
+  if (!mTile.IsPlaceholderTile()) {
+    mTile.ReadLock();
+  }
+}
+
+void
+ClientSingleTiledLayerBuffer::ReleaseTiles()
+{
+  if (!mTile.IsPlaceholderTile()) {
+    mTile.DiscardBuffers();
+  }
+  mTile.SetTextureAllocator(nullptr);
+}
+
+void
+ClientSingleTiledLayerBuffer::DiscardBuffers()
+{
+  if (!mTile.IsPlaceholderTile()) {
+    mTile.DiscardFrontBuffer();
+    mTile.DiscardBackBuffer();
+  }
+}
+
+SurfaceDescriptorTiles
+ClientSingleTiledLayerBuffer::GetSurfaceDescriptorTiles()
+{
+  InfallibleTArray<TileDescriptor> tiles;
+
+  TileDescriptor tileDesc = mTile.GetTileDescriptor();
+  tiles.AppendElement(tileDesc);
+  mTile.mUpdateRect = IntRect();
+
+  return SurfaceDescriptorTiles(mValidRegion,
+                                tiles,
+                                mTilingOrigin,
+                                mSize,
+                                0, 0, 1, 1,
+                                1.0,
+                                mFrameResolution.xScale,
+                                mFrameResolution.yScale);
+}
+
+already_AddRefed<TextureClient>
+ClientSingleTiledLayerBuffer::GetTextureClient()
+{
+  return mCompositableClient->CreateTextureClientForDrawing(
+    gfx::ImageFormatToSurfaceFormat(mFormat), mSize, gfx::BackendType::NONE,
+    TextureFlags::IMMEDIATE_UPLOAD);
+}
+
+void
+ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
+                                          const nsIntRegion& aPaintRegion,
+                                          const nsIntRegion& aDirtyRegion,
+                                          LayerManager::DrawPaintedLayerCallback aCallback,
+                                          void* aCallbackData)
+{
+  // Compare layer visible region size to current backbuffer size, discard if not matching.
+  IntSize size = mPaintedLayer->GetVisibleRegion().GetBounds().Size();
+  IntPoint origin = mPaintedLayer->GetVisibleRegion().GetBounds().TopLeft();
+  nsIntRegion paintRegion = aPaintRegion;
+  if (mSize != size ||
+      mTilingOrigin != origin) {
+    ResetPaintedAndValidState();
+    mSize = size;
+    mTilingOrigin = origin;
+    paintRegion = aNewValidRegion;
+  }
+
+  SurfaceMode mode;
+  gfxContentType content = GetContentType(&mode);
+  mFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(content);
+
+  if (mTile.IsPlaceholderTile()) {
+    mTile.SetLayerManager(mManager);
+    mTile.SetTextureAllocator(this);
+  }
+  mTile.SetCompositableClient(mCompositableClient);
+
+  // The dirty region relative to the top-left of the tile.
+  nsIntRegion tileDirtyRegion = paintRegion.MovedBy(-mTilingOrigin);
+
+  nsIntRegion extraPainted;
+  RefPtr<TextureClient> backBufferOnWhite;
+  RefPtr<TextureClient> backBuffer =
+    mTile.GetBackBuffer(tileDirtyRegion,
+                        content, mode,
+                        extraPainted,
+                        &backBufferOnWhite);
+
+  mTile.mUpdateRect = tileDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
+
+  extraPainted.MoveBy(mTilingOrigin);
+  extraPainted.And(extraPainted, aNewValidRegion);
+  mPaintedRegion.OrWith(paintRegion);
+  mPaintedRegion.OrWith(extraPainted);
+
+  if (!backBuffer) {
+    return;
+  }
+
+  RefPtr<DrawTarget> dt = backBuffer->BorrowDrawTarget();
+  RefPtr<DrawTarget> dtOnWhite;
+  if (backBufferOnWhite) {
+    dtOnWhite = backBufferOnWhite->BorrowDrawTarget();
+  }
+
+  if (mode != SurfaceMode::SURFACE_OPAQUE) {
+    nsIntRegionRectIterator iter(tileDirtyRegion);
+    const IntRect *iterRect;
+    while ((iterRect = iter.Next())) {
+      if (dtOnWhite) {
+        dt->FillRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height),
+                     ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));
+        dtOnWhite->FillRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height),
+                            ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
+      } else {
+        dt->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
+      }
+    }
+  }
+
+  if (dtOnWhite) {
+    dt = Factory::CreateDualDrawTarget(dt, dtOnWhite);
+    dtOnWhite = nullptr;
+  }
+
+  {
+    nsRefPtr<gfxContext> ctx = new gfxContext(dt);
+    ctx->SetMatrix(ctx->CurrentMatrix().Translate(-mTilingOrigin.x, -mTilingOrigin.y));
+
+    aCallback(mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
+  }
+
+  // Mark the area we just drew into the back buffer as invalid in the front buffer as they're
+  // now out of sync.
+  mTile.mInvalidFront.OrWith(paintRegion);
+
+  // The new buffer is now validated, remove the dirty region from it.
+  mTile.mInvalidBack.SubOut(tileDirtyRegion);
+
+  dt = nullptr;
+
+  mTile.Flip();
+  UnlockTile(mTile);
+
+  if (backBuffer->HasInternalBuffer()) {
+    // If our new buffer has an internal buffer, we don't want to keep another
+    // TextureClient around unnecessarily, so discard the back-buffer.
+    mTile.DiscardBackBuffer();
+  }
+
+  mValidRegion = aNewValidRegion;
+  mLastPaintSurfaceMode = mode;
+  mLastPaintContentType = content;
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/client/SingleTiledContentClient.h
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 20; 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/. */
+
+#ifndef MOZILLA_GFX_SINGLETILEDCONTENTCLIENT_H
+#define MOZILLA_GFX_SINGLETILEDCONTENTCLIENT_H
+
+#include "TiledContentClient.h"
+
+namespace mozilla {
+namespace layers {
+
+class ClientTiledPaintedLayer;
+class ClientLayerManager;
+
+/**
+ * Provide an instance of TiledLayerBuffer backed by drawable TextureClients.
+ * This buffer provides an implementation of ValidateTile using a
+ * thebes callback and can support painting using a single paint buffer.
+ * Whether a single paint buffer is used is controlled by
+ * gfxPrefs::PerTileDrawing().
+ */
+class ClientSingleTiledLayerBuffer
+  : public ClientTiledLayerBuffer
+  , public TextureClientAllocator
+{
+  virtual ~ClientSingleTiledLayerBuffer() {}
+public:
+  ClientSingleTiledLayerBuffer(ClientTiledPaintedLayer* aPaintedLayer,
+                               CompositableClient* aCompositableClient,
+                               ClientLayerManager* aManager);
+
+  // TextureClientAllocator
+  already_AddRefed<TextureClient> GetTextureClient() override;
+  void ReturnTextureClientDeferred(TextureClient* aClient) override {}
+  void ReportClientLost() override {}
+
+  // ClientTiledLayerBuffer
+  void PaintThebes(const nsIntRegion& aNewValidRegion,
+                   const nsIntRegion& aPaintRegion,
+                   const nsIntRegion& aDirtyRegion,
+                   LayerManager::DrawPaintedLayerCallback aCallback,
+                   void* aCallbackData) override;
+ 
+  bool SupportsProgressiveUpdate() override { return false; }
+  bool ProgressiveUpdate(nsIntRegion& aValidRegion,
+                         nsIntRegion& aInvalidRegion,
+                         const nsIntRegion& aOldValidRegion,
+                         BasicTiledLayerPaintData* aPaintData,
+                         LayerManager::DrawPaintedLayerCallback aCallback,
+                         void* aCallbackData) override
+  {
+    MOZ_ASSERT(false, "ProgressiveUpdate not supported!");
+    return false;
+  }
+  
+  void ResetPaintedAndValidState() override {
+    mPaintedRegion.SetEmpty();
+    mValidRegion.SetEmpty();
+    mTile.DiscardBuffers();
+  }
+  
+  const nsIntRegion& GetValidRegion() override {
+    return mValidRegion;
+  }
+  
+  bool IsLowPrecision() const override {
+    return false;
+  }
+
+  void ReadLock();
+
+  void ReleaseTiles();
+
+  void DiscardBuffers();
+
+  SurfaceDescriptorTiles GetSurfaceDescriptorTiles();
+
+  void ClearPaintedRegion() {
+    mPaintedRegion.SetEmpty();
+  }
+
+private:
+  TileClient mTile;
+
+  ClientLayerManager* mManager;
+
+  nsIntRegion mPaintedRegion;
+  nsIntRegion mValidRegion;
+
+  /**
+   * While we're adding tiles, this is used to keep track of the position of
+   * the top-left of the top-left-most tile.  When we come to wrap the tiles in
+   * TiledDrawTarget we subtract the value of this member from each tile's
+   * offset so that all the tiles have a positive offset, then add a
+   * translation to the TiledDrawTarget to compensate.  This is important so
+   * that the mRect of the TiledDrawTarget is always at a positive x/y
+   * position, otherwise its GetSize() methods will be broken.
+   */
+  gfx::IntPoint mTilingOrigin;
+  gfx::IntSize mSize;
+  gfxImageFormat mFormat;
+};
+
+class SingleTiledContentClient : public TiledContentClient
+{
+public:
+  SingleTiledContentClient(ClientTiledPaintedLayer* aPaintedLayer,
+                           ClientLayerManager* aManager);
+
+protected:
+  ~SingleTiledContentClient()
+  {
+    MOZ_COUNT_DTOR(SingleTiledContentClient);
+
+    mDestroyed = true;
+    mTiledBuffer->ReleaseTiles();
+  }
+
+public:
+
+  virtual void ClearCachedResources() override;
+
+  virtual void UpdatedBuffer(TiledBufferType aType) override;
+
+  virtual ClientTiledLayerBuffer* GetTiledBuffer() override { return mTiledBuffer; }
+  virtual ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() override { return nullptr; }
+
+private:
+  nsRefPtr<ClientSingleTiledLayerBuffer> mTiledBuffer;
+};
+
+}
+}
+
+#endif
--- a/gfx/layers/client/TextureClientPool.h
+++ b/gfx/layers/client/TextureClientPool.h
@@ -13,50 +13,66 @@
 #include "nsITimer.h"
 #include <stack>
 
 namespace mozilla {
 namespace layers {
 
 class ISurfaceAllocator;
 
-class TextureClientPool final
+class TextureClientAllocator
+{
+protected:
+  virtual ~TextureClientAllocator() {}
+public:
+  NS_INLINE_DECL_REFCOUNTING(TextureClientAllocator)
+
+  virtual already_AddRefed<TextureClient> GetTextureClient() = 0;
+
+  /**
+   * Return a TextureClient that is not yet ready to be reused, but will be
+   * imminently.
+   */
+  virtual void ReturnTextureClientDeferred(TextureClient *aClient) = 0;
+
+  virtual void ReportClientLost() = 0;
+};
+
+class TextureClientPool final : public TextureClientAllocator
 {
   ~TextureClientPool();
 
 public:
-  NS_INLINE_DECL_REFCOUNTING(TextureClientPool)
-
   TextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
                     uint32_t aMaxTextureClients,
                     uint32_t aShrinkTimeoutMsec,
                     ISurfaceAllocator *aAllocator);
 
   /**
    * Gets an allocated TextureClient of size and format that are determined
    * by the initialisation parameters given to the pool. This will either be
    * a cached client that was returned to the pool, or a newly allocated
    * client if one isn't available.
    *
    * All clients retrieved by this method should be returned using the return
    * functions, or reported lost so that the pool can manage its size correctly.
    */
-  already_AddRefed<TextureClient> GetTextureClient();
+  already_AddRefed<TextureClient> GetTextureClient() override;
 
   /**
    * Return a TextureClient that is no longer being used and is ready for
    * immediate re-use or destruction.
    */
   void ReturnTextureClient(TextureClient *aClient);
 
   /**
    * Return a TextureClient that is not yet ready to be reused, but will be
    * imminently.
    */
-  void ReturnTextureClientDeferred(TextureClient *aClient);
+  void ReturnTextureClientDeferred(TextureClient *aClient) override;
 
   /**
    * Attempt to shrink the pool so that there are no more than
    * mMaxTextureClients clients outstanding.
    */
   void ShrinkToMaximumSize();
 
   /**
@@ -70,17 +86,17 @@ public:
    * ReturnTextureClientDeferred.
    */
   void ReturnDeferredClients();
 
   /**
    * Report that a client retrieved via GetTextureClient() has become
    * unusable, so that it will no longer be tracked.
    */
-  void ReportClientLost();
+  virtual void ReportClientLost() override;
 
   /**
    * Calling this will cause the pool to attempt to relinquish any unused
    * clients.
    */
   void Clear();
 
   gfx::SurfaceFormat GetFormat() { return mFormat; }
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -82,45 +82,48 @@ static void DrawDebugOverlay(mozilla::gf
 
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
 
 
-TiledContentClient::TiledContentClient(ClientTiledPaintedLayer* aPaintedLayer,
-                                       ClientLayerManager* aManager)
-  : CompositableClient(aManager->AsShadowForwarder())
+MultiTiledContentClient::MultiTiledContentClient(ClientTiledPaintedLayer* aPaintedLayer,
+                                                 ClientLayerManager* aManager)
+  : TiledContentClient(aManager)
 {
-  MOZ_COUNT_CTOR(TiledContentClient);
+  MOZ_COUNT_CTOR(MultiTiledContentClient);
 
-  mTiledBuffer = ClientTiledLayerBuffer(aPaintedLayer, this, aManager,
-                                        &mSharedFrameMetricsHelper);
-  mLowPrecisionTiledBuffer = ClientTiledLayerBuffer(aPaintedLayer, this, aManager,
-                                                    &mSharedFrameMetricsHelper);
+  mTiledBuffer = ClientMultiTiledLayerBuffer(aPaintedLayer, this, aManager,
+                                             &mSharedFrameMetricsHelper);
+  mLowPrecisionTiledBuffer = ClientMultiTiledLayerBuffer(aPaintedLayer, this, aManager,
+                                                         &mSharedFrameMetricsHelper);
 
   mLowPrecisionTiledBuffer.SetResolution(gfxPrefs::LowPrecisionResolution());
+  mHasLowPrecision = gfxPrefs::UseLowPrecisionBuffer();
 }
 
 void
-TiledContentClient::ClearCachedResources()
+MultiTiledContentClient::ClearCachedResources()
 {
   CompositableClient::ClearCachedResources();
   mTiledBuffer.DiscardBuffers();
   mLowPrecisionTiledBuffer.DiscardBuffers();
 }
 
 void
-TiledContentClient::UseTiledLayerBuffer(TiledBufferType aType)
+MultiTiledContentClient::UpdatedBuffer(TiledBufferType aType)
 {
-  ClientTiledLayerBuffer* buffer = aType == LOW_PRECISION_TILED_BUFFER
+  ClientMultiTiledLayerBuffer* buffer = aType == LOW_PRECISION_TILED_BUFFER
     ? &mLowPrecisionTiledBuffer
     : &mTiledBuffer;
 
+  MOZ_ASSERT(aType != LOW_PRECISION_TILED_BUFFER || mHasLowPrecision);
+
   // Take a ReadLock on behalf of the TiledContentHost. This
   // reference will be adopted when the descriptor is opened in
   // TiledLayerBufferComposite.
   buffer->ReadLock();
 
   mForwarder->UseTiledLayerBuffer(this, buffer->GetSurfaceDescriptorTiles());
   buffer->ClearPaintedRegion();
 }
@@ -278,25 +281,22 @@ SharedFrameMetricsHelper::AboutToChecker
     TILING_LOG("TILING: About to checkerboard; painted %s\n", Stringify(painted).c_str());
     TILING_LOG("TILING: About to checkerboard; compositor %s\n", Stringify(aCompositorMetrics).c_str());
     TILING_LOG("TILING: About to checkerboard; showing %s\n", Stringify(showing).c_str());
     return true;
   }
   return false;
 }
 
-ClientTiledLayerBuffer::ClientTiledLayerBuffer(ClientTiledPaintedLayer* aPaintedLayer,
-                                               CompositableClient* aCompositableClient,
-                                               ClientLayerManager* aManager,
-                                               SharedFrameMetricsHelper* aHelper)
-  : mPaintedLayer(aPaintedLayer)
-  , mCompositableClient(aCompositableClient)
+ClientMultiTiledLayerBuffer::ClientMultiTiledLayerBuffer(ClientTiledPaintedLayer* aPaintedLayer,
+                                                         CompositableClient* aCompositableClient,
+                                                         ClientLayerManager* aManager,
+                                                         SharedFrameMetricsHelper* aHelper)
+  : ClientTiledLayerBuffer(aPaintedLayer, aCompositableClient)
   , mManager(aManager)
-  , mLastPaintContentType(gfxContentType::COLOR)
-  , mLastPaintSurfaceMode(SurfaceMode::SURFACE_OPAQUE)
   , mSharedFrameMetricsHelper(aHelper)
 {
 }
 
 bool
 ClientTiledLayerBuffer::HasFormatChanged() const
 {
   SurfaceMode mode;
@@ -323,17 +323,17 @@ ClientTiledLayerBuffer::GetContentType(S
         !gfxPrefs::TiledDrawTargetEnabled()) {
       mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
     } else {
       content = gfxContentType::COLOR;
     }
 #endif
   } else if (mode == SurfaceMode::SURFACE_OPAQUE) {
 #if defined(MOZ_GFX_OPTIMIZE_MOBILE) || defined(MOZ_WIDGET_GONK)
-    if (mResolution != 1) {
+    if (IsLowPrecision()) {
       // If we're in low-res mode, drawing can sample from outside the visible
       // region. Make sure that we only sample transparency if that happens.
       mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
       content = gfxContentType::COLOR_ALPHA;
     }
 #else
     if (mPaintedLayer->MayResample()) {
       mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
@@ -518,16 +518,17 @@ TileClient::TileClient(const TileClient&
   mBackLock = o.mBackLock;
   mFrontLock = o.mFrontLock;
   mCompositableClient = o.mCompositableClient;
   mUpdateRect = o.mUpdateRect;
 #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
   mLastUpdate = o.mLastUpdate;
 #endif
   mManager = o.mManager;
+  mAllocator = o.mAllocator;
   mInvalidFront = o.mInvalidFront;
   mInvalidBack = o.mInvalidBack;
 }
 
 TileClient&
 TileClient::operator=(const TileClient& o)
 {
   if (this == &o) return *this;
@@ -538,16 +539,17 @@ TileClient::operator=(const TileClient& 
   mBackLock = o.mBackLock;
   mFrontLock = o.mFrontLock;
   mCompositableClient = o.mCompositableClient;
   mUpdateRect = o.mUpdateRect;
 #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
   mLastUpdate = o.mLastUpdate;
 #endif
   mManager = o.mManager;
+  mAllocator = o.mAllocator;
   mInvalidFront = o.mInvalidFront;
   mInvalidBack = o.mInvalidBack;
   return *this;
 }
 
 void
 TileClient::Dump(std::stringstream& aStream)
 {
@@ -675,19 +677,19 @@ TileClient::DiscardFrontBuffer()
       tracker->SetTextureClient(mFrontBuffer);
       mFrontBuffer->SetRemoveFromCompositableWaiter(waiter);
       // RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
       mManager->AsShadowForwarder()->RemoveTextureFromCompositableAsync(tracker,
                                                                         mCompositableClient,
                                                                         mFrontBuffer);
     }
 #endif
-    mManager->ReturnTextureClientDeferred(*mFrontBuffer);
+    mAllocator->ReturnTextureClientDeferred(mFrontBuffer);
     if (mFrontBufferOnWhite) {
-      mManager->ReturnTextureClientDeferred(*mFrontBufferOnWhite);
+      mAllocator->ReturnTextureClientDeferred(mFrontBufferOnWhite);
     }
     mFrontLock->ReadUnlock();
     if (mFrontBuffer->IsLocked()) {
       mFrontBuffer->Unlock();
     }
     if (mFrontBufferOnWhite && mFrontBufferOnWhite->IsLocked()) {
       mFrontBufferOnWhite->Unlock();
     }
@@ -701,24 +703,24 @@ void
 TileClient::DiscardBackBuffer()
 {
   if (mBackBuffer) {
     MOZ_ASSERT(mBackLock);
     if (!mBackBuffer->ImplementsLocking() && mBackLock->GetReadCount() > 1) {
       // Our current back-buffer is still locked by the compositor. This can occur
       // when the client is producing faster than the compositor can consume. In
       // this case we just want to drop it and not return it to the pool.
-     mManager->ReportClientLost(*mBackBuffer);
+     mAllocator->ReportClientLost();
      if (mBackBufferOnWhite) {
-       mManager->ReportClientLost(*mBackBufferOnWhite);
+       mAllocator->ReportClientLost();
      }
     } else {
-      mManager->ReturnTextureClientDeferred(*mBackBuffer);
+      mAllocator->ReturnTextureClientDeferred(mBackBuffer);
       if (mBackBufferOnWhite) {
-        mManager->ReturnTextureClientDeferred(*mBackBufferOnWhite);
+        mAllocator->ReturnTextureClientDeferred(mBackBufferOnWhite);
       }
     }
     mBackLock->ReadUnlock();
     if (mBackBuffer->IsLocked()) {
       mBackBuffer->Unlock();
     }
     if (mBackBufferOnWhite && mBackBufferOnWhite->IsLocked()) {
       mBackBufferOnWhite->Unlock();
@@ -728,83 +730,114 @@ TileClient::DiscardBackBuffer()
     mBackLock = nullptr;
   }
 }
 
 TextureClient*
 TileClient::GetBackBuffer(const nsIntRegion& aDirtyRegion,
                           gfxContentType aContent,
                           SurfaceMode aMode,
-                          bool *aCreatedTextureClient,
                           nsIntRegion& aAddPaintedRegion,
                           RefPtr<TextureClient>* aBackBufferOnWhite)
 {
   // Try to re-use the front-buffer if possible
+  bool createdTextureClient = false;
   if (mFrontBuffer &&
       mFrontBuffer->HasInternalBuffer() &&
       mFrontLock->GetReadCount() == 1 &&
       !(aMode == SurfaceMode::SURFACE_COMPONENT_ALPHA && !mFrontBufferOnWhite)) {
     // If we had a backbuffer we no longer care about it since we'll
     // re-use the front buffer.
     DiscardBackBuffer();
     Flip();
-    *aBackBufferOnWhite = mBackBufferOnWhite;
-    return mBackBuffer;
-  }
+  } else {
+    if (!mBackBuffer ||
+        mBackLock->GetReadCount() > 1) {
+
+      if (mBackLock) {
+        // Before we Replacing the lock by another one we need to unlock it!
+        mBackLock->ReadUnlock();
+      }
 
-  if (!mBackBuffer ||
-      mBackLock->GetReadCount() > 1) {
+      if (mBackBuffer) {
+        // Our current back-buffer is still locked by the compositor. This can occur
+        // when the client is producing faster than the compositor can consume. In
+        // this case we just want to drop it and not return it to the pool.
+        mAllocator->ReportClientLost();
+      }
+      if (mBackBufferOnWhite) {
+        mAllocator->ReportClientLost();
+        mBackBufferOnWhite = nullptr;
+      }
 
-    if (mBackLock) {
-      // Before we Replacing the lock by another one we need to unlock it!
-      mBackLock->ReadUnlock();
-    }
+      mBackBuffer.Set(this, mAllocator->GetTextureClient());
+      if (!mBackBuffer) {
+        gfxCriticalError() << "[Tiling:Client] Failed to allocate a TextureClient";
+        return nullptr;
+      }
 
-    if (mBackBuffer) {
-      // Our current back-buffer is still locked by the compositor. This can occur
-      // when the client is producing faster than the compositor can consume. In
-      // this case we just want to drop it and not return it to the pool.
-      mManager->ReportClientLost(*mBackBuffer);
-    }
-    if (mBackBufferOnWhite) {
-      mManager->ReportClientLost(*mBackBufferOnWhite);
-      mBackBufferOnWhite = nullptr;
+      if (aMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
+        mBackBufferOnWhite = mAllocator->GetTextureClient();
+        if (!mBackBufferOnWhite) {
+          mBackBuffer.Set(this, nullptr);
+          gfxCriticalError() << "[Tiling:Client] Failed to allocate a TextureClient";
+          return nullptr;
+        }
+      }
+
+      // Create a lock for our newly created back-buffer.
+      if (mManager->AsShadowForwarder()->IsSameProcess()) {
+        // If our compositor is in the same process, we can save some cycles by not
+        // using shared memory.
+        mBackLock = new gfxMemorySharedReadLock();
+      } else {
+        mBackLock = new gfxShmSharedReadLock(mManager->AsShadowForwarder());
+      }
+
+      MOZ_ASSERT(mBackLock->IsValid());
+
+      createdTextureClient = true;
+      mInvalidBack = IntRect(0, 0, mBackBuffer->GetSize().width, mBackBuffer->GetSize().height);
     }
 
-    TextureClientPool *pool =
-      mManager->GetTexturePool(gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aContent));
-    mBackBuffer.Set(this, pool->GetTextureClient());
-    if (!mBackBuffer) {
+    ValidateBackBufferFromFront(aDirtyRegion, aAddPaintedRegion);
+  }
+
+  if (!mBackBuffer->IsLocked()) {
+    if (!mBackBuffer->Lock(OpenMode::OPEN_READ_WRITE)) {
+      gfxCriticalError() << "[Tiling:Client] Failed to lock a tile";
+      DiscardBackBuffer();
+      DiscardFrontBuffer();
       return nullptr;
     }
-
-    if (aMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
-      mBackBufferOnWhite = pool->GetTextureClient();
-      if (!mBackBufferOnWhite) {
-        mBackBuffer.Set(this, nullptr);
-        return nullptr;
-      }
-    }
+  }
 
-    // Create a lock for our newly created back-buffer.
-    if (mManager->AsShadowForwarder()->IsSameProcess()) {
-      // If our compositor is in the same process, we can save some cycles by not
-      // using shared memory.
-      mBackLock = new gfxMemorySharedReadLock();
-    } else {
-      mBackLock = new gfxShmSharedReadLock(mManager->AsShadowForwarder());
+  if (mBackBufferOnWhite && !mBackBufferOnWhite->IsLocked()) {
+    if (!mBackBufferOnWhite->Lock(OpenMode::OPEN_READ_WRITE)) {
+      gfxCriticalError() << "[Tiling:Client] Failed to lock a tile";
+      DiscardBackBuffer();
+      DiscardFrontBuffer();
+      return nullptr;
     }
-
-    MOZ_ASSERT(mBackLock->IsValid());
-
-    *aCreatedTextureClient = true;
-    mInvalidBack = IntRect(0, 0, mBackBuffer->GetSize().width, mBackBuffer->GetSize().height);
   }
 
-  ValidateBackBufferFromFront(aDirtyRegion, aAddPaintedRegion);
+  if (createdTextureClient) {
+    if (!mCompositableClient->AddTextureClient(mBackBuffer)) {
+      gfxCriticalError() << "[Tiling:Client] Failed to connect a TextureClient (a)";
+      DiscardFrontBuffer();
+      DiscardBackBuffer();
+      return nullptr;
+    }
+    if (mBackBufferOnWhite && !mCompositableClient->AddTextureClient(mBackBufferOnWhite)) {
+      gfxCriticalError() << "[Tiling:Client] Failed to connect a TextureClient (b)";
+      DiscardFrontBuffer();
+      DiscardBackBuffer();
+      return nullptr;
+    }
+  }
 
   *aBackBufferOnWhite = mBackBufferOnWhite;
   return mBackBuffer;
 }
 
 TileDescriptor
 TileClient::GetTileDescriptor()
 {
@@ -829,62 +862,63 @@ TileClient::GetTileDescriptor()
     return TexturedTileDescriptor(nullptr, mFrontBuffer->GetIPDLActor(),
                                   mFrontBufferOnWhite ? MaybeTexture(mFrontBufferOnWhite->GetIPDLActor()) : MaybeTexture(null_t()),
                                   mUpdateRect,
                                   TileLock(lock->GetShmemSection()));
   }
 }
 
 void
-ClientTiledLayerBuffer::ReadLock() {
+ClientMultiTiledLayerBuffer::ReadLock() {
   for (TileClient& tile : mRetainedTiles) {
     if (!tile.IsPlaceholderTile()) {
       tile.ReadLock();
     }
   }
 }
 
 void
-ClientTiledLayerBuffer::DiscardBuffers()
+ClientMultiTiledLayerBuffer::DiscardBuffers()
 {
   for (TileClient& tile : mRetainedTiles) {
     tile.DiscardBuffers();
   }
 }
 
 SurfaceDescriptorTiles
-ClientTiledLayerBuffer::GetSurfaceDescriptorTiles()
+ClientMultiTiledLayerBuffer::GetSurfaceDescriptorTiles()
 {
   InfallibleTArray<TileDescriptor> tiles;
 
   for (TileClient& tile : mRetainedTiles) {
     TileDescriptor tileDesc;
     if (tile.IsPlaceholderTile()) {
       tileDesc = PlaceholderTileDescriptor();
     } else {
       tileDesc = tile.GetTileDescriptor();
     }
     tiles.AppendElement(tileDesc);
     // Reset the update rect
     tile.mUpdateRect = IntRect();
   }
   return SurfaceDescriptorTiles(mValidRegion,
                                 tiles,
+                                mTileOrigin, mTileSize,
                                 mTiles.mFirst.x, mTiles.mFirst.y,
                                 mTiles.mSize.width, mTiles.mSize.height,
                                 mResolution, mFrameResolution.xScale,
                                 mFrameResolution.yScale);
 }
 
 void
-ClientTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
-                                   const nsIntRegion& aPaintRegion,
-                                   const nsIntRegion& aDirtyRegion,
-                                   LayerManager::DrawPaintedLayerCallback aCallback,
-                                   void* aCallbackData)
+ClientMultiTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
+                                         const nsIntRegion& aPaintRegion,
+                                         const nsIntRegion& aDirtyRegion,
+                                         LayerManager::DrawPaintedLayerCallback aCallback,
+                                         void* aCallbackData)
 {
   TILING_LOG("TILING %p: PaintThebes painting region %s\n", mPaintedLayer, Stringify(aPaintRegion).c_str());
   TILING_LOG("TILING %p: PaintThebes new valid region %s\n", mPaintedLayer, Stringify(aNewValidRegion).c_str());
 
   mCallback = aCallback;
   mCallbackData = aCallbackData;
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
@@ -894,17 +928,17 @@ ClientTiledLayerBuffer::PaintThebes(cons
   // If this region is empty XMost() - 1 will give us a negative value.
   NS_ASSERTION(!aPaintRegion.GetBounds().IsEmpty(), "Empty paint region\n");
 
   if (!gfxPrefs::TiledDrawTargetEnabled()) {
     nsRefPtr<gfxContext> ctxt;
 
     const IntRect bounds = aPaintRegion.GetBounds();
     {
-      PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesSingleBufferAlloc",
+      PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferAlloc",
         js::ProfileEntry::Category::GRAPHICS);
 
       mSinglePaintDrawTarget =
         gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
           gfx::IntSize(ceilf(bounds.width * mResolution),
                        ceilf(bounds.height * mResolution)),
           gfxPlatform::GetPlatform()->Optimal2DFormatForContent(
             GetContentType()));
@@ -922,17 +956,17 @@ ClientTiledLayerBuffer::PaintThebes(cons
       ctxt->CurrentMatrix().Scale(mResolution, mResolution).
                             Translate(-bounds.x, -bounds.y));
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
     if (PR_IntervalNow() - start > 3) {
       printf_stderr("Slow alloc %i\n", PR_IntervalNow() - start);
     }
     start = PR_IntervalNow();
 #endif
-    PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesSingleBufferDraw",
+    PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferDraw",
       js::ProfileEntry::Category::GRAPHICS);
 
     mCallback(mPaintedLayer, ctxt, aPaintRegion, aDirtyRegion,
               DrawRegionClip::NONE, nsIntRegion(), mCallbackData);
   }
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   if (PR_IntervalNow() - start > 30) {
@@ -944,17 +978,17 @@ ClientTiledLayerBuffer::PaintThebes(cons
       for (const IntRect* rect = it.Next(); rect != nullptr; rect = it.Next()) {
         printf_stderr(" rect %i, %i, %i, %i\n", rect->x, rect->y, rect->width, rect->height);
       }
     }
   }
   start = PR_IntervalNow();
 #endif
 
-  PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesUpdate",
+  PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesUpdate",
     js::ProfileEntry::Category::GRAPHICS);
 
   mNewValidRegion = aNewValidRegion;
   Update(aNewValidRegion, aPaintRegion, aDirtyRegion);
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   if (PR_IntervalNow() - start > 10) {
     const IntRect bounds = aPaintRegion.GetBounds();
@@ -1063,19 +1097,19 @@ ClientTiledLayerBuffer::UnlockTile(TileC
   if (aTile.mBackBuffer && aTile.mBackBuffer->IsLocked()) {
     aTile.mBackBuffer->Unlock();
   }
   if (aTile.mBackBufferOnWhite && aTile.mBackBufferOnWhite->IsLocked()) {
     aTile.mBackBufferOnWhite->Unlock();
   }
 }
 
-void ClientTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
-                                    const nsIntRegion& aPaintRegion,
-                                    const nsIntRegion& aDirtyRegion)
+void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
+                                         const nsIntRegion& aPaintRegion,
+                                         const nsIntRegion& aDirtyRegion)
 {
   const IntSize scaledTileSize = GetScaledTileSize();
   const gfx::IntRect newBounds = newValidRegion.GetBounds();
 
   const TilesPlacement oldTiles = mTiles;
   const TilesPlacement newTiles(floor_div(newBounds.x, scaledTileSize.width),
                           floor_div(newBounds.y, scaledTileSize.height),
                           floor_div(GetTileStart(newBounds.x, scaledTileSize.width)
@@ -1182,94 +1216,64 @@ void ClientTiledLayerBuffer::Update(cons
   }
 
   mTiles = newTiles;
   mValidRegion = newValidRegion;
   mPaintedRegion.OrWith(aPaintRegion);
 }
 
 bool
-ClientTiledLayerBuffer::ValidateTile(TileClient& aTile,
-                                    const nsIntPoint& aTileOrigin,
-                                    const nsIntRegion& aDirtyRegion)
+ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
+                                          const nsIntPoint& aTileOrigin,
+                                          const nsIntRegion& aDirtyRegion)
 {
-  PROFILER_LABEL("ClientTiledLayerBuffer", "ValidateTile",
+  PROFILER_LABEL("ClientMultiTiledLayerBuffer", "ValidateTile",
     js::ProfileEntry::Category::GRAPHICS);
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   if (aDirtyRegion.IsComplex()) {
     printf_stderr("Complex region\n");
   }
 #endif
 
+  SurfaceMode mode;
+  gfxContentType content = GetContentType(&mode);
+
   if (aTile.IsPlaceholderTile()) {
     aTile.SetLayerManager(mManager);
+    aTile.SetTextureAllocator(mManager->GetTexturePool(
+      gfxPlatform::GetPlatform()->Optimal2DFormatForContent(content)));
   }
   aTile.SetCompositableClient(mCompositableClient);
 
-  bool createdTextureClient = false;
   nsIntRegion offsetScaledDirtyRegion = aDirtyRegion.MovedBy(-aTileOrigin);
   offsetScaledDirtyRegion.ScaleRoundOut(mResolution, mResolution);
 
   bool usingTiledDrawTarget = gfxPrefs::TiledDrawTargetEnabled();
   MOZ_ASSERT(usingTiledDrawTarget || !!mSinglePaintDrawTarget);
 
-  SurfaceMode mode;
-  gfxContentType content = GetContentType(&mode);
   nsIntRegion extraPainted;
   RefPtr<TextureClient> backBufferOnWhite;
   RefPtr<TextureClient> backBuffer =
     aTile.GetBackBuffer(offsetScaledDirtyRegion,
                         content, mode,
-                        &createdTextureClient, extraPainted,
+                        extraPainted,
                         &backBufferOnWhite);
 
   aTile.mUpdateRect = offsetScaledDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
 
   extraPainted.MoveBy(aTileOrigin);
   extraPainted.And(extraPainted, mNewValidRegion);
   mPaintedRegion.Or(mPaintedRegion, extraPainted);
 
   if (!backBuffer) {
-    gfxCriticalError() << "[Tiling:Client] Failed to allocate a TextureClient";
-    aTile.DiscardBuffers();
     return false;
   }
 
-  // the back buffer may have been already locked in ValidateBackBufferFromFront
-  if (!backBuffer->IsLocked()) {
-    if (!backBuffer->Lock(OpenMode::OPEN_READ_WRITE)) {
-      gfxCriticalError() << "[Tiling:Client] Failed to lock a tile";
-      aTile.DiscardBuffers();
-      return false;
-    }
-  }
-
-  if (backBufferOnWhite && !backBufferOnWhite->IsLocked()) {
-    if (!backBufferOnWhite->Lock(OpenMode::OPEN_READ_WRITE)) {
-      gfxCriticalError() << "[Tiling:Client] Failed to lock a tile";
-      aTile.DiscardBuffers();
-      return false;
-    }
-  }
-
   if (usingTiledDrawTarget) {
-    if (createdTextureClient) {
-      if (!mCompositableClient->AddTextureClient(backBuffer)) {
-        gfxCriticalError() << "[Tiling:Client] Failed to connect a TextureClient (a)";
-        aTile.DiscardBuffers();
-        return false;
-      }
-      if (backBufferOnWhite && !mCompositableClient->AddTextureClient(backBufferOnWhite)) {
-        gfxCriticalError() << "[Tiling:Client] Failed to connect a TextureClient (b)";
-        aTile.DiscardBuffers();
-        return false;
-      }
-    }
-
     gfx::Tile moz2DTile;
     RefPtr<DrawTarget> dt = backBuffer->BorrowDrawTarget();
     RefPtr<DrawTarget> dtOnWhite;
     if (backBufferOnWhite) {
       dtOnWhite = backBufferOnWhite->BorrowDrawTarget();
       moz2DTile.mDrawTarget = Factory::CreateDualDrawTarget(dt, dtOnWhite);
     } else {
       moz2DTile.mDrawTarget = dt;
@@ -1365,24 +1369,16 @@ ClientTiledLayerBuffer::ValidateTile(Til
     IntRect(aTileOrigin.x, aTileOrigin.y,
               GetScaledTileSize().width, GetScaledTileSize().height);
   // Intersect this area with the portion that's invalid.
   tileRegion.SubOut(GetValidRegion());
   tileRegion.SubOut(aDirtyRegion); // Has now been validated
 
   backBuffer->SetWaste(tileRegion.Area() * mResolution * mResolution);
 
-  if (createdTextureClient) {
-    if (!mCompositableClient->AddTextureClient(backBuffer)) {
-      gfxCriticalError() << "[Tiling:Client] Failed to connect a TextureClient (c)";
-      aTile.DiscardBuffers();
-      return false;
-    }
-  }
-
   aTile.Flip();
 
   // Note, we don't call UpdatedTexture. The Updated function is called manually
   // by the TiledContentHost before composition.
 
   if (backBuffer->HasInternalBuffer()) {
     // If our new buffer has an internal buffer, we don't want to keep another
     // TextureClient around unnecessarily, so discard the back-buffer.
@@ -1408,21 +1404,21 @@ GetCompositorSideCompositionBounds(const
                                    const ViewTransform& aAPZTransform)
 {
   Matrix4x4 transform = aTransformToCompBounds * Matrix4x4(aAPZTransform);
   return TransformTo<LayerPixel>(transform.Inverse(),
             aScrollAncestor.Metrics().GetCompositionBounds());
 }
 
 bool
-ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
-                                                       const nsIntRegion& aOldValidRegion,
-                                                       nsIntRegion& aRegionToPaint,
-                                                       BasicTiledLayerPaintData* aPaintData,
-                                                       bool aIsRepeated)
+ClientMultiTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
+                                                            const nsIntRegion& aOldValidRegion,
+                                                            nsIntRegion& aRegionToPaint,
+                                                            BasicTiledLayerPaintData* aPaintData,
+                                                            bool aIsRepeated)
 {
   aRegionToPaint = aInvalidRegion;
 
   // If the composition bounds rect is empty, we can't make any sensible
   // decision about how to update coherently. In this case, just update
   // everything in one transaction.
   if (aPaintData->mCompositionBounds.IsEmpty()) {
     aPaintData->mPaintFinished = true;
@@ -1475,17 +1471,17 @@ ClientTiledLayerBuffer::ComputeProgressi
   TILING_LOG("TILING %p: Progressive update view transform %s zoom %f abort %d\n",
       mPaintedLayer, ToString(viewTransform.mTranslation).c_str(), viewTransform.mScale.scale, abortPaint);
 
   if (abortPaint) {
     // We ignore if front-end wants to abort if this is the first,
     // non-low-precision paint, as in that situation, we're about to override
     // front-end's page/viewport metrics.
     if (!aPaintData->mFirstPaint || drawingLowPrecision) {
-      PROFILER_LABEL("ClientTiledLayerBuffer", "ComputeProgressiveUpdateRegion",
+      PROFILER_LABEL("ClientMultiTiledLayerBuffer", "ComputeProgressiveUpdateRegion",
         js::ProfileEntry::Category::GRAPHICS);
 
       aRegionToPaint.SetEmpty();
       return aIsRepeated;
     }
   }
 
   LayerRect transformedCompositionBounds =
@@ -1601,22 +1597,22 @@ ClientTiledLayerBuffer::ComputeProgressi
   // We're not repeating painting and we've not requested a repeat transaction,
   // so the paint is finished. If there's still a separate low precision
   // paint to do, it will get marked as unfinished later.
   aPaintData->mPaintFinished = true;
   return false;
 }
 
 bool
-ClientTiledLayerBuffer::ProgressiveUpdate(nsIntRegion& aValidRegion,
-                                         nsIntRegion& aInvalidRegion,
-                                         const nsIntRegion& aOldValidRegion,
-                                         BasicTiledLayerPaintData* aPaintData,
-                                         LayerManager::DrawPaintedLayerCallback aCallback,
-                                         void* aCallbackData)
+ClientMultiTiledLayerBuffer::ProgressiveUpdate(nsIntRegion& aValidRegion,
+                                               nsIntRegion& aInvalidRegion,
+                                               const nsIntRegion& aOldValidRegion,
+                                               BasicTiledLayerPaintData* aPaintData,
+                                               LayerManager::DrawPaintedLayerCallback aCallback,
+                                               void* aCallbackData)
 {
   TILING_LOG("TILING %p: Progressive update valid region %s\n", mPaintedLayer, Stringify(aValidRegion).c_str());
   TILING_LOG("TILING %p: Progressive update invalid region %s\n", mPaintedLayer, Stringify(aInvalidRegion).c_str());
   TILING_LOG("TILING %p: Progressive update old valid region %s\n", mPaintedLayer, Stringify(aOldValidRegion).c_str());
 
   bool repeat = false;
   bool isBufferChanged = false;
   do {
@@ -1672,16 +1668,16 @@ TiledContentClient::PrintInfo(std::strin
     pfx += "  ";
 
     Dump(aStream, pfx.get(), false);
   }
 }
 
 void
 TiledContentClient::Dump(std::stringstream& aStream,
-                       const char* aPrefix,
-                       bool aDumpHtml)
+                         const char* aPrefix,
+                         bool aDumpHtml)
 {
-  mTiledBuffer.Dump(aStream, aPrefix, aDumpHtml);
+  GetTiledBuffer()->Dump(aStream, aPrefix, aDumpHtml);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/client/TiledContentClient.h
+++ b/gfx/layers/client/TiledContentClient.h
@@ -169,16 +169,20 @@ struct TileClient
   {
     return mFrontBuffer != o.mFrontBuffer;
   }
 
   void SetLayerManager(ClientLayerManager *aManager)
   {
     mManager = aManager;
   }
+  void SetTextureAllocator(TextureClientAllocator* aAllocator)
+  {
+    mAllocator = aAllocator;
+  }
 
   void SetCompositableClient(CompositableClient* aCompositableClient)
   {
     mCompositableClient = aCompositableClient;
   }
 
   bool IsPlaceholderTile() const
   {
@@ -235,17 +239,16 @@ struct TileClient
   * If getting the back buffer required copying pixels from the front buffer
   * then the copied region is stored in aAddPaintedRegion so the host side
   * knows to upload it.
   *
   * If nullptr is returned, aTextureClientOnWhite is undefined.
   */
   TextureClient* GetBackBuffer(const nsIntRegion& aDirtyRegion,
                                gfxContentType aContent, SurfaceMode aMode,
-                               bool *aCreatedTextureClient,
                                nsIntRegion& aAddPaintedRegion,
                                RefPtr<TextureClient>* aTextureClientOnWhite);
 
   void DiscardFrontBuffer();
 
   void DiscardBackBuffer();
 
   /* We wrap the back buffer in a class that disallows assignment
@@ -264,16 +267,17 @@ struct TileClient
       RefPtr<TextureClient> mBuffer;
   } mBackBuffer;
   RefPtr<TextureClient> mBackBufferOnWhite;
   RefPtr<TextureClient> mFrontBuffer;
   RefPtr<TextureClient> mFrontBufferOnWhite;
   RefPtr<gfxSharedReadLock> mBackLock;
   RefPtr<gfxSharedReadLock> mFrontLock;
   RefPtr<ClientLayerManager> mManager;
+  RefPtr<TextureClientAllocator> mAllocator;
   gfx::IntRect mUpdateRect;
   CompositableClient* mCompositableClient;
 #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
   TimeStamp        mLastUpdate;
 #endif
   nsIntRegion mInvalidFront;
   nsIntRegion mInvalidBack;
   nsExpirationState mExpirationState;
@@ -385,108 +389,160 @@ private:
 /**
  * Provide an instance of TiledLayerBuffer backed by drawable TextureClients.
  * This buffer provides an implementation of ValidateTile using a
  * thebes callback and can support painting using a single paint buffer.
  * Whether a single paint buffer is used is controlled by
  * gfxPrefs::PerTileDrawing().
  */
 class ClientTiledLayerBuffer
-  : public TiledLayerBuffer<ClientTiledLayerBuffer, TileClient>
 {
-  friend class TiledLayerBuffer<ClientTiledLayerBuffer, TileClient>;
-
 public:
   ClientTiledLayerBuffer(ClientTiledPaintedLayer* aPaintedLayer,
-                         CompositableClient* aCompositableClient,
-                         ClientLayerManager* aManager,
-                         SharedFrameMetricsHelper* aHelper);
-  ClientTiledLayerBuffer()
-    : mPaintedLayer(nullptr)
-    , mCompositableClient(nullptr)
+                         CompositableClient* aCompositableClient)
+    : mPaintedLayer(aPaintedLayer)
+    , mCompositableClient(aCompositableClient)
+    , mLastPaintContentType(gfxContentType::COLOR)
+    , mLastPaintSurfaceMode(SurfaceMode::SURFACE_OPAQUE)
+  {}
+
+  virtual void PaintThebes(const nsIntRegion& aNewValidRegion,
+                   const nsIntRegion& aPaintRegion,
+                   const nsIntRegion& aDirtyRegion,
+                   LayerManager::DrawPaintedLayerCallback aCallback,
+                   void* aCallbackData) = 0;
+
+  virtual bool SupportsProgressiveUpdate() = 0;
+  virtual bool ProgressiveUpdate(nsIntRegion& aValidRegion,
+                         nsIntRegion& aInvalidRegion,
+                         const nsIntRegion& aOldValidRegion,
+                         BasicTiledLayerPaintData* aPaintData,
+                         LayerManager::DrawPaintedLayerCallback aCallback,
+                         void* aCallbackData) = 0;
+  virtual void ResetPaintedAndValidState() = 0;
+
+  virtual const nsIntRegion& GetValidRegion() = 0;
+
+  virtual bool IsLowPrecision() const = 0;
+
+  virtual void Dump(std::stringstream& aStream,
+                    const char* aPrefix,
+                    bool aDumpHtml) {}
+
+  const CSSToParentLayerScale2D& GetFrameResolution() { return mFrameResolution; }
+  void SetFrameResolution(const CSSToParentLayerScale2D& aResolution) { mFrameResolution = aResolution; }
+
+  bool HasFormatChanged() const;
+
+protected:
+  void UnlockTile(TileClient& aTile);
+  gfxContentType GetContentType(SurfaceMode* aMode = nullptr) const;
+
+  ClientTiledPaintedLayer* mPaintedLayer;
+  CompositableClient* mCompositableClient;
+
+  gfxContentType mLastPaintContentType;
+  SurfaceMode mLastPaintSurfaceMode;
+  CSSToParentLayerScale2D mFrameResolution;
+};
+
+class ClientMultiTiledLayerBuffer
+  : public TiledLayerBuffer<ClientMultiTiledLayerBuffer, TileClient>
+  , public ClientTiledLayerBuffer
+{
+  friend class TiledLayerBuffer<ClientMultiTiledLayerBuffer, TileClient>;
+public:
+  ClientMultiTiledLayerBuffer(ClientTiledPaintedLayer* aPaintedLayer,
+                              CompositableClient* aCompositableClient,
+                              ClientLayerManager* aManager,
+                              SharedFrameMetricsHelper* aHelper);
+  ClientMultiTiledLayerBuffer()
+    : ClientTiledLayerBuffer(nullptr, nullptr)
     , mManager(nullptr)
     , mCallback(nullptr)
     , mCallbackData(nullptr)
-    , mLastPaintContentType(gfxContentType::COLOR)
-    , mLastPaintSurfaceMode(SurfaceMode::SURFACE_OPAQUE)
     , mSharedFrameMetricsHelper(nullptr)
     , mTilingOrigin(std::numeric_limits<int32_t>::max(),
                     std::numeric_limits<int32_t>::max())
   {}
 
   void PaintThebes(const nsIntRegion& aNewValidRegion,
                    const nsIntRegion& aPaintRegion,
                    const nsIntRegion& aDirtyRegion,
                    LayerManager::DrawPaintedLayerCallback aCallback,
-                   void* aCallbackData);
-
-  void Update(const nsIntRegion& aNewValidRegion,
-              const nsIntRegion& aPaintRegion,
-              const nsIntRegion& aDirtyRegion);
-
-  void ReadLock();
+                   void* aCallbackData) override;
 
-  void DiscardBuffers();
-
-  const CSSToParentLayerScale2D& GetFrameResolution() { return mFrameResolution; }
-
-  void SetFrameResolution(const CSSToParentLayerScale2D& aResolution) { mFrameResolution = aResolution; }
-
-  bool HasFormatChanged() const;
-
+  virtual bool SupportsProgressiveUpdate() override { return true; }
   /**
    * Performs a progressive update of a given tiled buffer.
    * See ComputeProgressiveUpdateRegion below for parameter documentation.
    */
   bool ProgressiveUpdate(nsIntRegion& aValidRegion,
                          nsIntRegion& aInvalidRegion,
                          const nsIntRegion& aOldValidRegion,
                          BasicTiledLayerPaintData* aPaintData,
                          LayerManager::DrawPaintedLayerCallback aCallback,
-                         void* aCallbackData);
+                         void* aCallbackData) override;
+  
+  void ResetPaintedAndValidState() override {
+    mPaintedRegion.SetEmpty();
+    mValidRegion.SetEmpty();
+    mTiles.mSize.width = 0;
+    mTiles.mSize.height = 0;
+    DiscardBuffers();
+    mRetainedTiles.Clear();
+  }
+
+
+  const nsIntRegion& GetValidRegion() override {
+    return TiledLayerBuffer::GetValidRegion();
+  }
+
+  bool IsLowPrecision() const override {
+    return TiledLayerBuffer::IsLowPrecision();
+  }
+
+  void Dump(std::stringstream& aStream,
+            const char* aPrefix,
+            bool aDumpHtml) override {
+    TiledLayerBuffer::Dump(aStream, aPrefix, aDumpHtml);
+  }
+
+  void ReadLock();
+
+  void Release();
+
+  void DiscardBuffers();
 
   SurfaceDescriptorTiles GetSurfaceDescriptorTiles();
 
   void SetResolution(float aResolution) {
     if (mResolution == aResolution) {
       return;
     }
 
     Update(nsIntRegion(), nsIntRegion(), nsIntRegion());
     mResolution = aResolution;
   }
 
-  void ResetPaintedAndValidState() {
-    mPaintedRegion.SetEmpty();
-    mValidRegion.SetEmpty();
-    mTiles.mSize.width = 0;
-    mTiles.mSize.height = 0;
-    DiscardBuffers();
-    mRetainedTiles.Clear();
-  }
-
 protected:
   bool ValidateTile(TileClient& aTile,
                     const nsIntPoint& aTileRect,
                     const nsIntRegion& dirtyRect);
-
-  void UnlockTile(TileClient& aTile);
+  
+  void Update(const nsIntRegion& aNewValidRegion,
+              const nsIntRegion& aPaintRegion,
+              const nsIntRegion& aDirtyRegion);
 
   TileClient GetPlaceholderTile() const { return TileClient(); }
 
 private:
-  gfxContentType GetContentType(SurfaceMode* aMode = nullptr) const;
-  ClientTiledPaintedLayer* mPaintedLayer;
-  CompositableClient* mCompositableClient;
   ClientLayerManager* mManager;
   LayerManager::DrawPaintedLayerCallback mCallback;
   void* mCallbackData;
-  CSSToParentLayerScale2D mFrameResolution;
-  gfxContentType mLastPaintContentType;
-  SurfaceMode mLastPaintSurfaceMode;
 
   // The region that will be made valid during Update(). Once Update() is
   // completed then this is identical to mValidRegion.
   nsIntRegion mNewValidRegion;
 
   // The DrawTarget we use when UseSinglePaintBuffer() above is true.
   RefPtr<gfx::DrawTarget>       mSinglePaintDrawTarget;
   nsIntPoint                    mSinglePaintBufferOffset;
@@ -524,58 +580,83 @@ private:
                                       const nsIntRegion& aOldValidRegion,
                                       nsIntRegion& aRegionToPaint,
                                       BasicTiledLayerPaintData* aPaintData,
                                       bool aIsRepeated);
 };
 
 class TiledContentClient : public CompositableClient
 {
-  // XXX: for now the layer which owns us interacts directly with our buffers.
-  // We should have a content client for each tiled buffer which manages its
-  // own valid region, resolution, etc. Then we could have a much cleaner
-  // interface and tidy up BasicTiledPaintedLayer::PaintThebes (bug 862547).
-  friend class ClientTiledPaintedLayer;
-
 public:
-  TiledContentClient(ClientTiledPaintedLayer* aPaintedLayer,
-                     ClientLayerManager* aManager);
+  TiledContentClient(ClientLayerManager* aManager)
+    : CompositableClient(aManager->AsShadowForwarder())
+  {}
 
 protected:
   ~TiledContentClient()
-  {
-    MOZ_COUNT_DTOR(TiledContentClient);
+  {}
 
-    mDestroyed = true;
-    mTiledBuffer.DiscardBuffers();
-    mLowPrecisionTiledBuffer.DiscardBuffers();
-  }
-
+public:
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
 
   virtual void Dump(std::stringstream& aStream,
                     const char* aPrefix="",
                     bool aDumpHtml=false);
 
-public:
   virtual TextureInfo GetTextureInfo() const override
   {
     return TextureInfo(CompositableType::CONTENT_TILED);
   }
 
-  virtual void ClearCachedResources() override;
+
+  virtual ClientTiledLayerBuffer* GetTiledBuffer() = 0;
+  virtual ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() = 0;
 
   enum TiledBufferType {
     TILED_BUFFER,
     LOW_PRECISION_TILED_BUFFER
   };
-  void UseTiledLayerBuffer(TiledBufferType aType);
+  virtual void UpdatedBuffer(TiledBufferType aType) = 0;
+};
+
+/**
+ * An implementation of TiledContentClient that supports
+ * multiple tiles and a low precision buffer.
+ */
+class MultiTiledContentClient : public TiledContentClient
+{
+public:
+  MultiTiledContentClient(ClientTiledPaintedLayer* aPaintedLayer,
+                          ClientLayerManager* aManager);
+
+protected:
+  ~MultiTiledContentClient()
+  {
+    MOZ_COUNT_DTOR(MultiTiledContentClient);
+ 
+    mDestroyed = true;
+    mTiledBuffer.DiscardBuffers();
+    mLowPrecisionTiledBuffer.DiscardBuffers();
+  }
+
+public:
+  void ClearCachedResources() override;
+  void UpdatedBuffer(TiledBufferType aType) override;
+
+  ClientTiledLayerBuffer* GetTiledBuffer() override { return &mTiledBuffer; }
+  ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() override {
+    if (mHasLowPrecision) {
+      return &mLowPrecisionTiledBuffer;
+    }
+    return nullptr;
+  }
 
 private:
   SharedFrameMetricsHelper mSharedFrameMetricsHelper;
-  ClientTiledLayerBuffer mTiledBuffer;
-  ClientTiledLayerBuffer mLowPrecisionTiledBuffer;
+  ClientMultiTiledLayerBuffer mTiledBuffer;
+  ClientMultiTiledLayerBuffer mLowPrecisionTiledBuffer;
+  bool mHasLowPrecision;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -6,16 +6,17 @@
 
 #include "mozilla/layers/AsyncCompositionManager.h"
 #include <stdint.h>                     // for uint32_t
 #include "apz/src/AsyncPanZoomController.h"
 #include "FrameMetrics.h"               // for FrameMetrics
 #include "LayerManagerComposite.h"      // for LayerManagerComposite, etc
 #include "Layers.h"                     // for Layer, ContainerLayer, etc
 #include "gfxPoint.h"                   // for gfxPoint, gfxSize
+#include "gfxPrefs.h"                   // for gfxPrefs
 #include "mozilla/StyleAnimationValue.h" // for StyleAnimationValue, etc
 #include "mozilla/WidgetUtils.h"        // for ComputeTransformForRotation
 #include "mozilla/dom/KeyframeEffect.h" // for KeyframeEffectReadOnly
 #include "mozilla/gfx/BaseRect.h"       // for BaseRect
 #include "mozilla/gfx/Point.h"          // for RoundedToInt, PointTyped
 #include "mozilla/gfx/Rect.h"           // for RoundedToInt, RectTyped
 #include "mozilla/gfx/ScaleFactor.h"    // for ScaleFactor
 #include "mozilla/layers/Compositor.h"  // for Compositor
@@ -27,16 +28,17 @@
 #include "nsDisplayList.h"              // for nsDisplayTransform, etc
 #include "nsMathUtils.h"                // for NS_round
 #include "nsPoint.h"                    // for nsPoint
 #include "nsRect.h"                     // for mozilla::gfx::IntRect
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl, etc
 #include "nsTArrayForwardDeclare.h"     // for InfallibleTArray
 #include "UnitTransforms.h"             // for TransformTo
+#include "gfxPrefs.h"
 #if defined(MOZ_WIDGET_ANDROID)
 # include <android/log.h>
 # include "AndroidBridge.h"
 #endif
 #include "GeckoProfiler.h"
 #include "FrameUniformityData.h"
 
 struct nsCSSValueSharedList;
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -11,17 +11,17 @@
 #include "mozilla/Attributes.h"         // for final, etc
 #include "mozilla/RefPtr.h"             // for RefCounted
 #include "mozilla/TimeStamp.h"          // for TimeStamp
 #include "mozilla/dom/ScreenOrientation.h"  // for ScreenOrientation
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/layers/FrameUniformityData.h" // For FrameUniformityData
 #include "mozilla/layers/LayersMessages.h"  // for TargetConfig
-#include "nsRefPtr.h"                   // for nsRefPtr
+#include "mozilla/nsRefPtr.h"                   // for nsRefPtr
 #include "nsISupportsImpl.h"            // for LayerManager::AddRef, etc
 
 namespace mozilla {
 namespace layers {
 
 class AsyncPanZoomController;
 class Layer;
 class LayerManagerComposite;
--- a/gfx/layers/composite/CanvasLayerComposite.cpp
+++ b/gfx/layers/composite/CanvasLayerComposite.cpp
@@ -10,17 +10,17 @@
 #include "gfxUtils.h"                   // for gfxUtils, etc
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/Effects.h"     // for EffectChain
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAString.h"
-#include "nsRefPtr.h"                   // for nsRefPtr
+#include "mozilla/nsRefPtr.h"                   // for nsRefPtr
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsString.h"                   // for nsAutoCString
 #include "gfxVR.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -9,17 +9,17 @@
 #include "ContentHost.h"                // for ContentHostDoubleBuffered, etc
 #include "Effects.h"                    // for EffectMask, Effect, etc
 #include "gfxUtils.h"
 #include "ImageHost.h"                  // for ImageHostBuffered, etc
 #include "TiledContentHost.h"           // for TiledContentHost
 #include "mozilla/layers/ImageContainerParent.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureHost.h"  // for TextureHost, etc
-#include "nsRefPtr.h"                   // for nsRefPtr
+#include "mozilla/nsRefPtr.h"                   // for nsRefPtr
 #include "nsDebug.h"                    // for NS_WARNING
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "mozilla/layers/PCompositableParent.h"
 
 namespace mozilla {
 
 using namespace gfx;
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -19,32 +19,37 @@
 #include "mozilla/gfx/Rect.h"           // for IntRect, Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor, etc
 #include "mozilla/layers/CompositorTypes.h"  // for DiagnosticFlags::CONTAINER
 #include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
 #include "mozilla/layers/TextureHost.h"  // for CompositingRenderTarget
 #include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
 #include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
 #include "mozilla/mozalloc.h"           // for operator delete, etc
-#include "nsRefPtr.h"                   // for nsRefPtr
+#include "mozilla/nsRefPtr.h"                   // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTArray.h"                   // for nsAutoTArray
 #include "TextRenderer.h"               // for TextRenderer
 #include <vector>
 #include "GeckoProfiler.h"              // for GeckoProfiler
 #ifdef MOZ_ENABLE_PROFILER_SPS
 #include "ProfilerMarkers.h"            // for ProfilerMarkers
 #endif
 
 #define CULLING_LOG(...)
 // #define CULLING_LOG(...) printf_stderr("CULLING: " __VA_ARGS__)
 
+#define DUMP(...) do { if (getenv("DUMP_DEBUG")) { printf_stderr(__VA_ARGS__); } } while(0)
+#define XYWH(k)  (k).x, (k).y, (k).width, (k).height
+#define XY(k)    (k).x, (k).y
+#define WH(k)    (k).width, (k).height
+
 namespace mozilla {
 namespace layers {
 
 using namespace gfx;
 
 static bool
 LayerHasCheckerboardingAPZC(Layer* aLayer, gfxRGBA* aOutColor)
 {
@@ -136,100 +141,180 @@ ContainerRenderVR(ContainerT* aContainer
                   gfx::VRHMDInfo* aHMD)
 {
   RefPtr<CompositingRenderTarget> surface;
 
   Compositor* compositor = aManager->GetCompositor();
 
   RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget();
 
-  gfx::IntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
-
   float opacity = aContainer->GetEffectiveOpacity();
 
-  gfx::IntRect surfaceRect = gfx::IntRect(visibleRect.x, visibleRect.y,
-                                          visibleRect.width, visibleRect.height);
-  // we're about to create a framebuffer backed by textures to use as an intermediate
-  // surface. What to do if its size (as given by framebufferRect) would exceed the
-  // maximum texture size supported by the GL? The present code chooses the compromise
-  // of just clamping the framebuffer's size to the max supported size.
-  // This gives us a lower resolution rendering of the intermediate surface (children layers).
-  // See bug 827170 for a discussion.
+  // The size of each individual eye surface
+  gfx::IntSize eyeResolution = aHMD->SuggestedEyeResolution();
+  gfx::IntRect eyeRect[2];
+  eyeRect[0] = gfx::IntRect(0, 0, eyeResolution.width, eyeResolution.height);
+  eyeRect[1] = gfx::IntRect(eyeResolution.width, 0, eyeResolution.width, eyeResolution.height);
+
+  // The intermediate surface size; we're going to assume that we're not going to run
+  // into max texture size limits
+  gfx::IntRect surfaceRect = gfx::IntRect(0, 0, eyeResolution.width * 2, eyeResolution.height);
+
   int32_t maxTextureSize = compositor->GetMaxTextureSize();
   surfaceRect.width = std::min(maxTextureSize, surfaceRect.width);
   surfaceRect.height = std::min(maxTextureSize, surfaceRect.height);
 
-  // use NONE here, because we draw black to clear below
-  surface = compositor->CreateRenderTarget(surfaceRect, INIT_MODE_NONE);
-  if (!surface) {
-    return;
+  gfx::VRHMDRenderingSupport *vrRendering = aHMD->GetRenderingSupport();
+  if (PR_GetEnv("NO_VR_RENDERING")) vrRendering = nullptr;
+  if (vrRendering) {
+    if (!aContainer->mVRRenderTargetSet || aContainer->mVRRenderTargetSet->size != surfaceRect.Size()) {
+      aContainer->mVRRenderTargetSet = vrRendering->CreateRenderTargetSet(compositor, surfaceRect.Size());
+    }
+
+    surface = aContainer->mVRRenderTargetSet->GetNextRenderTarget();
+    if (!surface) {
+      NS_WARNING("GetNextRenderTarget failed");
+      return;
+    }
+  } else {
+    surface = compositor->CreateRenderTarget(surfaceRect, INIT_MODE_CLEAR);
+    if (!surface) {
+      return;
+    }
   }
 
+  gfx::IntRect rtBounds = previousTarget->GetRect();
+  DUMP("eyeResolution: %d %d targetRT: %d %d %d %d\n", WH(eyeResolution), XYWH(rtBounds));
+
   compositor->SetRenderTarget(surface);
 
   nsAutoTArray<Layer*, 12> children;
   aContainer->SortChildrenBy3DZOrder(children);
 
-  /**
-   * Render this container's contents.
-   */
-  gfx::IntRect surfaceClipRect(0, 0, surfaceRect.width, surfaceRect.height);
-  RenderTargetIntRect rtClipRect(0, 0, surfaceRect.width, surfaceRect.height);
+  gfx::Matrix4x4 origTransform = aContainer->GetEffectiveTransform();
+
   for (uint32_t i = 0; i < children.Length(); i++) {
     LayerComposite* layerToRender = static_cast<LayerComposite*>(children.ElementAt(i)->ImplData());
     Layer* layer = layerToRender->GetLayer();
+    uint32_t contentFlags = layer->GetContentFlags();
 
     if (layer->GetEffectiveVisibleRegion().IsEmpty() &&
         !layer->AsContainerLayer()) {
       continue;
     }
 
-    RenderTargetIntRect clipRect = layer->CalculateScissorRect(rtClipRect);
-    if (clipRect.IsEmpty()) {
-      continue;
+    // We flip between pre-rendered and Gecko-rendered VR based on whether
+    // the child layer of this VR container layer has PRESERVE_3D or not.
+    if ((contentFlags & Layer::CONTENT_PRESERVE_3D) == 0) {
+      // This layer is native VR
+      DUMP("%p Switching to pre-rendered VR\n", aContainer);
+
+      // XXX we still need depth test here, but we have no way of preserving
+      // depth anyway in native VR layers until we have a way to save them
+      // from WebGL (and maybe depth video?)
+      compositor->SetRenderTarget(surface);
+      aContainer->ReplaceEffectiveTransform(origTransform);
+      
+      // If this native-VR child layer does not have sizes that match
+      // the eye resolution (that is, returned by the recommended
+      // render rect from the HMD device), then we need to scale it
+      // up/down.
+      nsIntRect layerBounds;
+      // XXX this is a hack! Canvas layers aren't reporting the
+      // proper bounds here (visible region bounds are 0,0,0,0)
+      // and I'm not sure if this is the bounds we want anyway.
+      if (layer->GetType() == Layer::TYPE_CANVAS) {
+        layerBounds = static_cast<CanvasLayer*>(layer)->GetBounds();
+      } else {
+        layerBounds = layer->GetEffectiveVisibleRegion().GetBounds();
+      }
+      DUMP("  layer %p [type %d] bounds [%d %d %d %d] surfaceRect [%d %d %d %d]\n", layer, (int) layer->GetType(),
+           XYWH(layerBounds), XYWH(surfaceRect));
+      
+      const gfx::Matrix4x4 childTransform = layer->GetEffectiveTransform();
+      bool restoreTransform = false;
+      if ((layerBounds.width != 0 && layerBounds.height != 0) &&
+          (layerBounds.width != surfaceRect.width ||
+           layerBounds.height != surfaceRect.height))
+      {
+        DUMP("  layer %p doesn't match, prescaling by %f %f\n", layer,
+             surfaceRect.width / float(layerBounds.width),
+             surfaceRect.height / float(layerBounds.height));
+        gfx::Matrix4x4 scaledChildTransform(childTransform);
+        scaledChildTransform.PreScale(surfaceRect.width / float(layerBounds.width),
+                                      surfaceRect.height / float(layerBounds.height),
+                                      1.0f);
+
+        layer->ReplaceEffectiveTransform(scaledChildTransform);
+        restoreTransform = true;
+      }
+
+      // XXX these are both clip rects, which end up as scissor rects in the compositor.  So we just
+      // pass the full target surface rect here.
+      layerToRender->Prepare(RenderTargetIntRect(surfaceRect.x, surfaceRect.y,
+                                                 surfaceRect.width, surfaceRect.height));
+      layerToRender->RenderLayer(surfaceRect);
+
+      if (restoreTransform) {
+        layer->ReplaceEffectiveTransform(childTransform);
+      }
+    } else {
+      // Gecko-rendered CSS VR -- not supported yet, so just don't render this layer!
     }
-
-    layerToRender->Prepare(rtClipRect);
-    layerToRender->RenderLayer(surfaceClipRect);
   }
 
-  // Unbind the current surface and rebind the previous one.
-#ifdef MOZ_DUMP_PAINTING
-  if (gfxUtils::sDumpPainting) {
-    RefPtr<gfx::DataSourceSurface> surf = surface->Dump(aManager->GetCompositor());
-    if (surf) {
-      WriteSnapshotToDumpFile(aContainer, surf);
+  DUMP(" -- ContainerRenderVR [%p] after child layers\n", aContainer);
+
+  // Now put back the original transfom on this container
+  aContainer->ReplaceEffectiveTransform(origTransform);
+
+  // then bind the original target and draw with distortion
+  compositor->SetRenderTarget(previousTarget);
+
+  if (vrRendering) {
+    vrRendering->SubmitFrame(aContainer->mVRRenderTargetSet);
+    DUMP("<<< ContainerRenderVR [used vrRendering] [%p]\n", aContainer);
+    if (!gfxPrefs::VRMirrorTextures()) {
+      return;
     }
   }
-#endif
 
-  compositor->SetRenderTarget(previousTarget);
-
-  gfx::Rect rect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height);
+  gfx::Rect rect(surfaceRect.x, surfaceRect.y, surfaceRect.width, surfaceRect.height);
   gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
 
   // The VR geometry may not cover the entire area; we need to fill with a solid color
   // first.
   // XXX should DrawQuad handle this on its own?  Is there a time where we wouldn't want
   // to do this? (e.g. something like Cardboard would not require distortion so will fill
   // the entire rect)
   EffectChain solidEffect(aContainer);
   solidEffect.mPrimaryEffect = new EffectSolidColor(Color(0.0, 0.0, 0.0, 1.0));
-  aManager->GetCompositor()->DrawQuad(rect, clipRect, solidEffect, opacity,
-                                      aContainer->GetEffectiveTransform());
+  aManager->GetCompositor()->DrawQuad(rect, rect, solidEffect, 1.0, gfx::Matrix4x4());
 
   // draw the temporary surface with VR distortion to the original destination
   EffectChain vrEffect(aContainer);
-  vrEffect.mPrimaryEffect = new EffectVRDistortion(aHMD, surface);
+  bool skipDistortion = vrRendering || PR_GetEnv("MOZ_GFX_VR_NO_DISTORTION");
+  if (skipDistortion) {
+    vrEffect.mPrimaryEffect = new EffectRenderTarget(surface);
+  } else {
+    vrEffect.mPrimaryEffect = new EffectVRDistortion(aHMD, surface);
+  }
+
+  gfx::Matrix4x4 scaleTransform = aContainer->GetEffectiveTransform();
+  scaleTransform.PreScale(rtBounds.width / float(surfaceRect.width),
+                          rtBounds.height / float(surfaceRect.height),
+                          1.0f);
 
   // XXX we shouldn't use visibleRect here -- the VR distortion needs to know the
   // full rect, not just the visible one.  Luckily, right now, VR distortion is only
   // rendered when the element is fullscreen, so the visibleRect will be right anyway.
   aManager->GetCompositor()->DrawQuad(rect, clipRect, vrEffect, opacity,
-                                      aContainer->GetEffectiveTransform());
+                                      scaleTransform);
+
+  DUMP("<<< ContainerRenderVR [%p]\n", aContainer);
 }
 
 /* all of the prepared data that we need in RenderLayer() */
 struct PreparedData
 {
   RefPtr<CompositingRenderTarget> mTmpTarget;
   nsAutoTArray<PreparedLayer, 12> mLayers;
   bool mNeedsSurfaceCopy;
--- a/gfx/layers/composite/ContainerLayerComposite.h
+++ b/gfx/layers/composite/ContainerLayerComposite.h
@@ -6,16 +6,17 @@
 #ifndef GFX_ContainerLayerComposite_H
 #define GFX_ContainerLayerComposite_H
 
 #include "Layers.h"                     // for Layer (ptr only), etc
 #include "mozilla/Attributes.h"         // for override
 #include "mozilla/UniquePtr.h"          // for UniquePtr
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/gfx/Rect.h"
+#include "gfxVR.h"
 
 namespace mozilla {
 namespace layers {
 
 class CompositableHost;
 class CompositingRenderTarget;
 struct PreparedData;
 
@@ -110,16 +111,17 @@ public:
     }
     return mPostYScale;
   }
 
   virtual const char* Name() const override { return "ContainerLayerComposite"; }
   UniquePtr<PreparedData> mPrepared;
 
   RefPtr<CompositingRenderTarget> mLastIntermediateSurface;
+  RefPtr<gfx::VRHMDRenderingSupport::RenderTargetSet> mVRRenderTargetSet;
 };
 
 class RefLayerComposite : public RefLayer,
                           public LayerComposite
 {
   template<class ContainerT>
   friend void ContainerPrepare(ContainerT* aContainer,
                                LayerManagerComposite* aManager,
@@ -175,14 +177,15 @@ public:
   virtual LayerComposite* AsLayerComposite() override { return this; }
 
   // ref layers don't use a compositable
   CompositableHost* GetCompositableHost() override { return nullptr; }
 
   virtual const char* Name() const override { return "RefLayerComposite"; }
   UniquePtr<PreparedData> mPrepared;
   RefPtr<CompositingRenderTarget> mLastIntermediateSurface;
+  nsRefPtr<gfx::VRHMDRenderingSupport::RenderTargetSet> mVRRenderTargetSet;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif /* GFX_ContainerLayerComposite_H */
--- a/gfx/layers/composite/FrameUniformityData.h
+++ b/gfx/layers/composite/FrameUniformityData.h
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_FrameUniformityData_h_
 #define mozilla_layers_FrameUniformityData_h_
 
 #include "ipc/IPCMessageUtils.h"
 #include "js/TypeDecls.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 namespace mozilla {
 namespace layers {
 class Layer;
 
 class FrameUniformityData {
   friend struct IPC::ParamTraits<FrameUniformityData>;
 
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -13,17 +13,17 @@
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for IntSize, Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/Effects.h"     // for EffectChain
 #include "mozilla/layers/TextureHost.h"  // for TextureHost, etc
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAString.h"
-#include "nsRefPtr.h"                   // for nsRefPtr
+#include "mozilla/nsRefPtr.h"                   // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsString.h"                   // for nsAutoCString
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -39,17 +39,17 @@
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
 #include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
 #include "mozilla/layers/LayersTypes.h"  // for etc
 #include "ipc/CompositorBench.h"        // for CompositorBench
 #include "ipc/ShadowLayerUtils.h"
 #include "mozilla/mozalloc.h"           // for operator new, etc
 #include "nsAppRunner.h"
-#include "nsRefPtr.h"                   // for nsRefPtr
+#include "mozilla/nsRefPtr.h"                   // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_WARNING, NS_RUNTIMEABORT, etc
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "nsIWidget.h"                  // for nsIWidget
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for mozilla::gfx::IntRect
 #include "nsRegion.h"                   // for nsIntRegion, etc
 #ifdef MOZ_WIDGET_ANDROID
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -20,17 +20,17 @@
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/Effects.h"     // for EffectChain
 #include "mozilla/layers/LayersMessages.h"
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend, etc
 #include "mozilla/Maybe.h"              // for Maybe
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 #include "nsAString.h"
-#include "nsRefPtr.h"                   // for nsRefPtr
+#include "mozilla/nsRefPtr.h"                   // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "nsRect.h"                     // for mozilla::gfx::IntRect
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nscore.h"                     // for nsAString, etc
 #include "LayerTreeInvalidation.h"
 
--- a/gfx/layers/composite/PaintedLayerComposite.cpp
+++ b/gfx/layers/composite/PaintedLayerComposite.cpp
@@ -13,17 +13,17 @@
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for RoundedToInt, Rect
 #include "mozilla/gfx/Types.h"          // for Filter::Filter::LINEAR
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/ContentHost.h"  // for ContentHost
 #include "mozilla/layers/Effects.h"     // for EffectChain
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAString.h"
-#include "nsRefPtr.h"                   // for nsRefPtr
+#include "mozilla/nsRefPtr.h"                   // for nsRefPtr
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsMathUtils.h"                // for NS_lround
 #include "nsString.h"                   // for nsAutoCString
 #include "TextRenderer.h"
 #include "GeckoProfiler.h"
 
 namespace mozilla {
 namespace layers {
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -12,17 +12,17 @@
 #include "mozilla/layers/CompositableTransactionParent.h" // for CompositableParentManager
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
 #include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "nsAString.h"
-#include "nsRefPtr.h"                   // for nsRefPtr
+#include "mozilla/nsRefPtr.h"                   // for nsRefPtr
 #include "nsPrintfCString.h"            // for nsPrintfCString
 #include "mozilla/layers/PTextureParent.h"
 #include "mozilla/unused.h"
 #include <limits>
 #include "../opengl/CompositorOGL.h"
 #include "gfxUtils.h"
 
 #ifdef MOZ_ENABLE_D3D10_LAYER
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -711,39 +711,71 @@ private:
  */
 class CompositingRenderTarget: public TextureSource
 {
 public:
 
   explicit CompositingRenderTarget(const gfx::IntPoint& aOrigin)
     : mClearOnBind(false)
     , mOrigin(aOrigin)
+    , mHasComplexProjection(false)
   {}
   virtual ~CompositingRenderTarget() {}
 
 #ifdef MOZ_DUMP_PAINTING
   virtual already_AddRefed<gfx::DataSourceSurface> Dump(Compositor* aCompositor) { return nullptr; }
 #endif
 
   /**
    * Perform a clear when recycling a non opaque surface.
    * The clear is deferred to when the render target is bound.
    */
   void ClearOnBind() {
     mClearOnBind = true;
   }
 
-  const gfx::IntPoint& GetOrigin() { return mOrigin; }
+  const gfx::IntPoint& GetOrigin() const { return mOrigin; }
   gfx::IntRect GetRect() { return gfx::IntRect(GetOrigin(), GetSize()); }
 
+  /**
+   * If a Projection matrix is set, then it is used for rendering to
+   * this render target instead of generating one.  If no explicit
+   * projection is set, Compositors are expected to generate an
+   * orthogonal maaping that maps 0..1 to the full size of the render
+   * target.
+   */
+  bool HasComplexProjection() const { return mHasComplexProjection; }
+  void ClearProjection() { mHasComplexProjection = false; }
+  void SetProjection(const gfx::Matrix4x4& aNewMatrix, bool aEnableDepthBuffer,
+                     float aZNear, float aZFar)
+  {
+    mProjectionMatrix = aNewMatrix;
+    mEnableDepthBuffer = aEnableDepthBuffer;
+    mZNear = aZNear;
+    mZFar = aZFar;
+    mHasComplexProjection = true;
+  }
+  void GetProjection(gfx::Matrix4x4& aMatrix, bool& aEnableDepth, float& aZNear, float& aZFar)
+  {
+    MOZ_ASSERT(mHasComplexProjection);
+    aMatrix = mProjectionMatrix;
+    aEnableDepth = mEnableDepthBuffer;
+    aZNear = mZNear;
+    aZFar = mZFar;
+  }
 protected:
   bool mClearOnBind;
 
 private:
   gfx::IntPoint mOrigin;
+
+  gfx::Matrix4x4 mProjectionMatrix;
+  float mZNear, mZFar;
+  bool mHasComplexProjection;
+  bool mEnableDepthBuffer;
 };
 
 /**
  * Creates a TextureHost that can be used with any of the existing backends
  * Not all SurfaceDescriptor types are supported
  */
 already_AddRefed<TextureHost>
 CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
--- a/gfx/layers/composite/TiledContentHost.cpp
+++ b/gfx/layers/composite/TiledContentHost.cpp
@@ -237,17 +237,18 @@ protected:
   size_t mFirstPossibility;
 };
 
 bool
 TiledLayerBufferComposite::UseTiles(const SurfaceDescriptorTiles& aTiles,
                                     Compositor* aCompositor,
                                     ISurfaceAllocator* aAllocator)
 {
-  if (mResolution != aTiles.resolution()) {
+  if (mResolution != aTiles.resolution() ||
+      aTiles.tileSize() != mTileSize) {
     Clear();
   }
   MOZ_ASSERT(aAllocator);
   MOZ_ASSERT(aCompositor);
   if (!aAllocator || !aCompositor) {
     return false;
   }
 
@@ -347,16 +348,18 @@ TiledLayerBufferComposite::UseTiles(cons
     if (tile.mTextureHost->HasInternalBuffer()) {
       // Now that we did the texture upload (in UseTileTexture), we can release
       // the lock.
       tile.ReadUnlock();
     }
   }
 
   mTiles = newTiles;
+  mTileSize = aTiles.tileSize();
+  mTileOrigin = aTiles.tileOrigin();
   mValidRegion = aTiles.validRegion();
   mResolution = aTiles.resolution();
   mFrameResolution = CSSToParentLayerScale2D(aTiles.frameXResolution(),
                                              aTiles.frameYResolution());
 
   return true;
 }
 
--- a/gfx/layers/composite/TiledContentHost.h
+++ b/gfx/layers/composite/TiledContentHost.h
@@ -184,16 +184,32 @@ public:
   explicit TiledContentHost(const TextureInfo& aTextureInfo);
 
 protected:
   ~TiledContentHost();
 
 public:
   virtual LayerRenderState GetRenderState() override
   {
+    // If we have exactly one high precision tile, then we can support hwc.
+    if (mTiledBuffer.GetTileCount() == 1 &&
+        mLowPrecisionTiledBuffer.GetTileCount() == 0) {
+      TextureHost* host = mTiledBuffer.GetTile(0).mTextureHost;
+      if (host) {
+        MOZ_ASSERT(!mTiledBuffer.GetTile(0).mTextureHostOnWhite, "Component alpha not supported!");
+        LayerRenderState state = host->GetRenderState();
+
+        // Offset by the distance between the start of the valid (visible) region and the top-left
+        // of the tile.
+        gfx::IntPoint offset = mTiledBuffer.GetTileOffset(mTiledBuffer.GetPlacement().TilePosition(0));
+
+        state.SetOffset(offset - GetValidRegion().GetBounds().TopLeft());
+        return host->GetRenderState();
+      }
+    }
     return LayerRenderState();
   }
 
 
   virtual bool UpdateThebes(const ThebesBufferData& aData,
                             const nsIntRegion& aUpdated,
                             const nsIntRegion& aOldValidRegionBack,
                             nsIntRegion* aUpdatedRegionBack) override
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -326,23 +326,23 @@ CompositorD3D11::Initialize()
       { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,       0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
       { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT,       0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
       { "TEXCOORD", 2, DXGI_FORMAT_R32G32_FLOAT,       0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
       { "COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
     };
 
     hr = mDevice->CreateInputLayout(vrlayout,
                                     sizeof(vrlayout) / sizeof(D3D11_INPUT_ELEMENT_DESC),
-                                    OculusVRDistortionVS,
-                                    sizeof(OculusVRDistortionVS),
-                                    byRef(mAttachments->mVRDistortionInputLayout[VRHMDType::Oculus]));
+                                    Oculus050VRDistortionVS,
+                                    sizeof(Oculus050VRDistortionVS),
+                                    byRef(mAttachments->mVRDistortionInputLayout[VRHMDType::Oculus050]));
 
     // XXX shared for now, rename
     mAttachments->mVRDistortionInputLayout[VRHMDType::Cardboard] =
-      mAttachments->mVRDistortionInputLayout[VRHMDType::Oculus];
+      mAttachments->mVRDistortionInputLayout[VRHMDType::Oculus050];
 
     cBufferDesc.ByteWidth = sizeof(gfx::VRDistortionConstants);
     hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mVRDistortionConstants));
     if (FAILED(hr)) {
       return false;
     }
   }
 
@@ -532,19 +532,30 @@ CompositorD3D11::CreateRenderTargetFromS
 }
 
 void
 CompositorD3D11::SetRenderTarget(CompositingRenderTarget* aRenderTarget)
 {
   MOZ_ASSERT(aRenderTarget);
   CompositingRenderTargetD3D11* newRT =
     static_cast<CompositingRenderTargetD3D11*>(aRenderTarget);
-  mCurrentRT = newRT;
-  mCurrentRT->BindRenderTarget(mContext);
-  PrepareViewport(newRT->GetSize());
+  if (mCurrentRT != newRT) {
+    mCurrentRT = newRT;
+    mCurrentRT->BindRenderTarget(mContext);
+  }
+
+  if (newRT->HasComplexProjection()) {
+    gfx::Matrix4x4 projection;
+    bool depthEnable;
+    float zNear, zFar;
+    newRT->GetProjection(projection, depthEnable, zNear, zFar);
+    PrepareViewport(newRT->GetSize(), projection, zNear, zFar);
+  } else {
+    PrepareViewport(newRT->GetSize());
+  }
 }
 
 void
 CompositorD3D11::SetPSForEffect(Effect* aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat)
 {
   switch (aEffect->mType) {
   case EffectTypes::SOLID_COLOR:
     mContext->PSSetShader(mAttachments->mSolidColorShader[aMaskType], nullptr, 0);
@@ -623,20 +634,27 @@ CompositorD3D11::DrawVRDistortion(const 
   }
 
   HRESULT hr;
 
   EffectVRDistortion* vrEffect =
     static_cast<EffectVRDistortion*>(aEffectChain.mPrimaryEffect.get());
 
   TextureSourceD3D11* source = vrEffect->mTexture->AsSourceD3D11();
-  gfx::IntSize size = vrEffect->mRenderTarget->GetSize(); // XXX source->GetSize()
 
   VRHMDInfo* hmdInfo = vrEffect->mHMD;
   VRHMDType hmdType = hmdInfo->GetType();
+
+  if (!mAttachments->mVRDistortionVS[hmdType] ||
+      !mAttachments->mVRDistortionPS[hmdType])
+  {
+    NS_WARNING("No VS/PS for hmd type for VR distortion!");
+    return;
+  }
+
   VRDistortionConstants shaderConstants;
 
   // do we need to recreate the VR buffers, since the config has changed?
   if (hmdInfo->GetConfiguration() != mAttachments->mVRConfiguration) {
     D3D11_SUBRESOURCE_DATA sdata = { 0 };
     CD3D11_BUFFER_DESC desc(0, D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_IMMUTABLE);
 
     // XXX as an optimization, we should really pack the indices and vertices for both eyes
@@ -683,41 +701,48 @@ CompositorD3D11::DrawVRDistortion(const 
   mContext->IASetInputLayout(mAttachments->mVRDistortionInputLayout[hmdType]);
   mContext->VSSetShader(mAttachments->mVRDistortionVS[hmdType], nullptr, 0);
   mContext->PSSetShader(mAttachments->mVRDistortionPS[hmdType], nullptr, 0);
 
   // This is the source texture SRV for the pixel shader
   ID3D11ShaderResourceView* srView = source->GetShaderResourceView();
   mContext->PSSetShaderResources(0, 1, &srView);
 
-  gfx::IntSize vpSizeInt = mCurrentRT->GetSize();
-  gfx::Size vpSize(vpSizeInt.width, vpSizeInt.height);
+  Rect destRect = aTransform.TransformBounds(aRect);
+  gfx::IntSize preDistortionSize = vrEffect->mRenderTarget->GetSize(); // XXX source->GetSize()
+  gfx::Size vpSize = destRect.Size();
+
   ID3D11Buffer* vbuffer;
   UINT vsize, voffset;
 
   for (uint32_t eye = 0; eye < 2; eye++) {
     gfx::IntRect eyeViewport;
-    eyeViewport.x = eye * size.width / 2;
+    eyeViewport.x = eye * preDistortionSize.width / 2;
     eyeViewport.y = 0;
-    eyeViewport.width = size.width / 2;
-    eyeViewport.height = size.height;
+    eyeViewport.width = preDistortionSize.width / 2;
+    eyeViewport.height = preDistortionSize.height;
 
     hmdInfo->FillDistortionConstants(eye,
-                                     size, eyeViewport,
-                                     vpSize, aRect,
+                                     preDistortionSize, eyeViewport,
+                                     vpSize, destRect,
                                      shaderConstants);
 
     // D3D has clip space top-left as -1,1 so we need to flip the Y coordinate offset here
     shaderConstants.destinationScaleAndOffset[1] = - shaderConstants.destinationScaleAndOffset[1];
 
     // XXX I really want to write a templated helper for these next 4 lines
     D3D11_MAPPED_SUBRESOURCE resource;
-    mContext->Map(mAttachments->mVRDistortionConstants, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
+    hr = mContext->Map(mAttachments->mVRDistortionConstants, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
+    if (FAILED(hr) || !resource.pData) {
+      gfxCriticalError() << "Failed to map VRDistortionConstants. Result: " << hr;
+      return;
+    }
     *(gfx::VRDistortionConstants*)resource.pData = shaderConstants;
     mContext->Unmap(mAttachments->mVRDistortionConstants, 0);
+    resource.pData = nullptr;
 
     // XXX is there a better way to change a bunch of these things from what they were set to
     // in BeginFrame/etc?
     vbuffer = mAttachments->mVRDistortionVertices[eye];
     vsize = sizeof(gfx::VRDistortionVertex);
     voffset = 0;
     mContext->IASetVertexBuffers(0, 1, &vbuffer, &vsize, &voffset);
     mContext->IASetIndexBuffer(mAttachments->mVRDistortionIndices[eye], DXGI_FORMAT_R16_UINT, 0);
@@ -1094,36 +1119,44 @@ CompositorD3D11::EndFrame()
   }
 
   mCurrentRT = nullptr;
 }
 
 void
 CompositorD3D11::PrepareViewport(const gfx::IntSize& aSize)
 {
-  D3D11_VIEWPORT viewport;
-  viewport.MaxDepth = 1.0f;
-  viewport.MinDepth = 0.0f;
-  viewport.Width = aSize.width;
-  viewport.Height = aSize.height;
-  viewport.TopLeftX = 0;
-  viewport.TopLeftY = 0;
-
-  mContext->RSSetViewports(1, &viewport);
-
   // This view matrix translates coordinates from 0..width and 0..height to
   // -1..1 on the X axis, and -1..1 on the Y axis (flips the Y coordinate)
   Matrix viewMatrix = Matrix::Translation(-1.0, 1.0);
   viewMatrix.PreScale(2.0f / float(aSize.width), 2.0f / float(aSize.height));
   viewMatrix.PreScale(1.0f, -1.0f);
 
   Matrix4x4 projection = Matrix4x4::From2D(viewMatrix);
   projection._33 = 0.0f;
 
-  memcpy(&mVSConstants.projection, &projection, sizeof(mVSConstants.projection));
+  PrepareViewport(aSize, projection, 0.0f, 1.0f);
+}
+
+void
+CompositorD3D11::PrepareViewport(const gfx::IntSize& aSize,
+                                 const gfx::Matrix4x4& aProjection,
+                                 float aZNear, float aZFar)
+{
+  D3D11_VIEWPORT viewport;
+  viewport.MaxDepth = aZFar;
+  viewport.MinDepth = aZNear;
+  viewport.Width = aSize.width;
+  viewport.Height = aSize.height;
+  viewport.TopLeftX = 0;
+  viewport.TopLeftY = 0;
+
+  mContext->RSSetViewports(1, &viewport);
+
+  memcpy(&mVSConstants.projection, &aProjection._11, sizeof(mVSConstants.projection));
 }
 
 void
 CompositorD3D11::EnsureSize()
 {
   IntRect rect;
   mWidget->GetClientBounds(rect);
 
@@ -1258,36 +1291,36 @@ CompositorD3D11::CreateShaders()
                                   byRef(mAttachments->mRGBAShader[MaskType::Mask3d]));
   if (FAILED(hr)) {
     return false;
   }
 
 
   /* VR stuff */
 
-  hr = mDevice->CreateVertexShader(OculusVRDistortionVS,
-                                   sizeof(OculusVRDistortionVS),
+  hr = mDevice->CreateVertexShader(Oculus050VRDistortionVS,
+                                   sizeof(Oculus050VRDistortionVS),
                                    nullptr,
-                                   byRef(mAttachments->mVRDistortionVS[VRHMDType::Oculus]));
+                                   byRef(mAttachments->mVRDistortionVS[VRHMDType::Oculus050]));
   if (FAILED(hr)) {
     return false;
   }
 
-  hr = mDevice->CreatePixelShader(OculusVRDistortionPS,
-                                  sizeof(OculusVRDistortionPS),
+  hr = mDevice->CreatePixelShader(Oculus050VRDistortionPS,
+                                  sizeof(Oculus050VRDistortionPS),
                                   nullptr,
-                                  byRef(mAttachments->mVRDistortionPS[VRHMDType::Oculus]));
+                                  byRef(mAttachments->mVRDistortionPS[VRHMDType::Oculus050]));
   if (FAILED(hr)) {
     return false;
   }
 
   // These are shared
-  // XXX rename Oculus shaders to something more generic
-  mAttachments->mVRDistortionVS[VRHMDType::Cardboard] = mAttachments->mVRDistortionVS[VRHMDType::Oculus];
-  mAttachments->mVRDistortionPS[VRHMDType::Cardboard] = mAttachments->mVRDistortionPS[VRHMDType::Oculus];
+  // XXX rename Oculus050 shaders to something more generic
+  mAttachments->mVRDistortionVS[VRHMDType::Cardboard] = mAttachments->mVRDistortionVS[VRHMDType::Oculus050];
+  mAttachments->mVRDistortionPS[VRHMDType::Cardboard] = mAttachments->mVRDistortionPS[VRHMDType::Oculus050];
 
   return true;
 }
 
 bool
 CompositorD3D11::UpdateConstantBuffers()
 {
   HRESULT hr;
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -124,17 +124,19 @@ public:
    * e.g., by Composer2D
    */
   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override {}
 
   /**
    * Setup the viewport and projection matrix for rendering
    * to a window of the given dimensions.
    */
-  virtual void PrepareViewport(const gfx::IntSize& aSize) override;
+  virtual void PrepareViewport(const gfx::IntSize& aSize);
+  virtual void PrepareViewport(const gfx::IntSize& aSize, const gfx::Matrix4x4& aProjection,
+                               float aZNear, float aZFar);
 
   virtual bool SupportsPartialTextureUpdate() override { return true; }
 
 #ifdef MOZ_DUMP_PAINTING
   virtual const char* Name() const override { return "Direct3D 11"; }
 #endif
 
   virtual LayersBackend GetBackendType() const override {
--- a/gfx/layers/d3d11/CompositorD3D11ShadersVR.h
+++ b/gfx/layers/d3d11/CompositorD3D11ShadersVR.h
@@ -103,17 +103,17 @@ mad o2.xy, v2.xyxx, cb0[0].zwzz, cb0[0].
 mov o2.z, l(1.000000)
 mad o3.xy, v3.xyxx, cb0[0].zwzz, cb0[0].xyxx
 mov o3.z, l(1.000000)
 mov o4.xyzw, v4.xyzw
 ret 
 // Approximately 10 instruction slots used
 #endif
 
-const BYTE OculusVRDistortionVS[] =
+const BYTE Oculus050VRDistortionVS[] =
 {
      68,  88,  66,  67, 206, 154, 
     203,  64, 121,  47, 121, 169, 
     222, 206, 108, 175, 167, 227, 
     154,  37,   1,   0,   0,   0, 
     244,   5,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
     108,   1,   0,   0,  44,   3, 
@@ -442,17 +442,17 @@ sample r0.xyzw, v2.xyxx, t0.xyzw, s0
 mul o0.y, r0.y, v4.x
 sample r0.xyzw, v3.xyxx, t0.xyzw, s0
 mul o0.z, r0.z, v4.x
 mov o0.w, l(1.000000)
 ret 
 // Approximately 8 instruction slots used
 #endif
 
-const BYTE OculusVRDistortionPS[] =
+const BYTE Oculus050VRDistortionPS[] =
 {
      68,  88,  66,  67,  48, 161, 
     127, 216, 149, 107,  53,  57, 
     164,  84,  84, 154,  58, 227, 
     125,  61,   1,   0,   0,   0, 
     124,   4,   0,   0,   6,   0, 
       0,   0,  56,   0,   0,   0, 
      60,   1,   0,   0, 132,   2, 
--- a/gfx/layers/d3d11/CompositorD3D11VR.hlsl
+++ b/gfx/layers/d3d11/CompositorD3D11VR.hlsl
@@ -33,19 +33,19 @@ struct VS_VR_OUTPUT {
 SamplerState Linear
 {
   Filter = MIN_MAG_MIP_LINEAR;
   AddressU = Clamp;
   AddressV = Clamp;
 };
 
 /*
- * Oculus basic distortion, with chroma aberration correction
+ * Oculus050 basic distortion, with chroma aberration correction
  */
-VS_VR_OUTPUT OculusVRDistortionVS(const VS_VR_INPUT aVertex)
+VS_VR_OUTPUT Oculus050VRDistortionVS(const VS_VR_INPUT aVertex)
 {
   VS_VR_OUTPUT res;
 
   float2 tc0 = aVertex.vTexCoord0 * VREyeToSource.zw + VREyeToSource.xy;
   float2 tc1 = aVertex.vTexCoord1 * VREyeToSource.zw + VREyeToSource.xy;
   float2 tc2 = aVertex.vTexCoord2 * VREyeToSource.zw + VREyeToSource.xy;
 
   //res.vPosition.xy = aVertex.vPosition.xy;
@@ -56,17 +56,17 @@ VS_VR_OUTPUT OculusVRDistortionVS(const 
   res.vTexCoord1 = float3(tc1, 1);
   res.vTexCoord2 = float3(tc2, 1);
 
   res.vGenericAttribs = aVertex.vGenericAttribs;
   
   return res;
 }
 
-float4 OculusVRDistortionPS(const VS_VR_OUTPUT aVertex) : SV_Target
+float4 Oculus050VRDistortionPS(const VS_VR_OUTPUT aVertex) : SV_Target
 {
   float resR = Texture.Sample(Linear, aVertex.vTexCoord0.xy).r;
   float resG = Texture.Sample(Linear, aVertex.vTexCoord1.xy).g;
   float resB = Texture.Sample(Linear, aVertex.vTexCoord2.xy).b;
 
   return float4(resR * aVertex.vGenericAttribs.r,
                 resG * aVertex.vGenericAttribs.r,
                 resB * aVertex.vGenericAttribs.r,
--- a/gfx/layers/d3d11/genshaders.sh
+++ b/gfx/layers/d3d11/genshaders.sh
@@ -40,12 +40,12 @@ makeShaderPS RGBAShaderMask
 makeShaderPS RGBAShaderMask3D
 makeShaderPS YCbCrShaderMask
 makeShaderPS ComponentAlphaShaderMask
 
 SRC=CompositorD3D11VR.hlsl
 DEST=CompositorD3D11ShadersVR.h
 
 rm -f $DEST
-makeShaderVS OculusVRDistortionVS
-makeShaderPS OculusVRDistortionPS
+makeShaderVS Oculus050VRDistortionVS
+makeShaderPS Oculus050VRDistortionPS
 
 rm $tempfile
--- a/gfx/layers/d3d9/CompositorD3D9.h
+++ b/gfx/layers/d3d9/CompositorD3D9.h
@@ -66,17 +66,17 @@ public:
                           const gfx::Rect& aRenderBounds,
                           gfx::Rect *aClipRectOut = nullptr,
                           gfx::Rect *aRenderBoundsOut = nullptr) override;
 
   virtual void EndFrame() override;
 
   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override {}
 
-  virtual void PrepareViewport(const gfx::IntSize& aSize) override;
+  virtual void PrepareViewport(const gfx::IntSize& aSize);
 
   virtual bool SupportsPartialTextureUpdate() override{ return true; }
 
 #ifdef MOZ_DUMP_PAINTING
   virtual const char* Name() const override { return "Direct3D9"; }
 #endif
 
   virtual LayersBackend GetBackendType() const override {
--- a/gfx/layers/ipc/FenceUtils.h
+++ b/gfx/layers/ipc/FenceUtils.h
@@ -4,17 +4,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef IPC_FencerUtils_h
 #define IPC_FencerUtils_h
 
 #include "ipc/IPCMessageUtils.h"
-#include "nsRefPtr.h"             // for nsRefPtr
+#include "mozilla/nsRefPtr.h"             // for nsRefPtr
 
 namespace mozilla {
 namespace layers {
 
 class FenceHandle {
 public:
   class FdObj {
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FdObj)
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -328,16 +328,18 @@ struct PlaceholderTileDescriptor {
 union TileDescriptor {
   TexturedTileDescriptor;
   PlaceholderTileDescriptor;
 };
 
 struct SurfaceDescriptorTiles {
   nsIntRegion validRegion;
   TileDescriptor[] tiles;
+  IntPoint    tileOrigin;
+  IntSize     tileSize;
   int         firstTileX;
   int         firstTileY;
   int         retainedWidth;
   int         retainedHeight;
   float       resolution;
   float       frameXResolution;
   float       frameYResolution;
 };
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -99,27 +99,29 @@ EXPORTS.mozilla.layers += [
     'apz/src/APZUtils.h',
     'apz/src/AsyncPanZoomAnimation.h',
     'apz/testutil/APZTestData.h',
     'apz/util/ActiveElementManager.h',
     'apz/util/APZCCallbackHelper.h',
     'apz/util/APZEventState.h',
     'apz/util/APZThreadUtils.h',
     'apz/util/ChromeProcessController.h',
+    'apz/util/DoubleTapToZoom.h',
     'apz/util/InputAPZContext.h',
     'AtomicRefCountedWithFinalize.h',
     'AxisPhysicsModel.h',
     'AxisPhysicsMSDModel.h',
     'basic/BasicCompositor.h',
     'basic/MacIOSurfaceTextureHostBasic.h',
     'basic/TextureHostBasic.h',
     'client/CanvasClient.h',
     'client/CompositableClient.h',
     'client/ContentClient.h',
     'client/ImageClient.h',
+    'client/SingleTiledContentClient.h',
     'client/TextureClient.h',
     'client/TextureClientPool.h',
     'client/TextureClientRecycleAllocator.h',
     'client/TextureClientSharedSurface.h',
     'client/TiledContentClient.h',
     'composite/AsyncCompositionManager.h',
     'composite/CanvasLayerComposite.h',
     'composite/ColorLayerComposite.h',
@@ -241,16 +243,17 @@ UNIFIED_SOURCES += [
     'apz/src/TaskThrottler.cpp',
     'apz/src/WheelScrollAnimation.cpp',
     'apz/testutil/APZTestData.cpp',
     'apz/util/ActiveElementManager.cpp',
     'apz/util/APZCCallbackHelper.cpp',
     'apz/util/APZEventState.cpp',
     'apz/util/APZThreadUtils.cpp',
     'apz/util/ChromeProcessController.cpp',
+    'apz/util/DoubleTapToZoom.cpp',
     'apz/util/InputAPZContext.cpp',
     'AxisPhysicsModel.cpp',
     'AxisPhysicsMSDModel.cpp',
     'basic/BasicCanvasLayer.cpp',
     'basic/BasicColorLayer.cpp',
     'basic/BasicCompositor.cpp',
     'basic/BasicContainerLayer.cpp',
     'basic/BasicImages.cpp',
@@ -265,16 +268,17 @@ UNIFIED_SOURCES += [
     'client/ClientContainerLayer.cpp',
     'client/ClientImageLayer.cpp',
     'client/ClientLayerManager.cpp',
     'client/ClientPaintedLayer.cpp',
     'client/ClientTiledPaintedLayer.cpp',
     'client/CompositableClient.cpp',
     'client/ContentClient.cpp',
     'client/ImageClient.cpp',
+    'client/SingleTiledContentClient.cpp',
     'client/TextureClient.cpp',
     'client/TextureClientPool.cpp',
     'client/TextureClientRecycleAllocator.cpp',
     'client/TextureClientSharedSurface.cpp',
     'client/TiledContentClient.cpp',
     'composite/AsyncCompositionManager.cpp',
     'composite/CanvasLayerComposite.cpp',
     'composite/ColorLayerComposite.cpp',
@@ -377,16 +381,17 @@ IPDL_SOURCES = [
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/docshell/base',  # for nsDocShell.h
     '/layout/base',    # for TouchManager.h
+    '/layout/generic', # for nsTextFrame.h
 ]
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_DEBUG']:
     DEFINES['D3D_DEBUG_INFO'] = True
 
 if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
@@ -28,18 +28,24 @@ CompositingRenderTargetOGL::BindTexture(
   MOZ_ASSERT(mTextureHandle != 0);
   mGL->fActiveTexture(aTextureUnit);
   mGL->fBindTexture(aTextureTarget, mTextureHandle);
 }
 
 void
 CompositingRenderTargetOGL::BindRenderTarget()
 {
+  bool needsClear = false;
+
   if (mInitParams.mStatus != InitParams::INITIALIZED) {
     InitializeImpl();
+    if (mInitParams.mInit == INIT_MODE_CLEAR) {
+      needsClear = true;
+      mClearOnBind = false;
+    }
   } else {
     MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
     GLuint fbo = mFBO == 0 ? mGL->GetDefaultFramebuffer() : mFBO;
     mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fbo);
     GLenum result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
     if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
       // The main framebuffer (0) of non-offscreen contexts
       // might be backed by a EGLSurface that needs to be renewed.
@@ -53,24 +59,24 @@ CompositingRenderTargetOGL::BindRenderTa
                          "GLContext=%p, IsOffscreen()=%d, mFBO=%d, aFBOTextureTarget=0x%x, "
                          "aRect.width=%d, aRect.height=%d",
                          result, mGL, mGL->IsOffscreen(), mFBO, mInitParams.mFBOTextureTarget,
                          mInitParams.mSize.width, mInitParams.mSize.height);
         NS_WARNING(msg.get());
       }
     }
 
-    mCompositor->PrepareViewport(mInitParams.mSize);
+    needsClear = mClearOnBind;
   }
 
-  if (mClearOnBind) {
+  if (needsClear) {
     mGL->fScissor(0, 0, mInitParams.mSize.width, mInitParams.mSize.height);
     mGL->fClearColor(0.0, 0.0, 0.0, 0.0);
-    mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
-    mClearOnBind = false;
+    mGL->fClearDepth(0.0);
+    mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
   }
 }
 
 #ifdef MOZ_DUMP_PAINTING
 already_AddRefed<DataSourceSurface>
 CompositingRenderTargetOGL::Dump(Compositor* aCompositor)
 {
   MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
@@ -99,21 +105,12 @@ CompositingRenderTargetOGL::InitializeIm
   if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
     nsAutoCString msg;
     msg.AppendPrintf("Framebuffer not complete -- error 0x%x, aFBOTextureTarget 0x%x, mFBO %d, mTextureHandle %d, aRect.width %d, aRect.height %d",
                       result, mInitParams.mFBOTextureTarget, mFBO, mTextureHandle, mInitParams.mSize.width, mInitParams.mSize.height);
     NS_ERROR(msg.get());
   }
 
   mInitParams.mStatus = InitParams::INITIALIZED;
-
-  mCompositor->PrepareViewport(mInitParams.mSize);
-  mGL->fScissor(0, 0, mInitParams.mSize.width, mInitParams.mSize.height);
-  if (mInitParams.mInit == INIT_MODE_CLEAR) {
-    mGL->fClearColor(0.0, 0.0, 0.0, 0.0);
-    mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
-    mClearOnBind = false;
-  }
-
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.h
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h
@@ -34,16 +34,18 @@ namespace gfx {
 namespace layers {
 
 class TextureSource;
 
 class CompositingRenderTargetOGL : public CompositingRenderTarget
 {
   typedef mozilla::gl::GLContext GLContext;
 
+  friend class CompositorOGL;
+
   // For lazy initialisation of the GL stuff
   struct InitParams
   {
     InitParams() : mStatus(NO_PARAMS) {}
     InitParams(const gfx::IntSize& aSize,
                GLenum aFBOTextureTarget,
                SurfaceInitMode aInit)
       : mStatus(READY)
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -439,53 +439,64 @@ CompositorOGL::BindAndDrawQuadWithTextur
                                             aTexCoordRect,
                                             &layerRects,
                                             &textureRects);
 
   BindAndDrawQuads(aProg, rects, layerRects, textureRects);
 }
 
 void
-CompositorOGL::PrepareViewport(const gfx::IntSize& aSize)
+CompositorOGL::PrepareViewport(CompositingRenderTargetOGL* aRenderTarget)
 {
+  MOZ_ASSERT(aRenderTarget);
+  const gfx::IntSize& size = aRenderTarget->mInitParams.mSize;
+
   // Set the viewport correctly.
-  mGLContext->fViewport(0, 0, aSize.width, aSize.height);
+  mGLContext->fViewport(0, 0, size.width, size.height);
 
-  mViewportSize = aSize;
+  mViewportSize = size;
 
-  // We flip the view matrix around so that everything is right-side up; we're
-  // drawing directly into the window's back buffer, so this keeps things
-  // looking correct.
-  // XXX: We keep track of whether the window size changed, so we could skip
-  // this update if it hadn't changed since the last call.
+  if (!aRenderTarget->HasComplexProjection()) {
+    // We flip the view matrix around so that everything is right-side up; we're
+    // drawing directly into the window's back buffer, so this keeps things
+    // looking correct.
+    // XXX: We keep track of whether the window size changed, so we could skip
+    // this update if it hadn't changed since the last call.
 
-  // Matrix to transform (0, 0, aWidth, aHeight) to viewport space (-1.0, 1.0,
-  // 2, 2) and flip the contents.
-  Matrix viewMatrix;
-  if (mGLContext->IsOffscreen() && !gIsGtest) {
-    // In case of rendering via GL Offscreen context, disable Y-Flipping
-    viewMatrix.PreTranslate(-1.0, -1.0);
-    viewMatrix.PreScale(2.0f / float(aSize.width), 2.0f / float(aSize.height));
+    // Matrix to transform (0, 0, aWidth, aHeight) to viewport space (-1.0, 1.0,
+    // 2, 2) and flip the contents.
+    Matrix viewMatrix;
+    if (mGLContext->IsOffscreen() && !gIsGtest) {
+      // In case of rendering via GL Offscreen context, disable Y-Flipping
+      viewMatrix.PreTranslate(-1.0, -1.0);
+      viewMatrix.PreScale(2.0f / float(size.width), 2.0f / float(size.height));
+    } else {
+      viewMatrix.PreTranslate(-1.0, 1.0);
+      viewMatrix.PreScale(2.0f / float(size.width), 2.0f / float(size.height));
+      viewMatrix.PreScale(1.0f, -1.0f);
+    }
+
+    MOZ_ASSERT(mCurrentRenderTarget, "No destination");
+    // If we're drawing directly to the window then we want to offset
+    // drawing by the render offset.
+    if (!mTarget && mCurrentRenderTarget->IsWindow()) {
+      viewMatrix.PreTranslate(mRenderOffset.x, mRenderOffset.y);
+    }
+
+    Matrix4x4 matrix3d = Matrix4x4::From2D(viewMatrix);
+    matrix3d._33 = 0.0f;
+    mProjMatrix = matrix3d;
+    mGLContext->fDepthRange(0.0f, 1.0f);
   } else {
-    viewMatrix.PreTranslate(-1.0, 1.0);
-    viewMatrix.PreScale(2.0f / float(aSize.width), 2.0f / float(aSize.height));
-    viewMatrix.PreScale(1.0f, -1.0f);
+    // XXX take into account mRenderOffset
+    bool depthEnable;
+    float zNear, zFar;
+    aRenderTarget->GetProjection(mProjMatrix, depthEnable, zNear, zFar);
+    mGLContext->fDepthRange(zNear, zFar);
   }
-
-  MOZ_ASSERT(mCurrentRenderTarget, "No destination");
-  // If we're drawing directly to the window then we want to offset
-  // drawing by the render offset.
-  if (!mTarget && mCurrentRenderTarget->IsWindow()) {
-    viewMatrix.PreTranslate(mRenderOffset.x, mRenderOffset.y);
-  }
-
-  Matrix4x4 matrix3d = Matrix4x4::From2D(viewMatrix);
-  matrix3d._33 = 0.0f;
-
-  mProjMatrix = matrix3d;
 }
 
 already_AddRefed<CompositingRenderTarget>
 CompositorOGL::CreateRenderTarget(const IntRect &aRect, SurfaceInitMode aInit)
 {
   MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size");
 
   if (aRect.width * aRect.height == 0) {
@@ -536,20 +547,24 @@ CompositorOGL::CreateRenderTargetFromSou
 void
 CompositorOGL::SetRenderTarget(CompositingRenderTarget *aSurface)
 {
   MOZ_ASSERT(aSurface);
   CompositingRenderTargetOGL* surface
     = static_cast<CompositingRenderTargetOGL*>(aSurface);
   if (mCurrentRenderTarget != surface) {
     mCurrentRenderTarget = surface;
-    mContextStateTracker.PopOGLSection(gl(), "Frame");
+    if (mCurrentRenderTarget) {
+      mContextStateTracker.PopOGLSection(gl(), "Frame");
+    }
     mContextStateTracker.PushOGLSection(gl(), "Frame");
     surface->BindRenderTarget();
   }
+
+  PrepareViewport(mCurrentRenderTarget);
 }
 
 CompositingRenderTarget*
 CompositorOGL::GetCurrentRenderTarget() const
 {
   return mCurrentRenderTarget;
 }
 
@@ -640,33 +655,34 @@ CompositorOGL::BeginFrame(const nsIntReg
 
   mPixelsPerFrame = width * height;
   mPixelsFilled = 0;
 
 #if MOZ_WIDGET_ANDROID
   TexturePoolOGL::Fill(gl());
 #endif
 
-  mCurrentRenderTarget =
-    CompositingRenderTargetOGL::RenderTargetForWindow(this,
-                                                      IntSize(width, height));
-  mCurrentRenderTarget->BindRenderTarget();
-
-  mContextStateTracker.PushOGLSection(gl(), "Frame");
-#ifdef DEBUG
-  mWindowRenderTarget = mCurrentRenderTarget;
-#endif
-
   // Default blend function implements "OVER"
   mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                                  LOCAL_GL_ONE, LOCAL_GL_ONE);
   mGLContext->fEnable(LOCAL_GL_BLEND);
 
+  // Make sure SCISSOR is enabled before setting the render target, since the RT
+  // assumes scissor is enabled while it does clears.
   mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
 
+  RefPtr<CompositingRenderTargetOGL> rt =
+    CompositingRenderTargetOGL::RenderTargetForWindow(this,
+                                                      IntSize(width, height));
+  SetRenderTarget(rt);
+
+#ifdef DEBUG
+  mWindowRenderTarget = mCurrentRenderTarget;
+#endif
+
   if (aClipRectOut && !aClipRectIn) {
     aClipRectOut->SetRect(0, 0, width, height);
   }
 
   // If the Android compositor is being used, this clear will be done in
   // DrawWindowUnderlay. Make sure the bits used here match up with those used
   // in mobile/android/base/gfx/LayerRenderer.java
 #ifndef MOZ_WIDGET_ANDROID
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -178,16 +178,17 @@ struct CompositorOGLVRObjects {
 
 // If you want to make this class not final, first remove calls to virtual
 // methods (Destroy) that are made in the destructor.
 class CompositorOGL final : public Compositor
 {
   typedef mozilla::gl::GLContext GLContext;
 
   friend class GLManagerCompositor;
+  friend class CompositingRenderTargetOGL;
 
   std::map<ShaderConfigOGL, ShaderProgramOGL*> mPrograms;
 public:
   explicit CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth = -1, int aSurfaceHeight = -1,
                          bool aUseExternalSurfaceSize = false);
 
 protected:
   virtual ~CompositorOGL();
@@ -256,19 +257,16 @@ public:
   virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override;
 
   virtual void SetScreenRenderOffset(const ScreenPoint& aOffset) override {
     mRenderOffset = aOffset;
   }
 
   virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) override;
 
-  virtual void PrepareViewport(const gfx::IntSize& aSize) override;
-
-
 #ifdef MOZ_DUMP_PAINTING
   virtual const char* Name() const override { return "OGL"; }
 #endif // MOZ_DUMP_PAINTING
 
   virtual LayersBackend GetBackendType() const override {
     return LayersBackend::LAYERS_OPENGL;
   }
 
@@ -323,16 +321,18 @@ private:
   void DestroyVR(GLContext *gl);
 
   void DrawVRDistortion(const gfx::Rect& aRect,
                         const gfx::Rect& aClipRect,
                         const EffectChain& aEffectChain,
                         gfx::Float aOpacity,
                         const gfx::Matrix4x4& aTransform);
 
+  void PrepareViewport(CompositingRenderTargetOGL *aRenderTarget);
+
   /** Widget associated with this compositor */
   nsIWidget *mWidget;
   gfx::IntSize mWidgetSize;
   nsRefPtr<GLContext> mGLContext;
   UniquePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper;
   gfx::Matrix4x4 mProjMatrix;
 
   /** The size of the surface we are rendering to */
--- a/gfx/layers/opengl/CompositorOGLVR.cpp
+++ b/gfx/layers/opengl/CompositorOGLVR.cpp
@@ -225,18 +225,16 @@ CompositorOGL::DrawVRDistortion(const gf
 
   GLenum textureTarget = LOCAL_GL_TEXTURE_2D;
   if (vrEffect->mRenderTarget)
     textureTarget = mFBOTextureTarget;
 
   RefPtr<CompositingRenderTargetOGL> surface =
     static_cast<CompositingRenderTargetOGL*>(vrEffect->mRenderTarget.get());
 
-  gfx::IntSize size = surface->GetInitSize(); // XXX source->GetSize()
-
   VRHMDInfo* hmdInfo = vrEffect->mHMD;
   VRDistortionConstants shaderConstants;
 
   if (hmdInfo->GetConfiguration() != mVR.mConfiguration) {
     for (uint32_t eye = 0; eye < 2; eye++) {
       const gfx::VRDistortionMesh& mesh = hmdInfo->GetDistortionMesh(eye);
       gl()->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mVR.mDistortionVertices[eye]);
       gl()->fBufferData(LOCAL_GL_ARRAY_BUFFER,
@@ -277,42 +275,43 @@ CompositorOGL::DrawVRDistortion(const gf
   gl()->fEnableVertexAttribArray(mVR.mATexCoord0);
   gl()->fEnableVertexAttribArray(mVR.mATexCoord1);
   gl()->fEnableVertexAttribArray(mVR.mATexCoord2);
   gl()->fEnableVertexAttribArray(mVR.mAGenericAttribs);
 
   surface->BindTexture(LOCAL_GL_TEXTURE0, mFBOTextureTarget);
   gl()->fUniform1i(mVR.mUTexture[programIndex], 0);
 
-  gfx::IntSize vpSizeInt = mCurrentRenderTarget->GetInitSize();
-  gfx::Size vpSize(vpSizeInt.width, vpSizeInt.height);
+  Rect destRect = aTransform.TransformBounds(aRect);
+  gfx::IntSize preDistortionSize = surface->GetInitSize(); // XXX source->GetSize()
+  gfx::Size vpSize = destRect.Size();
 
   for (uint32_t eye = 0; eye < 2; eye++) {
     gfx::IntRect eyeViewport;
-    eyeViewport.x = eye * size.width / 2;
+    eyeViewport.x = eye * preDistortionSize.width / 2;
     eyeViewport.y = 0;
-    eyeViewport.width = size.width / 2;
-    eyeViewport.height = size.height;
+    eyeViewport.width = preDistortionSize.width / 2;
+    eyeViewport.height = preDistortionSize.height;
 
     hmdInfo->FillDistortionConstants(eye,
-                                     size, eyeViewport,
-                                     vpSize, aRect,
+                                     preDistortionSize, eyeViewport,
+                                     vpSize, destRect,
                                      shaderConstants);
 
     float height = 1.0f;
     float texScaleAndOffset[4] = { shaderConstants.eyeToSourceScaleAndOffset[0],
                                    shaderConstants.eyeToSourceScaleAndOffset[1],
                                    shaderConstants.eyeToSourceScaleAndOffset[2],
                                    shaderConstants.eyeToSourceScaleAndOffset[3] };
     if (textureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) {
-      texScaleAndOffset[0] *= size.width;
-      texScaleAndOffset[1] *= size.height;
-      texScaleAndOffset[2] *= size.width;
-      texScaleAndOffset[3] *= size.height;
-      height = size.height;
+      texScaleAndOffset[0] *= preDistortionSize.width;
+      texScaleAndOffset[1] *= preDistortionSize.height;
+      texScaleAndOffset[2] *= preDistortionSize.width;
+      texScaleAndOffset[3] *= preDistortionSize.height;
+      height = preDistortionSize.height;
     }
 
     gl()->fUniform4fv(mVR.mUVRDestionatinScaleAndOffset[programIndex], 1, shaderConstants.destinationScaleAndOffset);
     gl()->fUniform4fv(mVR.mUVREyeToSource[programIndex], 1, texScaleAndOffset);
     gl()->fUniform1f(mVR.mUHeight[programIndex], height);
 
     gl()->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mVR.mDistortionVertices[eye]);
 
--- a/gfx/src/nsRenderingContext.h
+++ b/gfx/src/nsRenderingContext.h
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef NSRENDERINGCONTEXT__H__
 #define NSRENDERINGCONTEXT__H__
 
 #include "gfxContext.h"
 #include "mozilla/Attributes.h"
 #include "nsCOMPtr.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 
 namespace mozilla {
 namespace gfx {
 class DrawTarget;
 } // namespace gfx
 } // namespace mozilla
 
 class MOZ_STACK_CLASS nsRenderingContext final
--- a/gfx/tests/gtest/TestVsync.cpp
+++ b/gfx/tests/gtest/TestVsync.cpp
@@ -4,17 +4,17 @@
  */
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "MainThreadUtils.h"
 #include "nsIThread.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "SoftwareVsyncSource.h"
 #include "VsyncSource.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/VsyncDispatcher.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
--- a/gfx/thebes/VsyncSource.h
+++ b/gfx/thebes/VsyncSource.h
@@ -2,17 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_VSYNCSOURCE_H
 #define GFX_VSYNCSOURCE_H
 
 #include "nsTArray.h"
-#include "nsRefPtr.h"
+#include "mozilla/nsRefPtr.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/TimeStamp.h"
 #include "nsISupportsImpl.h"
 
 namespace mozilla {
 class RefreshTimerVsyncDispatcher;
 class CompositorVsyncDispatcher;
 
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -183,16 +183,19 @@ private:
   DECL_GFX_PREF(Live, "apz.x_skate_size_multiplier",           APZXSkateSizeMultiplier, float, 1.5f);
   DECL_GFX_PREF(Live, "apz.x_stationary_size_multiplier",      APZXStationarySizeMultiplier, float, 3.0f);
   DECL_GFX_PREF(Live, "apz.y_skate_size_multiplier",           APZYSkateSizeMultiplier, float, 2.5f);
   DECL_GFX_PREF(Live, "apz.y_stationary_size_multiplier",      APZYStationarySizeMultiplier, float, 3.5f);
   DECL_GFX_PREF(Live, "apz.zoom_animation_duration_ms",        APZZoomAnimationDuration, int32_t, 250);
 
   DECL_GFX_PREF(Live, "dom.meta-viewport.enabled",             MetaViewportEnabled, bool, false);
   DECL_GFX_PREF(Once, "dom.vr.enabled",                        VREnabled, bool, false);
+  DECL_GFX_PREF(Once, "dom.vr.oculus.enabled",                 VROculusEnabled, bool, true);
+  DECL_GFX_PREF(Once, "dom.vr.oculus050.enabled",              VROculus050Enabled, bool, true);
+  DECL_GFX_PREF(Once, "dom.vr.cardboard.enabled",              VRCardboardEnabled, bool, false);
   DECL_GFX_PREF(Once, "dom.vr.add-test-devices",               VRAddTestDevices, int32_t, 1);
   DECL_GFX_PREF(Live, "dom.w3c_pointer_events.enabled",        PointerEventsEnabled, bool, false);
 
   DECL_GFX_PREF(Live, "general.smoothScroll",                  SmoothScrollEnabled, bool, true);
   DECL_GFX_PREF(Live, "general.smoothScroll.durationToIntervalRatio",
                 SmoothScrollDurationToIntervalRatio, int32_t, 200);
   DECL_GFX_PREF(Live, "general.smoothScroll.mouseWheel",       WheelSmoothScrollEnabled, bool, true);
   DECL_GFX_PREF(Live, "general.smoothScroll.mouseWheel.durationMaxMS",
@@ -242,16 +245,18 @@ private:
   DECL_GFX_PREF(Once, "gfx.touch.resample",                    TouchResampling, bool, false);
 
   // These times should be in milliseconds
   DECL_GFX_PREF(Once, "gfx.touch.resample.delay-threshold",    TouchResampleVsyncDelayThreshold, int32_t, 20);
   DECL_GFX_PREF(Once, "gfx.touch.resample.max-predict",        TouchResampleMaxPredict, int32_t, 8);
   DECL_GFX_PREF(Once, "gfx.touch.resample.old-touch-threshold",TouchResampleOldTouchThreshold, int32_t, 17);
   DECL_GFX_PREF(Once, "gfx.touch.resample.vsync-adjust",       TouchVsyncSampleAdjust, int32_t, 5);
 
+  DECL_GFX_PREF(Once, "gfx.vr.mirror-textures",                VRMirrorTextures, bool, false);
+
   DECL_GFX_PREF(Live, "gfx.vsync.collect-scroll-transforms",   CollectScrollTransforms, bool, false);
   DECL_GFX_PREF(Once, "gfx.vsync.compositor",                  VsyncAlignedCompositor, bool, false);
   // On b2g, in really bad cases, I've seen up to 80 ms delays between touch events and the main thread
   // processing them. So 80 ms / 16 = 5 vsync events. Double it up just to be on the safe side, so 10.
   D