Merge mozilla-central to fx-team
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 12 Dec 2014 13:58:40 +0100
changeset 219493 1d53465964a2f696774a73932382333e0cf83ba0
parent 219492 1558ea234fb24aab47f3c553086b8d0ff3a60e16 (current diff)
parent 219379 28fdae8302890303fb4d3fec86ee1906aab7e404 (diff)
child 219494 63205db3303e08cb13b1058a28a02339fa6d3b49
push idunknown
push userunknown
push dateunknown
milestone37.0a1
Merge mozilla-central to fx-team
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -1475,17 +1475,18 @@ nsAccessibilityService::CreateHTMLAccess
       tag == nsGkAtoms::h1 ||
       tag == nsGkAtoms::h2 ||
       tag == nsGkAtoms::h3 ||
       tag == nsGkAtoms::h4 ||
       tag == nsGkAtoms::h5 ||
       tag == nsGkAtoms::h6 ||
       tag == nsGkAtoms::nav ||
       tag == nsGkAtoms::q ||
-      tag == nsGkAtoms::section) {
+      tag == nsGkAtoms::section ||
+      tag == nsGkAtoms::time) {
     nsRefPtr<Accessible> accessible =
       new HyperTextAccessibleWrap(aContent, document);
     return accessible.forget();
   }
 
   if (tag == nsGkAtoms::label) {
     nsRefPtr<Accessible> accessible =
       new HTMLLabelAccessible(aContent, document);
--- a/accessible/generic/HyperTextAccessible.cpp
+++ b/accessible/generic/HyperTextAccessible.cpp
@@ -977,16 +977,25 @@ HyperTextAccessible::NativeAttributes()
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("complementary"));
   } else if (tag == nsGkAtoms::article) {
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("article"));
   } else if (tag == nsGkAtoms::main) {
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("main"));
+  } else if (tag == nsGkAtoms::time) {
+    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
+                           NS_LITERAL_STRING("time"));
+
+    if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::datetime)) {
+      nsAutoString datetime;
+      mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::datetime, datetime);
+      nsAccUtils::SetAccAttr(attributes, nsGkAtoms::datetime, datetime);
+    }
   }
 
   return attributes.forget();
 }
 
 int32_t
 HyperTextAccessible::OffsetAtPoint(int32_t aX, int32_t aY, uint32_t aCoordType)
 {
--- a/accessible/tests/mochitest/elm/test_HTMLSpec.html
+++ b/accessible/tests/mochitest/elm/test_HTMLSpec.html
@@ -1227,17 +1227,22 @@
         actions: "activate",
         interfaces: [ nsIAccessibleText, nsIAccessibleEditableText ]
       };
       testElm("textarea", obj);
 
       //////////////////////////////////////////////////////////////////////////
       // HTML:time
 
-      ok(!isAccessible("time"), "time element is not accessible");
+      obj = {
+        role: ROLE_TEXT_CONTAINER,
+        attributes: { "xml-roles": "time", "datetime": "2001-05-15 19:00" },
+        interfaces: [ nsIAccessibleText, nsIAccessibleHyperText ]
+      };
+      testElm("time", obj);
 
       //////////////////////////////////////////////////////////////////////////
       // HTML:u contained by paragraph
 
       obj = {
         role: ROLE_PARAGRAPH,
         textAttrs: {
           0: { },
--- 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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="58aee9864c193acfd03fa196af399d0659ba506d"/>
--- 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="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6fa7a4936414ceb4055fd27f7a30e76790f834fb"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="58aee9864c193acfd03fa196af399d0659ba506d"/>
   <!-- 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="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="58aee9864c193acfd03fa196af399d0659ba506d"/>
   <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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="58aee9864c193acfd03fa196af399d0659ba506d"/>
--- 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="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6fa7a4936414ceb4055fd27f7a30e76790f834fb"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="58aee9864c193acfd03fa196af399d0659ba506d"/>
   <!-- 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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="58aee9864c193acfd03fa196af399d0659ba506d"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/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="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="58aee9864c193acfd03fa196af399d0659ba506d"/>
   <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="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "f1f983cfb1e42dbc6723c192f73c16bf098b6b4b", 
+    "revision": "21a79199c8869df69769148db45cf08aff37e315", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="58aee9864c193acfd03fa196af399d0659ba506d"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- 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="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="58aee9864c193acfd03fa196af399d0659ba506d"/>
   <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/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="1d9ae9cca415ad093beba9521c429350e1f2b14d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0de95b4017de73e72c897e2dcb87564d8f3756eb"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="58aee9864c193acfd03fa196af399d0659ba506d"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/docshell/base/LoadInfo.cpp
+++ b/docshell/base/LoadInfo.cpp
@@ -117,9 +117,15 @@ LoadInfo::GetContentPolicyType(nsContent
 NS_IMETHODIMP
 LoadInfo::GetBaseURI(nsIURI** aBaseURI)
 {
   *aBaseURI = mBaseURI;
   NS_IF_ADDREF(*aBaseURI);
   return NS_OK;
 }
 
+nsIURI*
+LoadInfo::BaseURI()
+{
+  return mBaseURI;
+}
+
 } // namespace mozilla
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1340,16 +1340,21 @@ nsDocShell::LoadURI(nsIURI * aURI,
     // true; that case will get handled in LoadInternal or LoadHistoryEntry,
     // so we pass false as the second parameter to IsNavigationAllowed.
     // However, we don't allow the page to change location *in the middle of*
     // firing beforeunload, so we do need to check if *beforeunload* is currently
     // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
     if (!IsNavigationAllowed(true, false)) {
       return NS_OK; // JS may not handle returning of an error code
     }
+
+    if (DoAppRedirectIfNeeded(aURI, aLoadInfo, aFirstParty)) {
+      return NS_OK;
+    }
+
     nsCOMPtr<nsIURI> referrer;
     nsCOMPtr<nsIInputStream> postStream;
     nsCOMPtr<nsIInputStream> headersStream;
     nsCOMPtr<nsISupports> owner;
     bool inheritOwner = false;
     bool ownerIsExplicit = false;
     bool sendReferrer = true;
     uint32_t referrerPolicy = mozilla::net::RP_Default;
@@ -6581,20 +6586,16 @@ nsDocShell::ForceRefreshURI(nsIURI * aUR
         if (internalReferrer) {
             loadInfo->SetReferrer(internalReferrer);
         }
     }
     else {
         loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
     }
 
-    if (DoAppRedirectIfNeeded(aURI, loadInfo, true)) {
-      return NS_OK;
-    }
-
     /*
      * LoadURI(...) will cancel all refresh timers... This causes the
      * Timer and its refreshData instance to be released...
      */
     LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true);
 
     return NS_OK;
 }
--- a/docshell/base/nsILoadInfo.idl
+++ b/docshell/base/nsILoadInfo.idl
@@ -12,17 +12,17 @@ interface nsINode;
 interface nsIPrincipal;
 interface nsIURI;
 
 typedef unsigned long nsSecurityFlags;
 
 /**
  * An nsILoadOwner represents per-load information about who started the load.
  */
-[scriptable, builtinclass, uuid(da363267-236d-49bf-83a2-33da8d892728)]
+[scriptable, builtinclass, uuid(768a1f20-57d4-462a-812a-41c04e5d1e19)]
 interface nsILoadInfo : nsISupports
 {
   /**
    * No special security flags:
    */
   const unsigned long SEC_NORMAL = 0;
 
   /**
@@ -151,27 +151,33 @@ interface nsILoadInfo : nsISupports
    * hence should use a NullPrincipal.
    */
   [infallible] readonly attribute boolean loadingSandboxed;
 
   /**
    * The contentPolicyType of the channel, used for security checks
    * like Mixed Content Blocking and Content Security Policy.
    */
-   readonly attribute nsContentPolicyType contentPolicyType;
+  readonly attribute nsContentPolicyType contentPolicyType;
 
 %{ C++
   inline nsContentPolicyType GetContentPolicyType()
   {
     nsContentPolicyType result;
     mozilla::DebugOnly<nsresult> rv = GetContentPolicyType(&result);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
     return result;
   }
 %}
 
   /**
    * A base URI for use in situations where it cannot otherwise be inferred.
    * This attribute may be null.  The value of this attribute may be
    * ignored if the base URI can be inferred by the channel's URI.
    */
-   readonly attribute nsIURI baseURI;
+  readonly attribute nsIURI baseURI;
+
+  /**
+   * A C++-friendly version of baseURI.
+   */
+  [noscript, notxpcom, nostdcall, binaryname(BaseURI)]
+  nsIURI binaryBaseURI();
 };
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -52,16 +52,47 @@
 
 #endif // DEBUG || GC_ON_IPC_MESSAGES
 
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
 /*******************************************************************************
+ * ThreadLocal
+ ******************************************************************************/
+
+ThreadLocal::ThreadLocal(const nsID& aBackgroundChildLoggingId)
+  : mLoggingInfo(aBackgroundChildLoggingId, 1, -1, 1)
+  , mCurrentTransaction(0)
+#ifdef DEBUG
+  , mOwningThread(PR_GetCurrentThread())
+#endif
+{
+  MOZ_ASSERT(mOwningThread);
+
+  MOZ_COUNT_CTOR(mozilla::dom::indexedDB::ThreadLocal);
+}
+
+ThreadLocal::~ThreadLocal()
+{
+  MOZ_COUNT_DTOR(mozilla::dom::indexedDB::ThreadLocal);
+}
+
+#ifdef DEBUG
+
+void
+ThreadLocal::AssertIsOnOwningThread() const
+{
+  MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread);
+}
+
+#endif // DEBUG
+
+/*******************************************************************************
  * Helpers
  ******************************************************************************/
 
 namespace {
 
 void
 MaybeCollectGarbageOnIPCMessage()
 {
@@ -99,49 +130,50 @@ MaybeCollectGarbageOnIPCMessage()
 }
 
 class MOZ_STACK_CLASS AutoSetCurrentTransaction MOZ_FINAL
 {
   typedef mozilla::ipc::BackgroundChildImpl BackgroundChildImpl;
 
   IDBTransaction* const mTransaction;
   IDBTransaction* mPreviousTransaction;
-  IDBTransaction** mThreadLocalSlot;
+  ThreadLocal* mThreadLocal;
 
 public:
   explicit AutoSetCurrentTransaction(IDBTransaction* aTransaction)
     : mTransaction(aTransaction)
     , mPreviousTransaction(nullptr)
-    , mThreadLocalSlot(nullptr)
+    , mThreadLocal(nullptr)
   {
     if (aTransaction) {
       BackgroundChildImpl::ThreadLocal* threadLocal =
         BackgroundChildImpl::GetThreadLocalForCurrentThread();
       MOZ_ASSERT(threadLocal);
 
-      // Hang onto this location for resetting later.
-      mThreadLocalSlot = &threadLocal->mCurrentTransaction;
+      // Hang onto this for resetting later.
+      mThreadLocal = threadLocal->mIndexedDBThreadLocal;
+      MOZ_ASSERT(mThreadLocal);
 
       // Save the current value.
-      mPreviousTransaction = *mThreadLocalSlot;
+      mPreviousTransaction = mThreadLocal->GetCurrentTransaction();
 
       // Set the new value.
-      *mThreadLocalSlot = aTransaction;
+      mThreadLocal->SetCurrentTransaction(aTransaction);
     }
   }
 
   ~AutoSetCurrentTransaction()
   {
-    MOZ_ASSERT_IF(mThreadLocalSlot, mTransaction);
-
-    if (mThreadLocalSlot) {
-      MOZ_ASSERT(*mThreadLocalSlot == mTransaction);
-
+    MOZ_ASSERT_IF(mThreadLocal, mTransaction);
+    MOZ_ASSERT_IF(mThreadLocal,
+                  mThreadLocal->GetCurrentTransaction() == mTransaction);
+
+    if (mThreadLocal) {
       // Reset old value.
-      *mThreadLocalSlot = mPreviousTransaction;
+      mThreadLocal->SetCurrentTransaction(mPreviousTransaction);
     }
   }
 
   IDBTransaction*
   Transaction() const
   {
     return mTransaction;
   }
@@ -584,16 +616,35 @@ DispatchErrorEvent(IDBRequest* aRequest,
     aEvent = errorEvent;
   }
 
   Maybe<AutoSetCurrentTransaction> asct;
   if (aTransaction) {
     asct.emplace(aTransaction);
   }
 
+  if (transaction) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "Firing %s event with error 0x%x",
+                 "IndexedDB %s: C T[%lld] R[%llu]: %s (0x%x)",
+                 IDB_LOG_ID_STRING(),
+                 transaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(aEvent, kErrorEventType),
+                 aErrorCode);
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: "
+                   "Firing %s event with error 0x%x",
+                 "IndexedDB %s: C R[%llu]: %s (0x%x)",
+                 IDB_LOG_ID_STRING(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(aEvent, kErrorEventType),
+                 aErrorCode);
+  }
+
   bool doDefault;
   nsresult rv = request->DispatchEvent(aEvent, &doDefault);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   MOZ_ASSERT(!transaction || transaction->IsOpen() || transaction->IsAborted());
 
@@ -643,16 +694,32 @@ DispatchSuccessEvent(ResultHelper* aResu
     aEvent = successEvent;
   }
 
   request->SetResultCallback(aResultHelper);
 
   MOZ_ASSERT(aEvent);
   MOZ_ASSERT_IF(transaction, transaction->IsOpen());
 
+  if (transaction) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "Firing %s event",
+                 "IndexedDB %s: C T[%lld] R[%llu]: %s",
+                 IDB_LOG_ID_STRING(),
+                 transaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: Firing %s event",
+                 "IndexedDB %s: C R[%llu]: %s",
+                 IDB_LOG_ID_STRING(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
+  }
+
   bool dummy;
   nsresult rv = request->DispatchEvent(aEvent, &dummy);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   MOZ_ASSERT_IF(transaction,
                 transaction->IsOpen() || transaction->IsAborted());
@@ -1063,16 +1130,21 @@ BackgroundFactoryRequestChild::RecvBlock
   }
 
   if (NS_WARN_IF(!blockedEvent)) {
     return false;
   }
 
   nsRefPtr<IDBRequest> kungFuDeathGrip = mRequest;
 
+  IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: Firing \"blocked\" event",
+               "IndexedDB %s: C R[%llu]: \"blocked\"",
+               IDB_LOG_ID_STRING(),
+               mRequest->LoggingSerialNumber());
+
   bool dummy;
   if (NS_FAILED(mRequest->DispatchEvent(blockedEvent, &dummy))) {
     NS_WARNING("Failed to dispatch event!");
   }
 
   return true;
 }
 
@@ -1352,16 +1424,20 @@ BackgroundDatabaseChild::RecvVersionChan
     default:
       MOZ_CRASH("Should never get here!");
   }
 
   if (NS_WARN_IF(!versionChangeEvent)) {
     return false;
   }
 
+  IDB_LOG_MARK("IndexedDB %s: Child : Firing \"versionchange\" event",
+               "IndexedDB %s: C: IDBDatabase \"versionchange\" event",
+               IDB_LOG_ID_STRING());
+
   bool dummy;
   if (NS_FAILED(mDatabase->DispatchEvent(versionChangeEvent, &dummy))) {
     NS_WARNING("Failed to dispatch event!");
   }
 
   if (!mDatabase->IsClosed()) {
     SendBlocked();
   }
--- a/dom/indexedDB/ActorsChild.h
+++ b/dom/indexedDB/ActorsChild.h
@@ -1,29 +1,32 @@
 /* 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_indexeddb_actorschild_h__
 #define mozilla_dom_indexeddb_actorschild_h__
 
+#include "IDBTransaction.h"
 #include "js/RootingAPI.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBCursorChild.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseChild.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryRequestChild.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBRequestChild.h"
+#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBTransactionChild.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBVersionChangeTransactionChild.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 
 class nsIEventTarget;
+struct nsID;
 struct PRThread;
 
 namespace mozilla {
 namespace ipc {
 
 class BackgroundChildImpl;
 
 } // namespace ipc
@@ -33,23 +36,107 @@ namespace indexedDB {
 
 class FileInfo;
 class IDBCursor;
 class IDBDatabase;
 class IDBFactory;
 class IDBMutableFile;
 class IDBOpenDBRequest;
 class IDBRequest;
-class IDBTransaction;
 class Key;
 class PBackgroundIDBFileChild;
 class PermissionRequestChild;
 class PermissionRequestParent;
 class SerializedStructuredCloneReadInfo;
 
+class ThreadLocal
+{
+  friend class nsAutoPtr<ThreadLocal>;
+  friend class IDBFactory;
+
+  LoggingInfo mLoggingInfo;
+  IDBTransaction* mCurrentTransaction;
+
+#ifdef DEBUG
+  PRThread* mOwningThread;
+#endif
+
+public:
+  void
+  AssertIsOnOwningThread() const
+#ifdef DEBUG
+  ;
+#else
+  { }
+#endif
+
+  const LoggingInfo&
+  GetLoggingInfo() const
+  {
+    AssertIsOnOwningThread();
+
+    return mLoggingInfo;
+  }
+
+  const nsID&
+  Id() const
+  {
+    AssertIsOnOwningThread();
+
+    return mLoggingInfo.backgroundChildLoggingId();
+  }
+
+  int64_t
+  NextTransactionSN(IDBTransaction::Mode aMode)
+  {
+    AssertIsOnOwningThread();
+    MOZ_ASSERT(mLoggingInfo.nextTransactionSerialNumber() < INT64_MAX);
+    MOZ_ASSERT(mLoggingInfo.nextVersionChangeTransactionSerialNumber() >
+                 INT64_MIN);
+
+    if (aMode == IDBTransaction::VERSION_CHANGE) {
+      return mLoggingInfo.nextVersionChangeTransactionSerialNumber()--;
+    }
+
+    return mLoggingInfo.nextTransactionSerialNumber()++;
+  }
+
+  uint64_t
+  NextRequestSN()
+  {
+    AssertIsOnOwningThread();
+    MOZ_ASSERT(mLoggingInfo.nextRequestSerialNumber() < UINT64_MAX);
+
+    return mLoggingInfo.nextRequestSerialNumber()++;
+  }
+
+  void
+  SetCurrentTransaction(IDBTransaction* aCurrentTransaction)
+  {
+    AssertIsOnOwningThread();
+
+    mCurrentTransaction = aCurrentTransaction;
+  }
+
+  IDBTransaction*
+  GetCurrentTransaction() const
+  {
+    AssertIsOnOwningThread();
+
+    return mCurrentTransaction;
+  }
+
+private:
+  ThreadLocal(const nsID& aBackgroundChildLoggingId);
+  ~ThreadLocal();
+
+  ThreadLocal() MOZ_DELETE;
+  ThreadLocal(const ThreadLocal& aOther) MOZ_DELETE;
+};
+
 class BackgroundFactoryChild MOZ_FINAL
   : public PBackgroundIDBFactoryChild
 {
   friend class mozilla::ipc::BackgroundChildImpl;
   friend class IDBFactory;
 
   IDBFactory* mFactory;
 
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -102,16 +102,17 @@ using namespace mozilla::ipc;
 #define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
 #endif
 
 namespace {
 
 class Cursor;
 class Database;
 struct DatabaseActorInfo;
+class DatabaseLoggingInfo;
 class DatabaseFile;
 class DatabaseOfflineStorage;
 class Factory;
 class OpenDatabaseOp;
 class TransactionBase;
 class VersionChangeTransaction;
 
 /*******************************************************************************
@@ -2548,27 +2549,24 @@ GetDatabaseConnection(const nsAString& a
 /*******************************************************************************
  * Actor class declarations
  ******************************************************************************/
 
 class DatabaseOperationBase
   : public nsRunnable
   , public mozIStorageProgressHandler
 {
-  // Uniquely tracks each operation for logging purposes. Only modified on the
-  // PBackground thread.
-  static uint64_t sNextSerialNumber;
-
 protected:
   class AutoSetProgressHandler;
 
   typedef nsDataHashtable<nsUint64HashKey, bool> UniqueIndexTable;
 
   nsCOMPtr<nsIEventTarget> mOwningThread;
-  const uint64_t mSerialNumber;
+  const nsID mBackgroundChildLoggingId;
+  const uint64_t mLoggingSerialNumber;
   nsresult mResultCode;
 
 private:
   Atomic<bool> mOperationMayProceed;
   bool mActorDestroyed;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
@@ -2605,20 +2603,26 @@ public:
 
   // May be called on any thread.
   bool
   OperationMayProceed() const
   {
     return mOperationMayProceed;
   }
 
+  const nsID&
+  BackgroundChildLoggingId() const
+  {
+    return mBackgroundChildLoggingId;
+  }
+
   uint64_t
-  SerialNumber() const
-  {
-    return mSerialNumber;
+  LoggingSerialNumber() const
+  {
+    return mLoggingSerialNumber;
   }
 
   nsresult
   ResultCode() const
   {
     return mResultCode;
   }
 
@@ -2627,19 +2631,21 @@ public:
   {
     MOZ_ASSERT(NS_SUCCEEDED(mResultCode));
     MOZ_ASSERT(NS_FAILED(aErrorCode));
 
     mResultCode = aErrorCode;
   }
 
 protected:
-  DatabaseOperationBase()
+  DatabaseOperationBase(const nsID& aBackgroundChildLoggingId,
+                        uint64_t aLoggingSerialNumber)
     : mOwningThread(NS_GetCurrentThread())
-    , mSerialNumber(++sNextSerialNumber)
+    , mBackgroundChildLoggingId(aBackgroundChildLoggingId)
+    , mLoggingSerialNumber(aLoggingSerialNumber)
     , mResultCode(NS_OK)
     , mOperationMayProceed(true)
     , mActorDestroyed(false)
   {
     AssertIsOnOwningThread();
   }
 
   virtual
@@ -2704,16 +2710,17 @@ public:
   Register(DatabaseOperationBase* aDatabaseOp,
            const nsCOMPtr<mozIStorageConnection>& aConnection);
 };
 
 class TransactionDatabaseOperationBase
   : public DatabaseOperationBase
 {
   nsRefPtr<TransactionBase> mTransaction;
+  const int64_t mTransactionLoggingSerialNumber;
   const bool mTransactionIsAborted;
 
 public:
   void
   AssertIsOnTransactionThread() const
 #ifdef DEBUG
   ;
 #else
@@ -2731,17 +2738,21 @@ public:
 
   // This callback will be called on the background thread before releasing the
   // final reference to this request object. Subclasses may perform any
   // additional cleanup here but must always call the base class implementation.
   virtual void
   Cleanup();
 
 protected:
-  explicit TransactionDatabaseOperationBase(TransactionBase* aTransaction);
+  explicit
+  TransactionDatabaseOperationBase(TransactionBase* aTransaction);
+
+  TransactionDatabaseOperationBase(TransactionBase* aTransaction,
+                                   uint64_t aLoggingSerialNumber);
 
   virtual
   ~TransactionDatabaseOperationBase();
 
   // Must be overridden in subclasses. Called on the target thread to allow the
   // subclass to perform necessary database or file operations. A successful
   // return value will trigger a SendSuccessResult callback on the background
   // thread while a failure value will trigger a SendFailureResult callback.
@@ -2774,38 +2785,53 @@ private:
 
 class Factory MOZ_FINAL
   : public PBackgroundIDBFactoryParent
 {
   // Counts the number of "live" Factory instances that have not yet had
   // ActorDestroy called.
   static uint64_t sFactoryInstanceCount;
 
+  nsRefPtr<DatabaseLoggingInfo> mLoggingInfo;
+
   DebugOnly<bool> mActorDestroyed;
 
 public:
   static already_AddRefed<Factory>
-  Create();
+  Create(const LoggingInfo& aLoggingInfo);
+
+  DatabaseLoggingInfo*
+  GetLoggingInfo() const
+  {
+    AssertIsOnBackgroundThread();
+    MOZ_ASSERT(mLoggingInfo);
+
+    return mLoggingInfo;
+  }
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::dom::indexedDB::Factory)
 
 private:
   // Only constructed in Create().
-  explicit Factory();
+  explicit
+  Factory(already_AddRefed<DatabaseLoggingInfo> aLoggingInfo);
 
   // Reference counted.
   ~Factory();
 
   // IPDL methods are only called by IPDL.
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   virtual bool
   RecvDeleteMe() MOZ_OVERRIDE;
 
+  virtual bool
+  RecvIncrementLoggingRequestSerialNumber() MOZ_OVERRIDE;
+
   virtual PBackgroundIDBFactoryRequestParent*
   AllocPBackgroundIDBFactoryRequestParent(const FactoryRequestParams& aParams)
                                           MOZ_OVERRIDE;
 
   virtual bool
   RecvPBackgroundIDBFactoryRequestConstructor(
                                      PBackgroundIDBFactoryRequestParent* aActor,
                                      const FactoryRequestParams& aParams)
@@ -2919,16 +2945,25 @@ public:
   GetBackgroundParent() const
   {
     AssertIsOnBackgroundThread();
     MOZ_ASSERT(!IsActorDestroyed());
 
     return Manager()->Manager();
   }
 
+  DatabaseLoggingInfo*
+  GetLoggingInfo() const
+  {
+    AssertIsOnBackgroundThread();
+    MOZ_ASSERT(mFactory);
+
+    return mFactory->GetLoggingInfo();
+  }
+
   bool
   RegisterTransaction(TransactionBase* aTransaction);
 
   void
   UnregisterTransaction(TransactionBase* aTransaction);
 
   void
   SetActorAlive();
@@ -3125,16 +3160,17 @@ private:
   nsCOMPtr<mozIStorageConnection> mConnection;
   nsRefPtr<UpdateRefcountFunction> mUpdateFileRefcountFunction;
   nsInterfaceHashtable<nsCStringHashKey, mozIStorageStatement>
     mCachedStatements;
   nsTArray<nsRefPtr<FullObjectStoreMetadata>>
     mModifiedAutoIncrementObjectStoreMetadataArray;
   const uint64_t mTransactionId;
   const nsCString mDatabaseId;
+  const int64_t mLoggingSerialNumber;
   uint64_t mActiveRequestCount;
   Atomic<bool> mInvalidatedOnAnyThread;
   Mode mMode;
   bool mHasBeenActive;
   bool mActorDestroyed;
   bool mInvalidated;
 
 protected:
@@ -3243,16 +3279,31 @@ public:
   GetDatabase() const
   {
     AssertIsOnBackgroundThread();
     MOZ_ASSERT(mDatabase);
 
     return mDatabase;
   }
 
+  DatabaseLoggingInfo*
+  GetLoggingInfo() const
+  {
+    AssertIsOnBackgroundThread();
+    MOZ_ASSERT(mDatabase);
+
+    return mDatabase->GetLoggingInfo();
+  }
+
+  int64_t
+  LoggingSerialNumber() const
+  {
+    return mLoggingSerialNumber;
+  }
+
   bool
   IsAborted() const
   {
     AssertIsOnBackgroundThread();
 
     return NS_FAILED(mResultCode);
   }
 
@@ -3292,18 +3343,17 @@ public:
 
   void
   NoteFinishedRequest();
 
   void
   Invalidate();
 
 protected:
-  TransactionBase(Database* aDatabase,
-                  Mode aMode);
+  TransactionBase(Database* aDatabase, Mode aMode);
 
   virtual
   ~TransactionBase();
 
   void
   NoteActorDestroyed()
   {
     AssertIsOnBackgroundThread();
@@ -3415,23 +3465,17 @@ class TransactionBase::CommitOp MOZ_FINA
   , public TransactionThreadPool::FinishCallback
 {
   friend class TransactionBase;
 
   nsRefPtr<TransactionBase> mTransaction;
   nsresult mResultCode;
 
 private:
-  CommitOp(TransactionBase* aTransaction,
-           nsresult aResultCode)
-    : mTransaction(aTransaction)
-    , mResultCode(aResultCode)
-  {
-    MOZ_ASSERT(aTransaction);
-  }
+  CommitOp(TransactionBase* aTransaction, nsresult aResultCode);
 
   ~CommitOp()
   { }
 
   // Writes new autoIncrement counts to database.
   nsresult
   WriteAutoIncrementCounts();
 
@@ -3665,18 +3709,18 @@ class NormalTransaction MOZ_FINAL
 {
   friend class Database;
 
   nsTArray<nsRefPtr<FullObjectStoreMetadata>> mObjectStores;
 
 private:
   // This constructor is only called by Database.
   NormalTransaction(Database* aDatabase,
-                    nsTArray<nsRefPtr<FullObjectStoreMetadata>>& aObjectStores,
-                    TransactionBase::Mode aMode);
+                    TransactionBase::Mode aMode,
+                    nsTArray<nsRefPtr<FullObjectStoreMetadata>>& aObjectStores);
 
   // Reference counted.
   ~NormalTransaction()
   { }
 
   bool
   IsSameProcessActor();
 
@@ -4128,19 +4172,21 @@ class OpenDatabaseOp::VersionChangeOp MO
 {
   friend class OpenDatabaseOp;
 
   nsRefPtr<OpenDatabaseOp> mOpenDatabaseOp;
   const uint64_t mRequestedVersion;
   uint64_t mPreviousVersion;
 
 private:
-  explicit VersionChangeOp(OpenDatabaseOp* aOpenDatabaseOp)
+  explicit
+  VersionChangeOp(OpenDatabaseOp* aOpenDatabaseOp)
     : TransactionDatabaseOperationBase(
-                                     aOpenDatabaseOp->mVersionChangeTransaction)
+                                     aOpenDatabaseOp->mVersionChangeTransaction,
+                                     aOpenDatabaseOp->LoggingSerialNumber())
     , mOpenDatabaseOp(aOpenDatabaseOp)
     , mRequestedVersion(aOpenDatabaseOp->mRequestedVersion)
     , mPreviousVersion(aOpenDatabaseOp->mMetadata->mCommonMetadata.version())
   {
     MOZ_ASSERT(aOpenDatabaseOp);
     MOZ_ASSERT(mRequestedVersion);
   }
 
@@ -4209,18 +4255,21 @@ private:
 class DeleteDatabaseOp::VersionChangeOp MOZ_FINAL
   : public DatabaseOperationBase
 {
   friend class DeleteDatabaseOp;
 
   nsRefPtr<DeleteDatabaseOp> mDeleteDatabaseOp;
 
 private:
-  explicit VersionChangeOp(DeleteDatabaseOp* aDeleteDatabaseOp)
-    : mDeleteDatabaseOp(aDeleteDatabaseOp)
+  explicit
+  VersionChangeOp(DeleteDatabaseOp* aDeleteDatabaseOp)
+    : DatabaseOperationBase(aDeleteDatabaseOp->BackgroundChildLoggingId(),
+                            aDeleteDatabaseOp->LoggingSerialNumber())
+    , mDeleteDatabaseOp(aDeleteDatabaseOp)
   {
     MOZ_ASSERT(aDeleteDatabaseOp);
     MOZ_ASSERT(!aDeleteDatabaseOp->mDatabaseDirectoryPath.IsEmpty());
   }
 
   ~VersionChangeOp()
   { }
 
@@ -4986,17 +5035,17 @@ private:
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 };
 
 /*******************************************************************************
  * Other class declarations
  ******************************************************************************/
 
-struct DatabaseActorInfo
+struct DatabaseActorInfo MOZ_FINAL
 {
   friend class nsAutoPtr<DatabaseActorInfo>;
 
   nsRefPtr<FullDatabaseMetadata> mMetadata;
   nsTArray<Database*> mLiveDatabases;
   nsRefPtr<FactoryOp> mWaitingFactoryOp;
 
   DatabaseActorInfo(FullDatabaseMetadata* aMetadata,
@@ -5016,16 +5065,70 @@ private:
     MOZ_ASSERT(mLiveDatabases.IsEmpty());
     MOZ_ASSERT(!mWaitingFactoryOp ||
                !mWaitingFactoryOp->HasBlockedDatabases());
 
     MOZ_COUNT_DTOR(DatabaseActorInfo);
   }
 };
 
+class DatabaseLoggingInfo MOZ_FINAL
+{
+#ifdef DEBUG
+  // Just for potential warnings.
+  friend class Factory;
+#endif
+
+  LoggingInfo mLoggingInfo;
+
+public:
+  DatabaseLoggingInfo(const LoggingInfo& aLoggingInfo)
+    : mLoggingInfo(aLoggingInfo)
+  {
+    AssertIsOnBackgroundThread();
+  }
+
+  const nsID&
+  Id() const
+  {
+    AssertIsOnBackgroundThread();
+
+    return mLoggingInfo.backgroundChildLoggingId();
+  }
+
+  int64_t
+  NextTransactionSN(IDBTransaction::Mode aMode)
+  {
+    AssertIsOnBackgroundThread();
+    MOZ_ASSERT(mLoggingInfo.nextTransactionSerialNumber() < INT64_MAX);
+    MOZ_ASSERT(mLoggingInfo.nextVersionChangeTransactionSerialNumber() >
+                 INT64_MIN);
+
+    if (aMode == IDBTransaction::VERSION_CHANGE) {
+      return mLoggingInfo.nextVersionChangeTransactionSerialNumber()--;
+    }
+
+    return mLoggingInfo.nextTransactionSerialNumber()++;
+  }
+
+  uint64_t
+  NextRequestSN()
+  {
+    AssertIsOnBackgroundThread();
+    MOZ_ASSERT(mLoggingInfo.nextRequestSerialNumber() < UINT64_MAX);
+
+    return mLoggingInfo.nextRequestSerialNumber()++;
+  }
+
+  NS_INLINE_DECL_REFCOUNTING(DatabaseLoggingInfo)
+
+private:
+  ~DatabaseLoggingInfo();
+};
+
 class NonMainThreadHackBlobImpl MOZ_FINAL
   : public FileImplFile
 {
 public:
   NonMainThreadHackBlobImpl(nsIFile* aFile, FileInfo* aFileInfo)
     : FileImplFile(aFile, aFileInfo)
   {
     // Getting the content type is not currently supported off the main thread.
@@ -5519,43 +5622,51 @@ typedef nsClassHashtable<nsCStringHashKe
         DatabaseActorHashtable;
 
 StaticAutoPtr<DatabaseActorHashtable> gLiveDatabaseHashtable;
 
 StaticRefPtr<nsRunnable> gStartTransactionRunnable;
 
 StaticRefPtr<TransactionThreadPool> gTransactionThreadPool;
 
+typedef nsDataHashtable<nsIDHashKey, DatabaseLoggingInfo*>
+        DatabaseLoggingInfoHashtable;
+
+StaticAutoPtr<DatabaseLoggingInfoHashtable> gLoggingInfoHashtable;
+
 #ifdef DEBUG
 
 StaticRefPtr<DEBUGThreadSlower> gDEBUGThreadSlower;
 
 #endif // DEBUG
 
 } // anonymous namespace
 
 /*******************************************************************************
  * Exported functions
  ******************************************************************************/
 
 PBackgroundIDBFactoryParent*
-AllocPBackgroundIDBFactoryParent()
+AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo)
 {
   AssertIsOnBackgroundThread();
 
   if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonMainThread())) {
     return nullptr;
   }
 
-  nsRefPtr<Factory> actor = Factory::Create();
+  nsRefPtr<Factory> actor = Factory::Create(aLoggingInfo);
+  MOZ_ASSERT(actor);
+
   return actor.forget().take();
 }
 
 bool
-RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor)
+RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor,
+                                     const LoggingInfo& /* aLoggingInfo */)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
   MOZ_ASSERT(!QuotaClient::IsShuttingDownOnNonMainThread());
 
   return true;
 }
 
@@ -5722,37 +5833,52 @@ FullDatabaseMetadata::Duplicate() const
   if (NS_WARN_IF(mObjectStores.Count() !=
                  newMetadata->mObjectStores.Count())) {
     return nullptr;
   }
 
   return newMetadata.forget();
 }
 
+DatabaseLoggingInfo::~DatabaseLoggingInfo()
+{
+  AssertIsOnBackgroundThread();
+
+  if (gLoggingInfoHashtable) {
+    const nsID& backgroundChildLoggingId =
+      mLoggingInfo.backgroundChildLoggingId();
+
+    MOZ_ASSERT(gLoggingInfoHashtable->Get(backgroundChildLoggingId) == this);
+
+    gLoggingInfoHashtable->Remove(backgroundChildLoggingId);
+  }
+}
+
 /*******************************************************************************
  * Factory
  ******************************************************************************/
 
 uint64_t Factory::sFactoryInstanceCount = 0;
 
-Factory::Factory()
-  : mActorDestroyed(false)
+Factory::Factory(already_AddRefed<DatabaseLoggingInfo> aLoggingInfo)
+  : mLoggingInfo(Move(aLoggingInfo))
+  , mActorDestroyed(false)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(!QuotaClient::IsShuttingDownOnNonMainThread());
 }
 
 Factory::~Factory()
 {
   MOZ_ASSERT(mActorDestroyed);
 }
 
 // static
 already_AddRefed<Factory>
-Factory::Create()
+Factory::Create(const LoggingInfo& aLoggingInfo)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(!QuotaClient::IsShuttingDownOnNonMainThread());
 
   // If this is the first instance then we need to do some initialization.
   if (!sFactoryInstanceCount) {
     if (!gTransactionThreadPool) {
       nsRefPtr<TransactionThreadPool> threadPool =
@@ -5765,16 +5891,19 @@ Factory::Create()
     }
 
     MOZ_ASSERT(!gLiveDatabaseHashtable);
     gLiveDatabaseHashtable = new DatabaseActorHashtable();
 
     MOZ_ASSERT(!gStartTransactionRunnable);
     gStartTransactionRunnable = new nsRunnable();
 
+    MOZ_ASSERT(!gLoggingInfoHashtable);
+    gLoggingInfoHashtable = new DatabaseLoggingInfoHashtable();
+
 #ifdef DEBUG
     if (kDEBUGThreadPriority != nsISupportsPriority::PRIORITY_NORMAL) {
       NS_WARNING("PBackground thread debugging enabled, priority has been "
                  "modified!");
       nsCOMPtr<nsISupportsPriority> thread =
         do_QueryInterface(NS_GetCurrentThread());
       MOZ_ASSERT(thread);
 
@@ -5790,33 +5919,58 @@ Factory::Create()
 
       gDEBUGThreadSlower = new DEBUGThreadSlower();
 
       MOZ_ALWAYS_TRUE(NS_SUCCEEDED(thread->AddObserver(gDEBUGThreadSlower)));
     }
 #endif // DEBUG
   }
 
-  nsRefPtr<Factory> actor = new Factory();
+  nsRefPtr<DatabaseLoggingInfo> loggingInfo =
+    gLoggingInfoHashtable->Get(aLoggingInfo.backgroundChildLoggingId());
+  if (loggingInfo) {
+    MOZ_ASSERT(aLoggingInfo.backgroundChildLoggingId() == loggingInfo->Id());
+#if !DISABLE_ASSERTS_FOR_FUZZING
+    NS_WARN_IF_FALSE(aLoggingInfo.nextTransactionSerialNumber() ==
+                       loggingInfo->mLoggingInfo.nextTransactionSerialNumber(),
+                     "NextTransactionSerialNumber doesn't match!");
+    NS_WARN_IF_FALSE(aLoggingInfo.nextVersionChangeTransactionSerialNumber() ==
+                       loggingInfo->mLoggingInfo.
+                         nextVersionChangeTransactionSerialNumber(),
+                     "NextVersionChangeTransactionSerialNumber doesn't match!");
+    NS_WARN_IF_FALSE(aLoggingInfo.nextRequestSerialNumber() ==
+                       loggingInfo->mLoggingInfo.nextRequestSerialNumber(),
+                     "NextRequestSerialNumber doesn't match!");
+#endif // !DISABLE_ASSERTS_FOR_FUZZING
+  } else {
+    loggingInfo = new DatabaseLoggingInfo(aLoggingInfo);
+    gLoggingInfoHashtable->Put(aLoggingInfo.backgroundChildLoggingId(),
+                               loggingInfo);
+  }
+
+  nsRefPtr<Factory> actor = new Factory(loggingInfo.forget());
 
   sFactoryInstanceCount++;
 
   return actor.forget();
 }
 
 void
 Factory::ActorDestroy(ActorDestroyReason aWhy)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(!mActorDestroyed);
 
   mActorDestroyed = true;
 
   // Clean up if there are no more instances.
   if (!(--sFactoryInstanceCount)) {
+    MOZ_ASSERT(gLoggingInfoHashtable);
+    gLoggingInfoHashtable = nullptr;
+
     MOZ_ASSERT(gStartTransactionRunnable);
     gStartTransactionRunnable = nullptr;
 
     MOZ_ASSERT(gLiveDatabaseHashtable);
     MOZ_ASSERT(!gLiveDatabaseHashtable->Count());
     gLiveDatabaseHashtable = nullptr;
 
 #ifdef DEBUG
@@ -5848,16 +6002,26 @@ bool
 Factory::RecvDeleteMe()
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(!mActorDestroyed);
 
   return PBackgroundIDBFactoryParent::Send__delete__(this);
 }
 
+bool
+Factory::RecvIncrementLoggingRequestSerialNumber()
+{
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(mLoggingInfo);
+
+  mLoggingInfo->NextRequestSN();
+  return true;
+}
+
 PBackgroundIDBFactoryRequestParent*
 Factory::AllocPBackgroundIDBFactoryRequestParent(
                                             const FactoryRequestParams& aParams)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aParams.type() != FactoryRequestParams::T__None);
 
   if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonMainThread())) {
@@ -6072,17 +6236,17 @@ Database::Invalidate()
   };
 
   if (mInvalidated) {
     return;
   }
 
   mInvalidated = true;
 
-  if (!mActorDestroyed) {
+  if (mActorWasAlive && !mActorDestroyed) {
     unused << SendInvalidate();
   }
 
   if (!Helper::InvalidateTransactions(mTransactions)) {
     NS_WARNING("Failed to abort all transactions!");
   }
 
   MOZ_ALWAYS_TRUE(CloseInternal());
@@ -6324,31 +6488,40 @@ Database::AllocPBackgroundIDBTransaction
 
   FallibleTArray<nsRefPtr<FullObjectStoreMetadata>> fallibleObjectStores;
   if (NS_WARN_IF(!fallibleObjectStores.SetCapacity(nameCount))) {
     return nullptr;
   }
 
   for (uint32_t nameIndex = 0; nameIndex < nameCount; nameIndex++) {
     const nsString& name = aObjectStoreNames[nameIndex];
+
+    if (nameIndex) {
+      // Make sure that this name is sorted properly and not a duplicate.
+      if (NS_WARN_IF(name <= aObjectStoreNames[nameIndex - 1])) {
+        ASSERT_UNLESS_FUZZING();
+        return nullptr;
+      }
+    }
+
     const uint32_t oldLength = fallibleObjectStores.Length();
 
     Closure closure(name, fallibleObjectStores);
     objectStores.EnumerateRead(Closure::Find, &closure);
 
     if (NS_WARN_IF((oldLength + 1) != fallibleObjectStores.Length())) {
       return nullptr;
     }
   }
 
   nsTArray<nsRefPtr<FullObjectStoreMetadata>> infallibleObjectStores;
   infallibleObjectStores.SwapElements(fallibleObjectStores);
 
   nsRefPtr<NormalTransaction> transaction =
-    new NormalTransaction(this, infallibleObjectStores, aMode);
+    new NormalTransaction(this, aMode, infallibleObjectStores);
 
   MOZ_ASSERT(infallibleObjectStores.IsEmpty());
 
   return transaction.forget().take();
 }
 
 bool
 Database::RecvPBackgroundIDBTransactionConstructor(
@@ -6367,23 +6540,23 @@ Database::RecvPBackgroundIDBTransactionC
     // This is an expected race. We don't want the child to die here, just don't
     // actually do any work.
     return true;
   }
 
   auto* transaction = static_cast<NormalTransaction*>(aActor);
 
   // Add a placeholder for this transaction immediately.
-  gTransactionThreadPool->Dispatch(transaction->TransactionId(),
-                                   mMetadata->mDatabaseId,
-                                   aObjectStoreNames,
-                                   aMode,
-                                   gStartTransactionRunnable,
-                                   /* aFinish */ false,
-                                   /* aFinishCallback */ nullptr);
+  gTransactionThreadPool->Start(transaction->TransactionId(),
+                                mMetadata->mDatabaseId,
+                                aObjectStoreNames,
+                                aMode,
+                                GetLoggingInfo()->Id(),
+                                transaction->LoggingSerialNumber(),
+                                gStartTransactionRunnable);
 
   transaction->SetActive();
 
   if (NS_WARN_IF(!RegisterTransaction(transaction))) {
     IDB_REPORT_INTERNAL_ERR();
     transaction->Abort(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR, /* aForce */ false);
     return true;
   }
@@ -6467,36 +6640,38 @@ Database::RecvClose()
 
   return true;
 }
 
 /*******************************************************************************
  * TransactionBase
  ******************************************************************************/
 
-TransactionBase::TransactionBase(Database* aDatabase,
-                                 Mode aMode)
+TransactionBase::TransactionBase(Database* aDatabase, Mode aMode)
   : mDatabase(aDatabase)
   , mTransactionId(gTransactionThreadPool->NextTransactionId())
   , mDatabaseId(aDatabase->Id())
+  , mLoggingSerialNumber(aDatabase->GetLoggingInfo()->NextTransactionSN(aMode))
   , mActiveRequestCount(0)
   , mInvalidatedOnAnyThread(false)
   , mMode(aMode)
   , mHasBeenActive(false)
   , mActorDestroyed(false)
   , mInvalidated(false)
   , mResultCode(NS_OK)
   , mCommitOrAbortReceived(false)
   , mCommittedOrAborted(false)
   , mForceAborted(false)
   , mTransactionThread(nullptr)
   , mSavepointCount(0)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aDatabase);
+  MOZ_ASSERT(mTransactionId);
+  MOZ_ASSERT(mLoggingSerialNumber);
 }
 
 TransactionBase::~TransactionBase()
 {
   MOZ_ASSERT(!mSavepointCount);
   MOZ_ASSERT(!mActiveRequestCount);
   MOZ_ASSERT(mActorDestroyed);
   MOZ_ASSERT_IF(mHasBeenActive, mCommittedOrAborted);
@@ -7616,18 +7791,18 @@ TransactionBase::ReleaseBackgroundThread
 }
 
 /*******************************************************************************
  * NormalTransaction
  ******************************************************************************/
 
 NormalTransaction::NormalTransaction(
                      Database* aDatabase,
-                     nsTArray<nsRefPtr<FullObjectStoreMetadata>>& aObjectStores,
-                     TransactionBase::Mode aMode)
+                     TransactionBase::Mode aMode,
+                     nsTArray<nsRefPtr<FullObjectStoreMetadata>>& aObjectStores)
   : TransactionBase(aDatabase, aMode)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(!aObjectStores.IsEmpty());
 
   mObjectStores.SwapElements(aObjectStores);
 }
 
@@ -9914,18 +10089,16 @@ DatabaseOfflineStorage::Invalidate()
 
 /*******************************************************************************
  * Local class implementations
  ******************************************************************************/
 
 NS_IMPL_ISUPPORTS(CompressDataBlobsFunction, mozIStorageFunction)
 NS_IMPL_ISUPPORTS(EncodeKeysFunction, mozIStorageFunction)
 
-uint64_t DatabaseOperationBase::sNextSerialNumber = 0;
-
 // static
 void
 DatabaseOperationBase::GetBindingClauseForKeyRange(
                                             const SerializedKeyRange& aKeyRange,
                                             const nsACString& aKeyColumnName,
                                             nsAutoCString& aBindingClause)
 {
   MOZ_ASSERT(!IsOnBackgroundThread());
@@ -10324,17 +10497,19 @@ AutoSetProgressHandler::Register(
 
   return NS_OK;
 }
 
 FactoryOp::FactoryOp(Factory* aFactory,
                      already_AddRefed<ContentParent> aContentParent,
                      const CommonFactoryRequestParams& aCommonParams,
                      bool aDeleting)
-  : mFactory(aFactory)
+  : DatabaseOperationBase(aFactory->GetLoggingInfo()->Id(),
+                          aFactory->GetLoggingInfo()->NextRequestSN())
+  , mFactory(aFactory)
   , mContentParent(Move(aContentParent))
   , mCommonParams(aCommonParams)
   , mState(State_Initial)
   , mIsApp(false)
   , mHasUnlimStoragePerm(false)
   , mEnforcingQuota(true)
   , mDeleting(aDeleting)
   , mBlockedQuotaManager(false)
@@ -11071,17 +11246,17 @@ OpenDatabaseOp::QuotaManagerOpen()
 
 nsresult
 OpenDatabaseOp::DoDatabaseWork()
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(mState == State_DatabaseWorkOpen);
 
   PROFILER_LABEL("IndexedDB",
-                 "OpenDatabaseHelper::DoDatabaseWork",
+                 "OpenDatabaseOp::DoDatabaseWork",
                  js::ProfileEntry::Category::STORAGE);
 
   if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonMainThread()) ||
       !OperationMayProceed()) {
     IDB_REPORT_INTERNAL_ERR();
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
@@ -11644,37 +11819,44 @@ OpenDatabaseOp::SendBlockedNotification(
 }
 
 nsresult
 OpenDatabaseOp::DispatchToWorkThread()
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mState == State_WaitingForTransactionsToComplete);
   MOZ_ASSERT(mVersionChangeTransaction);
+  MOZ_ASSERT(mVersionChangeTransaction->GetMode() ==
+               IDBTransaction::VERSION_CHANGE);
   MOZ_ASSERT(mMaybeBlockedDatabases.IsEmpty());
 
   if (IsActorDestroyed()) {
     IDB_REPORT_INTERNAL_ERR();
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   mState = State_DatabaseWorkVersionChange;
 
   // Intentionally empty.
   nsTArray<nsString> objectStoreNames;
 
+  const int64_t loggingSerialNumber =
+    mVersionChangeTransaction->LoggingSerialNumber();
+  const nsID& backgroundChildLoggingId =
+    mVersionChangeTransaction->GetLoggingInfo()->Id();
+
   nsRefPtr<VersionChangeOp> versionChangeOp = new VersionChangeOp(this);
 
-  gTransactionThreadPool->Dispatch(mVersionChangeTransaction->TransactionId(),
-                                   mVersionChangeTransaction->DatabaseId(),
-                                   objectStoreNames,
-                                   mVersionChangeTransaction->GetMode(),
-                                   versionChangeOp,
-                                   /* aFinish */ false,
-                                   /* aFinishCallback */ nullptr);
+  gTransactionThreadPool->Start(mVersionChangeTransaction->TransactionId(),
+                                mVersionChangeTransaction->DatabaseId(),
+                                objectStoreNames,
+                                mVersionChangeTransaction->GetMode(),
+                                backgroundChildLoggingId,
+                                loggingSerialNumber,
+                                versionChangeOp);
 
   mVersionChangeTransaction->SetActive();
 
   mVersionChangeTransaction->NoteActiveRequest();
 
   if (NS_WARN_IF(!mDatabase->RegisterTransaction(mVersionChangeTransaction))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -12104,17 +12286,17 @@ VersionChangeOp::DoDatabaseWork(Transact
 
   if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonMainThread()) ||
       !OperationMayProceed()) {
     IDB_REPORT_INTERNAL_ERR();
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   PROFILER_LABEL("IndexedDB",
-                 "VersionChangeOp::DoDatabaseWork",
+                 "OpenDatabaseOp::VersionChangeOp::DoDatabaseWork",
                  js::ProfileEntry::Category::STORAGE);
 
   mozIStorageConnection* connection = aTransaction->Connection();
   MOZ_ASSERT(connection);
 
   TransactionBase::AutoSavepoint autoSave;
   nsresult rv = autoSave.Start(aTransaction);
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -12792,20 +12974,37 @@ VersionChangeOp::Run()
                                                          NS_DISPATCH_NORMAL)));
   }
 
   return NS_OK;
 }
 
 TransactionDatabaseOperationBase::TransactionDatabaseOperationBase(
                                                   TransactionBase* aTransaction)
-  : mTransaction(aTransaction)
+  : DatabaseOperationBase(aTransaction->GetLoggingInfo()->Id(),
+                          aTransaction->GetLoggingInfo()->NextRequestSN())
+  , mTransaction(aTransaction)
+  , mTransactionLoggingSerialNumber(aTransaction->LoggingSerialNumber())
   , mTransactionIsAborted(aTransaction->IsAborted())
 {
   MOZ_ASSERT(aTransaction);
+  MOZ_ASSERT(LoggingSerialNumber());
+}
+
+TransactionDatabaseOperationBase::TransactionDatabaseOperationBase(
+                                                  TransactionBase* aTransaction,
+                                                  uint64_t aLoggingSerialNumber)
+  : DatabaseOperationBase(aTransaction->GetLoggingInfo()->Id(),
+                          aLoggingSerialNumber)
+  , mTransaction(aTransaction)
+  , mTransactionLoggingSerialNumber(aTransaction->LoggingSerialNumber())
+  , mTransactionIsAborted(aTransaction->IsAborted())
+{
+  MOZ_ASSERT(aTransaction);
+  MOZ_ASSERT(LoggingSerialNumber());
 }
 
 TransactionDatabaseOperationBase::~TransactionDatabaseOperationBase()
 {
   MOZ_ASSERT(!mTransaction,
              "TransactionDatabaseOperationBase::Cleanup() was not called by a "
              "subclass!");
 }
@@ -12837,16 +13036,20 @@ TransactionDatabaseOperationBase::Dispat
 
 void
 TransactionDatabaseOperationBase::RunOnTransactionThread()
 {
   MOZ_ASSERT(!IsOnBackgroundThread());
   MOZ_ASSERT(mTransaction);
   MOZ_ASSERT(NS_SUCCEEDED(mResultCode));
 
+  PROFILER_LABEL("IndexedDB",
+                 "TransactionDatabaseOperationBase::RunOnTransactionThread",
+                 js::ProfileEntry::Category::STORAGE);
+
   // There are several cases where we don't actually have to to any work here.
 
   if (mTransactionIsAborted) {
     // This transaction is already set to be aborted.
     mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR;
   } else if (mTransaction->IsInvalidatedOnAnyThread()) {
     // This transaction is being invalidated.
     mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@@ -12863,17 +13066,32 @@ TransactionDatabaseOperationBase::RunOnT
     } else {
       mTransaction->AssertIsOnTransactionThread();
 
       AutoSetProgressHandler autoProgress;
       rv = autoProgress.Register(this, mTransaction->Connection());
       if (NS_WARN_IF(NS_FAILED(rv))) {
         mResultCode = rv;
       } else {
+        IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld] Request[%llu]: "
+                       "Beginning database work",
+                     "IndexedDB %s: P T[%lld] R[%llu]: DB Start",
+                     IDB_LOG_ID_STRING(mBackgroundChildLoggingId),
+                     mTransactionLoggingSerialNumber,
+                     mLoggingSerialNumber);
+
         rv = DoDatabaseWork(mTransaction);
+
+        IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld] Request[%llu]: "
+                       "Finished database work",
+                     "IndexedDB %s: P T[%lld] R[%llu]: DB End",
+                     IDB_LOG_ID_STRING(mBackgroundChildLoggingId),
+                     mTransactionLoggingSerialNumber,
+                     mLoggingSerialNumber);
+
         if (NS_FAILED(rv)) {
           mResultCode = rv;
         }
       }
     }
   }
 
   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(mOwningThread->Dispatch(this,
@@ -12945,16 +13163,28 @@ TransactionDatabaseOperationBase::Run()
     RunOnOwningThread();
   } else {
     RunOnTransactionThread();
   }
 
   return NS_OK;
 }
 
+TransactionBase::
+
+CommitOp::CommitOp(TransactionBase* aTransaction, nsresult aResultCode)
+  : DatabaseOperationBase(aTransaction->GetLoggingInfo()->Id(),
+                          aTransaction->GetLoggingInfo()->NextRequestSN())
+  , mTransaction(aTransaction)
+  , mResultCode(aResultCode)
+{
+  MOZ_ASSERT(aTransaction);
+  MOZ_ASSERT(LoggingSerialNumber());
+}
+
 nsresult
 TransactionBase::
 CommitOp::WriteAutoIncrementCounts()
 {
   AssertIsOnTransactionThread();
   MOZ_ASSERT(mTransaction);
 
   const nsTArray<nsRefPtr<FullObjectStoreMetadata>>& metadataArray =
@@ -13050,16 +13280,23 @@ CommitOp::Run()
   nsCOMPtr<mozIStorageConnection>& connection = mTransaction->mConnection;
 
   if (!connection) {
     return NS_OK;
   }
 
   AssertIsOnTransactionThread();
 
+  IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld] Request[%llu]: "
+                 "Beginning database work",
+               "IndexedDB %s: P T[%lld] R[%llu]: DB Start",
+               IDB_LOG_ID_STRING(mBackgroundChildLoggingId),
+               mTransaction->LoggingSerialNumber(),
+               mLoggingSerialNumber);
+
   if (NS_SUCCEEDED(mResultCode) && mTransaction->mUpdateFileRefcountFunction) {
     mResultCode = mTransaction->
       mUpdateFileRefcountFunction->WillCommit(connection);
   }
 
   if (NS_SUCCEEDED(mResultCode)) {
     mResultCode = WriteAutoIncrementCounts();
   }
@@ -13090,16 +13327,23 @@ CommitOp::Run()
 
   if (mTransaction->mUpdateFileRefcountFunction) {
     NS_NAMED_LITERAL_CSTRING(functionName, "update_refcount");
     MOZ_ALWAYS_TRUE(NS_SUCCEEDED(connection->RemoveFunction(functionName)));
   }
 
   mTransaction->ReleaseTransactionThreadObjects();
 
+  IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld] Request[%llu]: "
+                 "Finished database work",
+               "IndexedDB %s: P T[%lld] R[%llu]: DB End",
+               IDB_LOG_ID_STRING(mBackgroundChildLoggingId),
+               mTransaction->LoggingSerialNumber(),
+               mLoggingSerialNumber);
+
   return NS_OK;
 }
 
 void
 TransactionBase::
 CommitOp::TransactionFinishedBeforeUnblock()
 {
   AssertIsOnBackgroundThread();
@@ -13116,23 +13360,24 @@ CommitOp::TransactionFinishedBeforeUnblo
 
 void
 TransactionBase::
 CommitOp::TransactionFinishedAfterUnblock()
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(mTransaction);
 
-  PROFILER_LABEL("IndexedDB",
-                 "CommitOp::TransactionFinishedAfterUnblock",
-                 js::ProfileEntry::Category::STORAGE);
-
-  IDB_PROFILER_MARK("IndexedDB Transaction %llu: Complete (rv = %lu)",
-                    "IDBTransaction[%llu] MT Complete",
-                    mTransaction->TransactionId(), mResultCode);
+  if (!mTransaction->IsActorDestroyed()) {
+    IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld]: "
+                   "Finished with result 0x%x",
+                 "IndexedDB %s: P T[%lld]: Transaction finished (0x%x)",
+                 IDB_LOG_ID_STRING(mTransaction->GetLoggingInfo()->Id()),
+                 mTransaction->LoggingSerialNumber(),
+                 mResultCode);
+  }
 
   mTransaction->ReleaseBackgroundThreadObjects();
 
   if (!mTransaction->IsActorDestroyed()) {
     mTransaction->SendCompleteNotification(ClampResultCode(mResultCode));
   }
 
   mTransaction->GetDatabase()->UnregisterTransaction(mTransaction);
@@ -16599,16 +16844,20 @@ OpenOp::DoDatabaseWork(TransactionBase* 
   MOZ_ASSERT(aTransaction);
   aTransaction->AssertIsOnTransactionThread();
   MOZ_ASSERT(mCursor);
   MOZ_ASSERT(mCursor->mContinueQuery.IsEmpty());
   MOZ_ASSERT(mCursor->mContinueToQuery.IsEmpty());
   MOZ_ASSERT(mCursor->mKey.IsUnset());
   MOZ_ASSERT(mCursor->mRangeKey.IsUnset());
 
+  PROFILER_LABEL("IndexedDB",
+                 "Cursor::OpenOp::DoDatabaseWork",
+                 js::ProfileEntry::Category::STORAGE);
+
   nsresult rv;
 
   switch (mCursor->mType) {
     case OpenCursorParams::TObjectStoreOpenCursorParams:
       rv = DoObjectStoreDatabaseWork(aTransaction);
       break;
 
     case OpenCursorParams::TObjectStoreOpenKeyCursorParams:
--- a/dom/indexedDB/ActorsParent.h
+++ b/dom/indexedDB/ActorsParent.h
@@ -2,40 +2,43 @@
  * 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_indexeddb_actorsparent_h__
 #define mozilla_dom_indexeddb_actorsparent_h__
 
 template <class> struct already_AddRefed;
 class nsCString;
+struct nsID;
 class nsIPrincipal;
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
 class TabParent;
 
 namespace quota {
 
 class Client;
 
 } // namespace quota
 
 namespace indexedDB {
 
+class LoggingInfo;
 class PBackgroundIDBFactoryParent;
 class PIndexedDBPermissionRequestParent;
 
 PBackgroundIDBFactoryParent*
-AllocPBackgroundIDBFactoryParent();
+AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo);
 
 bool
-RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor);
+RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor,
+                                     const LoggingInfo& aLoggingInfo);
 
 bool
 DeallocPBackgroundIDBFactoryParent(PBackgroundIDBFactoryParent* aActor);
 
 PIndexedDBPermissionRequestParent*
 AllocPIndexedDBPermissionRequestParent(nsPIDOMWindow* aWindow,
                                        nsIPrincipal* aPrincipal);
 
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -421,46 +421,51 @@ IDBCursor::Continue(JSContext* aCx,
         }
         break;
 
       default:
         MOZ_CRASH("Unknown direction type!");
     }
   }
 
+  const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
+  mRequest->SetLoggingSerialNumber(requestSerialNumber);
+
+  if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "cursor(%s).continue(%s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continue()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 requestSerialNumber,
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(mSourceObjectStore),
+                 IDB_LOG_STRINGIFY(mDirection),
+                 IDB_LOG_STRINGIFY(key));
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "index(%s).cursor(%s).continue(%s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continue()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 requestSerialNumber,
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()),
+                 IDB_LOG_STRINGIFY(mSourceIndex),
+                 IDB_LOG_STRINGIFY(mDirection),
+                 IDB_LOG_STRINGIFY(key));
+  }
+
   mBackgroundActor->SendContinueInternal(ContinueParams(key));
 
   mContinueCalled = true;
-
-#ifdef IDB_PROFILER_USE_MARKS
-  if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s).cursor(%s)."
-                      "continue(%s)",
-                      "IDBRequest[%llu] MT IDBCursor.continue()",
-                      Request()->GetSerialNumber(),
-                      IDB_PROFILER_STRING(Transaction()->Database()),
-                      IDB_PROFILER_STRING(Transaction()),
-                      IDB_PROFILER_STRING(mSourceObjectStore),
-                      IDB_PROFILER_STRING(mDirection),
-                      key.IsUnset() ? "" : IDB_PROFILER_STRING(key));
-  } else {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s).index(%s)."
-                      "cursor(%s).continue(%s)",
-                      "IDBRequest[%llu] MT IDBCursor.continue()",
-                      Request()->GetSerialNumber(),
-                      IDB_PROFILER_STRING(Transaction()->Database()),
-                      IDB_PROFILER_STRING(Transaction()),
-                      IDB_PROFILER_STRING(mSourceIndex->ObjectStore()),
-                      IDB_PROFILER_STRING(mSourceIndex),
-                      IDB_PROFILER_STRING(mDirection),
-                      key.IsUnset() ? "" : IDB_PROFILER_STRING(key));
-  }
-#endif
 }
 
 void
 IDBCursor::Advance(uint32_t aCount, ErrorResult &aRv)
 {
   AssertIsOnOwningThread();
 
   if (!mTransaction->IsOpen()) {
@@ -473,46 +478,51 @@ IDBCursor::Advance(uint32_t aCount, Erro
     return;
   }
 
   if (!aCount) {
     aRv.ThrowTypeError(MSG_INVALID_ADVANCE_COUNT);
     return;
   }
 
+  const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
+  mRequest->SetLoggingSerialNumber(requestSerialNumber);
+
+  if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "cursor(%s).advance(%ld)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.advance()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 requestSerialNumber,
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(mSourceObjectStore),
+                 IDB_LOG_STRINGIFY(mDirection),
+                 aCount);
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "index(%s).cursor(%s).advance(%ld)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.advance()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 requestSerialNumber,
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()),
+                 IDB_LOG_STRINGIFY(mSourceIndex),
+                 IDB_LOG_STRINGIFY(mDirection),
+                 aCount);
+  }
+
   mBackgroundActor->SendContinueInternal(AdvanceParams(aCount));
 
   mContinueCalled = true;
-
-#ifdef IDB_PROFILER_USE_MARKS
-  {
-    if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) {
-      IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                        "database(%s).transaction(%s).objectStore(%s)."
-                        "cursor(%s).advance(%ld)",
-                        "IDBRequest[%llu] MT IDBCursor.advance()",
-                        Request()->GetSerialNumber(),
-                        IDB_PROFILER_STRING(Transaction()->Database()),
-                        IDB_PROFILER_STRING(Transaction()),
-                        IDB_PROFILER_STRING(mSourceObjectStore),
-                        IDB_PROFILER_STRING(mDirection), aCount);
-    } else {
-      IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                        "database(%s).transaction(%s).objectStore(%s)."
-                        "index(%s).cursor(%s).advance(%ld)",
-                        "IDBRequest[%llu] MT IDBCursor.advance()",
-                        Request()->GetSerialNumber(),
-                        IDB_PROFILER_STRING(Transaction()->Database()),
-                        IDB_PROFILER_STRING(Transaction()),
-                        IDB_PROFILER_STRING(mSourceIndex->ObjectStore()),
-                        IDB_PROFILER_STRING(mSourceIndex),
-                        IDB_PROFILER_STRING(mDirection), aCount);
-    }
-  }
-#endif
 }
 
 already_AddRefed<IDBRequest>
 IDBCursor::Update(JSContext* aCx, JS::Handle<JS::Value> aValue,
                   ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
 
@@ -558,67 +568,74 @@ IDBCursor::Update(JSContext* aCx, JS::Ha
       return nullptr;
     }
 
     if (key != primaryKey) {
       aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
       return nullptr;
     }
 
-    request = objectStore->Put(aCx, aValue, JS::UndefinedHandleValue, aRv);
+    request = objectStore->AddOrPut(aCx,
+                                    aValue,
+                                    /* aKey */ JS::UndefinedHandleValue,
+                                    /* aOverwrite */ true,
+                                    /* aFromCursor */ true,
+                                    aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
   }
   else {
     JS::Rooted<JS::Value> keyVal(aCx);
     aRv = primaryKey.ToJSVal(aCx, &keyVal);
     if (aRv.Failed()) {
       return nullptr;
     }
 
-    request = objectStore->Put(aCx, aValue, keyVal, aRv);
+    request = objectStore->AddOrPut(aCx,
+                                    aValue,
+                                    keyVal,
+                                    /* aOverwrite */ true,
+                                    /* aFromCursor */ true,
+                                    aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
   }
 
   request->SetSource(this);
 
-#ifdef IDB_PROFILER_USE_MARKS
-  {
-    uint64_t requestSerial = request->GetSerialNumber();
-    if (mType == Type_ObjectStore) {
-      IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                        "database(%s).transaction(%s).objectStore(%s)."
-                        "cursor(%s).update(%s)",
-                        "IDBRequest[%llu] MT IDBCursor.update()",
-                        requestSerial,
-                        IDB_PROFILER_STRING(mTransaction->Database()),
-                        IDB_PROFILER_STRING(mTransaction),
-                        IDB_PROFILER_STRING(objectStore),
-                        IDB_PROFILER_STRING(mDirection),
-                        mObjectStore->HasValidKeyPath() ? "" :
-                          IDB_PROFILER_STRING(primaryKey));
-    } else {
-      IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                        "database(%s).transaction(%s).objectStore(%s)."
-                        "index(%s).cursor(%s).update(%s)",
-                        "IDBRequest[%llu] MT IDBCursor.update()",
-                        requestSerial,
-                        IDB_PROFILER_STRING(mTransaction->Database()),
-                        IDB_PROFILER_STRING(mTransaction),
-                        IDB_PROFILER_STRING(objectStore),
-                        IDB_PROFILER_STRING(mSourceIndex),
-                        IDB_PROFILER_STRING(mDirection),
-                        mObjectStore->HasValidKeyPath() ? "" :
-                          IDB_PROFILER_STRING(primaryKey));
-    }
+  if (mType == Type_ObjectStore) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "cursor(%s).update(%s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(objectStore),
+                 IDB_LOG_STRINGIFY(mDirection),
+                 IDB_LOG_STRINGIFY(objectStore, primaryKey));
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "index(%s).cursor(%s).update(%s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(objectStore),
+                 IDB_LOG_STRINGIFY(mSourceIndex),
+                 IDB_LOG_STRINGIFY(mDirection),
+                 IDB_LOG_STRINGIFY(objectStore, primaryKey));
   }
-#endif
 
   return request.forget();
 }
 
 already_AddRefed<IDBRequest>
 IDBCursor::Delete(JSContext* aCx, ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
@@ -653,54 +670,52 @@ IDBCursor::Delete(JSContext* aCx, ErrorR
   const Key& primaryKey = (mType == Type_ObjectStore) ? mKey : mPrimaryKey;
 
   JS::Rooted<JS::Value> key(aCx);
   aRv = primaryKey.ToJSVal(aCx, &key);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
-  nsRefPtr<IDBRequest> request = objectStore->Delete(aCx, key, aRv);
+  nsRefPtr<IDBRequest> request =
+    objectStore->DeleteInternal(aCx, key, /* aFromCursor */ true, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   request->SetSource(this);
 
-#ifdef IDB_PROFILER_USE_MARKS
-  {
-    uint64_t requestSerial = request->GetSerialNumber();
-    if (mType == Type_ObjectStore) {
-      IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                        "database(%s).transaction(%s).objectStore(%s)."
-                        "cursor(%s).delete(%s)",
-                        "IDBRequest[%llu] MT IDBCursor.delete()",
-                        requestSerial,
-                        IDB_PROFILER_STRING(mTransaction->Database()),
-                        IDB_PROFILER_STRING(mTransaction),
-                        IDB_PROFILER_STRING(objectStore),
-                        IDB_PROFILER_STRING(mDirection),
-                        mObjectStore->HasValidKeyPath() ? "" :
-                          IDB_PROFILER_STRING(primaryKey));
-    } else {
-      IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                        "database(%s).transaction(%s).objectStore(%s)."
-                        "index(%s).cursor(%s).delete(%s)",
-                        "IDBRequest[%llu] MT IDBCursor.delete()",
-                        requestSerial,
-                        IDB_PROFILER_STRING(mTransaction->Database()),
-                        IDB_PROFILER_STRING(mTransaction),
-                        IDB_PROFILER_STRING(objectStore),
-                        IDB_PROFILER_STRING(mSourceIndex),
-                        IDB_PROFILER_STRING(mDirection),
-                        mObjectStore->HasValidKeyPath() ? "" :
-                          IDB_PROFILER_STRING(primaryKey));
-    }
+  if (mType == Type_ObjectStore) {
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "database(%s).transaction(%s).objectStore(%s)."
+                 "cursor(%s).delete(%s)",
+               "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()",
+               IDB_LOG_ID_STRING(),
+               mTransaction->LoggingSerialNumber(),
+               request->LoggingSerialNumber(),
+               IDB_LOG_STRINGIFY(mTransaction->Database()),
+               IDB_LOG_STRINGIFY(mTransaction),
+               IDB_LOG_STRINGIFY(objectStore),
+               IDB_LOG_STRINGIFY(mDirection),
+               IDB_LOG_STRINGIFY(objectStore, primaryKey));
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "index(%s).cursor(%s).delete(%s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(objectStore),
+                 IDB_LOG_STRINGIFY(mSourceIndex),
+                 IDB_LOG_STRINGIFY(mDirection),
+                 IDB_LOG_STRINGIFY(objectStore, primaryKey));
   }
-#endif
 
   return request.forget();
 }
 
 void
 IDBCursor::Reset(Key&& aKey, StructuredCloneReadInfo&& aValue)
 {
   AssertIsOnOwningThread();
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -501,22 +501,30 @@ IDBDatabase::CreateObjectStore(
     // indexes.
     RefreshSpec(/* aMayDelete */ false);
   }
 
   nsRefPtr<IDBObjectStore> objectStore =
     transaction->CreateObjectStore(*newSpec);
   MOZ_ASSERT(objectStore);
 
-  IDB_PROFILER_MARK("IndexedDB Pseudo-request: "
-                    "database(%s).transaction(%s).createObjectStore(%s)",
-                    "MT IDBDatabase.createObjectStore()",
-                    IDB_PROFILER_STRING(this),
-                    IDB_PROFILER_STRING(aTransaction),
-                    IDB_PROFILER_STRING(objectStore));
+  // Don't do this in the macro because we always need to increment the serial
+  // number to keep in sync with the parent.
+  const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
+
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "database(%s).transaction(%s).createObjectStore(%s)",
+               "IndexedDB %s: C T[%lld] R[%llu]: "
+                 "IDBDatabase.createObjectStore()",
+               IDB_LOG_ID_STRING(),
+               transaction->LoggingSerialNumber(),
+               requestSerialNumber,
+               IDB_LOG_STRINGIFY(this),
+               IDB_LOG_STRINGIFY(transaction),
+               IDB_LOG_STRINGIFY(objectStore));
 
   return objectStore.forget();
 }
 
 void
 IDBDatabase::DeleteObjectStore(const nsAString& aName, ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
@@ -554,22 +562,30 @@ IDBDatabase::DeleteObjectStore(const nsA
     }
   }
 
   if (!objectStoreId) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR);
     return;
   }
 
-  IDB_PROFILER_MARK("IndexedDB Pseudo-request: "
-                    "database(%s).transaction(%s).deleteObjectStore(\"%s\")",
-                    "MT IDBDatabase.deleteObjectStore()",
-                    IDB_PROFILER_STRING(this),
-                    IDB_PROFILER_STRING(transaction),
-                    NS_ConvertUTF16toUTF8(aName).get());
+  // Don't do this in the macro because we always need to increment the serial
+  // number to keep in sync with the parent.
+  const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
+
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "database(%s).transaction(%s).deleteObjectStore(\"%s\")",
+               "IndexedDB %s: C T[%lld] R[%llu]: "
+                 "IDBDatabase.deleteObjectStore()",
+               IDB_LOG_ID_STRING(),
+               transaction->LoggingSerialNumber(),
+               requestSerialNumber,
+               IDB_LOG_STRINGIFY(this),
+               IDB_LOG_STRINGIFY(transaction),
+               NS_ConvertUTF16toUTF8(aName).get());
 }
 
 already_AddRefed<IDBTransaction>
 IDBDatabase::Transaction(const nsAString& aStoreName,
                          IDBTransactionMode aMode,
                          ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
@@ -664,28 +680,31 @@ IDBDatabase::Transaction(const Sequence<
 
   nsRefPtr<IDBTransaction> transaction =
     IDBTransaction::Create(this, sortedStoreNames, mode);
   MOZ_ASSERT(transaction);
 
   BackgroundTransactionChild* actor =
     new BackgroundTransactionChild(transaction);
 
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld]: "
+                 "database(%s).transaction(%s)",
+               "IndexedDB %s: C T[%lld]: IDBDatabase.transaction()",
+               IDB_LOG_ID_STRING(),
+               transaction->LoggingSerialNumber(),
+               IDB_LOG_STRINGIFY(this),
+               IDB_LOG_STRINGIFY(transaction));
+
   MOZ_ALWAYS_TRUE(
     mBackgroundActor->SendPBackgroundIDBTransactionConstructor(actor,
                                                                sortedStoreNames,
                                                                mode));
 
   transaction->SetBackgroundActor(actor);
 
-  IDB_PROFILER_MARK("IndexedDB Transaction %llu: database(%s).transaction(%s)",
-                    "IDBTransaction[%llu] MT Started",
-                    transaction->GetSerialNumber(), IDB_PROFILER_STRING(this),
-                    IDB_PROFILER_STRING(transaction));
-
   return transaction.forget();
 }
 
 StorageType
 IDBDatabase::Storage() const
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mSpec);
@@ -717,16 +736,18 @@ IDBDatabase::CreateMutableFile(const nsA
 
   nsRefPtr<IDBRequest> request = IDBRequest::Create(this, nullptr);
 
   nsString type;
   if (aType.WasPassed()) {
     type = aType.Value();
   }
 
+  mFactory->IncrementParentLoggingRequestSerialNumber();
+
   aRv = CreateFileHelper::CreateAndDispatch(this, request, aName, type);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
   return request.forget();
 }
 
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -1,32 +1,35 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=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 "IDBFactory.h"
 
+#include "BackgroundChildImpl.h"
 #include "IDBRequest.h"
 #include "IndexedDatabaseManager.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/IDBFactoryBinding.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackground.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "nsGlobalWindow.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
 #include "nsILoadContext.h"
 #include "nsIPrincipal.h"
+#include "nsIUUIDGenerator.h"
 #include "nsIWebNavigation.h"
+#include "nsServiceManagerUtils.h"
 #include "ProfilerHelpers.h"
 #include "ReportInternalError.h"
 
 // Include this last to avoid path problems on Windows.
 #include "ActorsChild.h"
 
 #ifdef DEBUG
 #include "nsContentUtils.h" // For assertions.
@@ -71,20 +74,24 @@ GetPrincipalInfoFromPrincipal(nsIPrincip
 }
 
 } // anonymous namespace
 
 class IDBFactory::BackgroundCreateCallback MOZ_FINAL
   : public nsIIPCBackgroundChildCreateCallback
 {
   nsRefPtr<IDBFactory> mFactory;
+  LoggingInfo mLoggingInfo;
 
 public:
-  explicit BackgroundCreateCallback(IDBFactory* aFactory)
-  : mFactory(aFactory)
+  explicit
+  BackgroundCreateCallback(IDBFactory* aFactory,
+                           const LoggingInfo& aLoggingInfo)
+    : mFactory(aFactory)
+    , mLoggingInfo(aLoggingInfo)
   {
     MOZ_ASSERT(aFactory);
   }
 
   NS_DECL_ISUPPORTS
 
 private:
   ~BackgroundCreateCallback()
@@ -301,16 +308,25 @@ IDBFactory::SetBackgroundActor(Backgroun
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aBackgroundActor);
   MOZ_ASSERT(!mBackgroundActor);
 
   mBackgroundActor = aBackgroundActor;
 }
 
+void
+IDBFactory::IncrementParentLoggingRequestSerialNumber()
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(mBackgroundActor);
+
+  mBackgroundActor->SendIncrementLoggingRequestSerialNumber();
+}
+
 already_AddRefed<IDBOpenDBRequest>
 IDBFactory::Open(const nsAString& aName,
                  uint64_t aVersion,
                  ErrorResult& aRv)
 {
   return OpenInternal(/* aPrincipal */ nullptr,
                       aName,
                       Optional<uint64_t>(aVersion),
@@ -496,37 +512,54 @@ IDBFactory::OpenInternal(nsIPrincipal* a
   if (aDeleting) {
     metadata.version() = 0;
     params = DeleteDatabaseRequestParams(commonParams);
   } else {
     metadata.version() = version;
     params = OpenDatabaseRequestParams(commonParams);
   }
 
-  if (!mBackgroundActor) {
-    // If another consumer has already created a background actor for this
-    // thread then we can start this request immediately.
-    if (PBackgroundChild* bgActor = BackgroundChild::GetForCurrentThread()) {
-      nsresult rv = BackgroundActorCreated(bgActor);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        IDB_REPORT_INTERNAL_ERR();
-        aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-        return nullptr;
+  if (!mBackgroundActor && mPendingRequests.IsEmpty()) {
+    // We need to start the sequence to create a background actor for this
+    // thread.
+    BackgroundChildImpl::ThreadLocal* threadLocal =
+      BackgroundChildImpl::GetThreadLocalForCurrentThread();
+
+    nsAutoPtr<ThreadLocal> newIDBThreadLocal;
+    ThreadLocal* idbThreadLocal;
+
+    if (threadLocal && threadLocal->mIndexedDBThreadLocal) {
+      idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
+    } else {
+      nsCOMPtr<nsIUUIDGenerator> uuidGen =
+        do_GetService("@mozilla.org/uuid-generator;1");
+      MOZ_ASSERT(uuidGen);
+
+      nsID id;
+      MOZ_ALWAYS_TRUE(NS_SUCCEEDED(uuidGen->GenerateUUIDInPlace(&id)));
+
+      newIDBThreadLocal = idbThreadLocal = new ThreadLocal(id);
+    }
+
+    nsRefPtr<BackgroundCreateCallback> cb =
+      new BackgroundCreateCallback(this, idbThreadLocal->GetLoggingInfo());
+    if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(cb))) {
+      IDB_REPORT_INTERNAL_ERR();
+      aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+      return nullptr;
+    }
+
+    if (newIDBThreadLocal) {
+      if (!threadLocal) {
+        threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread();
       }
-      MOZ_ASSERT(mBackgroundActor);
-    } else if (mPendingRequests.IsEmpty()) {
-      // We need to start the sequence to create a background actor for this
-      // thread.
-      nsRefPtr<BackgroundCreateCallback> cb =
-        new BackgroundCreateCallback(this);
-      if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(cb))) {
-        IDB_REPORT_INTERNAL_ERR();
-        aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-        return nullptr;
-      }
+      MOZ_ASSERT(threadLocal);
+      MOZ_ASSERT(!threadLocal->mIndexedDBThreadLocal);
+
+      threadLocal->mIndexedDBThreadLocal = newIDBThreadLocal.forget();
     }
   }
 
   AutoJSAPI autoJS;
   nsRefPtr<IDBOpenDBRequest> request;
 
   if (mWindow) {
     AutoJSContext cx;
@@ -545,62 +578,65 @@ IDBFactory::OpenInternal(nsIPrincipal* a
     autoJS.Init(mOwningObject.get());
     JS::Rooted<JSObject*> scriptOwner(autoJS.cx(), mOwningObject);
 
     request = IDBOpenDBRequest::CreateForJS(this, scriptOwner);
   }
 
   MOZ_ASSERT(request);
 
+  if (aDeleting) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: "
+                   "indexedDB.deleteDatabase(\"%s\")",
+                 "IndexedDB %s: C R[%llu]: IDBFactory.deleteDatabase()",
+                 IDB_LOG_ID_STRING(),
+                 request->LoggingSerialNumber(),
+                 NS_ConvertUTF16toUTF8(aName).get());
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: "
+                   "indexedDB.open(\"%s\", %s)",
+                 "IndexedDB %s: C R[%llu]: IDBFactory.open()",
+                 IDB_LOG_ID_STRING(),
+                 request->LoggingSerialNumber(),
+                 NS_ConvertUTF16toUTF8(aName).get(),
+                 IDB_LOG_STRINGIFY(aVersion));
+  }
+
   // If we already have a background actor then we can start this request now.
   if (mBackgroundActor) {
     nsresult rv = InitiateRequest(request, params);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       IDB_REPORT_INTERNAL_ERR();
       aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
       return nullptr;
     }
   } else {
     mPendingRequests.AppendElement(new PendingRequestInfo(request, params));
   }
 
-#ifdef IDB_PROFILER_USE_MARKS
-  {
-    NS_ConvertUTF16toUTF8 profilerName(aName);
-    if (aDeleting) {
-      IDB_PROFILER_MARK("IndexedDB Request %llu: deleteDatabase(\"%s\")",
-                        "MT IDBFactory.deleteDatabase()",
-                        request->GetSerialNumber(), profilerName.get());
-    } else {
-      IDB_PROFILER_MARK("IndexedDB Request %llu: open(\"%s\", %lld)",
-                        "MT IDBFactory.open()",
-                        request->GetSerialNumber(), profilerName.get(),
-                        aVersion);
-    }
-  }
-#endif
-
   return request.forget();
 }
 
 nsresult
-IDBFactory::BackgroundActorCreated(PBackgroundChild* aBackgroundActor)
+IDBFactory::BackgroundActorCreated(PBackgroundChild* aBackgroundActor,
+                                   const LoggingInfo& aLoggingInfo)
 {
   MOZ_ASSERT(aBackgroundActor);
   MOZ_ASSERT(!mBackgroundActor);
   MOZ_ASSERT(!mBackgroundActorFailed);
 
   {
     BackgroundFactoryChild* actor = new BackgroundFactoryChild(this);
 
     MOZ_ASSERT(NS_IsMainThread(), "Fix this windowId stuff for workers!");
 
     mBackgroundActor =
       static_cast<BackgroundFactoryChild*>(
-        aBackgroundActor->SendPBackgroundIDBFactoryConstructor(actor));
+        aBackgroundActor->SendPBackgroundIDBFactoryConstructor(actor,
+                                                               aLoggingInfo));
   }
 
   if (NS_WARN_IF(!mBackgroundActor)) {
     BackgroundActorFailed();
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   nsresult rv = NS_OK;
@@ -730,17 +766,17 @@ void
 IDBFactory::BackgroundCreateCallback::ActorCreated(PBackgroundChild* aActor)
 {
   MOZ_ASSERT(aActor);
   MOZ_ASSERT(mFactory);
 
   nsRefPtr<IDBFactory> factory;
   mFactory.swap(factory);
 
-  factory->BackgroundActorCreated(aActor);
+  factory->BackgroundActorCreated(aActor, mLoggingInfo);
 }
 
 void
 IDBFactory::BackgroundCreateCallback::ActorFailed()
 {
   MOZ_ASSERT(mFactory);
 
   nsRefPtr<IDBFactory> factory;
--- a/dom/indexedDB/IDBFactory.h
+++ b/dom/indexedDB/IDBFactory.h
@@ -37,16 +37,17 @@ namespace dom {
 struct IDBOpenDBOptions;
 class TabChild;
 
 namespace indexedDB {
 
 class BackgroundFactoryChild;
 class FactoryRequestParams;
 class IDBOpenDBRequest;
+class LoggingInfo;
 
 class IDBFactory MOZ_FINAL
   : public nsISupports
   , public nsWrapperCache
 {
   typedef mozilla::dom::StorageType StorageType;
   typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
   typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
@@ -107,16 +108,19 @@ public:
   void
   ClearBackgroundActor()
   {
     AssertIsOnOwningThread();
 
     mBackgroundActor = nullptr;
   }
 
+  void
+  IncrementParentLoggingRequestSerialNumber();
+
   nsPIDOMWindow*
   GetParentObject() const
   {
     return mWindow;
   }
 
   TabChild*
   GetTabChild() const
@@ -203,17 +207,18 @@ private:
   OpenInternal(nsIPrincipal* aPrincipal,
                const nsAString& aName,
                const Optional<uint64_t>& aVersion,
                const Optional<StorageType>& aStorageType,
                bool aDeleting,
                ErrorResult& aRv);
 
   nsresult
-  BackgroundActorCreated(PBackgroundChild* aBackgroundActor);
+  BackgroundActorCreated(PBackgroundChild* aBackgroundActor,
+                         const LoggingInfo& aLoggingInfo);
 
   void
   BackgroundActorFailed();
 
   nsresult
   InitiateRequest(IDBOpenDBRequest* aRequest,
                   const FactoryRequestParams& aParams);
 };
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -259,43 +259,48 @@ IDBIndex::GetInternal(bool aKeyOnly,
     params = IndexGetKeyParams(objectStoreId, indexId, optionalKeyRange);
   } else {
     params = IndexGetParams(objectStoreId, indexId, optionalKeyRange);
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  if (aKeyOnly) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
+                   "getKey(%s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getKey()",
+                 IDB_LOG_ID_STRING(),
+                 transaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(transaction->Database()),
+                 IDB_LOG_STRINGIFY(transaction),
+                 IDB_LOG_STRINGIFY(mObjectStore),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange));
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
+                   "get(%s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.get()",
+                 IDB_LOG_ID_STRING(),
+                 transaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(transaction->Database()),
+                 IDB_LOG_STRINGIFY(transaction),
+                 IDB_LOG_STRINGIFY(mObjectStore),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange));
+  }
+
   BackgroundRequestChild* actor = new BackgroundRequestChild(request);
 
   transaction->StartRequest(actor, params);
 
-  if (aKeyOnly) {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s).index(%s)."
-                      "getKey(%s)",
-                      "IDBRequest[%llu] MT IDBIndex.getKey()",
-                      request->GetSerialNumber(),
-                      IDB_PROFILER_STRING(transaction->Database()),
-                      IDB_PROFILER_STRING(transaction),
-                      IDB_PROFILER_STRING(mObjectStore),
-                      IDB_PROFILER_STRING(this),
-                      IDB_PROFILER_STRING(aKey));
-  } else {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s).index(%s)."
-                      "get(%s)",
-                      "IDBRequest[%llu] MT IDBIndex.get()",
-                      request->GetSerialNumber(),
-                      IDB_PROFILER_STRING(transaction->Database()),
-                      IDB_PROFILER_STRING(transaction),
-                      IDB_PROFILER_STRING(mObjectStore),
-                      IDB_PROFILER_STRING(this),
-                      IDB_PROFILER_STRING(aKey));
-  }
   return request.forget();
 }
 
 already_AddRefed<IDBRequest>
 IDBIndex::GetAllInternal(bool aKeysOnly,
                          JSContext* aCx,
                          JS::Handle<JS::Value> aKey,
                          const Optional<uint32_t>& aLimit,
@@ -335,46 +340,50 @@ IDBIndex::GetAllInternal(bool aKeysOnly,
                                    limit);
   } else {
     params = IndexGetAllParams(objectStoreId, indexId, optionalKeyRange, limit);
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  if (aKeysOnly) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
+                   "getAllKeys(%s, %s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAllKeys()",
+                 IDB_LOG_ID_STRING(),
+                 transaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(transaction->Database()),
+                 IDB_LOG_STRINGIFY(transaction),
+                 IDB_LOG_STRINGIFY(mObjectStore),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange),
+                 IDB_LOG_STRINGIFY(aLimit));
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
+                   "getAll(%s, %s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAll()",
+                 IDB_LOG_ID_STRING(),
+                 transaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(transaction->Database()),
+                 IDB_LOG_STRINGIFY(transaction),
+                 IDB_LOG_STRINGIFY(mObjectStore),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange),
+                 IDB_LOG_STRINGIFY(aLimit));
+  }
+
   BackgroundRequestChild* actor = new BackgroundRequestChild(request);
 
   transaction->StartRequest(actor, params);
 
-  if (aKeysOnly) {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s).index(%s)."
-                      "getAllKeys(%s, %lu)",
-                      "IDBRequest[%llu] MT IDBIndex.getAllKeys()",
-                      request->GetSerialNumber(),
-                      IDB_PROFILER_STRING(transaction->Database()),
-                      IDB_PROFILER_STRING(transaction),
-                      IDB_PROFILER_STRING(mObjectStore),
-                      IDB_PROFILER_STRING(this),
-                      IDB_PROFILER_STRING(aKeyRange),
-                      aLimit);
-  } else {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s).index(%s)."
-                      "getAll(%s, %lu)",
-                      "IDBRequest[%llu] MT IDBIndex.getAll()",
-                      request->GetSerialNumber(),
-                      IDB_PROFILER_STRING(transaction->Database()),
-                      IDB_PROFILER_STRING(transaction),
-                      IDB_PROFILER_STRING(mObjectStore),
-                      IDB_PROFILER_STRING(this),
-                      IDB_PROFILER_STRING(aKeyRange),
-                      aLimit);
-  }
-
   return request.forget();
 }
 
 already_AddRefed<IDBRequest>
 IDBIndex::OpenCursorInternal(bool aKeysOnly,
                              JSContext* aCx,
                              JS::Handle<JS::Value> aRange,
                              IDBCursorDirection aDirection,
@@ -427,16 +436,47 @@ IDBIndex::OpenCursorInternal(bool aKeysO
     openParams.direction() = direction;
 
     params = Move(openParams);
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  if (aKeysOnly) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
+                   "openKeyCursor(%s, %s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.openKeyCursor()",
+                 IDB_LOG_ID_STRING(),
+                 transaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(transaction->Database()),
+                 IDB_LOG_STRINGIFY(transaction),
+                 IDB_LOG_STRINGIFY(mObjectStore),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange),
+                 IDB_LOG_STRINGIFY(direction));
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s).index(%s)."
+                   "openCursor(%s, %s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: "
+                   "IDBObjectStore.openKeyCursor()",
+                 IDB_LOG_ID_STRING(),
+                 transaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(transaction->Database()),
+                 IDB_LOG_STRINGIFY(transaction),
+                 IDB_LOG_STRINGIFY(mObjectStore),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange),
+                 IDB_LOG_STRINGIFY(direction));
+  }
+
   BackgroundCursorChild* actor =
     new BackgroundCursorChild(request, this, direction);
 
   mObjectStore->Transaction()->OpenCursor(actor, params);
 
   return request.forget();
 }
 
@@ -469,31 +509,33 @@ IDBIndex::Count(JSContext* aCx,
     params.optionalKeyRange() = serializedKeyRange;
   } else {
     params.optionalKeyRange() = void_t();
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "database(%s).transaction(%s).objectStore(%s).index(%s)."
+                 "count(%s)",
+               "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.count()",
+               IDB_LOG_ID_STRING(),
+               transaction->LoggingSerialNumber(),
+               request->LoggingSerialNumber(),
+               IDB_LOG_STRINGIFY(transaction->Database()),
+               IDB_LOG_STRINGIFY(transaction),
+               IDB_LOG_STRINGIFY(mObjectStore),
+               IDB_LOG_STRINGIFY(this),
+               IDB_LOG_STRINGIFY(keyRange));
+
   BackgroundRequestChild* actor = new BackgroundRequestChild(request);
 
   transaction->StartRequest(actor, params);
 
-  IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                    "database(%s).transaction(%s).objectStore(%s).index(%s)."
-                    "count(%s)",
-                    "IDBRequest[%llu] MT IDBObjectStore.count()",
-                    request->GetSerialNumber(),
-                    IDB_PROFILER_STRING(transaction->Database()),
-                    IDB_PROFILER_STRING(transaction),
-                    IDB_PROFILER_STRING(mObjectStore),
-                    IDB_PROFILER_STRING(this),
-                    IDB_PROFILER_STRING(aKey));
-
   return request.forget();
 }
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBIndex)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBIndex)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBIndex)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1138,20 +1138,22 @@ IDBObjectStore::GetAddInfo(JSContext* aC
   return rv;
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::AddOrPut(JSContext* aCx,
                          JS::Handle<JS::Value> aValue,
                          JS::Handle<JS::Value> aKey,
                          bool aOverwrite,
+                         bool aFromCursor,
                          ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aCx);
+  MOZ_ASSERT_IF(aFromCursor, aOverwrite);
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   if (!mTransaction->IsWriteAllowed()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
@@ -1244,50 +1246,54 @@ IDBObjectStore::AddOrPut(JSContext* aCx,
     params = ObjectStorePutParams(commonParams);
   } else {
     params = ObjectStoreAddParams(commonParams);
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  if (!aFromCursor) {
+    if (aOverwrite) {
+      IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                     "database(%s).transaction(%s).objectStore(%s).put(%s)",
+                   "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.put()",
+                   IDB_LOG_ID_STRING(),
+                   mTransaction->LoggingSerialNumber(),
+                   request->LoggingSerialNumber(),
+                   IDB_LOG_STRINGIFY(mTransaction->Database()),
+                   IDB_LOG_STRINGIFY(mTransaction),
+                   IDB_LOG_STRINGIFY(this),
+                   IDB_LOG_STRINGIFY(key));
+    } else {
+      IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                     "database(%s).transaction(%s).objectStore(%s).add(%s)",
+                   "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.add()",
+                   IDB_LOG_ID_STRING(),
+                   mTransaction->LoggingSerialNumber(),
+                   request->LoggingSerialNumber(),
+                   IDB_LOG_STRINGIFY(mTransaction->Database()),
+                   IDB_LOG_STRINGIFY(mTransaction),
+                   IDB_LOG_STRINGIFY(this),
+                   IDB_LOG_STRINGIFY(key));
+    }
+  }
+
   BackgroundRequestChild* actor = new BackgroundRequestChild(request);
 
   mTransaction->StartRequest(actor, params);
 
   if (!fileInfosToKeepAlive.IsEmpty()) {
     nsTArray<nsRefPtr<FileInfo>> fileInfos;
     fileInfosToKeepAlive.SwapElements(fileInfos);
 
     actor->HoldFileInfosUntilComplete(fileInfos);
     MOZ_ASSERT(fileInfos.IsEmpty());
   }
 
-#ifdef IDB_PROFILER_USE_MARKS
-  if (aOverwrite) {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s).%s(%s)",
-                      "IDBRequest[%llu] MT IDBObjectStore.put()",
-                      request->GetSerialNumber(),
-                      IDB_PROFILER_STRING(Transaction()->Database()),
-                      IDB_PROFILER_STRING(Transaction()),
-                      IDB_PROFILER_STRING(this),
-                      key.IsUnset() ? "" : IDB_PROFILER_STRING(key));
-  } else {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s).add(%s)",
-                      "IDBRequest[%llu] MT IDBObjectStore.add()",
-                      request->GetSerialNumber(),
-                      IDB_PROFILER_STRING(Transaction()->Database()),
-                      IDB_PROFILER_STRING(Transaction()),
-                      IDB_PROFILER_STRING(this),
-                      key.IsUnset() ? "" : IDB_PROFILER_STRING(key));
-  }
-#endif
-
   return request.forget();
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::GetAllInternal(bool aKeysOnly,
                                JSContext* aCx,
                                JS::Handle<JS::Value> aKey,
                                const Optional<uint32_t>& aLimit,
@@ -1324,46 +1330,48 @@ IDBObjectStore::GetAllInternal(bool aKey
     params = ObjectStoreGetAllKeysParams(id, optionalKeyRange, limit);
   } else {
     params = ObjectStoreGetAllParams(id, optionalKeyRange, limit);
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  if (aKeysOnly) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "getAllKeys(%s, %s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.getAllKeys()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange),
+                 IDB_LOG_STRINGIFY(aLimit));
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "getAll(%s, %s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.getAll()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange),
+                 IDB_LOG_STRINGIFY(aLimit));
+  }
+
   BackgroundRequestChild* actor = new BackgroundRequestChild(request);
 
   mTransaction->StartRequest(actor, params);
 
-#ifdef IDB_PROFILER_USE_MARKS
-  if (aKeysOnly) {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s)."
-                      "getAllKeys(%s, %lu)",
-                      "IDBRequest[%llu] MT IDBObjectStore.getAllKeys()",
-                      request->GetSerialNumber(),
-                      IDB_PROFILER_STRING(Transaction()->Database()),
-                      IDB_PROFILER_STRING(Transaction()),
-                      IDB_PROFILER_STRING(this),
-                      IDB_PROFILER_STRING(aKeyRange),
-                      aLimit);
-  } else {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s)."
-                      "getAll(%s, %lu)",
-                      "IDBRequest[%llu] MT IDBObjectStore.getAll()",
-                      request->GetSerialNumber(),
-                      IDB_PROFILER_STRING(Transaction()->Database()),
-                      IDB_PROFILER_STRING(Transaction()),
-                      IDB_PROFILER_STRING(this),
-                      IDB_PROFILER_STRING(aKeyRange),
-                      aLimit);
-  }
-#endif
-
   return request.forget();
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::Clear(ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
 
@@ -1378,28 +1386,30 @@ IDBObjectStore::Clear(ErrorResult& aRv)
   }
 
   ObjectStoreClearParams params;
   params.objectStoreId() = Id();
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "database(%s).transaction(%s).objectStore(%s).clear()",
+               "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.clear()",
+               IDB_LOG_ID_STRING(),
+               mTransaction->LoggingSerialNumber(),
+               request->LoggingSerialNumber(),
+               IDB_LOG_STRINGIFY(mTransaction->Database()),
+               IDB_LOG_STRINGIFY(mTransaction),
+               IDB_LOG_STRINGIFY(this));
+
   BackgroundRequestChild* actor = new BackgroundRequestChild(request);
 
   mTransaction->StartRequest(actor, params);
 
-  IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                    "database(%s).transaction(%s).objectStore(%s).clear()",
-                    "IDBRequest[%llu] MT IDBObjectStore.clear()",
-                    request->GetSerialNumber(),
-                    IDB_PROFILER_STRING(Transaction()->Database()),
-                    IDB_PROFILER_STRING(Transaction()),
-                    IDB_PROFILER_STRING(this));
-
   return request.forget();
 }
 
 already_AddRefed<IDBIndex>
 IDBObjectStore::Index(const nsAString& aName, ErrorResult &aRv)
 {
   AssertIsOnOwningThread();
 
@@ -1574,35 +1584,39 @@ IDBObjectStore::Get(JSContext* aCx,
 
   ObjectStoreGetParams params;
   params.objectStoreId() = Id();
   keyRange->ToSerialized(params.keyRange());
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "database(%s).transaction(%s).objectStore(%s).get(%s)",
+               "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.get()",
+               IDB_LOG_ID_STRING(),
+               mTransaction->LoggingSerialNumber(),
+               request->LoggingSerialNumber(),
+               IDB_LOG_STRINGIFY(mTransaction->Database()),
+               IDB_LOG_STRINGIFY(mTransaction),
+               IDB_LOG_STRINGIFY(this),
+               IDB_LOG_STRINGIFY(keyRange));
+
   BackgroundRequestChild* actor = new BackgroundRequestChild(request);
 
   mTransaction->StartRequest(actor, params);
 
-  IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                    "database(%s).transaction(%s).objectStore(%s).get(%s)",
-                    "IDBRequest[%llu] MT IDBObjectStore.get()",
-                    request->GetSerialNumber(),
-                    IDB_PROFILER_STRING(Transaction()->Database()),
-                    IDB_PROFILER_STRING(Transaction()),
-                    IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
-
   return request.forget();
 }
 
 already_AddRefed<IDBRequest>
-IDBObjectStore::Delete(JSContext* aCx,
-                       JS::Handle<JS::Value> aKey,
-                       ErrorResult& aRv)
+IDBObjectStore::DeleteInternal(JSContext* aCx,
+                               JS::Handle<JS::Value> aKey,
+                               bool aFromCursor,
+                               ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
@@ -1625,28 +1639,33 @@ IDBObjectStore::Delete(JSContext* aCx,
 
   ObjectStoreDeleteParams params;
   params.objectStoreId() = Id();
   keyRange->ToSerialized(params.keyRange());
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  if (!aFromCursor) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s).delete(%s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.delete()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange));
+  }
+
   BackgroundRequestChild* actor = new BackgroundRequestChild(request);
 
   mTransaction->StartRequest(actor, params);
 
-  IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                    "database(%s).transaction(%s).objectStore(%s).delete(%s)",
-                    "IDBRequest[%llu] MT IDBObjectStore.delete()",
-                    request->GetSerialNumber(),
-                    IDB_PROFILER_STRING(Transaction()->Database()),
-                    IDB_PROFILER_STRING(Transaction()),
-                    IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
-
   return request.forget();
 }
 
 already_AddRefed<IDBIndex>
 IDBObjectStore::CreateIndex(const nsAString& aName,
                             const nsAString& aKeyPath,
                             const IDBIndexParameters& aOptionalParameters,
                             ErrorResult& aRv)
@@ -1743,23 +1762,30 @@ IDBObjectStore::CreateIndexInternal(
 
   transaction->CreateIndex(this, *metadata);
 
   nsRefPtr<IDBIndex> index = IDBIndex::Create(this, *metadata);
   MOZ_ASSERT(index);
 
   mIndexes.AppendElement(index);
 
-  IDB_PROFILER_MARK("IndexedDB Pseudo-request: "
-                    "database(%s).transaction(%s).objectStore(%s)."
-                    "createIndex(%s)",
-                    "MT IDBObjectStore.createIndex()",
-                    IDB_PROFILER_STRING(Transaction()->Database()),
-                    IDB_PROFILER_STRING(Transaction()),
-                    IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(index));
+  // Don't do this in the macro because we always need to increment the serial
+  // number to keep in sync with the parent.
+  const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
+
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "database(%s).transaction(%s).objectStore(%s).createIndex(%s)",
+               "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.createIndex()",
+               IDB_LOG_ID_STRING(),
+               mTransaction->LoggingSerialNumber(),
+               requestSerialNumber,
+               IDB_LOG_STRINGIFY(mTransaction->Database()),
+               IDB_LOG_STRINGIFY(mTransaction),
+               IDB_LOG_STRINGIFY(this),
+               IDB_LOG_STRINGIFY(index));
 
   return index.forget();
 }
 
 void
 IDBObjectStore::DeleteIndex(const nsAString& aName, ErrorResult& aRv)
 {
   AssertIsOnOwningThread();
@@ -1808,26 +1834,33 @@ IDBObjectStore::DeleteIndex(const nsAStr
     }
   }
 
   if (!foundId) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR);
     return;
   }
 
-  transaction->DeleteIndex(this, foundId);
+  // Don't do this in the macro because we always need to increment the serial
+  // number to keep in sync with the parent.
+  const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
 
-  IDB_PROFILER_MARK("IndexedDB Pseudo-request: "
-                    "database(%s).transaction(%s).objectStore(%s)."
-                    "deleteIndex(\"%s\")",
-                    "MT IDBObjectStore.deleteIndex()",
-                    IDB_PROFILER_STRING(Transaction()->Database()),
-                    IDB_PROFILER_STRING(Transaction()),
-                    IDB_PROFILER_STRING(this),
-                    NS_ConvertUTF16toUTF8(aName).get());
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "database(%s).transaction(%s).objectStore(%s)."
+                 "deleteIndex(\"%s\")",
+               "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.deleteIndex()",
+               IDB_LOG_ID_STRING(),
+               mTransaction->LoggingSerialNumber(),
+               requestSerialNumber,
+               IDB_LOG_STRINGIFY(mTransaction->Database()),
+               IDB_LOG_STRINGIFY(mTransaction),
+               IDB_LOG_STRINGIFY(this),
+               NS_ConvertUTF16toUTF8(aName).get());
+
+  transaction->DeleteIndex(this, foundId);
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::Count(JSContext* aCx,
                       JS::Handle<JS::Value> aKey,
                       ErrorResult& aRv)
 {
   if (!mTransaction->IsOpen()) {
@@ -1850,28 +1883,31 @@ IDBObjectStore::Count(JSContext* aCx,
     params.optionalKeyRange() = serializedKeyRange;
   } else {
     params.optionalKeyRange() = void_t();
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "database(%s).transaction(%s).objectStore(%s).count(%s)",
+               "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.count()",
+               IDB_LOG_ID_STRING(),
+               mTransaction->LoggingSerialNumber(),
+               request->LoggingSerialNumber(),
+               IDB_LOG_STRINGIFY(mTransaction->Database()),
+               IDB_LOG_STRINGIFY(mTransaction),
+               IDB_LOG_STRINGIFY(this),
+               IDB_LOG_STRINGIFY(keyRange));
+
   BackgroundRequestChild* actor = new BackgroundRequestChild(request);
 
   mTransaction->StartRequest(actor, params);
 
-  IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                    "database(%s).transaction(%s).objectStore(%s).count(%s)",
-                    "IDBRequest[%llu] MT IDBObjectStore.count()",
-                    request->GetSerialNumber(),
-                    IDB_PROFILER_STRING(Transaction()->Database()),
-                    IDB_PROFILER_STRING(Transaction()),
-                    IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
-
   return request.forget();
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::OpenCursorInternal(bool aKeysOnly,
                                    JSContext* aCx,
                                    JS::Handle<JS::Value> aRange,
                                    IDBCursorDirection aDirection,
@@ -1920,44 +1956,50 @@ IDBObjectStore::OpenCursorInternal(bool 
     openParams.direction() = direction;
 
     params = Move(openParams);
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   MOZ_ASSERT(request);
 
+  if (aKeysOnly) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "openKeyCursor(%s, %s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: "
+                   "IDBObjectStore.openKeyCursor()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange),
+                 IDB_LOG_STRINGIFY(direction));
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                   "database(%s).transaction(%s).objectStore(%s)."
+                   "openCursor(%s, %s)",
+                 "IndexedDB %s: C T[%lld] R[%llu]: IDBObjectStore.openCursor()",
+                 IDB_LOG_ID_STRING(),
+                 mTransaction->LoggingSerialNumber(),
+                 request->LoggingSerialNumber(),
+                 IDB_LOG_STRINGIFY(mTransaction->Database()),
+                 IDB_LOG_STRINGIFY(mTransaction),
+                 IDB_LOG_STRINGIFY(this),
+                 IDB_LOG_STRINGIFY(keyRange),
+                 IDB_LOG_STRINGIFY(direction));
+  }
+
   BackgroundCursorChild* actor =
     new BackgroundCursorChild(request, this, direction);
 
   mTransaction->OpenCursor(actor, params);
 
-#ifdef IDB_PROFILER_USE_MARKS
-  if (aKeysOnly) {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s)."
-                      "openKeyCursor(%s, %s)",
-                      "IDBRequest[%llu] MT IDBObjectStore.openKeyCursor()",
-                      request->GetSerialNumber(),
-                      IDB_PROFILER_STRING(Transaction()->Database()),
-                      IDB_PROFILER_STRING(Transaction()),
-                      IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange),
-                      IDB_PROFILER_STRING(direction));
-  } else {
-    IDB_PROFILER_MARK("IndexedDB Request %llu: "
-                      "database(%s).transaction(%s).objectStore(%s)."
-                      "openCursor(%s, %s)",
-                      "IDBRequest[%llu] MT IDBObjectStore.openKeyCursor()",
-                      request->GetSerialNumber(),
-                      IDB_PROFILER_STRING(Transaction()->Database()),
-                      IDB_PROFILER_STRING(Transaction()),
-                      IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange),
-                      IDB_PROFILER_STRING(direction));
-  }
-#endif
   return request.forget();
 }
 
 void
 IDBObjectStore::RefreshSpec(bool aMayDelete)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT_IF(mDeletedSpec, mSpec == mDeletedSpec);
--- a/dom/indexedDB/IDBObjectStore.h
+++ b/dom/indexedDB/IDBObjectStore.h
@@ -28,30 +28,34 @@ namespace dom {
 
 class DOMStringList;
 class nsIContentParent;
 template <typename> class Sequence;
 
 namespace indexedDB {
 
 class FileManager;
+class IDBCursor;
 class IDBKeyRange;
 class IDBRequest;
 class IDBTransaction;
 class IndexUpdateInfo;
 class Key;
 class KeyPath;
 class ObjectStoreSpec;
 struct StructuredCloneFile;
 struct StructuredCloneReadInfo;
 
 class IDBObjectStore MOZ_FINAL
   : public nsISupports
   , public nsWrapperCache
 {
+  // For AddOrPut() and DeleteInternal().
+  friend class IDBCursor; 
+
   static const JSClass sDummyPropJSClass;
 
   nsRefPtr<IDBTransaction> mTransaction;
   JS::Heap<JS::Value> mCachedKeyPath;
 
   // This normally points to the ObjectStoreSpec owned by the parent IDBDatabase
   // object. However, if this objectStore is part of a versionchange transaction
   // and it gets deleted then the spec is copied into mDeletedSpec and mSpec is
@@ -155,32 +159,39 @@ public:
   already_AddRefed<IDBRequest>
   Add(JSContext* aCx,
       JS::Handle<JS::Value> aValue,
       JS::Handle<JS::Value> aKey,
       ErrorResult& aRv)
   {
     AssertIsOnOwningThread();
 
-    return AddOrPut(aCx, aValue, aKey, false, aRv);
+    return AddOrPut(aCx, aValue, aKey, false, /* aFromCursor */ false, aRv);
   }
 
   already_AddRefed<IDBRequest>
   Put(JSContext* aCx,
       JS::Handle<JS::Value> aValue,
       JS::Handle<JS::Value> aKey,
       ErrorResult& aRv)
   {
     AssertIsOnOwningThread();
 
-    return AddOrPut(aCx, aValue, aKey, true, aRv);
+    return AddOrPut(aCx, aValue, aKey, true, /* aFromCursor */ false, aRv);
   }
 
   already_AddRefed<IDBRequest>
-  Delete(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
+  Delete(JSContext* aCx,
+         JS::Handle<JS::Value> aKey,
+         ErrorResult& aRv)
+  {
+    AssertIsOnOwningThread();
+
+    return DeleteInternal(aCx, aKey, /* aFromCursor */ false, aRv);
+  }
 
   already_AddRefed<IDBRequest>
   Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Clear(ErrorResult& aRv);
 
   already_AddRefed<IDBIndex>
@@ -281,19 +292,26 @@ private:
              Key& aKey,
              nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
 
   already_AddRefed<IDBRequest>
   AddOrPut(JSContext* aCx,
            JS::Handle<JS::Value> aValue,
            JS::Handle<JS::Value> aKey,
            bool aOverwrite,
+           bool aFromCursor,
            ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
+  DeleteInternal(JSContext* aCx,
+                 JS::Handle<JS::Value> aKey,
+                 bool aFromCursor,
+                 ErrorResult& aRv);
+
+  already_AddRefed<IDBRequest>
   GetAllInternal(bool aKeysOnly,
                  JSContext* aCx,
                  JS::Handle<JS::Value> aKey,
                  const Optional<uint32_t>& aLimit,
                  ErrorResult& aRv);
 
   already_AddRefed<IDBIndex>
   CreateIndexInternal(const nsAString& aName,
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -24,16 +24,19 @@
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsIScriptContext.h"
 #include "nsJSUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsString.h"
 #include "ReportInternalError.h"
 
+// Include this last to avoid path problems on Windows.
+#include "ActorsChild.h"
+
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
 using namespace mozilla::ipc;
 
 IDBRequest::IDBRequest(IDBDatabase* aDatabase)
   : IDBWrapperCache(aDatabase)
@@ -70,29 +73,20 @@ void
 IDBRequest::InitMembers()
 {
 #ifdef DEBUG
   mOwningThread = PR_GetCurrentThread();
 #endif
   AssertIsOnOwningThread();
 
   mResultVal.setUndefined();
+  mLoggingSerialNumber = NextSerialNumber();
   mErrorCode = NS_OK;
   mLineNo = 0;
   mHaveResultOrErrorCode = false;
-
-#ifdef MOZ_ENABLE_PROFILER_SPS
-  {
-    BackgroundChildImpl::ThreadLocal* threadLocal =
-      BackgroundChildImpl::GetThreadLocalForCurrentThread();
-    MOZ_ASSERT(threadLocal);
-
-    mSerialNumber = threadLocal->mNextRequestSerialNumber++;
-  }
-#endif
 }
 
 // static
 already_AddRefed<IDBRequest>
 IDBRequest::Create(IDBDatabase* aDatabase,
                    IDBTransaction* aTransaction)
 {
   MOZ_ASSERT(aDatabase);
@@ -135,16 +129,38 @@ IDBRequest::Create(IDBIndex* aSourceAsIn
   nsRefPtr<IDBRequest> request = Create(aDatabase, aTransaction);
 
   request->mSourceAsIndex = aSourceAsIndex;
 
   return request.forget();
 }
 
 // static
+uint64_t
+IDBRequest::NextSerialNumber()
+{
+  BackgroundChildImpl::ThreadLocal* threadLocal =
+    BackgroundChildImpl::GetThreadLocalForCurrentThread();
+  MOZ_ASSERT(threadLocal);
+
+  ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
+  MOZ_ASSERT(idbThreadLocal);
+
+  return idbThreadLocal->NextRequestSN();
+}
+
+void
+IDBRequest::SetLoggingSerialNumber(uint64_t aLoggingSerialNumber)
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(aLoggingSerialNumber > mLoggingSerialNumber);
+
+  mLoggingSerialNumber = aLoggingSerialNumber;
+}
+
 void
 IDBRequest::CaptureCaller(nsAString& aFilename, uint32_t* aLineNo)
 {
   MOZ_ASSERT(aFilename.IsEmpty());
   MOZ_ASSERT(aLineNo);
 
   ThreadsafeAutoJSContext cx;
 
--- a/dom/indexedDB/IDBRequest.h
+++ b/dom/indexedDB/IDBRequest.h
@@ -53,19 +53,17 @@ protected:
 #ifdef DEBUG
   PRThread* mOwningThread;
 #endif
 
   JS::Heap<JS::Value> mResultVal;
   nsRefPtr<DOMError> mError;
 
   nsString mFilename;
-#ifdef MOZ_ENABLE_PROFILER_SPS
-  uint64_t mSerialNumber;
-#endif
+  uint64_t mLoggingSerialNumber;
   nsresult mErrorCode;
   uint32_t mLineNo;
   bool mHaveResultOrErrorCode;
 
 public:
   class ResultCallback;
 
   static already_AddRefed<IDBRequest>
@@ -79,16 +77,19 @@ public:
   static already_AddRefed<IDBRequest>
   Create(IDBIndex* aSource,
          IDBDatabase* aDatabase,
          IDBTransaction* aTransaction);
 
   static void
   CaptureCaller(nsAString& aFilename, uint32_t* aLineNo);
 
+  static uint64_t
+  NextSerialNumber();
+
   // nsIDOMEventTarget
   virtual nsresult
   PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
 
   void
   GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const;
 
   void
@@ -120,23 +121,26 @@ public:
   GetCallerLocation(nsAString& aFilename, uint32_t* aLineNo) const;
 
   bool
   IsPending() const
   {
     return !mHaveResultOrErrorCode;
   }
 
-#ifdef MOZ_ENABLE_PROFILER_SPS
   uint64_t
-  GetSerialNumber() const
+  LoggingSerialNumber() const
   {
-    return mSerialNumber;
+    AssertIsOnOwningThread();
+
+    return mLoggingSerialNumber;
   }
-#endif
+
+  void
+  SetLoggingSerialNumber(uint64_t aLoggingSerialNumber);
 
   nsPIDOMWindow*
   GetParentObject() const
   {
     return GetOwner();
   }
 
   void
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -27,28 +27,31 @@
 
 // Include this last to avoid path problems on Windows.
 #include "ActorsChild.h"
 
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
+using namespace mozilla::ipc;
+
 namespace {
 
 NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 } // anonymous namespace
 
 IDBTransaction::IDBTransaction(IDBDatabase* aDatabase,
                                const nsTArray<nsString>& aObjectStoreNames,
                                Mode aMode)
   : IDBWrapperCache(aDatabase)
   , mDatabase(aDatabase)
   , mObjectStoreNames(aObjectStoreNames)
+  , mLoggingSerialNumber(0)
   , mNextObjectStoreId(0)
   , mNextIndexId(0)
   , mAbortCode(NS_OK)
   , mPendingRequestCount(0)
   , mLineNo(0)
   , mReadyState(IDBTransaction::INITIAL)
   , mMode(aMode)
   , mCreating(false)
@@ -58,26 +61,25 @@ IDBTransaction::IDBTransaction(IDBDataba
   , mFiredCompleteOrAbort(false)
 #endif
 {
   MOZ_ASSERT(aDatabase);
   aDatabase->AssertIsOnOwningThread();
 
   mBackgroundActor.mNormalBackgroundActor = nullptr;
 
-#ifdef MOZ_ENABLE_PROFILER_SPS
-  {
-    using namespace mozilla::ipc;
-    BackgroundChildImpl::ThreadLocal* threadLocal =
-      BackgroundChildImpl::GetThreadLocalForCurrentThread();
-    MOZ_ASSERT(threadLocal);
+  BackgroundChildImpl::ThreadLocal* threadLocal =
+    BackgroundChildImpl::GetThreadLocalForCurrentThread();
+  MOZ_ASSERT(threadLocal);
 
-    mSerialNumber = threadLocal->mNextTransactionSerialNumber++;
-  }
-#endif
+  ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
+  MOZ_ASSERT(idbThreadLocal);
+
+  const_cast<int64_t&>(mLoggingSerialNumber) =
+    idbThreadLocal->NextTransactionSN(aMode);
 
 #ifdef DEBUG
   if (!aObjectStoreNames.IsEmpty()) {
     nsTArray<nsString> sortedNames(aObjectStoreNames);
     sortedNames.Sort();
 
     const uint32_t count = sortedNames.Length();
     MOZ_ASSERT(count == aObjectStoreNames.Length());
@@ -106,23 +108,25 @@ IDBTransaction::~IDBTransaction()
                 mFiredCompleteOrAbort);
   MOZ_ASSERT_IF(mMode != VERSION_CHANGE &&
                   mBackgroundActor.mNormalBackgroundActor,
                 mFiredCompleteOrAbort);
 
   mDatabase->UnregisterTransaction(this);
 
   if (mMode == VERSION_CHANGE) {
-    if (mBackgroundActor.mVersionChangeBackgroundActor) {
-      mBackgroundActor.mVersionChangeBackgroundActor->SendDeleteMeInternal();
+    if (auto* actor = mBackgroundActor.mVersionChangeBackgroundActor) {
+      actor->SendDeleteMeInternal();
+
       MOZ_ASSERT(!mBackgroundActor.mVersionChangeBackgroundActor,
                  "SendDeleteMeInternal should have cleared!");
     }
-  } else if (mBackgroundActor.mNormalBackgroundActor) {
-    mBackgroundActor.mNormalBackgroundActor->SendDeleteMeInternal();
+  } else if (auto* actor = mBackgroundActor.mNormalBackgroundActor) {
+    actor->SendDeleteMeInternal();
+
     MOZ_ASSERT(!mBackgroundActor.mNormalBackgroundActor,
                "SendDeleteMeInternal should have cleared!");
   }
 }
 
 // static
 already_AddRefed<IDBTransaction>
 IDBTransaction::CreateVersionChange(
@@ -207,17 +211,20 @@ IDBTransaction::GetCurrent()
   using namespace mozilla::ipc;
 
   MOZ_ASSERT(BackgroundChild::GetForCurrentThread());
 
   BackgroundChildImpl::ThreadLocal* threadLocal =
     BackgroundChildImpl::GetThreadLocalForCurrentThread();
   MOZ_ASSERT(threadLocal);
 
-  return threadLocal->mCurrentTransaction;
+  ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
+  MOZ_ASSERT(idbThreadLocal);
+
+  return idbThreadLocal->GetCurrentTransaction();
 }
 
 #ifdef DEBUG
 
 void
 IDBTransaction::AssertIsOnOwningThread() const
 {
   MOZ_ASSERT(mDatabase);
@@ -334,16 +341,28 @@ IDBTransaction::OnRequestFinished()
 
 void
 IDBTransaction::SendCommit()
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(NS_SUCCEEDED(mAbortCode));
   MOZ_ASSERT(IsFinished());
   MOZ_ASSERT(!mSentCommitOrAbort);
+  MOZ_ASSERT(!mPendingRequestCount);
+
+  // Don't do this in the macro because we always need to increment the serial
+  // number to keep in sync with the parent.
+  const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
+
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "All requests complete, committing transaction",
+               "IndexedDB %s: C T[%lld] R[%llu]: IDBTransaction commit",
+               IDB_LOG_ID_STRING(),
+               LoggingSerialNumber(),
+               requestSerialNumber);
 
   if (mMode == VERSION_CHANGE) {
     MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
     mBackgroundActor.mVersionChangeBackgroundActor->SendCommit();
   } else {
     MOZ_ASSERT(mBackgroundActor.mNormalBackgroundActor);
     mBackgroundActor.mNormalBackgroundActor->SendCommit();
   }
@@ -356,16 +375,28 @@ IDBTransaction::SendCommit()
 void
 IDBTransaction::SendAbort(nsresult aResultCode)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(NS_FAILED(aResultCode));
   MOZ_ASSERT(IsFinished());
   MOZ_ASSERT(!mSentCommitOrAbort);
 
+  // Don't do this in the macro because we always need to increment the serial
+  // number to keep in sync with the parent.
+  const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
+
+  IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
+                 "Aborting transaction with result 0x%x",
+               "IndexedDB %s: C T[%lld] R[%llu]: IDBTransaction abort (0x%x)",
+               IDB_LOG_ID_STRING(),
+               LoggingSerialNumber(),
+               requestSerialNumber,
+               aResultCode);
+
   if (mMode == VERSION_CHANGE) {
     MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
     mBackgroundActor.mVersionChangeBackgroundActor->SendAbort(aResultCode);
   } else {
     MOZ_ASSERT(mBackgroundActor.mNormalBackgroundActor);
     mBackgroundActor.mNormalBackgroundActor->SendAbort(aResultCode);
   }
 
@@ -512,21 +543,24 @@ IDBTransaction::AbortInternal(nsresult a
     // Already finished, nothing to do here.
     return;
   }
 
   const bool isVersionChange = mMode == VERSION_CHANGE;
   const bool isInvalidated = mDatabase->IsInvalidated();
   bool needToSendAbort = mReadyState == INITIAL && !isInvalidated;
 
+  if (isInvalidated) {
 #ifdef DEBUG
-  if (isInvalidated) {
     mSentCommitOrAbort = true;
+#endif
+    // Increment the serial number counter here to account for the aborted
+    // transaction and keep the parent in sync.
+    IDBRequest::NextSerialNumber();
   }
-#endif
 
   mAbortCode = aAbortCode;
   mReadyState = DONE;
   mError = error.forget();
 
   if (isVersionChange) {
     // If a version change transaction is aborted, we must revert the world
     // back to its previous state unless we're being invalidated after the
@@ -634,20 +668,16 @@ IDBTransaction::Abort(ErrorResult& aRv)
 }
 
 void
 IDBTransaction::FireCompleteOrAbortEvents(nsresult aResult)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(!mFiredCompleteOrAbort);
 
-  IDB_PROFILER_MARK("IndexedDB Transaction %llu: Complete (rv = %lu)",
-                    "IDBTransaction[%llu] MT Complete",
-                    mTransaction->GetSerialNumber(), mAbortCode);
-
   mReadyState = DONE;
 
 #ifdef DEBUG
   mFiredCompleteOrAbort = true;
 #endif
 
   nsCOMPtr<nsIDOMEvent> event;
   if (NS_SUCCEEDED(aResult)) {
@@ -665,16 +695,31 @@ IDBTransaction::FireCompleteOrAbortEvent
                                eDoesBubble,
                                eNotCancelable);
   }
 
   if (NS_WARN_IF(!event)) {
     return;
   }
 
+  if (NS_SUCCEEDED(mAbortCode)) {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld]: "
+                   "Firing 'complete' event",
+                 "IndexedDB %s: C T[%lld]: IDBTransaction 'complete' event",
+                 IDB_LOG_ID_STRING(),
+                 mLoggingSerialNumber);
+  } else {
+    IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld]: "
+                   "Firing 'abort' event with error 0x%x",
+                 "IndexedDB %s: C T[%lld]: IDBTransaction 'abort' event (0x%x)",
+                 IDB_LOG_ID_STRING(),
+                 mLoggingSerialNumber,
+                 mAbortCode);
+  }
+
   bool dummy;
   if (NS_FAILED(DispatchEvent(event, &dummy))) {
     NS_WARNING("DispatchEvent failed!");
   }
 
   mDatabase->DelayedMaybeExpireFileActors();
 }
 
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -78,25 +78,22 @@ private:
   // Tagged with mMode. If mMode is VERSION_CHANGE then mBackgroundActor will be
   // a BackgroundVersionChangeTransactionChild. Otherwise it will be a
   // BackgroundTransactionChild.
   union {
     BackgroundTransactionChild* mNormalBackgroundActor;
     BackgroundVersionChangeTransactionChild* mVersionChangeBackgroundActor;
   } mBackgroundActor;
 
+  const int64_t mLoggingSerialNumber;
 
   // Only used for VERSION_CHANGE transactions.
   int64_t mNextObjectStoreId;
   int64_t mNextIndexId;
 
-#ifdef MOZ_ENABLE_PROFILER_SPS
-  uint64_t mSerialNumber;
-#endif
-
   nsresult mAbortCode;
   uint32_t mPendingRequestCount;
 
   nsString mFilename;
   uint32_t mLineNo;
 
   ReadyState mReadyState;
   Mode mMode;
@@ -240,24 +237,23 @@ public:
   DeleteIndex(IDBObjectStore* aObjectStore, int64_t aIndexId);
 
   void
   Abort(IDBRequest* aRequest);
 
   void
   Abort(nsresult aAbortCode);
 
-#ifdef MOZ_ENABLE_PROFILER_SPS
-  uint32_t
-  GetSerialNumber() const
+  int64_t
+  LoggingSerialNumber() const
   {
     AssertIsOnOwningThread();
-    return mSerialNumber;
+
+    return mLoggingSerialNumber;
   }
-#endif
 
   nsPIDOMWindow*
   GetParentObject() const;
 
   IDBTransactionMode
   GetMode(ErrorResult& aRv) const;
 
   DOMError*
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -27,21 +27,23 @@
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/Services.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/storage.h"
 #include "nsContentUtils.h"
 #include "nsThreadUtils.h"
+#include "prlog.h"
 
 #include "IDBEvents.h"
 #include "IDBFactory.h"
 #include "IDBKeyRange.h"
 #include "IDBRequest.h"
+#include "ProfilerHelpers.h"
 
 // Bindings for ResolveConstructors
 #include "mozilla/dom/IDBCursorBinding.h"
 #include "mozilla/dom/IDBDatabaseBinding.h"
 #include "mozilla/dom/IDBFactoryBinding.h"
 #include "mozilla/dom/IDBIndexBinding.h"
 #include "mozilla/dom/IDBKeyRangeBinding.h"
 #include "mozilla/dom/IDBMutableFileBinding.h"
@@ -106,17 +108,32 @@ private:
 
   nsTArray<nsRefPtr<FileManager> > mPersistentStorageFileManagers;
   nsTArray<nsRefPtr<FileManager> > mTemporaryStorageFileManagers;
   nsTArray<nsRefPtr<FileManager> > mDefaultStorageFileManagers;
 };
 
 namespace {
 
-const char kTestingPref[] = "dom.indexedDB.testing";
+#define IDB_PREF_BRANCH_ROOT "dom.indexedDB."
+
+const char kTestingPref[] = IDB_PREF_BRANCH_ROOT "testing";
+
+#define IDB_PREF_LOGGING_BRANCH_ROOT IDB_PREF_BRANCH_ROOT "logging."
+
+const char kPrefLoggingEnabled[] = IDB_PREF_LOGGING_BRANCH_ROOT "enabled";
+const char kPrefLoggingDetails[] = IDB_PREF_LOGGING_BRANCH_ROOT "details";
+
+#if defined(DEBUG) || defined(MOZ_ENABLE_PROFILER_SPS)
+const char kPrefLoggingProfiler[] =
+  IDB_PREF_LOGGING_BRANCH_ROOT "profiler-marks";
+#endif
+
+#undef IDB_PREF_LOGGING_BRANCH_ROOT
+#undef IDB_PREF_BRANCH_ROOT
 
 mozilla::StaticRefPtr<IndexedDatabaseManager> gDBManager;
 
 mozilla::Atomic<bool> gInitialized(false);
 mozilla::Atomic<bool> gClosed(false);
 mozilla::Atomic<bool> gTestingMode(false);
 
 class AsyncDeleteFileRunnable MOZ_FINAL : public nsIRunnable
@@ -200,32 +217,43 @@ IndexedDatabaseManager::IndexedDatabaseM
 
 IndexedDatabaseManager::~IndexedDatabaseManager()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 }
 
 bool IndexedDatabaseManager::sIsMainProcess = false;
 bool IndexedDatabaseManager::sFullSynchronousMode = false;
+
+PRLogModuleInfo* IndexedDatabaseManager::sLoggingModule;
+
+Atomic<IndexedDatabaseManager::LoggingMode>
+  IndexedDatabaseManager::sLoggingMode(
+    IndexedDatabaseManager::Logging_Disabled);
+
 mozilla::Atomic<bool> IndexedDatabaseManager::sLowDiskSpaceMode(false);
 
 // static
 IndexedDatabaseManager*
 IndexedDatabaseManager::GetOrCreate()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (IsClosed()) {
     NS_ERROR("Calling GetOrCreate() after shutdown!");
     return nullptr;
   }
 
   if (!gDBManager) {
     sIsMainProcess = XRE_GetProcessType() == GeckoProcessType_Default;
 
+    if (!sLoggingModule) {
+      sLoggingModule = PR_NewLogModule("IndexedDB");
+    }
+
     if (sIsMainProcess && Preferences::GetBool("disk_space_watcher.enabled", false)) {
       // See if we're starting up in low disk space conditions.
       nsCOMPtr<nsIDiskSpaceWatcher> watcher =
         do_GetService(DISKSPACEWATCHER_CONTRACTID);
       if (watcher) {
         bool isDiskFull;
         if (NS_SUCCEEDED(watcher->GetIsDiskFull(&isDiskFull))) {
           sLowDiskSpaceMode = isDiskFull;
@@ -295,30 +323,48 @@ IndexedDatabaseManager::Init()
   // By default IndexedDB uses SQLite with PRAGMA synchronous = NORMAL. This
   // guarantees (unlike synchronous = OFF) atomicity and consistency, but not
   // necessarily durability in situations such as power loss. This preference
   // allows enabling PRAGMA synchronous = FULL on SQLite, which does guarantee
   // durability, but with an extra fsync() and the corresponding performance
   // hit.
   sFullSynchronousMode = Preferences::GetBool("dom.indexedDB.fullSynchronous");
 
+  Preferences::RegisterCallback(LoggingModePrefChangedCallback,
+                                kPrefLoggingDetails);
+#ifdef MOZ_ENABLE_PROFILER_SPS
+  Preferences::RegisterCallback(LoggingModePrefChangedCallback,
+                                kPrefLoggingProfiler);
+#endif
+  Preferences::RegisterCallbackAndCall(LoggingModePrefChangedCallback,
+                                       kPrefLoggingEnabled);
+
   return NS_OK;
 }
 
 void
 IndexedDatabaseManager::Destroy()
 {
   // Setting the closed flag prevents the service from being recreated.
   // Don't set it though if there's no real instance created.
   if (gInitialized && gClosed.exchange(true)) {
     NS_ERROR("Shutdown more than once?!");
   }
 
   Preferences::UnregisterCallback(TestingPrefChangedCallback, kTestingPref);
 
+  Preferences::UnregisterCallback(LoggingModePrefChangedCallback,
+                                  kPrefLoggingDetails);
+#ifdef MOZ_ENABLE_PROFILER_SPS
+  Preferences::UnregisterCallback(LoggingModePrefChangedCallback,
+                                  kPrefLoggingProfiler);
+#endif
+  Preferences::UnregisterCallback(LoggingModePrefChangedCallback,
+                                  kPrefLoggingEnabled);
+
   delete this;
 }
 
 // static
 nsresult
 IndexedDatabaseManager::FireWindowOnError(nsPIDOMWindow* aOwner,
                                           EventChainPostVisitor& aVisitor)
 {
@@ -486,17 +532,40 @@ IndexedDatabaseManager::IsMainProcess()
 bool
 IndexedDatabaseManager::InLowDiskSpaceMode()
 {
   NS_ASSERTION(gDBManager,
                "InLowDiskSpaceMode() called before indexedDB has been "
                "initialized!");
   return sLowDiskSpaceMode;
 }
-#endif
+
+// static
+IndexedDatabaseManager::LoggingMode
+IndexedDatabaseManager::GetLoggingMode()
+{
+  MOZ_ASSERT(gDBManager,
+             "GetLoggingMode called before IndexedDatabaseManager has been "
+             "initialized!");
+
+  return sLoggingMode;
+}
+
+// static
+PRLogModuleInfo*
+IndexedDatabaseManager::GetLoggingModule()
+{
+  MOZ_ASSERT(gDBManager,
+             "GetLoggingModule called before IndexedDatabaseManager has been "
+             "initialized!");
+
+  return sLoggingModule;
+}
+
+#endif // DEBUG
 
 // static
 bool
 IndexedDatabaseManager::InTestingMode()
 {
   MOZ_ASSERT(gDBManager,
              "InTestingMode() called before indexedDB has been initialized!");
 
@@ -682,16 +751,54 @@ IndexedDatabaseManager::BlockAndGetFileR
                                              aResult)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   return NS_OK;
 }
 
+// static
+void
+IndexedDatabaseManager::LoggingModePrefChangedCallback(
+                                                    const char* /* aPrefName */,
+                                                    void* /* aClosure */)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!Preferences::GetBool(kPrefLoggingEnabled)) {
+    sLoggingMode = Logging_Disabled;
+    return;
+  }
+
+  bool useProfiler = 
+#if defined(DEBUG) || defined(MOZ_ENABLE_PROFILER_SPS)
+    Preferences::GetBool(kPrefLoggingProfiler);
+#if !defined(MOZ_ENABLE_PROFILER_SPS)
+  if (useProfiler) {
+    NS_WARNING("IndexedDB cannot create profiler marks because this build does "
+               "not have profiler extensions enabled!");
+    useProfiler = false;
+  }
+#endif
+#else
+    false;
+#endif
+
+  const bool logDetails = Preferences::GetBool(kPrefLoggingDetails);
+
+  if (useProfiler) {
+    sLoggingMode = logDetails ?
+                   Logging_DetailedProfilerMarks :
+                   Logging_ConciseProfilerMarks;
+  } else {
+    sLoggingMode = logDetails ? Logging_Detailed : Logging_Concise;
+  }
+}
+
 NS_IMPL_ADDREF(IndexedDatabaseManager)
 NS_IMPL_RELEASE_WITH_DESTROY(IndexedDatabaseManager, Destroy())
 NS_IMPL_QUERY_INTERFACE(IndexedDatabaseManager, nsIObserver)
 
 NS_IMETHODIMP
 IndexedDatabaseManager::Observe(nsISupports* aSubject, const char* aTopic,
                                 const char16_t* aData)
 {
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -12,16 +12,17 @@
 #include "js/TypeDecls.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/dom/quota/PersistenceType.h"
 #include "mozilla/Mutex.h"
 #include "nsClassHashtable.h"
 #include "nsHashKeys.h"
 
 class nsPIDOMWindow;
+struct PRLogModuleInfo;
 
 namespace mozilla {
 
 class EventChainPostVisitor;
 
 namespace dom {
 
 class TabContext;
@@ -31,16 +32,25 @@ namespace indexedDB {
 class FileManager;
 class FileManagerInfo;
 
 class IndexedDatabaseManager MOZ_FINAL : public nsIObserver
 {
   typedef mozilla::dom::quota::PersistenceType PersistenceType;
 
 public:
+  enum LoggingMode
+  {
+    Logging_Disabled = 0,
+    Logging_Concise,
+    Logging_Detailed,
+    Logging_ConciseProfilerMarks,
+    Logging_DetailedProfilerMarks
+  };
+
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   // Returns a non-owning reference.
   static IndexedDatabaseManager*
   GetOrCreate();
 
   // Returns a non-owning reference.
@@ -71,16 +81,36 @@ public:
 #endif
 
   static bool
   InTestingMode();
 
   static bool
   FullSynchronous();
 
+  static LoggingMode
+  GetLoggingMode()
+#ifdef DEBUG
+  ;
+#else
+  {
+    return sLoggingMode;
+  }
+#endif
+
+  static PRLogModuleInfo*
+  GetLoggingModule()
+#ifdef DEBUG
+  ;
+#else
+  {
+    return sLoggingModule;
+  }
+#endif
+
   already_AddRefed<FileManager>
   GetFileManager(PersistenceType aPersistenceType,
                  const nsACString& aOrigin,
                  const nsAString& aDatabaseName);
 
   void
   AddFileManager(FileManager* aFileManager);
 
@@ -138,27 +168,32 @@ private:
   ~IndexedDatabaseManager();
 
   nsresult
   Init();
 
   void
   Destroy();
 
+  static void
+  LoggingModePrefChangedCallback(const char* aPrefName, void* aClosure);
+
   // Maintains a list of all file managers per origin. This list isn't
   // protected by any mutex but it is only ever touched on the IO thread.
   nsClassHashtable<nsCStringHashKey, FileManagerInfo> mFileManagerInfos;
 
   // Lock protecting FileManager.mFileInfos and FileImplBase.mFileInfos
   // It's s also used to atomically update FileInfo.mRefCnt, FileInfo.mDBRefCnt
   // and FileInfo.mSliceRefCnt
   mozilla::Mutex mFileMutex;
 
   static bool sIsMainProcess;
   static bool sFullSynchronousMode;
+  static PRLogModuleInfo* sLoggingModule;
+  static Atomic<LoggingMode> sLoggingMode;
   static mozilla::Atomic<bool> sLowDiskSpaceMode;
 };
 
 } // namespace indexedDB
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_indexeddb_indexeddatabasemanager_h__
--- a/dom/indexedDB/PBackgroundIDBFactory.ipdl
+++ b/dom/indexedDB/PBackgroundIDBFactory.ipdl
@@ -46,16 +46,18 @@ protocol PBackgroundIDBFactory
   manages PBackgroundIDBDatabase;
   manages PBackgroundIDBFactoryRequest;
 
 parent:
   DeleteMe();
 
   PBackgroundIDBFactoryRequest(FactoryRequestParams params);
 
+  IncrementLoggingRequestSerialNumber();
+
 child:
   __delete__();
 
   PBackgroundIDBDatabase(DatabaseSpec spec,
                          PBackgroundIDBFactoryRequest request);
 };
 
 } // namespace indexedDB
--- a/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh
+++ b/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh
@@ -1,15 +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 protocol PBlob;
 include protocol PBackgroundIDBDatabaseFile;
 
+include DOMTypes;
+
 include "mozilla/dom/indexedDB/SerializationHelpers.h";
 
 using struct mozilla::void_t
   from "ipc/IPCMessageUtils.h";
 
 using mozilla::dom::indexedDB::IDBCursor::Direction
   from "mozilla/dom/indexedDB/IDBCursor.h";
 
@@ -248,11 +250,19 @@ union RequestParams
   ObjectStoreCountParams;
   IndexGetParams;
   IndexGetKeyParams;
   IndexGetAllParams;
   IndexGetAllKeysParams;
   IndexCountParams;
 };
 
+struct LoggingInfo
+{
+  nsID backgroundChildLoggingId;
+  int64_t nextTransactionSerialNumber;
+  int64_t nextVersionChangeTransactionSerialNumber;
+  uint64_t nextRequestSerialNumber;
+};
+
 } // namespace indexedDB
 } // namespace dom
 } // namespace mozilla
--- a/dom/indexedDB/ProfilerHelpers.h
+++ b/dom/indexedDB/ProfilerHelpers.h
@@ -2,206 +2,330 @@
 /* vim: set ts=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_indexeddb_profilerhelpers_h__
 #define mozilla_dom_indexeddb_profilerhelpers_h__
 
-#include "GeckoProfiler.h"
-
-// Uncomment this if you want IndexedDB operations to be marked in the profiler.
-//#define IDB_PROFILER_USE_MARKS
-
-// Uncomment this if you want extended details to appear in profiler marks.
-//#define IDB_PROFILER_MARK_DETAILS 0
+// This file is not exported and is only meant to be included in IndexedDB
+// source files.
 
-// Sanity check the options above.
-#if defined(IDB_PROFILER_USE_MARKS) && !defined(MOZ_ENABLE_PROFILER_SPS)
-#error Cannot use IDB_PROFILER_USE_MARKS without MOZ_ENABLE_PROFILER_SPS!
-#endif
-
-#if defined(IDB_PROFILER_MARK_DETAILS) && !defined(IDB_PROFILER_USE_MARKS)
-#error Cannot use IDB_PROFILER_MARK_DETAILS without IDB_PROFILER_USE_MARKS!
-#endif
-
-#ifdef IDB_PROFILER_USE_MARKS
-
-#ifdef IDB_PROFILER_MARK_DETAILS
-
+#include "BackgroundChildImpl.h"
+#include "GeckoProfiler.h"
 #include "IDBCursor.h"
 #include "IDBDatabase.h"
 #include "IDBIndex.h"
 #include "IDBKeyRange.h"
 #include "IDBObjectStore.h"
 #include "IDBTransaction.h"
+#include "IndexedDatabaseManager.h"
 #include "Key.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/BindingDeclarations.h"
+#include "nsDebug.h"
+#include "nsID.h"
+#include "nsIDOMEvent.h"
+#include "nsString.h"
+#include "prlog.h"
+
+// Include this last to avoid path problems on Windows.
+#include "ActorsChild.h"
 
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
-class ProfilerString : public nsAutoCString
+class MOZ_STACK_CLASS LoggingIdString MOZ_FINAL
+  : public nsAutoCString
+{
+public:
+  LoggingIdString()
+  {
+    using mozilla::ipc::BackgroundChildImpl;
+
+    BackgroundChildImpl::ThreadLocal* threadLocal =
+      BackgroundChildImpl::GetThreadLocalForCurrentThread();
+    MOZ_ASSERT(threadLocal);
+
+    ThreadLocal* idbThreadLocal = threadLocal->mIndexedDBThreadLocal;
+    MOZ_ASSERT(idbThreadLocal);
+
+    Init(idbThreadLocal->Id());
+  }
+
+  explicit
+  LoggingIdString(const nsID& aID)
+  {
+    Init(aID);
+  }
+
+private:
+  void
+  Init(const nsID& aID)
+  {
+    static_assert(NSID_LENGTH > 1, "NSID_LENGTH is set incorrectly!");
+    MOZ_ASSERT(Capacity() > NSID_LENGTH);
+
+    // NSID_LENGTH counts the null terminator, SetLength() does not.
+    SetLength(NSID_LENGTH - 1);
+
+    aID.ToProvidedString(
+      *reinterpret_cast<char(*)[NSID_LENGTH]>(BeginWriting()));
+  }
+};
+
+class MOZ_STACK_CLASS LoggingString MOZ_FINAL
+  : public nsAutoCString
 {
   static const char kQuote = '\"';
   static const char kOpenBracket = '[';
   static const char kCloseBracket = ']';
   static const char kOpenParen = '(';
   static const char kCloseParen = ')';
 
 public:
   explicit
-  ProfilerString(IDBDatabase* aDatabase)
+  LoggingString(IDBDatabase* aDatabase)
+    : nsAutoCString(kQuote)
   {
     MOZ_ASSERT(aDatabase);
 
-    Append(kQuote);
     AppendUTF16toUTF8(aDatabase->Name(), *this);
     Append(kQuote);
   }
 
   explicit
-  ProfilerString(IDBTransaction* aTransaction)
+  LoggingString(IDBTransaction* aTransaction)
+    : nsAutoCString(kOpenBracket)
   {
     MOZ_ASSERT(aTransaction);
 
+    NS_NAMED_LITERAL_CSTRING(kCommaSpace, ", ");
+
+    const nsTArray<nsString>& stores = aTransaction->ObjectStoreNamesInternal();
+
+    for (uint32_t count = stores.Length(), index = 0; index < count; index++) {
+      Append(kQuote);
+      AppendUTF16toUTF8(stores[index], *this);
+      Append(kQuote);
+
+      if (index != count - 1) {
+        Append(kCommaSpace);
+      }
+    }
+
+    Append(kCloseBracket);
+    Append(kCommaSpace);
+
     switch (aTransaction->GetMode()) {
       case IDBTransaction::READ_ONLY:
         AppendLiteral("\"readonly\"");
         break;
       case IDBTransaction::READ_WRITE:
         AppendLiteral("\"readwrite\"");
         break;
       case IDBTransaction::VERSION_CHANGE:
         AppendLiteral("\"versionchange\"");
         break;
       default:
         MOZ_CRASH("Unknown mode!");
     };
   }
 
   explicit
-  ProfilerString(IDBObjectStore* aObjectStore)
+  LoggingString(IDBObjectStore* aObjectStore)
+    : nsAutoCString(kQuote)
   {
     MOZ_ASSERT(aObjectStore);
 
-    Append(kQuote);
     AppendUTF16toUTF8(aObjectStore->Name(), *this);
     Append(kQuote);
   }
 
   explicit
-  ProfilerString(IDBIndex* aIndex)
+  LoggingString(IDBIndex* aIndex)
+    : nsAutoCString(kQuote)
   {
     MOZ_ASSERT(aIndex);
 
-    Append(kQuote);
     AppendUTF16toUTF8(aIndex->Name(), *this);
     Append(kQuote);
   }
 
   explicit
-  ProfilerString(IDBKeyRange* aKeyRange)
+  LoggingString(IDBKeyRange* aKeyRange)
   {
     if (aKeyRange) {
       if (aKeyRange->IsOnly()) {
-        Append(ProfilerString(aKeyRange->Lower()));
+        Assign(LoggingString(aKeyRange->Lower()));
+      } else {
+        Assign(aKeyRange->LowerOpen() ? kOpenParen : kOpenBracket);
+        Append(LoggingString(aKeyRange->Lower()));
+        AppendLiteral(", ");
+        Append(LoggingString(aKeyRange->Upper()));
+        Append(aKeyRange->UpperOpen() ? kCloseParen : kCloseBracket);
       }
-      else {
-        Append(aKeyRange->IsLowerOpen() ? kOpenParen : kOpenBracket);
-        Append(ProfilerString(aKeyRange->Lower()));
-        AppendLiteral(", ");
-        Append(ProfilerString(aKeyRange->Upper()));
-        Append(aKeyRange->IsUpperOpen() ? kCloseParen : kCloseBracket);
-      }
+    } else {
+      AssignLiteral("<undefined>");
     }
   }
 
   explicit
-  ProfilerString(const Key& aKey)
+  LoggingString(const Key& aKey)
   {
     if (aKey.IsUnset()) {
-      AssignLiteral("null");
-    }
-    else if (aKey.IsFloat()) {
+      AssignLiteral("<undefined>");
+    } else if (aKey.IsFloat()) {
       AppendPrintf("%g", aKey.ToFloat());
-    }
-    else if (aKey.IsDate()) {
+    } else if (aKey.IsDate()) {
       AppendPrintf("<Date %g>", aKey.ToDateMsec());
-    }
-    else if (aKey.IsString()) {
+    } else if (aKey.IsString()) {
       nsAutoString str;
       aKey.ToString(str);
       AppendPrintf("\"%s\"", NS_ConvertUTF16toUTF8(str).get());
-    }
-    else {
+    } else {
       MOZ_ASSERT(aKey.IsArray());
-      AppendLiteral("<Array>");
+      AssignLiteral("[...]");
     }
   }
 
   explicit
-  ProfilerString(const IDBCursor::Direction aDirection)
+  LoggingString(const IDBCursor::Direction aDirection)
   {
     switch (aDirection) {
       case IDBCursor::NEXT:
-        AppendLiteral("\"next\"");
+        AssignLiteral("\"next\"");
         break;
       case IDBCursor::NEXT_UNIQUE:
-        AppendLiteral("\"nextunique\"");
+        AssignLiteral("\"nextunique\"");
         break;
       case IDBCursor::PREV:
-        AppendLiteral("\"prev\"");
+        AssignLiteral("\"prev\"");
         break;
       case IDBCursor::PREV_UNIQUE:
-        AppendLiteral("\"prevunique\"");
+        AssignLiteral("\"prevunique\"");
         break;
       default:
         MOZ_CRASH("Unknown direction!");
     };
   }
+
+  explicit
+  LoggingString(const Optional<uint64_t>& aVersion)
+  {
+    if (aVersion.WasPassed()) {
+      AppendInt(aVersion.Value());
+    } else {
+      AssignLiteral("<undefined>");
+    }
+  }
+
+  explicit
+  LoggingString(const Optional<uint32_t>& aLimit)
+  {
+    if (aLimit.WasPassed()) {
+      AppendInt(aLimit.Value());
+    } else {
+      AssignLiteral("<undefined>");
+    }
+  }
+
+  LoggingString(IDBObjectStore* aObjectStore, const Key& aKey)
+  {
+    MOZ_ASSERT(aObjectStore);
+
+    if (!aObjectStore->HasValidKeyPath()) {
+      Append(LoggingString(aKey));
+    }
+  }
+
+  LoggingString(nsIDOMEvent* aEvent, const char16_t* aDefault)
+    : nsAutoCString(kQuote)
+  {
+    MOZ_ASSERT(aDefault);
+
+    nsString eventType;
+
+    if (aEvent) {
+      MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aEvent->GetType(eventType)));
+    } else {
+      eventType = nsDependentString(aDefault);
+    }
+
+    AppendUTF16toUTF8(eventType, *this);
+    Append(kQuote);
+  }
 };
 
+inline void
+LoggingHelper(bool aUseProfiler, const char* aFmt, ...)
+{
+  MOZ_ASSERT(IndexedDatabaseManager::GetLoggingMode() !=
+               IndexedDatabaseManager::Logging_Disabled);
+  MOZ_ASSERT(aFmt);
+
+  PRLogModuleInfo* logModule = IndexedDatabaseManager::GetLoggingModule();
+  MOZ_ASSERT(logModule);
+
+  static const PRLogModuleLevel logLevel = PR_LOG_DEBUG;
+
+  if (PR_LOG_TEST(logModule, logLevel) ||
+      (aUseProfiler && profiler_is_active())) {
+    nsAutoCString message;
+
+    {
+      va_list args;
+      va_start(args, aFmt);
+
+      message.AppendPrintf(aFmt, args);
+
+      va_end(args);
+    }
+
+    PR_LOG(logModule, logLevel, ("%s", message.get()));
+
+    if (aUseProfiler) {
+      PROFILER_MARKER(message.get());
+    }
+  }
+}
+
 } // namespace indexedDB
 } // namespace dom
 } // namespace mozilla
 
-#define IDB_PROFILER_MARK(_detailedFmt, _conciseFmt, ...)                      \
-  do {                                                                         \
-    nsAutoCString _mark;                                                       \
-    _mark.AppendPrintf(_detailedFmt, ##__VA_ARGS__);                           \
-    PROFILER_MARKER(_mark.get());                                              \
-  } while (0)
-
-#define IDB_PROFILER_STRING(_arg)                                              \
-  mozilla::dom::indexedDB::ProfilerString((_arg)).get()
-
-#else // IDB_PROFILER_MARK_DETAILS
-
-#define IDB_PROFILER_MARK(_detailedFmt, _conciseFmt, ...)                      \
+#define IDB_LOG_MARK(_detailedFmt, _conciseFmt, ...)                           \
   do {                                                                         \
-    nsAutoCString _mark;                                                       \
-    _mark.AppendPrintf(_conciseFmt, ##__VA_ARGS__);                            \
-    PROFILER_MARKER(_mark.get());                                              \
-  } while (0)
-
-#define IDB_PROFILER_STRING(_arg) ""
-
-#endif // IDB_PROFILER_MARK_DETAILS
-
-#define IDB_PROFILER_MARK_IF(_cond, _detailedFmt, _conciseFmt, ...)            \
-  do {                                                                         \
-    if (_cond) {                                                               \
-      IDB_PROFILER_MARK(_detailedFmt, _conciseFmt, __VA_ARGS__);               \
+    using namespace mozilla::dom::indexedDB;                                   \
+                                                                               \
+    const IndexedDatabaseManager::LoggingMode mode =                           \
+      IndexedDatabaseManager::GetLoggingMode();                                \
+                                                                               \
+    if (mode != IndexedDatabaseManager::Logging_Disabled) {                    \
+      const char* _fmt;                                                        \
+      if (mode == IndexedDatabaseManager::Logging_Concise ||                   \
+          mode == IndexedDatabaseManager::Logging_ConciseProfilerMarks) {      \
+        _fmt = _conciseFmt;                                                    \
+      } else {                                                                 \
+        MOZ_ASSERT(                                                            \
+          mode == IndexedDatabaseManager::Logging_Detailed ||                  \
+          mode == IndexedDatabaseManager::Logging_DetailedProfilerMarks);      \
+        _fmt = _detailedFmt;                                                   \
+      }                                                                        \
+                                                                               \
+      const bool _useProfiler =                                                \
+        mode == IndexedDatabaseManager::Logging_ConciseProfilerMarks ||        \
+        mode == IndexedDatabaseManager::Logging_DetailedProfilerMarks;         \
+                                                                               \
+      LoggingHelper(_useProfiler, _fmt, ##__VA_ARGS__);                        \
     }                                                                          \
   } while (0)
 
-#else // IDB_PROFILER_USE_MARKS
+#define IDB_LOG_ID_STRING(...)                                                 \
+  mozilla::dom::indexedDB::LoggingIdString(__VA_ARGS__).get()
 
-#define IDB_PROFILER_MARK(...) do { } while(0)
-#define IDB_PROFILER_MARK_IF(_cond, ...) do { } while(0)
-#define IDB_PROFILER_MARK2(_detailedFmt, _notdetailedFmt, ...) do { } while(0)
-#define IDB_PROFILER_STRING(_arg) ""
-
-#endif // IDB_PROFILER_USE_MARKS
+#define IDB_LOG_STRINGIFY(...)                                                 \
+  mozilla::dom::indexedDB::LoggingString(__VA_ARGS__).get()
 
 #endif // mozilla_dom_indexeddb_profilerhelpers_h__
--- a/dom/indexedDB/TransactionThreadPool.cpp
+++ b/dom/indexedDB/TransactionThreadPool.cpp
@@ -139,31 +139,35 @@ private:
 };
 
 class TransactionThreadPool::TransactionQueue MOZ_FINAL
   : public nsRunnable
 {
   Monitor mMonitor;
 
   nsRefPtr<TransactionThreadPool> mOwningThreadPool;
-  uint64_t mTransactionId;
+  const uint64_t mTransactionId;
+  const nsID mBackgroundChildLoggingId;
+  const int64_t mLoggingSerialNumber;
   const nsCString mDatabaseId;
   const nsTArray<nsString> mObjectStoreNames;
   uint16_t mMode;
 
   nsAutoTArray<nsCOMPtr<nsIRunnable>, 10> mQueue;
   nsRefPtr<FinishCallback> mFinishCallback;
   bool mShouldFinish;
 
 public:
   TransactionQueue(TransactionThreadPool* aThreadPool,
-                    uint64_t aTransactionId,
-                    const nsACString& aDatabaseId,
-                    const nsTArray<nsString>& aObjectStoreNames,
-                    uint16_t aMode);
+                   uint64_t aTransactionId,
+                   const nsACString& aDatabaseId,
+                   const nsTArray<nsString>& aObjectStoreNames,
+                   uint16_t aMode,
+                   const nsID& aBackgroundChildLoggingId,
+                   int64_t aLoggingSerialNumber);
 
   NS_DECL_ISUPPORTS_INHERITED
 
   void Unblock();
 
   void Dispatch(nsIRunnable* aRunnable);
 
   void Finish(FinishCallback* aFinishCallback);
@@ -182,23 +186,31 @@ struct TransactionThreadPool::Transactio
   nsRefPtr<TransactionQueue> queue;
   nsTHashtable<nsPtrHashKey<TransactionInfo>> blockedOn;
   nsTHashtable<nsPtrHashKey<TransactionInfo>> blocking;
 
   TransactionInfo(TransactionThreadPool* aThreadPool,
                   uint64_t aTransactionId,
                   const nsACString& aDatabaseId,
                   const nsTArray<nsString>& aObjectStoreNames,
-                  uint16_t aMode)
+                  uint16_t aMode,
+                  const nsID& aBackgroundChildLoggingId,
+                  int64_t aLoggingSerialNumber)
   : transactionId(aTransactionId), databaseId(aDatabaseId)
   {
     MOZ_COUNT_CTOR(TransactionInfo);
 
-    queue = new TransactionQueue(aThreadPool, aTransactionId, aDatabaseId,
-                                  aObjectStoreNames, aMode);
+    queue =
+      new TransactionQueue(aThreadPool,
+                           aTransactionId,
+                           aDatabaseId,
+                           aObjectStoreNames,
+                           aMode,
+                           aBackgroundChildLoggingId,
+                           aLoggingSerialNumber);
   }
 
   ~TransactionInfo()
   {
     MOZ_COUNT_DTOR(TransactionInfo);
   }
 };
 
@@ -297,17 +309,16 @@ TransactionThreadPool::Shutdown()
   nsIThread* currentThread = NS_GetCurrentThread();
   MOZ_ASSERT(currentThread);
 
   while (!mShutdownComplete) {
     MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(currentThread));
   }
 }
 
-// static
 uint64_t
 TransactionThreadPool::NextTransactionId()
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mNextTransactionId < UINT64_MAX);
 
   return ++mNextTransactionId;
 }
@@ -543,30 +554,27 @@ TransactionThreadPool::GetQueueForTransa
       return info->queue;
     }
   }
 
   return nullptr;
 }
 
 TransactionThreadPool::TransactionQueue&
-TransactionThreadPool::GetQueueForTransaction(
+TransactionThreadPool::CreateQueueForTransaction(
                                     uint64_t aTransactionId,
                                     const nsACString& aDatabaseId,
                                     const nsTArray<nsString>& aObjectStoreNames,
-                                    uint16_t aMode)
+                                    uint16_t aMode,
+                                    const nsID& aBackgroundChildLoggingId,
+                                    int64_t aLoggingSerialNumber)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aTransactionId <= mNextTransactionId);
-
-  TransactionQueue* existingQueue =
-    GetQueueForTransaction(aTransactionId, aDatabaseId);
-  if (existingQueue) {
-    return *existingQueue;
-  }
+  MOZ_ASSERT(!GetQueueForTransaction(aTransactionId, aDatabaseId));
 
   // See if we can run this transaction now.
   DatabaseTransactionInfo* dbTransactionInfo;
   if (!mTransactionsInProgress.Get(aDatabaseId, &dbTransactionInfo)) {
     // First transaction for this database.
     dbTransactionInfo = new DatabaseTransactionInfo();
     mTransactionsInProgress.Put(aDatabaseId, dbTransactionInfo);
   }
@@ -574,21 +582,24 @@ TransactionThreadPool::GetQueueForTransa
   DatabaseTransactionInfo::TransactionHashtable& transactionsInProgress =
     dbTransactionInfo->transactions;
   TransactionInfo* info = transactionsInProgress.Get(aTransactionId);
   if (info) {
     // We recognize this one.
     return *info->queue;
   }
 
-  TransactionInfo* transactionInfo = new TransactionInfo(this,
-                                                         aTransactionId,
-                                                         aDatabaseId,
-                                                         aObjectStoreNames,
-                                                         aMode);
+  TransactionInfo* transactionInfo =
+    new TransactionInfo(this,
+                        aTransactionId,
+                        aDatabaseId,
+                        aObjectStoreNames,
+                        aMode,
+                        aBackgroundChildLoggingId,
+                        aLoggingSerialNumber);
 
   dbTransactionInfo->transactions.Put(aTransactionId, transactionInfo);;
 
   for (uint32_t index = 0, count = aObjectStoreNames.Length(); index < count;
        index++) {
     TransactionInfoPair* blockInfo =
       dbTransactionInfo->blockingTransactions.Get(aObjectStoreNames[index]);
     if (!blockInfo) {
@@ -628,36 +639,37 @@ TransactionThreadPool::GetQueueForTransa
   if (!transactionInfo->blockedOn.Count()) {
     transactionInfo->queue->Unblock();
   }
 
   return *transactionInfo->queue;
 }
 
 void
-TransactionThreadPool::Dispatch(uint64_t aTransactionId,
-                                const nsACString& aDatabaseId,
-                                const nsTArray<nsString>& aObjectStoreNames,
-                                uint16_t aMode,
-                                nsIRunnable* aRunnable,
-                                bool aFinish,
-                                FinishCallback* aFinishCallback)
+TransactionThreadPool::Start(uint64_t aTransactionId,
+                             const nsACString& aDatabaseId,
+                             const nsTArray<nsString>& aObjectStoreNames,
+                             uint16_t aMode,
+                             const nsID& aBackgroundChildLoggingId,
+                             int64_t aLoggingSerialNumber,
+                             nsIRunnable* aRunnable)
 {
+  AssertIsOnOwningThread();
   MOZ_ASSERT(aTransactionId <= mNextTransactionId);
+  MOZ_ASSERT(aRunnable);
   MOZ_ASSERT(!mShutdownRequested);
 
-  TransactionQueue& queue = GetQueueForTransaction(aTransactionId,
-                                                   aDatabaseId,
-                                                   aObjectStoreNames,
-                                                   aMode);
+  TransactionQueue& queue = CreateQueueForTransaction(aTransactionId,
+                                                      aDatabaseId,
+                                                      aObjectStoreNames,
+                                                      aMode,
+                                                      aBackgroundChildLoggingId,
+                                                      aLoggingSerialNumber);
 
   queue.Dispatch(aRunnable);
-  if (aFinish) {
-    queue.Finish(aFinishCallback);
-  }
 }
 
 void
 TransactionThreadPool::Dispatch(uint64_t aTransactionId,
                                 const nsACString& aDatabaseId,
                                 nsIRunnable* aRunnable,
                                 bool aFinish,
                                 FinishCallback* aFinishCallback)
@@ -760,24 +772,28 @@ TransactionThreadPool::MaybeFireCallback
   return true;
 }
 
 TransactionThreadPool::
 TransactionQueue::TransactionQueue(TransactionThreadPool* aThreadPool,
                                    uint64_t aTransactionId,
                                    const nsACString& aDatabaseId,
                                    const nsTArray<nsString>& aObjectStoreNames,
-                                   uint16_t aMode)
-: mMonitor("TransactionQueue::mMonitor"),
-  mOwningThreadPool(aThreadPool),
-  mTransactionId(aTransactionId),
-  mDatabaseId(aDatabaseId),
-  mObjectStoreNames(aObjectStoreNames),
-  mMode(aMode),
-  mShouldFinish(false)
+                                   uint16_t aMode,
+                                   const nsID& aBackgroundChildLoggingId,
+                                   int64_t aLoggingSerialNumber)
+  : mMonitor("TransactionQueue::mMonitor")
+  , mOwningThreadPool(aThreadPool)
+  , mTransactionId(aTransactionId)
+  , mBackgroundChildLoggingId(aBackgroundChildLoggingId)
+  , mLoggingSerialNumber(aLoggingSerialNumber)
+  , mDatabaseId(aDatabaseId)
+  , mObjectStoreNames(aObjectStoreNames)
+  , mMode(aMode)
+  , mShouldFinish(false)
 {
   MOZ_ASSERT(aThreadPool);
   aThreadPool->AssertIsOnOwningThread();
 }
 
 void
 TransactionThreadPool::TransactionQueue::Unblock()
 {
@@ -819,19 +835,21 @@ NS_IMPL_ISUPPORTS_INHERITED0(Transaction
 
 NS_IMETHODIMP
 TransactionThreadPool::TransactionQueue::Run()
 {
   PROFILER_LABEL("IndexedDB",
                  "TransactionThreadPool::TransactionQueue""Run",
                  js::ProfileEntry::Category::STORAGE);
 
-  IDB_PROFILER_MARK("IndexedDB Transaction %llu: Beginning database work",
-                    "IDBTransaction[%llu] DT Start",
-                    mTransaction->GetSerialNumber());
+  IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld]: "
+                 "Beginning database work",
+               "IndexedDB %s: P T[%lld]: DB Start",
+               IDB_LOG_ID_STRING(mBackgroundChildLoggingId),
+               mLoggingSerialNumber);
 
   nsAutoTArray<nsCOMPtr<nsIRunnable>, 10> queue;
   nsRefPtr<FinishCallback> finishCallback;
   bool shouldFinish = false;
 
   do {
     NS_ASSERTION(queue.IsEmpty(), "Should have cleared this!");
 
@@ -872,19 +890,21 @@ TransactionThreadPool::TransactionQueue:
 
 #ifdef DEBUG
   if (kDEBUGThreadSleepMS) {
     MOZ_ALWAYS_TRUE(
       PR_Sleep(PR_MillisecondsToInterval(kDEBUGThreadSleepMS)) == PR_SUCCESS);
   }
 #endif // DEBUG
 
-  IDB_PROFILER_MARK("IndexedDB Transaction %llu: Finished database work",
-                    "IDBTransaction[%llu] DT Done",
-                    mTransaction->GetSerialNumber());
+  IDB_LOG_MARK("IndexedDB %s: Parent Transaction[%lld]: "
+                 "Finished database work",
+               "IndexedDB %s: P T[%lld]: DB End",
+               IDB_LOG_ID_STRING(mBackgroundChildLoggingId),
+               mLoggingSerialNumber);
 
   nsRefPtr<FinishTransactionRunnable> finishTransactionRunnable =
     new FinishTransactionRunnable(mOwningThreadPool.forget(),
                                   mTransactionId,
                                   mDatabaseId,
                                   mObjectStoreNames,
                                   mMode,
                                   finishCallback.forget());
--- a/dom/indexedDB/TransactionThreadPool.h
+++ b/dom/indexedDB/TransactionThreadPool.h
@@ -10,16 +10,17 @@
 #include "mozilla/Attributes.h"
 #include "nsAutoPtr.h"
 #include "nsClassHashtable.h"
 #include "nsCOMPtr.h"
 #include "nsHashKeys.h"
 #include "nsISupportsImpl.h"
 #include "nsTArray.h"
 
+struct nsID;
 class nsIEventTarget;
 class nsIRunnable;
 class nsIThreadPool;
 
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
@@ -50,23 +51,23 @@ class TransactionThreadPool MOZ_FINAL
 
 public:
   class FinishCallback;
 
   static already_AddRefed<TransactionThreadPool> Create();
 
   uint64_t NextTransactionId();
 
-  void Dispatch(uint64_t aTransactionId,
-                const nsACString& aDatabaseId,
-                const nsTArray<nsString>& aObjectStoreNames,
-                uint16_t aMode,
-                nsIRunnable* aRunnable,
-                bool aFinish,
-                FinishCallback* aFinishCallback);
+  void Start(uint64_t aTransactionId,
+             const nsACString& aDatabaseId,
+             const nsTArray<nsString>& aObjectStoreNames,
+             uint16_t aMode,
+             const nsID& aBackgroundChildLoggingId,
+             int64_t aLoggingSerialNumber,
+             nsIRunnable* aRunnable);
 
   void Dispatch(uint64_t aTransactionId,
                 const nsACString& aDatabaseId,
                 nsIRunnable* aRunnable,
                 bool aFinish,
                 FinishCallback* aFinishCallback);
 
   void WaitForDatabasesToComplete(nsTArray<nsCString>& aDatabaseIds,
@@ -109,21 +110,23 @@ private:
   void FinishTransaction(uint64_t aTransactionId,
                          const nsACString& aDatabaseId,
                          const nsTArray<nsString>& aObjectStoreNames,
                          uint16_t aMode);
 
   TransactionQueue* GetQueueForTransaction(uint64_t aTransactionId,
                                            const nsACString& aDatabaseId);
 
-  TransactionQueue& GetQueueForTransaction(
+  TransactionQueue& CreateQueueForTransaction(
                                     uint64_t aTransactionId,
                                     const nsACString& aDatabaseId,
                                     const nsTArray<nsString>& aObjectStoreNames,
-                                    uint16_t aMode);
+                                    uint16_t aMode,
+                                    const nsID& aBackgroundChildLoggingId,
+                                    int64_t aLoggingSerialNumber);
 
   bool MaybeFireCallback(DatabasesCompleteCallback* aCallback);
 
   void CleanupAsync();
 };
 
 class NS_NO_VTABLE TransactionThreadPool::FinishCallback
 {
--- a/dom/media/mediasource/MediaSourceReader.cpp
+++ b/dom/media/mediasource/MediaSourceReader.cpp
@@ -263,17 +263,17 @@ MediaSourceReader::OnVideoNotDecoded(Not
     mVideoPromise.Reject(aReason, __func__);
     return;
   }
 
   // End of stream. Force switching past this stream to another reader by
   // switching to the end of the buffered range.
   MOZ_ASSERT(aReason == END_OF_STREAM);
   if (mVideoReader) {
-    AdjustEndTime(&mLastVideoTime, mAudioReader);
+    AdjustEndTime(&mLastVideoTime, mVideoReader);
   }
 
   // See if we can find a different reader that can pick up where we left off. We use the
   // EOS_FUZZ_US to allow for the fact that our end time can be inaccurate due to bug
   // 1065207.
   if (SwitchVideoReader(mLastVideoTime + EOS_FUZZ_US)) {
     mVideoReader->RequestVideoData(false, 0)
                 ->Then(GetTaskQueue(), __func__, this,
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -229,18 +229,18 @@ public:
     copy.mContentDescription.Truncate();
     return copy;
   }
 
   // ---------------------------------------------------------------------------
   // The following metrics are all in widget space/device pixels.
   //
 
-  // This is the area within the widget that we're compositing to. It is relative
-  // to the layer tree origin.
+  // This is the area within the widget that we're compositing to. It is in the
+  // same coordinate space as the reference frame for the scrolled frame.
   //
   // This is useful because, on mobile, the viewport and composition dimensions
   // are not always the same. In this case, we calculate the displayport using
   // an area bigger than the region we're compositing to. If we used the
   // viewport dimensions to calculate the displayport, we'd run into situations
   // where we're prerendering the wrong regions and the content may be clipped,
   // or too much of it prerendered. If the composition dimensions are the same as the
   // viewport dimensions, there is no need for this and we can just use the viewport
@@ -251,21 +251,18 @@ public:
   // layout/paint time.
   ParentLayerRect mCompositionBounds;
 
   // ---------------------------------------------------------------------------
   // The following metrics are all in CSS pixels. They are not in any uniform
   // space, so each is explained separately.
   //
 
-  // The area of a frame's contents that has been painted, relative to the
-  // viewport. It is in the same coordinate space as |mViewport|. For example,
-  // if it is at 0,0, then it's at the same place at the viewport, which is at
-  // the top-left in the layer, and at the same place as the scroll offset of
-  // the document.
+  // The area of a frame's contents that has been painted, relative to
+  // mCompositionBounds.
   //
   // Note that this is structured in such a way that it doesn't depend on the
   // method layout uses to scroll content.
   //
   // May be larger or smaller than |mScrollableRect|.
   //
   // To pre-render a margin of 100 CSS pixels around the window,
   // { x = -100, y = - 100,
--- a/gfx/layers/apz/src/InputQueue.cpp
+++ b/gfx/layers/apz/src/InputQueue.cpp
@@ -122,17 +122,22 @@ InputQueue::ReceiveTouchInput(const nsRe
 
 nsEventStatus
 InputQueue::ReceiveScrollWheelInput(const nsRefPtr<AsyncPanZoomController>& aTarget,
                                     bool aTargetConfirmed,
                                     const ScrollWheelInput& aEvent,
                                     uint64_t* aOutInputBlockId) {
   WheelBlockState* block = nullptr;
   if (!mInputBlockQueue.IsEmpty()) {
-    block = mInputBlockQueue.LastElement().get()->AsWheelBlock();
+    block = mInputBlockQueue.LastElement()->AsWheelBlock();
+
+    // If the block's APZC has been destroyed, request a new block.
+    if (block && block->GetTargetApzc()->IsDestroyed()) {
+      block = nullptr;
+    }
   }
 
   if (!block) {
     block = new WheelBlockState(aTarget, aTargetConfirmed);
     INPQ_LOG("started new scroll wheel block %p for target %p\n", block, aTarget.get());
 
     SweepDepletedBlocks();
     mInputBlockQueue.AppendElement(block);
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -159,18 +159,17 @@ APZCCallbackHelper::UpdateRootFrame(nsID
 
     ScreenMargin margins = aMetrics.GetDisplayPortMargins();
     aUtils->SetDisplayPortMarginsForElement(margins.left,
                                             margins.top,
                                             margins.right,
                                             margins.bottom,
                                             element, 0);
     CSSRect baseCSS = aMetrics.CalculateCompositedRectInCssPixels();
-    nsRect base(baseCSS.x * nsPresContext::AppUnitsPerCSSPixel(),
-                baseCSS.y * nsPresContext::AppUnitsPerCSSPixel(),
+    nsRect base(0, 0,
                 baseCSS.width * nsPresContext::AppUnitsPerCSSPixel(),
                 baseCSS.height * nsPresContext::AppUnitsPerCSSPixel());
     nsLayoutUtils::SetDisplayPortBaseIfNotSet(content, base);
 }
 
 void
 APZCCallbackHelper::UpdateSubFrame(nsIContent* aContent,
                                    FrameMetrics& aMetrics)
@@ -203,18 +202,17 @@ APZCCallbackHelper::UpdateSubFrame(nsICo
         }
         ScreenMargin margins = aMetrics.GetDisplayPortMargins();
         utils->SetDisplayPortMarginsForElement(margins.left,
                                                margins.top,
                                                margins.right,
                                                margins.bottom,
                                                element, 0);
         CSSRect baseCSS = aMetrics.CalculateCompositedRectInCssPixels();
-        nsRect base(baseCSS.x * nsPresContext::AppUnitsPerCSSPixel(),
-                    baseCSS.y * nsPresContext::AppUnitsPerCSSPixel(),
+        nsRect base(0, 0,
                     baseCSS.width * nsPresContext::AppUnitsPerCSSPixel(),
                     baseCSS.height * nsPresContext::AppUnitsPerCSSPixel());
         nsLayoutUtils::SetDisplayPortBaseIfNotSet(aContent, base);
     }
 
     aMetrics.SetScrollOffset(actualScrollOffset);
 }
 
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -1,20 +1,22 @@
 /* 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 "BackgroundChildImpl.h"
 
+#include "ActorsChild.h" // IndexedDB
 #include "FileDescriptorSetChild.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/PBlobChild.h"
 #include "mozilla/dom/indexedDB/PBackgroundIDBFactoryChild.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/ipc/PBackgroundTestChild.h"
+#include "nsID.h"
 #include "nsTraceRefcnt.h"
 
 namespace {
 
 class TestChild MOZ_FINAL : public mozilla::ipc::PBackgroundTestChild
 {
   friend class mozilla::ipc::BackgroundChildImpl;
 
@@ -43,21 +45,16 @@ namespace mozilla {
 namespace ipc {
 
 // -----------------------------------------------------------------------------
 // BackgroundChildImpl::ThreadLocal
 // -----------------------------------------------------------------------------
 
 BackgroundChildImpl::
 ThreadLocal::ThreadLocal()
-  : mCurrentTransaction(nullptr)
-#ifdef MOZ_ENABLE_PROFILER_SPS
-  , mNextTransactionSerialNumber(1)
-  , mNextRequestSerialNumber(1)
-#endif
 {
   // May happen on any thread!
   MOZ_COUNT_CTOR(mozilla::ipc::BackgroundChildImpl::ThreadLocal);
 }
 
 BackgroundChildImpl::
 ThreadLocal::~ThreadLocal()
 {
@@ -131,17 +128,18 @@ BackgroundChildImpl::DeallocPBackgroundT
 {
   MOZ_ASSERT(aActor);
 
   delete static_cast<TestChild*>(aActor);
   return true;
 }
 
 BackgroundChildImpl::PBackgroundIDBFactoryChild*
-BackgroundChildImpl::AllocPBackgroundIDBFactoryChild()
+BackgroundChildImpl::AllocPBackgroundIDBFactoryChild(
+                                                const LoggingInfo& aLoggingInfo)
 {
   MOZ_CRASH("PBackgroundIDBFactoryChild actors should be manually "
             "constructed!");
 }
 
 bool
 BackgroundChildImpl::DeallocPBackgroundIDBFactoryChild(
                                              PBackgroundIDBFactoryChild* aActor)
--- a/ipc/glue/BackgroundChildImpl.h
+++ b/ipc/glue/BackgroundChildImpl.h
@@ -2,24 +2,23 @@
  * 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_ipc_backgroundchildimpl_h__
 #define mozilla_ipc_backgroundchildimpl_h__
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ipc/PBackgroundChild.h"
-
-template <class> class nsAutoPtr;
+#include "nsAutoPtr.h"
 
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
-class IDBTransaction;
+class ThreadLocal;
 
 } // namespace indexedDB
 } // namespace dom
 
 namespace ipc {
 
 // Instances of this class should never be created directly. This class is meant
 // to be inherited in BackgroundImpl.
@@ -48,17 +47,17 @@ protected:
 
   virtual PBackgroundTestChild*
   AllocPBackgroundTestChild(const nsCString& aTestArg) MOZ_OVERRIDE;
 
   virtual bool
   DeallocPBackgroundTestChild(PBackgroundTestChild* aActor) MOZ_OVERRIDE;
 
   virtual PBackgroundIDBFactoryChild*
-  AllocPBackgroundIDBFactoryChild() MOZ_OVERRIDE;
+  AllocPBackgroundIDBFactoryChild(const LoggingInfo& aLoggingInfo) MOZ_OVERRIDE;
 
   virtual bool
   DeallocPBackgroundIDBFactoryChild(PBackgroundIDBFactoryChild* aActor)
                                     MOZ_OVERRIDE;
 
   virtual PBlobChild*
   AllocPBlobChild(const BlobConstructorParams& aParams) MOZ_OVERRIDE;
 
@@ -73,22 +72,17 @@ protected:
   DeallocPFileDescriptorSetChild(PFileDescriptorSetChild* aActor) MOZ_OVERRIDE;
 };
 
 class BackgroundChildImpl::ThreadLocal MOZ_FINAL
 {
   friend class nsAutoPtr<ThreadLocal>;
 
 public:
-  mozilla::dom::indexedDB::IDBTransaction* mCurrentTransaction;
-
-#ifdef MOZ_ENABLE_PROFILER_SPS
-  uint64_t mNextTransactionSerialNumber;
-  uint64_t mNextRequestSerialNumber;
-#endif
+  nsAutoPtr<mozilla::dom::indexedDB::ThreadLocal> mIndexedDBThreadLocal;
 
 public:
   ThreadLocal();
 
 private:
   // Only destroyed by nsAutoPtr<ThreadLocal>.
   ~ThreadLocal();
 };
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -114,49 +114,53 @@ BackgroundParentImpl::DeallocPBackground
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   delete static_cast<TestParent*>(aActor);
   return true;
 }
 
 auto
-BackgroundParentImpl::AllocPBackgroundIDBFactoryParent()
+BackgroundParentImpl::AllocPBackgroundIDBFactoryParent(
+                                                const LoggingInfo& aLoggingInfo)
   -> PBackgroundIDBFactoryParent*
 {
   using mozilla::dom::indexedDB::AllocPBackgroundIDBFactoryParent;
 
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
 
-  return AllocPBackgroundIDBFactoryParent();
+  return AllocPBackgroundIDBFactoryParent(aLoggingInfo);
 }
 
 bool
 BackgroundParentImpl::RecvPBackgroundIDBFactoryConstructor(
-                                            PBackgroundIDBFactoryParent* aActor)
+                                            PBackgroundIDBFactoryParent* aActor,
+                                            const LoggingInfo& aLoggingInfo)
 {
   using mozilla::dom::indexedDB::RecvPBackgroundIDBFactoryConstructor;
 
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
-  return RecvPBackgroundIDBFactoryConstructor(aActor);
+  return RecvPBackgroundIDBFactoryConstructor(aActor, aLoggingInfo);
 }
 
 bool
 BackgroundParentImpl::DeallocPBackgroundIDBFactoryParent(
                                             PBackgroundIDBFactoryParent* aActor)
 {
+  using mozilla::dom::indexedDB::DeallocPBackgroundIDBFactoryParent;
+
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
-  return mozilla::dom::indexedDB::DeallocPBackgroundIDBFactoryParent(aActor);
+  return DeallocPBackgroundIDBFactoryParent(aActor);
 }
 
 auto
 BackgroundParentImpl::AllocPBlobParent(const BlobConstructorParams& aParams)
   -> PBlobParent*
 {
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -28,20 +28,22 @@ protected:
   virtual bool
   RecvPBackgroundTestConstructor(PBackgroundTestParent* aActor,
                                  const nsCString& aTestArg) MOZ_OVERRIDE;
 
   virtual bool
   DeallocPBackgroundTestParent(PBackgroundTestParent* aActor) MOZ_OVERRIDE;
 
   virtual PBackgroundIDBFactoryParent*
-  AllocPBackgroundIDBFactoryParent() MOZ_OVERRIDE;
+  AllocPBackgroundIDBFactoryParent(const LoggingInfo& aLoggingInfo)
+                                   MOZ_OVERRIDE;
 
   virtual bool
-  RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor)
+  RecvPBackgroundIDBFactoryConstructor(PBackgroundIDBFactoryParent* aActor,
+                                       const LoggingInfo& aLoggingInfo)
                                        MOZ_OVERRIDE;
 
   virtual bool
   DeallocPBackgroundIDBFactoryParent(PBackgroundIDBFactoryParent* aActor)
                                      MOZ_OVERRIDE;
 
   virtual PBlobParent*
   AllocPBlobParent(const BlobConstructorParams& aParams) MOZ_OVERRIDE;
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -3,32 +3,33 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PBackgroundIDBFactory;
 include protocol PBackgroundTest;
 include protocol PBlob;
 include protocol PFileDescriptorSet;
 
 include DOMTypes;
+include PBackgroundIDBSharedTypes;
 
 namespace mozilla {
 namespace ipc {
 
 sync protocol PBackground
 {
   manages PBackgroundIDBFactory;
   manages PBackgroundTest;
   manages PBlob;
   manages PFileDescriptorSet;
 
 parent:
   // Only called at startup during mochitests to check the basic infrastructure.
   PBackgroundTest(nsCString testArg);
 
-  PBackgroundIDBFactory();
+  PBackgroundIDBFactory(LoggingInfo loggingInfo);
 
 both:
   PBlob(BlobConstructorParams params);
 
   PFileDescriptorSet(FileDescriptor fd);
 };
 
 } // namespace ipc
--- a/ipc/glue/moz.build
+++ b/ipc/glue/moz.build
@@ -125,16 +125,17 @@ SOURCES += [
     'BackgroundParentImpl.cpp',
     'FileDescriptorSetChild.cpp',
     'FileDescriptorSetParent.cpp',
     'GeckoChildProcessHost.cpp',
     'URIUtils.cpp',
 ]
 
 LOCAL_INCLUDES += [
+    '/dom/indexedDB',
     '/xpcom/build',
 ]
 
 IPDL_SOURCES = [
     'InputStreamParams.ipdlh',
     'PBackground.ipdl',
     'PBackgroundSharedTypes.ipdlh',
     'PBackgroundTest.ipdl',
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -826,16 +826,17 @@ void wasapi_stream_destroy(cubeb_stream 
   }
 
   SafeRelease(stm->shutdown_event);
   SafeRelease(stm->refill_event);
 
   SafeRelease(stm->client);
   SafeRelease(stm->render_client);
   SafeRelease(stm->audio_clock);
+  SafeRelease(stm->audio_stream_volume);
 
   cubeb_resampler_destroy(stm->resampler);
 
   free(stm->mix_buffer);
   free(stm);
 }
 
 int wasapi_stream_start(cubeb_stream * stm)
--- a/mfbt/SegmentedVector.h
+++ b/mfbt/SegmentedVector.h
@@ -27,22 +27,34 @@
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
 #include "mozilla/TypeTraits.h"
 
 #include <new>  // for placement new
 
 namespace mozilla {
 
-// IdealSegmentSize is how big each segment will be in bytes (or as close as is
-// possible). It's best to choose a size that's a power-of-two (to avoid slop)
-// and moderately large (not too small so segment allocations are infrequent,
-// and not too large so that not too much space is wasted when the final
-// segment is not full). Something like 4096 or 8192 is probably good.
-template<typename T, size_t IdealSegmentSize,
+// |IdealSegmentSize| specifies how big each segment will be in bytes (or as
+// close as is possible). Use the following guidelines to choose a size.
+//
+// - It should be a power-of-two, to avoid slop.
+//
+// - It should not be too small, so that segment allocations are infrequent,
+//   and so that per-segment bookkeeping overhead is low. Typically each
+//   segment should be able to hold hundreds of elements, at least.
+//
+// - It should not be too large, so that OOMs are unlikely when allocating
+//   segments, and so that not too much space is wasted when the final segment
+//   is not full.
+//
+// The ideal size depends on how the SegmentedVector is used and the size of
+// |T|, but reasonable sizes include 1024, 4096 (the default), 8192, and 16384.
+//
+template<typename T,
+         size_t IdealSegmentSize = 4096,
          typename AllocPolicy = MallocAllocPolicy>
 class SegmentedVector : private AllocPolicy
 {
   template<size_t SegmentCapacity>
   struct SegmentImpl
     : public mozilla::LinkedListElement<SegmentImpl<SegmentCapacity>>
   {
     SegmentImpl() : mLength(0) {}
--- a/mfbt/tests/TestSegmentedVector.cpp
+++ b/mfbt/tests/TestSegmentedVector.cpp
@@ -142,17 +142,17 @@ void TestSegmentCapacitiesAndAlignments(
   //
   // Also, SegmentedVector has a static assertion that elements are
   // appropriately aligned.
   SegmentedVector<double, 512> v1(512);
   SegmentedVector<A, 1024> v2(1024);
   SegmentedVector<B, 999> v3(999);
   SegmentedVector<C, 10> v4(10);
   SegmentedVector<D, 1234> v5(1234);
-  SegmentedVector<E, 4096> v6(4096);
+  SegmentedVector<E> v6(4096);  // 4096 is the default segment size
   SegmentedVector<mozilla::AlignedElem<16>, 100> v7(100);
 }
 
 int main(void)
 {
   TestBasics();
   TestConstructorsAndDestructors();
   TestSegmentCapacitiesAndAlignments();
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -114,16 +114,22 @@ pref("dom.abortablepromise.enabled", fal
 pref("dom.quotaManager.testing", false);
 
 // Whether or not indexedDB is enabled.
 pref("dom.indexedDB.enabled", true);
 // Space to allow indexedDB databases before prompting (in MB).
 pref("dom.indexedDB.warningQuota", 50);
 // Whether or not indexedDB experimental features are enabled.
 pref("dom.indexedDB.experimental", false);
+// Enable indexedDB logging.
+pref("dom.indexedDB.logging.enabled", true);
+// Detailed output in log messages.
+pref("dom.indexedDB.logging.details", true);
+// Enable profiler marks for indexedDB events.
+pref("dom.indexedDB.logging.profiler-marks", false);
 
 // Whether or not Web Workers are enabled.
 pref("dom.workers.enabled", true);
 // The number of workers per domain allowed to run concurrently.
 pref("dom.workers.maxPerDomain", 20);
 
 // Whether or not Shared Web Workers are enabled.
 pref("dom.workers.sharedWorkers.enabled", true);
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -195,23 +195,27 @@ NS_NewFileURI(nsIURI* *result,
  *  3) Call NS_NewChannelInternal *only* if requesting Principal and
  *     the Node's Principal have to be different.
  *     >> Most likely this is not the case! <<
  *     Needs special approval!
  */
 inline nsresult
 NS_NewChannelInternal(nsIChannel**           outChannel,
                       nsIURI*                aUri,
-                      nsILoadInfo*           aLoadInfo,
+                      nsINode*               aRequestingNode,
+                      nsIPrincipal*          aRequestingPrincipal,
+                      nsIPrincipal*          aTriggeringPrincipal,
+                      nsSecurityFlags        aSecurityFlags,
+                      nsContentPolicyType    aContentPolicyType,
+                      nsIURI*                aBaseURI = nullptr,
                       nsILoadGroup*          aLoadGroup = nullptr,
                       nsIInterfaceRequestor* aCallbacks = nullptr,
                       nsLoadFlags            aLoadFlags = nsIRequest::LOAD_NORMAL,
                       nsIIOService*          aIoService = nullptr)
 {
-  NS_ASSERTION(aLoadInfo, "Can not create channel without aLoadInfo!");
   NS_ENSURE_ARG_POINTER(outChannel);
 
   nsCOMPtr<nsIIOService> grip;
   nsresult rv = net_EnsureIOService(&aIoService, grip);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIChannel> channel;
   rv = aIoService->NewChannelFromURI(aUri, getter_AddRefs(channel));
@@ -229,56 +233,72 @@ NS_NewChannelInternal(nsIChannel**      
 
   if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
     // Retain the LOAD_REPLACE load flag if set.
     nsLoadFlags normalLoadFlags = 0;
     channel->GetLoadFlags(&normalLoadFlags);
     rv = channel->SetLoadFlags(aLoadFlags | (normalLoadFlags & nsIChannel::LOAD_REPLACE));
     NS_ENSURE_SUCCESS(rv, rv);
   }
-  channel->SetLoadInfo(aLoadInfo);
+
+  // Some channels might already have a loadInfo attached at this
+  // point (see bug 1104623). We have to make sure to update
+  // security flags in such cases before we set the loadinfo.
+  // Once bug 1087442 lands, this problem disappears because we
+  // attach the loadinfo in each individual protocol handler.
+  nsCOMPtr<nsILoadInfo> loadInfo;
+  channel->GetLoadInfo(getter_AddRefs(loadInfo));
+  if (loadInfo) {
+    aSecurityFlags |= loadInfo->GetSecurityFlags();
+  }
+
+  // create a new Loadinfo with the potentially updated securityFlags
+  loadInfo =
+    new mozilla::LoadInfo(aRequestingPrincipal, aTriggeringPrincipal,
+                          aRequestingNode, aSecurityFlags,
+                          aContentPolicyType, aBaseURI);
+  if (!loadInfo) {
+    return NS_ERROR_UNEXPECTED;
+  }
+  channel->SetLoadInfo(loadInfo);
 
   // If we're sandboxed, make sure to clear any owner the channel
   // might already have.
-  if (aLoadInfo->GetLoadingSandboxed()) {
+  if (loadInfo->GetLoadingSandboxed()) {
     channel->SetOwner(nullptr);
   }
 
   channel.forget(outChannel);
   return NS_OK;
 }
 
 inline nsresult
 NS_NewChannelInternal(nsIChannel**           outChannel,
                       nsIURI*                aUri,
-                      nsINode*               aRequestingNode,
-                      nsIPrincipal*          aRequestingPrincipal,
-                      nsIPrincipal*          aTriggeringPrincipal,
-                      nsSecurityFlags        aSecurityFlags,
-                      nsContentPolicyType    aContentPolicyType,
+                      nsILoadInfo*           aLoadInfo,
                       nsILoadGroup*          aLoadGroup = nullptr,
                       nsIInterfaceRequestor* aCallbacks = nullptr,
                       nsLoadFlags            aLoadFlags = nsIRequest::LOAD_NORMAL,
                       nsIIOService*          aIoService = nullptr)
 {
-  NS_ASSERTION(aRequestingPrincipal, "Can not create channel without a requesting Principal!");
-
-  nsCOMPtr<nsILoadInfo> loadInfo =
-    new mozilla::LoadInfo(aRequestingPrincipal, aTriggeringPrincipal,
-                          aRequestingNode, aSecurityFlags, aContentPolicyType);
-  if (!loadInfo) {
-    return NS_ERROR_UNEXPECTED;
-  }
-  return NS_NewChannelInternal(outChannel,
-                               aUri,
-                               loadInfo,
-                               aLoadGroup,
-                               aCallbacks,
-                               aLoadFlags,
-                               aIoService);
+  MOZ_ASSERT(aLoadInfo, "Can not create a channel without a loadInfo");
+  nsresult rv = NS_NewChannelInternal(outChannel,
+                                      aUri,
+                                      aLoadInfo->LoadingNode(),
+                                      aLoadInfo->LoadingPrincipal(),
+                                      aLoadInfo->TriggeringPrincipal(),
+                                      aLoadInfo->GetSecurityFlags(),
+                                      aLoadInfo->GetContentPolicyType(),
+                                      aLoadInfo->BaseURI(),
+                                      aLoadGroup,
+                                      aCallbacks,
+                                      aLoadFlags,
+                                      aIoService);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return NS_OK;
 }
 
 inline nsresult /*NS_NewChannelWithNodeAndTriggeringPrincipal */
 NS_NewChannelWithTriggeringPrincipal(nsIChannel**           outChannel,
                                      nsIURI*                aUri,
                                      nsINode*               aRequestingNode,
                                      nsIPrincipal*          aTriggeringPrincipal,
                                      nsSecurityFlags        aSecurityFlags,
@@ -292,16 +312,17 @@ NS_NewChannelWithTriggeringPrincipal(nsI
   NS_ASSERTION(aTriggeringPrincipal, "Can not create channel without a triggering Principal!");
   return NS_NewChannelInternal(outChannel,
                                aUri,
                                aRequestingNode,
                                aRequestingNode->NodePrincipal(),
                                aTriggeringPrincipal,
                                aSecurityFlags,
                                aContentPolicyType,
+                               nullptr, // aBaseURI
                                aLoadGroup,
                                aCallbacks,
                                aLoadFlags,
                                aIoService);
 }
 
 inline nsresult /*NS_NewChannelWithPrincipalAndTriggeringPrincipal */
 NS_NewChannelWithTriggeringPrincipal(nsIChannel**           outChannel,
@@ -318,16 +339,17 @@ NS_NewChannelWithTriggeringPrincipal(nsI
   NS_ASSERTION(aRequestingPrincipal, "Can not create channel without a requesting Principal!");
   return NS_NewChannelInternal(outChannel,
                                aUri,
                                nullptr, // aRequestingNode
                                aRequestingPrincipal,
                                aTriggeringPrincipal,
                                aSecurityFlags,
                                aContentPolicyType,
+                               nullptr, // aBaseURI
                                aLoadGroup,
                                aCallbacks,
                                aLoadFlags,
                                aIoService);
 }
 
 inline nsresult /* NS_NewChannelNode */
 NS_NewChannel(nsIChannel**           outChannel,
@@ -343,16 +365,17 @@ NS_NewChannel(nsIChannel**           out
   NS_ASSERTION(aRequestingNode, "Can not create channel without a requesting Node!");
   return NS_NewChannelInternal(outChannel,
                                aUri,
                                aRequestingNode,
                                aRequestingNode->NodePrincipal(),
                                nullptr, // aTriggeringPrincipal
                                aSecurityFlags,
                                aContentPolicyType,
+                               nullptr, // aBaseURI
                                aLoadGroup,
                                aCallbacks,
                                aLoadFlags,
                                aIoService);
 }
 
 inline nsresult /* NS_NewChannelPrincipal */
 NS_NewChannel(nsIChannel**           outChannel,
@@ -367,16 +390,17 @@ NS_NewChannel(nsIChannel**           out
 {
   return NS_NewChannelInternal(outChannel,
                                aUri,
                                nullptr, // aRequestingNode,
                                aRequestingPrincipal,
                                nullptr, // aTriggeringPrincipal
                                aSecurityFlags,
                                aContentPolicyType,
+                               nullptr, // aBaseURI
                                aLoadGroup,
                                aCallbacks,
                                aLoadFlags,
                                aIoService);
 }
 
 // Use this function with CAUTION. It creates a stream that blocks when you
 // Read() from it and blocking the UI thread is a bad idea. If you don't want
@@ -401,16 +425,17 @@ NS_OpenURIInternal(nsIInputStream**     
   nsCOMPtr<nsIChannel> channel;
   nsresult rv = NS_NewChannelInternal(getter_AddRefs(channel),
                                       aUri,
                                       aRequestingNode,
                                       aRequestingPrincipal,
                                       aTriggeringPrincipal,
                                       aSecurityFlags,
                                       aContentPolicyType,
+                                      nullptr, // aBaseURI
                                       aLoadGroup,
                                       aCallbacks,
                                       aLoadFlags,
                                       aIoService);
 
   NS_ENSURE_SUCCESS(rv, rv);
   nsIInputStream *stream;
   rv = channel->Open(&stream);
@@ -957,16 +982,17 @@ NS_NewStreamLoaderInternal(nsIStreamLoad
    nsCOMPtr<nsIChannel> channel;
    nsresult rv = NS_NewChannelInternal(getter_AddRefs(channel),
                                        aUri,
                                        aRequestingNode,
                                        aRequestingPrincipal,
                                        nullptr, // aTriggeringPrincipal
                                        aSecurityFlags,
                                        aContentPolicyType,
+                                       nullptr, // aBaseURI
                                        aLoadGroup,
                                        aCallbacks,
                                        aLoadFlags);
 
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   if (httpChannel) {
     httpChannel->SetReferrer(aReferrer);