Merge f-t to m-c
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 31 May 2014 20:31:07 -0700
changeset 205241 d6fccb7c56a88d7601782ead5e076df17839b25c
parent 205223 0e10c81516548fae723c468d91c1973907207e29 (current diff)
parent 205240 9482bb487aa5bfbc7f73ab69f2b7630728b641dd (diff)
child 205245 84c32536a4a57c1f1cb37cf75316c3199d8ce922
child 205265 63c454501a6cb41b3137bd7901dbf8a6a7b3e6c7
child 205299 642d5cafb96bf0025d80d8eb07600c25ec8ac10a
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone32.0a1
first release with
nightly linux32
d6fccb7c56a8 / 32.0a1 / 20140601030204 / files
nightly linux64
d6fccb7c56a8 / 32.0a1 / 20140601030204 / files
nightly mac
d6fccb7c56a8 / 32.0a1 / 20140601030204 / files
nightly win32
d6fccb7c56a8 / 32.0a1 / 20140601030204 / files
nightly win64
d6fccb7c56a8 / 32.0a1 / 20140601030204 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge f-t to m-c
browser/themes/shared/devtools/images/debugger-blackBoxMessageEye.png
browser/themes/shared/devtools/images/debugger-blackbox-eye.png
dom/base/nsDOMWindowUtils.cpp
gfx/layers/opengl/CompositorOGL.cpp
gfx/thebes/gfxFont.cpp
js/public/ProfilingStack.h
layout/base/nsCSSRendering.cpp
widget/cocoa/nsChildView.mm
new file mode 100644
--- /dev/null
+++ b/b2g/dev/app/moz.build
@@ -0,0 +1,3 @@
+# 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/.
--- a/browser/components/preferences/in-content/main.xul
+++ b/browser/components/preferences/in-content/main.xul
@@ -84,23 +84,26 @@
     <preference id="browser.taskbar.previews.enable"
                 name="browser.taskbar.previews.enable"
                 type="bool"/>
 #endif
 </preferences>
 
 <hbox id="header-general"
       class="header"
+      hidden="true"
       data-category="paneGeneral">
   <image class="header-icon"/>
   <label class="header-name">&paneGeneral.title;</label>
 </hbox>
 
 <!-- Startup -->
-<groupbox id="startupGroup" data-category="paneGeneral">
+<groupbox id="startupGroup"
+          data-category="paneGeneral"
+          hidden="true">
   <caption><label>&startup.label;</label></caption>
 
   <hbox align="center">
     <label accesskey="&startupPage.accesskey;"
            control="browserStartupPage">&startupPage.label;</label>
     <menulist id="browserStartupPage"
               preference="browser.startup.page">
       <menupopup>
@@ -147,17 +150,19 @@
             accesskey="&restoreDefault.accesskey;"
             oncommand="gMainPane.restoreDefaultHomePage();"
             id="restoreDefaultHomePage"
             preference="pref.browser.homepage.disable_button.restore_default"/>
   </hbox>
 </groupbox>
 
 <!-- Downloads -->
-<groupbox id="downloadsGroup" data-category="paneGeneral">
+<groupbox id="downloadsGroup"
+          data-category="paneGeneral"
+          hidden="true">
   <caption><label>&downloads.label;</label></caption>
 
   <radiogroup id="saveWhere"
               preference="browser.download.useDownloadDir"
               onsyncfrompreference="return gMainPane.readUseDownloadDir();">
     <hbox id="saveToRow">
       <radio id="saveTo"
              value="true"
@@ -186,17 +191,18 @@
     <radio id="alwaysAsk"
            value="false"
            label="&alwaysAsk.label;"
            accesskey="&alwaysAsk.accesskey;"/>
   </radiogroup>
 </groupbox>
 
 <!-- Tab preferences -->
-<groupbox data-category="paneGeneral">
+<groupbox data-category="paneGeneral"
+          hidden="true">
     <caption><label>&tabsGroup.label;</label></caption>
     <checkbox id="linkTargeting" label="&newWindowsAsTabs.label;"
               accesskey="&newWindowsAsTabs.accesskey;"
               preference="browser.link.open_newwindow"
               onsyncfrompreference="return gMainPane.readLinkTarget();"
               onsynctopreference="return gMainPane.writeLinkTarget();"/>
 
     <checkbox id="warnCloseMultiple" label="&warnCloseMultipleTabs.label;"
--- a/browser/components/preferences/in-content/preferences.js
+++ b/browser/components/preferences/in-content/preferences.js
@@ -27,16 +27,18 @@ function init_all() {
   gSyncPane.init();
   gSecurityPane.init();
   var initFinished = document.createEvent("Event");
   initFinished.initEvent("Initialized", true, true);
   document.dispatchEvent(initFinished);
 
   let categories = document.getElementById("categories");
   categories.addEventListener("select", event => gotoPref(event.target.value));
+
+  gotoPref("paneGeneral");
 }
 
 function selectCategory(name) {
   let categories = document.getElementById("categories");
   let item = categories.querySelector(".category[value=" + name + "]");
   categories.selectedItem = item;
   gotoPref(name);
 }
--- a/browser/components/translation/translation-infobar.xml
+++ b/browser/components/translation/translation-infobar.xml
@@ -16,69 +16,85 @@
           xmlns:xbl="http://www.mozilla.org/xbl">
   <binding id="translationbar" extends="chrome://global/content/bindings/notification.xml#notification" role="xul:alert">
     <resources>
       <stylesheet src="chrome://global/skin/notification.css"/>
     </resources>
     <content>
       <xul:hbox class="notification-inner outset" flex="1" xbl:inherits="type">
         <xul:hbox anonid="details" align="center" flex="1">
-          <xul:image anonid="messageImage" class="messageImage"/>
+          <xul:image class="translate-infobar-element messageImage"
+                     anonid="messageImage"/>
           <xul:deck anonid="translationStates" selectedIndex="0">
 
             <!-- offer to translate -->
             <xul:hbox class="translate-offer-box" align="center">
-              <xul:label value="&translation.thisPageIsIn.label;"/>
-              <xul:menulist anonid="detectedLanguage">
+              <xul:label class="translate-infobar-element" value="&translation.thisPageIsIn.label;"/>
+              <xul:menulist class="translate-infobar-element" anonid="detectedLanguage">
                 <xul:menupopup/>
               </xul:menulist>
-              <xul:label value="&translation.translateThisPage.label;"/>
-              <xul:button label="&translation.translate.button;" anonid="translate"
+              <xul:label class="translate-infobar-element" value="&translation.translateThisPage.label;"/>
+              <xul:button class="translate-infobar-element"
+                          label="&translation.translate.button;"
+                          anonid="translate"
                           oncommand="document.getBindingParent(this).translate();"/>
-              <xul:button label="&translation.notNow.button;" anonid="notNow"
+              <xul:button class="translate-infobar-element"
+                          label="&translation.notNow.button;" anonid="notNow"
                           oncommand="document.getBindingParent(this).close();"/>
             </xul:hbox>
 
             <!-- translating -->
-            <xul:vbox class="translating-box" pack="center">
-              <xul:label value="&translation.translatingContent.label;"/>
-            </xul:vbox>
+            <xul:hbox class="translating-box" pack="center">
+              <xul:label class="translate-infobar-element"
+                         value="&translation.translatingContent.label;"/>
+            </xul:hbox>
 
             <!-- translated -->
             <xul:hbox class="translated-box" align="center">
-              <xul:label value="&translation.translatedFrom.label;"/>
-              <xul:menulist anonid="fromLanguage"
+              <xul:label class="translate-infobar-element"
+                         value="&translation.translatedFrom.label;"/>
+              <xul:menulist class="translate-infobar-element"
+                            anonid="fromLanguage"
                             oncommand="document.getBindingParent(this).translate()">
                 <xul:menupopup/>
               </xul:menulist>
-              <xul:label value="&translation.translatedTo.label;"/>
+              <xul:label class="translate-infobar-element"
+                         value="&translation.translatedTo.label;"/>
               <xul:menulist anonid="toLanguage"
                             oncommand="document.getBindingParent(this).translate()">
                 <xul:menupopup/>
               </xul:menulist>
               <xul:label value="&translation.translatedToSuffix.label;"/>
               <xul:button anonid="showOriginal"
+                          class="translate-infobar-element"
                           label="&translation.showOriginal.button;"
                           oncommand="document.getBindingParent(this).showOriginal();"/>
               <xul:button anonid="showTranslation"
+                          class="translate-infobar-element"
                           label="&translation.showTranslation.button;"
                           oncommand="document.getBindingParent(this).showTranslation();"/>
             </xul:hbox>
 
             <!-- error -->
             <xul:hbox class="translation-error" align="center">
-              <xul:label value="&translation.errorTranslating.label;"/>
-              <xul:button label="&translation.tryAgain.button;" anonid="tryAgain"
+              <xul:label class="translate-infobar-element"
+                         value="&translation.errorTranslating.label;"/>
+              <xul:button class="translate-infobar-element"
+                          label="&translation.tryAgain.button;"
+                          anonid="tryAgain"
                           oncommand="document.getBindingParent(this).translate();"/>
             </xul:hbox>
 
           </xul:deck>
           <xul:spacer flex="1"/>
 
-          <xul:button type="menu" anonid="options" label="&translation.options.menu;">
+          <xul:button type="menu"
+                      class="translate-infobar-element options-menu-button"
+                      anonid="options"
+                      label="&translation.options.menu;">
             <xul:menupopup onpopupshowing="document.getBindingParent(this).optionsShowing();">
               <xul:menuitem anonid="neverForLanguage"
                             oncommand="document.getBindingParent(this).neverForLanguage();"/>
               <xul:menuitem anonid="neverForSite"
                             oncommand="document.getBindingParent(this).neverForSite();"
                             label="&translation.options.neverForSite.label;"
                             accesskey="&translation.options.neverForSite.accesskey;"/>
               <xul:menuseparator/>
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -407,17 +407,16 @@
               align="center"
               pack="center">
           <description id="black-boxed-message-label">
             &debuggerUI.blackBoxMessage.label;
           </description>
           <button id="black-boxed-message-button"
                   class="devtools-toolbarbutton"
                   label="&debuggerUI.blackBoxMessage.unBlackBoxButton;"
-                  image="chrome://browser/skin/devtools/debugger-blackbox-eye.png"
                   command="unBlackBoxCommand"/>
         </vbox>
         <vbox id="source-progress-container"
               align="center"
               pack="center">
           <progressmeter id="source-progress"
                          mode="undetermined"/>
         </vbox>
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -47,16 +47,19 @@
 }
 
 #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):not(#nav-bar) {
   padding-top: 1px;
   padding-bottom: 1px;
 }
 
 #TabsToolbar:not([collapsed="true"]) + #nav-bar {
+  border-top: 1px solid hsla(0,0%,0%,.3) !important;
+  background-clip: padding-box;
+  margin-top: -1px; /* Move up into the TabsToolbar for the inner highlight at the top of the nav-bar */
   /* Position the toolbar above the bottom of background tabs */
   position: relative;
   z-index: 1;
 }
 
 #nav-bar {
   background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
   box-shadow: 0 1px 0 @toolbarHighlight@ inset;
@@ -1368,36 +1371,53 @@ toolbarbutton[sdk-button="true"][cui-are
 #pointerLock-cancel {
   margin: 0px;
 }
 
 /* Translation infobar */
 
 %include ../shared/translation/infobar.inc.css
 
+notification[value="translation"] {
+  min-height: 40px;
+}
+
 notification[value="translation"],
 notification[value="translation"] button,
 notification[value="translation"] menulist {
+  min-height: 30px;
   color: #5A5959;
 }
 
 notification[value="translation"] {
   background-color: #F2F1F0;
 }
 
+notification[value="translation"] button,
+notification[value="translation"] menulist {
+  -moz-padding-end: 1ch;
+}
+
 notification[value="translation"] menulist {
   border: 1px solid #C1C1C1;
   background-color: #FFF;
 }
 
 notification[value="translation"] button {
   border: 1px solid #C1C1C1;
   background-color: #F2F1F0;
 }
 
+notification[value="translation"] button,
+notification[value="translation"] menulist,
+notification[value="translation"] menulist > .menulist-label-box {
+  -moz-margin-start: 1ch;
+  -moz-margin-end: 1ch;
+}
+
 notification[value="translation"] button:hover,
 notification[value="translation"] button:active,
 notification[value="translation"] menulist:hover,
 notification[value="translation"] menulist:active {
   background-color: #E2E1E0;
 }
 
 notification[value="translation"] button[anonid="translate"] {
@@ -1407,16 +1427,26 @@ notification[value="translation"] button
   border: 1px solid #829C1C;
 }
 
 notification[value="translation"] button[anonid="translate"]:hover,
 notification[value="translation"] button[anonid="translate"]:active {
   background-image: linear-gradient(#8DA726, #8DA726);
 }
 
+notification[value="translation"] button > .button-box,
+notification[value="translation"] button[type="menu"] > .button-box > .button-menu-dropmarker {
+  padding: 0;
+  -moz-margin-start: 3ch;
+}
+
+notification[value="translation"] button:not([type="menu"]) > .button-box {
+  -moz-margin-end: 3ch;
+}
+
 notification[value="translation"] menulist > .menulist-dropmarker {
   display: block;
 }
 
 .translate-notification-icon,
 #translate-notification-icon {
   list-style-image: url(chrome://browser/skin/translation-16.png);
   -moz-image-region: rect(0px, 16px, 16px, 0px);
@@ -1716,33 +1746,19 @@ richlistitem[type~="action"][actiontype=
 #tabbrowser-tabs {
   /* override the global style to allow the selected tab to be above the nav-bar */
   z-index: auto;
 }
 
 #TabsToolbar {
   min-height: 0;
   padding: 0;
-  position: relative;
   margin-bottom: -@tabToolbarNavbarOverlap@;
 }
 
-/*
- * Draw the bottom border of the tabstrip:
- */
-#TabsToolbar::after {
-  content: "";
-  position: absolute;
-  bottom: @tabToolbarNavbarOverlap@;
-  left: 0;
-  right: 0;
-  z-index: 0;
-  border-bottom: 1px solid hsla(0,0%,0%,.3);
-}
-
 #TabsToolbar:not(:-moz-lwtheme) {
   -moz-appearance: menubar;
   color: -moz-menubartext;
 }
 
 #toolbar-menubar:not([autohide="true"]):not(:-moz-lwtheme):-moz-system-metric(menubar-drag),
 #TabsToolbar:not(:-moz-lwtheme):-moz-system-metric(menubar-drag) {
   -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-drag");
--- a/browser/themes/linux/jar.mn
+++ b/browser/themes/linux/jar.mn
@@ -238,17 +238,18 @@ browser.jar:
 * skin/classic/browser/devtools/shadereditor.css      (devtools/shadereditor.css)
 * skin/classic/browser/devtools/splitview.css         (../shared/devtools/splitview.css)
   skin/classic/browser/devtools/styleeditor.css       (../shared/devtools/styleeditor.css)
 * skin/classic/browser/devtools/webaudioeditor.css    (devtools/webaudioeditor.css)
   skin/classic/browser/devtools/magnifying-glass.png        (../shared/devtools/images/magnifying-glass.png)
   skin/classic/browser/devtools/magnifying-glass@2x.png     (../shared/devtools/images/magnifying-glass@2x.png)
   skin/classic/browser/devtools/magnifying-glass-light.png  (../shared/devtools/images/magnifying-glass-light.png)
   skin/classic/browser/devtools/magnifying-glass-light@2x.png (../shared/devtools/images/magnifying-glass-light@2x.png)
-  skin/classic/browser/devtools/itemToggle.png        (../shared/devtools/images/itemToggle.png)
+  skin/classic/browser/devtools/itemToggle.png         (../shared/devtools/images/itemToggle.png)
+  skin/classic/browser/devtools/itemToggle@2x.png      (../shared/devtools/images/itemToggle@2x.png)
   skin/classic/browser/devtools/itemArrow-dark-rtl.svg (../shared/devtools/images/itemArrow-dark-rtl.svg)
   skin/classic/browser/devtools/itemArrow-dark-ltr.svg (../shared/devtools/images/itemArrow-dark-ltr.svg)
   skin/classic/browser/devtools/itemArrow-rtl.svg      (../shared/devtools/images/itemArrow-rtl.svg)
   skin/classic/browser/devtools/itemArrow-ltr.svg      (../shared/devtools/images/itemArrow-ltr.svg)
   skin/classic/browser/devtools/noise.png             (../shared/devtools/images/noise.png)
   skin/classic/browser/devtools/dropmarker.png        (../shared/devtools/images/dropmarker.png)
   skin/classic/browser/devtools/layoutview.css         (../shared/devtools/layoutview.css)
   skin/classic/browser/devtools/debugger-collapse.png  (../shared/devtools/images/debugger-collapse.png)
@@ -260,17 +261,16 @@ browser.jar:
   skin/classic/browser/devtools/debugger-play.png      (../shared/devtools/images/debugger-play.png)
   skin/classic/browser/devtools/debugger-play@2x.png      (../shared/devtools/images/debugger-play@2x.png)
   skin/classic/browser/devtools/debugger-step-in.png   (../shared/devtools/images/debugger-step-in.png)
   skin/classic/browser/devtools/debugger-step-in@2x.png   (../shared/devtools/images/debugger-step-in@2x.png)
   skin/classic/browser/devtools/debugger-step-out.png  (../shared/devtools/images/debugger-step-out.png)
   skin/classic/browser/devtools/debugger-step-out@2x.png  (../shared/devtools/images/debugger-step-out@2x.png)
   skin/classic/browser/devtools/debugger-step-over.png (../shared/devtools/images/debugger-step-over.png)
   skin/classic/browser/devtools/debugger-step-over@2x.png (../shared/devtools/images/debugger-step-over@2x.png)
-  skin/classic/browser/devtools/debugger-blackbox-eye.png  (../shared/devtools/images/debugger-blackbox-eye.png)
   skin/classic/browser/devtools/debugger-blackbox.png  (../shared/devtools/images/debugger-blackbox.png)
   skin/classic/browser/devtools/debugger-blackbox@2x.png  (../shared/devtools/images/debugger-blackbox@2x.png)
   skin/classic/browser/devtools/debugger-toggleBreakpoints.png (../shared/devtools/images/debugger-toggleBreakpoints.png)
   skin/classic/browser/devtools/debugger-toggleBreakpoints@2x.png (../shared/devtools/images/debugger-toggleBreakpoints@2x.png)
   skin/classic/browser/devtools/tracer-icon.png        (../shared/devtools/images/tracer-icon.png)
   skin/classic/browser/devtools/tracer-icon@2x.png     (../shared/devtools/images/tracer-icon@2x.png)
   skin/classic/browser/devtools/responsive-se-resizer.png (../shared/devtools/images/responsive-se-resizer.png)
   skin/classic/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsive-vertical-resizer.png)
index 63f77f1b760b2e66e2fab7e739979b7cdede2116..0b3c4e4b5f6957c906c13ca2e73d11c523649441
GIT binary patch
literal 143
zc%17D@N?(olHy`uVBq!ia0vp^%s?#1!3HE>CM@{{q{2L1978G?lam~nR?P8#KhMys
z^W!FlOf|I?I?@8hhb-PW^e7!}32kHUm^ssdMWDDTRY0bNN8FKbnOxo)88MA^*42!6
rB;16<j(N^0wlLV!dnWOaY#u|%fA;?F%Pkv#HZXX)`njxgN@xNA95O8C
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -3611,16 +3611,18 @@ toolbarbutton.chevron > .toolbarbutton-m
 }
 @media (min-resolution: 2dppx) {
   .pointerLock-notification-icon,
   #pointerLock-notification-icon {
     list-style-image: url(chrome://browser/skin/pointerLock-16@2x.png);
   }
 }
 
+/* Translation */
+
 .translate-notification-icon,
 #translate-notification-icon {
   list-style-image: url(chrome://browser/skin/translation-16.png);
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 @media (min-resolution: 2dppx) {
   .translate-notification-icon,
   #translate-notification-icon {
@@ -3637,16 +3639,133 @@ toolbarbutton.chevron > .toolbarbutton-m
 @media (min-resolution: 2dppx) {
   .translated-notification-icon,
   #translated-notification-icon {
     list-style-image: url(chrome://browser/skin/translation-16@2x.png);
     -moz-image-region: rect(0px, 64px, 32px, 32px);
   }
 }
 
+%include ../shared/translation/infobar.inc.css
+
+notification[value="translation"] {
+  color: #484848;
+  background-color: #EFEFEF;
+  background-image: none;
+  border-top: none;
+  border-bottom: 1px solid #c4c4c4;
+  padding-top: 1px;
+  padding-bottom: 1px;
+}
+
+.translate-infobar-element {
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+}
+
+button.translate-infobar-element {
+  background: linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.1)) repeat scroll 0% 0% padding-box transparent;
+  color: #333333;
+  border: 1px solid;
+  border-color: rgba(23, 51, 78, 0.15) rgba(23, 51, 78, 0.17) rgba(23, 51, 78, 0.2);
+  box-shadow: 0px 0px 2px rgba(255, 255, 255, 0.5) inset, 0px 1px 0px rgba(255, 255, 255, 0.2);
+  transition-property: background-color, border-color, box-shadow;
+  transition-duration: 150ms;
+  min-height: 22px;
+  min-width: 0;
+  padding: 0 0.8em !important;
+  margin-left: 0.25em;
+  margin-right: 0.25em;
+}
+
+button.translate-infobar-element .button-text {
+  margin-left: 0 !important;
+  margin-right: 0 !important;
+}
+
+label.translate-infobar-element {
+  padding-top: 2px;
+}
+
+button.translate-infobar-element:hover {
+  background: #f0f0f0;
+  box-shadow: 0 1px 0 hsla(0,0%,100%,.1) inset,  0 0 0 1px hsla(0,0%,100%,.05) inset,  0 1px 0 hsla(210,54%,20%,.01),  0 0 4px hsla(206,100%,20%,.1);
+}
+
+button.translate-infobar-element:active {
+  box-shadow: 0 1px 1px hsla(211,79%,6%,.1) inset,  0 0 1px hsla(211,79%,6%,.2) inset;
+  transition-duration: 0ms;
+}
+
+button.translate-infobar-element[anonid="translate"] {
+  color: #ffffff;
+  background-image: linear-gradient(#4cb1ff, #1793e5);
+  box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,  0 0 0 1px hsla(0,0%,100%,.1) inset,  0 1px 0 hsla(210,54%,20%,.03);
+  border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
+  padding: 0 1.1em  !important;;
+}
+
+button.translate-infobar-element[anonid="translate"]:hover {
+  background-image: linear-gradient(#66bdff, #0d9eff);
+}
+
+button.translate-infobar-element.options-menu-button {
+  -moz-padding-start: 0.5em !important;
+  -moz-padding-end: 0.3em !important;
+}
+
+button.translate-infobar-element.options-menu-button > .button-box > .button-menu-dropmarker {
+  display: -moz-box;
+  list-style-image: url("chrome://browser/skin/toolbarbutton-dropmarker.png");
+  padding: 0 !important;
+  margin: 0 !important;
+}
+
+@media (min-resolution: 1.25dppx) {
+  button.translate-infobar-element.options-menu-button > .button-box > .button-menu-dropmarker {
+    list-style-image: url("chrome://browser/skin/toolbarbutton-dropmarker@2x.png");
+  }
+
+  button.translate-infobar-element.options-menu-button > .button-box > .button-menu-dropmarker > .dropmarker-icon {
+    width: 7px;
+  }
+}
+
+menulist.translate-infobar-element {
+  text-shadow: 0 1px 1px #FEFFFE;
+  border: 1px solid;
+  border-color: rgba(23, 51, 78, 0.15) rgba(23, 51, 78, 0.17) rgba(23, 51, 78, 0.2);
+  box-shadow: 0 1px 1px 0 #FFFFFF, inset 0 2px 2px 0 #FFFFFF;
+  background-color: #F1F1F1;
+  background-image: linear-gradient(#FFFFFF, rgba(255,255,255,0.1));
+  color: #333333;
+  padding: 0;
+}
+
+menulist.translate-infobar-element > .menulist-label-box {
+  padding-top: 1px;
+  -moz-padding-start: 0.3em;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+menulist.translate-infobar-element:hover {
+  background-image: linear-gradient(#FFFFFF, rgba(255,255,255,0.6));
+}
+
+menulist.translate-infobar-element[open="true"] {
+  background-image: linear-gradient(rgba(255,255,255,0.1),
+                                    rgba(255,255,255,0.6));
+}
+
+menulist.translate-infobar-element > .menulist-dropmarker {
+  display: -moz-box;
+  list-style-image: url("chrome://global/skin/icons/menulist-dropmarker.png");
+}
+
 
 .popup-notification-icon {
   width: 64px;
   height: 64px;
   -moz-margin-end: 10px;
 }
 
 .popup-notification-icon[popupid="geolocation"] {
--- a/browser/themes/osx/devtools/commandline.css
+++ b/browser/themes/osx/devtools/commandline.css
@@ -7,18 +7,17 @@
   font: message-box;
   color: hsl(210,30%,85%);
 }
 
 #gcli-output-root,
 #gcli-tooltip-root {
   border: 1px solid hsl(206,37%,4%);
   box-shadow: 0 1px 0 hsla(209,29%,72%,.25) inset;
-  background-image: url(background-noise-toolbar.png),
-                    linear-gradient(hsla(209,18%,18%,0.9), hsl(209,23%,18%));
+  background-image: linear-gradient(hsla(209,18%,18%,0.9), hsl(209,23%,18%));
   border-radius: 3px;
 }
 
 #gcli-output-root {
   padding: 5px 10px;
   border-bottom-left-radius: 0;
   border-bottom-right-radius: 0;
   border-bottom: 0;
@@ -31,17 +30,16 @@
 #gcli-tooltip-connector {
   margin-top: -1px;
   margin-left: 8px;
   width: 20px;
   height: 10px;
   border-left: 1px solid hsl(206,37%,4%);
   border-right: 1px solid hsl(206,37%,4%);
   background-color: hsl(209,23%,18%);
-  background-image: url(background-noise-toolbar.png);
 }
 
 .gcli-tt-description,
 .gcli-tt-error {
   padding: 0 10px;
 }
 
 .gcli-row-out {
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -357,16 +357,17 @@ browser.jar:
 * skin/classic/browser/devtools/splitview.css               (../shared/devtools/splitview.css)
   skin/classic/browser/devtools/styleeditor.css             (../shared/devtools/styleeditor.css)
 * skin/classic/browser/devtools/webaudioeditor.css          (devtools/webaudioeditor.css)
   skin/classic/browser/devtools/magnifying-glass.png        (../shared/devtools/images/magnifying-glass.png)
   skin/classic/browser/devtools/magnifying-glass@2x.png     (../shared/devtools/images/magnifying-glass@2x.png)
   skin/classic/browser/devtools/magnifying-glass-light.png  (../shared/devtools/images/magnifying-glass-light.png)
   skin/classic/browser/devtools/magnifying-glass-light@2x.png (../shared/devtools/images/magnifying-glass-light@2x.png)
   skin/classic/browser/devtools/itemToggle.png              (../shared/devtools/images/itemToggle.png)
+  skin/classic/browser/devtools/itemToggle@2x.png           (../shared/devtools/images/itemToggle@2x.png)
   skin/classic/browser/devtools/itemArrow-dark-rtl.svg      (../shared/devtools/images/itemArrow-dark-rtl.svg)
   skin/classic/browser/devtools/itemArrow-dark-ltr.svg      (../shared/devtools/images/itemArrow-dark-ltr.svg)
   skin/classic/browser/devtools/itemArrow-rtl.svg           (../shared/devtools/images/itemArrow-rtl.svg)
   skin/classic/browser/devtools/itemArrow-ltr.svg           (../shared/devtools/images/itemArrow-ltr.svg)
   skin/classic/browser/devtools/noise.png                   (../shared/devtools/images/noise.png)
   skin/classic/browser/devtools/dropmarker.png              (../shared/devtools/images/dropmarker.png)
   skin/classic/browser/devtools/layoutview.css              (../shared/devtools/layoutview.css)
   skin/classic/browser/devtools/debugger-collapse.png       (../shared/devtools/images/debugger-collapse.png)
@@ -378,17 +379,16 @@ browser.jar:
   skin/classic/browser/devtools/debugger-play.png           (../shared/devtools/images/debugger-play.png)
   skin/classic/browser/devtools/debugger-play@2x.png        (../shared/devtools/images/debugger-play@2x.png)
   skin/classic/browser/devtools/debugger-step-in.png        (../shared/devtools/images/debugger-step-in.png)
   skin/classic/browser/devtools/debugger-step-in@2x.png     (../shared/devtools/images/debugger-step-in@2x.png)
   skin/classic/browser/devtools/debugger-step-out.png       (../shared/devtools/images/debugger-step-out.png)
   skin/classic/browser/devtools/debugger-step-out@2x.png    (../shared/devtools/images/debugger-step-out@2x.png)
   skin/classic/browser/devtools/debugger-step-over.png      (../shared/devtools/images/debugger-step-over.png)
   skin/classic/browser/devtools/debugger-step-over@2x.png   (../shared/devtools/images/debugger-step-over@2x.png)
-  skin/classic/browser/devtools/debugger-blackbox-eye.png   (../shared/devtools/images/debugger-blackbox-eye.png)
   skin/classic/browser/devtools/debugger-blackbox.png       (../shared/devtools/images/debugger-blackbox.png)
   skin/classic/browser/devtools/debugger-blackbox@2x.png    (../shared/devtools/images/debugger-blackbox@2x.png)
   skin/classic/browser/devtools/debugger-toggleBreakpoints.png (../shared/devtools/images/debugger-toggleBreakpoints.png)
   skin/classic/browser/devtools/debugger-toggleBreakpoints@2x.png (../shared/devtools/images/debugger-toggleBreakpoints@2x.png)
   skin/classic/browser/devtools/tracer-icon.png             (../shared/devtools/images/tracer-icon.png)
   skin/classic/browser/devtools/tracer-icon@2x.png          (../shared/devtools/images/tracer-icon@2x.png)
   skin/classic/browser/devtools/floating-scrollbars.css     (devtools/floating-scrollbars.css)
   skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
index b643bfc6f67da9c4934f05510b5cbd296e901bcd..b81e691acd2c1d3027ec3675c5e189571f488ad4
GIT binary patch
literal 127
zc%17D@N?(olHy`uVBq!ia0vp^%s?#1!2%?mGjj@ol$)oEV@L&KY3D_*0|p$-$!e|t
z{<B*v>xi7%(cZ0|Et(~0%`{u0V|nJ;2}O(Arrh@rl<|7~{J5BG@Q+IiruKc$pHX|{
b!dIproh%O9ES#HxCNg-s`njxgN@xNAt4%7z
index 11cfca4c149871587aec2e18b71fd6ef3d49823a..2a6b04241cb3920098af122a413107d9ebab4a4e
GIT binary patch
literal 188
zc%17D@N?(olHy`uVBq!ia0vp^Y(Q+o!2%@Tt1xo_sb)_X$B+ufsS^Xa4j6Da=h}VS
z|66`rw%}oA#~F=hCzwR7a>(5O`)1*XH{l!k{O<10^IlZC%45-#h@WfSR&ubI?c6wN
zh4F??Gq>9uuAW}Pn|@uB;VQ`X-KKb!i}{vlgWd9+6Tc?1UAQKHdPceNiU+q&o4FNh
oFwGF_dthb!Q?S=~S;!;i+XWo;B463vfX-p?boFyt=akR{0K&INjQ{`u
--- a/browser/themes/shared/devtools/debugger.inc.css
+++ b/browser/themes/shared/devtools/debugger.inc.css
@@ -106,16 +106,34 @@
 #sources .selected > .black-boxed {
   color: rgba(255,255,255,0.4);
 }
 
 #sources .black-boxed > .dbg-breakpoint {
   display: none;
 }
 
+/* Debugger unblackbox button */
+
+#black-boxed-message-button > .button-box > .button-icon {
+  width: 16px;
+  height: 16px;
+  background-image: url(debugger-blackbox.png);
+  background-position: 0 0;
+  background-size: 32px 16px;
+  background-repeat: no-repeat;
+  -moz-margin-end: 5px;
+}
+
+@media (min-resolution: 2dppx) {
+  #black-boxed-message-button > .button-box > .button-icon {
+    background-image: url(debugger-blackbox@2x.png);
+  }
+}
+
 /* Black box message and source progress meter */
 
 #black-boxed-message,
 #source-progress-container {
   /* Prevent the container deck from aquiring the size from this message. */
   min-width: 1px;
   min-height: 1px;
 }
deleted file mode 100755
index 1169100fbb7d10c7fcfd0776e999bae4e9fc9c57..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100755
index 1169100fbb7d10c7fcfd0776e999bae4e9fc9c57..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..90421287cc6c9631cb8c182a9e89697fe71b22f7
GIT binary patch
literal 1032
zc$@(U1o!)iP)<h;3K|Lk000e1NJLTq003YB001xu1^@s6?iPQ~000BeNkl<Zc-rlm
z%W4!s6o$)aOw@QuOi)x*#Dz}0B%)EoOF)sR(Kqk{;>M*xP!JPWiks}*h?|g&#JdmR
zgJhAN1hQ~4T~((p17)3{%%r>84soV?g!93HqN}=7`A^M%s;e165ClOG1VIo4K@bE%
z5X66h*6yfM>L4SE5nm{E1EVF9;GA3UC)F=h^%_9+wg7V<!?*7Wp+-431Aa^=YfW(e
zYb%w?b^zEPMf$MTx*x;0O8{=a@9+Ko-K~p@zZAlpC~_tA1K7tx>JL7?{WX;R2--g7
z#tg6)0Y&!$p2UTNVrInk2;gE|eCOPnB34Yd06QKMnoB(`m3@VQ?a&y!chR{XRuFS@
zbDdI}(;=aivR5hq=P<Ax>n~pXNb8aWGZh!r3qFZfQ$Hze<2CFHBx(x4?PEE!xafMg
zQVC%rfD33f@%cwl)TdPSYD<XEwLT`4eV-IlJ#r2`G7R=fWycap12YW(dvmm$-k{x>
zB|+OV3T{w*tRE~7%1RyZBF=<Xeo*{y5+;*&WZwRCZd(qvxkU(dEwu7iE53AYHwU=n
zuXQwg@>@};py%`DMO8|<$4~Sg2XhPC^?f)t^bD*Q&bfBhBxYx4JGfGpLtc)y6Z>Dg
zyznJy%uts2LRCkx59<Xcv1wa03Hn7^!No}}6JP53U&%~;5^!u<VdheeHN#gYCMMdX
zv}e-_Zp==)YJQ(Be$2)On<4(1ns<j+E~^7qetZmGV|Cy?Y0ry<dC<rt;ImM?kobRA
zZp?B@nc~Zu`0+r?YIFkH1lZ>*O#s@?za&6_9>>4g$OJ4(b7rLp$g&*-?@4<e-rw+F
z@xsEwW&!3+vn@z~dHv&u+t`F(aXS{u3=7IAxV8DGy&C}7Vcclsu>;C3!eH)U1dDJu
zk?(M9-a8-++~=o?9|H?^N+L(Fez0cZCw0n;^(85uS@AX$#|9GcIgj%c&iRh8cZXlH
zLUs&b&nLyNUiW={EDtI;0jWO)YQb3Mi<q<z1LA*)0ESsk2;p`KFIX}O+2Z@Y!9emx
zaYw}R1Sb;maV|~jQAEnhpOMC#W;qi@uCM0f*`ANKld|%!a?W?MA}E*3-5l%_q3qXH
z9LC|8m(Dqyd?Db8Y}QuuZ-;Tx+OzZX^P5=F;92=^Ye^L7px1+b#<@9O{Ku5+m#mQ2
zOKFBG_~zVd;8qVmWN>9iIG8)jKFFx*O>UN~X#>lV)gG)>v_2F?`pEAn;SLaYN=r44
z_~)ba!wK<;{F6Z97YvC{5ClOG1VIo4K@bE%<jF5D@R$y|Pz_H20000<MNUMnLSTY$
CGURmt
--- a/browser/themes/shared/devtools/netmonitor.inc.css
+++ b/browser/themes/shared/devtools/netmonitor.inc.css
@@ -401,24 +401,44 @@ label.requests-menu-status-code {
 #details-pane-toggle {
   background: none;
   box-shadow: none;
   border-color: transparent;
   list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
   -moz-image-region: rect(0px,16px,16px,0px);
 }
 
+#details-pane-toggle > .toolbarbutton-icon {
+  width: 16px;
+  height: 16px;
+}
+
 #details-pane-toggle[pane-collapsed] {
   list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
 }
 
 #details-pane-toggle:active {
   -moz-image-region: rect(0px,32px,16px,16px);
 }
 
+@media (min-resolution: 2dppx) {
+  #details-pane-toggle {
+    list-style-image: url("chrome://browser/skin/devtools/debugger-collapse@2x.png");
+    -moz-image-region: rect(0px,32px,32px,0px);
+  }
+
+  #details-pane-toggle[pane-collapsed] {
+    list-style-image: url("chrome://browser/skin/devtools/debugger-expand@2x.png");
+  }
+
+  #details-pane-toggle:active {
+    -moz-image-region: rect(0px,64px,32px,32px);
+  }
+}
+
 /* Network request details tabpanels */
 
 .theme-dark .tabpanel-content {
   background-color: #343c45; /* Toolbars */
   color: #f5f7fa; /* Light foreground text */
 }
 
 /* Summary tabpanel */
--- a/browser/themes/shared/devtools/shadereditor.inc.css
+++ b/browser/themes/shared/devtools/shadereditor.inc.css
@@ -65,26 +65,33 @@
 .side-menu-widget-item.selected > .side-menu-widget-item-checkbox,
 .side-menu-widget-item-checkbox:not([checked]) {
   opacity: 1;
   transition: opacity .15s ease-out 0s;
 }
 
 .side-menu-widget-item-checkbox .checkbox-check {
   -moz-appearance: none;
-  background: url(itemToggle.png);
+  background-image: url(itemToggle.png);
+  background-color: transparent;
   background-repeat: no-repeat;
   background-clip: content-box;
   background-size: 32px 16px;
   background-position: -16px 0;
   width: 16px;
   height: 16px;
   border: 0;
 }
 
+@media (min-resolution: 2dppx) {
+  .side-menu-widget-item-checkbox .checkbox-check {
+    background-image: url(itemToggle@2x.png);
+  }
+}
+
 .side-menu-widget-item-checkbox[checked] .checkbox-check {
   background-position: 0 0;
 }
 
 /* Invert all toggle icons but the one in the active row for light theme */
 .theme-light .side-menu-widget-item:not(.selected) .checkbox-check {
   filter: url(filters.svg#invert);
 }
--- a/browser/themes/shared/devtools/styleeditor.css
+++ b/browser/themes/shared/devtools/styleeditor.css
@@ -99,20 +99,27 @@
 
 .stylesheet-enabled {
   padding: 8px 0;
   margin: 0 8px;
   background-image: url(itemToggle.png);
   background-repeat: no-repeat;
   background-clip: content-box;
   background-position: 0 8px;
+  background-size: 48px 24px;
   width: 24px;
   height: 40px;
 }
 
+@media (min-resolution: 2dppx) {
+  .stylesheet-enabled {
+    background-image: url(itemToggle@2x.png);
+  }
+}
+
 .disabled > .stylesheet-enabled {
   background-position: -24px 8px;
 }
 
 /* Invert all toggle icons but the one in the active row for light theme */
 .theme-light .splitview-nav > li:not(.splitview-active) .stylesheet-enabled {
   filter: url(filters.svg#invert);
 }
@@ -188,21 +195,21 @@ h3 {
   }
 
   .stylesheet-sidebar {
     width: 180px;
   }
 }
 
 .theme-light .csscoverage-report {
-  background: url(background-noise-toolbar.png), #f0f1f2; /* Toolbars */
+  background-color: #f0f1f2; /* Toolbars */
 }
 
 .theme-dark .csscoverage-report {
-  background: url(background-noise-toolbar.png), #343c45; /* Toolbars */
+  background-color: #343c45; /* Toolbars */
 }
 
 .csscoverage-report-container {
   height: 100vh;
   padding: 0 30px;
 }
 
 .csscoverage-report-content {
--- a/browser/themes/shared/incontentprefs/preferences.css
+++ b/browser/themes/shared/incontentprefs/preferences.css
@@ -136,45 +136,38 @@ tab[selected] > .tab-middle > .tab-text 
 
 button,
 menulist {
   -moz-appearance: none;
   height: 30px;
   color: #333333;
   line-height: 20px;
   text-shadow: 0 1px 1px #FEFFFE;
-  border: 1px solid rgba(23,50,77,0.4);
+  border: 1px solid #C1C1C1;
   -moz-border-top-colors: none !important;
   -moz-border-right-colors: none !important;
   -moz-border-bottom-colors: none !important;
   -moz-border-left-colors: none !important;
-  border-radius: 5px;
-  box-shadow: 0 1px 1px 0 #FFFFFF, inset 0 2px 2px 0 #FFFFFF;
-  background-color: #F1F1F1;
-  background-image: linear-gradient(#FFFFFF, rgba(255,255,255,0.1));
+  border-radius: 2px;
+  background-color: #FBFBFB;
 }
 
 button:not([disabled="true"]):hover,
 menulist:not([disabled="true"]):hover {
-  background-image: linear-gradient(#FFFFFF, rgba(255,255,255,0.6));
+  background-color: #EBEBEB;
 }
 
 button:not([disabled="true"]):hover:active,
 menulist[open="true"]:not([disabled="true"]) {
-  background-image: linear-gradient(rgba(255,255,255,0.1),
-                                    rgba(255,255,255,0.6));
+  background-color: #DADADA;
 }
 
 button[disabled="true"],
 menulist[disabled="true"] {
-  background-image: linear-gradient(rgba(255,255,255,0.5),
-                                    rgba(255,255,255,0.1));
-  border-color: rgba(23,50,77,0.25);
-  color: rgba(115,121,128,0.5);
-  text-shadow: 0 1px 1px #FFFFFF;
+  opacity: 0.5;
 }
 
 button > .button-box,
 menulist > .menulist-label-box {
   padding-right: 10px !important;
   padding-left: 10px !important;
 }
 
@@ -236,22 +229,22 @@ button[type="menu"] > .button-box > .but
 
 .spinbuttons-button {
   -moz-margin-start: 10px !important;
   -moz-margin-end: 2px !important;
 }
 
 .spinbuttons-up {
   margin-top: 2px !important;
-  border-radius: 4px 4px 0 0;
+  border-radius: 1px 1px 0 0;
 }
 
 .spinbuttons-down  {
   margin-bottom: 2px !important;
-  border-radius: 0 0 4px 4px;
+  border-radius: 0 0 1px 1px;
 }
 
 .spinbuttons-button > .button-box {
   padding: 1px 5px 2px !important;
 }
 
 .spinbuttons-up > .button-box > .button-icon {
   list-style-image: url("chrome://global/skin/arrow/arrow-up.gif");
@@ -298,17 +291,17 @@ menulist[disabled="true"]:not([editable=
     height: 16px;
   }
 }
 
 menulist > menupopup,
 button[type="menu"] > menupopup {
   -moz-appearance: none;
   border: 1px solid rgba(23,50,77,0.4);
-  border-radius: 5px;
+  border-radius: 2px;
   background-color: #FFFFFF;
 }
 
 menulist > menupopup menu,
 menulist > menupopup menuitem,
 button[type="menu"] > menupopup menu,
 button[type="menu"] > menupopup menuitem {
   -moz-appearance: none;
@@ -353,47 +346,41 @@ button[type="menu"] > menupopup menusepa
 textbox {
   -moz-appearance: none;
   height: 30px;
   color: #333333;
   line-height: 20px;
   text-shadow: 0 1px 1px #FEFFFE;
   padding-right: 10px;
   padding-left: 10px;
-  border: 1px solid rgba(23,50,77,0.4);
+  border: 1px solid #C1C1C1;
   -moz-border-top-colors: none !important;
   -moz-border-right-colors: none !important;
   -moz-border-bottom-colors: none !important;
   -moz-border-left-colors: none !important;
-  border-radius: 5px;
-  box-shadow: 0 1px 1px 0 #FFFFFF, inset 0 2px 2px 0 rgba(0,0,0,0.03);
-  background-color: #F1F1F1;
-  background-image: linear-gradient(#FFFFFF, rgba(255,255,255,0.8));
+  border-radius: 2px;
+  background-color: #FFF;
 }
 
 textbox[focused] {
-  color: #424E5A;
-  border-color: #0096DC;
-  box-shadow: 0 0 2px 2px rgba(0,150,220,0.35), inset 0 0 2px 0 #0096DC;
+  border-color: #0095DD;
 }
 
 textbox[disabled="true"] {
-  color: rgba(115,121,128,0.5);
-  border-color: rgba(23,50,77,0.25);
-  background-image: linear-gradient(rgba(255,255,255,0.5), rgba(255,255,255,0.4));
+  opacity: 0.5;
 }
 
 /* Links */
 
 .text-link,
 .inline-link,
 html|a.inline-link {
   font-size: 1.25rem;
   line-height: 22px;
-  color: #0096DC;
+  color: #0095DD;
 }
 
 .text-link:hover,
 .inline-link:hover {
   color: #4CB1FF;
   text-decoration: none;
 }
 
@@ -706,59 +693,56 @@ filefield {
 }
 
 #handlersView {
   -moz-appearance: none;
   -moz-margin-start: 0;
   font-size: 1.25rem;
   line-height: 22px;
   color: #333333;
-  border: 1px solid rgba(23,50,77,0.4);
-  border-radius: 5px;
-  background-color: #F1F1F1;
+  border: 1px solid #C1C1C1;
+  border-radius: 2px;
+  background-color: #FBFBFB;
   overflow-y: auto;
 }
 
 #typeColumn,
 #actionColumn {
   -moz-appearance: none;
   font-family: "Clear Sans", sans-serif;
   line-height: 20px;
   color: #333333;
   height: 36px;
   padding: 0 10px;
-  background-color: #F7F7F7;
-  border: 1px solid #CCCCCC;
+  background-color: #FBFBFB;
+  border: 1px solid #C1C1C1;
   -moz-border-top-colors: none;
   -moz-border-right-colors: none;
   -moz-border-bottom-colors: none;
   -moz-border-left-colors: none;
-  text-shadow: 0 1px 1px #FFFFFF;
 }
 
 #typeColumn:-moz-locale-dir(ltr),
 #actionColumn:-moz-locale-dir(rtl) {
-  border-top-left-radius: 5px;
+  border-top-left-radius: 2px;
 }
 
 #typeColumn:-moz-locale-dir(rtl),
 #actionColumn:-moz-locale-dir(ltr) {
-  border-top-right-radius: 5px;
+  border-top-right-radius: 2px;
 }
 
 #typeColumn:hover,
 #actionColumn:hover {
-  border-color: #737980;
+  border-color: #0095DD;
 }
 
 #typeColumn:hover:active,
 #actionColumn:hover:active {
   padding: 0 10px;
-  border-color: #0096DC;
-  box-shadow: 0 0 2px 2px rgba(0,150,220,0.35), inset 0 0 2px 0 #0096DC;
 }
 
 #typeColumn > .treecol-sortdirection[sortDirection=ascending],
 #actionColumn > .treecol-sortdirection[sortDirection=ascending],
 #typeColumn > .treecol-sortdirection[sortDirection=descending],
 #actionColumn > .treecol-sortdirection[sortDirection=descending] {
   -moz-appearance: none;
   list-style-image: url("chrome://browser/skin/preferences/in-content/sorter.png");
@@ -808,47 +792,35 @@ filefield {
 }
 
 /* XXX This style is for bug 740213 and should be removed once that
    bug has a solution. */
 description > html|a {
   cursor: pointer;
 }
 
-/* Sync Pane */
-
+#offlineAppsList,
 #syncEnginesList {
   -moz-appearance: none;
   color: #333333;
   padding: 10px;
-  border: 1px solid rgba(23,50,77,0.4);
-  border-radius: 5px;
-  background-color: #F1F1F1;
+  border: 1px solid #C1C1C1;
+  border-radius: 2px;
+  background-color: #FBFBFB;
 }
 
-/* Advanced Pane */
-
 #advancedPrefs {
   padding-bottom: 0; /* no padding needed in inContent prefs */
 }
 
 #encryptionPanel {
   margin-top: 15px;
   -moz-margin-start: 60px;
 }
 
-#offlineAppsList {
-  -moz-appearance: none;
-  color: #333333;
-  padding: 2px;
-  border: 1px solid rgba(23,50,77,0.4);
-  border-radius: 5px;
-  background-color: #F1F1F1;
-}
-
 #telemetryLearnMore,
 #FHRLearnMore,
 #crashReporterLearnMore {
   /* center the links */
   margin-top: 8px;
   margin-bottom: 8px;
 }
 
--- a/browser/themes/shared/translation/infobar.inc.css
+++ b/browser/themes/shared/translation/infobar.inc.css
@@ -21,51 +21,28 @@ notification[value="translation"][state=
 }
 
 @media (min-resolution: 1.25dppx) {
   notification[value="translation"][state="translating"] .messageImage {
     list-style-image: url(chrome://browser/skin/translating-16@2x.png);
   }
 }
 
-notification[value="translation"] {
-  min-height: 40px;
-}
-
 notification[value="translation"] button,
 notification[value="translation"] menulist {
   -moz-appearance: none;
   border-width: 1px;
   -moz-border-top-colors: none;
   -moz-border-right-colors: none;
   -moz-border-bottom-colors: none;
   -moz-border-left-colors: none;
   border-radius: 2px;
   min-width: 0;
-  min-height: 30px;
-  -moz-padding-end: 1ch;
   box-shadow: 0 1px rgba(255, 255, 255, 0.5), 0 1px rgba(255, 255, 255, 0.5) inset;
 }
 
-notification[value="translation"] button > .button-box,
-notification[value="translation"] button[type="menu"] > .button-box > .button-menu-dropmarker {
-  padding: 0;
-  -moz-margin-start: 3ch;
-}
-
-notification[value="translation"] button:not([type="menu"]) > .button-box {
-  -moz-margin-end: 3ch;
-}
-
-notification[value="translation"] button,
-notification[value="translation"] menulist,
-notification[value="translation"] menulist > .menulist-label-box {
-  -moz-margin-start: 1ch;
-  -moz-margin-end: 1ch;
-}
-
 notification[value="translation"] menulist > .menulist-dropmarker {
   -moz-appearance: toolbarbutton-dropdown;
   border: none;
   background-color: transparent;
   margin: auto;
   padding: 5px 0;
 }
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -2345,37 +2345,54 @@ toolbarbutton.bookmark-item[dragover="tr
 #pointerLock-cancel {
   margin: 0px;
 }
 
 /* Translation infobar */
 
 %include ../shared/translation/infobar.inc.css
 
+notification[value="translation"] {
+  min-height: 40px;
+}
+
 @media (-moz-windows-default-theme) {
   notification[value="translation"],
   notification[value="translation"] button,
   notification[value="translation"] menulist {
+    min-height: 30px;
     color: #545454;
   }
 
   notification[value="translation"] {
     background-color: #EEE;
   }
 
+  notification[value="translation"] button,
+  notification[value="translation"] menulist {
+    -moz-padding-end: 1ch;
+  }
+
   notification[value="translation"] menulist {
     border: 1px solid #C1C1C1;
     background-color: #FFF;
   }
 
   notification[value="translation"] button {
     border: 1px solid #C1C1C1;
     background-color: #FBFBFB;
   }
 
+  notification[value="translation"] button,
+  notification[value="translation"] menulist,
+  notification[value="translation"] menulist > .menulist-label-box {
+    -moz-margin-start: 1ch;
+    -moz-margin-end: 1ch;
+  }
+
   notification[value="translation"] button:hover,
   notification[value="translation"] button:active,
   notification[value="translation"] menulist:hover,
   notification[value="translation"] menulist:active {
     background-color: #EBEBEB;
   }
 
   notification[value="translation"] button[anonid="translate"] {
@@ -2390,16 +2407,26 @@ toolbarbutton.bookmark-item[dragover="tr
     background-color: #008ACB;
   }
 
   notification[value="translation"] button[type="menu"] > .button-box > .button-menu-dropmarker,
   notification[value="translation"] menulist > .menulist-dropmarker {
     list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow.png");
   }
 
+  notification[value="translation"] button > .button-box,
+  notification[value="translation"] button[type="menu"] > .button-box > .button-menu-dropmarker {
+    padding: 0;
+    -moz-margin-start: 3ch;
+  }
+
+  notification[value="translation"] button:not([type="menu"]) > .button-box {
+    -moz-margin-end: 3ch;
+  }
+
   @media (min-resolution: 1.25dppx) {
     notification[value="translation"] button[type="menu"] > .button-box > .button-menu-dropmarker,
     notification[value="translation"] menulist > .menulist-dropmarker {
       list-style-image: url("chrome://browser/skin/toolbarbutton-dropdown-arrow@2x.png");
     }
   }
 }
 
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -277,16 +277,17 @@ browser.jar:
 *       skin/classic/browser/devtools/splitview.css                 (../shared/devtools/splitview.css)
         skin/classic/browser/devtools/styleeditor.css               (../shared/devtools/styleeditor.css)
 *       skin/classic/browser/devtools/webaudioeditor.css            (devtools/webaudioeditor.css)
         skin/classic/browser/devtools/magnifying-glass.png          (../shared/devtools/images/magnifying-glass.png)
         skin/classic/browser/devtools/magnifying-glass@2x.png       (../shared/devtools/images/magnifying-glass@2x.png)
         skin/classic/browser/devtools/magnifying-glass-light.png    (../shared/devtools/images/magnifying-glass-light.png)
         skin/classic/browser/devtools/magnifying-glass-light@2x.png  (../shared/devtools/images/magnifying-glass-light@2x.png)
         skin/classic/browser/devtools/itemToggle.png                (../shared/devtools/images/itemToggle.png)
+        skin/classic/browser/devtools/itemToggle@2x.png             (../shared/devtools/images/itemToggle@2x.png)
         skin/classic/browser/devtools/itemArrow-dark-rtl.svg        (../shared/devtools/images/itemArrow-dark-rtl.svg)
         skin/classic/browser/devtools/itemArrow-dark-ltr.svg        (../shared/devtools/images/itemArrow-dark-ltr.svg)
         skin/classic/browser/devtools/itemArrow-rtl.svg             (../shared/devtools/images/itemArrow-rtl.svg)
         skin/classic/browser/devtools/itemArrow-ltr.svg             (../shared/devtools/images/itemArrow-ltr.svg)
         skin/classic/browser/devtools/noise.png                     (../shared/devtools/images/noise.png)
         skin/classic/browser/devtools/dropmarker.png                (../shared/devtools/images/dropmarker.png)
         skin/classic/browser/devtools/layoutview.css                (../shared/devtools/layoutview.css)
         skin/classic/browser/devtools/debugger-collapse.png         (../shared/devtools/images/debugger-collapse.png)
@@ -298,17 +299,16 @@ browser.jar:
         skin/classic/browser/devtools/debugger-play.png             (../shared/devtools/images/debugger-play.png)
         skin/classic/browser/devtools/debugger-play@2x.png          (../shared/devtools/images/debugger-play@2x.png)
         skin/classic/browser/devtools/debugger-step-in.png          (../shared/devtools/images/debugger-step-in.png)
         skin/classic/browser/devtools/debugger-step-in@2x.png       (../shared/devtools/images/debugger-step-in@2x.png)
         skin/classic/browser/devtools/debugger-step-out.png         (../shared/devtools/images/debugger-step-out.png)
         skin/classic/browser/devtools/debugger-step-out@2x.png      (../shared/devtools/images/debugger-step-out@2x.png)
         skin/classic/browser/devtools/debugger-step-over.png        (../shared/devtools/images/debugger-step-over.png)
         skin/classic/browser/devtools/debugger-step-over@2x.png     (../shared/devtools/images/debugger-step-over@2x.png)
-        skin/classic/browser/devtools/debugger-blackbox-eye.png     (../shared/devtools/images/debugger-blackbox-eye.png)
         skin/classic/browser/devtools/debugger-blackbox.png         (../shared/devtools/images/debugger-blackbox.png)
         skin/classic/browser/devtools/debugger-blackbox@2x.png      (../shared/devtools/images/debugger-blackbox@2x.png)
         skin/classic/browser/devtools/debugger-toggleBreakpoints.png  (../shared/devtools/images/debugger-toggleBreakpoints.png)
         skin/classic/browser/devtools/debugger-toggleBreakpoints@2x.png  (../shared/devtools/images/debugger-toggleBreakpoints@2x.png)
         skin/classic/browser/devtools/tracer-icon.png               (../shared/devtools/images/tracer-icon.png)
         skin/classic/browser/devtools/tracer-icon@2x.png            (../shared/devtools/images/tracer-icon@2x.png)
         skin/classic/browser/devtools/responsive-se-resizer.png     (../shared/devtools/images/responsive-se-resizer.png)
         skin/classic/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsive-vertical-resizer.png)
@@ -672,16 +672,17 @@ browser.jar:
 *       skin/classic/aero/browser/devtools/splitview.css             (../shared/devtools/splitview.css)
         skin/classic/aero/browser/devtools/styleeditor.css           (../shared/devtools/styleeditor.css)
 *       skin/classic/aero/browser/devtools/webaudioeditor.css        (devtools/webaudioeditor.css)
         skin/classic/aero/browser/devtools/magnifying-glass.png      (../shared/devtools/images/magnifying-glass.png)
         skin/classic/aero/browser/devtools/magnifying-glass@2x.png   (../shared/devtools/images/magnifying-glass@2x.png)
         skin/classic/aero/browser/devtools/magnifying-glass-light.png (../shared/devtools/images/magnifying-glass-light.png)
         skin/classic/aero/browser/devtools/magnifying-glass-light@2x.png  (../shared/devtools/images/magnifying-glass-light@2x.png)
         skin/classic/aero/browser/devtools/itemToggle.png            (../shared/devtools/images/itemToggle.png)
+        skin/classic/aero/browser/devtools/itemToggle@2x.png         (../shared/devtools/images/itemToggle@2x.png)
         skin/classic/aero/browser/devtools/itemArrow-dark-rtl.svg    (../shared/devtools/images/itemArrow-dark-rtl.svg)
         skin/classic/aero/browser/devtools/itemArrow-dark-ltr.svg    (../shared/devtools/images/itemArrow-dark-ltr.svg)
         skin/classic/aero/browser/devtools/itemArrow-rtl.svg         (../shared/devtools/images/itemArrow-rtl.svg)
         skin/classic/aero/browser/devtools/itemArrow-ltr.svg         (../shared/devtools/images/itemArrow-ltr.svg)
         skin/classic/aero/browser/devtools/noise.png                 (../shared/devtools/images/noise.png)
         skin/classic/aero/browser/devtools/dropmarker.png            (../shared/devtools/images/dropmarker.png)
         skin/classic/aero/browser/devtools/layoutview.css            (../shared/devtools/layoutview.css)
         skin/classic/aero/browser/devtools/debugger-collapse.png     (../shared/devtools/images/debugger-collapse.png)
@@ -693,17 +694,16 @@ browser.jar:
         skin/classic/aero/browser/devtools/debugger-play.png         (../shared/devtools/images/debugger-play.png)
         skin/classic/aero/browser/devtools/debugger-play@2x.png      (../shared/devtools/images/debugger-play@2x.png)
         skin/classic/aero/browser/devtools/debugger-step-in.png      (../shared/devtools/images/debugger-step-in.png)
         skin/classic/aero/browser/devtools/debugger-step-in@2x.png   (../shared/devtools/images/debugger-step-in@2x.png)
         skin/classic/aero/browser/devtools/debugger-step-out.png     (../shared/devtools/images/debugger-step-out.png)
         skin/classic/aero/browser/devtools/debugger-step-out@2x.png  (../shared/devtools/images/debugger-step-out@2x.png)
         skin/classic/aero/browser/devtools/debugger-step-over.png    (../shared/devtools/images/debugger-step-over.png)
         skin/classic/aero/browser/devtools/debugger-step-over@2x.png  (../shared/devtools/images/debugger-step-over@2x.png)
-        skin/classic/aero/browser/devtools/debugger-blackbox-eye.png  (../shared/devtools/images/debugger-blackbox-eye.png)
         skin/classic/aero/browser/devtools/debugger-blackbox.png      (../shared/devtools/images/debugger-blackbox.png)
         skin/classic/aero/browser/devtools/debugger-blackbox@2x.png   (../shared/devtools/images/debugger-blackbox@2x.png)
         skin/classic/aero/browser/devtools/debugger-toggleBreakpoints.png (../shared/devtools/images/debugger-toggleBreakpoints.png)
         skin/classic/aero/browser/devtools/debugger-toggleBreakpoints@2x.png (../shared/devtools/images/debugger-toggleBreakpoints@2x.png)
         skin/classic/aero/browser/devtools/tracer-icon.png           (../shared/devtools/images/tracer-icon.png)
         skin/classic/aero/browser/devtools/tracer-icon@2x.png        (../shared/devtools/images/tracer-icon@2x.png)
         skin/classic/aero/browser/devtools/responsive-se-resizer.png (../shared/devtools/images/responsive-se-resizer.png)
         skin/classic/aero/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsive-vertical-resizer.png)
index af4403a500a0e320d1fac2c4d7b9196c9f8973eb..8f46ed201249696e03e6ebd408afca7faa2ec237
GIT binary patch
literal 143
zc%17D@N?(olHy`uVBq!ia0vp^%s?#1!3HE>CM@{{q{2L1978G?lam~nR?P8#KhN-1
zRr_X!Of|I?I?@8hhb-PW^e7!}32kHUm^ssdMWDDTRY0bNN8FKbnOxo)88MA^*42!6
qB;16<j(N^0wlLV!dnWOaY#xJoF^8ddc3d6M1_n=8KbLh*2~7Y4_$v4S
index 2f8cae3b3251af8c85416c09ec2b7d3b094594e2..3f62dda73e3021820742e084c0c6b5ce7bda4ea9
GIT binary patch
literal 143
zc%17D@N?(olHy`uVBq!ia0vp^%s?#1!3HE>CM@{{q{2L1978G?lMnFP?X5m`LN)OW
z&ytxl8fpa6Sd-i&+Ic%38tI&nF)QIS7Vcn3;+vq*bGT2*c|!Bbc46&y)>ZASs~P7=
rxCw_H^P5wAV`J59&e%55W@ZK-M)rae8!nsx+Q8uH>gTe~DWM4fO<OGr
index c76c615fc18c37261e76ab39db98b18e19c67013..b4192f776e91b155a907592175310c33119343a2
GIT binary patch
literal 143
zc%17D@N?(olHy`uVBq!ia0vp^%s?#1!3HE>CM@{{q{2L1978G?lMnFP?X5nxBJ<2q
zo+UG9G}H*Bu_n1mwDWd6G}1XCV^+dvEZo76#5X~q=Ww5r^MvM=?ZVpatgG5tS2NC$
ra1#zY<~OJK#>T4IoUv`9&CCob{Opa_Hu)|E+Q8uH>gTe~DWM4fdDbm6
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -448,17 +448,18 @@ private:
   nsRefPtr<nsFrameLoader> mFrameLoader;
 };
 
 nsresult
 nsFrameLoader::ReallyStartLoadingInternal()
 {
   NS_ENSURE_STATE(mURIToLoad && mOwnerContent && mOwnerContent->IsInDoc());
 
-  PROFILER_LABEL("nsFrameLoader", "ReallyStartLoading");
+  PROFILER_LABEL("nsFrameLoader", "ReallyStartLoading",
+    js::ProfileEntry::Category::OTHER);
 
   nsresult rv = MaybeCreateDocShell();
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (mRemoteFrame) {
     if (!mRemoteBrowser) {
@@ -2094,17 +2095,18 @@ nsFrameLoader::TryRemoteBrowser()
   nsCOMPtr<nsIXULWindow> window(do_GetInterface(parentOwner));
   if (!window) {
     return false;
   }
   if (NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
     return false;
   }
 
-  PROFILER_LABEL("nsFrameLoader", "CreateRemoteBrowser");
+  PROFILER_LABEL("nsFrameLoader", "CreateRemoteBrowser",
+    js::ProfileEntry::Category::OTHER);
 
   MutableTabContext context;
   nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
   nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
   ScrollingBehavior scrollingBehavior = DEFAULT_SCROLLING;
 
   if (Preferences::GetBool("dom.browser_frames.useAsyncPanZoom", false) ||
       mOwnerContent->AttrValueIs(kNameSpaceID_None,
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -915,17 +915,18 @@ nsObjectLoadingContent::NotifyOwnerDocum
     QueueCheckPluginStopEvent();
 }
 
 // nsIRequestObserver
 NS_IMETHODIMP
 nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
                                        nsISupports *aContext)
 {
-  PROFILER_LABEL("nsObjectLoadingContent", "OnStartRequest");
+  PROFILER_LABEL("nsObjectLoadingContent", "OnStartRequest",
+    js::ProfileEntry::Category::NETWORK);
 
   LOG(("OBJLC [%p]: Channel OnStartRequest", this));
 
   if (aRequest != mChannel || !aRequest) {
     // happens when a new load starts before the previous one got here
     return NS_BINDING_ABORTED;
   }
 
@@ -977,16 +978,19 @@ nsObjectLoadingContent::OnStartRequest(n
   return LoadObject(true, false, aRequest);
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::OnStopRequest(nsIRequest *aRequest,
                                       nsISupports *aContext,
                                       nsresult aStatusCode)
 {
+  PROFILER_LABEL("nsObjectLoadingContent", "OnStopRequest",
+    js::ProfileEntry::Category::NETWORK);
+
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
 
   if (aRequest != mChannel) {
     return NS_BINDING_ABORTED;
   }
 
   mChannel = nullptr;
 
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1908,17 +1908,19 @@ nsXMLHttpRequest::OnDataAvailable(nsIReq
 
   return NS_OK;
 }
 
 /* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
 NS_IMETHODIMP
 nsXMLHttpRequest::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
 {
-  PROFILER_LABEL("nsXMLHttpRequest", "OnStartRequest");
+  PROFILER_LABEL("nsXMLHttpRequest", "OnStartRequest",
+    js::ProfileEntry::Category::NETWORK);
+
   nsresult rv = NS_OK;
   if (!mFirstStartRequestSeen && mRequestObserver) {
     mFirstStartRequestSeen = true;
     mRequestObserver->OnStartRequest(request, ctxt);
   }
 
   if (request != mChannel) {
     // Can this still happen?
@@ -2150,17 +2152,19 @@ nsXMLHttpRequest::OnStartRequest(nsIRequ
 
   return NS_OK;
 }
 
 /* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status, in wstring statusArg); */
 NS_IMETHODIMP
 nsXMLHttpRequest::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status)
 {
-  PROFILER_LABEL("content", "nsXMLHttpRequest::OnStopRequest");
+  PROFILER_LABEL("nsXMLHttpRequest", "OnStopRequest",
+    js::ProfileEntry::Category::NETWORK);
+
   if (request != mChannel) {
     // Can this still happen?
     return NS_OK;
   }
 
   mWaitingForOnStopRequest = false;
 
   if (mRequestObserver) {
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp
+++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp
@@ -71,17 +71,18 @@ nsGenericHTMLFrameElement::BindToTree(ns
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
     NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                  "Missing a script blocker!");
 
-    PROFILER_LABEL("nsGenericHTMLFrameElement", "BindToTree");
+    PROFILER_LABEL("nsGenericHTMLFrameElement", "BindToTree",
+      js::ProfileEntry::Category::OTHER);
 
     // We're in a document now.  Kick off the frame load.
     LoadSrc();
   }
 
   // We're now in document and scripts may move us, so clear
   // the mNetworkCreated flag.
   mNetworkCreated = false;
--- a/content/html/document/src/PluginDocument.cpp
+++ b/content/html/document/src/PluginDocument.cpp
@@ -68,17 +68,18 @@ public:
 private:
   nsRefPtr<PluginDocument> mPluginDoc;
 };
 
 
 NS_IMETHODIMP
 PluginStreamListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
 {
-  PROFILER_LABEL("PluginStreamListener", "OnStartRequest");
+  PROFILER_LABEL("PluginStreamListener", "OnStartRequest",
+    js::ProfileEntry::Category::NETWORK);
 
   nsCOMPtr<nsIContent> embed = mPluginDoc->GetPluginContent();
   nsCOMPtr<nsIObjectLoadingContent> objlc = do_QueryInterface(embed);
   nsCOMPtr<nsIStreamListener> objListener = do_QueryInterface(objlc);
 
   if (!objListener) {
     NS_NOTREACHED("PluginStreamListener without appropriate content node");
     return NS_BINDING_ABORTED;
--- a/content/svg/content/src/SVGIFrameElement.cpp
+++ b/content/svg/content/src/SVGIFrameElement.cpp
@@ -270,17 +270,18 @@ SVGIFrameElement::BindToTree(nsIDocument
                                          aBindingParent,
                                          aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aDocument) {
     NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                  "Missing a script blocker!");
 
-    PROFILER_LABEL("SVGIFrameElement", "BindToTree");
+    PROFILER_LABEL("SVGIFrameElement", "BindToTree",
+      js::ProfileEntry::Category::OTHER);
 
     // We're in a document now.  Kick off the frame load.
     LoadSrc();
 
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::sandbox)) {
       if (mFrameLoader) {
         mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
       }
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -658,17 +658,19 @@ nsDOMWindowUtils::SendMouseEventToWindow
                                          int32_t aClickCount,
                                          int32_t aModifiers,
                                          bool aIgnoreRootScrollFrame,
                                          float aPressure,
                                          unsigned short aInputSourceArg,
                                          bool aIsSynthesized,
                                          uint8_t aOptionalArgCount)
 {
-  PROFILER_LABEL("nsDOMWindowUtils", "SendMouseEventToWindow");
+  PROFILER_LABEL("nsDOMWindowUtils", "SendMouseEventToWindow",
+    js::ProfileEntry::Category::EVENTS);
+
   return SendMouseEventCommon(aType, aX, aY, aButton, aClickCount, aModifiers,
                               aIgnoreRootScrollFrame, aPressure,
                               aInputSourceArg, true, nullptr,
                               aOptionalArgCount >= 4 ? aIsSynthesized : true);
 }
 
 static LayoutDeviceIntPoint
 ToWidgetPoint(const CSSPoint& aPoint, const nsPoint& aOffset,
@@ -1420,17 +1422,19 @@ nsDOMWindowUtils::Focus(nsIDOMElement* a
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener *aListener,
                                  int32_t aExtraForgetSkippableCalls)
 {
-  PROFILER_LABEL("GC", "GarbageCollect");
+  PROFILER_LABEL("nsDOMWindowUtils", "GarbageCollect",
+    js::ProfileEntry::Category::GC);
+
   // Always permit this in debug builds.
 #ifndef DEBUG
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 #endif
 
   nsJSContext::GarbageCollectNow(JS::gcreason::DOM_UTILS);
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1712,17 +1712,18 @@ FullGCTimerFired(nsITimer* aTimer, void*
 
 //static
 void
 nsJSContext::GarbageCollectNow(JS::gcreason::Reason aReason,
                                IsIncremental aIncremental,
                                IsShrinking aShrinking,
                                int64_t aSliceMillis)
 {
-  PROFILER_LABEL("GC", "GarbageCollectNow");
+  PROFILER_LABEL("nsJSContext", "GarbageCollectNow",
+    js::ProfileEntry::Category::GC);
 
   MOZ_ASSERT_IF(aSliceMillis, aIncremental == IncrementalGC);
 
   KillGCTimer();
   KillShrinkGCBuffersTimer();
 
   // Reset sPendingLoadCount in case the timer that fired was a
   // timer we scheduled due to a normal GC timer firing while
@@ -1754,17 +1755,18 @@ nsJSContext::GarbageCollectNow(JS::gcrea
     JS::GCForReason(sRuntime, aReason);
   }
 }
 
 //static
 void
 nsJSContext::ShrinkGCBuffersNow()
 {
-  PROFILER_LABEL("GC", "ShrinkGCBuffersNow");
+  PROFILER_LABEL("nsJSContext", "ShrinkGCBuffersNow",
+    js::ProfileEntry::Category::GC);
 
   KillShrinkGCBuffersTimer();
 
   JS::ShrinkGCBuffers(sRuntime);
 }
 
 static void
 FinishAnyIncrementalGC()
@@ -1935,31 +1937,34 @@ CycleCollectorStats::RunForgetSkippable(
 void
 nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
                              int32_t aExtraForgetSkippableCalls)
 {
   if (!NS_IsMainThread()) {
     return;
   }
 
-  PROFILER_LABEL("CC", "CycleCollectNow");
+  PROFILER_LABEL("nsJSContext", "CycleCollectNow",
+    js::ProfileEntry::Category::CC);
+
   gCCStats.PrepareForCycleCollectionSlice(aExtraForgetSkippableCalls);
   nsCycleCollector_collect(aListener);
   gCCStats.FinishCycleCollectionSlice();
 }
 
 //static
 void
 nsJSContext::RunCycleCollectorSlice()
 {
   if (!NS_IsMainThread()) {
     return;
   }
 
-  PROFILER_LABEL("CC", "RunCycleCollectorSlice");
+  PROFILER_LABEL("nsJSContext", "RunCycleCollectorSlice",
+    js::ProfileEntry::Category::CC);
 
   gCCStats.PrepareForCycleCollectionSlice();
 
   // Decide how long we want to budget for this slice. By default,
   // use an unlimited budget.
   int64_t sliceBudget = -1;
 
   if (sIncrementalCC) {
@@ -1985,17 +1990,18 @@ nsJSContext::RunCycleCollectorSlice()
 //static
 void
 nsJSContext::RunCycleCollectorWorkSlice(int64_t aWorkBudget)
 {
   if (!NS_IsMainThread()) {
     return;
   }
 
-  PROFILER_LABEL("CC", "RunCycleCollectorWorkSlice");
+  PROFILER_LABEL("nsJSContext", "RunCycleCollectorWorkSlice",
+    js::ProfileEntry::Category::CC);
 
   gCCStats.PrepareForCycleCollectionSlice();
   nsCycleCollector_collectSliceWork(aWorkBudget);
   gCCStats.FinishCycleCollectionSlice();
 }
 
 static void
 ICCTimerFired(nsITimer* aTimer, void* aClosure)
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -191,17 +191,19 @@ nsresult
 nsJSUtils::EvaluateString(JSContext* aCx,
                           JS::SourceBufferHolder& aSrcBuf,
                           JS::Handle<JSObject*> aScopeObject,
                           JS::CompileOptions& aCompileOptions,
                           const EvaluateOptions& aEvaluateOptions,
                           JS::MutableHandle<JS::Value> aRetValue,
                           void **aOffThreadToken)
 {
-  PROFILER_LABEL("JS", "EvaluateString");
+  PROFILER_LABEL("nsJSUtils", "EvaluateString",
+    js::ProfileEntry::Category::JS);
+
   MOZ_ASSERT_IF(aCompileOptions.versionSet,
                 aCompileOptions.version != JSVERSION_UNKNOWN);
   MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, aEvaluateOptions.needResult);
   MOZ_ASSERT_IF(!aEvaluateOptions.reportUncaught, aEvaluateOptions.needResult);
   MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(aSrcBuf.get());
 
   // Unfortunately, the JS engine actually compiles scripts with a return value
--- a/dom/events/EventDispatcher.cpp
+++ b/dom/events/EventDispatcher.cpp
@@ -383,17 +383,19 @@ EventTargetChainItemForChromeTarget(nsTA
 EventDispatcher::Dispatch(nsISupports* aTarget,
                           nsPresContext* aPresContext,
                           WidgetEvent* aEvent,
                           nsIDOMEvent* aDOMEvent,
                           nsEventStatus* aEventStatus,
                           EventDispatchingCallback* aCallback,
                           nsCOMArray<EventTarget>* aTargets)
 {
-  PROFILER_LABEL("EventDispatcher", "Dispatch");
+  PROFILER_LABEL("EventDispatcher", "Dispatch",
+    js::ProfileEntry::Category::EVENTS);
+
   NS_ASSERTION(aEvent, "Trying to dispatch without WidgetEvent!");
   NS_ENSURE_TRUE(!aEvent->mFlags.mIsBeingDispatched,
                  NS_ERROR_DOM_INVALID_STATE_ERR);
   NS_ASSERTION(!aTargets || !aEvent->message, "Wrong parameters!");
 
   // If we're dispatching an already created DOMEvent object, make
   // sure it is initialized!
   // If aTargets is non-null, the event isn't going to be dispatched.
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -3568,17 +3568,19 @@ EventStateManager::IsHandlingUserInput()
 static void
 CreateMouseOrPointerWidgetEvent(WidgetMouseEvent* aMouseEvent,
                                 uint32_t aMessage,
                                 nsIContent* aRelatedContent,
                                 nsAutoPtr<WidgetMouseEvent>& aNewEvent)
 {
   WidgetPointerEvent* sourcePointer = aMouseEvent->AsPointerEvent();
   if (sourcePointer) {
-    PROFILER_LABEL("Input", "DispatchPointerEvent");
+    PROFILER_LABEL("Input", "DispatchPointerEvent",
+      js::ProfileEntry::Category::EVENTS);
+
     nsAutoPtr<WidgetPointerEvent> newPointerEvent;
     newPointerEvent =
       new WidgetPointerEvent(aMouseEvent->mFlags.mIsTrusted, aMessage,
                              aMouseEvent->widget);
     newPointerEvent->isPrimary = sourcePointer->isPrimary;
     newPointerEvent->pointerId = sourcePointer->pointerId;
     newPointerEvent->width = sourcePointer->width;
     newPointerEvent->height = sourcePointer->height;
@@ -3639,17 +3641,18 @@ EventStateManager::DispatchMouseOrPointe
                                   aRelatedContent, dispatchEvent);
 
   nsWeakFrame previousTarget = mCurrentTarget;
   mCurrentTargetContent = aTargetContent;
 
   nsIFrame* targetFrame = nullptr;
 
   if (aMouseEvent->AsMouseEvent()) {
-    PROFILER_LABEL("Input", "DispatchMouseEvent");
+    PROFILER_LABEL("Input", "DispatchMouseEvent",
+      js::ProfileEntry::Category::EVENTS);
   }
 
   nsEventStatus status = nsEventStatus_eIgnore;
   ESMEventCB callback(aTargetContent);
   EventDispatcher::Dispatch(aTargetContent, mPresContext, dispatchEvent, nullptr,
                             &status, &callback);
 
   if (mPresContext) {
--- a/dom/indexedDB/AsyncConnectionHelper.cpp
+++ b/dom/indexedDB/AsyncConnectionHelper.cpp
@@ -184,17 +184,18 @@ AsyncConnectionHelper::~AsyncConnectionH
 
 NS_IMPL_ISUPPORTS(AsyncConnectionHelper, nsIRunnable,
                   mozIStorageProgressHandler)
 
 NS_IMETHODIMP
 AsyncConnectionHelper::Run()
 {
   if (NS_IsMainThread()) {
-    PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::Run");
+    PROFILER_MAIN_THREAD_LABEL("AsyncConnectionHelper", "Run",
+      js::ProfileEntry::Category::STORAGE);
 
     if (mTransaction &&
         mTransaction->IsAborted()) {
       // Always fire a "error" event with ABORT_ERR if the transaction was
       // aborted, even if the request succeeded or failed with another error.
       mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR;
     }
 
@@ -266,17 +267,18 @@ AsyncConnectionHelper::Run()
     NS_ASSERTION(!(mDatabase || mTransaction || mRequest), "Subclass didn't "
                  "call AsyncConnectionHelper::ReleaseMainThreadObjects!");
 
     return NS_OK;
   }
 
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "AsyncConnectionHelper::Run");
+  PROFILER_LABEL("AsyncConnectionHelper", "Run",
+    js::ProfileEntry::Category::STORAGE);
 
   IDB_PROFILER_MARK_IF(mRequest,
                        "IndexedDB Request %llu: Beginning database work",
                        "IDBRequest[%llu] DT Start",
                        mRequest->GetSerialNumber());
 
   nsresult rv = NS_OK;
   nsCOMPtr<mozIStorageConnection> connection;
@@ -447,17 +449,18 @@ AsyncConnectionHelper::CreateSuccessEven
 }
 
 nsresult
 AsyncConnectionHelper::OnSuccess()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(mRequest, "Null request!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::OnSuccess");
+  PROFILER_MAIN_THREAD_LABEL("AsyncConnectionHelper", "OnSuccess",
+    js::ProfileEntry::Category::STORAGE);
 
   nsRefPtr<nsIDOMEvent> event = CreateSuccessEvent(mRequest);
   if (!event) {
     IDB_WARNING("Failed to create event!");
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   bool dummy;
@@ -483,17 +486,18 @@ AsyncConnectionHelper::OnSuccess()
 }
 
 void
 AsyncConnectionHelper::OnError()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(mRequest, "Null request!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::OnError");
+  PROFILER_MAIN_THREAD_LABEL("AsyncConnectionHelper", "OnError",
+    js::ProfileEntry::Category::STORAGE);
 
   // Make an error event and fire it at the target.
   nsRefPtr<nsIDOMEvent> event =
     CreateGenericEvent(mRequest, NS_LITERAL_STRING(ERROR_EVT_STR), eDoesBubble,
                        eCancelable);
   if (!event) {
     NS_ERROR("Failed to create event!");
     return;
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -978,17 +978,18 @@ CursorHelper::ReleaseMainThreadObjects()
   AsyncConnectionHelper::ReleaseMainThreadObjects();
 }
 
 nsresult
 CursorHelper::Dispatch(nsIEventTarget* aDatabaseThread)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB", "CursorHelper::Dispatch");
+  PROFILER_MAIN_THREAD_LABEL("CursorHelper", "Dispatch",
+    js::ProfileEntry::Category::STORAGE);
 
   if (IndexedDatabaseManager::IsMainProcess()) {
     return AsyncConnectionHelper::Dispatch(aDatabaseThread);
   }
 
   // If we've been invalidated then there's no point sending anything to the
   // parent process.
   if (mCursor->Transaction()->Database()->IsInvalidated()) {
@@ -1014,17 +1015,18 @@ CursorHelper::Dispatch(nsIEventTarget* a
 }
 
 nsresult
 ContinueHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "ContinueHelper::DoDatabaseWork");
+  PROFILER_LABEL("ContinueHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   // We need to pick a query based on whether or not the cursor's mContinueToKey
   // is set. If it is unset then othing was passed to continue so we'll grab the
   // next item in the database that is greater than (less than, if we're running
   // a PREV cursor) the current key. If it is set then a key was passed to
   // continue so we'll grab the next item in the database that is greater than
   // (less than, if we're running a PREV cursor) or equal to the key that was
   // specified.
@@ -1096,36 +1098,36 @@ ContinueHelper::ReleaseMainThreadObjects
 }
 
 nsresult
 ContinueHelper::PackArgumentsForParentProcess(CursorRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "ContinueHelper::PackArgumentsForParentProcess");
+  PROFILER_MAIN_THREAD_LABEL("ContinueHelper", "PackArgumentsForParentProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   ContinueParams params;
 
   params.key() = mCursor->mContinueToKey;
   params.count() = uint32_t(mCount);
 
   aParams = params;
   return NS_OK;
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 ContinueHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "ContinueHelper::SendResponseToChildProcess");
+  PROFILER_MAIN_THREAD_LABEL("ContinueHelper", "SendResponseToChildProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   InfallibleTArray<PBlobParent*> blobsParent;
 
   if (NS_SUCCEEDED(aResultCode)) {
     IDBDatabase* database = mTransaction->Database();
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -797,17 +797,18 @@ NoRequestDatabaseHelper::OnError()
 }
 
 nsresult
 CreateObjectStoreHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "CreateObjectStoreHelper::DoDatabaseWork");
+  PROFILER_LABEL("CreateObjectStoreHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
     NS_WARNING("Refusing to create additional objectStore because disk space "
                "is low!");
     return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
   }
 
   nsCOMPtr<mozIStorageStatement> stmt =
@@ -857,17 +858,18 @@ CreateObjectStoreHelper::ReleaseMainThre
 }
 
 nsresult
 DeleteObjectStoreHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "DeleteObjectStoreHelper::DoDatabaseWork");
+  PROFILER_LABEL("DeleteObjectStoreHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCOMPtr<mozIStorageStatement> stmt =
     mTransaction->GetCachedStatement(NS_LITERAL_CSTRING(
     "DELETE FROM object_store "
     "WHERE id = :id "
   ));
   IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
@@ -883,17 +885,18 @@ DeleteObjectStoreHelper::DoDatabaseWork(
 }
 
 nsresult
 CreateFileHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "CreateFileHelper::DoDatabaseWork");
+  PROFILER_LABEL("CreateFileHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
     NS_WARNING("Refusing to create file because disk space is low!");
     return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
   }
 
   FileManager* fileManager = mDatabase->Manager();
 
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -1028,17 +1028,18 @@ IndexHelper::ReleaseMainThreadObjects()
   AsyncConnectionHelper::ReleaseMainThreadObjects();
 }
 
 nsresult
 IndexHelper::Dispatch(nsIEventTarget* aDatabaseThread)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB", "IndexHelper::Dispatch");
+  PROFILER_MAIN_THREAD_LABEL("IndexHelper", "Dispatch",
+    js::ProfileEntry::Category::STORAGE);
 
   if (IndexedDatabaseManager::IsMainProcess()) {
     return AsyncConnectionHelper::Dispatch(aDatabaseThread);
   }
 
   // If we've been invalidated then there's no point sending anything to the
   // parent process.
   if (mIndex->ObjectStore()->Transaction()->Database()->IsInvalidated()) {
@@ -1065,17 +1066,18 @@ IndexHelper::Dispatch(nsIEventTarget* aD
 
 nsresult
 GetKeyHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(mKeyRange, "Must have a key range here!");
 
-  PROFILER_LABEL("IndexedDB", "GetKeyHelper::DoDatabaseWork");
+  PROFILER_LABEL("GetKeyHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCString indexTable;
   if (mIndex->IsUnique()) {
     indexTable.AssignLiteral("unique_index_data");
   }
   else {
     indexTable.AssignLiteral("index_data");
   }
@@ -1131,35 +1133,35 @@ GetKeyHelper::ReleaseMainThreadObjects()
 
 nsresult
 GetKeyHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(mKeyRange, "This should never be null!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetKeyHelper::PackArgumentsForParentProcess");
+  PROFILER_MAIN_THREAD_LABEL("GetKeyHelper", "PackArgumentsForParentProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   GetKeyParams params;
 
   mKeyRange->ToSerializedKeyRange(params.keyRange());
 
   aParams = params;
   return NS_OK;
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 GetKeyHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetKeyHelper::SendResponseToChildProcess");
+  PROFILER_MAIN_THREAD_LABEL("GetKeyHelper", "SendResponseToChildProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   ResponseValue response;
   if (NS_FAILED(aResultCode)) {
     response = aResultCode;
   }
@@ -1189,17 +1191,18 @@ GetKeyHelper::UnpackResponseFromParentPr
 
 nsresult
 GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(mKeyRange, "Must have a key range here!");
 
-  PROFILER_LABEL("IndexedDB", "GetHelper::DoDatabaseWork [IDBIndex.cpp]");
+  PROFILER_LABEL("GetHelper", "DoDatabaseWork [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCString indexTable;
   if (mIndex->IsUnique()) {
     indexTable.AssignLiteral("unique_index_data");
   }
   else {
     indexTable.AssignLiteral("index_data");
   }
@@ -1263,37 +1266,35 @@ GetHelper::ReleaseMainThreadObjects()
 
 nsresult
 GetHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(mKeyRange, "This should never be null!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetHelper::PackArgumentsForParentProcess "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   GetParams params;
 
   mKeyRange->ToSerializedKeyRange(params.keyRange());
 
   aParams = params;
   return NS_OK;
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 GetHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetHelper::SendResponseToChildProcess "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetHelper", "SendResponseToChildProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   InfallibleTArray<PBlobParent*> blobsParent;
 
   if (NS_SUCCEEDED(aResultCode)) {
     IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
@@ -1357,18 +1358,18 @@ GetHelper::UnpackResponseFromParentProce
 }
 
 nsresult
 GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
 
-  PROFILER_LABEL("IndexedDB",
-                 "GetAllKeysHelper::DoDatabaseWork [IDBIndex.cpp]");
+  PROFILER_LABEL("GetAllKeysHelper", "DoDatabaseWork [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCString tableName;
   if (mIndex->IsUnique()) {
     tableName.AssignLiteral("unique_index_data");
   }
   else {
     tableName.AssignLiteral("index_data");
   }
@@ -1424,19 +1425,18 @@ GetAllKeysHelper::DoDatabaseWork(mozISto
 
 nsresult
 GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
                                    JS::MutableHandle<JS::Value> aVal)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mKeys.Length() <= mLimit);
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetAllKeysHelper::GetSuccessResult "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetAllKeysHelper", "GetSuccessResult [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   nsTArray<Key> keys;
   mKeys.SwapElements(keys);
 
   JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
   if (!array) {
     IDB_WARNING("Failed to make array!");
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@@ -1471,19 +1471,18 @@ GetAllKeysHelper::GetSuccessResult(JSCon
 }
 
 nsresult
 GetAllKeysHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!IndexedDatabaseManager::IsMainProcess());
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetAllKeysHelper::PackArgumentsForParentProcess "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetAllKeysHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   GetAllKeysParams params;
 
   if (mKeyRange) {
     KeyRange keyRange;
     mKeyRange->ToSerializedKeyRange(keyRange);
     params.optionalKeyRange() = keyRange;
   }
@@ -1498,19 +1497,18 @@ GetAllKeysHelper::PackArgumentsForParent
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 GetAllKeysHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetAllKeysHelper::SendResponseToChildProcess "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetAllKeysHelper", "SendResponseToChildProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   ResponseValue response;
   if (NS_FAILED(aResultCode)) {
     response = aResultCode;
   }
@@ -1540,17 +1538,18 @@ GetAllKeysHelper::UnpackResponseFromPare
 }
 
 nsresult
 GetAllHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "GetAllHelper::DoDatabaseWork [IDBIndex.cpp]");
+  PROFILER_LABEL("GetAllHelper", "DoDatabaseWork [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCString indexTable;
   if (mIndex->IsUnique()) {
     indexTable.AssignLiteral("unique_index_data");
   }
   else {
     indexTable.AssignLiteral("index_data");
   }
@@ -1632,19 +1631,18 @@ GetAllHelper::ReleaseMainThreadObjects()
 }
 
 nsresult
 GetAllHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetAllHelper::PackArgumentsForParentProcess "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetAllHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   GetAllParams params;
 
   if (mKeyRange) {
     KeyRange keyRange;
     mKeyRange->ToSerializedKeyRange(keyRange);
     params.optionalKeyRange() = keyRange;
   }
@@ -1659,19 +1657,18 @@ GetAllHelper::PackArgumentsForParentProc
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 GetAllHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetAllHelper::SendResponseToChildProcess "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetAllHelper", "SendResponseToChildProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   GetAllResponse getAllResponse;
 
   if (NS_SUCCEEDED(aResultCode) && !mCloneReadInfos.IsEmpty()) {
     IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
@@ -1765,17 +1762,18 @@ GetAllHelper::UnpackResponseFromParentPr
 
 nsresult
 OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(aConnection, "Passed a null connection!");
 
-  PROFILER_LABEL("IndexedDB", "OpenKeyCursorHelper::DoDatabaseWork");
+  PROFILER_LABEL("OpenKeyCursorHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCString table;
   if (mIndex->IsUnique()) {
     table.AssignLiteral("unique_index_data");
   }
   else {
     table.AssignLiteral("index_data");
   }
@@ -1974,19 +1972,18 @@ OpenKeyCursorHelper::ReleaseMainThreadOb
 }
 
 nsresult
 OpenKeyCursorHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenKeyCursorHelper::"
-                             "PackArgumentsForParentProcess [IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("OpenKeyCursorHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   OpenKeyCursorParams params;
 
   if (mKeyRange) {
     KeyRange keyRange;
     mKeyRange->ToSerializedKeyRange(keyRange);
     params.optionalKeyRange() = keyRange;
   }
@@ -2002,18 +1999,18 @@ OpenKeyCursorHelper::PackArgumentsForPar
 
 AsyncConnectionHelper::ChildProcessSendResult
 OpenKeyCursorHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenKeyCursorHelper::SendResponseToChildProcess");
+  PROFILER_MAIN_THREAD_LABEL("OpenKeyCursorHelper", "SendResponseToChildProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   if (NS_SUCCEEDED(aResultCode)) {
     nsresult rv = EnsureCursor();
     if (NS_FAILED(rv)) {
       NS_WARNING("EnsureCursor failed!");
@@ -2099,18 +2096,18 @@ OpenKeyCursorHelper::UnpackResponseFromP
 
 nsresult
 OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(aConnection, "Passed a null connection!");
 
-  PROFILER_LABEL("IndexedDB",
-                 "OpenCursorHelper::DoDatabaseWork [IDBIndex.cpp]");
+  PROFILER_LABEL("OpenCursorHelper", "DoDatabaseWork [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCString indexTable;
   if (mIndex->IsUnique()) {
     indexTable.AssignLiteral("unique_index_data");
   }
   else {
     indexTable.AssignLiteral("index_data");
   }
@@ -2317,19 +2314,18 @@ OpenCursorHelper::ReleaseMainThreadObjec
 }
 
 nsresult
 OpenCursorHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenCursorHelper::PackArgumentsForParentProcess "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("OpenCursorHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   OpenCursorParams params;
 
   if (mKeyRange) {
     KeyRange keyRange;
     mKeyRange->ToSerializedKeyRange(keyRange);
     params.optionalKeyRange() = keyRange;
   }
@@ -2345,19 +2341,18 @@ OpenCursorHelper::PackArgumentsForParent
 
 AsyncConnectionHelper::ChildProcessSendResult
 OpenCursorHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenCursorHelper::SendResponseToChildProcess "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("OpenCursorHelper", "SendResponseToChildProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   InfallibleTArray<PBlobParent*> blobsParent;
 
   if (NS_SUCCEEDED(aResultCode)) {
     IDBDatabase* database = mIndex->ObjectStore()->Transaction()->Database();
@@ -2432,17 +2427,18 @@ OpenCursorHelper::SendResponseToChildPro
 }
 
 nsresult
 CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "CountHelper::DoDatabaseWork [IDBIndex.cpp]");
+  PROFILER_LABEL("CountHelper", "DoDatabaseWork [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCString table;
   if (mIndex->IsUnique()) {
     table.AssignLiteral("unique_index_data");
   }
   else {
     table.AssignLiteral("index_data");
   }
@@ -2511,19 +2507,18 @@ CountHelper::ReleaseMainThreadObjects()
 }
 
 nsresult
 CountHelper::PackArgumentsForParentProcess(IndexRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "CountHelper::PackArgumentsForParentProcess "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("CountHelper", "PackArgumentsForParentProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   CountParams params;
 
   if (mKeyRange) {
     KeyRange keyRange;
     mKeyRange->ToSerializedKeyRange(keyRange);
     params.optionalKeyRange() = keyRange;
   }
@@ -2536,19 +2531,18 @@ CountHelper::PackArgumentsForParentProce
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 CountHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "CountHelper::SendResponseToChildProcess "
-                             "[IDBIndex.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("CountHelper", "SendResponseToChildProcess [IDBIndex.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   ResponseValue response;
   if (NS_FAILED(aResultCode)) {
     response = aResultCode;
   }
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1076,17 +1076,18 @@ IDBObjectStore::UpdateIndexes(IDBTransac
                               const Key& aObjectStoreKey,
                               bool aOverwrite,
                               int64_t aObjectDataId,
                               const nsTArray<IndexUpdateInfo>& aUpdateInfoArray)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "IDBObjectStore::UpdateIndexes");
+  PROFILER_LABEL("IDBObjectStore", "UpdateIndexes",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv;
 
   NS_ASSERTION(aObjectDataId != INT64_MIN, "Bad objectData id!");
 
   NS_NAMED_LITERAL_CSTRING(objectDataId, "object_data_id");
 
   if (aOverwrite) {
@@ -1181,18 +1182,18 @@ IDBObjectStore::GetStructuredCloneReadIn
                                            uint32_t aDataIndex,
                                            uint32_t aFileIdsIndex,
                                            IDBDatabase* aDatabase,
                                            StructuredCloneReadInfo& aInfo)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB",
-                 "IDBObjectStore::GetStructuredCloneReadInfoFromStatement");
+  PROFILER_LABEL("IDBObjectStore", "GetStructuredCloneReadInfoFromStatement",
+    js::ProfileEntry::Category::STORAGE);
 
 #ifdef DEBUG
   {
     int32_t type;
     NS_ASSERTION(NS_SUCCEEDED(aStatement->GetTypeOfIndex(aDataIndex, &type)) &&
                  type == mozIStorageStatement::VALUE_TYPE_BLOB,
                  "Bad value type!");
   }
@@ -2972,17 +2973,18 @@ IDBObjectStore::OpenKeyCursor(JSContext*
 }
 
 inline nsresult
 CopyData(nsIInputStream* aInputStream, nsIOutputStream* aOutputStream)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "CopyData");
+  PROFILER_LABEL("IDBObjectStore", "CopyData",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv;
 
   do {
     char copyBuffer[FILE_COPY_BUFFER_SIZE];
 
     uint32_t numRead;
     rv = aInputStream->Read(copyBuffer, sizeof(copyBuffer), &numRead);
@@ -3015,17 +3017,18 @@ ObjectStoreHelper::ReleaseMainThreadObje
   AsyncConnectionHelper::ReleaseMainThreadObjects();
 }
 
 nsresult
 ObjectStoreHelper::Dispatch(nsIEventTarget* aDatabaseThread)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB", "ObjectStoreHelper::Dispatch");
+  PROFILER_MAIN_THREAD_LABEL("ObjectStoreHelper", "Dispatch",
+    js::ProfileEntry::Category::STORAGE);
 
   if (IndexedDatabaseManager::IsMainProcess()) {
     return AsyncConnectionHelper::Dispatch(aDatabaseThread);
   }
 
   // If we've been invalidated then there's no point sending anything to the
   // parent process.
   if (mObjectStore->Transaction()->Database()->IsInvalidated()) {
@@ -3101,17 +3104,18 @@ ReinterpretDoubleAsUInt64(double d)
 
 nsresult
 AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(aConnection, "Passed a null connection!");
 
-  PROFILER_LABEL("IndexedDB", "AddHelper::DoDatabaseWork");
+  PROFILER_LABEL("AddHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
     NS_WARNING("Refusing to add more data because disk space is low!");
     return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
   }
 
   nsresult rv;
   bool keyUnset = mKey.IsUnset();
@@ -3316,18 +3320,18 @@ AddHelper::ReleaseMainThreadObjects()
 }
 
 nsresult
 AddHelper::PackArgumentsForParentProcess(ObjectStoreRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "AddHelper::PackArgumentsForParentProcess");
+  PROFILER_MAIN_THREAD_LABEL("AddHelper", "PackArgumentsForParentProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   AddPutParams commonParams;
   commonParams.cloneInfo() = mCloneWriteInfo;
   commonParams.key() = mKey;
   commonParams.indexUpdateInfos().AppendElements(mIndexUpdateInfo);
 
   const nsTArray<StructuredCloneFile>& files = mCloneWriteInfo.mFiles;
 
@@ -3371,18 +3375,18 @@ AddHelper::PackArgumentsForParentProcess
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 AddHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "AddHelper::SendResponseToChildProcess");
+  PROFILER_MAIN_THREAD_LABEL("AddHelper", "SendResponseToChildProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   ResponseValue response;
   if (NS_FAILED(aResultCode)) {
     response =  aResultCode;
   }
@@ -3420,17 +3424,18 @@ AddHelper::UnpackResponseFromParentProce
 
 nsresult
 GetHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(mKeyRange, "Must have a key range here!");
 
-  PROFILER_LABEL("IndexedDB", "GetHelper::DoDatabaseWork [IDBObjectStore.cpp]");
+  PROFILER_LABEL("GetHelper", "DoDatabaseWork [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCString keyRangeClause;
   mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("key_value"), keyRangeClause);
 
   NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
 
   nsCString query = NS_LITERAL_CSTRING("SELECT data, file_ids FROM object_data "
                                        "WHERE object_store_id = :osid") +
@@ -3483,37 +3488,35 @@ GetHelper::ReleaseMainThreadObjects()
 
 nsresult
 GetHelper::PackArgumentsForParentProcess(ObjectStoreRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(mKeyRange, "This should never be null!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetHelper::PackArgumentsForParentProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetHelper", "PackArgumentsForParentProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   GetParams params;
 
   mKeyRange->ToSerializedKeyRange(params.keyRange());
 
   aParams = params;
   return NS_OK;
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 GetHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetHelper::SendResponseToChildProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetHelper", "SendResponseToChildProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   InfallibleTArray<PBlobParent*> blobsParent;
 
   if (NS_SUCCEEDED(aResultCode)) {
     IDBDatabase* database = mObjectStore->Transaction()->Database();
@@ -3578,17 +3581,18 @@ GetHelper::UnpackResponseFromParentProce
 
 nsresult
 DeleteHelper::DoDatabaseWork(mozIStorageConnection* /*aConnection */)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(mKeyRange, "Must have a key range here!");
 
-  PROFILER_LABEL("IndexedDB", "DeleteHelper::DoDatabaseWork");
+  PROFILER_LABEL("DeleteHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCString keyRangeClause;
   mKeyRange->GetBindingClause(NS_LITERAL_CSTRING("key_value"), keyRangeClause);
 
   NS_ASSERTION(!keyRangeClause.IsEmpty(), "Huh?!");
 
   nsCString query = NS_LITERAL_CSTRING("DELETE FROM object_data "
                                        "WHERE object_store_id = :osid") +
@@ -3622,35 +3626,35 @@ DeleteHelper::GetSuccessResult(JSContext
 
 nsresult
 DeleteHelper::PackArgumentsForParentProcess(ObjectStoreRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(mKeyRange, "This should never be null!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "DeleteHelper::PackArgumentsForParentProcess");
+  PROFILER_MAIN_THREAD_LABEL("DeleteHelper", "PackArgumentsForParentProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   DeleteParams params;
 
   mKeyRange->ToSerializedKeyRange(params.keyRange());
 
   aParams = params;
   return NS_OK;
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 DeleteHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "DeleteHelper::SendResponseToChildProcess");
+  PROFILER_MAIN_THREAD_LABEL("DeleteHelper", "SendResponseToChildProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   ResponseValue response;
   if (NS_FAILED(aResultCode)) {
     response = aResultCode;
   }
@@ -3677,17 +3681,18 @@ DeleteHelper::UnpackResponseFromParentPr
 
 nsresult
 ClearHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(aConnection, "Passed a null connection!");
 
-  PROFILER_LABEL("IndexedDB", "ClearHelper::DoDatabaseWork");
+  PROFILER_LABEL("ClearHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCOMPtr<mozIStorageStatement> stmt =
     mTransaction->GetCachedStatement(
       NS_LITERAL_CSTRING("DELETE FROM object_data "
                          "WHERE object_store_id = :osid"));
   IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   mozStorageStatementScoper scoper(stmt);
@@ -3703,31 +3708,31 @@ ClearHelper::DoDatabaseWork(mozIStorageC
 }
 
 nsresult
 ClearHelper::PackArgumentsForParentProcess(ObjectStoreRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "ClearHelper::PackArgumentsForParentProcess");
+  PROFILER_MAIN_THREAD_LABEL("ClearHelper", "PackArgumentsForParentProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   aParams = ClearParams();
   return NS_OK;
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 ClearHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "ClearHelper::SendResponseToChildProcess");
+  PROFILER_MAIN_THREAD_LABEL("ClearHelper", "SendResponseToChildProcess",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   ResponseValue response;
   if (NS_FAILED(aResultCode)) {
     response = aResultCode;
   }
@@ -3753,18 +3758,18 @@ ClearHelper::UnpackResponseFromParentPro
 }
 
 nsresult
 OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB",
-                 "OpenCursorHelper::DoDatabaseWork [IDBObjectStore.cpp]");
+  PROFILER_LABEL("OpenCursorHelper", "DoDatabaseWork [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   NS_NAMED_LITERAL_CSTRING(keyValue, "key_value");
 
   nsCString keyRangeClause;
   if (mKeyRange) {
     mKeyRange->GetBindingClause(keyValue, keyRangeClause);
   }
 
@@ -3938,19 +3943,18 @@ OpenCursorHelper::ReleaseMainThreadObjec
 
 nsresult
 OpenCursorHelper::PackArgumentsForParentProcess(
                                               ObjectStoreRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenCursorHelper::PackArgumentsForParentProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("OpenCursorHelper", "PackArgumentsForParentProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   OpenCursorParams params;
 
   if (mKeyRange) {
     KeyRange keyRange;
     mKeyRange->ToSerializedKeyRange(keyRange);
     params.optionalKeyRange() = keyRange;
   }
@@ -3966,19 +3970,18 @@ OpenCursorHelper::PackArgumentsForParent
 
 AsyncConnectionHelper::ChildProcessSendResult
 OpenCursorHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(!mCursor, "Shouldn't have this yet!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenCursorHelper::SendResponseToChildProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("OpenCursorHelper", "SendResponseToChildProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   InfallibleTArray<PBlobParent*> blobsParent;
 
   if (NS_SUCCEEDED(aResultCode)) {
     IDBDatabase* database = mObjectStore->Transaction()->Database();
@@ -4090,18 +4093,18 @@ OpenCursorHelper::UnpackResponseFromPare
 }
 
 nsresult
 OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
 
-  PROFILER_LABEL("IndexedDB",
-                 "OpenKeyCursorHelper::DoDatabaseWork [IDBObjectStore.cpp]");
+  PROFILER_LABEL("OpenKeyCursorHelper", "DoDatabaseWork [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   NS_NAMED_LITERAL_CSTRING(keyValue, "key_value");
   NS_NAMED_LITERAL_CSTRING(id, "id");
   NS_NAMED_LITERAL_CSTRING(openLimit, " LIMIT ");
 
   nsAutoCString queryStart = NS_LITERAL_CSTRING("SELECT ") + keyValue +
                              NS_LITERAL_CSTRING(" FROM object_data WHERE "
                                                 "object_store_id = :") +
@@ -4207,19 +4210,18 @@ OpenKeyCursorHelper::DoDatabaseWork(mozI
   return NS_OK;
 }
 
 nsresult
 OpenKeyCursorHelper::EnsureCursor()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenKeyCursorHelper::EnsureCursor "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("OpenKeyCursorHelper", "EnsureCursor [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   if (mCursor || mKey.IsUnset()) {
     return NS_OK;
   }
 
   mCursor = IDBCursor::Create(mRequest, mTransaction, mObjectStore, mDirection,
                               mRangeKey, mContinueQuery, mContinueToQuery,
                               mKey);
@@ -4229,19 +4231,18 @@ OpenKeyCursorHelper::EnsureCursor()
 }
 
 nsresult
 OpenKeyCursorHelper::GetSuccessResult(JSContext* aCx,
                                       JS::MutableHandle<JS::Value> aVal)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenKeyCursorHelper::GetSuccessResult "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("OpenKeyCursorHelper", "GetSuccessResult [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv = EnsureCursor();
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mCursor) {
     rv = WrapNative(aCx, mCursor, aVal);
     IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
   }
@@ -4265,20 +4266,18 @@ OpenKeyCursorHelper::ReleaseMainThreadOb
 
 nsresult
 OpenKeyCursorHelper::PackArgumentsForParentProcess(
                                               ObjectStoreRequestParams& aParams)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!IndexedDatabaseManager::IsMainProcess());
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenKeyCursorHelper::"
-                             "PackArgumentsForParentProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("OpenKeyCursorHelper", "PackArgumentsForParentProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   OpenKeyCursorParams params;
 
   if (mKeyRange) {
     KeyRange keyRange;
     mKeyRange->ToSerializedKeyRange(keyRange);
     params.optionalKeyRange() = keyRange;
   }
@@ -4294,19 +4293,18 @@ OpenKeyCursorHelper::PackArgumentsForPar
 
 AsyncConnectionHelper::ChildProcessSendResult
 OpenKeyCursorHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
   MOZ_ASSERT(!mCursor);
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenKeyCursorHelper::SendResponseToChildProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("OpenKeyCursorHelper", "SendResponseToChildProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   MOZ_ASSERT(actor);
 
   if (NS_SUCCEEDED(aResultCode)) {
     nsresult rv = EnsureCursor();
     if (NS_FAILED(rv)) {
       NS_WARNING("EnsureCursor failed!");
@@ -4360,20 +4358,18 @@ OpenKeyCursorHelper::UnpackResponseFromP
   MOZ_ASSERT(!IndexedDatabaseManager::IsMainProcess());
   MOZ_ASSERT(aResponseValue.type() == ResponseValue::TOpenCursorResponse);
   MOZ_ASSERT(aResponseValue.get_OpenCursorResponse().type() ==
                OpenCursorResponse::Tvoid_t ||
              aResponseValue.get_OpenCursorResponse().type() ==
                OpenCursorResponse::TPIndexedDBCursorChild);
   MOZ_ASSERT(!mCursor);
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenKeyCursorHelper::"
-                             "UnpackResponseFromParentProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("OpenKeyCursorHelper", "UnpackResponseFromParentProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   const OpenCursorResponse& response =
     aResponseValue.get_OpenCursorResponse();
 
   switch (response.type()) {
     case OpenCursorResponse::Tvoid_t:
       break;
 
@@ -4395,17 +4391,18 @@ OpenKeyCursorHelper::UnpackResponseFromP
 }
 
 nsresult
 CreateIndexHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "CreateIndexHelper::DoDatabaseWork");
+  PROFILER_LABEL("CreateIndexHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
     NS_WARNING("Refusing to create index because disk space is low!");
     return NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
   }
 
   // Insert the data into the database.
   nsCOMPtr<mozIStorageStatement> stmt =
@@ -4566,17 +4563,18 @@ CreateIndexHelper::DestroyTLSEntry(void*
 }
 
 nsresult
 DeleteIndexHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "DeleteIndexHelper::DoDatabaseWork");
+  PROFILER_LABEL("DeleteIndexHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCOMPtr<mozIStorageStatement> stmt =
     mTransaction->GetCachedStatement(
       "DELETE FROM object_store_index "
       "WHERE name = :name "
     );
   IDB_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
@@ -4593,18 +4591,18 @@ DeleteIndexHelper::DoDatabaseWork(mozISt
 }
 
 nsresult
 GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB",
-                 "GetAllHelper::DoDatabaseWork [IDBObjectStore.cpp]");
+  PROFILER_LABEL("GetAllHelper", "DoDatabaseWork [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
   NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key");
 
   nsAutoCString keyRangeClause;
   if (mKeyRange) {
     if (!mKeyRange->Lower().IsUnset()) {
       keyRangeClause = NS_LITERAL_CSTRING(" AND key_value");
@@ -4707,19 +4705,18 @@ GetAllHelper::ReleaseMainThreadObjects()
 }
 
 nsresult
 GetAllHelper::PackArgumentsForParentProcess(ObjectStoreRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetAllHelper::PackArgumentsForParentProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetAllHelper", "PackArgumentsForParentProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   GetAllParams params;
 
   if (mKeyRange) {
     KeyRange keyRange;
     mKeyRange->ToSerializedKeyRange(keyRange);
     params.optionalKeyRange() = keyRange;
   }
@@ -4734,19 +4731,18 @@ GetAllHelper::PackArgumentsForParentProc
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 GetAllHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetAllHelper::SendResponseToChildProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetAllHelper", "SendResponseToChildProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   GetAllResponse getAllResponse;
   if (NS_SUCCEEDED(aResultCode) && !mCloneReadInfos.IsEmpty()) {
     IDBDatabase* database = mObjectStore->Transaction()->Database();
     NS_ASSERTION(database, "This should never be null!");
@@ -4835,18 +4831,18 @@ GetAllHelper::UnpackResponseFromParentPr
 }
 
 nsresult
 GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* /* aConnection */)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
 
-  PROFILER_LABEL("IndexedDB",
-                 "GetAllKeysHelper::DoDatabaseWork [IDObjectStore.cpp]");
+  PROFILER_LABEL("GetAllKeysHelper", "DoDatabaseWork [IDObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   NS_NAMED_LITERAL_CSTRING(keyValue, "key_value");
 
   nsAutoCString keyRangeClause;
   if (mKeyRange) {
     mKeyRange->GetBindingClause(keyValue, keyRangeClause);
   }
 
@@ -4899,19 +4895,18 @@ GetAllKeysHelper::DoDatabaseWork(mozISto
 
 nsresult
 GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
                                    JS::MutableHandle<JS::Value> aVal)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mKeys.Length() <= mLimit);
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetAllKeysHelper::GetSuccessResult "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetAllKeysHelper", "GetSuccessResult [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   nsTArray<Key> keys;
   mKeys.SwapElements(keys);
 
   JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
   if (!array) {
     IDB_WARNING("Failed to make array!");
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
@@ -4957,19 +4952,18 @@ GetAllKeysHelper::ReleaseMainThreadObjec
 
 nsresult
 GetAllKeysHelper::PackArgumentsForParentProcess(
                                               ObjectStoreRequestParams& aParams)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!IndexedDatabaseManager::IsMainProcess());
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetAllKeysHelper::PackArgumentsForParentProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetAllKeysHelper", "PackArgumentsForParentProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   GetAllKeysParams params;
 
   if (mKeyRange) {
     KeyRange keyRange;
     mKeyRange->ToSerializedKeyRange(keyRange);
     params.optionalKeyRange() = keyRange;
   } else {
@@ -4983,19 +4977,18 @@ GetAllKeysHelper::PackArgumentsForParent
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 GetAllKeysHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "GetAllKeysHelper::SendResponseToChildProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("GetAllKeysHelper", "SendResponseToChildProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   MOZ_ASSERT(actor);
 
   ResponseValue response;
   if (NS_FAILED(aResultCode)) {
     response = aResultCode;
   }
@@ -5025,18 +5018,18 @@ GetAllKeysHelper::UnpackResponseFromPare
 }
 
 nsresult
 CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB",
-                 "CountHelper::DoDatabaseWork [IDBObjectStore.cpp]");
+  PROFILER_LABEL("CountHelper", "DoDatabaseWork [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
   NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key");
 
   nsAutoCString keyRangeClause;
   if (mKeyRange) {
     if (!mKeyRange->Lower().IsUnset()) {
       keyRangeClause = NS_LITERAL_CSTRING(" AND key_value");
@@ -5110,19 +5103,18 @@ CountHelper::ReleaseMainThreadObjects()
 }
 
 nsresult
 CountHelper::PackArgumentsForParentProcess(ObjectStoreRequestParams& aParams)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "CountHelper::PackArgumentsForParentProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("CountHelper", "PackArgumentsForParentProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   CountParams params;
 
   if (mKeyRange) {
     KeyRange keyRange;
     mKeyRange->ToSerializedKeyRange(keyRange);
     params.optionalKeyRange() = keyRange;
   }
@@ -5135,19 +5127,18 @@ CountHelper::PackArgumentsForParentProce
 }
 
 AsyncConnectionHelper::ChildProcessSendResult
 CountHelper::SendResponseToChildProcess(nsresult aResultCode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "CountHelper::SendResponseToChildProcess "
-                             "[IDBObjectStore.cpp]");
+  PROFILER_MAIN_THREAD_LABEL("CountHelper", "SendResponseToChildProcess [IDBObjectStore.cpp]",
+    js::ProfileEntry::Category::STORAGE);
 
   IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
   NS_ASSERTION(actor, "How did we get this far without an actor?");
 
   ResponseValue response;
   if (NS_FAILED(aResultCode)) {
     response = aResultCode;
   }
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -368,17 +368,18 @@ IDBTransaction::RollbackSavepoint()
 }
 
 nsresult
 IDBTransaction::GetOrCreateConnection(mozIStorageConnection** aResult)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "IDBTransaction::GetOrCreateConnection");
+  PROFILER_LABEL("IDBTransaction", "GetOrCreateConnection",
+    js::ProfileEntry::Category::STORAGE);
 
   if (mDatabase->IsInvalidated()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   if (!mConnection) {
     nsCOMPtr<mozIStorageConnection> connection =
       IDBFactory::GetConnection(mDatabase->FilePath(), mDatabase->Type(),
@@ -787,17 +788,18 @@ CommitHelper::~CommitHelper()
 }
 
 NS_IMPL_ISUPPORTS(CommitHelper, nsIRunnable)
 
 NS_IMETHODIMP
 CommitHelper::Run()
 {
   if (NS_IsMainThread()) {
-    PROFILER_MAIN_THREAD_LABEL("IndexedDB", "CommitHelper::Run");
+    PROFILER_MAIN_THREAD_LABEL("CommitHelper", "Run",
+      js::ProfileEntry::Category::STORAGE);
 
     NS_ASSERTION(mDoomedObjects.IsEmpty(), "Didn't release doomed objects!");
 
     mTransaction->mReadyState = IDBTransaction::DONE;
 
     // Release file infos on the main thread, so they will eventually get
     // destroyed on correct thread.
     mTransaction->ClearCreatedFileInfos();
@@ -855,17 +857,18 @@ CommitHelper::Run()
       mListener->NotifyTransactionPostComplete(mTransaction);
     }
 
     mTransaction = nullptr;
 
     return NS_OK;
   }
 
-  PROFILER_LABEL("IndexedDB", "CommitHelper::Run");
+  PROFILER_LABEL("CommitHelper", "Run",
+    js::ProfileEntry::Category::STORAGE);
 
   IDBDatabase* database = mTransaction->Database();
   if (database->IsInvalidated()) {
     IDB_REPORT_INTERNAL_ERR();
     mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   if (mConnection) {
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -120,17 +120,18 @@ GetDatabaseFilename(const nsAString& aNa
 }
 
 nsresult
 CreateFileTables(mozIStorageConnection* aDBConn)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "CreateFileTables");
+  PROFILER_LABEL("OpenDatabaseHelper", "CreateFileTables",
+    js::ProfileEntry::Category::STORAGE);
 
   // Table `file`
   nsresult rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE file ("
       "id INTEGER PRIMARY KEY, "
       "refcount INTEGER NOT NULL"
     ");"
   ));
@@ -183,17 +184,18 @@ CreateFileTables(mozIStorageConnection* 
 
 nsresult
 CreateTables(mozIStorageConnection* aDBConn)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(aDBConn, "Passing a null database connection!");
 
-  PROFILER_LABEL("IndexedDB", "CreateTables");
+  PROFILER_LABEL("OpenDatabaseHelper", "CreateTables",
+    js::ProfileEntry::Category::STORAGE);
 
   // Table `database`
   nsresult rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TABLE database ("
       "name TEXT NOT NULL, "
       "version INTEGER NOT NULL DEFAULT 0"
     ");"
   ));
@@ -299,17 +301,18 @@ CreateTables(mozIStorageConnection* aDBC
 }
 
 nsresult
 UpgradeSchemaFrom4To5(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom4To5");
+  PROFILER_LABEL("OpenDatabaseHelper", "UpgradeSchemaFrom4To5",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv;
 
   // All we changed is the type of the version column, so lets try to
   // convert that to an integer, and if we fail, set it to 0.
   nsCOMPtr<mozIStorageStatement> stmt;
   rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
     "SELECT name, version, dataVersion "
@@ -388,17 +391,18 @@ UpgradeSchemaFrom4To5(mozIStorageConnect
 }
 
 nsresult
 UpgradeSchemaFrom5To6(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom5To6");
+  PROFILER_LABEL("OpenDatabaseHelper", "UpgradeSchemaFrom5To6",
+    js::ProfileEntry::Category::STORAGE);
 
   // First, drop all the indexes we're no longer going to use.
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "DROP INDEX key_index;"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
@@ -746,17 +750,18 @@ UpgradeSchemaFrom5To6(mozIStorageConnect
 }
 
 nsresult
 UpgradeSchemaFrom6To7(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom6To7");
+  PROFILER_LABEL("OpenDatabaseHelper", "UpgradeSchemaFrom6To7",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TEMPORARY TABLE temp_upgrade ("
       "id, "
       "name, "
       "key_path, "
       "auto_increment"
     ");"
@@ -805,17 +810,18 @@ UpgradeSchemaFrom6To7(mozIStorageConnect
 }
 
 nsresult
 UpgradeSchemaFrom7To8(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom7To8");
+  PROFILER_LABEL("OpenDatabaseHelper", "UpgradeSchemaFrom7To8",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TEMPORARY TABLE temp_upgrade ("
       "id, "
       "object_store_id, "
       "name, "
       "key_path, "
       "unique_index, "
@@ -877,17 +883,18 @@ class CompressDataBlobsFunction MOZ_FINA
 {
 public:
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD
   OnFunctionCall(mozIStorageValueArray* aArguments,
                  nsIVariant** aResult)
   {
-    PROFILER_LABEL("IndexedDB", "CompressDataBlobsFunction::OnFunctionCall");
+    PROFILER_LABEL("CompressDataBlobsFunction", "OnFunctionCall",
+      js::ProfileEntry::Category::STORAGE);
 
     uint32_t argc;
     nsresult rv = aArguments->GetNumEntries(&argc);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (argc != 1) {
       NS_WARNING("Don't call me with the wrong number of arguments!");
       return NS_ERROR_UNEXPECTED;
@@ -927,17 +934,18 @@ public:
 NS_IMPL_ISUPPORTS(CompressDataBlobsFunction, mozIStorageFunction)
 
 nsresult
 UpgradeSchemaFrom8To9_0(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom8To9_0");
+  PROFILER_LABEL("OpenDatabaseHelper", "UpgradeSchemaFrom8To9_0",
+    js::ProfileEntry::Category::STORAGE);
 
   // We no longer use the dataVersion column.
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "UPDATE database SET dataVersion = 0;"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<mozIStorageFunction> compressor = new CompressDataBlobsFunction();
@@ -968,17 +976,18 @@ UpgradeSchemaFrom8To9_0(mozIStorageConne
 }
 
 nsresult
 UpgradeSchemaFrom9_0To10_0(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom9_0To10_0");
+  PROFILER_LABEL("OpenDatabaseHelper", "UpgradeSchemaFrom9_0To10_0",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "ALTER TABLE object_data ADD COLUMN file_ids TEXT;"
   ));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "ALTER TABLE ai_object_data ADD COLUMN file_ids TEXT;"
@@ -995,17 +1004,18 @@ UpgradeSchemaFrom9_0To10_0(mozIStorageCo
 }
 
 nsresult
 UpgradeSchemaFrom10_0To11_0(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom10_0To11_0");
+  PROFILER_LABEL("OpenDatabaseHelper", "UpgradeSchemaFrom10_0To11_0",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "CREATE TEMPORARY TABLE temp_upgrade ("
       "id, "
       "object_store_id, "
       "name, "
       "key_path, "
       "unique_index, "
@@ -1134,17 +1144,18 @@ class EncodeKeysFunction MOZ_FINAL : pub
 {
 public:
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD
   OnFunctionCall(mozIStorageValueArray* aArguments,
                  nsIVariant** aResult)
   {
-    PROFILER_LABEL("IndexedDB", "EncodeKeysFunction::OnFunctionCall");
+    PROFILER_LABEL("EncodeKeysFunction", "OnFunctionCall",
+      js::ProfileEntry::Category::STORAGE);
 
     uint32_t argc;
     nsresult rv = aArguments->GetNumEntries(&argc);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (argc != 1) {
       NS_WARNING("Don't call me with the wrong number of arguments!");
       return NS_ERROR_UNEXPECTED;
@@ -1185,17 +1196,18 @@ public:
 NS_IMPL_ISUPPORTS(EncodeKeysFunction, mozIStorageFunction)
 
 nsresult
 UpgradeSchemaFrom11_0To12_0(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom11_0To12_0");
+  PROFILER_LABEL("OpenDatabaseHelper", "UpgradeSchemaFrom11_0To12_0",
+    js::ProfileEntry::Category::STORAGE);
 
   NS_NAMED_LITERAL_CSTRING(encoderName, "encode");
 
   nsCOMPtr<mozIStorageFunction> encoder = new EncodeKeysFunction();
 
   nsresult rv = aConnection->CreateFunction(encoderName, 1, encoder);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1402,17 +1414,18 @@ UpgradeSchemaFrom11_0To12_0(mozIStorageC
 
 nsresult
 UpgradeSchemaFrom12_0To13_0(mozIStorageConnection* aConnection,
                             bool* aVacuumNeeded)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "UpgradeSchemaFrom12_0To13_0");
+  PROFILER_LABEL("OpenDatabaseHelper", "UpgradeSchemaFrom12_0To13_0",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv;
 
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
   int32_t defaultPageSize;
   rv = aConnection->GetDefaultPageSize(&defaultPageSize);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1622,17 +1635,18 @@ public:
 
     mWaitingDatabases.SwapElements(aWaitingDatabases);
   }
 
   NS_IMETHOD Run()
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-    PROFILER_MAIN_THREAD_LABEL("IndexedDB", "VersionChangeEventsRunnable::Run");
+    PROFILER_MAIN_THREAD_LABEL("OpenDatabaseHelper", "VersionChangeEventsRunnable::Run",
+      js::ProfileEntry::Category::STORAGE);
 
     // Fire version change events at all of the databases that are not already
     // closed. Also kick bfcached documents out of bfcache.
     uint32_t count = mWaitingDatabases.Length();
     for (uint32_t index = 0; index < count; index++) {
       IDBDatabase* database =
         IDBDatabase::FromStorage(mWaitingDatabases[index]);
       NS_ASSERTION(database, "This shouldn't be null!");
@@ -1773,17 +1787,18 @@ OpenDatabaseHelper::RunImmediately()
 }
 
 nsresult
 OpenDatabaseHelper::DoDatabaseWork()
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "OpenDatabaseHelper::DoDatabaseWork");
+  PROFILER_LABEL("OpenDatabaseHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   mState = eFiringEvents; // In case we fail somewhere along the line.
 
   if (QuotaManager::IsShuttingDown()) {
     IDB_REPORT_INTERNAL_ERR();
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
@@ -1926,17 +1941,18 @@ OpenDatabaseHelper::CreateDatabaseConnec
                                         PersistenceType aPersistenceType,
                                         const nsACString& aGroup,
                                         const nsACString& aOrigin,
                                         mozIStorageConnection** aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "OpenDatabaseHelper::CreateDatabaseConnection");
+  PROFILER_LABEL("OpenDatabaseHelper", "CreateDatabaseConnection",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv;
   bool exists;
 
   if (IndexedDatabaseManager::InLowDiskSpaceMode()) {
     rv = aDBFile->Exists(&exists);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2190,17 +2206,18 @@ OpenDatabaseHelper::StartDelete()
 }
 
 NS_IMETHODIMP
 OpenDatabaseHelper::Run()
 {
   NS_ASSERTION(mState != eCreated, "Dispatch was not called?!?");
 
   if (NS_IsMainThread()) {
-    PROFILER_MAIN_THREAD_LABEL("IndexedDB", "OpenDatabaseHelper::Run");
+    PROFILER_MAIN_THREAD_LABEL("OpenDatabaseHelper", "Run",
+      js::ProfileEntry::Category::STORAGE);
 
     if (mState == eOpenPending) {
       if (NS_FAILED(mResultCode)) {
         return RunImmediately();
       }
 
       return DispatchToIOThread();
     }
@@ -2287,17 +2304,18 @@ OpenDatabaseHelper::Run()
                               Nullable<PersistenceType>(mPersistenceType),
                               mDatabaseId);
 
     ReleaseMainThreadObjects();
 
     return NS_OK;
   }
 
-  PROFILER_LABEL("IndexedDB", "OpenDatabaseHelper::Run");
+  PROFILER_LABEL("OpenDatabaseHelper", "Run",
+    js::ProfileEntry::Category::STORAGE);
 
   // We're on the DB thread.
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   IDB_PROFILER_MARK("IndexedDB Request %llu: Beginning database work",
                     "IDBRequest[%llu] DT Start", mRequest->GetSerialNumber());
 
   NS_ASSERTION(mState == eDBWork, "Why are we here?");
@@ -2311,18 +2329,18 @@ OpenDatabaseHelper::Run()
   return NS_DispatchToMainThread(this);
 }
 
 nsresult
 OpenDatabaseHelper::EnsureSuccessResult()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "OpenDatabaseHelper::EnsureSuccessResult");
+  PROFILER_MAIN_THREAD_LABEL("OpenDatabaseHelper", "EnsureSuccessResult",
+    js::ProfileEntry::Category::STORAGE);
 
   nsRefPtr<DatabaseInfo> dbInfo;
   if (DatabaseInfo::Get(mDatabaseId, getter_AddRefs(dbInfo))) {
 
 #ifdef DEBUG
     {
       NS_ASSERTION(dbInfo->name == mName &&
                    dbInfo->version == mCurrentVersion &&
@@ -2456,18 +2474,18 @@ OpenDatabaseHelper::BlockDatabase()
   mDatabase->EnterSetVersionTransaction();
 }
 
 void
 OpenDatabaseHelper::DispatchSuccessEvent()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                              "OpenDatabaseHelper::DispatchSuccessEvent");
+  PROFILER_MAIN_THREAD_LABEL("OpenDatabaseHelper", "DispatchSuccessEvent",
+    js::ProfileEntry::Category::STORAGE);
 
   nsRefPtr<nsIDOMEvent> event =
     CreateGenericEvent(mOpenDBRequest, NS_LITERAL_STRING(SUCCESS_EVT_STR),
                        eDoesNotBubble, eNotCancelable);
   if (!event) {
     NS_ERROR("Failed to create event!");
     return;
   }
@@ -2476,18 +2494,18 @@ OpenDatabaseHelper::DispatchSuccessEvent
   mOpenDBRequest->DispatchEvent(event, &dummy);
 }
 
 void
 OpenDatabaseHelper::DispatchErrorEvent()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                              "OpenDatabaseHelper::DispatchErrorEvent");
+  PROFILER_MAIN_THREAD_LABEL("OpenDatabaseHelper", "DispatchErrorEvent",
+    js::ProfileEntry::Category::STORAGE);
 
   nsRefPtr<nsIDOMEvent> event =
     CreateGenericEvent(mOpenDBRequest, NS_LITERAL_STRING(ERROR_EVT_STR),
                        eDoesBubble, eCancelable);
   if (!event) {
     NS_ERROR("Failed to create event!");
     return;
   }
@@ -2528,17 +2546,18 @@ SetVersionHelper::Init()
 
 nsresult
 SetVersionHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(aConnection, "Passing a null connection!");
 
-  PROFILER_LABEL("IndexedDB", "SetVersionHelper::DoDatabaseWork");
+  PROFILER_LABEL("SetVersionHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCOMPtr<mozIStorageStatement> stmt;
   nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
     "UPDATE database "
     "SET version = :version"
   ), getter_AddRefs(stmt));
   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
@@ -2649,17 +2668,18 @@ NS_IMPL_ISUPPORTS_INHERITED0(DeleteDatab
 
 nsresult
 DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   AssertIsOnIOThread();
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(!aConnection, "How did we get a connection here?");
 
-  PROFILER_LABEL("IndexedDB", "DeleteDatabaseHelper::DoDatabaseWork");
+  PROFILER_LABEL("DeleteDatabaseHelper", "DoDatabaseWork",
+    js::ProfileEntry::Category::STORAGE);
 
   const StoragePrivilege& privilege = mOpenHelper->Privilege();
 
   QuotaManager* quotaManager = QuotaManager::Get();
   NS_ASSERTION(quotaManager, "This should never fail!");
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = quotaManager->GetDirectoryForOrigin(mPersistenceType,
--- a/dom/indexedDB/TransactionThreadPool.cpp
+++ b/dom/indexedDB/TransactionThreadPool.cpp
@@ -149,17 +149,18 @@ TransactionThreadPool::Init()
   return NS_OK;
 }
 
 nsresult
 TransactionThreadPool::Cleanup()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB", "TransactionThreadPool::Cleanup");
+  PROFILER_MAIN_THREAD_LABEL("TransactionThreadPool", "Cleanup",
+    js::ProfileEntry::Category::STORAGE);
 
   nsresult rv = mThreadPool->Shutdown();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Make sure the pool is still accessible while any callbacks generated from
   // the other threads are processed.
   rv = NS_ProcessPendingEvents(nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -201,18 +202,18 @@ TransactionThreadPool::MaybeUnblockTrans
 }
 
 void
 TransactionThreadPool::FinishTransaction(IDBTransaction* aTransaction)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aTransaction, "Null pointer!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "TransactionThreadPool::FinishTransaction");
+  PROFILER_MAIN_THREAD_LABEL("TransactionThreadPool", "FinishTransaction",
+    js::ProfileEntry::Category::STORAGE);
 
   // AddRef here because removing from the hash will call Release.
   nsRefPtr<IDBTransaction> transaction(aTransaction);
 
   const nsACString& databaseId = aTransaction->mDatabase->Id();
 
   DatabaseTransactionInfo* dbTransactionInfo;
   if (!mTransactionsInProgress.Get(databaseId, &dbTransactionInfo)) {
@@ -412,19 +413,18 @@ TransactionThreadPool::CollectTransactio
 }
 
 void
 TransactionThreadPool::AbortTransactionsForDatabase(IDBDatabase* aDatabase)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aDatabase, "Null pointer!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "TransactionThreadPool::"
-                             "AbortTransactionsForDatabase");
+  PROFILER_MAIN_THREAD_LABEL("TransactionThreadPool", "AbortTransactionsForDatabase",
+    js::ProfileEntry::Category::STORAGE);
 
   // Get list of transactions for this database id
   DatabaseTransactionInfo* dbTransactionInfo;
   if (!mTransactionsInProgress.Get(aDatabase->Id(), &dbTransactionInfo)) {
     // If there are no transactions, we're done.
     return;
   }
 
@@ -496,18 +496,18 @@ TransactionThreadPool::HasTransactionsFo
   return info.found;
 }
 
 bool
 TransactionThreadPool::MaybeFireCallback(DatabasesCompleteCallback aCallback)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB",
-                             "TransactionThreadPool::MaybeFireCallback");
+  PROFILER_MAIN_THREAD_LABEL("TransactionThreadPool", "MaybeFireCallback",
+    js::ProfileEntry::Category::STORAGE);
 
   for (uint32_t index = 0; index < aCallback.mDatabases.Length(); index++) {
     IDBDatabase* database = aCallback.mDatabases[index];
     if (!database) {
       MOZ_CRASH();
     }
 
     if (mTransactionsInProgress.Get(database->Id(), nullptr)) {
@@ -568,17 +568,18 @@ TransactionThreadPool::TransactionQueue:
 NS_IMPL_ISUPPORTS(TransactionThreadPool::TransactionQueue, nsIRunnable)
 
 NS_IMETHODIMP
 TransactionThreadPool::TransactionQueue::Run()
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
-  PROFILER_LABEL("IndexedDB", "TransactionQueue::Run");
+  PROFILER_LABEL("TransactionQueue", "Run",
+    js::ProfileEntry::Category::STORAGE);
 
   IDB_PROFILER_MARK("IndexedDB Transaction %llu: Beginning database work",
                     "IDBTransaction[%llu] DT Start",
                     mTransaction->GetSerialNumber());
 
   nsAutoTArray<nsCOMPtr<nsIRunnable>, 10> queue;
   nsCOMPtr<nsIRunnable> finishRunnable;
   bool shouldFinish = false;
@@ -638,17 +639,18 @@ FinishTransactionRunnable::FinishTransac
 
 NS_IMPL_ISUPPORTS(FinishTransactionRunnable, nsIRunnable)
 
 NS_IMETHODIMP
 FinishTransactionRunnable::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  PROFILER_MAIN_THREAD_LABEL("IndexedDB", "FinishTransactionRunnable::Run");
+  PROFILER_MAIN_THREAD_LABEL("FinishTransactionRunnable", "Run",
+    js::ProfileEntry::Category::STORAGE);
 
   if (!gThreadPool) {
     NS_ERROR("Running after shutdown!");
     return NS_ERROR_FAILURE;
   }
 
   gThreadPool->FinishTransaction(mTransaction);
 
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -415,17 +415,18 @@ nsPluginStreamListenerPeer::SetupPluginC
   return rv;
 }
 
 NS_IMETHODIMP
 nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
                                            nsISupports* aContext)
 {
   nsresult rv = NS_OK;
-  PROFILER_LABEL("nsPluginStreamListenerPeer", "OnStartRequest");
+  PROFILER_LABEL("nsPluginStreamListenerPeer", "OnStartRequest",
+    js::ProfileEntry::Category::OTHER);
 
   if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) {
     NS_ASSERTION(mRequests.Count() == 0,
                  "Only our initial stream should be unknown!");
     TrackRequest(request);
   }
 
   if (mHaveFiredOnStartRequest) {
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -886,17 +886,19 @@ PluginModuleParent::NPP_Destroy(NPP inst
     return retval;
 }
 
 NPError
 PluginModuleParent::NPP_NewStream(NPP instance, NPMIMEType type,
                                   NPStream* stream, NPBool seekable,
                                   uint16_t* stype)
 {
-    PROFILER_LABEL("PluginModuleParent", "NPP_NewStream");
+    PROFILER_LABEL("PluginModuleParent", "NPP_NewStream",
+      js::ProfileEntry::Category::OTHER);
+
     PluginInstanceParent* i = InstCast(instance);
     if (!i)
         return NPERR_GENERIC_ERROR;
 
     return i->NPP_NewStream(type, stream, seekable,
                             stype);
 }
 
--- a/dom/quota/QuotaManager.cpp
+++ b/dom/quota/QuotaManager.cpp
@@ -3450,17 +3450,18 @@ OriginClearRunnable::DeleteFiles(QuotaMa
   aQuotaManager->OriginClearCompleted(aPersistenceType, mOriginOrPattern);
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(OriginClearRunnable, nsRunnable)
 
 NS_IMETHODIMP
 OriginClearRunnable::Run()
 {
-  PROFILER_LABEL("Quota", "OriginClearRunnable::Run");
+  PROFILER_LABEL("OriginClearRunnable", "Run",
+    js::ProfileEntry::Category::OTHER);
 
   QuotaManager* quotaManager = QuotaManager::Get();
   NS_ASSERTION(quotaManager, "This should never fail!");
 
   switch (mCallbackState) {
     case Pending: {
       NS_NOTREACHED("Should never get here without being dispatched!");
       return NS_ERROR_UNEXPECTED;
@@ -3725,17 +3726,18 @@ AsyncUsageRunnable::AddToUsage(QuotaMana
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED(AsyncUsageRunnable, nsRunnable, nsIQuotaRequest)
 
 NS_IMETHODIMP
 AsyncUsageRunnable::Run()
 {
-  PROFILER_LABEL("Quota", "AsyncUsageRunnable::Run");
+  PROFILER_LABEL("Quota", "AsyncUsageRunnable::Run",
+    js::ProfileEntry::Category::OTHER);
 
   nsresult rv = RunInternal();
 
   if (!NS_IsMainThread()) {
     if (NS_FAILED(rv)) {
       ResetUsage();
     }
 
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -169,17 +169,19 @@ bool
 GLContextCGL::SupportsRobustness() const
 {
     return false;
 }
 
 bool
 GLContextCGL::SwapBuffers()
 {
-  PROFILER_LABEL("GLContext", "SwapBuffers");
+  PROFILER_LABEL("GLContextCGL", "SwapBuffers",
+    js::ProfileEntry::Category::GRAPHICS);
+
   [mContext flushBuffer];
   return true;
 }
 
 
 static GLContextCGL *
 GetGlobalContextCGL()
 {
--- a/gfx/gl/SurfaceStream.cpp
+++ b/gfx/gl/SurfaceStream.cpp
@@ -425,17 +425,18 @@ SurfaceStream_TripleBuffer::SurrenderSur
     if (!consumer)
         consumer = Surrender(mStaging);
 }
 
 SharedSurface*
 SurfaceStream_TripleBuffer::SwapProducer(SurfaceFactory* factory,
                                          const gfx::IntSize& size)
 {
-    PROFILER_LABEL("SurfaceStream_TripleBuffer", "SwapProducer");
+    PROFILER_LABEL("SurfaceStream_TripleBuffer", "SwapProducer",
+        js::ProfileEntry::Category::GRAPHICS);
 
     MonitorAutoLock lock(mMonitor);
     if (mProducer) {
         RecycleScraps(factory);
 
         // If WaitForCompositor succeeds, mStaging has moved to mConsumer.
         // If it failed, we might have to scrap it.
         if (mStaging) {
@@ -475,17 +476,18 @@ SurfaceStream_TripleBuffer_Async::Surfac
 
 SurfaceStream_TripleBuffer_Async::~SurfaceStream_TripleBuffer_Async()
 {
 }
 
 void
 SurfaceStream_TripleBuffer_Async::WaitForCompositor()
 {
-    PROFILER_LABEL("SurfaceStream_TripleBuffer_Async", "WaitForCompositor");
+    PROFILER_LABEL("SurfaceStream_TripleBuffer_Async", "WaitForCompositor",
+        js::ProfileEntry::Category::GRAPHICS);
 
     // If we haven't be notified within 100ms, then
     // something must have happened and it will never arrive.
     // Bail out to avoid deadlocking.
     mMonitor.Wait(PR_MillisecondsToInterval(100));
 }
 
 } /* namespace gfx */
--- a/gfx/layers/RotatedBuffer.cpp
+++ b/gfx/layers/RotatedBuffer.cpp
@@ -164,17 +164,19 @@ RotatedBuffer::DrawBufferQuadrant(gfx::D
 
 void
 RotatedBuffer::DrawBufferWithRotation(gfx::DrawTarget *aTarget, ContextSource aSource,
                                       float aOpacity,
                                       gfx::CompositionOp aOperator,
                                       gfx::SourceSurface* aMask,
                                       const gfx::Matrix* aMaskTransform) const
 {
-  PROFILER_LABEL("RotatedBuffer", "DrawBufferWithRotation");
+  PROFILER_LABEL("RotatedBuffer", "DrawBufferWithRotation",
+    js::ProfileEntry::Category::GRAPHICS);
+
   // See above, in Azure Repeat should always be a safe, even faster choice
   // though! Particularly on D2D Repeat should be a lot faster, need to look
   // into that. TODO[Bas]
   DrawBufferQuadrant(aTarget, LEFT, TOP, aSource, aOpacity, aOperator, aMask, aMaskTransform);
   DrawBufferQuadrant(aTarget, RIGHT, TOP, aSource, aOpacity, aOperator, aMask, aMaskTransform);
   DrawBufferQuadrant(aTarget, LEFT, BOTTOM, aSource, aOpacity, aOperator, aMask, aMaskTransform);
   DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aSource, aOpacity, aOperator,aMask, aMaskTransform);
 }
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -565,17 +565,19 @@ BasicLayerManager::RenderDebugOverlay()
   sFrameCount++;
 }
 
 bool
 BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
                                           void* aCallbackData,
                                           EndTransactionFlags aFlags)
 {
-  PROFILER_LABEL("BasicLayerManager", "EndTransactionInternal");
+  PROFILER_LABEL("BasicLayerManager", "EndTransactionInternal",
+    js::ProfileEntry::Category::GRAPHICS);
+
 #ifdef MOZ_LAYERS_HAVE_LOG
   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   Log();
 #endif
 
   NS_ASSERTION(InConstruction(), "Should be in construction phase");
   mPhase = PHASE_DRAWING;
 
@@ -875,17 +877,19 @@ BasicLayerManager::FlushGroup(PaintLayer
 }
 
 void
 BasicLayerManager::PaintLayer(gfxContext* aTarget,
                               Layer* aLayer,
                               DrawThebesLayerCallback aCallback,
                               void* aCallbackData)
 {
-  PROFILER_LABEL("BasicLayerManager", "PaintLayer");
+  PROFILER_LABEL("BasicLayerManager", "PaintLayer",
+    js::ProfileEntry::Category::GRAPHICS);
+
   PaintLayerContext paintLayerContext(aTarget, aLayer, aCallback, aCallbackData);
 
   // Don't attempt to paint layers with a singular transform, cairo will
   // just throw an error.
   if (aLayer->GetEffectiveTransform().IsSingular()) {
     return;
   }
 
--- a/gfx/layers/basic/BasicThebesLayer.cpp
+++ b/gfx/layers/basic/BasicThebesLayer.cpp
@@ -45,17 +45,19 @@ IntersectWithClip(const nsIntRegion& aRe
 }
 
 void
 BasicThebesLayer::PaintThebes(gfxContext* aContext,
                               Layer* aMaskLayer,
                               LayerManager::DrawThebesLayerCallback aCallback,
                               void* aCallbackData)
 {
-  PROFILER_LABEL("BasicThebesLayer", "PaintThebes");
+  PROFILER_LABEL("BasicThebesLayer", "PaintThebes",
+    js::ProfileEntry::Category::GRAPHICS);
+
   NS_ASSERTION(BasicManager()->InDrawing(),
                "Can only draw in drawing phase");
 
   float opacity = GetEffectiveOpacity();
   CompositionOp effectiveOperator = GetEffectiveOperator(this);
 
   if (!BasicManager()->IsRetained()) {
     mValidRegion.SetEmpty();
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -121,17 +121,19 @@ ClientCanvasLayer::Initialize(const Data
       screen->Morph(factory, streamType);
     }
   }
 }
 
 void
 ClientCanvasLayer::RenderLayer()
 {
-  PROFILER_LABEL("ClientCanvasLayer", "Paint");
+  PROFILER_LABEL("ClientCanvasLayer", "RenderLayer",
+    js::ProfileEntry::Category::GRAPHICS);
+
   if (!IsDirty()) {
     return;
   }
 
   if (GetMaskLayer()) {
     ToClientLayer(GetMaskLayer())->RenderLayer();
   }
   
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -178,17 +178,19 @@ ClientLayerManager::BeginTransaction()
   BeginTransactionWithTarget(nullptr);
 }
 
 bool
 ClientLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
                                            void* aCallbackData,
                                            EndTransactionFlags)
 {
-  PROFILER_LABEL("ClientLayerManager", "EndTransactionInternal");
+  PROFILER_LABEL("ClientLayerManager", "EndTransactionInternal",
+    js::ProfileEntry::Category::GRAPHICS);
+
 #ifdef MOZ_LAYERS_HAVE_LOG
   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
   Log();
 #endif
   profiler_tracing("Paint", "Rasterize", TRACING_INTERVAL_START);
 
   NS_ASSERTION(InConstruction(), "Should be in construction phase");
   mPhase = PHASE_DRAWING;
--- a/gfx/layers/client/ClientThebesLayer.cpp
+++ b/gfx/layers/client/ClientThebesLayer.cpp
@@ -28,17 +28,19 @@
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 void
 ClientThebesLayer::PaintThebes()
 {
-  PROFILER_LABEL("ClientThebesLayer", "PaintThebes");
+  PROFILER_LABEL("ClientThebesLayer", "PaintThebes",
+    js::ProfileEntry::Category::GRAPHICS);
+
   NS_ASSERTION(ClientManager()->InDrawing(),
                "Can only draw in drawing phase");
   
   uint32_t flags = RotatedContentBuffer::PAINT_CAN_DRAW_ROTATED;
 #ifndef MOZ_WIDGET_ANDROID
   if (ClientManager()->CompositorMightResample()) {
     flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE;
   }
--- a/gfx/layers/client/SimpleTiledContentClient.cpp
+++ b/gfx/layers/client/SimpleTiledContentClient.cpp
@@ -48,17 +48,18 @@ SimpleTiledLayerBuffer::PaintThebes(cons
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   long start = PR_IntervalNow();
 #endif
 
   // If this region is empty XMost() - 1 will give us a negative value.
   NS_ASSERTION(!aPaintRegion.GetBounds().IsEmpty(), "Empty paint region\n");
 
-  PROFILER_LABEL("SimpleTiledLayerBuffer", "PaintThebesUpdate");
+  PROFILER_LABEL("SimpleTiledLayerBuffer", "PaintThebesUpdate",
+    js::ProfileEntry::Category::GRAPHICS);
 
   Update(aNewValidRegion, aPaintRegion);
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   if (PR_IntervalNow() - start > 10) {
     const nsIntRect bounds = aPaintRegion.GetBounds();
     printf_stderr("Time to tile [%i, %i, %i, %i] -> %i\n", bounds.x, bounds.y, bounds.width, bounds.height, PR_IntervalNow() - start);
   }
@@ -69,17 +70,19 @@ SimpleTiledLayerBuffer::PaintThebes(cons
   mCallbackData = nullptr;
 }
 
 SimpleTiledLayerTile
 SimpleTiledLayerBuffer::ValidateTile(SimpleTiledLayerTile aTile,
                                      const nsIntPoint& aTileOrigin,
                                      const nsIntRegion& aDirtyRegion)
 {
-  PROFILER_LABEL("SimpleTiledLayerBuffer", "ValidateTile");
+  PROFILER_LABEL("SimpleTiledLayerBuffer", "ValidateTile",
+    js::ProfileEntry::Category::GRAPHICS);
+
   static gfx::IntSize kTileSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight());
 
   gfx::SurfaceFormat tileFormat = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType());
 
   // if this is true, we're using a separate buffer to do our drawing first
   bool doBufferedDrawing = true;
   bool fullPaint = false;
 
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -653,17 +653,19 @@ ClientTiledLayerBuffer::PaintThebes(cons
   }
   */
 
   if (useSinglePaintBuffer) {
     nsRefPtr<gfxContext> ctxt;
 
     const nsIntRect bounds = aPaintRegion.GetBounds();
     {
-      PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesSingleBufferAlloc");
+      PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesSingleBufferAlloc",
+        js::ProfileEntry::Category::GRAPHICS);
+
       gfxImageFormat format =
         gfxPlatform::GetPlatform()->OptimalFormatForContent(
           GetContentType());
 
       mSinglePaintDrawTarget =
         gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
           gfx::IntSize(ceilf(bounds.width * mResolution),
                        ceilf(bounds.height * mResolution)),
@@ -681,17 +683,18 @@ ClientTiledLayerBuffer::PaintThebes(cons
     ctxt->Scale(mResolution, mResolution);
     ctxt->Translate(gfxPoint(-bounds.x, -bounds.y));
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
     if (PR_IntervalNow() - start > 3) {
       printf_stderr("Slow alloc %i\n", PR_IntervalNow() - start);
     }
     start = PR_IntervalNow();
 #endif
-    PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesSingleBufferDraw");
+    PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesSingleBufferDraw",
+      js::ProfileEntry::Category::GRAPHICS);
 
     mCallback(mThebesLayer, ctxt, aPaintRegion, DrawRegionClip::CLIP_NONE, nsIntRegion(), mCallbackData);
   }
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   if (PR_IntervalNow() - start > 30) {
     const nsIntRect bounds = aPaintRegion.GetBounds();
     printf_stderr("Time to draw %i: %i, %i, %i, %i\n", PR_IntervalNow() - start, bounds.x, bounds.y, bounds.width, bounds.height);
@@ -701,17 +704,19 @@ ClientTiledLayerBuffer::PaintThebes(cons
       for (const nsIntRect* rect = it.Next(); rect != nullptr; rect = it.Next()) {
         printf_stderr(" rect %i, %i, %i, %i\n", rect->x, rect->y, rect->width, rect->height);
       }
     }
   }
   start = PR_IntervalNow();
 #endif
 
-  PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesUpdate");
+  PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesUpdate",
+    js::ProfileEntry::Category::GRAPHICS);
+
   Update(aNewValidRegion, aPaintRegion);
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   if (PR_IntervalNow() - start > 10) {
     const nsIntRect bounds = aPaintRegion.GetBounds();
     printf_stderr("Time to tile %i: %i, %i, %i, %i\n", PR_IntervalNow() - start, bounds.x, bounds.y, bounds.width, bounds.height);
   }
 #endif
@@ -722,17 +727,18 @@ ClientTiledLayerBuffer::PaintThebes(cons
   mSinglePaintDrawTarget = nullptr;
 }
 
 TileClient
 ClientTiledLayerBuffer::ValidateTile(TileClient aTile,
                                     const nsIntPoint& aTileOrigin,
                                     const nsIntRegion& aDirtyRegion)
 {
-  PROFILER_LABEL("ClientTiledLayerBuffer", "ValidateTile");
+  PROFILER_LABEL("ClientTiledLayerBuffer", "ValidateTile",
+    js::ProfileEntry::Category::GRAPHICS);
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   if (aDirtyRegion.IsComplex()) {
     printf_stderr("Complex region\n");
   }
 #endif
 
   if (aTile.IsPlaceholderTile()) {
@@ -957,17 +963,19 @@ ClientTiledLayerBuffer::ComputeProgressi
       zoom);
 #endif
 
   if (abortPaint) {
     // We ignore if front-end wants to abort if this is the first,
     // non-low-precision paint, as in that situation, we're about to override
     // front-end's page/viewport metrics.
     if (!aPaintData->mFirstPaint || drawingLowPrecision) {
-      PROFILER_LABEL("ContentClient", "Abort painting");
+      PROFILER_LABEL("ClientTiledLayerBuffer", "ComputeProgressiveUpdateRegion",
+        js::ProfileEntry::Category::GRAPHICS);
+
       aRegionToPaint.SetEmpty();
       return aIsRepeated;
     }
   }
 
   LayoutDeviceRect transformedCompositionBounds =
     TransformCompositionBounds(compositionBounds, zoom, aPaintData->mScrollOffset,
                                aPaintData->mResolution, aPaintData->mTransformDisplayPortToLayoutDevice);
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -849,17 +849,19 @@ AsyncCompositionManager::TransformScroll
   // Make sure fixed position layers don't move away from their anchor points
   // when we're asynchronously panning or zooming
   AlignFixedAndStickyLayers(aLayer, aLayer, oldTransform, fixedLayerMargins);
 }
 
 bool
 AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame)
 {
-  PROFILER_LABEL("AsyncCompositionManager", "TransformShadowTree");
+  PROFILER_LABEL("AsyncCompositionManager", "TransformShadowTree",
+    js::ProfileEntry::Category::GRAPHICS);
+
   Layer* root = mLayerManager->GetRoot();
   if (!root) {
     return false;
   }
 
   // NB: we must sample animations *before* sampling pan/zoom
   // transforms.
   bool wantNextFrame = SampleAnimations(root, aCurrentFrame);
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -371,17 +371,19 @@ LayerManagerComposite::RenderDebugOverla
     // We intentionally overflow at 2^16.
     sFrameCount++;
   }
 }
 
 void
 LayerManagerComposite::Render()
 {
-  PROFILER_LABEL("LayerManagerComposite", "Render");
+  PROFILER_LABEL("LayerManagerComposite", "Render",
+    js::ProfileEntry::Category::GRAPHICS);
+
   if (mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return;
   }
 
   if (gfxPrefs::LayersDump()) {
     this->Dump();
   }
@@ -396,17 +398,19 @@ LayerManagerComposite::Render()
         printf_stderr("HWComposer: FPS is %g\n", fps);
       }
     }
     mCompositor->EndFrameForExternalComposition(mWorldMatrix);
     return;
   }
 
   {
-    PROFILER_LABEL("LayerManagerComposite", "PreRender");
+    PROFILER_LABEL("LayerManagerComposite", "PreRender",
+      js::ProfileEntry::Category::GRAPHICS);
+
     if (!mCompositor->GetWidget()->PreRender(this)) {
       return;
     }
   }
 
   nsIntRegion invalid;
   if (mTarget) {
     invalid = mTargetBounds;
@@ -460,17 +464,19 @@ LayerManagerComposite::Render()
                                                               actualBounds.y,
                                                               actualBounds.width,
                                                               actualBounds.height));
 
   // Debugging
   RenderDebugOverlay(actualBounds);
 
   {
-    PROFILER_LABEL("LayerManagerComposite", "EndFrame");
+    PROFILER_LABEL("LayerManagerComposite", "EndFrame",
+      js::ProfileEntry::Category::GRAPHICS);
+
     mCompositor->EndFrame();
     mCompositor->SetFBAcquireFence(mRoot);
   }
 
   mCompositor->GetWidget()->PostRender(this);
 
   RecordFrame();
 }
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -106,17 +106,18 @@ ThebesLayerComposite::GetRenderState()
 }
 
 void
 ThebesLayerComposite::RenderLayer(const nsIntRect& aClipRect)
 {
   if (!mBuffer || !mBuffer->IsAttached()) {
     return;
   }
-  PROFILER_LABEL("ThebesLayerComposite", "RenderLayer");
+  PROFILER_LABEL("ThebesLayerComposite", "RenderLayer",
+    js::ProfileEntry::Category::GRAPHICS);
 
   MOZ_ASSERT(mBuffer->GetCompositor() == mCompositeManager->GetCompositor() &&
              mBuffer->GetLayer() == this,
              "buffer is corrupted");
 
   gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
 
 #ifdef MOZ_DUMP_PAINTING
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -607,17 +607,19 @@ CompositorParent::CompositeCallback()
   mCurrentCompositeTask = nullptr;
   CompositeToTarget(nullptr);
 }
 
 void
 CompositorParent::CompositeToTarget(DrawTarget* aTarget, const nsIntRect* aRect)
 {
   profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START);
-  PROFILER_LABEL("CompositorParent", "Composite");
+  PROFILER_LABEL("CompositorParent", "Composite",
+    js::ProfileEntry::Category::GRAPHICS);
+
   NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
                     "Composite can only be called on the compositor thread");
 
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   TimeDuration scheduleDelta = TimeStamp::Now() - mExpectedComposeStartTime;
   if (scheduleDelta > TimeDuration::FromMilliseconds(2) ||
       scheduleDelta < TimeDuration::FromMilliseconds(-2)) {
     printf_stderr("Compositor: Compose starting off schedule by %4.1f ms\n",
@@ -698,17 +700,19 @@ CompositorParent::CompositeToTarget(Draw
   }
 
   profiler_tracing("Paint", "Composite", TRACING_INTERVAL_END);
 }
 
 void
 CompositorParent::ForceComposeToTarget(DrawTarget* aTarget, const nsIntRect* aRect)
 {
-  PROFILER_LABEL("CompositorParent", "ForceComposeToTarget");
+  PROFILER_LABEL("CompositorParent", "ForceComposeToTarget",
+    js::ProfileEntry::Category::GRAPHICS);
+
   AutoRestore<bool> override(mOverrideComposeReadiness);
   mOverrideComposeReadiness = true;
 
   CompositeToTarget(aTarget, aRect);
 }
 
 bool
 CompositorParent::CanComposite()
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -195,17 +195,19 @@ LayerTransactionParent::RecvUpdate(const
                                    const uint64_t& aTransactionId,
                                    const TargetConfig& targetConfig,
                                    const bool& isFirstPaint,
                                    const bool& scheduleComposite,
                                    const uint32_t& paintSequenceNumber,
                                    InfallibleTArray<EditReply>* reply)
 {
   profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START);
-  PROFILER_LABEL("LayerTransactionParent", "RecvUpdate");
+  PROFILER_LABEL("LayerTransactionParent", "RecvUpdate",
+    js::ProfileEntry::Category::GRAPHICS);
+
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   TimeStamp updateStart = TimeStamp::Now();
 #endif
 
   MOZ_LAYERS_LOG(("[ParentSide] received txn with %d edits", cset.Length()));
 
   if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
     return true;
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -455,17 +455,19 @@ ShadowLayerForwarder::EndTransaction(Inf
                                      bool aScheduleComposite,
                                      uint32_t aPaintSequenceNumber,
                                      bool* aSent)
 {
   *aSent = false;
 
   MOZ_ASSERT(aId);
 
-  PROFILER_LABEL("ShadowLayerForwarder", "EndTranscation");
+  PROFILER_LABEL("ShadowLayerForwarder", "EndTranscation",
+    js::ProfileEntry::Category::GRAPHICS);
+
   RenderTraceScope rendertrace("Foward Transaction", "000091");
   NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to");
   NS_ABORT_IF_FALSE(!mTxn->Finished(), "forgot BeginTransaction?");
 
   DiagnosticTypes diagnostics = gfxPlatform::GetPlatform()->GetLayerDiagnosticTypes();
   if (mDiagnosticTypes != diagnostics) {
     mDiagnosticTypes = diagnostics;
     mTxn->AddEdit(OpSetDiagnosticTypes(diagnostics));
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -680,17 +680,19 @@ CompositorOGL::ClearRect(const gfx::Rect
 void
 CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
                           const Rect *aClipRectIn,
                           const gfx::Matrix& aTransform,
                           const Rect& aRenderBounds,
                           Rect *aClipRectOut,
                           Rect *aRenderBoundsOut)
 {
-  PROFILER_LABEL("CompositorOGL", "BeginFrame");
+  PROFILER_LABEL("CompositorOGL", "BeginFrame",
+    js::ProfileEntry::Category::GRAPHICS);
+
   MOZ_ASSERT(!mFrameInProgress, "frame still in progress (should have called EndFrame or AbortFrame");
 
   LayerScope::BeginFrame(mGLContext, PR_Now());
 
   mFrameInProgress = true;
   gfx::Rect rect;
   if (mUseExternalSurfaceSize) {
     rect = gfx::Rect(0, 0, mSurfaceSize.width, mSurfaceSize.height);
@@ -979,17 +981,19 @@ static bool SetBlendMode(GLContext* aGL,
 
 void
 CompositorOGL::DrawQuad(const Rect& aRect,
                         const Rect& aClipRect,
                         const EffectChain &aEffectChain,
                         Float aOpacity,
                         const gfx::Matrix4x4 &aTransform)
 {
-  PROFILER_LABEL("CompositorOGL", "DrawQuad");
+  PROFILER_LABEL("CompositorOGL", "DrawQuad",
+    js::ProfileEntry::Category::GRAPHICS);
+
   MOZ_ASSERT(mFrameInProgress, "frame not started");
 
   IntRect intClipRect;
   aClipRect.ToIntRect(&intClipRect);
 
   gl()->fScissor(intClipRect.x, FlipY(intClipRect.y + intClipRect.height),
                  intClipRect.width, intClipRect.height);
 
@@ -1250,17 +1254,19 @@ CompositorOGL::DrawQuad(const Rect& aRec
 
   // in case rendering has used some other GL context
   MakeCurrent();
 }
 
 void
 CompositorOGL::EndFrame()
 {
-  PROFILER_LABEL("CompositorOGL", "EndFrame");
+  PROFILER_LABEL("CompositorOGL", "EndFrame",
+    js::ProfileEntry::Category::GRAPHICS);
+
   MOZ_ASSERT(mCurrentRenderTarget == mWindowRenderTarget, "Rendering target not properly restored");
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
     nsIntRect rect;
     if (mUseExternalSurfaceSize) {
       rect = nsIntRect(0, 0, mSurfaceSize.width, mSurfaceSize.height);
     } else {
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -349,17 +349,19 @@ gfxContext::Stroke()
                   DrawOptions(1.0f, GetOp(), state.aaMode));
     }
   }
 }
 
 void
 gfxContext::Fill()
 {
-  PROFILER_LABEL("gfxContext", "Fill");
+  PROFILER_LABEL("gfxContext", "Fill",
+    js::ProfileEntry::Category::GRAPHICS);
+
   if (mCairo) {
     cairo_fill_preserve(mCairo);
   } else {
     FillAzure(1.0f);
   }
 }
 
 void
@@ -1499,17 +1501,19 @@ gfxContext::Mask(gfxPattern *pattern)
     }
     mDT->Mask(GeneralPattern(this), *pattern->GetPattern(mDT), DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode));
   }
 }
 
 void
 gfxContext::Mask(gfxASurface *surface, const gfxPoint& offset)
 {
-  PROFILER_LABEL("gfxContext", "Mask");
+  PROFILER_LABEL("gfxContext", "Mask",
+    js::ProfileEntry::Category::GRAPHICS);
+
   if (mCairo) {
     cairo_mask_surface(mCairo, surface->CairoSurface(), offset.x, offset.y);
   } else {
     // Lifetime needs to be limited here as we may simply wrap surface's data.
     RefPtr<SourceSurface> sourceSurf =
       gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mDT, surface);
 
     if (!sourceSurf) {
@@ -1533,17 +1537,19 @@ gfxContext::Mask(SourceSurface *surface,
             surface,
             offset,
             DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode));
 }
 
 void
 gfxContext::Paint(gfxFloat alpha)
 {
-  PROFILER_LABEL("gfxContext", "Paint");
+  PROFILER_LABEL("gfxContext", "Paint",
+    js::ProfileEntry::Category::GRAPHICS);
+
   if (mCairo) {
     cairo_paint_with_alpha(mCairo, alpha);
   } else {
     AzureState &state = CurrentState();
 
     if (state.sourceSurface && !state.sourceSurfCairo &&
         !state.patternTransformChanged && !state.opIsClear)
     {
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -2785,17 +2785,19 @@ struct GlyphBuffer {
         if (aDrawMode == DrawMode::GLYPH_PATH) {
             cairo_glyph_path(aCR, mGlyphBuffer, mNumGlyphs);
         } else {
             if ((int(aDrawMode) & (int(DrawMode::GLYPH_STROKE) | int(DrawMode::GLYPH_STROKE_UNDERNEATH))) ==
                                   (int(DrawMode::GLYPH_STROKE) | int(DrawMode::GLYPH_STROKE_UNDERNEATH))) {
                 FlushStroke(aCR, aContextPaint, aGlobalMatrix);
             }
             if (int(aDrawMode) & int(DrawMode::GLYPH_FILL)) {
-                PROFILER_LABEL("GlyphBuffer", "cairo_show_glyphs");
+                PROFILER_LABEL("GlyphBuffer", "Flush::cairo_show_glyphs",
+                    js::ProfileEntry::Category::GRAPHICS);
+
                 nsRefPtr<gfxPattern> pattern;
                 if (aContextPaint &&
                     !!(pattern = aContextPaint->GetFillPattern(aGlobalMatrix))) {
                     cairo_save(aCR);
                     cairo_set_source(aCR, pattern->CairoPattern());
                 }
 
                 cairo_show_glyphs(aCR, mGlyphBuffer, mNumGlyphs);
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -237,17 +237,19 @@ OptimalFillOperator()
 static already_AddRefed<gfxDrawable>
 CreateSamplingRestrictedDrawable(gfxDrawable* aDrawable,
                                  gfxContext* aContext,
                                  const gfxMatrix& aUserSpaceToImageSpace,
                                  const gfxRect& aSourceRect,
                                  const gfxRect& aSubimage,
                                  const gfxImageFormat aFormat)
 {
-    PROFILER_LABEL("gfxUtils", "CreateSamplingRestricedDrawable");
+    PROFILER_LABEL("gfxUtils", "CreateSamplingRestricedDrawable",
+      js::ProfileEntry::Category::GRAPHICS);
+
     gfxRect userSpaceClipExtents = aContext->GetClipExtents();
     // This isn't optimal --- if aContext has a rotation then GetClipExtents
     // will have to do a bounding-box computation, and TransformBounds might
     // too, so we could get a better result if we computed image space clip
     // extents in one go --- but it doesn't really matter and this is easier
     // to understand.
     gfxRect imageSpaceClipExtents =
         aUserSpaceToImageSpace.TransformBounds(userSpaceClipExtents);
@@ -443,17 +445,19 @@ gfxUtils::DrawPixelSnapped(gfxContext*  
                            const gfxRect&   aSubimage,
                            const gfxRect&   aSourceRect,
                            const gfxRect&   aImageRect,
                            const gfxRect&   aFill,
                            const gfxImageFormat aFormat,
                            GraphicsFilter aFilter,
                            uint32_t         aImageFlags)
 {
-    PROFILER_LABEL("gfxUtils", "DrawPixelSnapped");
+    PROFILER_LABEL("gfxUtils", "DrawPixelSnapped",
+      js::ProfileEntry::Category::GRAPHICS);
+
     bool doTile = !aImageRect.Contains(aSourceRect) &&
                   !(aImageFlags & imgIContainer::FLAG_CLAMP);
 
     nsRefPtr<gfxASurface> currentTarget = aContext->CurrentSurface();
     gfxMatrix deviceSpaceToImageSpace =
         DeviceToImageTransform(aContext, aUserSpaceToImageSpace);
 
     AutoCairoPixmanBugWorkaround workaround(aContext, deviceSpaceToImageSpace,
--- a/image/src/Decoder.cpp
+++ b/image/src/Decoder.cpp
@@ -82,17 +82,19 @@ Decoder::InitSharedDecoder(uint8_t* imag
   // Implementation-specific initialization
   InitInternal();
   mInitialized = true;
 }
 
 void
 Decoder::Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy)
 {
-  PROFILER_LABEL("ImageDecoder", "Write");
+  PROFILER_LABEL("ImageDecoder", "Write",
+    js::ProfileEntry::Category::GRAPHICS);
+
   MOZ_ASSERT(NS_IsMainThread() || aStrategy == DECODE_ASYNC);
 
   // We're strict about decoder errors
   NS_ABORT_IF_FALSE(!HasDecoderError(),
                     "Not allowed to make more decoder calls after error!");
 
   // If a data error occured, just ignore future data
   if (HasDataError())
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -2387,17 +2387,19 @@ RasterImage::RequestDecodeCore(RequestDe
   // If we've read all the data we have, we're done
   if (mHasSourceData && mBytesDecoded == mSourceData.Length())
     return NS_OK;
 
   // If we can do decoding now, do so.  Small images will decode completely,
   // large images will decode a bit and post themselves to the event loop
   // to finish decoding.
   if (!mDecoded && !mInDecoder && mHasSourceData && aDecodeType == SYNCHRONOUS_NOTIFY_AND_SOME_DECODE) {
-    PROFILER_LABEL_PRINTF("RasterImage", "DecodeABitOf", "%s", GetURIString().get());
+    PROFILER_LABEL_PRINTF("RasterImage", "DecodeABitOf",
+      js::ProfileEntry::Category::GRAPHICS, "%s", GetURIString().get());
+
     DecodePool::Singleton()->DecodeABitOf(this, DECODE_SYNC);
     return NS_OK;
   }
 
   if (!mDecoded) {
     // If we get this far, dispatch the worker. We do this instead of starting
     // any immediate decoding to guarantee that all our decode notifications are
     // dispatched asynchronously, and to ensure we stay responsive.
@@ -2406,17 +2408,18 @@ RasterImage::RequestDecodeCore(RequestDe
 
   return NS_OK;
 }
 
 // Synchronously decodes as much data as possible
 nsresult
 RasterImage::SyncDecode()
 {
-  PROFILER_LABEL_PRINTF("RasterImage", "SyncDecode", "%s", GetURIString().get());;
+  PROFILER_LABEL_PRINTF("RasterImage", "SyncDecode",
+    js::ProfileEntry::Category::GRAPHICS, "%s", GetURIString().get());
 
   // If we have a size decoder open, make sure we get the size
   if (mDecoder && mDecoder->IsSizeDecode()) {
     nsresult rv = DecodePool::Singleton()->DecodeUntilSizeAvailable(this);
     CONTAINER_ENSURE_SUCCESS(rv);
 
     // If we didn't get the size out of the image, we won't until we get more
     // data, so signal that we want a full decode and give up for now.
--- a/image/src/imgFrame.cpp
+++ b/image/src/imgFrame.cpp
@@ -478,17 +478,19 @@ imgFrame::SurfaceForDrawing(bool        
                            mFormat);
 }
 
 bool imgFrame::Draw(gfxContext *aContext, GraphicsFilter aFilter,
                     const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill,
                     const nsIntMargin &aPadding, const nsIntRect &aSubimage,
                     uint32_t aImageFlags)
 {
-  PROFILER_LABEL("image", "imgFrame::Draw");
+  PROFILER_LABEL("imgFrame", "Draw",
+    js::ProfileEntry::Category::GRAPHICS);
+
   NS_ASSERTION(!aFill.IsEmpty(), "zero dest size --- fix caller");
   NS_ASSERTION(!aSubimage.IsEmpty(), "zero source size --- fix caller");
   NS_ASSERTION(!mPalettedImageData, "Directly drawing a paletted image!");
 
   bool doPadding = aPadding != nsIntMargin(0,0,0,0);
   bool doPartialDecode = !ImageComplete();
 
   if (mSinglePixel && !doPadding && !doPartialDecode) {
--- a/ipc/chromium/src/base/message_pump_default.cc
+++ b/ipc/chromium/src/base/message_pump_default.cc
@@ -48,26 +48,28 @@ void MessagePumpDefault::Run(Delegate* d
     if (!keep_running_)
       break;
 
     if (did_work)
       continue;
 
     if (delayed_work_time_.is_null()) {
       hangMonitor.NotifyWait();
-      PROFILER_LABEL("MessagePump", "Wait");
+      PROFILER_LABEL("MessagePump", "Wait",
+        js::ProfileEntry::Category::OTHER);
       {
         GeckoProfilerSleepRAII profiler_sleep;
         event_.Wait();
       }
     } else {
       TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
       if (delay > TimeDelta()) {
         hangMonitor.NotifyWait();
-        PROFILER_LABEL("MessagePump", "Wait");
+        PROFILER_LABEL("MessagePump", "Wait",
+          js::ProfileEntry::Category::OTHER);
         {
           GeckoProfilerSleepRAII profiler_sleep;
           event_.TimedWait(delay);
         }
       } else {
         // It looks like delayed_work_time_ indicates a time in the past, so we
         // need to call DoDelayedWork now.
         delayed_work_time_ = TimeTicks();
--- a/ipc/glue/WindowsMessageLoop.cpp
+++ b/ipc/glue/WindowsMessageLoop.cpp
@@ -81,16 +81,17 @@ extern UINT sAppShellGeckoMsgId;
 extern UINT sDefaultBrowserMsgId;
 #endif
 }
 }
 
 namespace {
 
 const wchar_t kOldWndProcProp[] = L"MozillaIPCOldWndProc";
+const wchar_t k3rdPartyWindowProp[] = L"Mozilla3rdPartyWindow";
 
 // This isn't defined before Windows XP.
 enum { WM_XP_THEMECHANGED = 0x031A };
 
 char16_t gAppMessageWindowName[256] = { 0 };
 int32_t gAppMessageWindowNameLength = 0;
 
 nsTArray<HWND>* gNeuteredWindows = nullptr;
@@ -98,16 +99,19 @@ nsTArray<HWND>* gNeuteredWindows = nullp
 typedef nsTArray<nsAutoPtr<DeferredMessage> > DeferredMessageArray;
 DeferredMessageArray* gDeferredMessages = nullptr;
 
 HHOOK gDeferredGetMsgHook = nullptr;
 HHOOK gDeferredCallWndProcHook = nullptr;
 
 DWORD gUIThreadId = 0;
 
+// WM_GETOBJECT id pulled from uia headers
+#define MOZOBJID_UIAROOT -25
+
 LRESULT CALLBACK
 DeferredMessageHook(int nCode,
                     WPARAM wParam,
                     LPARAM lParam)
 {
   // XXX This function is called for *both* the WH_CALLWNDPROC hook and the
   //     WH_GETMESSAGE hook, but they have different parameters. We don't
   //     use any of them except nCode which has the same meaning.
@@ -156,16 +160,38 @@ ScheduleDeferredMessageRun()
     gDeferredCallWndProcHook = ::SetWindowsHookEx(WH_CALLWNDPROC,
                                                   DeferredMessageHook, nullptr,
                                                   gUIThreadId);
     NS_ASSERTION(gDeferredGetMsgHook && gDeferredCallWndProcHook,
                  "Failed to set hooks!");
   }
 }
 
+static void
+DumpNeuteredMessage(HWND hwnd, UINT uMsg)
+{
+#ifdef DEBUG
+  nsAutoCString log("Received \"nonqueued\" message ");
+  log.AppendInt(uMsg);
+  log.AppendLiteral(" during a synchronous IPC message for window ");
+  log.AppendInt((int64_t)hwnd);
+
+  wchar_t className[256] = { 0 };
+  if (GetClassNameW(hwnd, className, sizeof(className) - 1) > 0) {
+    log.AppendLiteral(" (\"");
+    log.Append(NS_ConvertUTF16toUTF8((char16_t*)className));
+    log.AppendLiteral("\")");
+  }
+
+  log.AppendLiteral(", sending it to DefWindowProc instead of the normal "
+                    "window procedure.");
+  NS_ERROR(log.get());
+#endif
+}
+
 LRESULT
 ProcessOrDeferMessage(HWND hwnd,
                       UINT uMsg,
                       WPARAM wParam,
                       LPARAM lParam)
 {
   DeferredMessage* deferred = nullptr;
 
@@ -280,50 +306,52 @@ ProcessOrDeferMessage(HWND hwnd,
     case WM_SYNCPAINT:
       return 0;
 
     // This message causes QuickTime to make re-entrant calls.
     // Simply discarding it doesn't seem to hurt anything.
     case WM_APP-1:
       return 0;
 
+    // We only support a query for our IAccessible or UIA pointers.
+    // This should be safe, and needs to be sync.
+#if defined(ACCESSIBILITY)
+   case WM_GETOBJECT: {
+      if (!::GetPropW(hwnd, k3rdPartyWindowProp)) {
+        DWORD objId = static_cast<DWORD>(lParam);
+        WNDPROC oldWndProc = (WNDPROC)GetProp(hwnd, kOldWndProcProp);
+        if ((objId == OBJID_CLIENT || objId == MOZOBJID_UIAROOT) && oldWndProc) {
+          return CallWindowProcW(oldWndProc, hwnd, uMsg, wParam, lParam);
+        }
+      }
+      break;
+    }
+#endif // ACCESSIBILITY
+
     default: {
+      // Unknown messages only are logged in debug builds and sent to
+      // DefWindowProc.
       if (uMsg && uMsg == mozilla::widget::sAppShellGeckoMsgId) {
         // Widget's registered native event callback
         deferred = new DeferredSendMessage(hwnd, uMsg, wParam, lParam);
 #ifdef MOZ_METRO
       } else if (uMsg && uMsg == mozilla::widget::sDefaultBrowserMsgId) {
         // Metro widget's system shutdown message
         deferred = new DeferredSendMessage(hwnd, uMsg, wParam, lParam);
 #endif
-      } else {
-        // Unknown messages only
-#ifdef DEBUG
-        nsAutoCString log("Received \"nonqueued\" message ");
-        log.AppendInt(uMsg);
-        log.AppendLiteral(" during a synchronous IPC message for window ");
-        log.AppendInt((int64_t)hwnd);
-
-        wchar_t className[256] = { 0 };
-        if (GetClassNameW(hwnd, className, sizeof(className) - 1) > 0) {
-          log.AppendLiteral(" (\"");
-          log.Append(NS_ConvertUTF16toUTF8((char16_t*)className));
-          log.AppendLiteral("\")");
-        }
-
-        log.AppendLiteral(", sending it to DefWindowProc instead of the normal "
-                          "window procedure.");
-        NS_ERROR(log.get());
-#endif
-        return DefWindowProc(hwnd, uMsg, wParam, lParam);
       }
     }
   }
 
-  NS_ASSERTION(deferred, "Must have a message here!");
+  // No deferred message was created and we land here, this is an
+  // unhandled message.
+  if (!deferred) {
+    DumpNeuteredMessage(hwnd, uMsg);
+    return DefWindowProc(hwnd, uMsg, wParam, lParam);
+  }
 
   // Create the deferred message array if it doesn't exist already.
   if (!gDeferredMessages) {
     gDeferredMessages = new nsTArray<nsAutoPtr<DeferredMessage> >(20);
     NS_ASSERTION(gDeferredMessages, "Out of memory!");
   }
 
   // Save for later. The array takes ownership of |deferred|.
@@ -395,23 +423,25 @@ WindowIsDeferredWindow(HWND hWnd)
 
   // Plugin windows that can trigger ipc calls in child:
   // 'ShockwaveFlashFullScreen' - flash fullscreen window
   // 'QTNSHIDDEN' - QuickTime
   // 'AGFullScreenWinClass' - silverlight fullscreen window
   if (className.EqualsLiteral("ShockwaveFlashFullScreen") ||
       className.EqualsLiteral("QTNSHIDDEN") ||
       className.EqualsLiteral("AGFullScreenWinClass")) {
+    SetPropW(hWnd, k3rdPartyWindowProp, (HANDLE)1);
     return true;
   }
 
   // Google Earth bridging msg window between the plugin instance and a separate
   // earth process. The earth process can trigger a plugin incall on the browser
   // at any time, which is badness if the instance is already making an incall.
   if (className.EqualsLiteral("__geplugin_bridge_window__")) {
+    SetPropW(hWnd, k3rdPartyWindowProp, (HANDLE)1);
     return true;
   }
 
   // nsNativeAppSupport makes a window like "FirefoxMessageWindow" based on the
   // toolkit app's name. It's pretty expensive to calculate this so we only try
   // once.
   if (gAppMessageWindowNameLength == 0) {
     nsCOMPtr<nsIXULAppInfo> appInfo =
@@ -468,17 +498,18 @@ NeuterWindowProcedure(HWND hWnd)
 
   NS_ASSERTION(currentWndProc != (LONG_PTR)NeuteredWindowProc,
                "This shouldn't be possible!");
 
   if (!SetProp(hWnd, kOldWndProcProp, (HANDLE)currentWndProc)) {
     // Cleanup
     NS_WARNING("SetProp failed!");
     SetWindowLongPtr(hWnd, GWLP_WNDPROC, currentWndProc);
-    RemoveProp(hWnd, kOldWndProcProp);
+    RemovePropW(hWnd, kOldWndProcProp);
+    RemovePropW(hWnd, k3rdPartyWindowProp);
     return false;
   }
 
   return true;
 }
 
 void
 RestoreWindowProcedure(HWND hWnd)
@@ -490,17 +521,18 @@ RestoreWindowProcedure(HWND hWnd)
     NS_ASSERTION(oldWndProc != (LONG_PTR)NeuteredWindowProc,
                  "This shouldn't be possible!");
 
     DebugOnly<LONG_PTR> currentWndProc =
       SetWindowLongPtr(hWnd, GWLP_WNDPROC, oldWndProc);
     NS_ASSERTION(currentWndProc == (LONG_PTR)NeuteredWindowProc,
                  "This should never be switched out from under us!");
   }
-  RemoveProp(hWnd, kOldWndProcProp);
+  RemovePropW(hWnd, kOldWndProcProp);
+  RemovePropW(hWnd, k3rdPartyWindowProp);
 }
 
 LRESULT CALLBACK
 CallWindowProcedureHook(int nCode,
                         WPARAM wParam,
                         LPARAM lParam)
 {
   if (nCode >= 0) {
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -5364,17 +5364,18 @@ class _GenerateProtocolActorCode(ipdl.as
             ExprSelect(msgptr, '->', 'Log'),
             args=[ ExprLiteral.String('['+ actorname +'] '+ pfx),
                    self.protocol.callOtherProcess(actor),
                    ExprLiteral.TRUE if receiving else ExprLiteral.FALSE ])) ])
 
     def profilerLabel(self, tag, msgname):
         return StmtExpr(ExprCall(ExprVar('PROFILER_LABEL'),
                                  [ ExprLiteral.String('IPDL::' + self.protocol.name),
-                                   ExprLiteral.String(tag + msgname) ]))
+                                   ExprLiteral.String(tag + msgname),
+                                   ExprVar('js::ProfileEntry::Category::OTHER') ]))
 
     def saveActorId(self, md):
         idvar = ExprVar('__id')
         if md.decl.type.hasReply():
             # only save the ID if we're actually going to use it, to
             # avoid unused-variable warnings
             saveIdStmts = [ StmtDecl(Decl(_actorIdType(), idvar.name),
                                      self.protocol.routingId()) ]
--- a/js/public/ProfilingStack.h
+++ b/js/public/ProfilingStack.h
@@ -3,16 +3,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef js_ProfilingStack_h
 #define js_ProfilingStack_h
 
 #include "mozilla/NullPtr.h"
+#include "mozilla/TypedEnum.h"
 
 #include "jsbytecode.h"
 #include "jstypes.h"
 
 #include "js/Utility.h"
 
 struct JSRuntime;
 
@@ -58,16 +59,31 @@ class ProfileEntry
         // change the frame type. Instead, call `setJsFrame` or `setCppFrame`.
         IS_CPP_ENTRY = 0x01,
 
         // Indicate that copying the frame label is not necessary when taking a
         // sample of the pseudostack.
         FRAME_LABEL_COPY = 0x02
     };
 
+    MOZ_BEGIN_NESTED_ENUM_CLASS(Category, uint32_t)
+        OTHER    = 0x04,
+        CSS      = 0x08,
+        JS       = 0x10,
+        GC       = 0x20,
+        CC       = 0x40,
+        NETWORK  = 0x80,
+        GRAPHICS = 0x100,
+        STORAGE  = 0x200,
+        EVENTS   = 0x400,
+
+        FIRST    = OTHER,
+        LAST     = EVENTS
+    MOZ_END_NESTED_ENUM_CLASS(Category)
+
     // All of these methods are marked with the 'volatile' keyword because SPS's
     // representation of the stack is stored such that all ProfileEntry
     // instances are volatile. These methods would not be available unless they
     // were marked as volatile as well.
 
     bool isCpp() const volatile { return hasFlag(IS_CPP_ENTRY); }
     bool isJs() const volatile { return !isCpp(); }
 
@@ -82,25 +98,25 @@ class ProfileEntry
         setPC(aPc);
     }
     void setCppFrame(void *aSp, uint32_t aLine) volatile {
         flags |= IS_CPP_ENTRY;
         spOrScript = aSp;
         lineOrPc = static_cast<int32_t>(aLine);
     }
 
-    void setFlag(Flags flag) volatile {
+    void setFlag(uint32_t flag) volatile {
         MOZ_ASSERT(flag != IS_CPP_ENTRY);
         flags |= flag;
     }
-    void unsetFlag(Flags flag) volatile {
+    void unsetFlag(uint32_t flag) volatile {
         MOZ_ASSERT(flag != IS_CPP_ENTRY);
         flags &= ~flag;
     }
-    bool hasFlag(Flags flag) const volatile {
+    bool hasFlag(uint32_t flag) const volatile {
         return bool(flags & uint32_t(flag));
     }
 
     void *stackAddress() const volatile {
         MOZ_ASSERT(!isJs());
         return spOrScript;
     }
     JSScript *script() const volatile {
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -2411,17 +2411,18 @@ ContainerState::ChooseAnimatedGeometryRo
  * We set the visible rect for all layers, although the actual setting
  * of visible rects for some ThebesLayers is deferred until the calling
  * of ContainerState::Finish.
  */
 void
 ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
                                     uint32_t aFlags)
 {
-  PROFILER_LABEL("ContainerState", "ProcessDisplayItems");
+  PROFILER_LABEL("ContainerState", "ProcessDisplayItems",
+    js::ProfileEntry::Category::GRAPHICS);
 
   const nsIFrame* lastAnimatedGeometryRoot = mContainerReferenceFrame;
   nsPoint topLeft(0,0);
 
   // When NO_COMPONENT_ALPHA is set, items will be flattened into a single
   // layer, so we need to choose which active scrolled root to use for all
   // items.
   if (aFlags & NO_COMPONENT_ALPHA) {
@@ -3767,17 +3768,18 @@ static void DrawForcedBackgroundColor(gf
 /* static */ void
 FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
                                    gfxContext* aContext,
                                    const nsIntRegion& aRegionToDraw,
                                    DrawRegionClip aClip,
                                    const nsIntRegion& aRegionToInvalidate,
                                    void* aCallbackData)
 {
-  PROFILER_LABEL("gfx", "DrawThebesLayer");
+  PROFILER_LABEL("FrameLayerBuilder", "DrawThebesLayer",
+    js::ProfileEntry::Category::GRAPHICS);
 
   nsDisplayListBuilder* builder = static_cast<nsDisplayListBuilder*>
     (aCallbackData);
 
   FrameLayerBuilder *layerBuilder = aLayer->Manager()->GetLayerBuilder();
   NS_ASSERTION(layerBuilder, "Unexpectedly null layer builder!");
 
   if (layerBuilder->CheckDOMModified())
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -585,17 +585,18 @@ nsresult
 RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
 {
   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                "Someone forgot a script blocker");
   int32_t count = aChangeList.Count();
   if (!count)
     return NS_OK;
 
-  PROFILER_LABEL("CSS", "ProcessRestyledFrames");
+  PROFILER_LABEL("RestyleManager", "ProcessRestyledFrames",
+    js::ProfileEntry::Category::CSS);
 
   // Make sure to not rebuild quote or counter lists while we're
   // processing restyles
   FrameConstructor()->BeginUpdate();
 
   FramePropertyTable* propTable = mPresContext->PropertyTable();
 
   // Mark frames so that we skip frames that die along the way, bug 123049.
@@ -2903,17 +2904,18 @@ GetNextBlockInInlineSibling(FramePropert
 
 void
 RestyleManager::ComputeStyleChangeFor(nsIFrame*          aFrame,
                                       nsStyleChangeList* aChangeList,
                                       nsChangeHint       aMinChange,
                                       RestyleTracker&    aRestyleTracker,
                                       bool               aRestyleDescendants)
 {
-  PROFILER_LABEL("CSS", "ComputeStyleChangeFor");
+  PROFILER_LABEL("RestyleManager", "ComputeStyleChangeFor",
+    js::ProfileEntry::Category::CSS);
 
   nsIContent *content = aFrame->GetContent();
   if (aMinChange) {
     aChangeList->AppendChange(aFrame, content, aMinChange);
   }
 
   NS_ASSERTION(!aFrame->GetPrevContinuation(),
                "must start with the first continuation");
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -129,17 +129,18 @@ RestyleTracker::ProcessOneRestyle(Elemen
     changeList.AppendChange(primaryFrame, aElement, aChangeHint);
     mRestyleManager->ProcessRestyledFrames(changeList);
   }
 }
 
 void
 RestyleTracker::DoProcessRestyles()
 {
-  PROFILER_LABEL("CSS", "ProcessRestyles");
+  PROFILER_LABEL("RestyleTracker", "ProcessRestyles",
+    js::ProfileEntry::Category::CSS);
 
   mRestyleManager->BeginProcessingRestyles();
 
   // loop so that we process any restyle events generated by processing
   while (mPendingRestyles.Count()) {
     if (mHaveLaterSiblingRestyles) {
       // Convert them to individual restyles on all the later siblings
       nsAutoTArray<nsRefPtr<Element>, RESTYLE_ARRAY_STACKSIZE> laterSiblingArr;
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -570,17 +570,19 @@ void
 nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
                             nsRenderingContext& aRenderingContext,
                             nsIFrame* aForFrame,
                             const nsRect& aDirtyRect,
                             const nsRect& aBorderArea,
                             nsStyleContext* aStyleContext,
                             int aSkipSides)
 {
-  PROFILER_LABEL("nsCSSRendering", "PaintBorder");
+  PROFILER_LABEL("nsCSSRendering", "PaintBorder",
+    js::ProfileEntry::Category::GRAPHICS);
+
   nsStyleContext *styleIfVisited = aStyleContext->GetStyleIfVisited();
   const nsStyleBorder *styleBorder = aStyleContext->StyleBorder();
   // Don't check RelevantLinkVisited here, since we want to take the
   // same amount of time whether or not it's true.
   if (!styleIfVisited) {
     PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
                                aDirtyRect, aBorderArea, *styleBorder,
                                aStyleContext, aSkipSides);
@@ -1546,17 +1548,19 @@ nsCSSRendering::PaintBackground(nsPresCo
                                 nsRenderingContext& aRenderingContext,
                                 nsIFrame* aForFrame,
                                 const nsRect& aDirtyRect,
                                 const nsRect& aBorderArea,
                                 uint32_t aFlags,
                                 nsRect* aBGClipRect,
                                 int32_t aLayer)
 {
-  PROFILER_LABEL("nsCSSRendering", "PaintBackground");
+  PROFILER_LABEL("nsCSSRendering", "PaintBackground",
+    js::ProfileEntry::Category::GRAPHICS);
+
   NS_PRECONDITION(aForFrame,
                   "Frame is expected to be provided to PaintBackground");
 
   nsStyleContext *sc;
   if (!FindBackground(aForFrame, &sc)) {
     // We don't want to bail out if moz-appearance is set on a root
     // node. If it has a parent content node, bail because it's not
     // a root, otherwise keep going in order to let the theme stuff
@@ -1583,17 +1587,19 @@ nsCSSRendering::PaintBackground(nsPresCo
 void
 nsCSSRendering::PaintBackgroundColor(nsPresContext* aPresContext,
                                      nsRenderingContext& aRenderingContext,
                                      nsIFrame* aForFrame,
                                      const nsRect& aDirtyRect,
                                      const nsRect& aBorderArea,
                                      uint32_t aFlags)
 {
-  PROFILER_LABEL("nsCSSRendering", "PaintBackgroundColor");
+  PROFILER_LABEL("nsCSSRendering", "PaintBackgroundColor",
+    js::ProfileEntry::Category::GRAPHICS);
+
   NS_PRECONDITION(aForFrame,
                   "Frame is expected to be provided to PaintBackground");
 
   nsStyleContext *sc;
   if (!FindBackground(aForFrame, &sc)) {
     // We don't want to bail out if moz-appearance is set on a root
     // node. If it has a parent content node, bail because it's not
     // a root, other wise keep going in order to let the theme stuff
@@ -2223,17 +2229,19 @@ nsCSSRendering::PaintGradient(nsPresCont
                               nsRenderingContext& aRenderingContext,
                               nsStyleGradient* aGradient,
                               const nsRect& aDirtyRect,
                               const nsRect& aDest,
                               const nsRect& aFillArea,
                               const CSSIntRect& aSrc,
                               const nsSize& aIntrinsicSize)
 {
-  PROFILER_LABEL("nsCSSRendering", "PaintGradient");
+  PROFILER_LABEL("nsCSSRendering", "PaintGradient",
+    js::ProfileEntry::Category::GRAPHICS);
+
   Telemetry::AutoTimer<Telemetry::GRADIENT_DURATION, Telemetry::Microsecond> gradientTimer;
   if (aDest.IsEmpty() || aFillArea.IsEmpty()) {
     return;
   }
 
   gfxContext *ctx = aRenderingContext.ThebesContext();
   nscoord appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
   gfxSize srcSize = gfxSize(gfxFloat(aIntrinsicSize.width)/appUnitsPerDevPixel,
--- a/layout/base/nsCSSRenderingBorders.cpp
+++ b/layout/base/nsCSSRenderingBorders.cpp
@@ -1765,17 +1765,19 @@ nsCSSBorderRenderer::DrawBorders()
 
   SF(" allBordersSame: %d dashedSides: 0x%02x\n", allBordersSame, dashedSides);
 
   if (allBordersSame && !forceSeparateCorners) {
     /* Draw everything in one go */
     DrawBorderSides(SIDE_BITS_ALL);
     SN("---------------- (1)");
   } else {
-    PROFILER_LABEL("nsCSSBorderRenderer", "DrawBorders::multipass");
+    PROFILER_LABEL("nsCSSBorderRenderer", "DrawBorders::multipass",
+      js::ProfileEntry::Category::GRAPHICS);
+
     /* We have more than one pass to go.  Draw the corners separately from the sides. */
 
     /*
      * If we have a 1px-wide border, the corners are going to be
      * negligible, so don't bother doing anything fancy.  Just extend
      * the top and bottom borders to the right 1px and the left border
      * to the bottom 1px.  We do this by twiddling the corner dimensions,
      * which causes the right to happen later on.  Only do this if we have
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -1034,17 +1034,19 @@ nsDisplayList::GetBounds(nsDisplayListBu
   }
   return bounds;
 }
 
 bool
 nsDisplayList::ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
                                         nsRegion* aVisibleRegion,
                                         nsIFrame* aDisplayPortFrame) {
-  PROFILER_LABEL("nsDisplayList", "ComputeVisibilityForRoot");
+  PROFILER_LABEL("nsDisplayList", "ComputeVisibilityForRoot",
+    js::ProfileEntry::Category::GRAPHICS);
+
   nsRegion r;
   r.And(*aVisibleRegion, GetBounds(aBuilder));
   return ComputeVisibilityForSublist(aBuilder, aVisibleRegion,
                                      r.GetBounds(), r.GetBounds(),
                                      aDisplayPortFrame);
 }
 
 static nsRegion
@@ -1202,17 +1204,19 @@ nsDisplayList::ComputeVisibilityForSubli
   mDidComputeVisibility = true;
 #endif
   return anyVisible;
 }
 
 void nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder,
                               nsRenderingContext* aCtx,
                               uint32_t aFlags) const {
-  PROFILER_LABEL("nsDisplayList", "PaintRoot");
+  PROFILER_LABEL("nsDisplayList", "PaintRoot",
+    js::ProfileEntry::Category::GRAPHICS);
+
   PaintForFrame(aBuilder, aCtx, aBuilder->RootReferenceFrame(), aFlags);
 }
 
 /**
  * We paint by executing a layer manager transaction, constructing a
  * single layer representing the display list, and then making it the
  * root of the layer manager, drawing into the ThebesLayers.
  */
@@ -2848,17 +2852,19 @@ void
 nsDisplayBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
                                nsRenderingContext* aCtx) {
   nsPoint offset = ToReferenceFrame();
   nsRect borderRect = mFrame->VisualBorderRectRelativeToSelf() + offset;
   nsPresContext* presContext = mFrame->PresContext();
   nsAutoTArray<nsRect,10> rects;
   ComputeDisjointRectangles(mVisibleRegion, &rects);
 
-  PROFILER_LABEL("nsDisplayBoxShadowOuter", "Paint");
+  PROFILER_LABEL("nsDisplayBoxShadowOuter", "Paint",
+    js::ProfileEntry::Category::GRAPHICS);
+
   for (uint32_t i = 0; i < rects.Length(); ++i) {
     nsCSSRendering::PaintBoxShadowOuter(presContext, *aCtx, mFrame,
                                         borderRect, rects[i], mOpacity);
   }
 }
 
 nsRect
 nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
@@ -2931,17 +2937,19 @@ void
 nsDisplayBoxShadowInner::Paint(nsDisplayListBuilder* aBuilder,
                                nsRenderingContext* aCtx) {
   nsPoint offset = ToReferenceFrame();
   nsRect borderRect = nsRect(offset, mFrame->GetSize());
   nsPresContext* presContext = mFrame->PresContext();
   nsAutoTArray<nsRect,10> rects;
   ComputeDisjointRectangles(mVisibleRegion, &rects);
 
-  PROFILER_LABEL("nsDisplayBoxShadowInner", "Paint");
+  PROFILER_LABEL("nsDisplayBoxShadowInner", "Paint",
+    js::ProfileEntry::Category::GRAPHICS);
+
   for (uint32_t i = 0; i < rects.Length(); ++i) {
     aCtx->PushState();
     aCtx->IntersectClip(rects[i]);
     nsCSSRendering::PaintBoxShadowInner(presContext, *aCtx, mFrame,
                                         borderRect, rects[i]);
     aCtx->PopState();
   }
 }
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2479,30 +2479,34 @@ nsLayoutUtils::GetRemoteContentIds(nsIFr
   list.DeleteAll();
 
   return NS_OK;
 }
 
 nsIFrame*
 nsLayoutUtils::GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt, uint32_t aFlags)
 {
-  PROFILER_LABEL("nsLayoutUtils", "GetFrameForPoint");
+  PROFILER_LABEL("nsLayoutUtils", "GetFrameForPoint",
+    js::ProfileEntry::Category::GRAPHICS);
+
   nsresult rv;
   nsAutoTArray<nsIFrame*,8> outFrames;
   rv = GetFramesForArea(aFrame, nsRect(aPt, nsSize(1, 1)), outFrames, aFlags);
   NS_ENSURE_SUCCESS(rv, nullptr);
   return outFrames.Length() ? outFrames.ElementAt(0) : nullptr;
 }
 
 nsresult
 nsLayoutUtils::GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,
                                 nsTArray<nsIFrame*> &aOutFrames,
                                 uint32_t aFlags)
 {
-  PROFILER_LABEL("nsLayoutUtils","GetFramesForArea");
+  PROFILER_LABEL("nsLayoutUtils", "GetFramesForArea",
+    js::ProfileEntry::Category::GRAPHICS);
+
   nsDisplayListBuilder builder(aFrame, nsDisplayListBuilder::EVENT_DELIVERY,
                                false);
   nsDisplayList list;
   nsRect target(aRect);
 
   if (aFlags & IGNORE_PAINT_SUPPRESSION) {
     builder.IgnorePaintSuppression();
   }
@@ -2634,17 +2638,19 @@ nsLayoutUtils::GetOrMaybeCreateDisplayPo
   return haveDisplayPort;
 }
 
 nsresult
 nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFrame,
                           const nsRegion& aDirtyRegion, nscolor aBackstop,
                           uint32_t aFlags)
 {
-  PROFILER_LABEL("nsLayoutUtils","PaintFrame");
+  PROFILER_LABEL("nsLayoutUtils", "PaintFrame",
+    js::ProfileEntry::Category::GRAPHICS);
+
   if (aFlags & PAINT_WIDGET_LAYERS) {
     nsView* view = aFrame->GetView();
     if (!(view && view->GetWidget() && GetDisplayRootFrame(aFrame) == aFrame)) {
       aFlags &= ~PAINT_WIDGET_LAYERS;
       NS_ASSERTION(aRenderingContext, "need a rendering context");
     }
   }
 
@@ -2752,30 +2758,34 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
       if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) {
         if (nsIContent* content = rootScrollFrame->GetContent()) {
           id = nsLayoutUtils::FindOrCreateIDFor(content);
         }
       }
     }
     nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(&builder, id);
 
-    PROFILER_LABEL("nsLayoutUtils","PaintFrame::BuildDisplayList");
+    PROFILER_LABEL("nsLayoutUtils", "PaintFrame::BuildDisplayList",
+      js::ProfileEntry::Category::GRAPHICS);
+
     aFrame->BuildDisplayListForStackingContext(&builder, dirtyRect, &list);
   }
   const bool paintAllContinuations = aFlags & PAINT_ALL_CONTINUATIONS;
   NS_ASSERTION(!paintAllContinuations || !aFrame->GetPrevContinuation(),
                "If painting all continuations, the frame must be "
                "first-continuation");
 
   nsIAtom* frameType = aFrame->GetType();
 
   if (paintAllContinuations) {
     nsIFrame* currentFrame = aFrame;
     while ((currentFrame = currentFrame->GetNextContinuation()) != nullptr) {
-      PROFILER_LABEL("nsLayoutUtils","PaintFrame::ContinuationsBuildDisplayList");
+      PROFILER_LABEL("nsLayoutUtils", "PaintFrame::ContinuationsBuildDisplayList",
+        js::ProfileEntry::Category::GRAPHICS);
+
       nsRect frameDirty = dirtyRect - builder.ToReferenceFrame(currentFrame);
       currentFrame->BuildDisplayListForStackingContext(&builder,
                                                        frameDirty, &list);
     }
   }
 
   // For the viewport frame in print preview/page layout we want to paint
   // the grey background behind the page, not the canvas color.
@@ -5064,17 +5074,18 @@ nsLayoutUtils::DrawBackgroundImage(nsRen
                                    const nsIntSize&    aImageSize,
                                    GraphicsFilter      aGraphicsFilter,
                                    const nsRect&       aDest,
                                    const nsRect&       aFill,
                                    const nsPoint&      aAnchor,
                                    const nsRect&       aDirty,
                                    uint32_t            aImageFlags)
 {
-  PROFILER_LABEL("layout", "nsLayoutUtils::DrawBackgroundImage");
+  PROFILER_LABEL("nsLayoutUtils", "DrawBackgroundImage",
+    js::ProfileEntry::Category::GRAPHICS);
 
   if (UseBackgroundNearestFiltering()) {
     aGraphicsFilter = GraphicsFilter::FILTER_NEAREST;
   }
 
   return DrawImageInternal(aRenderingContext, aImage, aGraphicsFilter,
                            aDest, aFill, aAnchor, aDirty,
                            aImageSize, nullptr, aImageFlags);
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -3961,18 +3961,18 @@ PresShell::FlushPendingNotifications(moz
     "InterruptibleLayout",
     "Layout",
     "Display"
   };
 
   // Make sure that we don't miss things added to mozFlushType!
   MOZ_ASSERT(static_cast<uint32_t>(flushType) <= ArrayLength(flushTypeNames));
 
-  PROFILER_LABEL_PRINTF("layout", "Flush", "(Flush_%s)",
-                      flushTypeNames[flushType - 1]);
+  PROFILER_LABEL_PRINTF("PresShell", "Flush",
+    js::ProfileEntry::Category::GRAPHICS, "(Flush_%s)", flushTypeNames[flushType - 1]);
 #endif
 
 #ifdef ACCESSIBILITY
 #ifdef DEBUG
   nsAccessibilityService* accService = GetAccService();
   if (accService) {
     NS_ASSERTION(!accService->IsProcessingRefreshDriverNotification(),
                  "Flush during accessible tree update!");
@@ -5808,17 +5808,19 @@ PresShell::RestyleShadowRoot(ShadowRoot*
   }
 }
 
 void
 PresShell::Paint(nsView*        aViewToPaint,
                  const nsRegion& aDirtyRegion,
                  uint32_t        aFlags)
 {
-  PROFILER_LABEL("Paint", "PresShell::Paint");
+  PROFILER_LABEL("PresShell", "Paint",
+    js::ProfileEntry::Category::GRAPHICS);
+
   NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
   NS_ASSERTION(aViewToPaint, "null view");
 
   MOZ_ASSERT(!mImageVisibilityVisited, "should have been cleared");
 
   if (!mIsActive || mIsZombie) {
     return;
   }
@@ -8365,17 +8367,19 @@ PresShell::DoReflow(nsIFrame* target, bo
     nsSVGEffects::InvalidateDirectRenderingObservers(parent);
     parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
   }
 
   nsAutoCString docURL("N/A");
   nsIURI *uri = mDocument->GetDocumentURI();
   if (uri)
     uri->GetSpec(docURL);
-  PROFILER_LABEL_PRINTF("layout", "DoReflow", "(%s)", docURL.get());
+
+  PROFILER_LABEL_PRINTF("PresShell", "DoReflow",
+    js::ProfileEntry::Category::GRAPHICS, "(%s)", docURL.get());
 
   if (mReflowContinueTimer) {
     mReflowContinueTimer->Cancel();
     mReflowContinueTimer = nullptr;
   }
 
   nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
 
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1051,17 +1051,18 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
                   "Shouldn't have a JSContext on the stack");
 
   if (nsNPAPIPluginInstance::InPluginCallUnsafeForReentry()) {
     NS_ERROR("Refresh driver should not run during plugin call!");
     // Try to survive this by just ignoring the refresh tick.
     return;
   }
 
-  PROFILER_LABEL("nsRefreshDriver", "Tick");
+  PROFILER_LABEL("nsRefreshDriver", "Tick",
+    js::ProfileEntry::Category::GRAPHICS);
 
   // We're either frozen or we were disconnected (likely in the middle
   // of a tick iteration).  Just do nothing here, since our
   // prescontext went away.
   if (IsFrozen() || !mPresContext) {
     return;
   }
 
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -4522,17 +4522,19 @@ public:
   }
 
   bool mDisableSubpixelAA;
 };
 
 void
 nsDisplayText::Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) {
-  PROFILER_LABEL("nsDisplayText", "Paint");
+  PROFILER_LABEL("nsDisplayText", "Paint",
+    js::ProfileEntry::Category::GRAPHICS);
+
   // Add 1 pixel of dirty area around mVisibleRect to allow us to paint
   // antialiased pixels beyond the measured text extents.
   // This is temporary until we do this in the actual calculation of text extents.
   nsRect extraVisible = mVisibleRect;
   nscoord appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
   extraVisible.Inflate(appUnitsPerDevPixel, appUnitsPerDevPixel);
   nsTextFrame* f = static_cast<nsTextFrame*>(mFrame);
 
@@ -5328,17 +5330,19 @@ void
 nsTextFrame::PaintOneShadow(uint32_t aOffset, uint32_t aLength,
                             nsCSSShadowItem* aShadowDetails,
                             PropertyProvider* aProvider, const nsRect& aDirtyRect,
                             const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt,
                             gfxContext* aCtx, const nscolor& aForegroundColor,
                             const nsCharClipDisplayItem::ClipEdges& aClipEdges,
                             nscoord aLeftSideOffset, gfxRect& aBoundingBox)
 {
-  PROFILER_LABEL("nsTextFrame", "PaintOneShadow");
+  PROFILER_LABEL("nsTextFrame", "PaintOneShadow",
+    js::ProfileEntry::Category::GRAPHICS);
+
   gfxPoint shadowOffset(aShadowDetails->mXOffset, aShadowDetails->mYOffset);
   nscoord blurRadius = std::max(aShadowDetails->mRadius, 0);
 
   // This rect is the box which is equivalent to where the shadow will be painted.
   // The origin of aBoundingBox is the text baseline left, so we must translate it by
   // that much in order to make the origin the top-left corner of the text bounding box.
   gfxRect shadowGfxRect = aBoundingBox +
     gfxPoint(aFramePt.x + aLeftSideOffset, aTextBaselinePt.y) + shadowOffset;
--- a/layout/generic/nsViewportFrame.cpp
+++ b/layout/generic/nsViewportFrame.cpp
@@ -43,17 +43,19 @@ ViewportFrame::Init(nsIContent*       aC
   }
 }
 
 void
 ViewportFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists)
 {
-  PROFILER_LABEL("ViewportFrame", "BuildDisplayList");
+  PROFILER_LABEL("ViewportFrame", "BuildDisplayList",
+    js::ProfileEntry::Category::GRAPHICS);
+
   nsIFrame* kid = mFrames.FirstChild();
   if (!kid)
     return;
 
   // make the kid's BorderBackground our own. This ensures that the canvas
   // frame's background becomes our own background and therefore appears
   // below negative z-index elements.
   BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -404,17 +404,18 @@ nsStyleContext::ApplyStyleFixups(bool aS
   // Compute User Interface style, to trigger loads of cursors
   StyleUserInterface();
 }
 
 nsChangeHint
 nsStyleContext::CalcStyleDifference(nsStyleContext* aOther,
                                     nsChangeHint aParentHintsNotHandledForDescendants)
 {
-  PROFILER_LABEL("nsStyleContext", "CalcStyleDifference");
+  PROFILER_LABEL("nsStyleContext", "CalcStyleDifference",
+    js::ProfileEntry::Category::CSS);
 
   NS_ABORT_IF_FALSE(NS_IsHintSubset(aParentHintsNotHandledForDescendants,
                                     nsChangeHint_Hints_NotHandledForDescendants),
                     "caller is passing inherited hints, but shouldn't be");
 
   nsChangeHint hint = NS_STYLE_HINT_NONE;
   NS_ENSURE_TRUE(aOther, hint);
   // We must always ensure that we populate the structs on the new style
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -945,17 +945,18 @@ nsStyleSet::AssertNoCSSRules(nsRuleNode*
 #endif
 
 // Enumerate the rules in a way that cares about the order of the rules.
 void
 nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc, 
                       RuleProcessorData* aData, Element* aElement,
                       nsRuleWalker* aRuleWalker)
 {
-  PROFILER_LABEL("nsStyleSet", "FileRules");
+  PROFILER_LABEL("nsStyleSet", "FileRules",
+    js::ProfileEntry::Category::CSS);
 
   // Cascading order:
   // [least important]
   //  - UA normal rules                    = Agent        normal
   //  - User normal rules                  = User         normal
   //  - Presentation hints                 = PresHint     normal
   //  - Author normal rules                = Document     normal
   //  - Override normal rules              = Override     normal
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -1698,17 +1698,19 @@ abstract public class BrowserApp extends
                     return;
                 }
 
                 recordSearch(null, "barkeyword");
 
                 // Otherwise, construct a search query from the bookmark keyword.
                 final String searchUrl = keywordUrl.replace("%s", URLEncoder.encode(keywordSearch));
                 Tabs.getInstance().loadUrl(searchUrl, Tabs.LOADURL_USER_ENTERED);
-                Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, "", "keyword");
+                Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL,
+                                      TelemetryContract.Method.NONE,
+                                      "keyword");
             }
         });
     }
 
     /**
      * Record in Health Report that a search has occurred.
      *
      * @param engine
--- a/mobile/android/base/DataReportingNotification.java
+++ b/mobile/android/base/DataReportingNotification.java
@@ -122,13 +122,12 @@ public class DataReportingNotification {
             SharedPreferences.Editor editor = sharedPrefs.edit();
             long now = System.currentTimeMillis();
             editor.putLong(PREFS_POLICY_NOTIFIED_TIME, now);
             editor.putInt(PREFS_POLICY_VERSION, DATA_REPORTING_VERSION);
             editor.commit();
             result = true;
         } finally {
             // We want to track any errors, so record notification outcome.
-            final String notificationEvent = TelemetryContract.Event.POLICY_NOTIFICATION_SUCCESS + result;
-            Telemetry.sendUIEvent(notificationEvent);
+            Telemetry.sendUIEvent(TelemetryContract.Event.POLICY_NOTIFICATION_SUCCESS, result);
         }
     }
 }
--- a/mobile/android/base/Telemetry.java
+++ b/mobile/android/base/Telemetry.java
@@ -1,23 +1,27 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.mozglue.RobocopTarget;
+import org.mozilla.gecko.TelemetryContract.Event;
+import org.mozilla.gecko.TelemetryContract.Method;
+import org.mozilla.gecko.TelemetryContract.Reason;
+import org.mozilla.gecko.TelemetryContract.Session;
 
 import android.os.SystemClock;
 import android.util.Log;
 
 /**
  * All telemetry times are relative to one of two clocks:
- * 
+ *
  * * Real time since the device was booted, including deep sleep. Use this
  *   as a substitute for wall clock.
  * * Uptime since the device was booted, excluding deep sleep. Use this to
  *   avoid timing a user activity when their phone is in their pocket!
  *
  * The majority of methods in this class are defined in terms of real time.
  */
 @RobocopTarget
@@ -102,46 +106,94 @@ public class Telemetry {
         }
 
         @Override
         protected long now() {
             return Telemetry.uptime();
         }
     }
 
-    public static void startUISession(String sessionName) {
+    public static void startUISession(final Session session, final String sessionNameSuffix) {
+        final String sessionName = getSessionName(session, sessionNameSuffix);
+
         Log.d(LOGTAG, "StartUISession: " + sessionName);
-        GeckoEvent event = GeckoEvent.createTelemetryUISessionStartEvent(sessionName, realtime());
-        GeckoAppShell.sendEventToGecko(event);
+        final GeckoEvent geckoEvent =
+                GeckoEvent.createTelemetryUISessionStartEvent(sessionName, realtime());
+        GeckoAppShell.sendEventToGecko(geckoEvent);
+    }
+
+    public static void startUISession(final Session session) {
+        startUISession(session, null);
     }
 
-    public static void stopUISession(String sessionName, String reason) {
+    public static void stopUISession(final Session session, final String sessionNameSuffix,
+            final Reason reason) {
+        final String sessionName = getSessionName(session, sessionNameSuffix);
+
         Log.d(LOGTAG, "StopUISession: " + sessionName + ", reason=" + reason);
-        GeckoEvent event = GeckoEvent.createTelemetryUISessionStopEvent(sessionName, reason, realtime());
-        GeckoAppShell.sendEventToGecko(event);
+        final GeckoEvent geckoEvent = GeckoEvent.createTelemetryUISessionStopEvent(
+                sessionName, reason.toString(), realtime());
+        GeckoAppShell.sendEventToGecko(geckoEvent);
+    }
+
+    public static void stopUISession(final Session session, final Reason reason) {
+        stopUISession(session, null, reason);
     }
 
-    public static void stopUISession(String sessionName) {
-        stopUISession(sessionName, null);
+    public static void stopUISession(final Session session, final String sessionNameSuffix) {
+        stopUISession(session, sessionNameSuffix, Reason.NONE);
+    }
+
+    public static void stopUISession(final Session session) {
+        stopUISession(session, null, Reason.NONE);
+    }
+
+    private static String getSessionName(final Session session, final String sessionNameSuffix) {
+        if (sessionNameSuffix != null) {
+            return session.toString() + ":" + sessionNameSuffix;
+        } else {
+            return session.toString();
+        }
     }
 
-    public static void sendUIEvent(String action, String method, long timestamp, String extras) {
-        Log.d(LOGTAG, "SendUIEvent: action = " + action + " method = " + method + " timestamp = " + timestamp + " extras = " + extras);
-        GeckoEvent event = GeckoEvent.createTelemetryUIEvent(action, method, timestamp, extras);
-        GeckoAppShell.sendEventToGecko(event);
+    private static void sendUIEvent(final String eventName, final Method method,
+            final long timestamp, final String extras) {
+        Log.d(LOGTAG, "SendUIEvent: event = " + eventName + " method = " + method +
+                " timestamp = " + timestamp + " extras = " + extras);
+        final GeckoEvent geckoEvent = GeckoEvent.createTelemetryUIEvent(
+                eventName, method.toString(), timestamp, extras);
+        GeckoAppShell.sendEventToGecko(geckoEvent);
     }
 
-    public static void sendUIEvent(String action, String method, long timestamp) {
-        sendUIEvent(action, method, timestamp, null);
+    public static void sendUIEvent(final Event event, final Method method, final long timestamp,
+            final String extras) {
+        sendUIEvent(event.toString(), method, timestamp, extras);
+    }
+
+    public static void sendUIEvent(final Event event, final Method method, final long timestamp) {
+        sendUIEvent(event, method, timestamp, null);
+    }
+
+    public static void sendUIEvent(final Event event, final Method method, final String extras) {
+        sendUIEvent(event, method, realtime(), extras);
     }
 
-    public static void sendUIEvent(String action, String method, String extras) {
-        sendUIEvent(action, method, realtime(), extras);
+    public static void sendUIEvent(final Event event, final Method method) {
+        sendUIEvent(event, method, realtime(), null);
+    }
+
+    public static void sendUIEvent(final Event event) {
+        sendUIEvent(event, Method.NONE, realtime(), null);
     }
 
-    public static void sendUIEvent(String action, String method) {
-        sendUIEvent(action, method, realtime(), null);
-    }
-
-    public static void sendUIEvent(String action) {
-        sendUIEvent(action, null, realtime(), null);
+    /**
+     * Sends a UIEvent with the given status appended to the event name.
+     *
+     * This method is a slight bend of the Telemetry framework so chances
+     * are that you don't want to use this: please think really hard before you do.
+     *
+     * Intended for use with data policy notifications.
+     */
+    public static void sendUIEvent(final Event event, final boolean eventStatus) {
+        final String eventName = event + ":" + eventStatus;
+        sendUIEvent(eventName, Method.NONE, realtime(), null);
     }
 }
--- a/mobile/android/base/TelemetryContract.java
+++ b/mobile/android/base/TelemetryContract.java
@@ -1,152 +1,231 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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/. */
 
 package org.mozilla.gecko;
 
+import org.mozilla.gecko.mozglue.RobocopTarget;
+
 /**
  * Holds data definitions for our UI Telemetry implementation.
  *
+ * Note that enum values of "_TEST*" are reserved for testing and
+ * should not be changed without changing the associated tests.
+ *
  * See mobile/android/base/docs/index.rst for a full dictionary.
  */
+@RobocopTarget
 public interface TelemetryContract {
 
     /**
      * Holds event names. Intended for use with
      * Telemetry.sendUIEvent() as the "action" parameter.
      *
      * Please keep this list sorted.
      */
-    public interface Event {
+    public enum Event {
         // Generic action, usually for tracking menu and toolbar actions.
-        public static final String ACTION = "action.1";
+        ACTION("action.1"),
 
         // Cancel a state, action, etc.
-        public static final String CANCEL = "cancel.1";
+        CANCEL("cancel.1"),
 
         // Editing an item.
-        public static final String EDIT = "edit.1";
+        EDIT("edit.1"),
 
         // Launching (opening) an external application.
         // Note: Only used in JavaScript for now, but here for completeness.
-        public static final String LAUNCH = "launch.1";
+        LAUNCH("launch.1"),
 
         // Loading a URL.
-        public static final String LOAD_URL = "loadurl.1";
+        LOAD_URL("loadurl.1"),
 
-        public static final String LOCALE_BROWSER_RESET = "locale.browser.reset.1";
-        public static final String LOCALE_BROWSER_SELECTED = "locale.browser.selected.1";
-        public static final String LOCALE_BROWSER_UNSELECTED = "locale.browser.unselected.1";
+        LOCALE_BROWSER_RESET("locale.browser.reset.1"),
+        LOCALE_BROWSER_SELECTED("locale.browser.selected.1"),
+        LOCALE_BROWSER_UNSELECTED("locale.browser.unselected.1"),
 
         // Set default panel.
-        public static final String PANEL_SET_DEFAULT = "setdefault.1";
+        PANEL_SET_DEFAULT("setdefault.1"),
 
         // Pinning an item.
-        public static final String PIN = "pin.1";
+        PIN("pin.1"),
 
         // Outcome of data policy notification: can be true or false.
-        public static final String POLICY_NOTIFICATION_SUCCESS = "policynotification.success.1:";
+        POLICY_NOTIFICATION_SUCCESS("policynotification.success.1"),
 
         // Sanitizing private data.
-        public static final String SANITIZE = "sanitize.1";
+        SANITIZE("sanitize.1"),
 
         // Saving a resource (reader, bookmark, etc) for viewing later.
         // Note: Only used in JavaScript for now, but here for completeness.
-        public static final String SAVE = "save.1";
+        SAVE("save.1"),
 
         // Sharing content.
-        public static final String SHARE = "share.1";
+        SHARE("share.1"),
 
         // Unpinning an item.
-        public static final String UNPIN = "unpin.1";
+        UNPIN("unpin.1"),
 
         // Stop holding a resource (reader, bookmark, etc) for viewing later.
         // Note: Only used in JavaScript for now, but here for completeness.
-        public static final String UNSAVE = "unsave.1";
+        UNSAVE("unsave.1"),
+
+        // VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
+        _TEST1("_test_event_1.1"),
+        _TEST2("_test_event_2.1"),
+        _TEST3("_test_event_3.1"),
+        _TEST4("_test_event_4.1"),
+        ;
+
+        private final String string;
+
+        Event(final String string) {
+            this.string = string;
+        }
+
+        @Override
+        public String toString() {
+            return string;
+        }
     }
 
     /**
      * Holds event methods. Intended for use in
      * Telemetry.sendUIEvent() as the "method" parameter.
      *
      * Please keep this list sorted.
      */
-    public interface Method {
+    public enum Method {
         // Action triggered from the action bar (including the toolbar).
-        public static final String ACTIONBAR = "actionbar";
+        ACTIONBAR("actionbar"),
 
         // Action triggered by hitting the Android back button.
-        public static final String BACK = "back";
+        BACK("back"),
 
         // Action triggered from a button.
-        public static final String BUTTON = "button";
+        BUTTON("button"),
 
         // Action occurred via a context menu.
-        public static final String CONTEXT_MENU = "contextmenu";
+        CONTEXT_MENU("contextmenu"),
 
         // Action triggered from a dialog.
-        public static final String DIALOG = "dialog";
+        DIALOG("dialog"),
 
         // Action triggered from a view grid item, like a thumbnail.
-        public static final String GRID_ITEM = "griditem";
+        GRID_ITEM("griditem"),
 
         // Action occurred via an intent.
-        public static final String INTENT = "intent";
+        INTENT("intent"),
 
         // Action triggered from a list.
-        public static final String LIST = "list";
+        LIST("list"),
 
         // Action triggered from a view list item, like a row of a list.
-        public static final String LIST_ITEM = "listitem";
+        LIST_ITEM("listitem"),
 
         // Action occurred via the main menu.
-        public static final String MENU = "menu";
+        MENU("menu"),
+
+        // No method is specified.
+        NONE(null),
 
         // Action triggered from a pageaction in the URLBar.
         // Note: Only used in JavaScript for now, but here for completeness.
-        public static final String PAGEACTION = "pageaction";
+        PAGEACTION("pageaction"),
 
         // Action triggered from a suggestion provided to the user.
-        public static final String SUGGESTION = "suggestion";
+        SUGGESTION("suggestion"),
+
+        // VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
+        _TEST1("_test_method_1"),
+        _TEST2("_test_method_2"),
+        ;
+
+        private final String string;
+
+        Method(final String string) {
+            this.string = string;
+        }
+
+        @Override
+        public String toString() {
+            return string;
+        }
     }
 
     /**
      * Holds session names. Intended for use with
      * Telemetry.startUISession() as the "sessionName" parameter.
      *
      * Please keep this list sorted.
      */
-    public interface Session {
+    public enum Session {
         // Awesomescreen (including frecency search) is active.
-        public static final String AWESOMESCREEN = "awesomescreen.1";
+        AWESOMESCREEN("awesomescreen.1"),
 
         // Started the very first time we believe the application has been launched.
-        public static final String FIRSTRUN = "firstrun.1";
+        FIRSTRUN("firstrun.1"),
 
         // Awesomescreen frecency search is active.
-        public static final String FRECENCY = "frecency.1";
+        FRECENCY("frecency.1"),
 
         // Started when a user enters about:home.
-        public static final String HOME = "home.1";
+        HOME("home.1"),
 
         // Started when a user enters a given home panel.
         // Session name is dynamic, encoded as "homepanel.1:<panel_id>"
-        public static final String HOME_PANEL = "homepanel.1:";
+        HOME_PANEL("homepanel.1"),
 
         // Started when a Reader viewer becomes active in the foreground.
         // Note: Only used in JavaScript for now, but here for completeness.
-        public static final String READER = "reader.1";
+        READER("reader.1"),
+
+        // VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
+        _TEST_STARTED_TWICE("_test_session_started_twice.1"),
+        _TEST_STOPPED_TWICE("_test_session_stopped_twice.1"),
+        ;
+
+        private final String string;
+
+        Session(final String string) {
+            this.string = string;
+        }
+
+        @Override
+        public String toString() {
+            return string;
+        }
     }
 
     /**
      * Holds reasons for stopping a session. Intended for use in
      * Telemetry.stopUISession() as the "reason" parameter.
      *
      * Please keep this list sorted.
      */
-    public interface Reason {
+    public enum Reason {
         // Changes were committed.
-        public static final String COMMIT = "commit";
+        COMMIT("commit"),
+
+        // No reason is specified.
+        NONE(null),
+
+        // VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
+        _TEST1("_test_reason_1"),
+        _TEST2("_test_reason_2"),
+        _TEST_IGNORED("_test_reason_ignored"),
+        ;
+
+        private final String string;
+
+        Reason(final String string) {
+            this.string = string;
+        }
+
+        @Override
+        public String toString() {
+            return string;
+        }
     }
 }
--- a/mobile/android/base/home/HomePager.java
+++ b/mobile/android/base/home/HomePager.java
@@ -48,17 +48,18 @@ public class HomePager extends ViewPager
     private ConfigLoaderCallbacks mConfigLoaderCallbacks;
 
     private String mInitialPanelId;
 
     // Cached original ViewPager background.
     private final Drawable mOriginalBackground;
 
     // Telemetry session for current panel.
-    private String mCurrentPanelSession;
+    private TelemetryContract.Session mCurrentPanelSession;
+    private String mCurrentPanelSessionSuffix;
 
     // Current load state of HomePager.
     private LoadState mLoadState;
 
     // Listens for when the current panel changes.
     private OnPanelChangeListener mPanelChangedListener;
 
     // This is mostly used by UI tests to easily fetch
@@ -504,22 +505,24 @@ public class HomePager extends ViewPager
      * it will be stopped before a new one is started.
      *
      * @param panelId of panel to start a session for
      */
     private void startNewPanelTelemetrySession(String panelId) {
         // Stop the current panel's session if we have one.
         stopCurrentPanelTelemetrySession();
 
-        mCurrentPanelSession = TelemetryContract.Session.HOME_PANEL + panelId;
-        Telemetry.startUISession(mCurrentPanelSession);
+        mCurrentPanelSession = TelemetryContract.Session.HOME_PANEL;
+        mCurrentPanelSessionSuffix = panelId;
+        Telemetry.startUISession(mCurrentPanelSession, mCurrentPanelSessionSuffix);
     }
 
     /**
      * Stop the current panel telemetry session if one exists.
      */
     private void stopCurrentPanelTelemetrySession() {
         if (mCurrentPanelSession != null) {
-            Telemetry.stopUISession(mCurrentPanelSession);
+            Telemetry.stopUISession(mCurrentPanelSession, mCurrentPanelSessionSuffix);
             mCurrentPanelSession = null;
+            mCurrentPanelSessionSuffix = null;
         }
     }
 }
--- a/mobile/android/base/home/TopSitesGridView.java
+++ b/mobile/android/base/home/TopSitesGridView.java
@@ -108,17 +108,17 @@ public class TopSitesGridView extends Gr
                 // Decode "user-entered" URLs before loading them.
                 String url = HomeFragment.decodeUserEnteredUrl(item.getUrl());
                 int type = item.getType();
 
                 // If the url is empty, the user can pin a site.
                 // If not, navigate to the page given by the url.
                 if (type != TopSites.TYPE_BLANK) {
                     if (mUrlOpenListener != null) {
-                        final String method;
+                        final TelemetryContract.Method method;
                         if (type == TopSites.TYPE_SUGGESTED) {
                             method = TelemetryContract.Method.SUGGESTION;
                         } else {
                             method = TelemetryContract.Method.GRID_ITEM;
                         }
                         Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, method, Integer.toString(position));
 
                         mUrlOpenListener.onUrlOpen(url, EnumSet.noneOf(OnUrlOpenListener.Flags.class));
--- a/mobile/android/base/resources/values-large-land-v11/styles.xml
+++ b/mobile/android/base/resources/values-large-land-v11/styles.xml
@@ -46,9 +46,41 @@
 
     <style name="Widget.Home.HistoryTabWidget">
         <item name="android:showDividers">beginning|middle|end</item>
         <item name="android:dividerPadding">0dp</item>
         <item name="android:paddingLeft">100dp</item>
         <item name="android:paddingTop">30dp</item>
     </style>
 
+    <!-- Remote tabs panel -->
+    <style name="RemoteTabsPanelChild" parent="RemoteTabsPanelChildBase">
+        <item name="android:paddingTop">32dp</item>
+        <!-- Additional spacing set via margins on RemoteTabsSection. -->
+        <item name="android:paddingLeft">0dp</item>
+        <item name="android:paddingRight">0dp</item>
+    </style>
+
+    <style name="RemoteTabsSection" parent="RemoteTabsSectionBase">
+        <!-- To override the values-land style. -->
+    </style>
+
+    <style name="RemoteTabsItem" parent="RemoteTabsItemBase">
+        <!-- To override the values-land style. -->
+    </style>
+
+    <style name="RemoteTabsItem.Button" parent="RemoteTabsItem.ButtonBase">
+        <item name="android:paddingTop">12dp</item>
+        <item name="android:paddingBottom">12dp</item>
+        <item name="android:paddingLeft">36dp</item>
+        <item name="android:paddingRight">36dp</item>
+        <item name="android:textSize">16dp</item>
+    </style>
+
+    <style name="RemoteTabsItem.TextAppearance.Header.FXAccounts">
+        <item name="android:visibility">gone</item>
+    </style>
+
+    <style name="RemoteTabsItem.TextAppearance.Linkified.Resend">
+        <item name="android:layout_height">wrap_content</item>
+    </style>
+
 </resources>
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -447,43 +447,44 @@
          <item name="android:childDivider">@drawable/remote_tabs_child_divider</item>
          <item name="android:groupIndicator">@android:color/transparent</item>
     </style>
 
     <!-- Remote tabs panel -->
     <style name="RemoteTabsPanelChildBase">
         <item name="android:paddingLeft">16dp</item>
         <item name="android:paddingRight">16dp</item>
+        <item name="android:paddingTop">62dp</item>
+        <item name="android:orientation">vertical</item>
     </style>
 
     <style name="RemoteTabsPanelChild" parent="RemoteTabsPanelChildBase">
-        <item name="android:orientation">vertical</item>
-        <item name="android:paddingTop">62dp</item>
+        <!-- We set values in landscape. -->
     </style>
 
     <style name="RemoteTabsSectionBase">
         <item name="android:orientation">vertical</item>
         <item name="android:layout_marginLeft">16dp</item>
         <item name="android:layout_marginRight">16dp</item>
     </style>
 
     <style name="RemoteTabsSection" parent="RemoteTabsSectionBase">
         <!-- We set values in landscape. -->
     </style>
 
-    <style name="RemoteTabsSection.Resend" parent="RemoteTabsSectionBase">
-        <!-- We set values in landscape. -->
-    </style>
-
-    <style name="RemoteTabsItem">
+    <style name="RemoteTabsItemBase">
         <item name="android:layout_marginBottom">28dp</item>
         <item name="android:layout_gravity">center</item>
         <item name="android:gravity">center</item>
     </style>
 
+    <style name="RemoteTabsItem" parent="RemoteTabsItemBase">
+        <!-- We set values in landscape. -->
+    </style>
+
     <style name="RemoteTabsItem.ButtonBase">
         <item name="android:background">@drawable/remote_tabs_setup_button_background</item>
         <item name="android:textColor">#FFFEFF</item>
         <item name="android:textSize">20sp</item>
     </style>
 
     <style name="RemoteTabsItem.Button" parent="RemoteTabsItem.ButtonBase">
         <item name="android:paddingTop">18dp</item>
--- a/mobile/android/base/sqlite/SQLiteBridge.java
+++ b/mobile/android/base/sqlite/SQLiteBridge.java
@@ -5,44 +5,52 @@
 package org.mozilla.gecko.sqlite;
 
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
 import android.text.TextUtils;
 import android.util.Log;
+
 import org.mozilla.gecko.mozglue.RobocopTarget;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Map.Entry;
 
 /*
  * This class allows using the mozsqlite3 library included with Firefox
  * to read SQLite databases, instead of the Android SQLiteDataBase API,
  * which might use whatever outdated DB is present on the Android system.
  */
 public class SQLiteBridge {
     private static final String LOGTAG = "SQLiteBridge";
 
     // Path to the database. If this database was not opened with openDatabase, we reopen it every query.
     private String mDb;
-    // pointer to the database if it was opened with openDatabase
-    protected long mDbPointer = 0;
+
+    // Pointer to the database if it was opened with openDatabase. 0 implies closed.
+    protected volatile long mDbPointer = 0L;
 
     // Values remembered after a query.
     private long[] mQueryResults;
 
     private boolean mTransactionSuccess = false;
     private boolean mInTransaction = false;
 
     private static final int RESULT_INSERT_ROW_ID = 0;
     private static final int RESULT_ROWS_CHANGED = 1;
 
+    // Shamelessly cribbed from db/sqlite3/src/moz.build.
+    private static final int DEFAULT_PAGE_SIZE_BYTES = 32768;
+
+    // The same size we use elsewhere.
+    private static final int MAX_WAL_SIZE_BYTES = 524288;
+
     // JNI code in $(topdir)/mozglue/android/..
     private static native MatrixBlobCursor sqliteCall(String aDb, String aQuery,
                                                       String[] aParams,
                                                       long[] aUpdateResult)
         throws SQLiteBridgeException;
     private static native MatrixBlobCursor sqliteCallWithDb(long aDb, String aQuery,
                                                             String[] aParams,
                                                             long[] aUpdateResult)
@@ -249,31 +257,34 @@ public class SQLiteBridge {
             throw new RuntimeException("flags not supported.");
         }
 
         SQLiteBridge bridge = null;
         try {
             bridge = new SQLiteBridge(path);
             bridge.mDbPointer = SQLiteBridge.openDatabase(path);
         } catch (SQLiteBridgeException ex) {
-            // catch and rethrow as a SQLiteException to match SQLiteDatabase
+            // Catch and rethrow as a SQLiteException to match SQLiteDatabase.
             throw new SQLiteException(ex.getMessage());
         }
+
+        prepareWAL(bridge);
+
         return bridge;
     }
 
     public void close() {
         if (isOpen()) {
           closeDatabase(mDbPointer);
         }
-        mDbPointer = 0;
+        mDbPointer = 0L;
     }
 
     public boolean isOpen() {
-        return mDbPointer > 0;
+        return mDbPointer != 0;
     }
 
     public void beginTransaction() throws SQLiteBridgeException {
         if (inTransaction()) {
             throw new SQLiteBridgeException("Nested transactions are not supported");
         }
         execSQL("BEGIN EXCLUSIVE");
         mTransactionSuccess = false;
@@ -319,9 +330,55 @@ public class SQLiteBridge {
 
     @Override
     public void finalize() {
         if (isOpen()) {
             Log.e(LOGTAG, "Bridge finalized without closing the database");
             close();
         }
     }
+
+    private static void prepareWAL(final SQLiteBridge bridge) {
+        // Prepare for WAL mode. If we can, we switch to journal_mode=WAL, then
+        // set the checkpoint size appropriately. If we can't, then we fall back
+        // to truncating and synchronous writes.
+        final Cursor cursor = bridge.internalQuery("PRAGMA journal_mode=WAL", null);
+        try {
+            if (cursor.moveToFirst()) {
+                String journalMode = cursor.getString(0);
+                Log.d(LOGTAG, "Journal mode: " + journalMode);
+                if ("wal".equals(journalMode)) {
+                    // Success! Let's make sure we autocheckpoint at a reasonable interval.
+                    final int pageSizeBytes = bridge.getPageSizeBytes();
+                    final int checkpointPageCount = MAX_WAL_SIZE_BYTES / pageSizeBytes;
+                    bridge.internalQuery("PRAGMA wal_autocheckpoint=" + checkpointPageCount, null).close();
+                } else {
+                    if (!"truncate".equals(journalMode)) {
+                        Log.w(LOGTAG, "Unable to activate WAL journal mode. Using truncate instead.");
+                        bridge.internalQuery("PRAGMA journal_mode=TRUNCATE", null).close();
+                    }
+                    Log.w(LOGTAG, "Not using WAL mode: using synchronous=FULL instead.");
+                    bridge.internalQuery("PRAGMA synchronous=FULL", null).close();
+                }
+            }
+        } finally {
+            cursor.close();
+        }
+    }
+
+    private int getPageSizeBytes() {
+        if (!isOpen()) {
+            throw new IllegalStateException("Database not open.");
+        }
+
+        final Cursor cursor = internalQuery("PRAGMA page_size", null);
+        try {
+            if (!cursor.moveToFirst()) {
+                Log.w(LOGTAG, "Unable to retrieve page size.");
+                return DEFAULT_PAGE_SIZE_BYTES;
+            }
+
+            return cursor.getInt(0);
+        } finally {
+            cursor.close();
+        }
+    }
 }
--- a/mobile/android/base/tabspanel/RemoteTabsList.java
+++ b/mobile/android/base/tabspanel/RemoteTabsList.java
@@ -65,17 +65,17 @@ class RemoteTabsList extends ExpandableL
     @Override
     public boolean onChildClick(ExpandableListView parent, View view, int groupPosition, int childPosition, long id) {
         HashMap <String, String> tab = tabsList.get(groupPosition).get(childPosition);
         if (tab == null) {
             autoHidePanel();
             return true;
         }
 
-        Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, "", "remote");
+        Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.NONE, "remote");
 
         Tabs.getInstance().loadUrl(tab.get("url"), Tabs.LOADURL_NEW_TAB);
         autoHidePanel();
         return true;
     }
 
     @Override
     public void onQueryTabsComplete(List<TabsAccessor.RemoteTab> remoteTabsList) {
--- a/mobile/android/base/tabspanel/RemoteTabsSetupPanel.java
+++ b/mobile/android/base/tabspanel/RemoteTabsSetupPanel.java
@@ -6,17 +6,16 @@ package org.mozilla.gecko.tabspanel;
 
 import java.util.Locale;
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.fxa.FirefoxAccounts;
 import org.mozilla.gecko.fxa.activities.FxAccountCreateAccountActivity;
 import org.mozilla.gecko.tabspanel.TabsPanel.PanelView;
-import org.mozilla.gecko.util.HardwareUtils;
 
 import android.content.Context;
 import android.content.Intent;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.LinearLayout;
 
 /**
@@ -64,21 +63,16 @@ class RemoteTabsSetupPanel extends Linea
 
     @Override
     public void setTabsPanel(TabsPanel panel) {
         tabsPanel = panel;
     }
 
     @Override
     public void show() {
-        // We don't have a tablet implementation of this panel.
-        if (HardwareUtils.isTablet()) {
-            return;
-        }
-
         setVisibility(View.VISIBLE);
     }
 
     @Override
     public void hide() {
         setVisibility(View.GONE);
     }
 
--- a/mobile/android/base/tabspanel/RemoteTabsVerificationPanel.java
+++ b/mobile/android/base/tabspanel/RemoteTabsVerificationPanel.java
@@ -3,17 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tabspanel;
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.fxa.FirefoxAccounts;
 import org.mozilla.gecko.fxa.login.State;
 import org.mozilla.gecko.tabspanel.TabsPanel.PanelView;
-import org.mozilla.gecko.util.HardwareUtils;
 
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
@@ -93,21 +92,16 @@ class RemoteTabsVerificationPanel extend
 
     @Override
     public void setTabsPanel(TabsPanel panel) {
         tabsPanel = panel;
     }
 
     @Override
     public void show() {
-        // We don't have a tablet implementation of this panel.
-        if (HardwareUtils.isTablet()) {
-            return;
-        }
-
         refresh();
         setVisibility(View.VISIBLE);
     }
 
     @Override
     public void hide() {
         setVisibility(View.GONE);
     }
--- a/mobile/android/base/tests/testUITelemetry.java
+++ b/mobile/android/base/tests/testUITelemetry.java
@@ -1,48 +1,54 @@
 package org.mozilla.gecko.tests;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.PrefsHelper;
 import org.mozilla.gecko.Telemetry;
+import org.mozilla.gecko.TelemetryContract.Event;
+import org.mozilla.gecko.TelemetryContract.Method;
+import org.mozilla.gecko.TelemetryContract.Reason;
+import org.mozilla.gecko.TelemetryContract.Session;
 
 import android.util.Log;
 
 public class testUITelemetry extends JavascriptTest {
-    // Prefix used to distinguish test events and sessions from
-    // real ones. Used by the javascript part of the test.
-    static final String TEST_PREFIX = "TEST-";
-
     public testUITelemetry() {
         super("testUITelemetry.js");
     }
 
     @Override
     public void testJavascript() throws Exception {
         blockForGeckoReady();
 
         // We can't run these tests unless telemetry is turned on --
         // the events will be dropped on the floor.
         Log.i("GeckoTest", "Enabling telemetry.");
         PrefsHelper.setPref(AppConstants.TELEMETRY_PREF_NAME, true);
 
         Log.i("GeckoTest", "Adding telemetry events.");
         try {
-            Telemetry.sendUIEvent(TEST_PREFIX + "enone", "method0");
-            Telemetry.startUISession(TEST_PREFIX + "foo");
-            Telemetry.sendUIEvent(TEST_PREFIX + "efoo", "method1");
-            Telemetry.startUISession(TEST_PREFIX + "foo");
-            Telemetry.sendUIEvent(TEST_PREFIX + "efoo", "method2");
-            Telemetry.startUISession(TEST_PREFIX + "bar");
-            Telemetry.sendUIEvent(TEST_PREFIX + "efoobar", "method3", "foobarextras");
-            Telemetry.stopUISession(TEST_PREFIX + "foo", "reasonfoo");
-            Telemetry.sendUIEvent(TEST_PREFIX + "ebar", "method4", "barextras");
-            Telemetry.stopUISession(TEST_PREFIX + "bar", "reasonbar");
-            Telemetry.stopUISession(TEST_PREFIX + "bar", "reasonbar2");
-            Telemetry.sendUIEvent(TEST_PREFIX + "enone", "method5");
+            Telemetry.sendUIEvent(Event._TEST1, Method._TEST1);
+            Telemetry.startUISession(Session._TEST_STARTED_TWICE);
+            Telemetry.sendUIEvent(Event._TEST2, Method._TEST1);
+
+            // We can only start one session per name, so this call should be ignored.
+            Telemetry.startUISession(Session._TEST_STARTED_TWICE);
+
+            Telemetry.sendUIEvent(Event._TEST2, Method._TEST2);
+            Telemetry.startUISession(Session._TEST_STOPPED_TWICE);
+            Telemetry.sendUIEvent(Event._TEST3, Method._TEST1, "foobarextras");
+            Telemetry.stopUISession(Session._TEST_STARTED_TWICE, Reason._TEST1);
+            Telemetry.sendUIEvent(Event._TEST4, Method._TEST1, "barextras");
+            Telemetry.stopUISession(Session._TEST_STOPPED_TWICE, Reason._TEST2);
+
+            // This session is already stopped, so this call should be ignored.
+            Telemetry.stopUISession(Session._TEST_STOPPED_TWICE, Reason._TEST_IGNORED);
+
+            Telemetry.sendUIEvent(Event._TEST1, Method._TEST1);
         } catch (Exception e) {
             Log.e("GeckoTest", "Oops.", e);
         }
 
         Log.i("GeckoTest", "Running remaining JS test code.");
         super.testJavascript();
     }
 }
--- a/mobile/android/base/tests/testUITelemetry.js
+++ b/mobile/android/base/tests/testUITelemetry.js
@@ -4,26 +4,62 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 
-const TEST_PREFIX = "TEST-";
-const TEST_REGEX = new RegExp("^" + TEST_PREFIX);
+const EVENT_TEST1 = "_test_event_1.1";
+const EVENT_TEST2 = "_test_event_2.1";
+const EVENT_TEST3 = "_test_event_3.1";
+const EVENT_TEST4 = "_test_event_4.1";
+
+const METHOD_TEST1 = "_test_method_1";
+const METHOD_TEST2 = "_test_method_2";
+
+const REASON_TEST1 = "_test_reason_1";
+const REASON_TEST2 = "_test_reason_2";
+
+const SESSION_STARTED_TWICE = "_test_session_started_twice.1";
+const SESSION_STOPPED_TWICE = "_test_session_stopped_twice.1";
 
 function do_check_array_eq(a1, a2) {
   do_check_eq(a1.length, a2.length);
   for (let i = 0; i < a1.length; ++i) {
     do_check_eq(a1[i], a2[i]);
   }
 }
 
+/**
+ * Asserts that the given measurements are equal. Assumes that measurements
+ * of type "event" have their sessions arrays sorted.
+ */
+function do_check_measurement_eq(m1, m2) {
+  do_check_eq(m1.type, m2.type);
+
+  switch (m1.type) {
+    case "event":
+      do_check_eq(m1.action, m2.action);
+      do_check_eq(m1.method, m2.method);
+      do_check_array_eq(m1.sessions, m2.sessions);
+      do_check_eq(m1.extras, m2.extras);
+      break;
+
+    case "session":
+      do_check_eq(m1.name, m2.name);
+      do_check_eq(m1.reason, m2.reason);
+      break;
+
+    default:
+      do_throw("Unknown event type: " + m1.type);
+  }
+}
+
 function getObserver() {
   let bridge = Cc["@mozilla.org/android/bridge;1"]
                  .getService(Ci.nsIAndroidBridge);
   let obsXPCOM = bridge.browserApp.getUITelemetryObserver();
   do_check_true(!!obsXPCOM);
   return obsXPCOM.wrappedJSObject;
 }
 
@@ -34,54 +70,78 @@ function getObserver() {
 add_test(function test_enabled() {
   let obs = getObserver();
   do_check_true(!!obs);
   do_check_true(obs.enabled);
   run_next_test();
 });
 
 add_test(function test_telemetry_events() {
-  let obs = getObserver();
-  let measurements = obs.getUIMeasurements().filter(function(m) {
-    // Only want events and sessions that were generated by
-    // the Java-side of the test.
-    return TEST_REGEX.test(m.type == "event" ? m.action : m.name);
-  });
+  let expected = expectedArraysToObjs([
+    ["event",   EVENT_TEST1, METHOD_TEST1, [],                                             undefined],
+    ["event",   EVENT_TEST2, METHOD_TEST1, [SESSION_STARTED_TWICE],                        undefined],
+    ["event",   EVENT_TEST2, METHOD_TEST2, [SESSION_STARTED_TWICE],                        undefined],
+    ["event",   EVENT_TEST3, METHOD_TEST1, [SESSION_STARTED_TWICE, SESSION_STOPPED_TWICE], "foobarextras"],
+    ["session", SESSION_STARTED_TWICE, REASON_TEST1],
+    ["event",   EVENT_TEST4, METHOD_TEST1, [SESSION_STOPPED_TWICE],                        "barextras"],
+    ["session", SESSION_STOPPED_TWICE, REASON_TEST2],
+    ["event",   EVENT_TEST1, METHOD_TEST1, [],                                             undefined],
+  ]);
 
-  let expected = [
-    ["event",   TEST_PREFIX + "enone",   "method0", [], null],
-    ["event",   TEST_PREFIX + "efoo",    "method1", [TEST_PREFIX + "foo"], null],
-    ["event",   TEST_PREFIX + "efoo",    "method2", [TEST_PREFIX + "foo"], null],
-    ["event",   TEST_PREFIX + "efoobar", "method3", [TEST_PREFIX + "foo", TEST_PREFIX + "bar"], "foobarextras"],
-    ["session", TEST_PREFIX + "foo",     "reasonfoo"],
-    ["event",   TEST_PREFIX + "ebar",    "method4", [TEST_PREFIX + "bar"], "barextras"],
-    ["session", TEST_PREFIX + "bar",     "reasonbar"],
-    ["event",   TEST_PREFIX + "enone",   "method5", [], null],
-  ];
-
-  do_check_eq(expected.length, measurements.length);
+  let obs = getObserver();
+  let measurements = removeNonTestMeasurements(obs.getUIMeasurements());
 
-  for (let i = 0; i < measurements.length; ++i) {
-    let m = measurements[i];
-
-    let type = m.type;
-    if (type == "event") {
-      let [type, action, method, sessions, extras] = expected[i];
-      do_check_eq(m.action, action);
-      do_check_eq(m.method, method);
-      // might receive real sessions in addition to the test ones -- remove the real ones
-      do_check_array_eq(m.sessions.filter(s => TEST_REGEX.test(s)), sessions);
-      do_check_eq(m.extras, extras);
-      continue;
+  measurements.forEach(function (m, i) {
+    if (m.type === "event") {
+      m.sessions = removeNonTestSessions(m.sessions);
+      m.sessions.sort(); // Mutates.
     }
 
-    if (type == "session") {
-      let [type, name, reason] = expected[i];
-      do_check_eq(m.name, name);
-      do_check_eq(m.reason, reason);
-      continue;
-    }
-  }
+    do_check_measurement_eq(expected[i], m);
+  });
 
   run_next_test();
 });
 
+/**
+ * Converts the expected value arrays to objects,
+ * for less typing when initializing the expected arrays.
+ */
+function expectedArraysToObjs(expectedArrays) {
+  return expectedArrays.map(function (arr) {
+    let type = arr[0];
+    if (type === "event") {
+      return {
+        type: type,
+        action: arr[1],
+        method: arr[2],
+        sessions: arr[3].sort(), // Sort, just in case it's not sorted by hand!
+        extras: arr[4],
+      };
+
+    } else if (type === "session") {
+      return {
+        type: type,
+        name: arr[1],
+        reason: arr[2],
+      };
+    }
+  });
+}
+
+function removeNonTestMeasurements(measurements) {
+  return measurements.filter(function (measurement) {
+    if (measurement.type === "event") {
+      return measurement.action.startsWith("_test_event_");
+    } else if (measurement.type === "session") {
+      return measurement.name.startsWith("_test_session_");
+    }
+    return false;
+  });
+}
+
+function removeNonTestSessions(sessions) {
+  return sessions.filter(function (sessionName) {
+    return sessionName.startsWith("_test_session_");
+  });
+}
+
 run_next_test();
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -837,17 +837,21 @@ SessionStore.prototype = {
     aIndex = aIndex || 0;
     if (!(aIndex in closedTabs))
       throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
 
     // fetch the data of closed tab, while removing it from the array
     let closedTab = closedTabs.splice(aIndex, 1).shift();
 
     // create a new tab and bring to front
-    let params = { selected: true };
+    let params = {
+      selected: true,
+      isPrivate: closedTab.isPrivate,
+      desktopMode: closedTab.desktopMode
+    };
     let tab = aWindow.BrowserApp.addTab(closedTab.entries[closedTab.index - 1].url, params);
     this._restoreHistory(closedTab, tab.browser.sessionHistory);
 
     // Put back the extra data
     tab.browser.__SS_extdata = closedTab.extData;
 
     return tab.browser;
   },
--- a/netwerk/base/src/nsInputStreamPump.cpp
+++ b/netwerk/base/src/nsInputStreamPump.cpp
@@ -395,17 +395,19 @@ nsInputStreamPump::AsyncRead(nsIStreamLi
 // nsInputStreamPump::nsIInputStreamCallback implementation
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream *stream)
 {
     LOG(("nsInputStreamPump::OnInputStreamReady [this=%p]\n", this));
 
-    PROFILER_LABEL("Input", "nsInputStreamPump::OnInputStreamReady");
+    PROFILER_LABEL("nsInputStreamPump", "OnInputStreamReady",
+        js::ProfileEntry::Category::NETWORK);
+
     // this function has been called from a PLEvent, so we can safely call
     // any listener or progress sink methods directly from here.
 
     for (;;) {
         // There should only be one iteration of this loop happening at a time. 
         // To prevent AsyncWait() (called during callbacks or on other threads)
         // from creating a parallel OnInputStreamReady(), we use:
         // -- a monitor; and
@@ -489,17 +491,19 @@ nsInputStreamPump::OnInputStreamReady(ns
     return NS_OK;
 }
 
 uint32_t
 nsInputStreamPump::OnStateStart()
 {
     mMonitor.AssertCurrentThreadIn();
 
-    PROFILER_LABEL("nsInputStreamPump", "OnStateStart");
+    PROFILER_LABEL("nsInputStreamPump", "OnStateStart",
+        js::ProfileEntry::Category::NETWORK);
+
     LOG(("  OnStateStart [this=%p]\n", this));
 
     nsresult rv;
 
     // need to check the reason why the stream is ready.  this is required
     // so our listener can check our status from OnStartRequest.
     // XXX async streams should have a GetStatus method!
     if (NS_SUCCEEDED(mStatus)) {
@@ -526,17 +530,19 @@ nsInputStreamPump::OnStateStart()
     return NS_SUCCEEDED(mStatus) ? STATE_TRANSFER : STATE_STOP;
 }
 
 uint32_t
 nsInputStreamPump::OnStateTransfer()
 {
     mMonitor.AssertCurrentThreadIn();
 
-    PROFILER_LABEL("Input", "nsInputStreamPump::OnStateTransfer");
+    PROFILER_LABEL("nsInputStreamPump", "OnStateTransfer",
+        js::ProfileEntry::Category::NETWORK);
+
     LOG(("  OnStateTransfer [this=%p]\n", this));
 
     // if canceled, go directly to STATE_STOP...
     if (NS_FAILED(mStatus))
         return STATE_STOP;
 
     nsresult rv;
 
@@ -669,17 +675,19 @@ nsInputStreamPump::OnStateStop()
         MOZ_ASSERT(NS_IsMainThread(),
                    "OnStateStop should only be called on the main thread.");
         nsresult rv = NS_DispatchToMainThread(
             NS_NewRunnableMethod(this, &nsInputStreamPump::CallOnStateStop));
         NS_ENSURE_SUCCESS(rv, STATE_IDLE);
         return STATE_IDLE;
     }
 
-    PROFILER_LABEL("Input", "nsInputStreamPump::OnStateTransfer");
+    PROFILER_LABEL("nsInputStreamPump", "OnStateStop",
+        js::ProfileEntry::Category::NETWORK);
+
     LOG(("  OnStateStop [this=%p status=%x]\n", this, mStatus));
 
     // if an error occurred, we must be sure to pass the error onto the async
     // stream.  in some cases, this is redundant, but since close is idempotent,
     // this is OK.  otherwise, be sure to honor the "close-when-done" option.
 
     if (!mAsyncStream || !mListener) {
         MOZ_ASSERT(mAsyncStream, "null mAsyncStream: OnStateStop called twice?");
--- a/netwerk/base/src/nsStreamLoader.cpp
+++ b/netwerk/base/src/nsStreamLoader.cpp
@@ -86,17 +86,19 @@ nsStreamLoader::OnStartRequest(nsIReques
   mContext = ctxt;
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsStreamLoader::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
                               nsresult aStatus)
 {
-  PROFILER_LABEL("network", "nsStreamLoader::OnStopRequest");
+  PROFILER_LABEL("nsStreamLoader", "OnStopRequest",
+    js::ProfileEntry::Category::NETWORK);
+
   if (mObserver) {
     // provide nsIStreamLoader::request during call to OnStreamComplete
     mRequest = request;
     nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus,
                                               mLength, mData);
     if (rv == NS_SUCCESS_ADOPTED_DATA) {
       // the observer now owns the data buffer, and the loader must
       // not deallocate it
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -4902,17 +4902,19 @@ nsHttpChannel::GetRequestMethod(nsACStri
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsIRequestObserver
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
 {
-    PROFILER_LABEL("nsHttpChannel", "OnStartRequest");
+    PROFILER_LABEL("nsHttpChannel", "OnStartRequest",
+        js::ProfileEntry::Category::NETWORK);
+
     if (!(mCanceled || NS_FAILED(mStatus))) {
         // capture the request's status, so our consumers will know ASAP of any
         // connection failures, etc - bug 93581
         request->GetStatus(&mStatus);
     }
 
     LOG(("nsHttpChannel::OnStartRequest [this=%p request=%p status=%x]\n",
         this, request, mStatus));
@@ -5007,17 +5009,19 @@ nsHttpChannel::ContinueOnStartRequest3(n
         return NS_OK;
 
     return CallOnStartRequest();
 }
 
 NS_IMETHODIMP
 nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status)
 {
-    PROFILER_LABEL("network", "nsHttpChannel::OnStopRequest");
+    PROFILER_LABEL("nsHttpChannel", "OnStopRequest",
+        js::ProfileEntry::Category::NETWORK);
+
     LOG(("nsHttpChannel::OnStopRequest [this=%p request=%p status=%x]\n",
         this, request, status));
 
     if (mTimingEnabled && request == mCachePump) {
         mCacheReadEnd = TimeStamp::Now();
     }
 
     // allow content to be cached if it was loaded successfully (bug #482935)
@@ -5241,17 +5245,19 @@ private:
     uint64_t mProgressMax;
 };
 
 NS_IMETHODIMP
 nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
                                nsIInputStream *input,
                                uint64_t offset, uint32_t count)
 {
-    PROFILER_LABEL("network", "nsHttpChannel::OnDataAvailable");
+    PROFILER_LABEL("nsHttpChannel", "OnDataAvailable",
+        js::ProfileEntry::Category::NETWORK);
+
     LOG(("nsHttpChannel::OnDataAvailable [this=%p request=%p offset=%llu count=%u]\n",
         this, request, offset, count));
 
     // don't send out OnDataAvailable notifications if we've been canceled.
     if (mCanceled)
         return mStatus;
 
     MOZ_ASSERT(mResponseHead, "No response head in ODA!!");
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -333,17 +333,19 @@ class nsHtml5FlushLoopGuard
 };
 
 /**
  * The purpose of the loop here is to avoid returning to the main event loop
  */
 void
 nsHtml5TreeOpExecutor::RunFlushLoop()
 {
-  PROFILER_LABEL("html5", "RunFlushLoop");
+  PROFILER_LABEL("nsHtml5TreeOpExecutor", "RunFlushLoop",
+    js::ProfileEntry::Category::OTHER);
+
   if (mRunFlushLoopOnStack) {
     // There's already a RunFlushLoop() on the call stack.
     return;
   }
   
   nsHtml5FlushLoopGuard guard(this); // this is also the self-kungfu!
   
   nsCOMPtr<nsISupports> parserKungFuDeathGrip(mParser);
--- a/storage/src/mozStorageConnection.cpp
+++ b/storage/src/mozStorageConnection.cpp
@@ -558,34 +558,36 @@ Connection::getAsyncExecutionTarget()
 
   return mAsyncExecutionThread;
 }
 
 nsresult
 Connection::initialize()
 {
   NS_ASSERTION (!mDBConn, "Initialize called on already opened database!");
-  PROFILER_LABEL("storage", "Connection::initialize");
+  PROFILER_LABEL("mozStorageConnection", "initialize",
+    js::ProfileEntry::Category::STORAGE);
 
   // in memory database requested, sqlite uses a magic file name
   int srv = ::sqlite3_open_v2(":memory:", &mDBConn, mFlags, nullptr);
   if (srv != SQLITE_OK) {
     mDBConn = nullptr;
     return convertResultCode(srv);
   }
 
   return initializeInternal(nullptr);
 }
 
 nsresult
 Connection::initialize(nsIFile *aDatabaseFile)
 {
   NS_ASSERTION (aDatabaseFile, "Passed null file!");
   NS_ASSERTION (!mDBConn, "Initialize called on already opened database!");
-  PROFILER_LABEL("storage", "Connection::initialize");
+  PROFILER_LABEL("mozStorageConnection", "initialize",
+    js::ProfileEntry::Category::STORAGE);
 
   mDatabaseFile = aDatabaseFile;
 
   nsAutoString path;
   nsresult rv = aDatabaseFile->GetPath(path);
   NS_ENSURE_SUCCESS(rv, rv);
 
   int srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn,
@@ -603,17 +605,18 @@ Connection::initialize(nsIFile *aDatabas
   return NS_OK;
 }
 
 nsresult
 Connection::initialize(nsIFileURL *aFileURL)
 {
   NS_ASSERTION (aFileURL, "Passed null file URL!");
   NS_ASSERTION (!mDBConn, "Initialize called on already opened database!");
-  PROFILER_LABEL("storage", "Connection::initialize");
+  PROFILER_LABEL("mozStorageConnection", "initialize",
+    js::ProfileEntry::Category::STORAGE);
 
   nsCOMPtr<nsIFile> databaseFile;
   nsresult rv = aFileURL->GetFile(getter_AddRefs(databaseFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString spec;
   rv = aFileURL->GetSpec(spec);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1162,17 +1165,19 @@ Connection::AsyncClose(mozIStorageComple
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Connection::AsyncClone(bool aReadOnly,
                        mozIStorageCompletionCallback *aCallback)
 {
-  PROFILER_LABEL("storage", "Connection::Clone");
+  PROFILER_LABEL("mozStorageConnection", "AsyncClone",
+    js::ProfileEntry::Category::STORAGE);
+
   if (!NS_IsMainThread()) {
     return NS_ERROR_NOT_SAME_THREAD;
   }
   if (!mDBConn)
     return NS_ERROR_NOT_INITIALIZED;
   if (!mDatabaseFile)
     return NS_ERROR_UNEXPECTED;
 
@@ -1243,17 +1248,19 @@ Connection::initializeClone(Connection* 
 }
 
 NS_IMETHODIMP
 Connection::Clone(bool aReadOnly,
                   mozIStorageConnection **_connection)
 {
   MOZ_ASSERT(threadOpenedOn == NS_GetCurrentThread());
 
-  PROFILER_LABEL("storage", "Connection::Clone");
+  PROFILER_LABEL("mozStorageConnection", "Clone",
+    js::ProfileEntry::Category::STORAGE);
+
   if (!mDBConn)
     return NS_ERROR_NOT_INITIALIZED;
   if (!mDatabaseFile)
     return NS_ERROR_UNEXPECTED;
 
   int flags = mFlags;
   if (aReadOnly) {
     // Turn off SQLITE_OPEN_READWRITE, and set SQLITE_OPEN_READONLY.
--- a/storage/src/mozStorageStatement.cpp
+++ b/storage/src/mozStorageStatement.cpp
@@ -604,17 +604,19 @@ Statement::Execute()
   nsresult rv2 = Reset();
 
   return NS_FAILED(rv) ? rv : rv2;
 }
 
 NS_IMETHODIMP
 Statement::ExecuteStep(bool *_moreResults)
 {
-  PROFILER_LABEL("storage", "Statement::ExecuteStep");
+  PROFILER_LABEL("Statement", "ExecuteStep",
+    js::ProfileEntry::Category::STORAGE);
+
   if (!mDBStatement)
     return NS_ERROR_NOT_INITIALIZED;
 
   // Bind any parameters first before executing.
   if (mParamsArray) {
     // If we have more than one row of parameters to bind, they shouldn't be
     // calling this method (and instead use executeAsync).
     if (mParamsArray->length() != 1)
--- a/toolkit/components/places/nsAnnotationService.cpp
+++ b/toolkit/components/places/nsAnnotationService.cpp
@@ -254,17 +254,19 @@ nsAnnotationService::SetPageAnnotation(n
 
 NS_IMETHODIMP
 nsAnnotationService::SetItemAnnotation(int64_t aItemId,
                                        const nsACString& aName,
                                        nsIVariant* aValue,
                                        int32_t aFlags,
                                        uint16_t aExpiration)
 {
-  PROFILER_LABEL("AnnotationService", "SetItemAnnotation");
+  PROFILER_LABEL("AnnotationService", "SetItemAnnotation",
+    js::ProfileEntry::Category::OTHER);
+
   NS_ENSURE_ARG_MIN(aItemId, 1);
   NS_ENSURE_ARG(aValue);
 
   if (aExpiration == EXPIRE_WITH_HISTORY)
     return NS_ERROR_INVALID_ARG;
 
   uint16_t dataType;
   nsresult rv = aValue->GetDataType(&dataType);
--- a/toolkit/components/places/nsNavBookmarks.cpp
+++ b/toolkit/components/places/nsNavBookmarks.cpp
@@ -652,17 +652,19 @@ nsNavBookmarks::InsertBookmark(int64_t a
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsNavBookmarks::RemoveItem(int64_t aItemId)
 {
-  PROFILER_LABEL("bookmarks", "RemoveItem");
+  PROFILER_LABEL("nsNavBookmarks", "RemoveItem",
+    js::ProfileEntry::Category::OTHER);
+
   NS_ENSURE_ARG(!IsRoot(aItemId));
 
   BookmarkData bookmark;
   nsresult rv = FetchItemInfo(aItemId, bookmark);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mozStorageTransaction transaction(mDB->MainConn(), false);
 
@@ -1148,17 +1150,19 @@ nsNavBookmarks::GetDescendantChildren(in
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsNavBookmarks::RemoveFolderChildren(int64_t aFolderId)
 {
-  PROFILER_LABEL("bookmarks", "RemoveFolderChilder");
+  PROFILER_LABEL("nsNavBookmarks", "RemoveFolderChilder",
+    js::ProfileEntry::Category::OTHER);
+
   NS_ENSURE_ARG_MIN(aFolderId, 1);
   NS_ENSURE_ARG(aFolderId != mRoot);
 
   BookmarkData folder;
   nsresult rv = FetchItemInfo(aFolderId, folder);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_ARG(folder.type == TYPE_FOLDER);
 
@@ -2656,17 +2660,19 @@ nsNavBookmarks::EnsureKeywordsHash() {
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsNavBookmarks::RunInBatchMode(nsINavHistoryBatchCallback* aCallback,
                                nsISupports* aUserData) {
-  PROFILER_LABEL("bookmarks", "RunInBatchMode");
+  PROFILER_LABEL("nsNavBookmarks", "RunInBatchMode",
+    js::ProfileEntry::Category::OTHER);
+
   NS_ENSURE_ARG(aCallback);
 
   mBatching = true;
 
   // Just forward the request to history.  History service must exist for
   // bookmarks to work and we are observing it, thus batch notifications will be
   // forwarded to bookmarks observers.
   nsNavHistory* history = nsNavHistory::GetHistoryService();
--- a/toolkit/devtools/server/actors/framerate.js
+++ b/toolkit/devtools/server/actors/framerate.js
@@ -47,54 +47,30 @@ let FramerateActor = exports.FramerateAc
     this._ticks = [];
 
     this._startTime = this._contentWin.performance.now();
     this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
   }, {
   }),
 
   /**
-   * Stops monitoring framerate, returning the recorded values at an
-   * interval defined by the specified resolution, in milliseconds.
+   * Stops monitoring framerate, returning the recorded values.
    */
-  stopRecording: method(function(resolution = 100) {
+  stopRecording: method(function() {
     if (!this._recording) {
-      return {};
+      return [];
     }
     this._recording = false;
 
-    let timeline = {};
+    // We don't need to store the ticks array for future use, release it.
     let ticks = this._ticks;
-    let totalTicks = ticks.length;
-
-    // We don't need to store the ticks array for future use, release it.
     this._ticks = null;
-
-    // If the refresh driver didn't get a chance to tick before the
-    // recording was stopped, assume framerate was 0.
-    if (totalTicks == 0) {
-      timeline[resolution] = 0;
-      return timeline;
-    }
-
-    let pivotTick = 0;
-    let lastTick = ticks[totalTicks - 1];
-
-    for (let bucketTime = resolution; bucketTime < lastTick; bucketTime += resolution) {
-      let frameCount = 0;
-      while (ticks[pivotTick++] < bucketTime) frameCount++;
-
-      let framerate = 1000 / (resolution / frameCount);
-      timeline[bucketTime] = framerate;
-    }
-
-    return timeline;
+    return ticks;
   }, {
-    request: { resolution: Arg(0, "nullable:number") },
-    response: { timeline: RetVal("json") }
+    response: { timeline: RetVal("array:number") }
   }),
 
   /**
    * Function invoked along with the refresh driver.
    */
   _onRefreshDriverTick: function() {
     if (!this._recording) {
       return;
@@ -110,10 +86,57 @@ let FramerateActor = exports.FramerateAc
 
 /**
  * The corresponding Front object for the FramerateActor.
  */
 let FramerateFront = exports.FramerateFront = protocol.FrontClass(FramerateActor, {
   initialize: function(client, { framerateActor }) {
     protocol.Front.prototype.initialize.call(this, client, { actor: framerateActor });
     this.manage(this);
+  },
+
+  /**
+   * Plots the frames per second on a timeline.
+   *
+   * @param array ticks
+   *        The raw data received from the framerate actor, which represents
+   *        the elapsed time on each refresh driver tick.
+   * @param number interval
+   *        The maximum amount of time to wait between calculations.
+   * @return array
+   *         A collection of { delta, value } objects representing the
+   *         framerate value at every delta time.
+   */
+  plotFPS: function(ticks, interval = 100) {
+    let timeline = [];
+    let totalTicks = ticks.length;
+
+    // If the refresh driver didn't get a chance to tick before the
+    // recording was stopped, assume framerate was 0.
+    if (totalTicks == 0) {
+      timeline.push({ delta: 0, value: 0 });
+      timeline.push({ delta: interval, value: 0 });
+      return timeline;
+    }
+
+    let frameCount = 0;
+    let prevTime = ticks[0];
+
+    for (let i = 1; i < totalTicks; i++) {
+      let currTime = ticks[i];
+      frameCount++;
+
+      let elapsedTime = currTime - prevTime;
+      if (elapsedTime < interval) {
+        continue;
+      }
+
+      let framerate = 1000 / (elapsedTime / frameCount);
+      timeline.push({ delta: prevTime, value: framerate });
+      timeline.push({ delta: currTime, value: framerate });
+
+      frameCount = 0;
+      prevTime = currTime;
+    }
+
+    return timeline;
   }
 });
--- a/toolkit/devtools/server/tests/mochitest/test_framerate_01.html
+++ b/toolkit/devtools/server/tests/mochitest/test_framerate_01.html
@@ -41,43 +41,61 @@ window.onload = function() {
   client.connect(function onConnect() {
     client.listTabs(function onListTabs(aResponse) {
       var form = aResponse.tabs[aResponse.selected];
       var front = FramerateFront(client, form);
 
       window.setTimeout(() => {
         front.startRecording().then(() => {
           window.setTimeout(() => {
-            front.stopRecording().then(timeline => {
-              onRecordingStopped(timeline);
+            front.stopRecording().then(rawData => {
+              onRecordingStopped(front, rawData);
             });
           }, 1000);
         });
       }, 1000);
     });
   });
 
-  function onRecordingStopped(timeline) {
-    ok(timeline, "There should be a recording available.");
+  function onRecordingStopped(front, rawData) {
+    ok(rawData, "There should be a recording available.");
+
+    var timeline = front.plotFPS(rawData);
+    ok(timeline.length >= 2,
+      "There should be at least one measurement available, with two entries.");
 
-    var ticks = Object.keys(timeline);
-    var values = ticks.map(e => timeline[e]);
+    var prevTimeStart = timeline[0].delta;
+
+    for (var i = 0; i < timeline.length; i += 2) {
+      var currTimeStart = timeline[i].delta;
+      var currTimeEnd = timeline[i + 1].delta;
+      info("Testing delta: " + currTimeStart + " vs. " + currTimeEnd);
 
-    ok(ticks.length >= 1,
-      "There should be at least one measurement available.");
-    is(ticks[0], 100,
-      "The first measurement should be performed when exactly 100ms passed.");
+      ok(currTimeStart < currTimeEnd,
+        "The start and end time deltas should be consecutive.");
+      is(currTimeStart, prevTimeStart,
+        "There should be two time deltas for each framerate value.");
+
+      prevTimeStart = currTimeEnd;
+    }
+
+    var prevFramerateValue = -1;
 
-    for (var tick of ticks) {
-      info("Testing tick: " + tick);
-      is(tick % 100, 0, "All ticks should be divisible by the resolution.");
-    }
-    for (var value of values) {
-      info("Testing value: " + value);
-      is(typeof value, "number", "All values should be integers.");
+    for (var i = 0; i < timeline.length; i += 2) {
+      var currFramerateStart = timeline[i].value;
+      var currFramerateEnd = timeline[i + 1].value;
+      info("Testing framerate: " + currFramerateStart);
+
+      is(currFramerateStart, currFramerateEnd,
+        "The start and end framerate values should be equal.");
+      isnot(currFramerateStart, prevFramerateValue,
+        "There should be different framerate values for each bucket.");
+
+      is(typeof currFramerateStart, "number", "All values should be numbers.");
+      prevFramerateValue = currFramerateStart;
     }
 
     client.close(() => {
       DebuggerServer.destroy();
       SimpleTest.finish()
     });
   }
 }
--- a/toolkit/devtools/server/tests/mochitest/test_framerate_02.html
+++ b/toolkit/devtools/server/tests/mochitest/test_framerate_02.html
@@ -38,19 +38,35 @@ window.onload = function() {
   DebuggerServer.addBrowserActors();
 
   var client = new DebuggerClient(DebuggerServer.connectPipe());
   client.connect(function onConnect() {
     client.listTabs(function onListTabs(aResponse) {
       var form = aResponse.tabs[aResponse.selected];
       var front = FramerateFront(client, form);
 
-      front.stopRecording().then(timeline => {
-        ok(timeline, "There should be a recording available.");
-        is(Object.keys(timeline).length, 0, "...but it should be empty.");
+      front.stopRecording().then(rawData => {
+        ok(rawData, "There should be a recording available.");
+        is(rawData.length, 0, "...but it should be empty.");
+
+        var timeline = front.plotFPS(rawData);
+        is(timeline.length, 2,
+          "There should be one measurement plotted, with two entries.");
+
+        info("The framerate should be assumed to be 0 if the recording is empty.");
+
+        is(timeline[0].delta, 0,
+          "The first time delta should be 0.");
+        is(timeline[0].value, 0,
+          "The first framerate value should be 0.");
+
+        is(timeline[1].delta, 100,
+          "The last time delta should be 100 (the default interval value).");
+        is(timeline[1].value, 0,
+          "The last framerate value should be 0.");
 
         client.close(() => {
           DebuggerServer.destroy();
           SimpleTest.finish()
         });
       });
     });
   });
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -4022,17 +4022,19 @@ XREMain::XRE_mainRun()
 /*
  * XRE_main - A class based main entry point used by most platforms.
  */
 int
 XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
 {
   char aLocal;
   GeckoProfilerInitRAII profilerGuard(&aLocal);
-  PROFILER_LABEL("Startup", "XRE_Main");
+
+  PROFILER_LABEL("Startup", "XRE_Main",
+    js::ProfileEntry::Category::OTHER);
 
   nsresult rv = NS_OK;
 
   gArgc = argc;
   gArgv = argv;
 
   NS_ENSURE_TRUE(aAppData, 2);
 
@@ -4227,17 +4229,19 @@ public:
   HRESULT mResult;
 };
 
 int
 XRE_mainMetro(int argc, char* argv[], const nsXREAppData* aAppData)
 {
   char aLocal;
   GeckoProfilerInitRAII profilerGuard(&aLocal);
-  PROFILER_LABEL("Startup", "XRE_Main");
+
+  PROFILER_LABEL("Startup", "XRE_Main",
+    js::ProfileEntry::Category::OTHER);
 
   mozilla::IOInterposerInit ioInterposerGuard;
 
   nsresult rv = NS_OK;
 
   xreMainPtr = new XREMain();
   if (!xreMainPtr) {
     return 1;
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -298,17 +298,19 @@ XRE_InitChildProcess(int aArgc,
         freopen("CONOUT$", "w", stderr);
     if (_fileno(stdin) == -1 || _get_osfhandle(fileno(stdin)) == -1)
         freopen("CONIN$", "r", stdin);
   }
 #endif
 
   char aLocal;
   profiler_init(&aLocal);
-  PROFILER_LABEL("Startup", "XRE_InitChildProcess");
+
+  PROFILER_LABEL("Startup", "XRE_InitChildProcess",
+    js::ProfileEntry::Category::OTHER);
 
   sChildProcessType = aProcess;
 
   // Complete 'task_t' exchange for Mac OS X. This structure has the same size
   // regardless of architecture so we don't have any cross-arch issues here.
 #ifdef XP_MACOSX
   if (aArgc < 1)
     return NS_ERROR_FAILURE;
--- a/tools/profiler/GeckoProfiler.h
+++ b/tools/profiler/GeckoProfiler.h
@@ -66,34 +66,34 @@ enum TracingMetadata {
 
 #ifndef MOZ_ENABLE_PROFILER_SPS
 
 #include <stdint.h>
 
 // Insert a RAII in this scope to active a pseudo label. Any samples collected
 // in this scope will contain this annotation. For dynamic strings use
 // PROFILER_LABEL_PRINTF. Arguments must be string literals.
-#define PROFILER_LABEL(name_space, info) do {} while (0)
+#define PROFILER_LABEL(name_space, info, category) do {} while (0)
 
 // Format a dynamic string as a pseudo label. These labels will a considerable
 // storage size in the circular buffer compared to regular labels. This function
 // can be used to annotate custom information such as URL for the resource being
 // decoded or the size of the paint.
-#define PROFILER_LABEL_PRINTF(name_space, info, format, ...) do {} while (0)
+#define PROFILER_LABEL_PRINTF(name_space, info, category, format, ...) do {} while (0)
 
 // Insert a marker in the profile timeline. This is useful to delimit something
 // important happening such as the first paint. Unlike profiler_label that are
 // only recorded if a sample is collected while it is active, marker will always
 // be collected.
 #define PROFILER_MARKER(info) do {} while (0)
 #define PROFILER_MARKER_PAYLOAD(info, payload) do {} while (0)
 
 // Main thread specilization to avoid TLS lookup for performance critical use.
-#define PROFILER_MAIN_THREAD_LABEL(name_space, info) do {} while (0)
-#define PROFILER_MAIN_THREAD_LABEL_PRINTF(name_space, info, format, ...) do {} while (0)
+#define PROFILER_MAIN_THREAD_LABEL(name_space, info, category) do {} while (0)
+#define PROFILER_MAIN_THREAD_LABEL_PRINTF(name_space, info, category, format, ...) do {} while (0)
 
 static inline void profiler_tracing(const char* aCategory, const char* aInfo,
                                     TracingMetadata metaData = TRACING_DEFAULT) {}
 class ProfilerBacktrace;
 
 static inline void profiler_tracing(const char* aCategory, const char* aInfo,
                                     ProfilerBacktrace* aCause,
                                     TracingMetadata metaData = TRACING_DEFAULT) {}
--- a/tools/profiler/GeckoProfilerFunc.h
+++ b/tools/profiler/GeckoProfilerFunc.h
@@ -3,34 +3,38 @@
  * 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 PROFILER_FUNCS_H
 #define PROFILER_FUNCS_H
 
 #include "mozilla/NullPtr.h"
 #include "js/TypeDecls.h"
+#include "js/ProfilingStack.h"
 #include <stdint.h>
 
 namespace mozilla {
 class TimeDuration;
 class TimeStamp;
 }
 
 using mozilla::TimeStamp;
 using mozilla::TimeDuration;
 
 class ProfilerBacktrace;
 class ProfilerMarkerPayload;
 
 // Returns a handle to pass on exit. This can check that we are popping the
 // correct callstack.
-inline void* mozilla_sampler_call_enter(const char *aInfo, void *aFrameAddress = nullptr,
-                                        bool aCopy = false, uint32_t line = 0);
+inline void* mozilla_sampler_call_enter(const char *aInfo, js::ProfileEntry::Category aCategory,
+                                        void *aFrameAddress = nullptr, bool aCopy = false,
+                                        uint32_t line = 0);
+
 inline void  mozilla_sampler_call_exit(void* handle);
+
 void  mozilla_sampler_add_marker(const char *aInfo,
                                  ProfilerMarkerPayload *aPayload = nullptr);
 
 void mozilla_sampler_start(int aEntries, double aInterval,
                            const char** aFeatures, uint32_t aFeatureCount,
                            const char** aThreadNameFilters, uint32_t aFilterCount);
 
 void mozilla_sampler_stop();
--- a/tools/profiler/GeckoProfilerImpl.h
+++ b/tools/profiler/GeckoProfilerImpl.h
@@ -305,25 +305,25 @@ static inline void profiler_tracing(cons
 
 // we want the class and function name but can't easily get that using preprocessor macros
 // __func__ doesn't have the class name and __PRETTY_FUNCTION__ has the parameters
 
 #define SAMPLER_APPEND_LINE_NUMBER_PASTE(id, line) id ## line
 #define SAMPLER_APPEND_LINE_NUMBER_EXPAND(id, line) SAMPLER_APPEND_LINE_NUMBER_PASTE(id, line)
 #define SAMPLER_APPEND_LINE_NUMBER(id) SAMPLER_APPEND_LINE_NUMBER_EXPAND(id, __LINE__)
 
-#define PROFILER_LABEL(name_space, info) MOZ_PLATFORM_TRACING(name_space "::" info) mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__)
-#define PROFILER_LABEL_PRINTF(name_space, info, ...) MOZ_PLATFORM_TRACING(name_space "::" info) mozilla::SamplerStackFramePrintfRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__, __VA_ARGS__)
+#define PROFILER_LABEL(name_space, info, category) MOZ_PLATFORM_TRACING(name_space "::" info) mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, category, __LINE__)
+#define PROFILER_LABEL_PRINTF(name_space, info, category, ...) MOZ_PLATFORM_TRACING(name_space "::" info) mozilla::SamplerStackFramePrintfRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, category, __LINE__, __VA_ARGS__)
 
 #define PROFILER_MARKER(info) mozilla_sampler_add_marker(info)
 #define PROFILER_MARKER_PAYLOAD(info, payload) mozilla_sampler_add_marker(info, payload)
 #define PROFILER_MAIN_THREAD_MARKER(info)  MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla_sampler_add_marker(info)
 
-#define PROFILER_MAIN_THREAD_LABEL(name_space, info)  MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__)
-#define PROFILER_MAIN_THREAD_LABEL_PRINTF(name_space, info, ...)  MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla::SamplerStackFramePrintfRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, __LINE__, __VA_ARGS__)
+#define PROFILER_MAIN_THREAD_LABEL(name_space, info, category)  MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, category, __LINE__)
+#define PROFILER_MAIN_THREAD_LABEL_PRINTF(name_space, info, category, ...)  MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread"); mozilla::SamplerStackFramePrintfRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, category, __LINE__, __VA_ARGS__)
 
 
 /* FIXME/bug 789667: memory constraints wouldn't much of a problem for
  * this small a sample buffer size, except that serializing the
  * profile data is extremely, unnecessarily memory intensive. */
 #ifdef MOZ_WIDGET_GONK
 # define PLATFORM_LIKELY_MEMORY_CONSTRAINED
 #endif
@@ -362,49 +362,53 @@ static inline void profiler_tracing(cons
 #define PROFILE_DEFAULT_FEATURES NULL
 #define PROFILE_DEFAULT_FEATURE_COUNT 0
 
 namespace mozilla {
 
 class MOZ_STACK_CLASS SamplerStackFrameRAII {
 public:
   // we only copy the strings at save time, so to take multiple parameters we'd need to copy them then.
-  SamplerStackFrameRAII(const char *aInfo, uint32_t line) {
-    mHandle = mozilla_sampler_call_enter(aInfo, this, false, line);
+  SamplerStackFrameRAII(const char *aInfo,
+    js::ProfileEntry::Category aCategory, uint32_t line)
+  {
+    mHandle = mozilla_sampler_call_enter(aInfo, aCategory, this, false, line);
   }
   ~SamplerStackFrameRAII() {
     mozilla_sampler_call_exit(mHandle);
   }
 private:
   void* mHandle;
 };
 
 static const int SAMPLER_MAX_STRING = 128;
 class MOZ_STACK_CLASS SamplerStackFramePrintfRAII {
 public:
   // we only copy the strings at save time, so to take multiple parameters we'd need to copy them then.
-  SamplerStackFramePrintfRAII(const char *aDefault, uint32_t line, const char *aFormat, ...) {
+  SamplerStackFramePrintfRAII(const char *aInfo,
+    js::ProfileEntry::Category aCategory, uint32_t line, const char *aFormat, ...)
+  {
     if (profiler_is_active() && !profiler_in_privacy_mode()) {
       va_list args;
       va_start(args, aFormat);
       char buff[SAMPLER_MAX_STRING];
 
       // We have to use seperate printf's because we're using
       // the vargs.
 #if _MSC_VER
       _vsnprintf(buff, SAMPLER_MAX_STRING, aFormat, args);
-      _snprintf(mDest, SAMPLER_MAX_STRING, "%s %s", aDefault, buff);
+      _snprintf(mDest, SAMPLER_MAX_STRING, "%s %s", aInfo, buff);
 #else
       ::vsnprintf(buff, SAMPLER_MAX_STRING, aFormat, args);
-      ::snprintf(mDest, SAMPLER_MAX_STRING, "%s %s", aDefault, buff);
+      ::snprintf(mDest, SAMPLER_MAX_STRING, "%s %s", aInfo, buff);
 #endif
-      mHandle = mozilla_sampler_call_enter(mDest, this, true, line);
+      mHandle = mozilla_sampler_call_enter(mDest, aCategory, this, true, line);
       va_end(args);
     } else {
-      mHandle = mozilla_sampler_call_enter(aDefault, this, false, line);
+      mHandle = mozilla_sampler_call_enter(aInfo, aCategory, this, false, line);
     }
   }
   ~SamplerStackFramePrintfRAII() {
     mozilla_sampler_call_exit(mHandle);
   }
 private:
   char mDest[SAMPLER_MAX_STRING];
   void* mHandle;
@@ -414,33 +418,33 @@ private:
 
 inline PseudoStack* mozilla_get_pseudo_stack(void)
 {
   if (!stack_key_initialized)
     return nullptr;
   return tlsPseudoStack.get();
 }
 
-inline void* mozilla_sampler_call_enter(const char *aInfo, void *aFrameAddress,
-                                        bool aCopy, uint32_t line)
+inline void* mozilla_sampler_call_enter(const char *aInfo,
+  js::ProfileEntry::Category aCategory, void *aFrameAddress, bool aCopy, uint32_t line)
 {
   // check if we've been initialized to avoid calling pthread_getspecific
   // with a null tlsStack which will return undefined results.
   if (!stack_key_initialized)
     return nullptr;
 
   PseudoStack *stack = tlsPseudoStack.get();
   // we can't infer whether 'stack' has been initialized
   // based on the value of stack_key_intiailized because
   // 'stack' is only intialized when a thread is being
   // profiled.
   if (!stack) {
     return stack;
   }
-  stack->push(aInfo, aFrameAddress, aCopy, line);
+  stack->push(aInfo, aCategory, aFrameAddress, aCopy, line);
 
   // The handle is meant to support future changes
   // but for now it is simply use to save a call to
   // pthread_getspecific on exit. It also supports the
   // case where the sampler is initialized between
   // enter and exit.
   return stack;
 }
--- a/tools/profiler/PseudoStack.h
+++ b/tools/profiler/PseudoStack.h
@@ -338,35 +338,43 @@ public:
   }
 
   // called within signal. Function must be reentrant
   ProfilerMarkerLinkedList* getPendingMarkers()
   {
     return mPendingMarkers.getPendingMarkers();
   }
 
-  void push(const char *aName, uint32_t line)
+  void push(const char *aName, js::ProfileEntry::Category aCategory, uint32_t line)
   {
-    push(aName, nullptr, false, line);
+    push(aName, aCategory, nullptr, false, line);
   }
 
-  void push(const char *aName, void *aStackAddress, bool aCopy, uint32_t line)
+  void push(const char *aName, js::ProfileEntry::Category aCategory,
+    void *aStackAddress, bool aCopy, uint32_t line)
   {
     if (size_t(mStackPointer) >= mozilla::ArrayLength(mStack)) {
       mStackPointer++;
       return;
     }
 
     volatile StackEntry &entry = mStack[mStackPointer];
 
     // Make sure we increment the pointer after the name has
     // been written such that mStack is always consistent.
     entry.setLabel(aName);
     entry.setCppFrame(aStackAddress, line);
 
+    uint32_t uint_category = static_cast<uint32_t>(aCategory);
+    MOZ_ASSERT(
+      uint_category >= static_cast<uint32_t>(js::ProfileEntry::Category::FIRST) &&
+      uint_category <= static_cast<uint32_t>(js::ProfileEntry::Category::LAST));
+
+    entry.setFlag(uint_category);
+
     // Track if mLabel needs a copy.
     if (aCopy)
       entry.setFlag(js::ProfileEntry::FRAME_LABEL_COPY);
     else
       entry.unsetFlag(js::ProfileEntry::FRAME_LABEL_COPY);
 
     // Prevent the optimizer from re-ordering these instructions
     STORE_SEQUENCER();
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -717,17 +717,18 @@ void nsViewManager::DidPaintWindow()
   }
 }
 
 void
 nsViewManager::DispatchEvent(WidgetGUIEvent *aEvent,
                              nsView* aView,
                              nsEventStatus* aStatus)
 {
-  PROFILER_LABEL("event", "nsViewManager::DispatchEvent");
+  PROFILER_LABEL("nsViewManager", "DispatchEvent",
+    js::ProfileEntry::Category::EVENTS);
 
   WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
   if ((mouseEvent &&
        // Ignore mouse events that we synthesize.
        mouseEvent->reason == WidgetMouseEvent::eReal &&
        // Ignore mouse exit and enter (we'll get moves if the user
        // is really moving the mouse) since we get them when we
        // create and destroy widgets.
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -223,24 +223,28 @@ nsAppShell::ScheduleNativeEventCallback(
     PostEvent(AndroidGeckoEvent::MakeNativePoke());
 }
 
 bool
 nsAppShell::ProcessNextNativeEvent(bool mayWait)
 {
     EVLOG("nsAppShell::ProcessNextNativeEvent %d", mayWait);
 
-    PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent");
+    PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent",
+        js::ProfileEntry::Category::EVENTS);
+
     nsAutoPtr<AndroidGeckoEvent> curEvent;
     {
         MutexAutoLock lock(mCondLock);
 
         curEvent = PopNextEvent();
         if (!curEvent && mayWait) {
-            PROFILER_LABEL("nsAppShell::ProcessNextNativeEvent", "Wait");
+            PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent::Wait",
+                js::ProfileEntry::Category::EVENTS);
+
             // hmm, should we really hardcode this 10s?
 #if defined(DEBUG_ANDROID_EVENTS)
             PRTime t0, t1;
             EVLOG("nsAppShell: waiting on mQueueCond");
             t0 = PR_Now();
             mQueueCond.Wait(PR_MillisecondsToInterval(10000));
             t1 = PR_Now();
             EVLOG("nsAppShell: wait done, waited %d ms", (int)(t1-t0)/1000);
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -2432,17 +2432,19 @@ nsWindow::DrawWindowUnderlay(LayerManage
     if (!mLayerRendererFrame.BeginDrawing(&jniFrame)) return;
     if (!mLayerRendererFrame.DrawBackground(&jniFrame)) return;
     client->DeactivateProgram(); // redundant, but in case somebody adds code after this...
 }
 
 void
 nsWindow::DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect)
 {
-    PROFILER_LABEL("nsWindow", "DrawWindowOverlay");
+    PROFILER_LABEL("nsWindow", "DrawWindowOverlay",
+        js::ProfileEntry::Category::GRAPHICS);
+
     JNIEnv *env = GetJNIForThread();
 
     AutoLocalJNIFrame jniFrame(env);
 
     if (mLayerRendererFrame.isNull()) {
         NS_WARNING("Warning: do not have a LayerRenderer frame; aborting window overlay draw");
         return;
     }
--- a/widget/cocoa/nsAppShell.mm
+++ b/widget/cocoa/nsAppShell.mm
@@ -244,17 +244,19 @@ nsAppShell::Init()
 // to ScheduleNativeEventCallback(), if processing of Gecko events via "native
 // methods" hasn't been suspended).  This happens in NativeEventCallback().
 //
 // protected static
 void
 nsAppShell::ProcessGeckoEvents(void* aInfo)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-  PROFILER_LABEL("Events", "ProcessGeckoEvents");
+  PROFILER_LABEL("Events", "ProcessGeckoEvents",
+    js::ProfileEntry::Category::EVENTS);
+
   nsAppShell* self = static_cast<nsAppShell*> (aInfo);
 
   if (self->mRunningEventLoop) {
     self->mRunningEventLoop = false;
 
     // The run loop may be sleeping -- [NSRunLoop runMode:...]
     // won't return until it's given a reason to wake up.  Awaken it by
     // posting a bogus event.  There's no need to make the event
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -3544,17 +3544,18 @@ NSEvent* gLastDragMouseDownEvent = nil;
     // So we need to clear the pixel buffer contents in the corners.
     [self clearCorners];
 
     // Do GL composition and return.
     [self drawUsingOpenGL];
     return;
   }
 
-  PROFILER_LABEL("widget", "ChildView::drawRect");
+  PROFILER_LABEL("ChildView", "drawRect",
+    js::ProfileEntry::Category::GRAPHICS);
 
   // The CGContext that drawRect supplies us with comes with a transform that
   // scales one user space unit to one Cocoa point, which can consist of
   // multiple dev pixels. But Gecko expects its supplied context to be scaled
   // to device pixels, so we need to reverse the scaling.
   double scale = mGeckoChild->BackingScaleFactor();
   CGContextSaveGState(aContext);
   CGContextScaleCTM(aContext, 1.0 / scale, 1.0 / scale);
@@ -3665,17 +3666,18 @@ NSEvent* gLastDragMouseDownEvent = nil;
   if (!mGeckoChild || ![self window])
     return NO;
 
   return mGLContext || mUsingOMTCompositor || [self isUsingMainThreadOpenGL];
 }
 
 - (void)drawUsingOpenGL
 {
-  PROFILER_LABEL("widget", "ChildView::drawUsingOpenGL");
+  PROFILER_LABEL("ChildView", "drawUsingOpenGL",
+    js::ProfileEntry::Category::GRAPHICS);
 
   if (![self isUsingOpenGL] || !mGeckoChild->IsVisible())
     return;
 
   mWaitingForPaint = NO;
 
   nsIntRect geckoBounds;
   mGeckoChild->GetBounds(geckoBounds);
--- a/widget/gonk/nsAppShell.cpp
+++ b/widget/gonk/nsAppShell.cpp
@@ -1065,22 +1065,26 @@ nsAppShell::ScheduleNativeEventCallback(
 {
     mNativeCallbackRequest = true;
     NotifyEvent();
 }
 
 bool
 nsAppShell::ProcessNextNativeEvent(bool mayWait)
 {
-    PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent");
+    PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent",
+        js::ProfileEntry::Category::EVENTS);
+
     epoll_event events[16] = {{ 0 }};
 
     int event_count;
     {
-        PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent::Wait");
+        PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent::Wait",
+            js::ProfileEntry::Category::EVENTS);
+
         if ((event_count = epoll_wait(epollfd, events, 16,  mayWait ? -1 : 0)) <= 0)
             return true;
     }
 
     for (int i = 0; i < event_count; i++)
         mHandlers[events[i].data.u32].run();
 
     if (mDispatcher.get())
--- a/widget/windows/winrt/MetroWidget.cpp
+++ b/widget/windows/winrt/MetroWidget.cpp
@@ -72,17 +72,17 @@ const char16_t* kMetroSubclassThisProp =
 HWND MetroWidget::sICoreHwnd = nullptr;
 
 namespace mozilla {
 namespace widget {
 UINT sDefaultBrowserMsgId = RegisterWindowMessageW(L"DefaultBrowserClosing");
 } }
 
 // WM_GETOBJECT id pulled from uia headers
-#define UiaRootObjectId -25
+#define MOZOBJID_UIAROOT -25
 
 namespace mozilla {
 namespace widget {
 namespace winrt {
 extern ComPtr<MetroApp> sMetroApp;
 extern ComPtr<IUIABridge> gProviderRoot;
 } } }
 
@@ -887,17 +887,17 @@ MetroWidget::WindowProcedure(HWND aWnd, 
       DWORD dwObjId = (LPARAM)(DWORD) aLParam;
       // Passing this to CallWindowProc can result in a failure due to a timing issue
       // in winrt core window server code, so we call it directly here. Also, it's not
       // clear Windows::UI::Core::WindowServer::OnAutomationProviderRequestedEvent is
       // compatible with metro enabled desktop browsers, it makes an initial call to
       // UiaReturnRawElementProvider passing the return result from FrameworkView
       // OnAutomationProviderRequested as the hwnd (me scratches head) which results in
       // GetLastError always being set to invalid handle (6) after CallWindowProc returns.
-      if (dwObjId == UiaRootObjectId && gProviderRoot) {
+      if (dwObjId == MOZOBJID_UIAROOT && gProviderRoot) {
         ComPtr<IRawElementProviderSimple> simple;
         gProviderRoot.As(&simple);
         if (simple) {
           LRESULT res = UiaReturnRawElementProvider(aWnd, aWParam, aLParam, simple.Get());
           if (res) {
             return res;
           }
           NS_ASSERTION(res, "UiaReturnRawElementProvider failed!");
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -4069,17 +4069,19 @@ nsCycleCollector_forgetSkippable(bool aR
                                  bool aAsyncSnowWhiteFreeing)
 {
   CollectorData* data = sCollectorData.get();
 
   // We should have started the cycle collector by now.
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
 
-  PROFILER_LABEL("CC", "nsCycleCollector_forgetSkippable");
+  PROFILER_LABEL("nsCycleCollector", "forgetSkippable",
+    js::ProfileEntry::Category::CC);
+
   TimeLog timeLog;
   data->mCollector->ForgetSkippable(aRemoveChildlessNodes,
                                     aAsyncSnowWhiteFreeing);
   timeLog.Checkpoint("ForgetSkippable()");
 }
 
 void
 nsCycleCollector_dispatchDeferredDeletion(bool aContinuation)
@@ -4117,48 +4119,54 @@ void
 nsCycleCollector_collect(nsICycleCollectorListener* aManualListener)
 {
   CollectorData* data = sCollectorData.get();
 
   // We should have started the cycle collector by now.
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
 
-  PROFILER_LABEL("CC", "nsCycleCollector_collect");
+  PROFILER_LABEL("nsCycleCollector", "collect",
+    js::ProfileEntry::Category::CC);
+
   SliceBudget unlimitedBudget;
   data->mCollector->Collect(ManualCC, unlimitedBudget, aManualListener);
 }
 
 void
 nsCycleCollector_collectSlice(int64_t aSliceTime)
 {
   CollectorData* data = sCollectorData.get();
 
   // We should have started the cycle collector by now.
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
 
-  PROFILER_LABEL("CC", "nsCycleCollector_collectSlice");
+  PROFILER_LABEL("nsCycleCollector", "collectSlice",
+    js::ProfileEntry::Category::CC);
+
   SliceBudget budget;
   if (aSliceTime >= 0) {
     budget = SliceBudget(SliceBudget::TimeBudget(aSliceTime));
   }
   data->mCollector->Collect(SliceCC, budget, nullptr);
 }
 
 void
 nsCycleCollector_collectSliceWork(int64_t aSliceWork)
 {
   CollectorData* data = sCollectorData.get();
 
   // We should have started the cycle collector by now.
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
 
-  PROFILER_LABEL("CC", "nsCycleCollector_collectSliceWork");
+  PROFILER_LABEL("nsCycleCollector", "collectSliceWork",
+    js::ProfileEntry::Category::CC);
+
   SliceBudget budget;
   if (aSliceWork >= 0) {
     budget = SliceBudget(SliceBudget::WorkBudget(aSliceWork));
   }
   data->mCollector->Collect(SliceCC, budget, nullptr);
 }
 
 void
@@ -4191,17 +4199,19 @@ nsCycleCollector_finishAnyCurrentCollect
 
 void
 nsCycleCollector_shutdown()
 {
   CollectorData* data = sCollectorData.get();
 
   if (data) {
     MOZ_ASSERT(data->mCollector);
-    PROFILER_LABEL("CC", "nsCycleCollector_shutdown");
+    PROFILER_LABEL("nsCycleCollector", "shutdown",
+      js::ProfileEntry::Category::CC);
+
     data->mCollector->Shutdown();
     data->mCollector = nullptr;
     if (!data->mRuntime) {
       delete data;
       sCollectorData.set(nullptr);
     }
   }
 }
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -542,17 +542,18 @@ nsTimerImpl::SetTarget(nsIEventTarget* a
 
 void
 nsTimerImpl::Fire()
 {
   if (mCanceled) {
     return;
   }
 
-  PROFILER_LABEL("Timer", "Fire");
+  PROFILER_LABEL("Timer", "Fire",
+    js::ProfileEntry::Category::OTHER);
 
 #ifdef MOZ_TASK_TRACER
   mozilla::tasktracer::AutoRunFakeTracedTask runTracedTask(mTracedTask);
 #endif
 
 #ifdef DEBUG_TIMERS
   TimeStamp now = TimeStamp::Now();
   if (PR_LOG_TEST(GetTimerLog(), PR_LOG_DEBUG)) {