Merge inbound to mozilla-central. a=merge
authorMargareta Eliza Balazs <ebalazs@mozilla.com>
Wed, 18 Jul 2018 12:33:29 +0300
changeset 427061 8dab948a10f073a46f13f55f94d1f6514c7360ac
parent 426994 7692346c4515d94e12966f22f2278a9c2b7946b9 (current diff)
parent 427060 5d85b6db0a8df2f014c29a21c8e2b6fc80ea7faf (diff)
child 427075 9796bad0c302364c70b6c1a99a6932ff9de3a9a9
child 427117 ded303b9b93e23e2c2ebee4b7c5d71b867f00944
push id34291
push userebalazs@mozilla.com
push dateWed, 18 Jul 2018 09:33:54 +0000
treeherdermozilla-central@8dab948a10f0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone63.0a1
first release with
nightly linux32
8dab948a10f0 / 63.0a1 / 20180718100918 / files
nightly linux64
8dab948a10f0 / 63.0a1 / 20180718100918 / files
nightly mac
8dab948a10f0 / 63.0a1 / 20180718100918 / files
nightly win32
8dab948a10f0 / 63.0a1 / 20180718100918 / files
nightly win64
8dab948a10f0 / 63.0a1 / 20180718100918 / 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 inbound to mozilla-central. a=merge
accessible/tests/mochitest/table/test_headers_listbox.xul
accessible/tests/mochitest/table/test_indexes_listbox.xul
accessible/tests/mochitest/table/test_sels_listbox.xul
accessible/tests/mochitest/table/test_struct_listbox.xul
dom/base/nsContentUtils.cpp
js/src/jit-test/tests/debug/resumption-04.js
js/src/jit-test/tests/debug/resumption-06.js
testing/web-platform/tests/interfaces/ServiceWorker.idl
--- a/.flake8
+++ b/.flake8
@@ -2,15 +2,22 @@
 # See http://pep8.readthedocs.io/en/latest/intro.html#configuration
 ignore = E121, E123, E126, E129, E133, E226, E241, E242, E704, W503, E402, E741
 max-line-length = 99
 exclude =
     browser/extensions/mortar/ppapi/,
     browser/moz.configure,
     build/moz.configure/*.configure,
     build/pymake/,
+    dom/canvas/test/webgl-conf/checkout/closure-library/,
+    editor/libeditor/tests/browserscope/,
+    intl/icu/,
+    ipc/chromium/,
+    gfx/angle/,
+    gfx/harfbuzz,
+    glx/skia/,
     js/*.configure,
     memory/moz.configure,
     mobile/android/*.configure,
     node_modules,
     security/nss/,
     testing/mochitest/pywebsocket,
     tools/lint/test/files,
--- a/accessible/base/SelectionManager.cpp
+++ b/accessible/base/SelectionManager.cpp
@@ -204,17 +204,18 @@ SelectionManager::ProcessSelectionChange
       cntrNode = selection->GetPresShell()->GetDocument();
       NS_ASSERTION(aSelData->mSel->GetPresShell()->ConstFrameSelection() == selection->GetFrameSelection(),
                    "Wrong selection container was used!");
     }
   }
 
   HyperTextAccessible* text = nsAccUtils::GetTextContainer(cntrNode);
   if (!text) {
-    NS_NOTREACHED("We must reach document accessible implementing text interface!");
+    // FIXME bug 1126649
+    NS_ERROR("We must reach document accessible implementing text interface!");
     return;
   }
 
   if (selection->GetType() == SelectionType::eNormal) {
     RefPtr<AccEvent> event =
       new AccTextSelChangeEvent(text, selection, aSelData->mReason);
     text->Document()->FireDelayedEvent(event);
 
--- a/accessible/tests/mochitest/attributes/test_obj_group.xul
+++ b/accessible/tests/mochitest/attributes/test_obj_group.xul
@@ -141,22 +141,22 @@
     <div id="content" style="display: none">
     </div>
     <pre id="test">
     </pre>
   </body>
 
   <vbox flex="1">
 
-  <listbox>
-    <listitem label="listitem1" id="listitem1"/>
-    <listitem label="listitem2" id="listitem2" type="checkbox"/>
-    <listitem label="listitem3" id="listitem3" type="checkbox"/>
-    <listitem label="listitem4" id="listitem4"/>
-  </listbox>
+  <richlistbox>
+    <richlistitem id="listitem1"/>
+    <richlistitem id="listitem2"><label value="listitem2"/></richlistitem>
+    <richlistitem id="listitem3"/>
+    <richlistitem id="listitem4"><label value="listitem4"/></richlistitem>
+  </richlistbox>
 
   <menubar>
     <menu label="item1" id="menu_item1">
       <menupopup>
         <menuitem label="item1.1" id="menu_item1.1"/>
         <menuseparator/>
         <menuitem label="item1.2" id="menu_item1.2"/>
         <menuitem label="item1.3" hidden="true"/>
--- a/accessible/tests/mochitest/elm/test_listbox.xul
+++ b/accessible/tests/mochitest/elm/test_listbox.xul
@@ -58,17 +58,17 @@
     <div id="content" style="display: none">
     </div>
     <pre id="test">
     </pre>
   </body>
 
   <vbox flex="1">
     <label control="listbox1" value="listbox: "/>
-    <listbox id="listbox1">
-      <listitem label="item1" id="item1"/>
-      <listitem label="item2" id="item2"/>
-    </listbox>
+    <richlistbox id="listbox1">
+      <richlistitem id="item1"><label value="item1"/></richlistitem>
+      <richlistitem id="item1"><label value="item2"/></richlistitem>
+    </richlistbox>
   </vbox>
   </hbox>
 
 </window>
 
--- a/accessible/tests/mochitest/events/test_focus_listcontrols.xul
+++ b/accessible/tests/mochitest/events/test_focus_listcontrols.xul
@@ -25,26 +25,16 @@
     gA11yEventDumpToConsole = true; // debug stuff
 
     var gQueue = null;
     function doTests()
     {
       // Test focus events.
       gQueue = new eventQueue();
 
-      gQueue.push(new synthFocus("listbox", new focusChecker("lb_item1")));
-      gQueue.push(new synthDownKey("lb_item1", new focusChecker("lb_item2")));
-      gQueue.push(new synthTab("lb_item2", new focusChecker("mslb_item1")));
-      gQueue.push(new synthDownKey("mslb_item1", new focusChecker("mslb_item2"), { shiftKey: true }));
-      gQueue.push(new synthTab("mslb_item2", new focusChecker("emptylistbox")));
-      gQueue.push(new synthFocus("mcolumnlistbox", new focusChecker("mclb_item1")));
-      gQueue.push(new synthDownKey("mclb_item1", new focusChecker("mclb_item2")));
-      gQueue.push(new synthFocus("headerlistbox", new focusChecker("hlb_item1")));
-      gQueue.push(new synthDownKey("hlb_item1", new focusChecker("hlb_item2")));
-
       gQueue.push(new synthFocus("richlistbox", new focusChecker("rlb_item1")));
       gQueue.push(new synthDownKey("rlb_item1", new focusChecker("rlb_item2")));
       gQueue.push(new synthFocus("multiselrichlistbox", new focusChecker("msrlb_item1")));
       gQueue.push(new synthDownKey("msrlb_item1", new focusChecker("msrlb_item2"), { shiftKey: true }));
       gQueue.push(new synthFocus("emptyrichlistbox", new focusChecker("emptyrichlistbox")));
 
       gQueue.push(new synthFocus("menulist"));
       gQueue.push(new synthClick("menulist", new focusChecker("ml_tangerine")));
@@ -65,19 +55,18 @@ if (!MAC) {
       gQueue.push(new synthDownKey(textentry, new nofocusChecker("eml_tangerine")));
       gQueue.push(new synthUpKey(textentry, new focusChecker("eml_marmalade")));
       gQueue.push(new synthEnterKey("eml_marmalade", new focusChecker(textentry)));
       gQueue.push(new synthOpenComboboxKey("emenulist", new focusChecker("eml_marmalade")));
       gQueue.push(new synthEscapeKey("eml_marmalade", new focusChecker(textentry)));
 
       // no focus events for unfocused list controls when current item is
       // changed.
-      gQueue.push(new synthFocus("emptylistbox"));
+      gQueue.push(new synthFocus("emptyrichlistbox"));
 
-      gQueue.push(new changeCurrentItem("listbox", "lb_item1"));
       gQueue.push(new changeCurrentItem("richlistbox", "rlb_item1"));
 if (!MAC) {
       gQueue.push(new changeCurrentItem("menulist", WIN ? "ml_marmalade" : "ml_tangerine"));
 }
       gQueue.push(new changeCurrentItem("emenulist", "eml_tangerine"));
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
@@ -105,58 +94,16 @@ if (!MAC) {
       </a>
       <p id="display"></p>
       <div id="content" style="display: none"></div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
-      <listbox id="listbox" rows="3">
-        <listitem id="lb_item1" label="item1"/>
-        <listitem id="lb_item2" label="item1"/>
-      </listbox>
-      <listbox id="multisellistbox" rows="3" seltype="multiple">
-        <listitem id="mslb_item1" label="item1"/>
-        <listitem id="mslb_item2" label="item1"/>
-      </listbox>
-      <listbox id="emptylistbox" rows="3"/>
-      <listbox id="mcolumnlistbox" rows="3">
-        <listcols>
-          <listcol/>
-          <listcol/>
-        </listcols>
-        <listitem id="mclb_item1">
-          <listcell label="George"/>
-          <listcell label="House Painter"/>
-        </listitem>
-        <listitem id="mclb_item2">
-          <listcell label="Mary Ellen"/>
-          <listcell label="Candle Maker"/>
-        </listitem>
-      </listbox>
-      <listbox id="headerlistbox" rows="3">
-        <listhead>
-          <listheader label="Name"/>
-          <listheader label="Occupation"/>
-        </listhead>
-        <listcols>
-          <listcol/>
-          <listcol flex="1"/>
-        </listcols>
-        <listitem id="hlb_item1">
-          <listcell label="George"/>
-          <listcell label="House Painter"/>
-        </listitem>
-        <listitem id="hlb_item2">
-          <listcell label="Mary Ellen"/>
-          <listcell label="Candle Maker"/>
-        </listitem>
-      </listbox>
-
       <richlistbox id="richlistbox">
         <richlistitem id="rlb_item1">
           <description>A XUL Description!</description>
         </richlistitem>
         <richlistitem id="rlb_item2">
           <button label="A XUL Button"/>
         </richlistitem>
       </richlistbox>
--- a/accessible/tests/mochitest/events/test_selection.xul
+++ b/accessible/tests/mochitest/events/test_selection.xul
@@ -161,19 +161,22 @@
     {
       gQueue = new eventQueue();
 
       //////////////////////////////////////////////////////////////////////////
       // tabbox
       gQueue.push(new advanceTab("tabs", 1, "tab3"));
 
       //////////////////////////////////////////////////////////////////////////
-      // listbox
-      gQueue.push(new synthClick("lb1_item1",
-                                 new invokerChecker(EVENT_SELECTION, "lb1_item1")));
+      // single selection listbox, the first item is selected by default
+
+      gQueue.push(new synthClick("lb1_item2",
+                                 new invokerChecker(EVENT_SELECTION, "lb1_item2")));
+      gQueue.push(new synthUpKey("lb1_item2",
+                                   new invokerChecker(EVENT_SELECTION, "lb1_item1")));
       gQueue.push(new synthDownKey("lb1_item1",
                                    new invokerChecker(EVENT_SELECTION, "lb1_item2")));
 
       //////////////////////////////////////////////////////////////////////////
       // multiselectable listbox
       gQueue.push(new synthClick("lb2_item1",
                                  new invokerChecker(EVENT_SELECTION, "lb2_item1")));
       gQueue.push(new synthDownKey("lb2_item1",
@@ -229,25 +232,25 @@
       <tabpanels>
         <tabpanel><!-- tabpanel First elements go here --></tabpanel>
         <tabpanel><button id="b1" label="b1"/></tabpanel>
         <tabpanel><button id="b2" label="b2"/></tabpanel>
         <tabpanel></tabpanel>
       </tabpanels>
     </tabbox>
 
-    <listbox id="listbox">
-      <listitem id="lb1_item1" label="item1"/>
-      <listitem id="lb1_item2" label="item2"/>
-    </listbox>
+    <richlistbox id="listbox">
+      <richlistitem id="lb1_item1"><label value="item1"/></richlistitem>
+      <richlistitem id="lb1_item2"><label value="item2"/></richlistitem>
+    </richlistbox>
 
-    <listbox id="listbox2" seltype="multiple">
-      <listitem id="lb2_item1" label="item1"/>
-      <listitem id="lb2_item2" label="item2"/>
-      <listitem id="lb2_item3" label="item3"/>
-      <listitem id="lb2_item4" label="item4"/>
-      <listitem id="lb2_item5" label="item5"/>
-      <listitem id="lb2_item6" label="item6"/>
-      <listitem id="lb2_item7" label="item7"/>
-    </listbox>
+    <richlistbox id="listbox2" seltype="multiple">
+      <richlistitem id="lb2_item1"><label value="item1"/></richlistitem>
+      <richlistitem id="lb2_item2"><label value="item2"/></richlistitem>
+      <richlistitem id="lb2_item3"><label value="item3"/></richlistitem>
+      <richlistitem id="lb2_item4"><label value="item4"/></richlistitem>
+      <richlistitem id="lb2_item5"><label value="item5"/></richlistitem>
+      <richlistitem id="lb2_item6"><label value="item6"/></richlistitem>
+      <richlistitem id="lb2_item7"><label value="item7"/></richlistitem>
+    </richlistbox>
 
   </hbox>
 </window>
--- a/accessible/tests/mochitest/focus/test_takeFocus.xul
+++ b/accessible/tests/mochitest/focus/test_takeFocus.xul
@@ -90,17 +90,17 @@
       <tree id="tree" flex="1">
         <treecols>
           <treecol id="col1" flex="1" primary="true" label="column"/>
           <treecol id="col2" flex="1" label="column 2"/>
         </treecols>
         <treechildren id="treechildren"/>
       </tree>
 
-      <listbox id="listbox">
-        <listitem id="listitem1">item1</listitem>
-        <listitem id="listitem2">item2</listitem>
-      </listbox>
+      <richlistbox id="listbox">
+        <richlistitem id="listitem1"><label value="item1"/></richlistitem>
+        <richlistitem id="listitem2"><label value="item2"/></richlistitem>
+      </richlistbox>
 
       <vbox id="eventdump"/>
     </vbox>
   </hbox>
 </window>
--- a/accessible/tests/mochitest/name/test_general.xul
+++ b/accessible/tests/mochitest/name/test_general.xul
@@ -271,20 +271,21 @@
   <button id="btn_labelledby_mixed_menulist"
           aria-labelledby="labelledby_mixed_menulist"/>
 
   <!-- nsIDOMXULLabeledControlElement -->
   <button id="btn_nsIDOMXULLabeledControlElement"
           label="labeled element"/>
 
   <!-- nsIDOMXULSelectControlItemElement -->
-  <listbox>
-    <listitem id="li_nsIDOMXULSelectControlItemElement"
-              label="select control item"/>
-  </listbox>
+  <richlistbox>
+    <richlistitem id="li_nsIDOMXULSelectControlItemElement">
+      <label value="select control item"/>
+    </richlistitem>
+  </richlistbox>
 
   <!-- not nsIDOMXULSelectControlElement -->
   <box id="box_not_nsIDOMXULSelectControlElement" role="group" label="box"/>
 
   <!-- label element  -->
   <hbox>
     <box>
       <label control="btn_label_1">label1</label>
@@ -354,21 +355,22 @@
     <groupbox id="groupbox2">
       <caption><label>Some caption</label></caption>
       <checkbox label="some checkbox label" />
     </groupbox>
   </vbox>
 
   <!-- bug 441991; create name from other menuitem label listitem's own label -->
   <hbox>
-    <listbox>
-    <listitem id="li_labelledby"
-              label="The moment the event starts"
-              aria-labelledby="menuitem-DISPLAY li_labelledby"/>
-    </listbox>
+    <richlistbox>
+      <richlistitem id="li_labelledby"
+                    aria-labelledby="menuitem-DISPLAY li_labelledby">
+        <label value="The moment the event starts"/>
+      </richlistitem>
+    </richlistbox>
     <menulist>
       <menupopup>
         <menuitem id="menuitem-DISPLAY"
                   value="DISPLAY"
                   label="Show an Alert"/>
         <menuitem id="menuitem-EMAIL"
                   value="EMAIL"
                   label="Send an E-mail"/>
--- a/accessible/tests/mochitest/selectable/test_listbox.xul
+++ b/accessible/tests/mochitest/selectable/test_listbox.xul
@@ -27,23 +27,24 @@
 
     //gA11yEventDumpID = "debug";
 
     var gQueue = null;
 
     function doTest()
     {
       //////////////////////////////////////////////////////////////////////////
-      // single selectable listbox
+      // single selectable listbox, the first item is selected by default
 
       var id = "listbox";
       ok(isAccessible(id, [nsIAccessibleSelectable]),
          "No selectable accessible for list of " + id);
 
       var select = getAccessible(id, [nsIAccessibleSelectable]);
+      select.removeItemFromSelection(0);
       testSelectableSelection(select, [ ]);
 
       select.addItemToSelection(1);
       testSelectableSelection(select, [ "lb1_item2" ], "addItemToSelect(1): ");
 
       select.removeItemFromSelection(1);
       testSelectableSelection(select, [ ],
                               "removeItemFromSelection(1): ");
@@ -109,44 +110,36 @@
       <p id="display"></p>
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
-      <listbox id="listbox">
-        <listcols>
-          <listcol flex="1"/>
-          <listcol flex="1"/>
-        </listcols>
-        <listitem id="lb1_item1">
-          <listcell label="cell0"/>
-          <listcell label="cell1"/>
-        </listitem>
-        <listitem id="lb1_item2">
-          <listcell label="cell3"/>
-          <listcell label="cell4"/>
-        </listitem>
-      </listbox>
+      <richlistbox id="listbox">
+        <richlistitem id="lb1_item1">
+          <label value="cell0"/>
+          <label value="cell1"/>
+        </richlistitem>
+        <richlistitem id="lb1_item2">
+          <label value="cell3"/>
+          <label value="cell4"/>
+        </richlistitem>
+      </richlistbox>
 
-      <listbox id="listbox2" seltype="multiple">
-        <listcols>
-          <listcol flex="1"/>
-          <listcol flex="1"/>
-        </listcols>
-        <listitem id="lb2_item1">
-          <listcell label="cell0"/>
-          <listcell label="cell1"/>
-        </listitem>
-        <listitem id="lb2_item2">
-          <listcell label="cell3"/>
-          <listcell label="cell4"/>
-        </listitem>
-      </listbox>
+      <richlistbox id="listbox2" seltype="multiple">
+        <richlistitem id="lb2_item1">
+          <label value="cell0"/>
+          <label value="cell1"/>
+        </richlistitem>
+        <richlistitem id="lb2_item2">
+          <label value="cell3"/>
+          <label value="cell4"/>
+        </richlistitem>
+      </richlistbox>
 
       <vbox id="debug"/>
     </vbox>
   </hbox>
 
 </window>
 
--- a/accessible/tests/mochitest/states.js
+++ b/accessible/tests/mochitest/states.js
@@ -150,17 +150,17 @@ function testStates(aAccOrElmOrID, aStat
     isState(state & STATE_MIXED, 0, false,
             "Checked element cannot be state mixed!");
 
   if (state & STATE_MIXED)
     isState(state & STATE_CHECKED, 0, false,
             "Mixed element cannot be state checked!");
 
   // selected/selectable
-  if (state & STATE_SELECTED) {
+  if ((state & STATE_SELECTED) && !(aAbsentState & STATE_SELECTABLE)) {
     isState(state & STATE_SELECTABLE, STATE_SELECTABLE, false,
             "Selected element must be selectable!");
   }
 }
 
 /**
  * Tests an accessible and its sub tree for the passed in state bits.
  * Used to make sure that states are propagated to descendants, for example the
--- a/accessible/tests/mochitest/states/test_controls.xul
+++ b/accessible/tests/mochitest/states/test_controls.xul
@@ -59,19 +59,19 @@
       testStates("radio-disabledradiogroup", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
       testStates("button", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
       testStates("button-disabled", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
       testStates("colorpicker", STATE_FOCUSABLE | STATE_HASPOPUP, 0, STATE_UNAVAILABLE);
       testStates("colorpicker-disabled", STATE_HASPOPUP, 0, STATE_FOCUSABLE);
       testStates("combobox", STATE_FOCUSABLE | STATE_HASPOPUP, 0, STATE_UNAVAILABLE);
       testStates("combobox-disabled", STATE_UNAVAILABLE | STATE_HASPOPUP, 0, STATE_FOCUSABLE);
       testStates("listbox", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
-      testStates("listitem", STATE_FOCUSABLE | STATE_SELECTABLE, 0, STATE_UNAVAILABLE);
+      testStates("listitem", STATE_FOCUSABLE | STATE_SELECTABLE | STATE_SELECTED, 0, STATE_UNAVAILABLE);
       testStates("listbox-disabled", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE | STATE_SELECTABLE);
-      testStates("listitem-disabledlistbox", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE | STATE_SELECTABLE);
+      testStates("listitem-disabledlistbox", STATE_UNAVAILABLE | STATE_SELECTED, 0, STATE_FOCUSABLE | STATE_SELECTABLE);
       testStates("menubar", 0, 0, STATE_FOCUSABLE);
       testStates("menu", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
       testStates("menu-disabled", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE | STATE_SELECTABLE);
       testStates("tab", STATE_FOCUSABLE | STATE_SELECTABLE | STATE_SELECTED, 0, STATE_UNAVAILABLE);
       testStates("tab-disabled", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE | STATE_SELECTABLE | STATE_SELECTED);
 
       gQueue = new eventQueue();
       gQueue.push(new openColorpicker("colorpicker"));
@@ -130,23 +130,27 @@
     </menulist>
 
     <menulist id="combobox-disabled" disabled="true">
       <menupopup>
         <menuitem label="item1"/>
       </menupopup>
     </menulist>
 
-    <listbox id="listbox">
-      <listitem id="listitem" label="list item"/>
-    </listbox>
+    <richlistbox id="listbox">
+      <richlistitem id="listitem">
+        <label value="list item"/>
+      </richlistitem>
+    </richlistbox>
 
-    <listbox id="listbox-disabled" disabled="true">
-      <listitem id="listitem-disabledlistbox" label="list item"/>
-    </listbox>
+    <richlistbox id="listbox-disabled" disabled="true">
+      <richlistitem id="listitem-disabledlistbox">
+        <label value="list item"/>
+      </richlistitem>
+    </richlistbox>
 
     <toolbox>
       <menubar id="menubar">
         <menu id="menu" label="menu1">
           <menupopup>
             <menuitem id="menu1-item1" label="menuitem1.1"/>
           </menupopup>
         </menu>
--- a/accessible/tests/mochitest/table/a11y.ini
+++ b/accessible/tests/mochitest/table/a11y.ini
@@ -1,27 +1,23 @@
 [DEFAULT]
 support-files =
   !/accessible/tests/mochitest/*.js
 
 [test_css_tables.html]
 [test_headers_ariagrid.html]
 [test_headers_ariatable.html]
-[test_headers_listbox.xul]
 [test_headers_table.html]
 [test_headers_tree.xul]
 [test_indexes_ariagrid.html]
-[test_indexes_listbox.xul]
 [test_indexes_table.html]
 [test_indexes_tree.xul]
 [test_layoutguess.html]
 [test_mtable.html]
 [test_sels_ariagrid.html]
-[test_sels_listbox.xul]
 [test_sels_table.html]
 [test_sels_tree.xul]
 [test_struct_ariagrid.html]
 [test_struct_ariatreegrid.html]
-[test_struct_listbox.xul]
 [test_struct_table.html]
 [test_struct_tree.xul]
 [test_table_1.html]
 [test_table_2.html]
deleted file mode 100644
--- a/accessible/tests/mochitest/table/test_headers_listbox.xul
+++ /dev/null
@@ -1,194 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="Table header information cells for XUL listbox">
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-
-  <script type="application/javascript"
-          src="../common.js"></script>
-  <script type="application/javascript"
-          src="../table.js"></script>
-
-  <script type="application/javascript">
-  <![CDATA[
-    function doTest()
-    {
-      //////////////////////////////////////////////////////////////////////////
-      // XUL listbox
-
-      var headerInfoMap = [
-        {
-          cell: "lb1_cell0",
-          rowHeaderCells: [],
-          columnHeaderCells: [ "lb1_header1" ]
-        },
-        {
-          cell: "lb1_cell1",
-          rowHeaderCells: [],
-          columnHeaderCells: [ "lb1_header2" ]
-        },
-        {
-          cell: "lb1_cell2",
-          rowHeaderCells: [],
-          columnHeaderCells: [ "lb1_header3" ]
-        },
-        {
-          cell: "lb1_cell3",
-          rowHeaderCells: [],
-          columnHeaderCells: [ "lb1_header1" ]
-        },
-        {
-          cell: "lb1_cell4",
-          rowHeaderCells: [],
-          columnHeaderCells: [ "lb1_header2" ]
-        },
-        {
-          cell: "lb1_cell5",
-          rowHeaderCells: [],
-          columnHeaderCells: [ "lb1_header3" ]
-        },
-      ];
-
-      testHeaderCells(headerInfoMap);
-
-      //////////////////////////////////////////////////////////////////////////
-      // XUL listbox with ARIA
-
-      headerInfoMap = [
-        {
-          cell: "lb2_cell0",
-          rowHeaderCells: [],
-          columnHeaderCells: []
-        },
-        {
-          cell: "lb2_cell1",
-          rowHeaderCells: [],
-          columnHeaderCells: []
-        },
-        {
-          cell: "lb2_cell2",
-          rowHeaderCells: [],
-          columnHeaderCells: []
-        },
-        {
-          cell: "lb2_cell3",
-          rowHeaderCells: [],
-          columnHeaderCells: [ "lb2_cell0" ]
-        },
-        {
-          cell: "lb2_cell4",
-          rowHeaderCells: [ "lb2_cell3" ],
-          columnHeaderCells: [ "lb2_cell1" ]
-        },
-        {
-          cell: "lb2_cell5",
-          rowHeaderCells: [ "lb2_cell3" ],
-          columnHeaderCells: [ "lb2_cell2" ]
-        },
-        {
-          cell: "lb2_cell6",
-          rowHeaderCells: [],
-          columnHeaderCells: [ "lb2_cell0" ]
-        },
-        {
-          cell: "lb2_cell7",
-          rowHeaderCells: [ "lb2_cell6" ],
-          columnHeaderCells: [ "lb2_cell1" ]
-        },
-        {
-          cell: "lb2_cell8",
-          rowHeaderCells: [ "lb2_cell6" ],
-          columnHeaderCells: [ "lb2_cell2" ]
-        }
-      ];
-
-      testHeaderCells(headerInfoMap);
-
-      SimpleTest.finish();
-    }
-
-    SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTest);
-  ]]>
-  </script>
-
-  <hbox style="overflow: auto;">
-  <body xmlns="http://www.w3.org/1999/xhtml">
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=512424"
-       title="implement IAccessibleTable2">
-      Mozilla Bug 512424
-    </a>
-
-    <p id="display"></p>
-    <div id="content" style="display: none">
-    </div>
-    <pre id="test">
-    </pre>
-  </body>
-
-  <vbox flex="1">
-
-    <label control="listbox" value="multicolumn listbox with header"/>
-    <listbox id="listbox">
-      <listhead>
-        <listheader id="lb1_header1" label="header1"/>
-        <listheader id="lb1_header2" label="header2"/>
-        <listheader id="lb1_header3" label="header3"/>
-      </listhead>
-      <listcols>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-      </listcols>
-      <listitem>
-        <listcell id="lb1_cell0" label="cell0"/>
-        <listcell id="lb1_cell1" label="cell1"/>
-        <listcell id="lb1_cell2" label="cell2"/>
-      </listitem>
-      <listitem>
-        <listcell id="lb1_cell3" label="cell3"/>
-        <listcell id="lb1_cell4" label="cell4"/>
-        <listcell id="lb1_cell5" label="cell5"/>
-      </listitem>
-      <listitem>
-        <listcell id="lb1_cell6" label="cell6"/>
-        <listcell id="lb1_cell7" label="cell7"/>
-        <listcell id="lb1_cell8" label="cell8"/>
-      </listitem>
-    </listbox>
-
-    <label control="listbox2" value="multicolumn listbox with ARIA headers"/>
-    <listbox id="listbox2">
-      <listcols>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-      </listcols>
-      <listitem>
-        <listcell role="columnheader" id="lb2_cell0" label="cell0"/>
-        <listcell role="columnheader" id="lb2_cell1" label="cell1"/>
-        <listcell role="columnheader" id="lb2_cell2" label="cell2"/>
-      </listitem>
-      <listitem>
-        <listcell role="rowheader" id="lb2_cell3" label="cell3"/>
-        <listcell id="lb2_cell4" label="cell4"/>
-        <listcell id="lb2_cell5" label="cell5"/>
-      </listitem>
-      <listitem>
-        <listcell role="rowheader" id="lb2_cell6" label="cell6"/>
-        <listcell id="lb2_cell7" label="cell7"/>
-        <listcell id="lb2_cell8" label="cell8"/>
-      </listitem>
-    </listbox>
-
-  </vbox>
-  </hbox>
-
-</window>
-
deleted file mode 100644
--- a/accessible/tests/mochitest/table/test_indexes_listbox.xul
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="Table indices of accessible table for XUL listbox">
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-
-  <script type="application/javascript"
-          src="../common.js"></script>
-  <script type="application/javascript"
-          src="../table.js"></script>
-
-  <script type="application/javascript">
-  <![CDATA[
-    function doTest()
-    {
-      var idxes = [
-        [0, 1, 2],
-        [3, 4, 5],
-        [6, 7, 8]
-      ];
-      testTableIndexes("listbox", idxes);
-
-      SimpleTest.finish();
-    }
-
-    SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTest);
-  ]]>
-  </script>
-
-  <hbox style="overflow: auto;">
-  <body xmlns="http://www.w3.org/1999/xhtml">
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=512424"
-       title="implement IAccessibleTable2">
-      Mozilla Bug 512424
-    </a>
-
-    <p id="display"></p>
-    <div id="content" style="display: none">
-    </div>
-    <pre id="test">
-    </pre>
-  </body>
-
-  <vbox flex="1">
-
-    <label control="listbox" value="multicolumn listbox with header"/>
-    <listbox id="listbox">
-      <listhead>
-        <listheader label="header1"/>
-        <listheader label="header2"/>
-        <listheader label="header3"/>
-      </listhead>
-      <listcols>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-      </listcols>
-      <listitem>
-        <listcell label="cell0"/>
-        <listcell label="cell1"/>
-        <listcell label="cell2"/>
-      </listitem>
-      <listitem>
-        <listcell label="cell3"/>
-        <listcell label="cell4"/>
-        <listcell label="cell5"/>
-      </listitem>
-      <listitem>
-        <listcell label="cell6"/>
-        <listcell label="cell7"/>
-        <listcell label="cell8"/>
-      </listitem>
-    </listbox>
-  </vbox>
-  </hbox>
-
-</window>
-
deleted file mode 100644
--- a/accessible/tests/mochitest/table/test_sels_listbox.xul
+++ /dev/null
@@ -1,247 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="nsIAccessibleTable selection methods on xul:listbox test.">
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-
-  <script type="application/javascript"
-          src="../common.js"></script>
-  <script type="application/javascript"
-          src="../table.js"></script>
-
-  <script type="application/javascript">
-  <![CDATA[
-    function doTest()
-    {
-      var id = "listbox3";
-      var acc = getAccessible(id, [nsIAccessibleTable]);
-
-      var rowCount = acc.rows;
-      var colsCount = acc.columns;
-
-      // columns selection
-      testColumnSelection(id, acc, colsCount, 0, null);
-      acc.selectColumn(0);
-      testColumnSelection(id, acc, colsCount, 0, null);
-
-      // rows selection
-      testRowSelection(id, acc, rowCount, 0, null);
-      acc.selectRow(0);
-      testRowSelection(id, acc, rowCount, 1, [0]);
-      acc.selectRow(1);
-      testRowSelection(id, acc, rowCount, 1, [1]);
-      acc.unselectRow(1);
-      testRowSelection(id, acc, rowCount, 0, null);
-
-      // cells selection
-      testCellSelection(id, acc, rowCount, colsCount, 0, null);
-      acc.selectRow(2);
-      testCellSelection(id, acc, rowCount, colsCount, 3, [6, 7, 8]);
-      acc.unselectRow(2);
-      testCellSelection(id, acc, rowCount, colsCount, 0, null);
-
-      SimpleTest.finish();
-    }
-
-    /**
-     * Helper function to test isColumnSelected(), selectedColumnCount and
-     * getSelectedColumn() methods.
-     */
-    function testColumnSelection(aId, aAcc, aCount, aSelCount, aSelIndexesArray)
-    {
-      // isColumnSelected
-      for (var col = 0; col < aCount; col++) {
-        if (aSelIndexesArray && aSelIndexesArray.includes(col)) {
-          is(aAcc.isColumnSelected(col), true,
-             aId + ": column " + col + " should be selected");
-        } else {
-          is(aAcc.isColumnSelected(col), false,
-             aId + ": column " + col + " shouldn't be selected");
-        }
-      }
-
-      // selectedColumnCount
-      is(aAcc.selectedColumnCount, aSelCount,
-         aId + ": wrong number of selected columns");
-
-      // getSelectedColumns
-      var selColsCount = {}, selCols = {};
-      aAcc.getSelectedColumnIndices(selColsCount, selCols);
-
-      is(selColsCount.value, aSelCount,
-         aId + ": wrong number of selected columns");
-
-      if (!aSelIndexesArray) {
-        is(selCols.value, undefined,
-           aId + ": no columns should be selected");
-      } else {
-        for (var i = 0; i < selCols.length; i++) {
-          is(selCols[i], aSelIndexesArray[i],
-             aId + ": wrong selected column index " + i);
-        }
-      }
-    }
-
-    /**
-     * Helper function to test isRowSelected(), selectedRowCount() and
-     * getSelectedRow() methods.
-     */
-    function testRowSelection(aId, aAcc, aCount, aSelCount, aSelIndexesArray)
-    {
-      // isRowSelected
-      for (var row = 0; row < aCount; row++) {
-        if (aSelIndexesArray && aSelIndexesArray.includes(row)) {
-          is(aAcc.isRowSelected(row), true,
-             aId + ": row " + row + " should be selected");
-        } else {
-          is(aAcc.isRowSelected(row), false,
-             aId + ": row " + row + " shouldn't be selected");
-        }
-      }
-
-      // selectedRowCount
-      is(aAcc.selectedRowCount, aSelCount,
-         aId + ": wrong number of selected rows");
-
-      // getSelectedRows
-      var selColsCount = {}, selCols = {};
-      aAcc.getSelectedRowIndices(selColsCount, selCols);
-
-      is(selColsCount.value, aSelCount,
-         aId + ": wrong number of selected rows");
-
-      if (!aSelIndexesArray) {
-        is(selCols.value, undefined,
-           aId + ": no row should be selected");
-      } else {
-        for (var i = 0; i < selCols.length; i++) {
-          is(selCols[i], aSelIndexesArray[i],
-             aId + ": wrong selected row index " + i);
-        }
-      }
-    }
-
-    /**
-     * Helper function to test isCellSelected(), selectedCellCount() and
-     * getSelectedCells() methods.
-     */
-    function testCellSelection(aId, aAcc, aRowCount, aColCount,
-                               aSelCount, aSelIndexesArray)
-    {
-      // isCellSelected
-      for (var row = 0; row < aRowCount; row++) {
-        for (var col = 0; col < aColCount; col++) {
-          var index = aAcc.getIndexAt(row, col);
-          if (aSelIndexesArray && aSelIndexesArray.includes(index)) {
-            is(aAcc.isCellSelected(row, col), true,
-               aId + ": cell (" + row + ", " + col + ") should be selected");
-          } else {
-            is(aAcc.isCellSelected(row, col), false,
-               aId + ": cell (" + row + ", " + col + ") shouldn't be selected");
-          }
-        }
-      }
-
-      // selectedCellCount
-      is(aAcc.selectedCellCount, aSelCount,
-         aId + ": wrong number of selected cells");
-
-      // getSelectedCells
-      var selColsCount = {}, selCols = {};
-      aAcc.getSelectedCellIndices(selColsCount, selCols);
-
-      is(selColsCount.value, aSelCount,
-         aId + ": wrong number of selected cells");
-
-      if (!aSelIndexesArray) {
-        is(selCols.value, undefined,
-           aId + ": no cells should be selected");
-      } else {
-        for (var i = 0; i < selCols.length; i++) {
-          is(selCols[i], aSelIndexesArray[i],
-             aId + ": wrong selected cell index " + i);
-        }
-      }
-    }
-
-    SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTest);
-  ]]>
-  </script>
-
-  <hbox style="overflow: auto;">
-  <body xmlns="http://www.w3.org/1999/xhtml">
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=418371"
-       title="implement the rest of methods of nsIAccessibleTable on xul:listbox">
-      Mozilla Bug 418371
-    </a>
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=512424"
-       title="implement IAccessibleTable2">
-      Mozilla Bug 512424
-    </a>
-
-    <p id="display"></p>
-    <div id="content" style="display: none">
-    </div>
-    <pre id="test">
-    </pre>
-  </body>
-
-  <vbox flex="1">
-
-    <label control="listbox2" value="multicolumn listbox: "/>
-    <listbox id="listbox2">
-      <listcols>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-      </listcols>
-      <listitem>
-        <listcell label="cell1"/>
-        <listcell label="cell2"/>
-      </listitem>
-      <listitem>
-        <listcell label="cell1"/>
-        <listcell label="cell2"/>
-      </listitem>
-    </listbox>
-
-    <label control="listbox3" value="multicolumn listbox with header"/>
-    <listbox id="listbox3">
-      <listhead>
-        <listheader label="header1"/>
-        <listheader label="header2"/>
-        <listheader label="header3"/>
-      </listhead>
-      <listcols>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-      </listcols>
-      <listitem>
-        <listcell label="cell0"/>
-        <listcell label="cell1"/>
-        <listcell label="cell2"/>
-      </listitem>
-      <listitem>
-        <listcell label="cell3"/>
-        <listcell label="cell4"/>
-        <listcell label="cell5"/>
-      </listitem>
-      <listitem>
-        <listcell label="cell6"/>
-        <listcell label="cell7"/>
-        <listcell label="cell8"/>
-      </listitem>
-    </listbox>
-  </vbox>
-  </hbox>
-
-</window>
-
deleted file mode 100644
--- a/accessible/tests/mochitest/table/test_struct_listbox.xul
+++ /dev/null
@@ -1,117 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="Table accessible tree and table interface tests for XUL listboxes">
-
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-
-  <script type="application/javascript"
-          src="../common.js"></script>
-  <script type="application/javascript"
-          src="../role.js"></script>
-  <script type="application/javascript"
-          src="../table.js"></script>
-
-  <script type="application/javascript">
-  <![CDATA[
-    function doTest()
-    {
-      //////////////////////////////////////////////////////////////////////////
-      // Multicolumn listbox.
-
-      var cellsArray = [
-        [kDataCell, kDataCell],
-        [kDataCell, kDataCell]
-      ];
-
-      testTableStruct("listbox1", cellsArray);
-
-      //////////////////////////////////////////////////////////////////////////
-      // Multicolumn listbox with header.
-
-      var cellsArray = [
-        [kDataCell, kDataCell, kDataCell],
-        [kDataCell, kDataCell, kDataCell],
-        [kDataCell, kDataCell, kDataCell]
-      ];
-
-      testTableStruct("listbox2", cellsArray, kListboxColumnHeader);
-
-      SimpleTest.finish();
-    }
-
-    SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTest);
-  ]]>
-  </script>
-
-  <hbox style="overflow: auto;">
-  <body xmlns="http://www.w3.org/1999/xhtml">
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=512424"
-       title="implement IAccessibleTable2">
-      Mozilla Bug 512424
-    </a>
-
-    <p id="display"></p>
-    <div id="content" style="display: none">
-    </div>
-    <pre id="test">
-    </pre>
-  </body>
-
-  <vbox flex="1">
-
-    <label control="listbox1" value="multicolumn listbox: "/>
-    <listbox id="listbox1">
-      <listcols>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-      </listcols>
-      <listitem>
-        <listcell label="cell1"/>
-        <listcell label="cell2"/>
-      </listitem>
-      <listitem>
-        <listcell label="cell1"/>
-        <listcell label="cell2"/>
-      </listitem>
-    </listbox>
-
-    <label control="listbox2" value="multicolumn listbox with header"/>
-    <listbox id="listbox2">
-      <listhead>
-        <listheader label="header1"/>
-        <listheader label="header2"/>
-        <listheader label="header3"/>
-      </listhead>
-      <listcols>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-        <listcol flex="1"/>
-      </listcols>
-      <listitem>
-        <listcell label="cell0"/>
-        <listcell label="cell1"/>
-        <listcell label="cell2"/>
-      </listitem>
-      <listitem>
-        <listcell label="cell3"/>
-        <listcell label="cell4"/>
-        <listcell label="cell5"/>
-      </listitem>
-      <listitem>
-        <listcell label="cell6"/>
-        <listcell label="cell7"/>
-        <listcell label="cell8"/>
-      </listitem>
-    </listbox>
-  </vbox>
-  </hbox>
-
-</window>
-
--- a/accessible/tests/mochitest/treeupdate/test_listbox.xul
+++ b/accessible/tests/mochitest/treeupdate/test_listbox.xul
@@ -20,18 +20,20 @@
   <![CDATA[
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
     function insertListitem(aListboxID)
     {
       this.listboxNode = getNode(aListboxID);
 
-      this.listitemNode = document.createElement("listitem");
-      this.listitemNode.setAttribute("label", "item1");
+      this.listitemNode = document.createElement("richlistitem");
+      var label = document.createElement("label");
+      label.setAttribute("value", "item1");
+      this.listitemNode.appendChild(label);
 
       this.eventSeq = [
         new invokerChecker(EVENT_SHOW, this.listitemNode),
         new invokerChecker(EVENT_REORDER, this.listboxNode)
       ];
 
       this.invoke = function insertListitem_invoke()
       {
@@ -163,18 +165,18 @@
       <p id="display"></p>
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
-      <listbox id="listbox" rows="2">
-        <listitem label="item2"/>
-        <listitem label="item3"/>
-        <listitem label="item4"/>
-      </listbox>
+      <richlistbox id="listbox">
+        <richlistitem><label value="item2"/></richlistitem>
+        <richlistitem><label value="item3"/></richlistitem>
+        <richlistitem><label value="item4"/></richlistitem>
+      </richlistbox>
     </vbox>
   </hbox>
 
 </window>
 
--- a/browser/base/content/test/performance/browser_startup_content.js
+++ b/browser/base/content/test/performance/browser_startup_content.js
@@ -40,16 +40,17 @@ const whitelist = {
     "resource://gre/modules/Services.jsm", // bug 1464542
     "resource://gre/modules/Timer.jsm",
     "resource://gre/modules/XPCOMUtils.jsm",
 
     // Logging related
     "resource://gre/modules/Log.jsm",
 
     // Session store
+    "resource:///modules/sessionstore/ContentSessionStore.jsm",
     "resource://gre/modules/sessionstore/SessionHistory.jsm",
 
     // Forms and passwords
     "resource://formautofill/FormAutofill.jsm",
     "resource://formautofill/FormAutofillContent.jsm",
 
     // Browser front-end
     "resource:///modules/ContentLinkHandler.jsm",
copy from browser/components/sessionstore/content/content-sessionStore.js
copy to browser/components/sessionstore/ContentSessionStore.jsm
--- a/browser/components/sessionstore/content/content-sessionStore.js
+++ b/browser/components/sessionstore/ContentSessionStore.jsm
@@ -1,15 +1,15 @@
 /* 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/. */
 
-/* eslint-env mozilla/frame-script */
+"use strict";
 
-"use strict";
+var EXPORTED_SYMBOLS = ["ContentSessionStore"];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
 ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
 ChromeUtils.import("resource://gre/modules/Services.jsm", this);
 
 ChromeUtils.defineModuleGetter(this, "TelemetryStopwatch",
   "resource://gre/modules/TelemetryStopwatch.jsm");
 
@@ -26,133 +26,149 @@ ChromeUtils.defineModuleGetter(this, "Do
   "resource:///modules/sessionstore/DocShellCapabilities.jsm");
 ChromeUtils.defineModuleGetter(this, "ScrollPosition",
   "resource://gre/modules/ScrollPosition.jsm");
 ChromeUtils.defineModuleGetter(this, "SessionHistory",
   "resource://gre/modules/sessionstore/SessionHistory.jsm");
 ChromeUtils.defineModuleGetter(this, "SessionStorage",
   "resource:///modules/sessionstore/SessionStorage.jsm");
 
-var contentRestoreInitialized = false;
-
-XPCOMUtils.defineLazyGetter(this, "gContentRestore",
-                            () => {
-                              contentRestoreInitialized = true;
-                              return new ContentRestore(this);
-                            });
-
 ChromeUtils.defineModuleGetter(this, "Utils",
   "resource://gre/modules/sessionstore/Utils.jsm");
 const ssu = Cc["@mozilla.org/browser/sessionstore/utils;1"]
               .getService(Ci.nsISessionStoreUtils);
 
-// The current epoch.
-var gCurrentEpoch = 0;
-
 // A bound to the size of data to store for DOM Storage.
 const DOM_STORAGE_LIMIT_PREF = "browser.sessionstore.dom_storage_limit";
 
 // This pref controls whether or not we send updates to the parent on a timeout
 // or not, and should only be used for tests or debugging.
 const TIMEOUT_DISABLED_PREF = "browser.sessionstore.debug.no_auto_updates";
 
 const PREF_INTERVAL = "browser.sessionstore.interval";
 
 const kNoIndex = Number.MAX_SAFE_INTEGER;
 const kLastIndex = Number.MAX_SAFE_INTEGER - 1;
 
-// Grab our global so we can access it in functions below.
-const global = this;
-
 /**
  * A function that will recursively call |cb| to collect data for all
  * non-dynamic frames in the current frame/docShell tree.
  */
-function mapFrameTree(callback) {
-  let [data] = Utils.mapFrameTree(content, callback);
+function mapFrameTree(mm, callback) {
+  let [data] = Utils.mapFrameTree(mm.content, callback);
   return data;
 }
 
+class Handler {
+  constructor(store) {
+    this.store = store;
+  }
+
+  get contentRestore() {
+    return this.store.contentRestore;
+  }
+
+  get contentRestoreInitialized() {
+    return this.store.contentRestoreInitialized;
+  }
+
+  get mm() {
+    return this.store.mm;
+  }
+
+  get messageQueue() {
+    return this.store.messageQueue;
+  }
+
+  get stateChangeNotifier() {
+    return this.store.stateChangeNotifier;
+  }
+}
+
 /**
  * Listens for state change notifcations from webProgress and notifies each
  * registered observer for either the start of a page load, or its completion.
  */
-var StateChangeNotifier = {
+class StateChangeNotifier extends Handler {
+  constructor(store) {
+    super(store);
 
-  init() {
     this._observers = new Set();
-    let ifreq = docShell.QueryInterface(Ci.nsIInterfaceRequestor);
+    let ifreq = this.mm.docShell.QueryInterface(Ci.nsIInterfaceRequestor);
     let webProgress = ifreq.getInterface(Ci.nsIWebProgress);
     webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
-  },
+  }
 
   /**
    * Adds a given observer |obs| to the set of observers that will be notified
    * when when a new document starts or finishes loading.
    *
    * @param obs (object)
    */
   addObserver(obs) {
     this._observers.add(obs);
-  },
+  }
 
   /**
    * Notifies all observers that implement the given |method|.
    *
    * @param method (string)
    */
   notifyObservers(method) {
     for (let obs of this._observers) {
-      if (obs.hasOwnProperty(method)) {
+      if (typeof obs[method] == "function") {
         obs[method]();
       }
     }
-  },
+  }
 
   /**
    * @see nsIWebProgressListener.onStateChange
    */
   onStateChange(webProgress, request, stateFlags, status) {
     // Ignore state changes for subframes because we're only interested in the
     // top-document starting or stopping its load.
-    if (!webProgress.isTopLevel || webProgress.DOMWindow != content) {
+    if (!webProgress.isTopLevel || webProgress.DOMWindow != this.mm.content) {
       return;
     }
 
     // onStateChange will be fired when loading the initial about:blank URI for
     // a browser, which we don't actually care about. This is particularly for
     // the case of unrestored background tabs, where the content has not yet
     // been restored: we don't want to accidentally send any updates to the
     // parent when the about:blank placeholder page has loaded.
-    if (!docShell.hasLoadedNonBlankURI) {
+    if (!this.mm.docShell.hasLoadedNonBlankURI) {
       return;
     }
 
     if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
       this.notifyObservers("onPageLoadStarted");
     } else if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
       this.notifyObservers("onPageLoadCompleted");
     }
-  },
-
-  QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener,
-                                          Ci.nsISupportsWeakReference])
-};
+  }
+}
+StateChangeNotifier.prototype.QueryInterface =
+  ChromeUtils.generateQI([Ci.nsIWebProgressListener,
+                          Ci.nsISupportsWeakReference]);
 
 /**
  * Listens for and handles content events that we need for the
  * session store service to be notified of state changes in content.
  */
-var EventListener = {
+class EventListener extends Handler {
+  constructor(store) {
+    super(store);
 
-  init() {
-    ssu.addDynamicFrameFilteredListener(global, "load", this, true);
-  },
+    ssu.addDynamicFrameFilteredListener(this.mm, "load", this, true);
+  }
 
   handleEvent(event) {
+    let {content} = this.mm;
+
     // Ignore load events from subframes.
     if (event.target != content.document) {
       return;
     }
 
     if (content.document.documentURI.startsWith("about:reader")) {
       if (event.type == "load" &&
           !content.document.body.classList.contains("loaded")) {
@@ -160,204 +176,86 @@ var EventListener = {
         // point; listen for the custom event dispatched from AboutReader.jsm.
         content.addEventListener("AboutReaderContentReady", this);
         return;
       }
 
       content.removeEventListener("AboutReaderContentReady", this);
     }
 
-    if (contentRestoreInitialized) {
+    if (this.contentRestoreInitialized) {
       // Restore the form data and scroll position. If we're not currently
       // restoring a tab state then this call will simply be a noop.
-      gContentRestore.restoreDocument();
+      this.contentRestore.restoreDocument();
     }
   }
-};
-
-/**
- * Listens for and handles messages sent by the session store service.
- */
-var MessageListener = {
-
-  MESSAGES: [
-    "SessionStore:restoreHistory",
-    "SessionStore:restoreTabContent",
-    "SessionStore:resetRestore",
-    "SessionStore:flush",
-    "SessionStore:becomeActiveProcess",
-  ],
-
-  init() {
-    this.MESSAGES.forEach(m => addMessageListener(m, this));
-  },
-
-  receiveMessage({name, data}) {
-    // The docShell might be gone. Don't process messages,
-    // that will just lead to errors anyway.
-    if (!docShell) {
-      return;
-    }
-
-    // A fresh tab always starts with epoch=0. The parent has the ability to
-    // override that to signal a new era in this tab's life. This enables it
-    // to ignore async messages that were already sent but not yet received
-    // and would otherwise confuse the internal tab state.
-    if (data.epoch && data.epoch != gCurrentEpoch) {
-      gCurrentEpoch = data.epoch;
-    }
-
-    switch (name) {
-      case "SessionStore:restoreHistory":
-        this.restoreHistory(data);
-        break;
-      case "SessionStore:restoreTabContent":
-        if (data.isRemotenessUpdate) {
-          let histogram = Services.telemetry.getKeyedHistogramById("FX_TAB_REMOTE_NAVIGATION_DELAY_MS");
-          histogram.add("SessionStore:restoreTabContent",
-                        Services.telemetry.msSystemNow() - data.requestTime);
-        }
-        this.restoreTabContent(data);
-        break;
-      case "SessionStore:resetRestore":
-        gContentRestore.resetRestore();
-        break;
-      case "SessionStore:flush":
-        this.flush(data);
-        break;
-      case "SessionStore:becomeActiveProcess":
-        SessionHistoryListener.collect();
-        break;
-      default:
-        debug("received unknown message '" + name + "'");
-        break;
-    }
-  },
-
-  restoreHistory({epoch, tabData, loadArguments, isRemotenessUpdate}) {
-    gContentRestore.restoreHistory(tabData, loadArguments, {
-      // Note: The callbacks passed here will only be used when a load starts
-      // that was not initiated by sessionstore itself. This can happen when
-      // some code calls browser.loadURI() or browser.reload() on a pending
-      // browser/tab.
-
-      onLoadStarted() {
-        // Notify the parent that the tab is no longer pending.
-        sendAsyncMessage("SessionStore:restoreTabContentStarted", {epoch});
-      },
-
-      onLoadFinished() {
-        // Tell SessionStore.jsm that it may want to restore some more tabs,
-        // since it restores a max of MAX_CONCURRENT_TAB_RESTORES at a time.
-        sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch});
-      }
-    });
-
-    if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_DEFAULT) {
-      // For non-remote tabs, when restoreHistory finishes, we send a synchronous
-      // message to SessionStore.jsm so that it can run SSTabRestoring. Users of
-      // SSTabRestoring seem to get confused if chrome and content are out of
-      // sync about the state of the restore (particularly regarding
-      // docShell.currentURI). Using a synchronous message is the easiest way
-      // to temporarily synchronize them.
-      //
-      // For remote tabs, because all nsIWebProgress notifications are sent
-      // asynchronously using messages, we get the same-order guarantees of the
-      // message manager, and can use an async message.
-      sendSyncMessage("SessionStore:restoreHistoryComplete", {epoch, isRemotenessUpdate});
-    } else {
-      sendAsyncMessage("SessionStore:restoreHistoryComplete", {epoch, isRemotenessUpdate});
-    }
-  },
-
-  restoreTabContent({loadArguments, isRemotenessUpdate, reason}) {
-    let epoch = gCurrentEpoch;
-
-    // We need to pass the value of didStartLoad back to SessionStore.jsm.
-    let didStartLoad = gContentRestore.restoreTabContent(loadArguments, isRemotenessUpdate, () => {
-      // Tell SessionStore.jsm that it may want to restore some more tabs,
-      // since it restores a max of MAX_CONCURRENT_TAB_RESTORES at a time.
-      sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
-    });
-
-    sendAsyncMessage("SessionStore:restoreTabContentStarted", {
-      epoch, isRemotenessUpdate, reason,
-    });
-
-    if (!didStartLoad) {
-      // Pretend that the load succeeded so that event handlers fire correctly.
-      sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
-    }
-  },
-
-  flush({id}) {
-    // Flush the message queue, send the latest updates.
-    MessageQueue.send({flushID: id});
-  }
-};
+}
 
 /**
  * Listens for changes to the session history. Whenever the user navigates
  * we will collect URLs and everything belonging to session history.
  *
  * Causes a SessionStore:update message to be sent that contains the current
  * session history.
  *
  * Example:
  *   {entries: [{url: "about:mozilla", ...}, ...], index: 1}
  */
-var SessionHistoryListener = {
-  init() {
+class SessionHistoryListener extends Handler {
+  constructor(store) {
+    super(store);
+
+    this._fromIdx = kNoIndex;
+
+
     // The state change observer is needed to handle initial subframe loads.
     // It will redundantly invalidate with the SHistoryListener in some cases
     // but these invalidations are very cheap.
-    StateChangeNotifier.addObserver(this);
+    this.stateChangeNotifier.addObserver(this);
 
     // By adding the SHistoryListener immediately, we will unfortunately be
     // notified of every history entry as the tab is restored. We don't bother
     // waiting to add the listener later because these notifications are cheap.
     // We will likely only collect once since we are batching collection on
     // a delay.
-    docShell.QueryInterface(Ci.nsIWebNavigation).
-      sessionHistory.legacySHistory.addSHistoryListener(this);
+    this.mm.docShell.QueryInterface(Ci.nsIWebNavigation)
+      .sessionHistory.legacySHistory.addSHistoryListener(this);
 
     // Collect data if we start with a non-empty shistory.
-    if (!SessionHistory.isEmpty(docShell)) {
+    if (!SessionHistory.isEmpty(this.mm.docShell)) {
       this.collect();
       // When a tab is detached from the window, for the new window there is a
       // new SessionHistoryListener created. Normally it is empty at this point
       // but in a test env. the initial about:blank might have a children in which
       // case we fire off a history message here with about:blank in it. If we
       // don't do it ASAP then there is going to be a browser swap and the parent
       // will be all confused by that message.
-      MessageQueue.send();
+      this.messageQueue.send();
     }
 
     // Listen for page title changes.
-    addEventListener("DOMTitleChanged", this);
-  },
+    this.mm.addEventListener("DOMTitleChanged", this);
+  }
 
   uninit() {
-    let sessionHistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
+    let sessionHistory = this.mm.docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
     if (sessionHistory) {
       sessionHistory.legacySHistory.removeSHistoryListener(this);
     }
-  },
+  }
 
   collect() {
     // We want to send down a historychange even for full collects in case our
     // session history is a partial session history, in which case we don't have
     // enough information for a full update. collectFrom(-1) tells the collect
     // function to collect all data avaliable in this process.
-    if (docShell) {
+    if (this.mm.docShell) {
       this.collectFrom(-1);
     }
-  },
-
-  _fromIdx: kNoIndex,
+  }
 
   // History can grow relatively big with the nested elements, so if we don't have to, we
   // don't want to send the entire history all the time. For a simple optimization
   // we keep track of the smallest index from after any change has occured and we just send
   // the elements from that index. If something more complicated happens we just clear it
   // and send the entire history. We always send the additional info like the current selected
   // index (so for going back and forth between history entries we set the index to kLastIndex
   // if nothing else changed send an empty array and the additonal info like the selected index)
@@ -367,124 +265,124 @@ var SessionHistoryListener = {
       // tha happened with an element with index larger than N.
       // Note: initially we use kNoIndex which is MAX_SAFE_INTEGER which means we don't ignore anything
       // here, and in case of navigation in the history back and forth we use kLastIndex which ignores
       // only the subsequent navigations, but not any new elements added.
       return;
     }
 
     this._fromIdx = idx;
-    MessageQueue.push("historychange", () => {
+    this.messageQueue.push("historychange", () => {
       if (this._fromIdx === kNoIndex) {
         return null;
       }
 
-      let history = SessionHistory.collect(docShell, this._fromIdx);
+      let history = SessionHistory.collect(this.mm.docShell, this._fromIdx);
       this._fromIdx = kNoIndex;
       return history;
     });
-  },
+  }
 
   handleEvent(event) {
     this.collect();
-  },
+  }
 
   onPageLoadCompleted() {
     this.collect();
-  },
+  }
 
   onPageLoadStarted() {
     this.collect();
-  },
+  }
 
   OnHistoryNewEntry(newURI, oldIndex) {
     // We ought to collect the previously current entry as well, see bug 1350567.
     this.collectFrom(oldIndex);
-  },
+  }
 
   OnHistoryGoBack(backURI) {
     // We ought to collect the previously current entry as well, see bug 1350567.
     this.collectFrom(kLastIndex);
     return true;
-  },
+  }
 
   OnHistoryGoForward(forwardURI) {
     // We ought to collect the previously current entry as well, see bug 1350567.
     this.collectFrom(kLastIndex);
     return true;
-  },
+  }
 
   OnHistoryGotoIndex(index, gotoURI) {
     // We ought to collect the previously current entry as well, see bug 1350567.
     this.collectFrom(kLastIndex);
     return true;
-  },
+  }
 
   OnHistoryPurge(numEntries) {
     this.collect();
     return true;
-  },
+  }
 
   OnHistoryReload(reloadURI, reloadFlags) {
     this.collect();
     return true;
-  },
+  }
 
   OnHistoryReplaceEntry(index) {
     this.collect();
-  },
+  }
 
   OnLengthChanged(aCount) {
     // Ignore, the method is implemented so that XPConnect doesn't throw!
-  },
+  }
 
   OnIndexChanged(aIndex) {
     // Ignore, the method is implemented so that XPConnect doesn't throw!
-  },
-
-  QueryInterface: ChromeUtils.generateQI([
-    Ci.nsISHistoryListener,
-    Ci.nsISupportsWeakReference
-  ])
-};
+  }
+}
+SessionHistoryListener.prototype.QueryInterface =
+  ChromeUtils.generateQI([Ci.nsISHistoryListener,
+                          Ci.nsISupportsWeakReference]);
 
 /**
  * Listens for scroll position changes. Whenever the user scrolls the top-most
  * frame we update the scroll position and will restore it when requested.
  *
  * Causes a SessionStore:update message to be sent that contains the current
  * scroll positions as a tree of strings. If no frame of the whole frame tree
  * is scrolled this will return null so that we don't tack a property onto
  * the tabData object in the parent process.
  *
  * Example:
  *   {scroll: "100,100", children: [null, null, {scroll: "200,200"}]}
  */
-var ScrollPositionListener = {
-  init() {
-    ssu.addDynamicFrameFilteredListener(global, "scroll", this, false);
-    StateChangeNotifier.addObserver(this);
-  },
+class ScrollPositionListener extends Handler {
+  constructor(store) {
+    super(store);
+
+    ssu.addDynamicFrameFilteredListener(this.mm, "scroll", this, false);
+    this.stateChangeNotifier.addObserver(this);
+  }
 
   handleEvent() {
-    MessageQueue.push("scroll", () => this.collect());
-  },
+    this.messageQueue.push("scroll", () => this.collect());
+  }
 
   onPageLoadCompleted() {
-    MessageQueue.push("scroll", () => this.collect());
-  },
+    this.messageQueue.push("scroll", () => this.collect());
+  }
 
   onPageLoadStarted() {
-    MessageQueue.push("scroll", () => null);
-  },
+    this.messageQueue.push("scroll", () => null);
+  }
 
   collect() {
-    return mapFrameTree(ScrollPosition.collect);
+    return mapFrameTree(this.mm, ScrollPosition.collect);
   }
-};
+}
 
 /**
  * Listens for changes to input elements. Whenever the value of an input
  * element changes we will re-collect data for the current frame tree and send
  * a message to the parent process.
  *
  * Causes a SessionStore:update message to be sent that contains the form data
  * for all reachable frames.
@@ -493,314 +391,329 @@ var ScrollPositionListener = {
  *   {
  *     formdata: {url: "http://mozilla.org/", id: {input_id: "input value"}},
  *     children: [
  *       null,
  *       {url: "http://sub.mozilla.org/", id: {input_id: "input value 2"}}
  *     ]
  *   }
  */
-var FormDataListener = {
-  init() {
-    ssu.addDynamicFrameFilteredListener(global, "input", this, true);
-    StateChangeNotifier.addObserver(this);
-  },
+class FormDataListener extends Handler {
+  constructor(store) {
+    super(store);
+
+    ssu.addDynamicFrameFilteredListener(this.mm, "input", this, true);
+    this.stateChangeNotifier.addObserver(this);
+  }
 
   handleEvent() {
-    MessageQueue.push("formdata", () => this.collect());
-  },
+    this.messageQueue.push("formdata", () => this.collect());
+  }
 
   onPageLoadStarted() {
-    MessageQueue.push("formdata", () => null);
-  },
+    this.messageQueue.push("formdata", () => null);
+  }
 
   collect() {
-    return mapFrameTree(FormData.collect);
+    return mapFrameTree(this.mm, FormData.collect);
   }
-};
+}
 
 /**
  * Listens for changes to docShell capabilities. Whenever a new load is started
  * we need to re-check the list of capabilities and send message when it has
  * changed.
  *
  * Causes a SessionStore:update message to be sent that contains the currently
  * disabled docShell capabilities (all nsIDocShell.allow* properties set to
  * false) as a string - i.e. capability names separate by commas.
  */
-var DocShellCapabilitiesListener = {
-  /**
-   * This field is used to compare the last docShell capabilities to the ones
-   * that have just been collected. If nothing changed we won't send a message.
-   */
-  _latestCapabilities: "",
+class DocShellCapabilitiesListener extends Handler {
+  constructor(store) {
+    super(store);
 
-  init() {
-    StateChangeNotifier.addObserver(this);
-  },
+    /**
+     * This field is used to compare the last docShell capabilities to the ones
+     * that have just been collected. If nothing changed we won't send a message.
+     */
+    this._latestCapabilities = "";
+
+    this.stateChangeNotifier.addObserver(this);
+  }
 
   onPageLoadStarted() {
     // The order of docShell capabilities cannot change while we're running
     // so calling join() without sorting before is totally sufficient.
-    let caps = DocShellCapabilities.collect(docShell).join(",");
+    let caps = DocShellCapabilities.collect(this.mm.docShell).join(",");
 
     // Send new data only when the capability list changes.
     if (caps != this._latestCapabilities) {
       this._latestCapabilities = caps;
-      MessageQueue.push("disallow", () => caps || null);
+      this.messageQueue.push("disallow", () => caps || null);
     }
   }
-};
+}
 
 /**
  * Listens for changes to the DOMSessionStorage. Whenever new keys are added,
  * existing ones removed or changed, or the storage is cleared we will send a
  * message to the parent process containing up-to-date sessionStorage data.
  *
  * Causes a SessionStore:update message to be sent that contains the current
  * DOMSessionStorage contents. The data is a nested object using host names
  * as keys and per-host DOMSessionStorage data as values.
  */
-var SessionStorageListener = {
-  init() {
+class SessionStorageListener extends Handler {
+  constructor(store) {
+    super(store);
+
+    // We don't want to send all the session storage data for all the frames
+    // for every change. So if only a few value changed we send them over as
+    // a "storagechange" event. If however for some reason before we send these
+    // changes we have to send over the entire sessions storage data, we just
+    // reset these changes.
+    this._changes = undefined;
+
+    // The event listener waiting for MozSessionStorageChanged events.
+    this._listener = null;
+
     Services.obs.addObserver(this, "browser:purge-domain-data");
-    StateChangeNotifier.addObserver(this);
+    this.stateChangeNotifier.addObserver(this);
     this.resetEventListener();
-  },
+  }
 
   uninit() {
     Services.obs.removeObserver(this, "browser:purge-domain-data");
-  },
+  }
 
   observe() {
     // Collect data on the next tick so that any other observer
     // that needs to purge data can do its work first.
-    setTimeoutWithTarget(() => this.collect(), 0, tabEventTarget);
-  },
-
-  // We don't want to send all the session storage data for all the frames
-  // for every change. So if only a few value changed we send them over as
-  // a "storagechange" event. If however for some reason before we send these
-  // changes we have to send over the entire sessions storage data, we just
-  // reset these changes.
-  _changes: undefined,
+    setTimeoutWithTarget(() => this.collect(), 0, this.mm.tabEventTarget);
+  }
 
   resetChanges() {
     this._changes = undefined;
-  },
-
-  // The event listener waiting for MozSessionStorageChanged events.
-  _listener: null,
+  }
 
   resetEventListener() {
     if (!this._listener) {
       this._listener =
-        ssu.addDynamicFrameFilteredListener(global, "MozSessionStorageChanged",
+        ssu.addDynamicFrameFilteredListener(this.mm, "MozSessionStorageChanged",
                                             this, true);
     }
-  },
+  }
 
   removeEventListener() {
-    ssu.removeDynamicFrameFilteredListener(global, "MozSessionStorageChanged",
+    ssu.removeDynamicFrameFilteredListener(this.mm, "MozSessionStorageChanged",
                                            this._listener, true);
     this._listener = null;
-  },
+  }
 
   handleEvent(event) {
-    if (!docShell) {
+    if (!this.mm.docShell) {
       return;
     }
 
+    let {content} = this.mm;
+
     // How much data does DOMSessionStorage contain?
     let usage = content.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIDOMWindowUtils)
                        .getStorageUsage(event.storageArea);
 
     // Don't store any data if we exceed the limit. Wipe any data we previously
     // collected so that we don't confuse websites with partial state.
     if (usage > Services.prefs.getIntPref(DOM_STORAGE_LIMIT_PREF)) {
-      MessageQueue.push("storage", () => null);
+      this.messageQueue.push("storage", () => null);
       this.removeEventListener();
       this.resetChanges();
       return;
     }
 
     let {url, key, newValue} = event;
     let uri = Services.io.newURI(url);
     let domain = uri.prePath;
     if (!this._changes) {
       this._changes = {};
     }
     if (!this._changes[domain]) {
       this._changes[domain] = {};
     }
     this._changes[domain][key] = newValue;
 
-    MessageQueue.push("storagechange", () => {
+    this.messageQueue.push("storagechange", () => {
       let tmp = this._changes;
       // If there were multiple changes we send them merged.
       // First one will collect all the changes the rest of
       // these messages will be ignored.
       this.resetChanges();
       return tmp;
     });
-  },
+  }
 
   collect() {
-    if (!docShell) {
+    if (!this.mm.docShell) {
       return;
     }
 
+    let {content} = this.mm;
+
     // We need the entire session storage, let's reset the pending individual change
     // messages.
     this.resetChanges();
 
-    MessageQueue.push("storage", () => SessionStorage.collect(content));
-  },
+    this.messageQueue.push("storage", () => SessionStorage.collect(content));
+  }
 
   onPageLoadCompleted() {
     this.collect();
-  },
+  }
 
   onPageLoadStarted() {
     this.resetEventListener();
     this.collect();
   }
-};
+}
 
 /**
  * Listen for changes to the privacy status of the tab.
  * By definition, tabs start in non-private mode.
  *
  * Causes a SessionStore:update message to be sent for
  * field "isPrivate". This message contains
  *  |true| if the tab is now private
  *  |null| if the tab is now public - the field is therefore
  *  not saved.
  */
-var PrivacyListener = {
-  init() {
-    docShell.addWeakPrivacyTransitionObserver(this);
+class PrivacyListener extends Handler {
+  constructor(store) {
+    super(store);
+
+    this.mm.docShell.addWeakPrivacyTransitionObserver(this);
 
     // Check that value at startup as it might have
     // been set before the frame script was loaded.
-    if (docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing) {
-      MessageQueue.push("isPrivate", () => true);
+    if (this.mm.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing) {
+      this.messageQueue.push("isPrivate", () => true);
     }
-  },
+  }
 
   // Ci.nsIPrivacyTransitionObserver
   privateModeChanged(enabled) {
-    MessageQueue.push("isPrivate", () => enabled || null);
-  },
-
-  QueryInterface: ChromeUtils.generateQI([Ci.nsIPrivacyTransitionObserver,
-                                          Ci.nsISupportsWeakReference])
-};
+    this.messageQueue.push("isPrivate", () => enabled || null);
+  }
+}
+PrivacyListener.prototype.QueryInterface =
+  ChromeUtils.generateQI([Ci.nsIPrivacyTransitionObserver,
+                          Ci.nsISupportsWeakReference]);
 
 /**
  * A message queue that takes collected data and will take care of sending it
  * to the chrome process. It allows flushing using synchronous messages and
  * takes care of any race conditions that might occur because of that. Changes
  * will be batched if they're pushed in quick succession to avoid a message
  * flood.
  */
-var MessageQueue = {
-  /**
-   * A map (string -> lazy fn) holding lazy closures of all queued data
-   * collection routines. These functions will return data collected from the
-   * docShell.
-   */
-  _data: new Map(),
+class MessageQueue extends Handler {
+  constructor(store) {
+    super(store);
+
+    /**
+     * A map (string -> lazy fn) holding lazy closures of all queued data
+     * collection routines. These functions will return data collected from the
+     * docShell.
+     */
+    this._data = new Map();
 
-  /**
-   * The delay (in ms) used to delay sending changes after data has been
-   * invalidated.
-   */
-  BATCH_DELAY_MS: 1000,
+    /**
+     * The delay (in ms) used to delay sending changes after data has been
+     * invalidated.
+     */
+    this.BATCH_DELAY_MS = 1000;
 
-  /**
-   * The minimum idle period (in ms) we need for sending data to chrome process.
-   */
-  NEEDED_IDLE_PERIOD_MS: 5,
+    /**
+     * The minimum idle period (in ms) we need for sending data to chrome process.
+     */
+    this.NEEDED_IDLE_PERIOD_MS = 5;
+
+    /**
+     * Timeout for waiting an idle period to send data. We will set this from
+     * the pref "browser.sessionstore.interval".
+     */
+    this._timeoutWaitIdlePeriodMs = null;
 
-  /**
-   * Timeout for waiting an idle period to send data. We will set this from
-   * the pref "browser.sessionstore.interval".
-   */
-  _timeoutWaitIdlePeriodMs: null,
+    /**
+     * The current timeout ID, null if there is no queue data. We use timeouts
+     * to damp a flood of data changes and send lots of changes as one batch.
+     */
+    this._timeout = null;
 
-  /**
-   * The current timeout ID, null if there is no queue data. We use timeouts
-   * to damp a flood of data changes and send lots of changes as one batch.
-   */
-  _timeout: null,
+    /**
+     * Whether or not sending batched messages on a timer is disabled. This should
+     * only be used for debugging or testing. If you need to access this value,
+     * you should probably use the timeoutDisabled getter.
+     */
+    this._timeoutDisabled = false;
 
-  /**
-   * Whether or not sending batched messages on a timer is disabled. This should
-   * only be used for debugging or testing. If you need to access this value,
-   * you should probably use the timeoutDisabled getter.
-   */
-  _timeoutDisabled: false,
+    /**
+     * True if there is already a send pending idle dispatch, set to prevent
+     * scheduling more than one. If false there may or may not be one scheduled.
+     */
+    this._idleScheduled = false;
+
 
-  /**
-   * True if there is already a send pending idle dispatch, set to prevent
-   * scheduling more than one. If false there may or may not be one scheduled.
-   */
-  _idleScheduled: false,
+    this.timeoutDisabled =
+      Services.prefs.getBoolPref(TIMEOUT_DISABLED_PREF);
+    this._timeoutWaitIdlePeriodMs =
+      Services.prefs.getIntPref(PREF_INTERVAL);
+
+    Services.prefs.addObserver(TIMEOUT_DISABLED_PREF, this);
+    Services.prefs.addObserver(PREF_INTERVAL, this);
+  }
 
   /**
    * True if batched messages are not being fired on a timer. This should only
    * ever be true when debugging or during tests.
    */
   get timeoutDisabled() {
     return this._timeoutDisabled;
-  },
+  }
 
   /**
    * Disables sending batched messages on a timer. Also cancels any pending
    * timers.
    */
   set timeoutDisabled(val) {
     this._timeoutDisabled = val;
 
     if (val && this._timeout) {
       clearTimeout(this._timeout);
       this._timeout = null;
     }
 
     return val;
-  },
-
-  init() {
-    this.timeoutDisabled =
-      Services.prefs.getBoolPref(TIMEOUT_DISABLED_PREF);
-    this._timeoutWaitIdlePeriodMs =
-      Services.prefs.getIntPref(PREF_INTERVAL);
-
-    Services.prefs.addObserver(TIMEOUT_DISABLED_PREF, this);
-    Services.prefs.addObserver(PREF_INTERVAL, this);
-  },
+  }
 
   uninit() {
     Services.prefs.removeObserver(TIMEOUT_DISABLED_PREF, this);
     Services.prefs.removeObserver(PREF_INTERVAL, this);
     this.cleanupTimers();
-  },
+  }
 
   /**
    * Cleanup pending idle callback and timer.
    */
   cleanupTimers() {
     this._idleScheduled = false;
     if (this._timeout) {
       clearTimeout(this._timeout);
       this._timeout = null;
     }
-  },
+  }
 
   observe(subject, topic, data) {
     if (topic == "nsPref:changed") {
       switch (data) {
         case TIMEOUT_DISABLED_PREF:
           this.timeoutDisabled =
             Services.prefs.getBoolPref(TIMEOUT_DISABLED_PREF);
           break;
@@ -808,17 +721,17 @@ var MessageQueue = {
           this._timeoutWaitIdlePeriodMs =
             Services.prefs.getIntPref(PREF_INTERVAL);
           break;
         default:
           debug("received unknown message '" + data + "'");
           break;
       }
     }
-  },
+  }
 
   /**
    * Pushes a given |value| onto the queue. The given |key| represents the type
    * of data that is stored and can override data that has been queued before
    * but has not been sent to the parent process, yet.
    *
    * @param key (string)
    *        A unique identifier specific to the type of data this is passed.
@@ -827,59 +740,60 @@ var MessageQueue = {
    *        process.
    */
   push(key, fn) {
     this._data.set(key, fn);
 
     if (!this._timeout && !this._timeoutDisabled) {
       // Wait a little before sending the message to batch multiple changes.
       this._timeout = setTimeoutWithTarget(
-        () => this.sendWhenIdle(), this.BATCH_DELAY_MS, tabEventTarget);
+        () => this.sendWhenIdle(), this.BATCH_DELAY_MS, this.mm.tabEventTarget);
     }
-  },
+  }
 
   /**
    * Sends queued data when the remaining idle time is enough or waiting too
    * long; otherwise, request an idle time again. If the |deadline| is not
    * given, this function is going to schedule the first request.
    *
    * @param deadline (object)
    *        An IdleDeadline object passed by idleDispatch().
    */
   sendWhenIdle(deadline) {
-    if (!content) {
+    if (!this.mm.content) {
       // The frameloader is being torn down. Nothing more to do.
       return;
     }
 
     if (deadline) {
-      if (deadline.didTimeout || deadline.timeRemaining() > MessageQueue.NEEDED_IDLE_PERIOD_MS) {
-        MessageQueue.send();
+      if (deadline.didTimeout || deadline.timeRemaining() > this.NEEDED_IDLE_PERIOD_MS) {
+        this.send();
         return;
       }
-    } else if (MessageQueue._idleScheduled) {
+    } else if (this._idleScheduled) {
       // Bail out if there's a pending run.
       return;
     }
-    ChromeUtils.idleDispatch(MessageQueue.sendWhenIdle, {timeout: MessageQueue._timeoutWaitIdlePeriodMs});
-    MessageQueue._idleScheduled = true;
-  },
+    ChromeUtils.idleDispatch((deadline_) => this.sendWhenIdle(deadline_),
+                             {timeout: this._timeoutWaitIdlePeriodMs});
+    this._idleScheduled = true;
+  }
 
   /**
    * Sends queued data to the chrome process.
    *
    * @param options (object)
    *        {flushID: 123} to specify that this is a flush
    *        {isFinal: true} to signal this is the final message sent on unload
    */
   send(options = {}) {
     // Looks like we have been called off a timeout after the tab has been
     // closed. The docShell is gone now and we can just return here as there
     // is nothing to do.
-    if (!docShell) {
+    if (!this.mm.docShell) {
       return;
     }
 
     this.cleanupTimers();
 
     let flushID = (options && options.flushID) || 0;
     let histID = "FX_SESSION_RESTORE_CONTENT_COLLECT_DATA_MS";
 
@@ -899,83 +813,231 @@ var MessageQueue = {
         data[key] = value;
       }
     }
 
     this._data.clear();
 
     try {
       // Send all data to the parent process.
-      sendAsyncMessage("SessionStore:update", {
+      this.mm.sendAsyncMessage("SessionStore:update", {
         data, flushID,
         isFinal: options.isFinal || false,
-        epoch: gCurrentEpoch
+        epoch: this.store.epoch,
       });
     } catch (ex) {
       if (ex && ex.result == Cr.NS_ERROR_OUT_OF_MEMORY) {
         Services.telemetry.getHistogramById("FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM").add(1);
-        sendAsyncMessage("SessionStore:error");
+        this.mm.sendAsyncMessage("SessionStore:error");
       }
     }
-  },
-};
-
-StateChangeNotifier.init();
-EventListener.init();
-MessageListener.init();
-FormDataListener.init();
-SessionHistoryListener.init();
-SessionStorageListener.init();
-ScrollPositionListener.init();
-DocShellCapabilitiesListener.init();
-PrivacyListener.init();
-MessageQueue.init();
-
-function handleRevivedTab() {
-  if (!content) {
-    removeEventListener("pagehide", handleRevivedTab);
-    return;
-  }
-
-  if (content.document.documentURI.startsWith("about:tabcrashed")) {
-    if (Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_DEFAULT) {
-      // Sanity check - we'd better be loading this in a non-remote browser.
-      throw new Error("We seem to be navigating away from about:tabcrashed in " +
-                      "a non-remote browser. This should really never happen.");
-    }
-
-    removeEventListener("pagehide", handleRevivedTab);
-
-    // Notify the parent.
-    sendAsyncMessage("SessionStore:crashedTabRevived");
   }
 }
 
-// If we're browsing from the tab crashed UI to a blacklisted URI that keeps
-// this browser non-remote, we'll handle that in a pagehide event.
-addEventListener("pagehide", handleRevivedTab);
+/**
+ * Listens for and handles messages sent by the session store service.
+ */
+const MESSAGES = [
+  "SessionStore:restoreHistory",
+  "SessionStore:restoreTabContent",
+  "SessionStore:resetRestore",
+  "SessionStore:flush",
+  "SessionStore:becomeActiveProcess",
+];
+
+class ContentSessionStore {
+  constructor(mm) {
+    this.mm = mm;
+    this.messageQueue = new MessageQueue(this);
+    this.stateChangeNotifier = new StateChangeNotifier(this);
+
+    this.epoch = 0;
 
-addEventListener("unload", () => {
-  // Upon frameLoader destruction, send a final update message to
-  // the parent and flush all data currently held in the child.
-  MessageQueue.send({isFinal: true});
+    this.contentRestoreInitialized = false;
+
+    XPCOMUtils.defineLazyGetter(this, "contentRestore",
+                                () => {
+                                  this.contentRestoreInitialized = true;
+                                  return new ContentRestore(mm);
+                                });
+
+    this.handlers = [
+      new EventListener(this),
+      new FormDataListener(this),
+      new SessionHistoryListener(this),
+      new SessionStorageListener(this),
+      new ScrollPositionListener(this),
+      new DocShellCapabilitiesListener(this),
+      new PrivacyListener(this),
+      this.stateChangeNotifier,
+      this.messageQueue,
+    ];
+
+    MESSAGES.forEach(m => mm.addMessageListener(m, this));
 
-  // If we're browsing from the tab crashed UI to a URI that causes the tab
-  // to go remote again, we catch this in the unload event handler, because
-  // swapping out the non-remote browser for a remote one in
-  // tabbrowser.xml's updateBrowserRemoteness doesn't cause the pagehide
-  // event to be fired.
-  handleRevivedTab();
+    // If we're browsing from the tab crashed UI to a blacklisted URI that keeps
+    // this browser non-remote, we'll handle that in a pagehide event.
+    mm.addEventListener("pagehide", this);
+    mm.addEventListener("unload", this);
+  }
+
+  receiveMessage({name, data}) {
+    // The docShell might be gone. Don't process messages,
+    // that will just lead to errors anyway.
+    if (!this.mm.docShell) {
+      return;
+    }
+
+    // A fresh tab always starts with epoch=0. The parent has the ability to
+    // override that to signal a new era in this tab's life. This enables it
+    // to ignore async messages that were already sent but not yet received
+    // and would otherwise confuse the internal tab state.
+    if (data.epoch && data.epoch != this.epoch) {
+      this.epoch = data.epoch;
+    }
 
-  // Remove all registered nsIObservers.
-  SessionStorageListener.uninit();
-  SessionHistoryListener.uninit();
-  MessageQueue.uninit();
-
-  if (contentRestoreInitialized) {
-    // Remove progress listeners.
-    gContentRestore.resetRestore();
+    switch (name) {
+      case "SessionStore:restoreHistory":
+        this.restoreHistory(data);
+        break;
+      case "SessionStore:restoreTabContent":
+        if (data.isRemotenessUpdate) {
+          let histogram = Services.telemetry.getKeyedHistogramById("FX_TAB_REMOTE_NAVIGATION_DELAY_MS");
+          histogram.add("SessionStore:restoreTabContent",
+                        Services.telemetry.msSystemNow() - data.requestTime);
+        }
+        this.restoreTabContent(data);
+        break;
+      case "SessionStore:resetRestore":
+        this.contentRestore.resetRestore();
+        break;
+      case "SessionStore:flush":
+        this.flush(data);
+        break;
+      case "SessionStore:becomeActiveProcess":
+        SessionHistoryListener.collect();
+        break;
+      default:
+        debug("received unknown message '" + name + "'");
+        break;
+    }
   }
 
-  // We don't need to take care of any StateChangeNotifier observers as they
-  // will die with the content script. The same goes for the privacy transition
-  // observer that will die with the docShell when the tab is closed.
-});
+  restoreHistory({epoch, tabData, loadArguments, isRemotenessUpdate}) {
+    this.contentRestore.restoreHistory(tabData, loadArguments, {
+      // Note: The callbacks passed here will only be used when a load starts
+      // that was not initiated by sessionstore itself. This can happen when
+      // some code calls browser.loadURI() or browser.reload() on a pending
+      // browser/tab.
+
+      onLoadStarted: () => {
+        // Notify the parent that the tab is no longer pending.
+        this.mm.sendAsyncMessage("SessionStore:restoreTabContentStarted", {epoch});
+      },
+
+      onLoadFinished: () => {
+        // Tell SessionStore.jsm that it may want to restore some more tabs,
+        // since it restores a max of MAX_CONCURRENT_TAB_RESTORES at a time.
+        this.mm.sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch});
+      }
+    });
+
+    if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_DEFAULT) {
+      // For non-remote tabs, when restoreHistory finishes, we send a synchronous
+      // message to SessionStore.jsm so that it can run SSTabRestoring. Users of
+      // SSTabRestoring seem to get confused if chrome and content are out of
+      // sync about the state of the restore (particularly regarding
+      // docShell.currentURI). Using a synchronous message is the easiest way
+      // to temporarily synchronize them.
+      //
+      // For remote tabs, because all nsIWebProgress notifications are sent
+      // asynchronously using messages, we get the same-order guarantees of the
+      // message manager, and can use an async message.
+      this.mm.sendSyncMessage("SessionStore:restoreHistoryComplete", {epoch, isRemotenessUpdate});
+    } else {
+      this.mm.sendAsyncMessage("SessionStore:restoreHistoryComplete", {epoch, isRemotenessUpdate});
+    }
+  }
+
+  restoreTabContent({loadArguments, isRemotenessUpdate, reason}) {
+    let epoch = this.epoch;
+
+    // We need to pass the value of didStartLoad back to SessionStore.jsm.
+    let didStartLoad = this.contentRestore.restoreTabContent(loadArguments, isRemotenessUpdate, () => {
+      // Tell SessionStore.jsm that it may want to restore some more tabs,
+      // since it restores a max of MAX_CONCURRENT_TAB_RESTORES at a time.
+      this.mm.sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
+    });
+
+    this.mm.sendAsyncMessage("SessionStore:restoreTabContentStarted", {
+      epoch, isRemotenessUpdate, reason,
+    });
+
+    if (!didStartLoad) {
+      // Pretend that the load succeeded so that event handlers fire correctly.
+      this.mm.sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
+    }
+  }
+
+  flush({id}) {
+    // Flush the message queue, send the latest updates.
+    this.messageQueue.send({flushID: id});
+  }
+
+  handleEvent(event) {
+    if (event.type == "pagehide") {
+      this.handleRevivedTab();
+    } else if (event.type == "unload") {
+      this.onUnload();
+    }
+  }
+
+  onUnload() {
+    // Upon frameLoader destruction, send a final update message to
+    // the parent and flush all data currently held in the child.
+    this.messageQueue.send({isFinal: true});
+
+    // If we're browsing from the tab crashed UI to a URI that causes the tab
+    // to go remote again, we catch this in the unload event handler, because
+    // swapping out the non-remote browser for a remote one in
+    // tabbrowser.xml's updateBrowserRemoteness doesn't cause the pagehide
+    // event to be fired.
+    this.handleRevivedTab();
+
+    for (let handler of this.handlers) {
+      if (handler.uninit) {
+        handler.uninit();
+      }
+    }
+
+    if (this.contentRestoreInitialized) {
+      // Remove progress listeners.
+      this.contentRestore.resetRestore();
+    }
+
+    // We don't need to take care of any StateChangeNotifier observers as they
+    // will die with the content script. The same goes for the privacy transition
+    // observer that will die with the docShell when the tab is closed.
+  }
+
+  handleRevivedTab() {
+    let {content} = this.mm;
+
+    if (!content) {
+      this.mm.removeEventListener("pagehide", this);
+      return;
+    }
+
+    if (content.document.documentURI.startsWith("about:tabcrashed")) {
+      if (Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_DEFAULT) {
+        // Sanity check - we'd better be loading this in a non-remote browser.
+        throw new Error("We seem to be navigating away from about:tabcrashed in " +
+                        "a non-remote browser. This should really never happen.");
+      }
+
+      this.mm.removeEventListener("pagehide", this);
+
+      // Notify the parent.
+      this.mm.sendAsyncMessage("SessionStore:crashedTabRevived");
+    }
+  }
+}
+
--- a/browser/components/sessionstore/content/content-sessionStore.js
+++ b/browser/components/sessionstore/content/content-sessionStore.js
@@ -1,981 +1,11 @@
 /* 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/. */
 
 /* eslint-env mozilla/frame-script */
 
 "use strict";
 
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
-ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
-ChromeUtils.import("resource://gre/modules/Services.jsm", this);
-
-ChromeUtils.defineModuleGetter(this, "TelemetryStopwatch",
-  "resource://gre/modules/TelemetryStopwatch.jsm");
-
-function debug(msg) {
-  Services.console.logStringMessage("SessionStoreContent: " + msg);
-}
-
-ChromeUtils.defineModuleGetter(this, "FormData",
-  "resource://gre/modules/FormData.jsm");
-
-ChromeUtils.defineModuleGetter(this, "ContentRestore",
-  "resource:///modules/sessionstore/ContentRestore.jsm");
-ChromeUtils.defineModuleGetter(this, "DocShellCapabilities",
-  "resource:///modules/sessionstore/DocShellCapabilities.jsm");
-ChromeUtils.defineModuleGetter(this, "ScrollPosition",
-  "resource://gre/modules/ScrollPosition.jsm");
-ChromeUtils.defineModuleGetter(this, "SessionHistory",
-  "resource://gre/modules/sessionstore/SessionHistory.jsm");
-ChromeUtils.defineModuleGetter(this, "SessionStorage",
-  "resource:///modules/sessionstore/SessionStorage.jsm");
-
-var contentRestoreInitialized = false;
-
-XPCOMUtils.defineLazyGetter(this, "gContentRestore",
-                            () => {
-                              contentRestoreInitialized = true;
-                              return new ContentRestore(this);
-                            });
-
-ChromeUtils.defineModuleGetter(this, "Utils",
-  "resource://gre/modules/sessionstore/Utils.jsm");
-const ssu = Cc["@mozilla.org/browser/sessionstore/utils;1"]
-              .getService(Ci.nsISessionStoreUtils);
-
-// The current epoch.
-var gCurrentEpoch = 0;
-
-// A bound to the size of data to store for DOM Storage.
-const DOM_STORAGE_LIMIT_PREF = "browser.sessionstore.dom_storage_limit";
-
-// This pref controls whether or not we send updates to the parent on a timeout
-// or not, and should only be used for tests or debugging.
-const TIMEOUT_DISABLED_PREF = "browser.sessionstore.debug.no_auto_updates";
-
-const PREF_INTERVAL = "browser.sessionstore.interval";
-
-const kNoIndex = Number.MAX_SAFE_INTEGER;
-const kLastIndex = Number.MAX_SAFE_INTEGER - 1;
-
-// Grab our global so we can access it in functions below.
-const global = this;
-
-/**
- * A function that will recursively call |cb| to collect data for all
- * non-dynamic frames in the current frame/docShell tree.
- */
-function mapFrameTree(callback) {
-  let [data] = Utils.mapFrameTree(content, callback);
-  return data;
-}
-
-/**
- * Listens for state change notifcations from webProgress and notifies each
- * registered observer for either the start of a page load, or its completion.
- */
-var StateChangeNotifier = {
-
-  init() {
-    this._observers = new Set();
-    let ifreq = docShell.QueryInterface(Ci.nsIInterfaceRequestor);
-    let webProgress = ifreq.getInterface(Ci.nsIWebProgress);
-    webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
-  },
-
-  /**
-   * Adds a given observer |obs| to the set of observers that will be notified
-   * when when a new document starts or finishes loading.
-   *
-   * @param obs (object)
-   */
-  addObserver(obs) {
-    this._observers.add(obs);
-  },
-
-  /**
-   * Notifies all observers that implement the given |method|.
-   *
-   * @param method (string)
-   */
-  notifyObservers(method) {
-    for (let obs of this._observers) {
-      if (obs.hasOwnProperty(method)) {
-        obs[method]();
-      }
-    }
-  },
-
-  /**
-   * @see nsIWebProgressListener.onStateChange
-   */
-  onStateChange(webProgress, request, stateFlags, status) {
-    // Ignore state changes for subframes because we're only interested in the
-    // top-document starting or stopping its load.
-    if (!webProgress.isTopLevel || webProgress.DOMWindow != content) {
-      return;
-    }
-
-    // onStateChange will be fired when loading the initial about:blank URI for
-    // a browser, which we don't actually care about. This is particularly for
-    // the case of unrestored background tabs, where the content has not yet
-    // been restored: we don't want to accidentally send any updates to the
-    // parent when the about:blank placeholder page has loaded.
-    if (!docShell.hasLoadedNonBlankURI) {
-      return;
-    }
-
-    if (stateFlags & Ci.nsIWebProgressListener.STATE_START) {
-      this.notifyObservers("onPageLoadStarted");
-    } else if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
-      this.notifyObservers("onPageLoadCompleted");
-    }
-  },
-
-  QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener,
-                                          Ci.nsISupportsWeakReference])
-};
-
-/**
- * Listens for and handles content events that we need for the
- * session store service to be notified of state changes in content.
- */
-var EventListener = {
-
-  init() {
-    ssu.addDynamicFrameFilteredListener(global, "load", this, true);
-  },
-
-  handleEvent(event) {
-    // Ignore load events from subframes.
-    if (event.target != content.document) {
-      return;
-    }
-
-    if (content.document.documentURI.startsWith("about:reader")) {
-      if (event.type == "load" &&
-          !content.document.body.classList.contains("loaded")) {
-        // Don't restore the scroll position of an about:reader page at this
-        // point; listen for the custom event dispatched from AboutReader.jsm.
-        content.addEventListener("AboutReaderContentReady", this);
-        return;
-      }
-
-      content.removeEventListener("AboutReaderContentReady", this);
-    }
-
-    if (contentRestoreInitialized) {
-      // Restore the form data and scroll position. If we're not currently
-      // restoring a tab state then this call will simply be a noop.
-      gContentRestore.restoreDocument();
-    }
-  }
-};
-
-/**
- * Listens for and handles messages sent by the session store service.
- */
-var MessageListener = {
-
-  MESSAGES: [
-    "SessionStore:restoreHistory",
-    "SessionStore:restoreTabContent",
-    "SessionStore:resetRestore",
-    "SessionStore:flush",
-    "SessionStore:becomeActiveProcess",
-  ],
-
-  init() {
-    this.MESSAGES.forEach(m => addMessageListener(m, this));
-  },
-
-  receiveMessage({name, data}) {
-    // The docShell might be gone. Don't process messages,
-    // that will just lead to errors anyway.
-    if (!docShell) {
-      return;
-    }
-
-    // A fresh tab always starts with epoch=0. The parent has the ability to
-    // override that to signal a new era in this tab's life. This enables it
-    // to ignore async messages that were already sent but not yet received
-    // and would otherwise confuse the internal tab state.
-    if (data.epoch && data.epoch != gCurrentEpoch) {
-      gCurrentEpoch = data.epoch;
-    }
-
-    switch (name) {
-      case "SessionStore:restoreHistory":
-        this.restoreHistory(data);
-        break;
-      case "SessionStore:restoreTabContent":
-        if (data.isRemotenessUpdate) {
-          let histogram = Services.telemetry.getKeyedHistogramById("FX_TAB_REMOTE_NAVIGATION_DELAY_MS");
-          histogram.add("SessionStore:restoreTabContent",
-                        Services.telemetry.msSystemNow() - data.requestTime);
-        }
-        this.restoreTabContent(data);
-        break;
-      case "SessionStore:resetRestore":
-        gContentRestore.resetRestore();
-        break;
-      case "SessionStore:flush":
-        this.flush(data);
-        break;
-      case "SessionStore:becomeActiveProcess":
-        SessionHistoryListener.collect();
-        break;
-      default:
-        debug("received unknown message '" + name + "'");
-        break;
-    }
-  },
-
-  restoreHistory({epoch, tabData, loadArguments, isRemotenessUpdate}) {
-    gContentRestore.restoreHistory(tabData, loadArguments, {
-      // Note: The callbacks passed here will only be used when a load starts
-      // that was not initiated by sessionstore itself. This can happen when
-      // some code calls browser.loadURI() or browser.reload() on a pending
-      // browser/tab.
-
-      onLoadStarted() {
-        // Notify the parent that the tab is no longer pending.
-        sendAsyncMessage("SessionStore:restoreTabContentStarted", {epoch});
-      },
-
-      onLoadFinished() {
-        // Tell SessionStore.jsm that it may want to restore some more tabs,
-        // since it restores a max of MAX_CONCURRENT_TAB_RESTORES at a time.
-        sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch});
-      }
-    });
-
-    if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_DEFAULT) {
-      // For non-remote tabs, when restoreHistory finishes, we send a synchronous
-      // message to SessionStore.jsm so that it can run SSTabRestoring. Users of
-      // SSTabRestoring seem to get confused if chrome and content are out of
-      // sync about the state of the restore (particularly regarding
-      // docShell.currentURI). Using a synchronous message is the easiest way
-      // to temporarily synchronize them.
-      //
-      // For remote tabs, because all nsIWebProgress notifications are sent
-      // asynchronously using messages, we get the same-order guarantees of the
-      // message manager, and can use an async message.
-      sendSyncMessage("SessionStore:restoreHistoryComplete", {epoch, isRemotenessUpdate});
-    } else {
-      sendAsyncMessage("SessionStore:restoreHistoryComplete", {epoch, isRemotenessUpdate});
-    }
-  },
-
-  restoreTabContent({loadArguments, isRemotenessUpdate, reason}) {
-    let epoch = gCurrentEpoch;
-
-    // We need to pass the value of didStartLoad back to SessionStore.jsm.
-    let didStartLoad = gContentRestore.restoreTabContent(loadArguments, isRemotenessUpdate, () => {
-      // Tell SessionStore.jsm that it may want to restore some more tabs,
-      // since it restores a max of MAX_CONCURRENT_TAB_RESTORES at a time.
-      sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
-    });
-
-    sendAsyncMessage("SessionStore:restoreTabContentStarted", {
-      epoch, isRemotenessUpdate, reason,
-    });
-
-    if (!didStartLoad) {
-      // Pretend that the load succeeded so that event handlers fire correctly.
-      sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
-    }
-  },
-
-  flush({id}) {
-    // Flush the message queue, send the latest updates.
-    MessageQueue.send({flushID: id});
-  }
-};
-
-/**
- * Listens for changes to the session history. Whenever the user navigates
- * we will collect URLs and everything belonging to session history.
- *
- * Causes a SessionStore:update message to be sent that contains the current
- * session history.
- *
- * Example:
- *   {entries: [{url: "about:mozilla", ...}, ...], index: 1}
- */
-var SessionHistoryListener = {
-  init() {
-    // The state change observer is needed to handle initial subframe loads.
-    // It will redundantly invalidate with the SHistoryListener in some cases
-    // but these invalidations are very cheap.
-    StateChangeNotifier.addObserver(this);
-
-    // By adding the SHistoryListener immediately, we will unfortunately be
-    // notified of every history entry as the tab is restored. We don't bother
-    // waiting to add the listener later because these notifications are cheap.
-    // We will likely only collect once since we are batching collection on
-    // a delay.
-    docShell.QueryInterface(Ci.nsIWebNavigation).
-      sessionHistory.legacySHistory.addSHistoryListener(this);
-
-    // Collect data if we start with a non-empty shistory.
-    if (!SessionHistory.isEmpty(docShell)) {
-      this.collect();
-      // When a tab is detached from the window, for the new window there is a
-      // new SessionHistoryListener created. Normally it is empty at this point
-      // but in a test env. the initial about:blank might have a children in which
-      // case we fire off a history message here with about:blank in it. If we
-      // don't do it ASAP then there is going to be a browser swap and the parent
-      // will be all confused by that message.
-      MessageQueue.send();
-    }
-
-    // Listen for page title changes.
-    addEventListener("DOMTitleChanged", this);
-  },
-
-  uninit() {
-    let sessionHistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
-    if (sessionHistory) {
-      sessionHistory.legacySHistory.removeSHistoryListener(this);
-    }
-  },
-
-  collect() {
-    // We want to send down a historychange even for full collects in case our
-    // session history is a partial session history, in which case we don't have
-    // enough information for a full update. collectFrom(-1) tells the collect
-    // function to collect all data avaliable in this process.
-    if (docShell) {
-      this.collectFrom(-1);
-    }
-  },
-
-  _fromIdx: kNoIndex,
-
-  // History can grow relatively big with the nested elements, so if we don't have to, we
-  // don't want to send the entire history all the time. For a simple optimization
-  // we keep track of the smallest index from after any change has occured and we just send
-  // the elements from that index. If something more complicated happens we just clear it
-  // and send the entire history. We always send the additional info like the current selected
-  // index (so for going back and forth between history entries we set the index to kLastIndex
-  // if nothing else changed send an empty array and the additonal info like the selected index)
-  collectFrom(idx) {
-    if (this._fromIdx <= idx) {
-      // If we already know that we need to update history fromn index N we can ignore any changes
-      // tha happened with an element with index larger than N.
-      // Note: initially we use kNoIndex which is MAX_SAFE_INTEGER which means we don't ignore anything
-      // here, and in case of navigation in the history back and forth we use kLastIndex which ignores
-      // only the subsequent navigations, but not any new elements added.
-      return;
-    }
-
-    this._fromIdx = idx;
-    MessageQueue.push("historychange", () => {
-      if (this._fromIdx === kNoIndex) {
-        return null;
-      }
-
-      let history = SessionHistory.collect(docShell, this._fromIdx);
-      this._fromIdx = kNoIndex;
-      return history;
-    });
-  },
-
-  handleEvent(event) {
-    this.collect();
-  },
-
-  onPageLoadCompleted() {
-    this.collect();
-  },
-
-  onPageLoadStarted() {
-    this.collect();
-  },
-
-  OnHistoryNewEntry(newURI, oldIndex) {
-    // We ought to collect the previously current entry as well, see bug 1350567.
-    this.collectFrom(oldIndex);
-  },
-
-  OnHistoryGoBack(backURI) {
-    // We ought to collect the previously current entry as well, see bug 1350567.
-    this.collectFrom(kLastIndex);
-    return true;
-  },
-
-  OnHistoryGoForward(forwardURI) {
-    // We ought to collect the previously current entry as well, see bug 1350567.
-    this.collectFrom(kLastIndex);
-    return true;
-  },
-
-  OnHistoryGotoIndex(index, gotoURI) {
-    // We ought to collect the previously current entry as well, see bug 1350567.
-    this.collectFrom(kLastIndex);
-    return true;
-  },
-
-  OnHistoryPurge(numEntries) {
-    this.collect();
-    return true;
-  },
-
-  OnHistoryReload(reloadURI, reloadFlags) {
-    this.collect();
-    return true;
-  },
-
-  OnHistoryReplaceEntry(index) {
-    this.collect();
-  },
-
-  OnLengthChanged(aCount) {
-    // Ignore, the method is implemented so that XPConnect doesn't throw!
-  },
-
-  OnIndexChanged(aIndex) {
-    // Ignore, the method is implemented so that XPConnect doesn't throw!
-  },
-
-  QueryInterface: ChromeUtils.generateQI([
-    Ci.nsISHistoryListener,
-    Ci.nsISupportsWeakReference
-  ])
-};
-
-/**
- * Listens for scroll position changes. Whenever the user scrolls the top-most
- * frame we update the scroll position and will restore it when requested.
- *
- * Causes a SessionStore:update message to be sent that contains the current
- * scroll positions as a tree of strings. If no frame of the whole frame tree
- * is scrolled this will return null so that we don't tack a property onto
- * the tabData object in the parent process.
- *
- * Example:
- *   {scroll: "100,100", children: [null, null, {scroll: "200,200"}]}
- */
-var ScrollPositionListener = {
-  init() {
-    ssu.addDynamicFrameFilteredListener(global, "scroll", this, false);
-    StateChangeNotifier.addObserver(this);
-  },
-
-  handleEvent() {
-    MessageQueue.push("scroll", () => this.collect());
-  },
-
-  onPageLoadCompleted() {
-    MessageQueue.push("scroll", () => this.collect());
-  },
-
-  onPageLoadStarted() {
-    MessageQueue.push("scroll", () => null);
-  },
-
-  collect() {
-    return mapFrameTree(ScrollPosition.collect);
-  }
-};
+ChromeUtils.import("resource:///modules/sessionstore/ContentSessionStore.jsm");
 
-/**
- * Listens for changes to input elements. Whenever the value of an input
- * element changes we will re-collect data for the current frame tree and send
- * a message to the parent process.
- *
- * Causes a SessionStore:update message to be sent that contains the form data
- * for all reachable frames.
- *
- * Example:
- *   {
- *     formdata: {url: "http://mozilla.org/", id: {input_id: "input value"}},
- *     children: [
- *       null,
- *       {url: "http://sub.mozilla.org/", id: {input_id: "input value 2"}}
- *     ]
- *   }
- */
-var FormDataListener = {
-  init() {
-    ssu.addDynamicFrameFilteredListener(global, "input", this, true);
-    StateChangeNotifier.addObserver(this);
-  },
-
-  handleEvent() {
-    MessageQueue.push("formdata", () => this.collect());
-  },
-
-  onPageLoadStarted() {
-    MessageQueue.push("formdata", () => null);
-  },
-
-  collect() {
-    return mapFrameTree(FormData.collect);
-  }
-};
-
-/**
- * Listens for changes to docShell capabilities. Whenever a new load is started
- * we need to re-check the list of capabilities and send message when it has
- * changed.
- *
- * Causes a SessionStore:update message to be sent that contains the currently
- * disabled docShell capabilities (all nsIDocShell.allow* properties set to
- * false) as a string - i.e. capability names separate by commas.
- */
-var DocShellCapabilitiesListener = {
-  /**
-   * This field is used to compare the last docShell capabilities to the ones
-   * that have just been collected. If nothing changed we won't send a message.
-   */
-  _latestCapabilities: "",
-
-  init() {
-    StateChangeNotifier.addObserver(this);
-  },
-
-  onPageLoadStarted() {
-    // The order of docShell capabilities cannot change while we're running
-    // so calling join() without sorting before is totally sufficient.
-    let caps = DocShellCapabilities.collect(docShell).join(",");
-
-    // Send new data only when the capability list changes.
-    if (caps != this._latestCapabilities) {
-      this._latestCapabilities = caps;
-      MessageQueue.push("disallow", () => caps || null);
-    }
-  }
-};
-
-/**
- * Listens for changes to the DOMSessionStorage. Whenever new keys are added,
- * existing ones removed or changed, or the storage is cleared we will send a
- * message to the parent process containing up-to-date sessionStorage data.
- *
- * Causes a SessionStore:update message to be sent that contains the current
- * DOMSessionStorage contents. The data is a nested object using host names
- * as keys and per-host DOMSessionStorage data as values.
- */
-var SessionStorageListener = {
-  init() {
-    Services.obs.addObserver(this, "browser:purge-domain-data");
-    StateChangeNotifier.addObserver(this);
-    this.resetEventListener();
-  },
-
-  uninit() {
-    Services.obs.removeObserver(this, "browser:purge-domain-data");
-  },
-
-  observe() {
-    // Collect data on the next tick so that any other observer
-    // that needs to purge data can do its work first.
-    setTimeoutWithTarget(() => this.collect(), 0, tabEventTarget);
-  },
-
-  // We don't want to send all the session storage data for all the frames
-  // for every change. So if only a few value changed we send them over as
-  // a "storagechange" event. If however for some reason before we send these
-  // changes we have to send over the entire sessions storage data, we just
-  // reset these changes.
-  _changes: undefined,
-
-  resetChanges() {
-    this._changes = undefined;
-  },
-
-  // The event listener waiting for MozSessionStorageChanged events.
-  _listener: null,
-
-  resetEventListener() {
-    if (!this._listener) {
-      this._listener =
-        ssu.addDynamicFrameFilteredListener(global, "MozSessionStorageChanged",
-                                            this, true);
-    }
-  },
-
-  removeEventListener() {
-    ssu.removeDynamicFrameFilteredListener(global, "MozSessionStorageChanged",
-                                           this._listener, true);
-    this._listener = null;
-  },
-
-  handleEvent(event) {
-    if (!docShell) {
-      return;
-    }
-
-    // How much data does DOMSessionStorage contain?
-    let usage = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindowUtils)
-                       .getStorageUsage(event.storageArea);
-
-    // Don't store any data if we exceed the limit. Wipe any data we previously
-    // collected so that we don't confuse websites with partial state.
-    if (usage > Services.prefs.getIntPref(DOM_STORAGE_LIMIT_PREF)) {
-      MessageQueue.push("storage", () => null);
-      this.removeEventListener();
-      this.resetChanges();
-      return;
-    }
-
-    let {url, key, newValue} = event;
-    let uri = Services.io.newURI(url);
-    let domain = uri.prePath;
-    if (!this._changes) {
-      this._changes = {};
-    }
-    if (!this._changes[domain]) {
-      this._changes[domain] = {};
-    }
-    this._changes[domain][key] = newValue;
-
-    MessageQueue.push("storagechange", () => {
-      let tmp = this._changes;
-      // If there were multiple changes we send them merged.
-      // First one will collect all the changes the rest of
-      // these messages will be ignored.
-      this.resetChanges();
-      return tmp;
-    });
-  },
-
-  collect() {
-    if (!docShell) {
-      return;
-    }
-
-    // We need the entire session storage, let's reset the pending individual change
-    // messages.
-    this.resetChanges();
-
-    MessageQueue.push("storage", () => SessionStorage.collect(content));
-  },
-
-  onPageLoadCompleted() {
-    this.collect();
-  },
-
-  onPageLoadStarted() {
-    this.resetEventListener();
-    this.collect();
-  }
-};
-
-/**
- * Listen for changes to the privacy status of the tab.
- * By definition, tabs start in non-private mode.
- *
- * Causes a SessionStore:update message to be sent for
- * field "isPrivate". This message contains
- *  |true| if the tab is now private
- *  |null| if the tab is now public - the field is therefore
- *  not saved.
- */
-var PrivacyListener = {
-  init() {
-    docShell.addWeakPrivacyTransitionObserver(this);
-
-    // Check that value at startup as it might have
-    // been set before the frame script was loaded.
-    if (docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing) {
-      MessageQueue.push("isPrivate", () => true);
-    }
-  },
-
-  // Ci.nsIPrivacyTransitionObserver
-  privateModeChanged(enabled) {
-    MessageQueue.push("isPrivate", () => enabled || null);
-  },
-
-  QueryInterface: ChromeUtils.generateQI([Ci.nsIPrivacyTransitionObserver,
-                                          Ci.nsISupportsWeakReference])
-};
-
-/**
- * A message queue that takes collected data and will take care of sending it
- * to the chrome process. It allows flushing using synchronous messages and
- * takes care of any race conditions that might occur because of that. Changes
- * will be batched if they're pushed in quick succession to avoid a message
- * flood.
- */
-var MessageQueue = {
-  /**
-   * A map (string -> lazy fn) holding lazy closures of all queued data
-   * collection routines. These functions will return data collected from the
-   * docShell.
-   */
-  _data: new Map(),
-
-  /**
-   * The delay (in ms) used to delay sending changes after data has been
-   * invalidated.
-   */
-  BATCH_DELAY_MS: 1000,
-
-  /**
-   * The minimum idle period (in ms) we need for sending data to chrome process.
-   */
-  NEEDED_IDLE_PERIOD_MS: 5,
-
-  /**
-   * Timeout for waiting an idle period to send data. We will set this from
-   * the pref "browser.sessionstore.interval".
-   */
-  _timeoutWaitIdlePeriodMs: null,
-
-  /**
-   * The current timeout ID, null if there is no queue data. We use timeouts
-   * to damp a flood of data changes and send lots of changes as one batch.
-   */
-  _timeout: null,
-
-  /**
-   * Whether or not sending batched messages on a timer is disabled. This should
-   * only be used for debugging or testing. If you need to access this value,
-   * you should probably use the timeoutDisabled getter.
-   */
-  _timeoutDisabled: false,
-
-  /**
-   * True if there is already a send pending idle dispatch, set to prevent
-   * scheduling more than one. If false there may or may not be one scheduled.
-   */
-  _idleScheduled: false,
-
-  /**
-   * True if batched messages are not being fired on a timer. This should only
-   * ever be true when debugging or during tests.
-   */
-  get timeoutDisabled() {
-    return this._timeoutDisabled;
-  },
-
-  /**
-   * Disables sending batched messages on a timer. Also cancels any pending
-   * timers.
-   */
-  set timeoutDisabled(val) {
-    this._timeoutDisabled = val;
-
-    if (val && this._timeout) {
-      clearTimeout(this._timeout);
-      this._timeout = null;
-    }
-
-    return val;
-  },
-
-  init() {
-    this.timeoutDisabled =
-      Services.prefs.getBoolPref(TIMEOUT_DISABLED_PREF);
-    this._timeoutWaitIdlePeriodMs =
-      Services.prefs.getIntPref(PREF_INTERVAL);
-
-    Services.prefs.addObserver(TIMEOUT_DISABLED_PREF, this);
-    Services.prefs.addObserver(PREF_INTERVAL, this);
-  },
-
-  uninit() {
-    Services.prefs.removeObserver(TIMEOUT_DISABLED_PREF, this);
-    Services.prefs.removeObserver(PREF_INTERVAL, this);
-    this.cleanupTimers();
-  },
-
-  /**
-   * Cleanup pending idle callback and timer.
-   */
-  cleanupTimers() {
-    this._idleScheduled = false;
-    if (this._timeout) {
-      clearTimeout(this._timeout);
-      this._timeout = null;
-    }
-  },
-
-  observe(subject, topic, data) {
-    if (topic == "nsPref:changed") {
-      switch (data) {
-        case TIMEOUT_DISABLED_PREF:
-          this.timeoutDisabled =
-            Services.prefs.getBoolPref(TIMEOUT_DISABLED_PREF);
-          break;
-        case PREF_INTERVAL:
-          this._timeoutWaitIdlePeriodMs =
-            Services.prefs.getIntPref(PREF_INTERVAL);
-          break;
-        default:
-          debug("received unknown message '" + data + "'");
-          break;
-      }
-    }
-  },
-
-  /**
-   * Pushes a given |value| onto the queue. The given |key| represents the type
-   * of data that is stored and can override data that has been queued before
-   * but has not been sent to the parent process, yet.
-   *
-   * @param key (string)
-   *        A unique identifier specific to the type of data this is passed.
-   * @param fn (function)
-   *        A function that returns the value that will be sent to the parent
-   *        process.
-   */
-  push(key, fn) {
-    this._data.set(key, fn);
-
-    if (!this._timeout && !this._timeoutDisabled) {
-      // Wait a little before sending the message to batch multiple changes.
-      this._timeout = setTimeoutWithTarget(
-        () => this.sendWhenIdle(), this.BATCH_DELAY_MS, tabEventTarget);
-    }
-  },
-
-  /**
-   * Sends queued data when the remaining idle time is enough or waiting too
-   * long; otherwise, request an idle time again. If the |deadline| is not
-   * given, this function is going to schedule the first request.
-   *
-   * @param deadline (object)
-   *        An IdleDeadline object passed by idleDispatch().
-   */
-  sendWhenIdle(deadline) {
-    if (!content) {
-      // The frameloader is being torn down. Nothing more to do.
-      return;
-    }
-
-    if (deadline) {
-      if (deadline.didTimeout || deadline.timeRemaining() > MessageQueue.NEEDED_IDLE_PERIOD_MS) {
-        MessageQueue.send();
-        return;
-      }
-    } else if (MessageQueue._idleScheduled) {
-      // Bail out if there's a pending run.
-      return;
-    }
-    ChromeUtils.idleDispatch(MessageQueue.sendWhenIdle, {timeout: MessageQueue._timeoutWaitIdlePeriodMs});
-    MessageQueue._idleScheduled = true;
-  },
-
-  /**
-   * Sends queued data to the chrome process.
-   *
-   * @param options (object)
-   *        {flushID: 123} to specify that this is a flush
-   *        {isFinal: true} to signal this is the final message sent on unload
-   */
-  send(options = {}) {
-    // Looks like we have been called off a timeout after the tab has been
-    // closed. The docShell is gone now and we can just return here as there
-    // is nothing to do.
-    if (!docShell) {
-      return;
-    }
-
-    this.cleanupTimers();
-
-    let flushID = (options && options.flushID) || 0;
-    let histID = "FX_SESSION_RESTORE_CONTENT_COLLECT_DATA_MS";
-
-    let data = {};
-    for (let [key, func] of this._data) {
-      if (key != "isPrivate") {
-        TelemetryStopwatch.startKeyed(histID, key);
-      }
-
-      let value = func();
-
-      if (key != "isPrivate") {
-        TelemetryStopwatch.finishKeyed(histID, key);
-      }
-
-      if (value || (key != "storagechange" && key != "historychange")) {
-        data[key] = value;
-      }
-    }
-
-    this._data.clear();
-
-    try {
-      // Send all data to the parent process.
-      sendAsyncMessage("SessionStore:update", {
-        data, flushID,
-        isFinal: options.isFinal || false,
-        epoch: gCurrentEpoch
-      });
-    } catch (ex) {
-      if (ex && ex.result == Cr.NS_ERROR_OUT_OF_MEMORY) {
-        Services.telemetry.getHistogramById("FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM").add(1);
-        sendAsyncMessage("SessionStore:error");
-      }
-    }
-  },
-};
-
-StateChangeNotifier.init();
-EventListener.init();
-MessageListener.init();
-FormDataListener.init();
-SessionHistoryListener.init();
-SessionStorageListener.init();
-ScrollPositionListener.init();
-DocShellCapabilitiesListener.init();
-PrivacyListener.init();
-MessageQueue.init();
-
-function handleRevivedTab() {
-  if (!content) {
-    removeEventListener("pagehide", handleRevivedTab);
-    return;
-  }
-
-  if (content.document.documentURI.startsWith("about:tabcrashed")) {
-    if (Services.appinfo.processType != Services.appinfo.PROCESS_TYPE_DEFAULT) {
-      // Sanity check - we'd better be loading this in a non-remote browser.
-      throw new Error("We seem to be navigating away from about:tabcrashed in " +
-                      "a non-remote browser. This should really never happen.");
-    }
-
-    removeEventListener("pagehide", handleRevivedTab);
-
-    // Notify the parent.
-    sendAsyncMessage("SessionStore:crashedTabRevived");
-  }
-}
-
-// If we're browsing from the tab crashed UI to a blacklisted URI that keeps
-// this browser non-remote, we'll handle that in a pagehide event.
-addEventListener("pagehide", handleRevivedTab);
-
-addEventListener("unload", () => {
-  // Upon frameLoader destruction, send a final update message to
-  // the parent and flush all data currently held in the child.
-  MessageQueue.send({isFinal: true});
-
-  // If we're browsing from the tab crashed UI to a URI that causes the tab
-  // to go remote again, we catch this in the unload event handler, because
-  // swapping out the non-remote browser for a remote one in
-  // tabbrowser.xml's updateBrowserRemoteness doesn't cause the pagehide
-  // event to be fired.
-  handleRevivedTab();
-
-  // Remove all registered nsIObservers.
-  SessionStorageListener.uninit();
-  SessionHistoryListener.uninit();
-  MessageQueue.uninit();
-
-  if (contentRestoreInitialized) {
-    // Remove progress listeners.
-    gContentRestore.resetRestore();
-  }
-
-  // We don't need to take care of any StateChangeNotifier observers as they
-  // will die with the content script. The same goes for the privacy transition
-  // observer that will die with the docShell when the tab is closed.
-});
+void new ContentSessionStore(this);
--- a/browser/components/sessionstore/moz.build
+++ b/browser/components/sessionstore/moz.build
@@ -17,16 +17,17 @@ XPIDL_MODULE = 'sessionstore'
 
 EXTRA_COMPONENTS += [
     'nsSessionStartup.js',
     'nsSessionStartup.manifest',
 ]
 
 EXTRA_JS_MODULES.sessionstore = [
     'ContentRestore.jsm',
+    'ContentSessionStore.jsm',
     'DocShellCapabilities.jsm',
     'GlobalState.jsm',
     'RecentlyClosedTabsAndWindowsMenuUtils.jsm',
     'RunState.jsm',
     'SessionCookies.jsm',
     'SessionFile.jsm',
     'SessionMigration.jsm',
     'SessionSaver.jsm',
--- a/browser/extensions/formautofill/content/FormAutofillFrameScript.js
+++ b/browser/extensions/formautofill/content/FormAutofillFrameScript.js
@@ -7,16 +7,18 @@
  */
 
 "use strict";
 
 /* eslint-env mozilla/frame-script */
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
+ChromeUtils.defineModuleGetter(this, "setTimeout",
+                               "resource://gre/modules/Timer.jsm");
 ChromeUtils.defineModuleGetter(this, "FormAutofill",
                                "resource://formautofill/FormAutofill.jsm");
 ChromeUtils.defineModuleGetter(this, "FormAutofillUtils",
                                "resource://formautofill/FormAutofillUtils.jsm");
 
 /**
  * Handles content's interactions for the frame.
  *
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -7,24 +7,24 @@
 #include "mozilla/BasePrincipal.h"
 
 #include "nsDocShell.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIStandardURL.h"
 
-#include "ContentPrincipal.h"
 #include "ExpandedPrincipal.h"
 #include "nsNetUtil.h"
 #include "nsIURIWithPrincipal.h"
-#include "NullPrincipal.h"
 #include "nsScriptSecurityManager.h"
 #include "nsServiceManagerUtils.h"
 
+#include "mozilla/ContentPrincipal.h"
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/dom/ChromeUtils.h"
 #include "mozilla/dom/CSPDictionariesBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 
 namespace mozilla {
 
 BasePrincipal::BasePrincipal(PrincipalKind aKind)
   : mKind(aKind)
--- a/caps/ContentPrincipal.h
+++ b/caps/ContentPrincipal.h
@@ -1,27 +1,29 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef ContentPrincipal_h
-#define ContentPrincipal_h
+#ifndef mozilla_ContentPrincipal_h
+#define mozilla_ContentPrincipal_h
 
 #include "nsCOMPtr.h"
 #include "nsJSPrincipals.h"
 #include "nsTArray.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIProtocolHandler.h"
 #include "nsNetUtil.h"
 #include "nsScriptSecurityManager.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/extensions/WebExtensionPolicy.h"
 
-class ContentPrincipal final : public mozilla::BasePrincipal
+namespace mozilla {
+
+class ContentPrincipal final : public BasePrincipal
 {
 public:
   NS_DECL_NSISERIALIZABLE
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
@@ -30,38 +32,40 @@ public:
   bool IsCodebasePrincipal() const override { return true; }
 
   ContentPrincipal();
 
   static PrincipalKind Kind() { return eCodebasePrincipal; }
 
   // Init() must be called before the principal is in a usable state.
   nsresult Init(nsIURI* aCodebase,
-                const mozilla::OriginAttributes& aOriginAttributes,
+                const OriginAttributes& aOriginAttributes,
                 const nsACString& aOriginNoSuffix);
 
   virtual nsresult GetScriptLocation(nsACString& aStr) override;
 
   static nsresult
   GenerateOriginNoSuffixFromURI(nsIURI* aURI, nsACString& aOrigin);
 
-  mozilla::extensions::WebExtensionPolicy* AddonPolicy();
+  extensions::WebExtensionPolicy* AddonPolicy();
 
   nsCOMPtr<nsIURI> mDomain;
   nsCOMPtr<nsIURI> mCodebase;
 
 protected:
   virtual ~ContentPrincipal();
 
   bool SubsumesInternal(nsIPrincipal* aOther,
                         DocumentDomainConsideration aConsideration) override;
   bool MayLoadInternal(nsIURI* aURI) override;
 
 private:
-  mozilla::Maybe<mozilla::WeakPtr<mozilla::extensions::WebExtensionPolicy>> mAddon;
+  Maybe<WeakPtr<extensions::WebExtensionPolicy>> mAddon;
 };
 
+} // mozilla namespace
+
 #define NS_PRINCIPAL_CONTRACTID "@mozilla.org/principal;1"
 #define NS_PRINCIPAL_CID \
 { 0x653e0e4d, 0x3ee4, 0x45fa, \
   { 0xb2, 0x72, 0x97, 0xc2, 0x0b, 0xc0, 0x1e, 0xb8 } }
 
-#endif // ContentPrincipal_h
+#endif // mozilla_ContentPrincipal_h
--- a/caps/NullPrincipal.cpp
+++ b/caps/NullPrincipal.cpp
@@ -64,17 +64,17 @@ NullPrincipal::Create(const OriginAttrib
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
 
   return nullPrin.forget();
 }
 
 /* static */ already_AddRefed<NullPrincipal>
 NullPrincipal::CreateWithoutOriginAttributes()
 {
-  return NullPrincipal::Create(mozilla::OriginAttributes(), nullptr);
+  return NullPrincipal::Create(OriginAttributes(), nullptr);
 }
 
 nsresult
 NullPrincipal::Init(const OriginAttributes& aOriginAttributes, nsIURI* aURI)
 {
   if (aURI) {
     nsAutoCString scheme;
     nsresult rv = aURI->GetScheme(scheme);
--- a/caps/NullPrincipal.h
+++ b/caps/NullPrincipal.h
@@ -4,18 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * This is the principal that has no rights and can't be accessed by
  * anything other than itself and chrome; null principals are not
  * same-origin with anything but themselves.
  */
 
-#ifndef NullPrincipal_h
-#define NullPrincipal_h
+#ifndef mozilla_NullPrincipal_h
+#define mozilla_NullPrincipal_h
 
 #include "nsIPrincipal.h"
 #include "nsJSPrincipals.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsCOMPtr.h"
 #include "nsIContentSecurityPolicy.h"
 
 #include "mozilla/BasePrincipal.h"
@@ -25,17 +25,19 @@ class nsIURI;
 
 #define NS_NULLPRINCIPAL_CID \
 { 0xbd066e5f, 0x146f, 0x4472, \
   { 0x83, 0x31, 0x7b, 0xfd, 0x05, 0xb1, 0xed, 0x90 } }
 #define NS_NULLPRINCIPAL_CONTRACTID "@mozilla.org/nullprincipal;1"
 
 #define NS_NULLPRINCIPAL_SCHEME "moz-nullprincipal"
 
-class NullPrincipal final : public mozilla::BasePrincipal
+namespace mozilla {
+
+class NullPrincipal final : public BasePrincipal
 {
 public:
   // This should only be used by deserialization, and the factory constructor.
   // Other consumers should use the Create and CreateWithInheritedAttributes
   // methods.
   NullPrincipal()
     : BasePrincipal(eNullPrincipal)
   {
@@ -59,23 +61,23 @@ public:
   // Create NullPrincipal with origin attributes from docshell.
   // If aIsFirstParty is true, and the pref 'privacy.firstparty.isolate' is also
   // enabled, the mFirstPartyDomain value of the origin attributes will be set
   // to an unique value.
   static already_AddRefed<NullPrincipal>
   CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty = false);
 
   static already_AddRefed<NullPrincipal>
-  Create(const mozilla::OriginAttributes& aOriginAttributes,
+  Create(const OriginAttributes& aOriginAttributes,
          nsIURI* aURI = nullptr);
 
   static already_AddRefed<NullPrincipal>
   CreateWithoutOriginAttributes();
 
-  nsresult Init(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes(),
+  nsresult Init(const OriginAttributes& aOriginAttributes = OriginAttributes(),
                 nsIURI* aURI = nullptr);
 
   virtual nsresult GetScriptLocation(nsACString &aStr) override;
 
  protected:
   virtual ~NullPrincipal() = default;
 
   bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override
@@ -86,12 +88,14 @@ public:
   bool MayLoadInternal(nsIURI* aURI) override;
 
   nsCOMPtr<nsIURI> mURI;
 
 private:
   // If aIsFirstParty is true, this NullPrincipal will be initialized base on
   // the aOriginAttributes with FirstPartyDomain set to an unique value, and this
   // value is generated from mURI.path, with ".mozilla" appending at the end.
-  nsresult Init(const mozilla::OriginAttributes& aOriginAttributes, bool aIsFirstParty);
+  nsresult Init(const OriginAttributes& aOriginAttributes, bool aIsFirstParty);
 };
 
-#endif // NullPrincipal_h__
+} // mozilla namespace
+
+#endif // mozilla_NullPrincipal_h
--- a/caps/NullPrincipalURI.cpp
+++ b/caps/NullPrincipalURI.cpp
@@ -10,16 +10,18 @@
 #include "mozilla/MemoryReporting.h"
 
 #include "mozilla/ipc/URIParams.h"
 
 #include "nsEscape.h"
 #include "nsCRT.h"
 #include "nsIUUIDGenerator.h"
 
+using namespace mozilla;
+
 ////////////////////////////////////////////////////////////////////////////////
 //// NullPrincipalURI
 
 NullPrincipalURI::NullPrincipalURI()
 {
 }
 
 NullPrincipalURI::NullPrincipalURI(const NullPrincipalURI& aOther)
@@ -401,18 +403,18 @@ NullPrincipalURI::Deserialize(const mozi
 
   return true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsISizeOf
 
 size_t
-NullPrincipalURI::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+NullPrincipalURI::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
   return mPath.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
 }
 
 size_t
-NullPrincipalURI::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+NullPrincipalURI::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
 }
--- a/caps/NullPrincipalURI.h
+++ b/caps/NullPrincipalURI.h
@@ -3,18 +3,18 @@
  * 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/. */
 
 /**
  * This wraps nsSimpleURI so that all calls to it are done on the main thread.
  */
 
-#ifndef __NullPrincipalURI_h__
-#define __NullPrincipalURI_h__
+#ifndef mozilla_NullPrincipalURI_h
+#define mozilla_NullPrincipalURI_h
 
 #include "nsIURI.h"
 #include "nsISizeOf.h"
 #include "nsString.h"
 #include "mozilla/Attributes.h"
 #include "nsIIPCSerializableURI.h"
 #include "mozilla/MemoryReporting.h"
 #include "NullPrincipal.h"
@@ -22,31 +22,31 @@
 #include "nsIURIMutator.h"
 
 // {51fcd543-3b52-41f7-b91b-6b54102236e6}
 #define NS_NULLPRINCIPALURI_IMPLEMENTATION_CID \
   {0x51fcd543, 0x3b52, 0x41f7, \
     {0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} }
 
 namespace mozilla {
+
 class Encoding;
-}
 
 class NullPrincipalURI final : public nsIURI
                              , public nsISizeOf
                              , public nsIIPCSerializableURI
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIURI
   NS_DECL_NSIIPCSERIALIZABLEURI
 
   // nsISizeOf
-  virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
-  virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
+  virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
+  virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
 
   // Returns null on failure.
   static already_AddRefed<NullPrincipalURI> Create();
 
 private:
   NullPrincipalURI();
   NullPrincipalURI(const NullPrincipalURI& aOther);
 
@@ -64,17 +64,17 @@ private:
   nsresult SetPassword(const nsACString &input);
   nsresult SetHostPort(const nsACString &aValue);
   nsresult SetHost(const nsACString &input);
   nsresult SetPort(int32_t port);
   nsresult SetPathQueryRef(const nsACString &input);
   nsresult SetRef(const nsACString &input);
   nsresult SetFilePath(const nsACString &input);
   nsresult SetQuery(const nsACString &input);
-  nsresult SetQueryWithEncoding(const nsACString &input, const mozilla::Encoding* encoding);
+  nsresult SetQueryWithEncoding(const nsACString &input, const Encoding* encoding);
   bool Deserialize(const mozilla::ipc::URIParams&);
 
 public:
   class Mutator final
       : public nsIURIMutator
       , public BaseURIMutator<NullPrincipalURI>
   {
     NS_DECL_ISUPPORTS
@@ -105,9 +105,11 @@ public:
     virtual ~Mutator() { }
 
     friend class NullPrincipalURI;
   };
 
   friend class BaseURIMutator<NullPrincipalURI>;
 };
 
-#endif // __NullPrincipalURI_h__
+} // mozilla namespace
+
+#endif // mozilla_NullPrincipalURI_h
--- a/caps/SystemPrincipal.cpp
+++ b/caps/SystemPrincipal.cpp
@@ -13,16 +13,18 @@
 #include "nsCOMPtr.h"
 #include "nsReadableUtils.h"
 #include "nsCRT.h"
 #include "nsString.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIScriptSecurityManager.h"
 #include "pratom.h"
 
+using namespace mozilla;
+
 NS_IMPL_CLASSINFO(SystemPrincipal, nullptr,
                   nsIClassInfo::SINGLETON | nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_SYSTEMPRINCIPAL_CID)
 NS_IMPL_QUERY_INTERFACE_CI(SystemPrincipal,
                            nsIPrincipal,
                            nsISerializable)
 NS_IMPL_CI_INTERFACE_GETTER(SystemPrincipal,
                             nsIPrincipal,
--- a/caps/SystemPrincipal.h
+++ b/caps/SystemPrincipal.h
@@ -1,31 +1,32 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* The privileged system principal. */
 
-#ifndef SystemPrincipal_h
-#define SystemPrincipal_h
+#ifndef mozilla_SystemPrincipal_h
+#define mozilla_SystemPrincipal_h
 
 #include "nsIPrincipal.h"
 #include "nsJSPrincipals.h"
 
 #include "mozilla/BasePrincipal.h"
 
 #define NS_SYSTEMPRINCIPAL_CID \
 { 0x4a6212db, 0xaccb, 0x11d3, \
 { 0xb7, 0x65, 0x0, 0x60, 0xb0, 0xb6, 0xce, 0xcb }}
 #define NS_SYSTEMPRINCIPAL_CONTRACTID "@mozilla.org/systemprincipal;1"
 
+namespace mozilla {
 
-class SystemPrincipal final : public mozilla::BasePrincipal
+class SystemPrincipal final : public BasePrincipal
 {
   SystemPrincipal()
     : BasePrincipal(eSystemPrincipal)
   {
   }
 
 public:
   static already_AddRefed<SystemPrincipal> Create();
@@ -58,9 +59,11 @@ protected:
   }
 
   bool MayLoadInternal(nsIURI* aURI) override
   {
     return true;
   }
 };
 
-#endif // SystemPrincipal_h
+} // mozilla namespace
+
+#endif // mozilla_SystemPrincipal_h
--- a/caps/moz.build
+++ b/caps/moz.build
@@ -19,27 +19,27 @@ XPIDL_SOURCES += [
     'nsIDomainPolicy.idl',
     'nsIPrincipal.idl',
     'nsIScriptSecurityManager.idl',
 ]
 
 XPIDL_MODULE = 'caps'
 
 EXPORTS += [
-    'ContentPrincipal.h',
     'nsJSPrincipals.h',
     'nsScriptSecurityManager.h',
-    'NullPrincipal.h',
-    'NullPrincipalURI.h',
-    'SystemPrincipal.h',
 ]
 
 EXPORTS.mozilla = [
     'BasePrincipal.h',
+    'ContentPrincipal.h',
+    'NullPrincipal.h',
+    'NullPrincipalURI.h',
     'OriginAttributes.h',
+    'SystemPrincipal.h',
 ]
 
 SOURCES += [
     # Compile this separately since nsExceptionHandler.h conflicts
     # with something from NullPrincipal.cpp.
     'BasePrincipal.cpp',
 ]
 
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -18,17 +18,16 @@
 #include "nsIURL.h"
 #include "nsIURIMutator.h"
 #include "nsINestedURI.h"
 #include "nspr.h"
 #include "nsJSPrincipals.h"
 #include "mozilla/BasePrincipal.h"
 #include "ExpandedPrincipal.h"
 #include "SystemPrincipal.h"
-#include "NullPrincipal.h"
 #include "DomainPolicy.h"
 #include "nsString.h"
 #include "nsCRT.h"
 #include "nsCRTGlue.h"
 #include "nsDocShell.h"
 #include "nsError.h"
 #include "nsDOMCID.h"
 #include "nsTextFormatter.h"
@@ -54,16 +53,17 @@
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIChromeRegistry.h"
 #include "nsIResProtocolHandler.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/NullPrincipal.h"
 #include <stdint.h>
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StaticPtr.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "nsILoadInfo.h"
 #include "nsIDOMXULCommandDispatcher.h"
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -16,20 +16,20 @@
 #include "nsStringFwd.h"
 #include "plstr.h"
 #include "js/TypeDecls.h"
 
 #include <stdint.h>
 
 class nsIIOService;
 class nsIStringBundle;
-class SystemPrincipal;
 
 namespace mozilla {
 class OriginAttributes;
+class SystemPrincipal;
 } // namespace mozilla
 
 /////////////////////////////
 // nsScriptSecurityManager //
 /////////////////////////////
 #define NS_SCRIPTSECURITYMANAGER_CID \
 { 0x7ee2a4c0, 0x4b93, 0x17d3, \
 { 0xba, 0x18, 0x00, 0x60, 0xb0, 0xf1, 0x99, 0xa2 }}
@@ -45,17 +45,17 @@ public:
     NS_DECL_NSISCRIPTSECURITYMANAGER
 
     static nsScriptSecurityManager*
     GetScriptSecurityManager();
 
     // Invoked exactly once, by XPConnect.
     static void InitStatics();
 
-    static already_AddRefed<SystemPrincipal>
+    static already_AddRefed<mozilla::SystemPrincipal>
     SystemPrincipalSingletonConstructor();
 
     /**
      * Utility method for comparing two URIs.  For security purposes, two URIs
      * are equivalent if their schemes, hosts, and ports (if any) match.  This
      * method returns true if aSubjectURI and aObjectURI have the same origin,
      * false otherwise.
      */
--- a/devtools/client/inspector/flexbox/actions/flexbox.js
+++ b/devtools/client/inspector/flexbox/actions/flexbox.js
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {
   CLEAR_FLEXBOX,
   UPDATE_FLEXBOX,
+  UPDATE_FLEXBOX_COLOR,
   UPDATE_FLEXBOX_HIGHLIGHTED,
 } = require("./index");
 
 module.exports = {
 
   /**
    * Clears the flexbox state by resetting it back to the initial flexbox state.
    */
@@ -27,16 +28,29 @@ module.exports = {
   updateFlexbox(flexbox) {
     return {
       type: UPDATE_FLEXBOX,
       flexbox,
     };
   },
 
   /**
+   * Update the color used for the flexbox's highlighter.
+   *
+   * @param  {String} color
+   *         The color to use for this nodeFront's flexbox highlighter.
+   */
+  updateFlexboxColor(color) {
+    return {
+      type: UPDATE_FLEXBOX_COLOR,
+      color,
+    };
+  },
+
+  /**
    * Updates the flexbox highlighted state.
    *
    * @param  {Boolean} highlighted
    *         Whether or not the flexbox highlighter is highlighting the flexbox.
    */
   updateFlexboxHighlighted(highlighted) {
     return {
       type: UPDATE_FLEXBOX_HIGHLIGHTED,
--- a/devtools/client/inspector/flexbox/actions/index.js
+++ b/devtools/client/inspector/flexbox/actions/index.js
@@ -9,12 +9,15 @@ const { createEnum } = require("devtools
 createEnum([
 
   // Clears the flexbox state by resetting it back to the initial flexbox state.
   "CLEAR_FLEXBOX",
 
   // Updates the flexbox state with the newly selected flexbox.
   "UPDATE_FLEXBOX",
 
+  // Update the color used for the overlay of a flexbox.
+  "UPDATE_FLEXBOX_COLOR",
+
   // Updates the flexbox highlighted state.
   "UPDATE_FLEXBOX_HIGHLIGHTED",
 
 ], module.exports);
--- a/devtools/client/inspector/flexbox/components/Flexbox.js
+++ b/devtools/client/inspector/flexbox/components/Flexbox.js
@@ -12,28 +12,32 @@ const { getStr } = require("devtools/cli
 const FlexboxItem = createFactory(require("./FlexboxItem"));
 
 const Types = require("../types");
 
 class Flexbox extends PureComponent {
   static get propTypes() {
     return {
       flexbox: PropTypes.shape(Types.flexbox).isRequired,
+      getSwatchColorPickerTooltip: PropTypes.func.isRequired,
       setSelectedNode: PropTypes.func.isRequired,
       onHideBoxModelHighlighter: PropTypes.func.isRequired,
+      onSetFlexboxOverlayColor: PropTypes.func.isRequired,
       onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
       onToggleFlexboxHighlighter: PropTypes.func.isRequired,
     };
   }
 
   render() {
     const {
       flexbox,
+      getSwatchColorPickerTooltip,
       setSelectedNode,
       onHideBoxModelHighlighter,
+      onSetFlexboxOverlayColor,
       onShowBoxModelHighlighterForNode,
       onToggleFlexboxHighlighter,
     } = this.props;
 
     return flexbox.actorID ?
       dom.div({ id: "layout-flexbox-container" },
         dom.div({ className: "flexbox-content" },
           dom.div({ className: "flexbox-container" },
@@ -41,18 +45,20 @@ class Flexbox extends PureComponent {
             dom.ul(
               {
                 id: "flexbox-list",
                 className: "devtools-monospace",
               },
               FlexboxItem({
                 key: flexbox.id,
                 flexbox,
+                getSwatchColorPickerTooltip,
                 setSelectedNode,
                 onHideBoxModelHighlighter,
+                onSetFlexboxOverlayColor,
                 onShowBoxModelHighlighterForNode,
                 onToggleFlexboxHighlighter,
               })
             )
           )
         )
       )
       :
--- a/devtools/client/inspector/flexbox/components/FlexboxItem.js
+++ b/devtools/client/inspector/flexbox/components/FlexboxItem.js
@@ -2,42 +2,81 @@
  * 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/. */
 
 "use strict";
 
 const { PureComponent } = require("devtools/client/shared/vendor/react");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const { findDOMNode } = require("devtools/client/shared/vendor/react-dom");
 const { translateNodeFrontToGrip } = require("devtools/client/inspector/shared/utils");
 
 // Reps
 const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
 const { Rep } = REPS;
 const ElementNode = REPS.ElementNode;
 
 const Types = require("../types");
 
 class FlexboxItem extends PureComponent {
   static get propTypes() {
     return {
       flexbox: PropTypes.shape(Types.flexbox).isRequired,
+      getSwatchColorPickerTooltip: PropTypes.func.isRequired,
       setSelectedNode: PropTypes.func.isRequired,
       onHideBoxModelHighlighter: PropTypes.func.isRequired,
+      onSetFlexboxOverlayColor: PropTypes.func.isRequired,
       onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
       onToggleFlexboxHighlighter: PropTypes.func.isRequired,
     };
   }
 
   constructor(props) {
     super(props);
+
+    this.setFlexboxColor = this.setFlexboxColor.bind(this);
     this.onFlexboxCheckboxClick = this.onFlexboxCheckboxClick.bind(this);
     this.onFlexboxInspectIconClick = this.onFlexboxInspectIconClick.bind(this);
   }
 
+  componentDidMount() {
+    const {
+      flexbox,
+      getSwatchColorPickerTooltip,
+      onSetFlexboxOverlayColor,
+    } = this.props;
+
+    const swatchEl = findDOMNode(this).querySelector(".flexbox-color-swatch");
+    const tooltip = getSwatchColorPickerTooltip();
+
+    let previousColor;
+    tooltip.addSwatch(swatchEl, {
+      onCommit: this.setFlexboxColor,
+      onPreview: this.setFlexboxColor,
+      onRevert: () => {
+        onSetFlexboxOverlayColor(previousColor);
+      },
+      onShow: () => {
+        previousColor = flexbox.color;
+      },
+    });
+  }
+
+  componentWillUnMount() {
+    const swatchEl = findDOMNode(this).querySelector(".flexbox-color-swatch");
+    const tooltip = this.props.getSwatchColorPickerTooltip();
+    tooltip.removeSwatch(swatchEl);
+  }
+
+  setFlexboxColor() {
+    const color = findDOMNode(this).querySelector(".flexbox-color-value").textContent;
+    this.props.onSetFlexboxOverlayColor(color);
+  }
+
   onFlexboxCheckboxClick(e) {
     // If the click was on the svg icon to select the node in the inspector, bail out.
     const originalTarget = e.nativeEvent && e.nativeEvent.explicitOriginalTarget;
     if (originalTarget && originalTarget.namespaceURI === "http://www.w3.org/2000/svg") {
       // We should be able to cancel the click event propagation after the following reps
       // issue is implemented : https://github.com/devtools-html/reps/issues/95 .
       e.preventDefault();
       return;
@@ -60,16 +99,17 @@ class FlexboxItem extends PureComponent 
   render() {
     const {
       flexbox,
       onHideBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
     } = this.props;
     const {
       actorID,
+      color,
       highlighted,
       nodeFront,
     } = flexbox;
 
     return dom.li(
       {},
       dom.label(
         {},
@@ -86,14 +126,28 @@ class FlexboxItem extends PureComponent 
             defaultRep: ElementNode,
             mode: MODE.TINY,
             object: translateNodeFrontToGrip(nodeFront),
             onDOMNodeMouseOut: () => onHideBoxModelHighlighter(),
             onDOMNodeMouseOver: () => onShowBoxModelHighlighterForNode(nodeFront),
             onInspectIconClick: () => this.onFlexboxInspectIconClick(nodeFront),
           }
         )
-      )
+      ),
+      dom.div(
+        {
+          className: "flexbox-color-swatch",
+          style: {
+            backgroundColor: color,
+          },
+          title: color,
+        }
+      ),
+      // The SwatchColorPicker relies on the nextSibling of the swatch element to apply
+      // the selected color. This is why we use a span in display: none for now.
+      // Ideally we should modify the SwatchColorPickerTooltip to bypass this requirement.
+      // See https://bugzilla.mozilla.org/show_bug.cgi?id=1341578
+      dom.span({ className: "flexbox-color-value" }, color)
     );
   }
 }
 
 module.exports = FlexboxItem;
--- a/devtools/client/inspector/flexbox/flexbox.js
+++ b/devtools/client/inspector/flexbox/flexbox.js
@@ -4,29 +4,36 @@
 
 "use strict";
 
 const { throttle } = require("devtools/client/inspector/shared/utils");
 
 const {
   clearFlexbox,
   updateFlexbox,
+  updateFlexboxColor,
   updateFlexboxHighlighted,
 } = require("./actions/flexbox");
 
+loader.lazyRequireGetter(this, "parseURL", "devtools/client/shared/source-utils", true);
+loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
+
+const FLEXBOX_COLOR = "#9400FF";
+
 class FlexboxInspector {
   constructor(inspector, window) {
     this.document = window.document;
     this.inspector = inspector;
     this.store = inspector.store;
     this.walker = inspector.walker;
 
     this.onHighlighterShown = this.onHighlighterShown.bind(this);
     this.onHighlighterHidden = this.onHighlighterHidden.bind(this);
     this.onReflow = throttle(this.onReflow, 500, this);
+    this.onSetFlexboxOverlayColor = this.onSetFlexboxOverlayColor.bind(this);
     this.onSidebarSelect = this.onSidebarSelect.bind(this);
     this.onToggleFlexboxHighlighter = this.onToggleFlexboxHighlighter.bind(this);
     this.onUpdatePanel = this.onUpdatePanel.bind(this);
 
     this.init();
   }
 
   // Get the highlighters overlay from the Inspector.
@@ -81,21 +88,32 @@ class FlexboxInspector {
     this.inspector = null;
     this.layoutInspector = null;
     this.store = null;
     this.walker = null;
   }
 
   getComponentProps() {
     return {
+      getSwatchColorPickerTooltip: this.getSwatchColorPickerTooltip,
+      onSetFlexboxOverlayColor: this.onSetFlexboxOverlayColor,
       onToggleFlexboxHighlighter: this.onToggleFlexboxHighlighter,
     };
   }
 
   /**
+   * Returns an object containing the custom flexbox colors for different hosts.
+   *
+   * @return {Object} that maps a host name to a custom flexbox color for a given host.
+   */
+  async getCustomFlexboxColors() {
+    return await asyncStorage.getItem("flexboxInspectorHostColors") || {};
+  }
+
+  /**
    * Returns true if the layout panel is visible, and false otherwise.
    */
   isPanelVisible() {
     return this.inspector && this.inspector.toolbox && this.inspector.sidebar &&
            this.inspector.toolbox.currentToolId === "inspector" &&
            this.inspector.sidebar.getCurrentTabID() === "layoutview";
   }
   /**
@@ -186,16 +204,41 @@ class FlexboxInspector {
       return;
     }
 
     // Update the flexbox panel with the new flexbox front contents.
     this.update(flexboxFront);
   }
 
   /**
+   * Handler for a change in the flexbox overlay color picker for a flex container.
+   *
+   * @param  {String} color
+   *         A hex string representing the color to use.
+   */
+  async onSetFlexboxOverlayColor(color) {
+    this.store.dispatch(updateFlexboxColor(color));
+
+    const { flexbox } = this.store.getState();
+
+    if (flexbox.highlighted) {
+      this.highlighters.showFlexboxHighlighter(flexbox.nodeFront);
+    }
+
+    const currentUrl = this.inspector.target.url;
+    // Get the hostname, if there is no hostname, fall back on protocol
+    // ex: `data:` uri, and `about:` pages
+    const hostname = parseURL(currentUrl).hostname || parseURL(currentUrl).protocol;
+    const customFlexboxColors = await this.getCustomFlexboxColors();
+
+    customFlexboxColors[hostname] = color;
+    await asyncStorage.setItem("flexboxInspectorHostColors", customFlexboxColors);
+  }
+
+  /**
    * Handler for the inspector sidebar "select" event. Updates the flexbox panel if it
    * is visible.
    */
   onSidebarSelect() {
     if (!this.isPanelVisible()) {
       this.inspector.reflowTracker.untrackReflows(this, this.onReflow);
       this.inspector.selection.off("new-node-front", this.onUpdatePanel);
       this.inspector.off("new-root", this.onUpdatePanel);
@@ -236,17 +279,17 @@ class FlexboxInspector {
   }
 
   /**
    * Updates the flexbox panel by dispatching the new flexbox data. This is called when
    * the layout view becomes visible or a new node is selected and needs to be update
    * with new flexbox data.
    *
    * @param  {FlexboxFront|Null} flexboxFront
-   *         THe FlexboxFront of the flex container for the current node selection.
+   *         The FlexboxFront of the flex container for the current node selection.
    */
   async update(flexboxFront) {
     // Stop refreshing if the inspector or store is already destroyed or no node is
     // selected.
     if (!this.inspector || !this.store || !this.inspector.selection.nodeFront) {
       return;
     }
 
@@ -287,17 +330,25 @@ class FlexboxInspector {
         // closing.
         return;
       }
     }
 
     const highlighted = this._highlighters &&
       nodeFront == this.highlighters.flexboxHighlighterShown;
 
+    const currentUrl = this.inspector.target.url;
+    // Get the hostname, if there is no hostname, fall back on protocol
+    // ex: `data:` uri, and `about:` pages
+    const hostname = parseURL(currentUrl).hostname || parseURL(currentUrl).protocol;
+    const customColors = await this.getCustomFlexboxColors();
+    const color = customColors[hostname] ? customColors[hostname] : FLEXBOX_COLOR;
+
     this.store.dispatch(updateFlexbox({
       actorID: flexboxFront.actorID,
+      color,
       highlighted,
       nodeFront,
     }));
   }
 }
 
 module.exports = FlexboxInspector;
--- a/devtools/client/inspector/flexbox/reducers/flexbox.js
+++ b/devtools/client/inspector/flexbox/reducers/flexbox.js
@@ -2,38 +2,47 @@
  * 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/. */
 
 "use strict";
 
 const {
   CLEAR_FLEXBOX,
   UPDATE_FLEXBOX,
+  UPDATE_FLEXBOX_COLOR,
   UPDATE_FLEXBOX_HIGHLIGHTED,
 } = require("../actions/index");
 
 const INITIAL_FLEXBOX = {
   // The actor ID of the flex container.
   actorID: null,
+  // The color of the flexbox highlighter overlay.
+  color: "",
   // Whether or not the flexbox highlighter is highlighting the flex container.
   highlighted: false,
   // The NodeFront of the flex container.
   nodeFront: null,
 };
 
 const reducers = {
 
   [CLEAR_FLEXBOX](flexbox, _) {
     return INITIAL_FLEXBOX;
   },
 
   [UPDATE_FLEXBOX](_, { flexbox }) {
     return flexbox;
   },
 
+  [UPDATE_FLEXBOX_COLOR](flexbox, { color }) {
+    return Object.assign({}, flexbox, {
+      color,
+    });
+  },
+
   [UPDATE_FLEXBOX_HIGHLIGHTED](flexbox, { highlighted }) {
     return Object.assign({}, flexbox, {
       highlighted,
     });
   },
 
 };
 
--- a/devtools/client/inspector/flexbox/types.js
+++ b/devtools/client/inspector/flexbox/types.js
@@ -4,17 +4,20 @@
 
 "use strict";
 
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 
 exports.flexbox = {
 
   // The actor ID of the flex container.
-  actorID: PropTypes.number,
+  actorID: PropTypes.string,
+
+  // The color of the flexbox highlighter overlay.
+  color: PropTypes.string,
 
   // Whether or not the flexbox highlighter is highlighting the flex container.
   highlighted: PropTypes.bool,
 
   // The NodeFront of the flex container.
   nodeFront: PropTypes.object,
 
 };
--- a/devtools/client/inspector/grids/grid-inspector.js
+++ b/devtools/client/inspector/grids/grid-inspector.js
@@ -14,17 +14,16 @@ const {
 } = require("./actions/grids");
 const {
   updateShowGridAreas,
   updateShowGridLineNumbers,
   updateShowInfiniteLines,
 } = require("./actions/highlighter-settings");
 
 loader.lazyRequireGetter(this, "compareFragmentsGeometry", "devtools/client/inspector/grids/utils/utils", true);
-loader.lazyRequireGetter(this, "SwatchColorPickerTooltip", "devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
 loader.lazyRequireGetter(this, "parseURL", "devtools/client/shared/source-utils", true);
 loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
 
 const CSS_GRID_COUNT_HISTOGRAM_ID = "DEVTOOLS_NUMBER_OF_CSS_GRIDS_IN_A_PAGE";
 
 const SHOW_GRID_AREAS = "devtools.gridinspector.showGridAreas";
 const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
 const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
@@ -52,17 +51,16 @@ const GRID_COLORS = [
 class GridInspector {
   constructor(inspector, window) {
     this.document = window.document;
     this.inspector = inspector;
     this.store = inspector.store;
     this.telemetry = inspector.telemetry;
     this.walker = this.inspector.walker;
 
-    this.getSwatchColorPickerTooltip = this.getSwatchColorPickerTooltip.bind(this);
     this.updateGridPanel = this.updateGridPanel.bind(this);
 
     this.onHighlighterShown = this.onHighlighterShown.bind(this);
     this.onHighlighterHidden = this.onHighlighterHidden.bind(this);
     this.onNavigate = this.onNavigate.bind(this);
     this.onReflow = throttle(this.onReflow, 500, this);
     this.onSetGridOverlayColor = this.onSetGridOverlayColor.bind(this);
     this.onShowGridOutlineHighlight = this.onShowGridOutlineHighlight.bind(this);
@@ -78,31 +76,19 @@ class GridInspector {
   get highlighters() {
     if (!this._highlighters) {
       this._highlighters = this.inspector.highlighters;
     }
 
     return this._highlighters;
   }
 
-  get swatchColorPickerTooltip() {
-    if (!this._swatchColorPickerTooltip) {
-      this._swatchColorPickerTooltip = new SwatchColorPickerTooltip(
-        this.inspector.toolbox.doc,
-        this.inspector,
-        { supportsCssColor4ColorFunction: () => false }
-      );
-    }
-
-    return this._swatchColorPickerTooltip;
-  }
-
   /**
-   * Initializes the grid inspector by fetching the LayoutFront from the walker, loading
-   * the highlighter settings and initalizing the SwatchColorPicker instance.
+   * Initializes the grid inspector by fetching the LayoutFront from the walker and
+   * loading the highlighter settings.
    */
   async init() {
     if (!this.inspector) {
       return;
     }
 
     try {
       this.layoutInspector = await this.inspector.walker.getLayoutInspector();
@@ -133,34 +119,26 @@ class GridInspector {
       this.highlighters.off("grid-highlighter-shown", this.onHighlighterShown);
     }
 
     this.inspector.sidebar.off("select", this.onSidebarSelect);
     this.inspector.off("new-root", this.onNavigate);
 
     this.inspector.reflowTracker.untrackReflows(this, this.onReflow);
 
-    // The color picker may not be ready as `init` function is async,
-    // and we do not wait for its completion before calling destroy in tests
-    if (this._swatchColorPickerTooltip) {
-      this._swatchColorPickerTooltip.destroy();
-      this._swatchColorPickerTooltip = null;
-    }
-
     this._highlighters = null;
     this.document = null;
     this.inspector = null;
     this.layoutInspector = null;
     this.store = null;
     this.walker = null;
   }
 
   getComponentProps() {
     return {
-      getSwatchColorPickerTooltip: this.getSwatchColorPickerTooltip,
       onSetGridOverlayColor: this.onSetGridOverlayColor,
       onShowGridOutlineHighlight: this.onShowGridOutlineHighlight,
       onToggleGridHighlighter: this.onToggleGridHighlighter,
       onToggleShowGridAreas: this.onToggleShowGridAreas,
       onToggleShowGridLineNumbers: this.onToggleShowGridLineNumbers,
       onToggleShowInfiniteLines: this.onToggleShowInfiniteLines,
     };
   }
@@ -211,23 +189,16 @@ class GridInspector {
         return grid.color;
       }
     }
 
     return null;
   }
 
   /**
-   * Retrieve the shared SwatchColorPicker instance.
-   */
-  getSwatchColorPickerTooltip() {
-    return this.swatchColorPickerTooltip;
-  }
-
-  /**
    * Given a list of new grid fronts, and if we have a currently highlighted grid, check
    * if its fragments have changed.
    *
    * @param  {Array} newGridFronts
    *         A list of GridFront objects.
    * @return {Boolean}
    */
   haveCurrentFragmentsChanged(newGridFronts) {
--- a/devtools/client/inspector/grids/test/browser_grids_color-in-rules-grid-toggle.js
+++ b/devtools/client/inspector/grids/test/browser_grids_color-in-rules-grid-toggle.js
@@ -15,20 +15,20 @@ const TEST_URI = `
   <div id="grid">
     <div id="cell1">cell1</div>
     <div id="cell2">cell2</div>
   </div>
 `;
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  const { inspector, gridInspector } = await openLayoutView();
+  const { inspector, gridInspector, layoutView } = await openLayoutView();
   const { document: doc } = gridInspector;
   const { store } = inspector;
-  const cPicker = gridInspector.getSwatchColorPickerTooltip();
+  const cPicker = layoutView.getSwatchColorPickerTooltip();
   const spectrum = cPicker.spectrum;
   const swatch = doc.querySelector(".grid-color-swatch");
 
   info("Scrolling into view of the #grid color swatch.");
   swatch.scrollIntoView();
 
   info("Opening the color picker by clicking on the #grid color swatch.");
   const onColorPickerReady = cPicker.once("ready");
--- a/devtools/client/inspector/grids/test/browser_grids_grid-list-color-picker-on-ESC.js
+++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-color-picker-on-ESC.js
@@ -15,20 +15,20 @@ const TEST_URI = `
   <div id="grid">
     <div id="cell1">cell1</div>
     <div id="cell2">cell2</div>
   </div>
 `;
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  const { inspector, gridInspector } = await openLayoutView();
+  const { inspector, gridInspector, layoutView } = await openLayoutView();
   const { document: doc } = gridInspector;
   const { store } = inspector;
-  const cPicker = gridInspector.getSwatchColorPickerTooltip();
+  const cPicker = layoutView.getSwatchColorPickerTooltip();
   const spectrum = cPicker.spectrum;
   const swatch = doc.querySelector(".grid-color-swatch");
 
   info("Checking the initial state of the Grid Inspector.");
   is(swatch.style.backgroundColor, "rgb(148, 0, 255)",
     "The color swatch's background is correct.");
   is(store.getState().grids[0].color, "#9400FF", "The grid color state is correct.");
 
--- a/devtools/client/inspector/grids/test/browser_grids_grid-list-color-picker-on-RETURN.js
+++ b/devtools/client/inspector/grids/test/browser_grids_grid-list-color-picker-on-RETURN.js
@@ -15,20 +15,20 @@ const TEST_URI = `
   <div id="grid">
     <div id="cell1">cell1</div>
     <div id="cell2">cell2</div>
   </div>
 `;
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  const { inspector, gridInspector } = await openLayoutView();
+  const { inspector, gridInspector, layoutView } = await openLayoutView();
   const { document: doc } = gridInspector;
   const { store } = inspector;
-  const cPicker = gridInspector.getSwatchColorPickerTooltip();
+  const cPicker = layoutView.getSwatchColorPickerTooltip();
   const spectrum = cPicker.spectrum;
   const swatch = doc.querySelector(".grid-color-swatch");
 
   info("Checking the initial state of the Grid Inspector.");
   is(swatch.style.backgroundColor, "rgb(148, 0, 255)",
     "The color swatch's background is correct.");
   is(store.getState().grids[0].color, "#9400FF", "The grid color state is correct.");
 
--- a/devtools/client/inspector/grids/test/browser_grids_persist-color-palette.js
+++ b/devtools/client/inspector/grids/test/browser_grids_persist-color-palette.js
@@ -15,20 +15,20 @@ const TEST_URI = `
   <div id="grid">
     <div class="cell1">cell1</div>
     <div class="cell2">cell2</div>
   </div>
 `;
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  const { inspector, gridInspector, toolbox } = await openLayoutView();
+  const { inspector, gridInspector, layoutView, toolbox } = await openLayoutView();
   const { document: doc } = gridInspector;
   const { store } = inspector;
-  const cPicker = gridInspector.getSwatchColorPickerTooltip();
+  const cPicker = layoutView.getSwatchColorPickerTooltip();
   const swatch = doc.querySelector(".grid-color-swatch");
 
   info("Scrolling into view of the #grid color swatch.");
   swatch.scrollIntoView();
 
   info("Opening the color picker by clicking on the #grid color swatch.");
   const onColorPickerReady = cPicker.once("ready");
   swatch.click();
--- a/devtools/client/inspector/layout/components/LayoutApp.js
+++ b/devtools/client/inspector/layout/components/LayoutApp.js
@@ -37,16 +37,17 @@ class LayoutApp extends PureComponent {
     return {
       boxModel: PropTypes.shape(BoxModelTypes.boxModel).isRequired,
       getSwatchColorPickerTooltip: PropTypes.func.isRequired,
       grids: PropTypes.arrayOf(PropTypes.shape(GridTypes.grid)).isRequired,
       highlighterSettings: PropTypes.shape(GridTypes.highlighterSettings).isRequired,
       setSelectedNode: PropTypes.func.isRequired,
       showBoxModelProperties: PropTypes.bool.isRequired,
       onHideBoxModelHighlighter: PropTypes.func.isRequired,
+      onSetFlexboxOverlayColor: PropTypes.func.isRequired,
       onSetGridOverlayColor: PropTypes.func.isRequired,
       onShowBoxModelEditor: PropTypes.func.isRequired,
       onShowBoxModelHighlighter: PropTypes.func.isRequired,
       onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
       onToggleGridHighlighter: PropTypes.func.isRequired,
       onToggleShowGridLineNumbers: PropTypes.func.isRequired,
       onToggleShowInfiniteLines: PropTypes.func.isRequired,
     };
--- a/devtools/client/inspector/layout/layout.js
+++ b/devtools/client/inspector/layout/layout.js
@@ -10,23 +10,26 @@ const { Provider } = require("devtools/c
 const LayoutApp = createFactory(require("./components/LayoutApp"));
 
 const { LocalizationHelper } = require("devtools/shared/l10n");
 const INSPECTOR_L10N =
   new LocalizationHelper("devtools/client/locales/inspector.properties");
 
 loader.lazyRequireGetter(this, "FlexboxInspector", "devtools/client/inspector/flexbox/flexbox");
 loader.lazyRequireGetter(this, "GridInspector", "devtools/client/inspector/grids/grid-inspector");
+loader.lazyRequireGetter(this, "SwatchColorPickerTooltip", "devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
 
 class LayoutView {
   constructor(inspector, window) {
     this.document = window.document;
     this.inspector = inspector;
     this.store = inspector.store;
 
+    this.getSwatchColorPickerTooltip = this.getSwatchColorPickerTooltip.bind(this);
+
     this.init();
   }
 
   init() {
     if (!this.inspector) {
       return;
     }
 
@@ -37,42 +40,42 @@ class LayoutView {
 
     const {
       onHideBoxModelHighlighter,
       onShowBoxModelEditor,
       onShowBoxModelHighlighter,
       onToggleGeometryEditor,
     } = this.inspector.getPanel("boxmodel").getComponentProps();
 
-    this.flexboxInspector = new FlexboxInspector(this.inspector,
-      this.inspector.panelWin);
+    this.flexboxInspector = new FlexboxInspector(this.inspector, this.inspector.panelWin);
     const {
+      onSetFlexboxOverlayColor,
       onToggleFlexboxHighlighter,
     } = this.flexboxInspector.getComponentProps();
 
     this.gridInspector = new GridInspector(this.inspector, this.inspector.panelWin);
     const {
-      getSwatchColorPickerTooltip,
       onSetGridOverlayColor,
       onShowGridOutlineHighlight,
       onToggleGridHighlighter,
       onToggleShowGridAreas,
       onToggleShowGridLineNumbers,
       onToggleShowInfiniteLines,
     } = this.gridInspector.getComponentProps();
 
     const layoutApp = LayoutApp({
-      getSwatchColorPickerTooltip,
+      getSwatchColorPickerTooltip: this.getSwatchColorPickerTooltip,
       setSelectedNode,
       /**
        * Shows the box model properties under the box model if true, otherwise, hidden by
        * default.
        */
       showBoxModelProperties: true,
       onHideBoxModelHighlighter,
+      onSetFlexboxOverlayColor,
       onSetGridOverlayColor,
       onShowBoxModelEditor,
       onShowBoxModelHighlighter,
       onShowBoxModelHighlighterForNode,
       onShowGridOutlineHighlight,
       onToggleFlexboxHighlighter,
       onToggleGeometryEditor,
       onToggleGridHighlighter,
@@ -91,18 +94,42 @@ class LayoutView {
     // Expose the provider to let inspector.js use it in setupSidebar.
     this.provider = provider;
   }
 
   /**
    * Destruction function called when the inspector is destroyed. Cleans up references.
    */
   destroy() {
+    if (this._swatchColorPickerTooltip) {
+      this._swatchColorPickerTooltip.destroy();
+      this._swatchColorPickerTooltip = null;
+    }
+
     this.flexboxInspector.destroy();
     this.gridInspector.destroy();
 
     this.document = null;
     this.inspector = null;
     this.store = null;
   }
+
+  /**
+   * Retrieve the shared SwatchColorPicker instance.
+   */
+  getSwatchColorPickerTooltip() {
+    return this.swatchColorPickerTooltip;
+  }
+
+  get swatchColorPickerTooltip() {
+    if (!this._swatchColorPickerTooltip) {
+      this._swatchColorPickerTooltip = new SwatchColorPickerTooltip(
+        this.inspector.toolbox.doc,
+        this.inspector,
+        { supportsCssColor4ColorFunction: () => false }
+      );
+    }
+
+    return this._swatchColorPickerTooltip;
+  }
 }
 
 module.exports = LayoutView;
--- a/devtools/client/inspector/shared/highlighters-overlay.js
+++ b/devtools/client/inspector/shared/highlighters-overlay.js
@@ -211,16 +211,28 @@ class HighlightersOverlay {
     if (node == this.shapesHighlighterShown) {
       const options = Object.assign({}, this.state.shapes.options);
       options.hoverPoint = point;
       await this.showShapesHighlighter(node, options);
     }
   }
 
   /**
+   * Create a flexbox highlighter settings object for the provided nodeFront.
+   *
+   * @param  {NodeFront} nodeFront
+   *         The NodeFront for which we need highlighter settings.
+   */
+  getFlexboxHighlighterSettings(nodeFront) {
+    const { flexbox } = this.store.getState();
+    const color = flexbox.color;
+    return { color };
+  }
+
+  /**
    * Toggle the flexbox highlighter for the given flexbox container element.
    *
    * @param  {NodeFront} node
    *         The NodeFront of the flexbox container element to highlight.
    * @param  {Object} options
    *         Object used for passing options to the flexbox highlighter.
    */
   async toggleFlexboxHighlighter(node, options = {}) {
@@ -241,16 +253,18 @@ class HighlightersOverlay {
    *         Object used for passing options to the flexbox highlighter.
    */
   async showFlexboxHighlighter(node, options) {
     const highlighter = await this._getHighlighter("FlexboxHighlighter");
     if (!highlighter) {
       return;
     }
 
+    options = Object.assign({}, options, this.getFlexboxHighlighterSettings(node));
+
     const isShown = await highlighter.show(node, options);
     if (!isShown) {
       return;
     }
 
     this._toggleRuleViewIcon(node, true, ".ruleview-flex");
 
     try {
--- a/devtools/client/inspector/test/shared-head.js
+++ b/devtools/client/inspector/test/shared-head.js
@@ -146,16 +146,17 @@ function openLayoutView() {
     }
     mockHighlighter(data.toolbox);
 
     return {
       toolbox: data.toolbox,
       inspector: data.inspector,
       boxmodel: data.inspector.getPanel("boxmodel"),
       gridInspector: data.inspector.layoutview.gridInspector,
+      layoutView: data.inspector.layoutview,
       testActor: data.testActor
     };
   });
 }
 
 /**
  * Select the rule view sidebar tab on an already opened inspector panel.
  *
--- a/devtools/client/sourceeditor/test/helper_codemirror_runner.js
+++ b/devtools/client/sourceeditor/test/helper_codemirror_runner.js
@@ -23,16 +23,17 @@ function runCodeMirrorTest(browser) {
   });
 
   // Interact with the content iframe, giving it a function to
   //  1) Proxy CM test harness calls into ok() calls
   //  2) Detecting when it finishes by checking the DOM and
   //     setting a timeout to check again if not.
   /* eslint-disable max-len */
   mm.loadFrameScript("data:," +
+    "ChromeUtils.import('resource://gre/modules/Timer.jsm');" +
     "content.wrappedJSObject.mozilla_setStatus = function(statusMsg, type, customMsg) {" +
     "  sendSyncMessage('setStatus', {statusMsg: statusMsg, type: type, customMsg: customMsg});" +
     "};" +
     "function check() { " +
     "  var doc = content.document; var out = doc.getElementById('status'); " +
     "  if (!out || !out.classList.contains('done')) { return setTimeout(check, 100); }" +
     "  sendAsyncMessage('done', { failed: content.wrappedJSObject.failed });" +
     "}" +
--- a/devtools/client/themes/layout.css
+++ b/devtools/client/themes/layout.css
@@ -125,30 +125,32 @@
 .grid-outline-text-icon {
   background: url("chrome://devtools/skin/images/sad-face.svg");
   margin-inline-end: 5px;
   width: 16px;
   height: 16px;
 }
 
 /**
- * Grid Item
+ * Flexbox and Grid Item
  */
 
+.flexbox-color-swatch,
 .grid-color-swatch {
   width: 12px;
   height: 12px;
   margin-inline-start: -1px;
   border: 1px solid var(--theme-highlight-gray);
   border-radius: 50%;
   cursor: pointer;
   display: inline-block;
   vertical-align: middle;
 }
 
+.flexbox-color-value,
 .grid-color-value {
   display: none;
 }
 
 /**
  * Settings Item
  */
 
--- a/devtools/server/actors/highlighters/flexbox.js
+++ b/devtools/server/actors/highlighters/flexbox.js
@@ -55,22 +55,25 @@ const gCachedFlexboxPattern = new Map();
 const FLEXBOX = "flexbox";
 const JUSTIFY_CONTENT = "justify-content";
 
 /**
  * The FlexboxHighlighter is the class that overlays a visual canvas on top of
  * display: [inline-]flex elements.
  *
  * Available Options:
+ * - color(colorValue)
+ *     @param  {String} colorValue
+ *     The color that should be used to draw the highlighter for this flexbox.
  * - showAlignment(isShown)
- *   @param  {Boolean} isShown
- *   Shows the alignment in the flexbox highlighter.
+ *     @param  {Boolean} isShown
+ *     Shows the alignment in the flexbox highlighter.
  * - showFlexBasis(isShown)
- *   @param  {Boolean} isShown
- *   Shows the flex basis in the flexbox highlighter.
+ *     @param  {Boolean} isShown
+ *     Shows the flex basis in the flexbox highlighter.
  */
 class FlexboxHighlighter extends AutoRefreshHighlighter {
   constructor(highlighterEnv) {
     super(highlighterEnv);
 
     this.ID_CLASS_PREFIX = "flexbox-";
 
     this.markup = new CanvasFrameAnonymousContentHelper(this.highlighterEnv,
@@ -164,16 +167,20 @@ class FlexboxHighlighter extends AutoRef
     drawRect(this.ctx, left, top, right, bottom, this.currentMatrix);
     this.ctx.fill();
   }
 
   get canvas() {
     return this.getElement("canvas");
   }
 
+  get color() {
+    return this.options.color || DEFAULT_COLOR;
+  }
+
   get ctx() {
     return this.canvas.getCanvasContext("2d");
   }
 
   getElement(id) {
     return this.markup.getElement(this.ID_CLASS_PREFIX + id);
   }
 
@@ -206,17 +213,17 @@ class FlexboxHighlighter extends AutoRef
     ctx.save();
     ctx.setLineDash(FLEXBOX_CONTAINER_PATTERN_LINE_DISH);
     ctx.beginPath();
     ctx.translate(.5, .5);
 
     ctx.moveTo(0, 0);
     ctx.lineTo(width, height);
 
-    ctx.strokeStyle = DEFAULT_COLOR;
+    ctx.strokeStyle = this.color;
     ctx.stroke();
     ctx.restore();
 
     const pattern = ctx.createPattern(canvas, "repeat");
     flexboxPatternMap.set(FLEXBOX, pattern);
     gCachedFlexboxPattern.set(devicePixelRatio, flexboxPatternMap);
 
     return pattern;
@@ -253,17 +260,17 @@ class FlexboxHighlighter extends AutoRef
     ctx.save();
     ctx.setLineDash(FLEXBOX_CONTAINER_PATTERN_LINE_DISH);
     ctx.beginPath();
     ctx.translate(.5, .5);
 
     ctx.moveTo(0, height);
     ctx.lineTo(width, 0);
 
-    ctx.strokeStyle = DEFAULT_COLOR;
+    ctx.strokeStyle = this.color;
     ctx.stroke();
     ctx.restore();
 
     const pattern = ctx.createPattern(canvas, "repeat");
     flexboxPatternMap.set(JUSTIFY_CONTENT, pattern);
     gCachedFlexboxPattern.set(devicePixelRatio, flexboxPatternMap);
 
     return pattern;
@@ -388,17 +395,17 @@ class FlexboxHighlighter extends AutoRef
     const offset = (lineWidth / 2) % 1;
     const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
     const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
 
     this.ctx.save();
     this.ctx.translate(offset - canvasX, offset - canvasY);
     this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.alignItems.lineDash);
     this.ctx.lineWidth = lineWidth * 3;
-    this.ctx.strokeStyle = DEFAULT_COLOR;
+    this.ctx.strokeStyle = this.color;
 
     const { bounds } = this.currentQuads.content[0];
     const isColumn = this.flexDirection.startsWith("column");
     const options = { matrix: this.currentMatrix };
 
     for (const flexLine of this.flexData.lines) {
       const { crossStart, crossSize } = flexLine;
 
@@ -488,17 +495,17 @@ class FlexboxHighlighter extends AutoRef
     const offset = (lineWidth / 2) % 1;
     const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
     const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
 
     this.ctx.save();
     this.ctx.translate(offset - canvasX, offset - canvasY);
     this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.edge.lineDash);
     this.ctx.lineWidth = lineWidth;
-    this.ctx.strokeStyle = DEFAULT_COLOR;
+    this.ctx.strokeStyle = this.color;
 
     const { bounds } = this.currentQuads.content[0];
     drawRect(this.ctx, 0, 0, bounds.width, bounds.height, this.currentMatrix);
 
     this.ctx.stroke();
     this.ctx.restore();
   }
 
@@ -512,17 +519,17 @@ class FlexboxHighlighter extends AutoRef
     const offset = (lineWidth / 2) % 1;
     const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
     const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
 
     this.ctx.save();
     this.ctx.translate(offset - canvasX, offset - canvasY);
     this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.edge.lineDash);
     this.ctx.lineWidth = 0;
-    this.ctx.strokeStyle = DEFAULT_COLOR;
+    this.ctx.strokeStyle = this.color;
     this.ctx.fillStyle = this.getFlexContainerPattern(devicePixelRatio);
 
     const { bounds } = this.currentQuads.content[0];
     drawRect(this.ctx, 0, 0, bounds.width, bounds.height, this.currentMatrix);
 
     // Find current angle of outer flex element by measuring the angle of two arbitrary
     // points, then rotate canvas, so the hash pattern stays 45deg to the boundary.
     const p1 = apply(this.currentMatrix, [0, 0]);
@@ -567,17 +574,17 @@ class FlexboxHighlighter extends AutoRef
     const offset = (lineWidth / 2) % 1;
     const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
     const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
 
     this.ctx.save();
     this.ctx.translate(offset - canvasX, offset - canvasY);
     this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.item.lineDash);
     this.ctx.lineWidth = lineWidth;
-    this.ctx.strokeStyle = DEFAULT_COLOR;
+    this.ctx.strokeStyle = this.color;
 
     const { bounds } = this.currentQuads.content[0];
 
     for (const flexLine of this.flexData.lines) {
       for (const flexItem of flexLine.items) {
         const quads = flexItem.quads;
         if (!quads.length) {
           continue;
@@ -610,17 +617,17 @@ class FlexboxHighlighter extends AutoRef
     const lineWidth = getDisplayPixelRatio(this.win);
     const offset = (lineWidth / 2) % 1;
     const canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
     const canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
 
     this.ctx.save();
     this.ctx.translate(offset - canvasX, offset - canvasY);
     this.ctx.lineWidth = lineWidth;
-    this.ctx.strokeStyle = DEFAULT_COLOR;
+    this.ctx.strokeStyle = this.color;
 
     const { bounds } = this.currentQuads.content[0];
     const isColumn = this.flexDirection.startsWith("column");
     const options = { matrix: this.currentMatrix };
 
     for (const flexLine of this.flexData.lines) {
       const { crossStart, crossSize } = flexLine;
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -194,18 +194,18 @@
 #include "nsView.h"
 #include "nsViewManager.h"
 #include "nsViewSourceHandler.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsWidgetsCID.h"
 #include "nsXULAppAPI.h"
 
 #include "GeckoProfiler.h"
+#include "mozilla/NullPrincipal.h"
 #include "Navigator.h"
-#include "NullPrincipal.h"
 #include "prenv.h"
 #include "URIUtils.h"
 
 #include "timeline/JavascriptTimelineMarker.h"
 
 #ifdef MOZ_PLACES
 #include "nsIFaviconService.h"
 #include "mozIPlacesPendingOperation.h"
--- a/dom/base/DOMParser.cpp
+++ b/dom/base/DOMParser.cpp
@@ -14,18 +14,18 @@
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsCRT.h"
 #include "nsStreamUtils.h"
 #include "nsContentUtils.h"
 #include "nsDOMJSUtils.h"
 #include "nsError.h"
 #include "nsPIDOMWindow.h"
-#include "NullPrincipal.h"
 #include "mozilla/LoadInfo.h"
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 DOMParser::DOMParser(nsIGlobalObject* aOwner, nsIPrincipal* aDocPrincipal,
                      nsIURI* aDocumentURI, nsIURI* aBaseURI)
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -26,17 +26,17 @@
 #include "nsError.h"
 #include "nsReadableUtils.h"
 #include "nsITextToSubURI.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/Likely.h"
 #include "nsCycleCollectionParticipant.h"
-#include "NullPrincipal.h"
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/LocationBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 namespace mozilla {
 namespace dom {
 
 Location::Location(nsPIDOMWindowInner* aWindow, nsIDocShell *aDocShell)
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -153,16 +153,17 @@
 #include "nsIIOService.h"
 #include "nsILoadContext.h"
 #include "nsILoadGroup.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMIMEHeaderParam.h"
 #include "nsIMIMEService.h"
 #include "nsINode.h"
 #include "mozilla/dom/NodeInfo.h"
+#include "mozilla/NullPrincipal.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsIParser.h"
 #include "nsIParserUtils.h"
 #include "nsIPermissionManager.h"
 #include "nsIPluginHost.h"
@@ -182,17 +183,16 @@
 #include "nsIWebNavigation.h"
 #include "nsIWindowMediator.h"
 #include "nsIXPConnect.h"
 #include "nsJSUtils.h"
 #include "nsMappedAttributes.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsNodeInfoManager.h"
-#include "NullPrincipal.h"
 #include "nsParserCIID.h"
 #include "nsParserConstants.h"
 #include "nsPIDOMWindow.h"
 #include "nsPresContext.h"
 #include "nsPrintfCString.h"
 #include "nsSandboxFlags.h"
 #include "nsScriptSecurityManager.h"
 #include "nsSerializationHelper.h"
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -105,17 +105,17 @@
 #include "nsIInputStreamChannel.h"
 #include "nsIAuthPrompt.h"
 #include "nsIAuthPrompt2.h"
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "ExpandedPrincipal.h"
-#include "NullPrincipal.h"
+#include "mozilla/NullPrincipal.h"
 
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsFocusManager.h"
 
 // for radio group stuff
 #include "nsIRadioVisitor.h"
 #include "nsIFormControl.h"
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -39,17 +39,16 @@
 #include "nsIScrollableFrame.h"
 #include "nsSubDocumentFrame.h"
 #include "nsError.h"
 #include "nsISHistory.h"
 #include "nsISHistoryInternal.h"
 #include "nsIXULWindow.h"
 #include "nsIMozBrowserFrame.h"
 #include "nsISHistory.h"
-#include "NullPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsGlobalWindow.h"
 #include "nsHTMLDocument.h"
 #include "nsPIWindowRoot.h"
 #include "nsLayoutUtils.h"
 #include "nsMappedAttributes.h"
 #include "nsView.h"
 #include "nsBaseWidget.h"
@@ -71,16 +70,17 @@
 #include "ClientLayerManager.h"
 
 #include "ContentParent.h"
 #include "TabParent.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/HTMLEditor.h"
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FrameLoaderBinding.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layout/RenderFrameParent.h"
 #include "nsGenericHTMLFrameElement.h"
@@ -97,17 +97,17 @@
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/GroupedHistoryEvent.h"
 #include "mozilla/dom/ParentSHistory.h"
 #include "mozilla/dom/ChildSHistory.h"
 
 #include "mozilla/dom/HTMLBodyElement.h"
 
-#include "ContentPrincipal.h"
+#include "mozilla/ContentPrincipal.h"
 
 #ifdef XP_WIN
 #include "mozilla/plugins/PPluginWidgetParent.h"
 #include "../plugins/ipc/PluginWidgetParent.h"
 #endif
 
 #ifdef MOZ_XUL
 #include "nsXULPopupManager.h"
--- a/dom/base/nsNodeInfoManager.cpp
+++ b/dom/base/nsNodeInfoManager.cpp
@@ -8,16 +8,17 @@
  * A class for handing out nodeinfos and ensuring sharing of them as needed.
  */
 
 #include "nsNodeInfoManager.h"
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "mozilla/dom/NodeInfoInlines.h"
+#include "mozilla/NullPrincipal.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsAtom.h"
 #include "nsIDocument.h"
 #include "nsIPrincipal.h"
 #include "nsIURI.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
@@ -25,17 +26,16 @@
 #include "nsComponentManagerUtils.h"
 #include "nsLayoutStatics.h"
 #include "nsBindingManager.h"
 #include "nsHashKeys.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsNameSpaceManager.h"
 #include "nsDocument.h"
 #include "nsWindowSizes.h"
-#include "NullPrincipal.h"
 
 using namespace mozilla;
 using mozilla::dom::NodeInfo;
 
 #include "mozilla/Logging.h"
 
 static LazyLogModule gNodeInfoManagerLeakPRLog("NodeInfoManagerLeak");
 static const uint32_t kInitialNodeInfoHashSize = 32;
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -9,24 +9,24 @@
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/BindingStyleRule.h"
 #include "mozilla/DeclarationBlock.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/css/Rule.h"
 #include "mozilla/dom/CSSRuleList.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/SRIMetadata.h"
+#include "mozilla/NullPrincipal.h"
 #include "nsCSSPropertyID.h"
 #include "nsUnicharInputStream.h"
 #include "nsAttrName.h"
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsNetUtil.h"
 #include "nsComponentManagerUtils.h"
-#include "NullPrincipal.h"
 #include "nsContentUtils.h"
 #include "nsIParserUtils.h"
 #include "nsIDocument.h"
 #include "nsQueryObject.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
--- a/dom/bindings/SimpleGlobalObject.cpp
+++ b/dom/bindings/SimpleGlobalObject.cpp
@@ -5,23 +5,23 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SimpleGlobalObject.h"
 
 #include "jsapi.h"
 #include "js/Class.h"
 
 #include "nsJSPrincipals.h"
-#include "NullPrincipal.h"
 #include "nsThreadUtils.h"
 #include "nsContentUtils.h"
 
 #include "xpcprivate.h"
 
 #include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/NullPrincipal.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(SimpleGlobalObject)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SimpleGlobalObject)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
--- a/dom/console/ConsoleUtils.cpp
+++ b/dom/console/ConsoleUtils.cpp
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ConsoleUtils.h"
 #include "ConsoleCommon.h"
 
 #include "mozilla/ClearOnShutdown.h"
-#include "NullPrincipal.h"
+#include "mozilla/NullPrincipal.h"
 
 namespace mozilla {
 namespace dom {
 
 namespace {
 
 StaticRefPtr<ConsoleUtils> gConsoleUtilsService;
 
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -18,22 +18,22 @@
 #include "IDBTransaction.h"
 #include "IndexedDatabase.h"
 #include "IndexedDatabaseInlines.h"
 #include "IndexedDatabaseManager.h"
 #include "js/Class.h"
 #include "js/Date.h"
 #include "js/StructuredClone.h"
 #include "KeyPath.h"
-#include "NullPrincipal.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EndianUtils.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/JSObjectHolder.h"
 #include "mozilla/Move.h"
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DOMStringList.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileBlobImpl.h"
 #include "mozilla/dom/IDBMutableFileBinding.h"
 #include "mozilla/dom/BlobBinding.h"
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -12,16 +12,17 @@
 
 #include "GeckoProfiler.h"
 #include "TabChild.h"
 #include "HandlerServiceChild.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/BackgroundHangMonitor.h"
 #include "mozilla/LookAndFeel.h"
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ProcessHangMonitorIPC.h"
 #include "mozilla/Unused.h"
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/TelemetryIPC.h"
 #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
 #include "mozilla/docshell/OfflineCacheUpdateChild.h"
 #include "mozilla/dom/ClientManager.h"
@@ -80,17 +81,16 @@
 #include "mozilla/widget/WidgetMessageUtils.h"
 #include "nsBaseDragService.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/WebBrowserPersistDocumentChild.h"
 #include "mozilla/HangDetails.h"
 #include "imgLoader.h"
 #include "GMPServiceChild.h"
-#include "NullPrincipal.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIStringBundle.h"
 #include "nsIWorkerDebuggerManager.h"
 
 #if !defined(XP_WIN)
 #include "mozilla/Omnijar.h"
 #endif
 
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -90,20 +90,20 @@
 #include "gfxPrefs.h"
 #include "nsILoginManagerPrompter.h"
 #include "nsPIWindowRoot.h"
 #include "nsIAuthPrompt2.h"
 #include "gfxDrawable.h"
 #include "ImageOps.h"
 #include "UnitTransforms.h"
 #include <algorithm>
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/WebBrowserPersistDocumentParent.h"
 #include "ProcessPriorityManager.h"
 #include "nsString.h"
-#include "NullPrincipal.h"
 
 #ifdef XP_WIN
 #include "mozilla/plugins/PluginWidgetParent.h"
 #endif
 
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
 #include "mozilla/a11y/AccessibleWrap.h"
 #include "mozilla/a11y/Compatibility.h"
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -31,16 +31,17 @@
 #include "nsIKeyModule.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsIInputStream.h"
 #include "nsILineInputStream.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsPIDOMWindow.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/MozPromise.h"
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Types.h"
 #include "mozilla/PeerIdentity.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/MediaStreamBinding.h"
@@ -52,17 +53,16 @@
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/media/MediaTaskUtils.h"
 #include "MediaTrackConstraints.h"
 #include "VideoUtils.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 #include "Latency.h"
 #include "nsProxyRelease.h"
-#include "NullPrincipal.h"
 #include "nsVariant.h"
 
 // For snprintf
 #include "mozilla/Sprintf.h"
 
 #include "nsJSUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsIUUIDGenerator.h"
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -45,16 +45,17 @@
 #include "nsPluginLogging.h"
 #include "nsIScriptChannel.h"
 #include "nsIBlocklistService.h"
 #include "nsVersionComparator.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsICategoryManager.h"
 #include "nsPluginStreamListenerPeer.h"
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FakePluginTagInitBinding.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/plugins/PluginBridge.h"
 #include "mozilla/plugins/PluginTypes.h"
@@ -91,17 +92,16 @@
 #include "nsPluginNativeWindow.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Telemetry.h"
 #include "nsIImageLoadingContent.h"
 #include "mozilla/Preferences.h"
 #include "nsVersionComparator.h"
-#include "NullPrincipal.h"
 
 #include "mozilla/dom/Promise.h"
 
 #if defined(XP_WIN)
 #include "nsIWindowMediator.h"
 #include "nsIBaseWindow.h"
 #include "windows.h"
 #include "winbase.h"
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -26,17 +26,17 @@
 #include "nsIDocument.h"
 #include "nsIWebNavigation.h"
 #include "nsContentUtils.h"
 #include "nsNetUtil.h"
 #include "nsPluginNativeWindow.h"
 #include "GeckoProfiler.h"
 #include "nsPluginInstanceOwner.h"
 #include "nsDataHashtable.h"
-#include "NullPrincipal.h"
+#include "mozilla/NullPrincipal.h"
 
 // nsPluginStreamListenerPeer
 
 NS_IMPL_ISUPPORTS(nsPluginStreamListenerPeer,
                   nsIStreamListener,
                   nsIRequestObserver,
                   nsIHttpHeaderVisitor,
                   nsISupportsWeakReference,
--- a/dom/security/test/gtest/TestSecureContext.cpp
+++ b/dom/security/test/gtest/TestSecureContext.cpp
@@ -8,17 +8,19 @@
 
 #include <string.h>
 #include <stdlib.h>
 
 #include "nsContentSecurityManager.h"
 #include "nsContentUtils.h"
 #include "nsIPrincipal.h"
 #include "nsScriptSecurityManager.h"
-#include "NullPrincipal.h"
+#include "mozilla/NullPrincipal.h"
+
+using namespace mozilla;
 
 static const uint32_t kURIMaxLength = 64;
 
 struct TestExpectations {
   char uri[kURIMaxLength ];
   bool expectedResult;
 };
 
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/BasePrincipal.h"
+#include "mozilla/ContentPrincipal.h"
 #include "mozilla/Services.h"
 #include "mozilla/SystemGroup.h"
 #include "mozilla/Unused.h"
 #include "nsPermissionManager.h"
 #include "nsPermission.h"
 #include "nsCRT.h"
 #include "nsNetUtil.h"
 #include "nsCOMArray.h"
@@ -39,17 +40,16 @@
 #include "nsReadLine.h"
 #include "mozilla/Telemetry.h"
 #include "nsIConsoleService.h"
 #include "nsINavHistoryService.h"
 #include "nsToolkitCompsCID.h"
 #include "nsIObserverService.h"
 #include "nsPrintfCString.h"
 #include "mozilla/AbstractThread.h"
-#include "ContentPrincipal.h"
 #include "ExpandedPrincipal.h"
 
 static nsPermissionManager *gPermissionManager = nullptr;
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static bool
--- a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
+++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
@@ -11,25 +11,26 @@
 #include "nsIServiceManager.h"
 #include "nsIComponentManager.h"
 #include "nsString.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nspr.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Maybe.h"
+#include "mozilla/NullPrincipal.h"
 #include "nsContentUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsJSPrincipals.h"
 #include "nsIScriptError.h"
 #include "js/Wrapper.h"
-#include "NullPrincipal.h"
 
 extern mozilla::LazyLogModule MCD;
 using mozilla::AutoSafeJSContext;
+using mozilla::NullPrincipal;
 using mozilla::dom::AutoJSAPI;
 
 //*****************************************************************************
 
 static JS::PersistentRooted<JSObject *> autoconfigSystemSb;
 static JS::PersistentRooted<JSObject *> autoconfigSb;
 static bool sandboxEnabled;
 
--- a/gfx/2d/FilterNodeD2D1.cpp
+++ b/gfx/2d/FilterNodeD2D1.cpp
@@ -467,16 +467,17 @@ GetD2D1PropsForIntSize(FilterType aType,
     break;
   }
   return false;
 }
 
 static inline REFCLSID GetCLDIDForFilterType(FilterType aType)
 {
   switch (aType) {
+  case FilterType::OPACITY:
   case FilterType::COLOR_MATRIX:
     return CLSID_D2D1ColorMatrix;
   case FilterType::TRANSFORM:
     return CLSID_D2D12DAffineTransform;
   case FilterType::BLEND:
     return CLSID_D2D1Blend;
   case FilterType::MORPHOLOGY:
     return CLSID_D2D1Morphology;
@@ -580,16 +581,20 @@ FilterNodeD2D1::Create(ID2D1DeviceContex
     gfxCriticalErrorOnce() << "Failed to create effect for FilterType: " << hexa(hr);
     return nullptr;
   }
 
   if (aType == FilterType::ARITHMETIC_COMBINE) {
     effect->SetValue(D2D1_ARITHMETICCOMPOSITE_PROP_CLAMP_OUTPUT, TRUE);
   }
 
+  if (aType == FilterType::OPACITY) {
+    return MakeAndAddRef<FilterNodeOpacityD2D1>(effect, aType);
+  }
+
   RefPtr<FilterNodeD2D1> filter = new FilterNodeD2D1(effect, aType);
 
   if (HasUnboundedOutputRegion(aType)) {
     // These filters can produce non-transparent output from transparent
     // input pixels, and we want them to have an unbounded output region.
     filter = new FilterNodeExtendInputAdapterD2D1(aDC, filter, aType);
   }
 
@@ -865,16 +870,30 @@ void
 FilterNodeD2D1::SetAttribute(uint32_t aIndex, const Matrix &aMatrix)
 {
   UINT32 input = GetD2D1PropForAttribute(mType, aIndex);
   MOZ_ASSERT(input < mEffect->GetPropertyCount());
 
   mEffect->SetValue(input, D2DMatrix(aMatrix));
 }
 
+void
+FilterNodeOpacityD2D1::SetAttribute(uint32_t aIndex, Float aValue)
+{
+  D2D1_MATRIX_5X4_F matrix = D2D1::Matrix5x4F(aValue, 0, 0, 0,
+                                              0, aValue, 0, 0,
+                                              0, 0, aValue, 0,
+                                              0, 0, 0, aValue,
+                                              0, 0, 0, 0);
+
+  mEffect->SetValue(D2D1_COLORMATRIX_PROP_COLOR_MATRIX, matrix);
+  mEffect->SetValue(D2D1_COLORMATRIX_PROP_ALPHA_MODE, D2D1_COLORMATRIX_ALPHA_MODE_STRAIGHT);
+}
+
+
 FilterNodeConvolveD2D1::FilterNodeConvolveD2D1(ID2D1DeviceContext *aDC)
   : FilterNodeD2D1(nullptr, FilterType::CONVOLVE_MATRIX)
   , mEdgeMode(EDGE_MODE_DUPLICATE)
 {
   // Correctly handling the interaction of edge mode and source rect is a bit
   // tricky with D2D1 effects. We want the edge mode to only apply outside of
   // the source rect (as specified by the ATT_CONVOLVE_MATRIX_SOURCE_RECT
   // attribute). So if our input surface or filter is smaller than the source
--- a/gfx/2d/FilterNodeD2D1.h
+++ b/gfx/2d/FilterNodeD2D1.h
@@ -103,16 +103,27 @@ private:
   RefPtr<ID2D1Effect> mExtendInputEffect;
   RefPtr<ID2D1Effect> mBorderEffect;
   ConvolveMatrixEdgeMode mEdgeMode;
   IntPoint mTarget;
   IntSize mKernelSize;
   IntRect mSourceRect;
 };
 
+class FilterNodeOpacityD2D1 : public FilterNodeD2D1
+{
+public:
+  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeOpacityD2D1, override)
+  explicit FilterNodeOpacityD2D1(ID2D1Effect *aEffect, FilterType aType)
+    : FilterNodeD2D1(aEffect, aType)
+  {}
+
+  virtual void SetAttribute(uint32_t aIndex, Float aValue) override;
+};
+
 class FilterNodeExtendInputAdapterD2D1 : public FilterNodeD2D1
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeExtendInputAdapterD2D1, override)
   FilterNodeExtendInputAdapterD2D1(ID2D1DeviceContext *aDC, FilterNodeD2D1 *aFilterNode, FilterType aType);
 
   virtual ID2D1Effect* InputEffect() override { return mExtendInputEffect.get(); }
   virtual ID2D1Effect* OutputEffect() override { return mWrappedFilterNode->OutputEffect(); }
--- a/gfx/2d/FilterNodeSoftware.cpp
+++ b/gfx/2d/FilterNodeSoftware.cpp
@@ -509,16 +509,19 @@ FilterNodeSoftware::Create(FilterType aT
       filter = new FilterNodeCropSoftware();
       break;
     case FilterType::PREMULTIPLY:
       filter = new FilterNodePremultiplySoftware();
       break;
     case FilterType::UNPREMULTIPLY:
       filter = new FilterNodeUnpremultiplySoftware();
       break;
+    case FilterType::OPACITY:
+      filter = new FilterNodeOpacitySoftware();
+      break;
     case FilterType::POINT_DIFFUSE:
       filter = new FilterNodeLightingSoftware<PointLightSoftware, DiffuseLightingSoftware>("FilterNodeLightingSoftware<PointLight, DiffuseLighting>");
       break;
     case FilterType::POINT_SPECULAR:
       filter = new FilterNodeLightingSoftware<PointLightSoftware, SpecularLightingSoftware>("FilterNodeLightingSoftware<PointLight, SpecularLighting>");
       break;
     case FilterType::SPOT_DIFFUSE:
       filter = new FilterNodeLightingSoftware<SpotLightSoftware, DiffuseLightingSoftware>("FilterNodeLightingSoftware<SpotLight, DiffuseLighting>");
@@ -1427,16 +1430,54 @@ Unpremultiply(DataSourceSurface* aSurfac
   int32_t targetStride = targetMap.GetStride();
 
   FilterProcessing::DoUnpremultiplicationCalculation(
     size, targetData, targetStride, inputData, inputStride);
 
   return target.forget();
 }
 
+static already_AddRefed<DataSourceSurface>
+Opacity(DataSourceSurface* aSurface, Float aValue)
+{
+  if (aValue == 1.0f) {
+    RefPtr<DataSourceSurface> surface(aSurface);
+    return surface.forget();
+  }
+
+  IntSize size = aSurface->GetSize();
+  RefPtr<DataSourceSurface> target =
+    Factory::CreateDataSourceSurface(size, aSurface->GetFormat());
+  if (MOZ2D_WARN_IF(!target)) {
+    return nullptr;
+  }
+
+  DataSourceSurface::ScopedMap inputMap(aSurface, DataSourceSurface::READ);
+  DataSourceSurface::ScopedMap targetMap(target, DataSourceSurface::WRITE);
+  if (MOZ2D_WARN_IF(!inputMap.IsMapped() || !targetMap.IsMapped())) {
+    return nullptr;
+  }
+
+  uint8_t* inputData = inputMap.GetData();
+  int32_t inputStride = inputMap.GetStride();
+  uint8_t* targetData = targetMap.GetData();
+  int32_t targetStride = targetMap.GetStride();
+
+  if (aSurface->GetFormat() == SurfaceFormat::A8) {
+    FilterProcessing::DoOpacityCalculationA8(
+      size, targetData, targetStride, inputData, inputStride, aValue);
+  } else {
+    MOZ_ASSERT(aSurface->GetFormat() == SurfaceFormat::B8G8R8A8);
+    FilterProcessing::DoOpacityCalculation(
+      size, targetData, targetStride, inputData, inputStride, aValue);
+  }
+
+  return target.forget();
+}
+
 already_AddRefed<DataSourceSurface>
 FilterNodeColorMatrixSoftware::Render(const IntRect& aRect)
 {
   RefPtr<DataSourceSurface> input =
     GetInputDataSourceSurface(IN_COLOR_MATRIX_IN, aRect, NEED_COLOR_CHANNELS);
   if (!input) {
     return nullptr;
   }
@@ -3207,16 +3248,54 @@ FilterNodeUnpremultiplySoftware::Request
 }
 
 IntRect
 FilterNodeUnpremultiplySoftware::GetOutputRectInRect(const IntRect& aRect)
 {
   return GetInputRectInRect(IN_UNPREMULTIPLY_IN, aRect);
 }
 
+void
+FilterNodeOpacitySoftware::SetAttribute(uint32_t aIndex,
+                                        Float aValue)
+{
+  MOZ_ASSERT(aIndex == ATT_OPACITY_VALUE);
+  mValue = aValue;
+  Invalidate();
+}
+
+int32_t
+FilterNodeOpacitySoftware::InputIndex(uint32_t aInputEnumIndex)
+{
+  switch (aInputEnumIndex) {
+  case IN_OPACITY_IN: return 0;
+  default: return -1;
+  }
+}
+
+already_AddRefed<DataSourceSurface>
+FilterNodeOpacitySoftware::Render(const IntRect& aRect)
+{
+  RefPtr<DataSourceSurface> input =
+    GetInputDataSourceSurface(IN_OPACITY_IN, aRect);
+  return input ? Opacity(input, mValue) : nullptr;
+}
+
+void
+FilterNodeOpacitySoftware::RequestFromInputsForRect(const IntRect &aRect)
+{
+  RequestInputRect(IN_OPACITY_IN, aRect);
+}
+
+IntRect
+FilterNodeOpacitySoftware::GetOutputRectInRect(const IntRect& aRect)
+{
+  return GetInputRectInRect(IN_OPACITY_IN, aRect);
+}
+
 bool
 PointLightSoftware::SetAttribute(uint32_t aIndex, const Point3D &aPoint)
 {
   switch (aIndex) {
     case ATT_POINT_LIGHT_POSITION:
       mPosition = aPoint;
       break;
     default:
--- a/gfx/2d/FilterNodeSoftware.h
+++ b/gfx/2d/FilterNodeSoftware.h
@@ -683,16 +683,32 @@ public:
   virtual const char* GetName() override { return "Unpremultiply"; }
 protected:
   virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
   virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
   virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
   virtual void RequestFromInputsForRect(const IntRect &aRect) override;
 };
 
+class FilterNodeOpacitySoftware : public FilterNodeSoftware
+{
+public:
+  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeOpacitySoftware, override)
+  virtual const char* GetName() override { return "Opacity"; }
+  using FilterNodeSoftware::SetAttribute;
+  virtual void SetAttribute(uint32_t aIndex, Float aValue) override;
+protected:
+  virtual already_AddRefed<DataSourceSurface> Render(const IntRect& aRect) override;
+  virtual IntRect GetOutputRectInRect(const IntRect& aRect) override;
+  virtual int32_t InputIndex(uint32_t aInputEnumIndex) override;
+  virtual void RequestFromInputsForRect(const IntRect &aRect) override;
+
+  Float mValue = 1.0f;
+};
+
 template<typename LightType, typename LightingType>
 class FilterNodeLightingSoftware : public FilterNodeSoftware
 {
 public:
 #if defined(MOZILLA_INTERNAL_API) && (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
   // Helpers for refcounted
   virtual const char* typeName() const override { return mTypeName; }
   virtual size_t typeSize() const override { return sizeof(*this); }
--- a/gfx/2d/FilterProcessing.cpp
+++ b/gfx/2d/FilterProcessing.cpp
@@ -231,16 +231,44 @@ FilterProcessing::DoUnpremultiplicationC
       aSize, aTargetData, aTargetStride, aSourceData, aSourceStride);
 #endif
   } else {
     DoUnpremultiplicationCalculation_Scalar(
       aSize, aTargetData, aTargetStride, aSourceData, aSourceStride);
   }
 }
 
+void
+FilterProcessing::DoOpacityCalculation(const IntSize& aSize,
+  uint8_t* aTargetData, int32_t aTargetStride,
+  uint8_t* aSourceData, int32_t aSourceStride,
+  Float aValue)
+{
+  if (Factory::HasSSE2()) {
+#ifdef USE_SSE2
+    DoOpacityCalculation_SSE2(
+      aSize, aTargetData, aTargetStride, aSourceData, aSourceStride, aValue);
+#endif
+  }
+  else {
+    DoOpacityCalculation_Scalar(
+      aSize, aTargetData, aTargetStride, aSourceData, aSourceStride, aValue);
+  }
+}
+
+void
+FilterProcessing::DoOpacityCalculationA8(const IntSize& aSize,
+  uint8_t* aTargetData, int32_t aTargetStride,
+  uint8_t* aSourceData, int32_t aSourceStride,
+  Float aValue)
+{
+  DoOpacityCalculationA8_Scalar(
+    aSize, aTargetData, aTargetStride, aSourceData, aSourceStride, aValue);
+}
+
 already_AddRefed<DataSourceSurface>
 FilterProcessing::RenderTurbulence(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
                                    int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect)
 {
   if (Factory::HasSSE2()) {
 #ifdef USE_SSE2
     return RenderTurbulence_SSE2(aSize, aOffset, aBaseFrequency, aSeed, aNumOctaves, aType, aStitch, aTileRect);
 #endif
--- a/gfx/2d/FilterProcessing.h
+++ b/gfx/2d/FilterProcessing.h
@@ -54,16 +54,24 @@ public:
     CombineColorChannels(DataSourceSurface* aChannel0, DataSourceSurface* aChannel1,
                          DataSourceSurface* aChannel2, DataSourceSurface* aChannel3);
   static void DoPremultiplicationCalculation(const IntSize& aSize,
                                         uint8_t* aTargetData, int32_t aTargetStride,
                                         uint8_t* aSourceData, int32_t aSourceStride);
   static void DoUnpremultiplicationCalculation(const IntSize& aSize,
                                                uint8_t* aTargetData, int32_t aTargetStride,
                                                uint8_t* aSourceData, int32_t aSourceStride);
+  static void DoOpacityCalculation(const IntSize& aSize,
+                                   uint8_t* aTargetData, int32_t aTargetStride,
+                                   uint8_t* aSourceData, int32_t aSourceStride,
+                                   Float aValue);
+  static void DoOpacityCalculationA8(const IntSize& aSize,
+                                     uint8_t* aTargetData, int32_t aTargetStride,
+                                     uint8_t* aSourceData, int32_t aSourceStride,
+                                     Float aValue);
   static already_AddRefed<DataSourceSurface>
     RenderTurbulence(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
                      int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect);
   static already_AddRefed<DataSourceSurface>
     ApplyArithmeticCombine(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4);
 
 protected:
   static void ExtractAlpha_Scalar(const IntSize& size, uint8_t* sourceData, int32_t sourceStride, uint8_t* alphaData, int32_t alphaStride);
@@ -82,16 +90,24 @@ protected:
   static void SeparateColorChannels_Scalar(const IntSize &size, uint8_t* sourceData, int32_t sourceStride, uint8_t* channel0Data, uint8_t* channel1Data, uint8_t* channel2Data, uint8_t* channel3Data, int32_t channelStride);
   static void CombineColorChannels_Scalar(const IntSize &size, int32_t resultStride, uint8_t* resultData, int32_t channelStride, uint8_t* channel0Data, uint8_t* channel1Data, uint8_t* channel2Data, uint8_t* channel3Data);
   static void DoPremultiplicationCalculation_Scalar(const IntSize& aSize,
                                         uint8_t* aTargetData, int32_t aTargetStride,
                                         uint8_t* aSourceData, int32_t aSourceStride);
   static void DoUnpremultiplicationCalculation_Scalar(const IntSize& aSize,
                                                uint8_t* aTargetData, int32_t aTargetStride,
                                                uint8_t* aSourceData, int32_t aSourceStride);
+  static void DoOpacityCalculation_Scalar(const IntSize& aSize,
+                                          uint8_t* aTargetData, int32_t aTargetStride,
+                                          uint8_t* aSourceData, int32_t aSourceStride,
+                                          Float aValue);
+  static void DoOpacityCalculationA8_Scalar(const IntSize& aSize,
+                                            uint8_t* aTargetData, int32_t aTargetStride,
+                                            uint8_t* aSourceData, int32_t aSourceStride,
+                                            Float aValue);
   static already_AddRefed<DataSourceSurface>
     RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
                             int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect);
   static already_AddRefed<DataSourceSurface>
     ApplyArithmeticCombine_Scalar(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4);
 
 #ifdef USE_SSE2
   static void ExtractAlpha_SSE2(const IntSize& size, uint8_t* sourceData, int32_t sourceStride, uint8_t* alphaData, int32_t alphaStride);
@@ -110,16 +126,20 @@ protected:
   static void SeparateColorChannels_SSE2(const IntSize &size, uint8_t* sourceData, int32_t sourceStride, uint8_t* channel0Data, uint8_t* channel1Data, uint8_t* channel2Data, uint8_t* channel3Data, int32_t channelStride);
   static void CombineColorChannels_SSE2(const IntSize &size, int32_t resultStride, uint8_t* resultData, int32_t channelStride, uint8_t* channel0Data, uint8_t* channel1Data, uint8_t* channel2Data, uint8_t* channel3Data);
   static void DoPremultiplicationCalculation_SSE2(const IntSize& aSize,
                                         uint8_t* aTargetData, int32_t aTargetStride,
                                         uint8_t* aSourceData, int32_t aSourceStride);
   static void DoUnpremultiplicationCalculation_SSE2(const IntSize& aSize,
                                                uint8_t* aTargetData, int32_t aTargetStride,
                                                uint8_t* aSourceData, int32_t aSourceStride);
+  static void DoOpacityCalculation_SSE2(const IntSize& aSize,
+                                        uint8_t* aTargetData, int32_t aTargetStride,
+                                        uint8_t* aSourceData, int32_t aSourceStride,
+                                        Float aValue);
   static already_AddRefed<DataSourceSurface>
     RenderTurbulence_SSE2(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
                           int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect);
   static already_AddRefed<DataSourceSurface>
     ApplyArithmeticCombine_SSE2(DataSourceSurface* aInput1, DataSourceSurface* aInput2, Float aK1, Float aK2, Float aK3, Float aK4);
 #endif
 };
 
--- a/gfx/2d/FilterProcessingSIMD-inl.h
+++ b/gfx/2d/FilterProcessingSIMD-inl.h
@@ -977,16 +977,48 @@ DoUnpremultiplicationCalculation_SIMD(co
       p34 = simd::ShiftRight16<8>(simd::Add16(simd::Mul16(p34, aF34), simd::FromU16<u16x8_t>(128)));
 
       u8x16_t result = simd::PackAndSaturate16To8(p12, p34);
       simd::Store8(&aTargetData[targetIndex], result);
     }
   }
 }
 
+template<typename u16x8_t, typename u8x16_t>
+static void
+DoOpacityCalculation_SIMD(const IntSize& aSize,
+                          uint8_t* aTargetData, int32_t aTargetStride,
+                          uint8_t* aSourceData, int32_t aSourceStride,
+                          Float aOpacity)
+{
+  uint8_t alphaValue = uint8_t(roundf(255.f * aOpacity));
+  u16x8_t alphaValues = simd::FromU16<u16x8_t>(alphaValue, alphaValue, alphaValue, alphaValue,
+                                               alphaValue, alphaValue, alphaValue, alphaValue);
+  for (int32_t y = 0; y < aSize.height; y++) {
+    for (int32_t x = 0; x < aSize.width; x += 4) {
+      int32_t inputIndex = y * aSourceStride + 4 * x;
+      int32_t targetIndex = y * aTargetStride + 4 * x;
+
+      u8x16_t p1234 = simd::Load8<u8x16_t>(&aSourceData[inputIndex]);
+      u16x8_t p12 = simd::UnpackLo8x8ToU16x8(p1234);
+      u16x8_t p34 = simd::UnpackHi8x8ToU16x8(p1234);
+
+      // Multiply all components with alpha.
+      p12 = simd::Mul16(p12, alphaValues);
+      p34 = simd::Mul16(p34, alphaValues);
+
+      // Divide by 255 and pack.
+      u8x16_t result = simd::PackAndSaturate16To8(simd::ShiftRight16<8>(p12),
+        simd::ShiftRight16<8>(p34));
+
+      simd::Store8(&aTargetData[targetIndex], result);
+    }
+  }
+}
+
 template<typename f32x4_t, typename i32x4_t, typename u8x16_t>
 static already_AddRefed<DataSourceSurface>
 RenderTurbulence_SIMD(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
                       int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect)
 {
 #define RETURN_TURBULENCE(Type, Stitch) \
   SVGTurbulenceRenderer<Type,Stitch,f32x4_t,i32x4_t,u8x16_t> \
     renderer(aBaseFrequency, aSeed, aNumOctaves, aTileRect); \
--- a/gfx/2d/FilterProcessingSSE2.cpp
+++ b/gfx/2d/FilterProcessingSSE2.cpp
@@ -91,16 +91,25 @@ void
 FilterProcessing::DoUnpremultiplicationCalculation_SSE2(
                                  const IntSize& aSize,
                                  uint8_t* aTargetData, int32_t aTargetStride,
                                  uint8_t* aSourceData, int32_t aSourceStride)
 {
   DoUnpremultiplicationCalculation_SIMD<__m128i,__m128i>(aSize, aTargetData, aTargetStride, aSourceData, aSourceStride);
 }
 
+void
+FilterProcessing::DoOpacityCalculation_SSE2(const IntSize& aSize,
+                                            uint8_t* aTargetData, int32_t aTargetStride,
+                                            uint8_t* aSourceData, int32_t aSourceStride,
+                                            Float aValue)
+{
+  DoOpacityCalculation_SIMD<__m128i, __m128i>(aSize, aTargetData, aTargetStride, aSourceData, aSourceStride, aValue);
+}
+
 already_AddRefed<DataSourceSurface>
 FilterProcessing::RenderTurbulence_SSE2(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
                                         int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect)
 {
   return RenderTurbulence_SIMD<__m128,__m128i,__m128i>(aSize, aOffset, aBaseFrequency, aSeed, aNumOctaves, aType, aStitch, aTileRect);
 }
 
 already_AddRefed<DataSourceSurface>
--- a/gfx/2d/FilterProcessingScalar.cpp
+++ b/gfx/2d/FilterProcessingScalar.cpp
@@ -222,16 +222,56 @@ FilterProcessing::DoUnpremultiplicationC
         (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] * alphaFactor + 128) >> 8;
       aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] =
         (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] * alphaFactor + 128) >> 8;
       aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] = alpha;
     }
   }
 }
 
+void
+FilterProcessing::DoOpacityCalculation_Scalar(const IntSize& aSize,
+                                              uint8_t* aTargetData, int32_t aTargetStride,
+                                              uint8_t* aSourceData, int32_t aSourceStride,
+                                              Float aValue)
+{
+  uint8_t alpha = uint8_t(roundf(255.f * aValue));
+  for (int32_t y = 0; y < aSize.height; y++) {
+    for (int32_t x = 0; x < aSize.width; x++) {
+      int32_t inputIndex = y * aSourceStride + 4 * x;
+      int32_t targetIndex = y * aTargetStride + 4 * x;
+      aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] =
+        (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_R] * alpha) >> 8;
+      aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] =
+        (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_G] * alpha) >> 8;
+      aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] =
+        (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_B] * alpha) >> 8;
+      aTargetData[targetIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] =
+        (aSourceData[inputIndex + B8G8R8A8_COMPONENT_BYTEOFFSET_A] * alpha) >> 8;
+    }
+  }
+}
+
+void
+FilterProcessing::DoOpacityCalculationA8_Scalar(const IntSize& aSize,
+                                                uint8_t* aTargetData, int32_t aTargetStride,
+                                                uint8_t* aSourceData, int32_t aSourceStride,
+                                                Float aValue)
+{
+  uint8_t alpha = uint8_t(255.f * aValue);
+  for (int32_t y = 0; y < aSize.height; y++) {
+    for (int32_t x = 0; x < aSize.width; x++) {
+      int32_t inputIndex = y * aSourceStride;
+      int32_t targetIndex = y * aTargetStride;
+      aTargetData[targetIndex] =
+        FastDivideBy255<uint8_t>(aSourceData[inputIndex] * alpha);
+    }
+  }
+}
+
 already_AddRefed<DataSourceSurface>
 FilterProcessing::RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
                                           int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect)
 {
    return RenderTurbulence_SIMD<simd::Scalarf32x4_t,simd::Scalari32x4_t,simd::Scalaru8x16_t>(
      aSize, aOffset, aBaseFrequency, aSeed, aNumOctaves, aType, aStitch, aTileRect);
 }
 
--- a/gfx/2d/Filters.h
+++ b/gfx/2d/Filters.h
@@ -471,16 +471,26 @@ enum PremultiplyInputs
   IN_PREMULTIPLY_IN = 0
 };
 
 enum UnpremultiplyInputs
 {
   IN_UNPREMULTIPLY_IN = 0
 };
 
+enum OpacityAtts
+{
+  ATT_OPACITY_VALUE = 0
+};
+
+enum OpacityInputs
+{
+  IN_OPACITY_IN = 0
+};
+
 class FilterNode : public external::AtomicRefCounted<FilterNode>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNode)
   virtual ~FilterNode() {}
 
   virtual FilterBackend GetBackendType() = 0;
 
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -123,17 +123,18 @@ enum class FilterType : int8_t {
   POINT_DIFFUSE,
   POINT_SPECULAR,
   SPOT_DIFFUSE,
   SPOT_SPECULAR,
   DISTANT_DIFFUSE,
   DISTANT_SPECULAR,
   CROP,
   PREMULTIPLY,
-  UNPREMULTIPLY
+  UNPREMULTIPLY,
+  OPACITY
 };
 
 enum class DrawTargetType : int8_t {
   SOFTWARE_RASTER = 0,
   HARDWARE_RASTER,
   VECTOR
 };
 
--- a/gfx/gl/GLParseRegistryXML.py
+++ b/gfx/gl/GLParseRegistryXML.py
@@ -17,38 +17,37 @@
 #   Do not add the downloaded XML in the patch
 #
 # Step 4:
 #   Enjoy =)
 #
 ################################################################################
 
 # includes
+from __future__ import print_function
 import os
 import sys
 import xml.etree.ElementTree
 
 
 ################################################################################
 # export management
 
 class GLConstHeader:
     def __init__(self, f):
         self.f = f
 
-
     def write(self, arg):
         if isinstance(arg, list):
             self.f.write('\n'.join(arg) + '\n')
         elif isinstance(arg, (int, long)):
             self.f.write('\n' * arg)
         else:
             self.f.write(str(arg) + '\n')
 
-
     def formatFileBegin(self):
         self.write([
             '/* 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 GLCONSTS_H_',
             '#define GLCONSTS_H_',
@@ -58,46 +57,42 @@ class GLConstHeader:
             ' * This is a file generated directly from the official OpenGL registry',
             ' * xml available http://www.opengl.org/registry/#specfiles.',
             ' *',
             ' * To generate this file, see tutorial in \'GLParseRegistryXML.py\'.',
             ' */',
             ''
         ])
 
-
     def formatLibBegin(self, lib):
         # lib would be 'GL', 'EGL', 'GLX' or 'WGL'
         self.write('// ' + lib)
 
-
     def formatLibConstant(self, lib, name, value):
         # lib would be 'GL', 'EGL', 'GLX' or 'WGL'
         # name is the name of the const (example: MAX_TEXTURE_SIZE)
         # value is the value of the const (example: 0xABCD)
 
         define = '#define LOCAL_' + lib + '_' + name
         whitespace = 60 - len(define)
-        
+
         if whitespace < 0:
             whitespace = whitespace % 8
-        
+
         self.write(define + ' ' * whitespace + ' ' + value)
 
-
     def formatLibEnd(self, lib):
         # lib would be 'GL', 'EGL', 'GLX' or 'WGL'
         self.write(2)
 
-
     def formatFileEnd(self):
         self.write([
-                    '',
-                    '#endif // GLCONSTS_H_'
-                   ])
+            '',
+            '#endif // GLCONSTS_H_'
+        ])
 
 
 ################################################################################
 # underground code
 
 def getScriptDir():
     return os.path.dirname(__file__) + '/'
 
@@ -127,22 +122,21 @@ class GLDatabase:
 
     def __init__(self):
         self.consts = {}
         self.libs = set(GLDatabase.LIBS)
         self.vendors = set(['EXT', 'ATI'])
         # there is no vendor="EXT" and vendor="ATI" in gl.xml,
         # so we manualy declare them
 
-
     def loadXML(self, path):
         xmlPath = getXMLDir() + path
 
         if not os.path.isfile(xmlPath):
-            print 'missing file "' + xmlPath + '"'
+            print('missing file "' + xmlPath + '"')
             return False
 
         tree = xml.etree.ElementTree.parse(xmlPath)
         root = tree.getroot()
 
         for enums in root.iter('enums'):
             vendor = enums.get('vendor')
             if not vendor:
@@ -174,19 +168,18 @@ class GLDatabase:
                 if not type:
                     # if no type specified, we get the namespace's default type
                     type = namespaceType
 
                 self.consts[lib + '_' + name] = GLConst(lib, name, value, type)
 
         return True
 
-
     def exportConsts(self, path):
-        with open(getScriptDir() + path,'w') as f:
+        with open(getScriptDir() + path, 'w') as f:
 
             headerFile = GLConstHeader(f)
             headerFile.formatFileBegin()
 
             constNames = self.consts.keys()
             constNames.sort()
 
             for lib in GLDatabase.LIBS:
--- a/gfx/layers/d3d11/genshaders.py
+++ b/gfx/layers/d3d11/genshaders.py
@@ -7,152 +7,165 @@ import locale
 import os
 import re
 import subprocess
 import sys
 import tempfile
 import yaml
 import buildconfig
 
+
 def shell_main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument('-o', '--output', type=str, required=True,
-                      help='Output file')
-  parser.add_argument('manifest', type=str,
-                      help='Manifest source file')
-  args = parser.parse_args()
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-o', '--output', type=str, required=True,
+                        help='Output file')
+    parser.add_argument('manifest', type=str,
+                        help='Manifest source file')
+    args = parser.parse_args()
 
-  with open(args.output, 'w') as out_file:
-    process_manifest(out_file, args.manifest)
+    with open(args.output, 'w') as out_file:
+        process_manifest(out_file, args.manifest)
+
 
 def main(output_fp, input_filename):
-  return process_manifest(output_fp, input_filename)
+    return process_manifest(output_fp, input_filename)
+
 
 HEADER = """// AUTOGENERATED - DO NOT EDIT
 namespace mozilla {
 namespace layers {
 
 struct ShaderBytes { const void* mData; size_t mLength; };
 """
 FOOTER = """
 } // namespace layers
 } // namespace mozilla"""
 
+
 def process_manifest(output_fp, manifest_filename):
-  with codecs.open(manifest_filename, 'r', 'UTF-8') as in_fp:
-    manifest = yaml.safe_load(in_fp)
-  shader_folder, _ = os.path.split(manifest_filename)
+    with codecs.open(manifest_filename, 'r', 'UTF-8') as in_fp:
+        manifest = yaml.safe_load(in_fp)
+    shader_folder, _ = os.path.split(manifest_filename)
 
-  output_fp.write(HEADER)
+    output_fp.write(HEADER)
 
-  deps = set()
-  for block in manifest:
-    if 'type' not in block:
-      raise Exception("Expected 'type' key with shader mode")
-    if 'file' not in block:
-      raise Exception("Expected 'file' key with shader file")
-    if 'shaders' not in block:
-      raise Exception("Expected 'shaders' key with shader name list")
+    deps = set()
+    for block in manifest:
+        if 'type' not in block:
+            raise Exception("Expected 'type' key with shader mode")
+        if 'file' not in block:
+            raise Exception("Expected 'file' key with shader file")
+        if 'shaders' not in block:
+            raise Exception("Expected 'shaders' key with shader name list")
 
-    shader_file = os.path.join(shader_folder, block['file'])
-    deps.add(shader_file)
+        shader_file = os.path.join(shader_folder, block['file'])
+        deps.add(shader_file)
 
-    shader_model = block['type']
-    for shader_name in block['shaders']:
-      new_deps = run_fxc(
-        shader_model = shader_model,
-        shader_file = shader_file,
-        shader_name = shader_name,
-        output_fp = output_fp)
-      deps |= new_deps
+        shader_model = block['type']
+        for shader_name in block['shaders']:
+            new_deps = run_fxc(
+                shader_model=shader_model,
+                shader_file=shader_file,
+                shader_name=shader_name,
+                output_fp=output_fp)
+            deps |= new_deps
 
-  output_fp.write(FOOTER)
-  return deps
+    output_fp.write(FOOTER)
+    return deps
+
 
 def run_fxc(shader_model,
             shader_file,
             shader_name,
             output_fp):
-  fxc_location = buildconfig.substs['FXC']
+    fxc_location = buildconfig.substs['FXC']
+
+    argv = [
+        fxc_location,
+        '-nologo',
+        '-T{0}'.format(shader_model),
+        shader_file,
+        '-E{0}'.format(shader_name),
+        '-Vn{0}'.format(shader_name),
+        '-Vi',
+    ]
+    if 'Linux' in buildconfig.substs['HOST_OS_ARCH']:
+        argv.insert(0, buildconfig.substs['WINE'])
+    if shader_model.startswith('vs_'):
+        argv += ['-DVERTEX_SHADER']
+    elif shader_model.startswith('ps_'):
+        argv += ['-DPIXEL_SHADER']
 
-  argv = [
-    fxc_location,
-    '-nologo',
-    '-T{0}'.format(shader_model),
-    shader_file,
-    '-E{0}'.format(shader_name),
-    '-Vn{0}'.format(shader_name),
-    '-Vi',
-  ]
-  if 'Linux' in buildconfig.substs['HOST_OS_ARCH']:
-    argv.insert(0, buildconfig.substs['WINE'])
-  if shader_model.startswith('vs_'):
-    argv += ['-DVERTEX_SHADER']
-  elif shader_model.startswith('ps_'):
-    argv += ['-DPIXEL_SHADER']
+    deps = None
+    with ScopedTempFilename() as temp_filename:
+        argv += ['-Fh{0}'.format(temp_filename)]
 
-  deps = None
-  with ScopedTempFilename() as temp_filename:
-    argv += ['-Fh{0}'.format(temp_filename)]
+        sys.stdout.write('{0}\n'.format(' '.join(argv)))
+        proc_stdout = subprocess.check_output(argv)
+        proc_stdout = decode_console_text(sys.stdout, proc_stdout)
+        deps = find_dependencies(proc_stdout)
+        assert 'fxc2' in fxc_location or len(deps) > 0
 
-    sys.stdout.write('{0}\n'.format(' '.join(argv)))
-    proc_stdout = subprocess.check_output(argv)
-    proc_stdout = decode_console_text(sys.stdout, proc_stdout)
-    deps = find_dependencies(proc_stdout)
-    assert 'fxc2' in fxc_location or len(deps) > 0
+        with open(temp_filename, 'r') as temp_fp:
+            output_fp.write(temp_fp.read())
 
-    with open(temp_filename, 'r') as temp_fp:
-      output_fp.write(temp_fp.read())
+    output_fp.write("ShaderBytes s{0} = {{ {0}, sizeof({0}) }};\n".format(
+        shader_name))
+    return deps
 
-  output_fp.write("ShaderBytes s{0} = {{ {0}, sizeof({0}) }};\n".format(
-    shader_name))
-  return deps
 
 def find_dependencies(fxc_output):
-  # Dependencies look like this:
-  #   Resolved to [<path>]
-  #
-  # Microsoft likes to change output strings based on the user's language, so
-  # instead of pattern matching on that string, we take everything in between
-  # brackets. We filter out potentially bogus strings later.
-  deps = set()
-  for line in fxc_output.split('\n'):
-    m = re.search(r"\[([^\]]+)\]", line)
-    if m is None:
-      continue
-    dep_path = m.group(1)
-    dep_path = os.path.normpath(dep_path)
-    if os.path.isfile(dep_path):
-      deps.add(dep_path)
-  return deps
+    # Dependencies look like this:
+    #   Resolved to [<path>]
+    #
+    # Microsoft likes to change output strings based on the user's language, so
+    # instead of pattern matching on that string, we take everything in between
+    # brackets. We filter out potentially bogus strings later.
+    deps = set()
+    for line in fxc_output.split('\n'):
+        m = re.search(r"\[([^\]]+)\]", line)
+        if m is None:
+            continue
+        dep_path = m.group(1)
+        dep_path = os.path.normpath(dep_path)
+        if os.path.isfile(dep_path):
+            deps.add(dep_path)
+    return deps
 
 # Python reads the raw bytes from stdout, so we need to try our best to
 # capture that as a valid Python string.
+
+
 def decode_console_text(pipe, text):
-  try:
-    if pipe.encoding:
-      return text.decode(pipe.encoding, 'replace')
-  except:
-    pass
-  try:
-    return text.decode(locale.getpreferredencoding(), 'replace')
-  except:
-    return text.decode('utf8', 'replace')
+    try:
+        if pipe.encoding:
+            return text.decode(pipe.encoding, 'replace')
+    except Exception:
+        pass
+    try:
+        return text.decode(locale.getpreferredencoding(), 'replace')
+    except Exception:
+        return text.decode('utf8', 'replace')
 
 # Allocate a temporary file name and delete it when done. We need an extra
 # wrapper for this since TemporaryNamedFile holds the file open.
+
+
 class ScopedTempFilename(object):
-  def __init__(self):
-    self.name = None
-  def __enter__(self):
-    with tempfile.NamedTemporaryFile(delete = False) as tmp:
-      self.name = tmp.name
-      return self.name
-  def __exit__(self, type, value, traceback):
-    if not self.name:
-      return
-    try:
-      os.unlink(self.name)
-    except:
-      pass
+    def __init__(self):
+        self.name = None
+
+    def __enter__(self):
+        with tempfile.NamedTemporaryFile(delete=False) as tmp:
+            self.name = tmp.name
+            return self.name
+
+    def __exit__(self, type, value, traceback):
+        if not self.name:
+            return
+        try:
+            os.unlink(self.name)
+        except Exception:
+            pass
+
 
 if __name__ == '__main__':
-  shell_main()
+    shell_main()
--- a/gfx/src/FilterSupport.cpp
+++ b/gfx/src/FilterSupport.cpp
@@ -857,16 +857,27 @@ FilterNodeFromPrimitiveDescription(const
           filters[i]->SetInput(0, lastFilter);
           lastFilter = filters[i];
         }
       }
 
       return lastFilter.forget();
     }
 
+    case PrimitiveType::Opacity:
+    {
+      RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::OPACITY);
+      if (!filter) {
+        return nullptr;
+      }
+      filter->SetAttribute(ATT_OPACITY_VALUE, atts.GetFloat(eOpacityOpacity));
+      filter->SetInput(IN_OPACITY_IN, aSources[0]);
+      return filter.forget();
+    }
+
     case PrimitiveType::ConvolveMatrix:
     {
       RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::CONVOLVE_MATRIX);
       if (!filter) {
         return nullptr;
       }
       filter->SetAttribute(ATT_CONVOLVE_MATRIX_KERNEL_SIZE, atts.GetIntSize(eConvolveMatrixKernelSize));
       const nsTArray<float>& matrix = atts.GetFloats(eConvolveMatrixKernelMatrix);
@@ -1389,16 +1400,17 @@ ResultChangeRegionForPrimitive(const Fil
     case PrimitiveType::Flood:
     case PrimitiveType::Turbulence:
     case PrimitiveType::Image:
       return nsIntRegion();
 
     case PrimitiveType::Blend:
     case PrimitiveType::Composite:
     case PrimitiveType::Merge:
+    case PrimitiveType::Opacity:
       return UnionOfRegions(aInputChangeRegions);
 
     case PrimitiveType::ColorMatrix:
     case PrimitiveType::ComponentTransfer:
     case PrimitiveType::ToAlpha:
       return aInputChangeRegions[0];
 
     case PrimitiveType::Morphology:
@@ -1609,16 +1621,24 @@ FilterSupport::PostFilterExtentsForPrimi
       AttributeMap functionAttributes =
         atts.GetAttributeMap(eComponentTransferFunctionA);
       if (ResultOfZeroUnderTransferFunction(functionAttributes) > 0.0f) {
         return aDescription.PrimitiveSubregion();
       }
       return aInputExtents[0];
     }
 
+    case PrimitiveType::Opacity:
+    {
+      if (atts.GetFloat(eOpacityOpacity) == 0.0f) {
+        return IntRect();
+      }
+      return ResultChangeRegionForPrimitive(aDescription, aInputExtents);
+    }
+
     case PrimitiveType::Turbulence:
     case PrimitiveType::Image:
     case PrimitiveType::DiffuseLighting:
     case PrimitiveType::SpecularLighting:
     {
       return aDescription.PrimitiveSubregion();
     }
 
@@ -1687,16 +1707,17 @@ SourceNeededRegionForPrimitive(const Fil
       return nsIntRegion();
 
     case PrimitiveType::Blend:
     case PrimitiveType::Composite:
     case PrimitiveType::Merge:
     case PrimitiveType::ColorMatrix:
     case PrimitiveType::ComponentTransfer:
     case PrimitiveType::ToAlpha:
+    case PrimitiveType::Opacity:
       return aResultNeededRegion;
 
     case PrimitiveType::Morphology:
     {
       Size radii = atts.GetSize(eMorphologyRadii);
       int32_t rx = clamped(int32_t(ceil(radii.width)), 0, kMorphologyMaxRadius);
       int32_t ry = clamped(int32_t(ceil(radii.height)), 0, kMorphologyMaxRadius);
       return aResultNeededRegion.Inflated(nsIntMargin(ry, rx, ry, rx));
--- a/gfx/src/FilterSupport.h
+++ b/gfx/src/FilterSupport.h
@@ -90,16 +90,17 @@ const unsigned short SVG_FECOMPOSITE_OPE
 enum AttributeName {
   eBlendBlendmode = 0,
   eMorphologyRadii,
   eMorphologyOperator,
   eColorMatrixType,
   eColorMatrixValues,
   eFloodColor,
   eTileSourceRect,
+  eOpacityOpacity,
   eComponentTransferFunctionR,
   eComponentTransferFunctionG,
   eComponentTransferFunctionB,
   eComponentTransferFunctionA,
   eComponentTransferFunctionType,
   eComponentTransferFunctionTableValues,
   eComponentTransferFunctionSlope,
   eComponentTransferFunctionIntercept,
@@ -272,16 +273,17 @@ public:
 enum class PrimitiveType {
   Empty = 0,
   Blend,
   Morphology,
   ColorMatrix,
   Flood,
   Tile,
   ComponentTransfer,
+  Opacity,
   ConvolveMatrix,
   Offset,
   DisplacementMap,
   Turbulence,
   Composite,
   Merge,
   Image,
   GaussianBlur,
--- a/gfx/thebes/gencjkcisvs.py
+++ b/gfx/thebes/gencjkcisvs.py
@@ -12,25 +12,25 @@ line = f.readline()
 m = re.compile('^# (StandardizedVariants(-\d+(\.\d+)*)?\.txt)').search(line)
 fileversion = m.group(1)
 vsdict = {}
 r = re.compile('^([0-9A-F]{4,6}) (FE0[0-9A-F]); CJK COMPATIBILITY IDEOGRAPH-([0-9A-F]{4,6});')
 while True:
     line = f.readline()
     if not line:
         break
-    if not 'CJK COMPATIBILITY IDEOGRAPH-' in line:
+    if 'CJK COMPATIBILITY IDEOGRAPH-' not in line:
         continue
 
     m = r.search(line)
     unified = int(m.group(1), 16)
     vs = int(m.group(2), 16)
     compat = int(m.group(3), 16)
 
-    if not vs in vsdict:
+    if vs not in vsdict:
         vsdict[vs] = {}
     vsdict[vs][unified] = compat
 
 f.close
 
 offsets = []
 length = 10 + 11 * len(vsdict)
 for (k, mappings) in sorted(vsdict.items()):
--- a/gfx/thebes/gfxSVGGlyphs.cpp
+++ b/gfx/thebes/gfxSVGGlyphs.cpp
@@ -10,26 +10,26 @@
 #include "nsIDocument.h"
 #include "nsICategoryManager.h"
 #include "nsIDocumentLoaderFactory.h"
 #include "nsIContentViewer.h"
 #include "nsIStreamListener.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIPresShell.h"
 #include "nsNetUtil.h"
-#include "NullPrincipal.h"
 #include "nsIInputStream.h"
 #include "nsStringStream.h"
 #include "nsStreamUtils.h"
 #include "nsIPrincipal.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FontTableURIProtocolHandler.h"
 #include "mozilla/dom/SVGDocument.h"
 #include "mozilla/LoadInfo.h"
+#include "mozilla/NullPrincipal.h"
 #include "nsSVGUtils.h"
 #include "nsContentUtils.h"
 #include "gfxFont.h"
 #include "nsSMILAnimationController.h"
 #include "gfxContext.h"
 #include "harfbuzz/hb.h"
 #include "mozilla/dom/ImageTracker.h"
 
--- a/image/decoders/icon/android/nsIconChannel.cpp
+++ b/image/decoders/icon/android/nsIconChannel.cpp
@@ -1,24 +1,24 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdlib.h>
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/NullPrincipal.h"
 #include "nsMimeTypes.h"
 #include "nsIURL.h"
 #include "nsXULAppAPI.h"
 #include "AndroidBridge.h"
 #include "nsIconChannel.h"
 #include "nsIStringStream.h"
 #include "nsNetUtil.h"
 #include "nsComponentManagerUtils.h"
-#include "NullPrincipal.h"
 
 NS_IMPL_ISUPPORTS(nsIconChannel,
                   nsIRequest,
                   nsIChannel)
 
 using namespace mozilla;
 using mozilla::dom::ContentChild;
 
--- a/image/decoders/icon/gtk/nsIconChannel.cpp
+++ b/image/decoders/icon/gtk/nsIconChannel.cpp
@@ -5,32 +5,32 @@
 
 #include "nsIconChannel.h"
 
 #include <stdlib.h>
 #include <unistd.h>
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/EndianUtils.h"
+#include "mozilla/NullPrincipal.h"
 #include <algorithm>
 
 #include <gio/gio.h>
 
 #include <gtk/gtk.h>
 
 #include "nsMimeTypes.h"
 #include "nsIMIMEService.h"
 
 #include "nsServiceManagerUtils.h"
 
 #include "nsNetUtil.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIStringStream.h"
 #include "nsServiceManagerUtils.h"
-#include "NullPrincipal.h"
 #include "nsIURL.h"
 #include "prlink.h"
 #include "gfxPlatform.h"
 
 NS_IMPL_ISUPPORTS(nsIconChannel,
                   nsIRequest,
                   nsIChannel)
 
@@ -101,17 +101,18 @@ moz_gdk_pixbuf_to_channel(GdkPixbuf* aPi
 
   // If this no longer holds then re-examine buf's lifetime.
   MOZ_ASSERT(NS_SUCCEEDED(rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // nsIconProtocolHandler::NewChannel2 will provide the correct loadInfo for
   // this iconChannel. Use the most restrictive security settings for the
   // temporary loadInfo to make sure the channel can not be openend.
-  nsCOMPtr<nsIPrincipal> nullPrincipal = NullPrincipal::CreateWithoutOriginAttributes();
+  nsCOMPtr<nsIPrincipal> nullPrincipal =
+    mozilla::NullPrincipal::CreateWithoutOriginAttributes();
   return NS_NewInputStreamChannel(aChannel,
                                   aURI,
                                   stream.forget(),
                                   nullPrincipal,
                                   nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
                                   nsIContentPolicy::TYPE_INTERNAL_IMAGE,
                                   NS_LITERAL_CSTRING(IMAGE_ICON_MS));
 }
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -4,21 +4,21 @@
  * 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/. */
 
 // Undefine windows version of LoadImage because our code uses that name.
 #undef LoadImage
 
 #include "ImageLogging.h"
 #include "imgLoader.h"
-#include "NullPrincipal.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Move.h"
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ChaosMode.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsImageModule.h"
 #include "imgRequestProxy.h"
 
--- a/intl/icu_sources_data.py
+++ b/intl/icu_sources_data.py
@@ -79,21 +79,21 @@ def update_sources(topsrcdir):
                    for s in list_headers(mozpath.join(base_path, 'unicode'))]
         write_sources(mozbuild, sources, headers)
 
 
 def try_run(name, command, cwd=None, **kwargs):
     try:
         with tempfile.NamedTemporaryFile(prefix=name, delete=False) as f:
             subprocess.check_call(command, cwd=cwd, stdout=f,
-                                stderr=subprocess.STDOUT, **kwargs)
+                                  stderr=subprocess.STDOUT, **kwargs)
     except subprocess.CalledProcessError:
         print('''Error running "{}" in directory {}
     See output in {}'''.format(' '.join(command), cwd, f.name),
-            file=sys.stderr)
+              file=sys.stderr)
         return False
     else:
         os.unlink(f.name)
         return True
 
 
 def get_data_file(data_dir):
     files = glob.glob(mozpath.join(data_dir, 'icudt*.dat'))
@@ -146,17 +146,17 @@ def update_data_file(topsrcdir):
         print('Error: no ICU data in ICU objdir', file=sys.stderr)
         return False
     if os.path.basename(old_data_file) != os.path.basename(new_data_file):
         # Data file name has the major version number embedded.
         os.unlink(old_data_file)
     shutil.copy(new_data_file, tree_data_path)
     try:
         shutil.rmtree(objdir)
-    except:
+    except Exception:
         print('Warning: failed to remove %s' % objdir, file=sys.stderr)
     return True
 
 
 def main():
     if len(sys.argv) != 2:
         print('Usage: icu_sources_data.py <mozilla topsrcdir>',
               file=sys.stderr)
--- a/intl/locale/props2arrays.py
+++ b/intl/locale/props2arrays.py
@@ -1,27 +1,25 @@
 # 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/.
 
-import sys
 
 def main(header, propFile):
-  mappings = {}
+    mappings = {}
+
+    with open(propFile, 'r') as f:
+        for line in f:
+            line = line.strip()
+            if not line.startswith('#'):
+                parts = line.split("=", 1)
+                if len(parts) == 2 and len(parts[0]) > 0:
+                    mappings[parts[0].strip()] = parts[1].strip()
 
-  with open(propFile, 'r') as f:
-    for line in f:
-      line = line.strip()
-      if not line.startswith('#'):
-        parts = line.split("=", 1)
-        if len(parts) == 2 and len(parts[0]) > 0:
-          mappings[parts[0].strip()] = parts[1].strip()
- 
-  keys = mappings.keys()
-  keys.sort()
+    keys = mappings.keys()
+    keys.sort()
 
-  header.write("// This is a generated file. Please do not edit.\n")
-  header.write("// Please edit the corresponding .properties file instead.\n")
+    header.write("// This is a generated file. Please do not edit.\n")
+    header.write("// Please edit the corresponding .properties file instead.\n")
 
-  entries = ['{ "%s", "%s", %d }'
-             % (key, mappings[key], len(mappings[key])) for key in keys]
-  header.write(',\n'.join(entries) + '\n')
-
+    entries = ['{ "%s", "%s", %d }'
+               % (key, mappings[key], len(mappings[key])) for key in keys]
+    header.write(',\n'.join(entries) + '\n')
--- a/ipc/glue/BackgroundUtils.cpp
+++ b/ipc/glue/BackgroundUtils.cpp
@@ -4,26 +4,26 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BackgroundUtils.h"
 
 #include "MainThreadUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/BasePrincipal.h"
+#include "mozilla/ContentPrincipal.h"
+#include "mozilla/NullPrincipal.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/net/NeckoChannelParams.h"
 #include "ExpandedPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "mozilla/LoadInfo.h"
-#include "ContentPrincipal.h"
-#include "NullPrincipal.h"
 #include "nsContentUtils.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "mozilla/nsRedirectHistoryEntry.h"
 #include "URIUtils.h"
 
 namespace mozilla {
 namespace net {
--- a/ipc/glue/URIUtils.cpp
+++ b/ipc/glue/URIUtils.cpp
@@ -6,22 +6,22 @@
 
 #include "URIUtils.h"
 
 #include "nsIIPCSerializableURI.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/BlobURL.h"
+#include "mozilla/NullPrincipalURI.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDebug.h"
 #include "nsID.h"
 #include "nsJARURI.h"
 #include "nsIIconURI.h"
-#include "NullPrincipalURI.h"
 #include "nsJSProtocolHandler.h"
 #include "nsNetCID.h"
 #include "nsSimpleNestedURI.h"
 #include "nsThreadUtils.h"
 #include "nsIURIMutator.h"
 
 using namespace mozilla::ipc;
 using mozilla::ArrayLength;
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/.flake8
@@ -0,0 +1,5 @@
+[flake8]
+# See http://pep8.readthedocs.io/en/latest/intro.html#configuration
+ignore = E121, E123, E126, E129, E133, E226, E241, E242, E704, W503, E402, E741, F405, F403
+max-line-length = 99
+
--- a/ipc/ipdl/ipdl.py
+++ b/ipc/ipdl/ipdl.py
@@ -1,27 +1,29 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import optparse, os, re, sys
+import optparse
+import os
+import sys
 from cStringIO import StringIO
-import mozpack.path as mozpath
 from ConfigParser import RawConfigParser
 
 import ipdl
 
+
 def log(minv, fmt, *args):
     if _verbosity >= minv:
-        print fmt % args
+        print(fmt % args)
 
 # process command line
 
+
 op = optparse.OptionParser(usage='ipdl.py [options] IPDLfiles...')
-op.add_option('-I', '--include', dest='includedirs', default=[ ],
+op.add_option('-I', '--include', dest='includedirs', default=[],
               action='append',
               help='Additional directory to search for included protocol specifications')
 op.add_option('-s', '--sync-msg-list', dest='syncMsgList', default='sync-messages.ini',
               help="Config file listing allowed sync messages")
 op.add_option('-m', '--msg-metadata', dest='msgMetadata', default='message-metadata.ini',
               help="Predicted message sizes for reducing serialization malloc overhead.")
 op.add_option('-v', '--verbose', dest='verbosity', default=1, action='count',
               help='Verbose logging (specify -vv or -vvv for very verbose logging)')
@@ -39,36 +41,38 @@ A protocol Foo in the namespace bar will
 to be generated""")
 
 options, files = op.parse_args()
 _verbosity = options.verbosity
 syncMsgList = options.syncMsgList
 msgMetadata = options.msgMetadata
 headersdir = options.headersdir
 cppdir = options.cppdir
-includedirs = [ os.path.abspath(incdir) for incdir in options.includedirs ]
+includedirs = [os.path.abspath(incdir) for incdir in options.includedirs]
 
 if not len(files):
     op.error("No IPDL files specified")
 
 ipcmessagestartpath = os.path.join(headersdir, 'IPCMessageStart.h')
 ipc_msgtype_name_path = os.path.join(cppdir, 'IPCMessageTypeName.cpp')
 
 log(2, 'Generated C++ headers will be generated relative to "%s"', headersdir)
 log(2, 'Generated C++ sources will be generated in "%s"', cppdir)
 
 allmessages = {}
 allmessageprognames = []
 allprotocols = []
 
+
 def normalizedFilename(f):
     if f == '-':
         return '<stdin>'
     return f
 
+
 log(2, 'Reading sync message list')
 parser = RawConfigParser()
 parser.readfp(open(options.syncMsgList))
 syncMsgList = parser.sections()
 
 # Read message metadata. Right now we only have 'segment_capacity'
 # for the standard segment size used for serialization.
 log(2, 'Reading message metadata...')
@@ -99,17 +103,17 @@ for f in files:
         sys.exit(1)
 
     log(2, 'checking types')
     if not ipdl.typecheck(ast):
         print >>sys.stderr, 'Specification is not well typed.'
         sys.exit(1)
 
     if not ipdl.checkSyncMessage(ast, syncMsgList):
-        print >>sys.stderr, 'Error: New sync IPC messages must be reviewed by an IPC peer and recorded in %s' % options.syncMsgList
+        print >>sys.stderr, 'Error: New sync IPC messages must be reviewed by an IPC peer and recorded in %s' % options.syncMsgList  # NOQA: E501
         sys.exit(1)
 
 if not ipdl.checkFixedSyncMessages(parser):
     # Errors have alraedy been printed to stderr, just exit
     sys.exit(1)
 
 # Second pass: generate code
 for f in files:
--- a/ipc/ipdl/ipdl/__init__.py
+++ b/ipc/ipdl/ipdl/__init__.py
@@ -1,28 +1,29 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-__all__ = [ 'gencxx', 'genipdl', 'parse', 'typecheck', 'writeifmodified',
-            'checkSyncMessage', 'checkFixedSyncMessages' ]
+__all__ = ['gencxx', 'genipdl', 'parse', 'typecheck', 'writeifmodified',
+           'checkSyncMessage', 'checkFixedSyncMessages']
 
-import os, sys
+import os
+import sys
 from cStringIO import StringIO
 
 from ipdl.cgen import IPDLCodeGen
 from ipdl.lower import LowerToCxx, msgenums
 from ipdl.parser import Parser, ParseError
 from ipdl.type import TypeCheck
 from ipdl.checker import checkSyncMessage, checkFixedSyncMessages
 
 from ipdl.cxx.cgen import CxxCodeGen
 
 
-def parse(specstring, filename='/stdin', includedirs=[ ], errout=sys.stderr):
+def parse(specstring, filename='/stdin', includedirs=[], errout=sys.stderr):
     '''Return an IPDL AST if parsing was successful.  Print errors to |errout|
     if it is not.'''
     # The file type and name are later enforced by the type checker.
     # This is just a hint to the parser.
     prefix, ext = os.path.splitext(filename)
     name = os.path.basename(prefix)
     if ext == '.ipdlh':
         type = 'header'
@@ -30,49 +31,52 @@ def parse(specstring, filename='/stdin',
         type = 'protocol'
 
     try:
         return Parser(type, name).parse(specstring, os.path.abspath(filename), includedirs)
     except ParseError as p:
         print >>errout, p
         return None
 
+
 def typecheck(ast, errout=sys.stderr):
     '''Return True iff |ast| is well typed.  Print errors to |errout| if
     it is not.'''
     return TypeCheck().check(ast, errout)
 
 
 def gencxx(ipdlfilename, ast, outheadersdir, outcppdir, segmentcapacitydict):
     headers, cpps = LowerToCxx().lower(ast, segmentcapacitydict)
 
     def resolveHeader(hdr):
         return [
             hdr,
             os.path.join(
                 outheadersdir,
                 *([ns.name for ns in ast.namespaces] + [hdr.name]))
         ]
-    def resolveCpp(cpp):
-        return [ cpp, os.path.join(outcppdir, cpp.name) ]
 
-    for ast, filename in ([ resolveHeader(hdr) for hdr in headers ]
-                          + [ resolveCpp(cpp) for cpp in cpps ]):
+    def resolveCpp(cpp):
+        return [cpp, os.path.join(outcppdir, cpp.name)]
+
+    for ast, filename in ([resolveHeader(hdr) for hdr in headers]
+                          + [resolveCpp(cpp) for cpp in cpps]):
         tempfile = StringIO()
         CxxCodeGen(tempfile).cgen(ast)
         writeifmodified(tempfile.getvalue(), filename)
 
 
 def genipdl(ast, outdir):
     return IPDLCodeGen().cgen(ast)
 
 
 def genmsgenum(ast):
     return msgenums(ast.protocol, pretty=True)
 
+
 def writeifmodified(contents, file):
     dir = os.path.dirname(file)
     os.path.exists(dir) or os.makedirs(dir)
 
     oldcontents = None
     if os.path.exists(file):
         fd = open(file, 'rb')
         oldcontents = fd.read()
--- a/ipc/ipdl/ipdl/ast.py
+++ b/ipc/ipdl/ipdl/ast.py
@@ -1,42 +1,40 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-import sys
-
 NOT_NESTED = 1
 INSIDE_SYNC_NESTED = 2
 INSIDE_CPOW_NESTED = 3
 
 NORMAL_PRIORITY = 1
 INPUT_PRIORITY = 2
 HIGH_PRIORITY = 3
 
+
 class Visitor:
     def defaultVisit(self, node):
-        raise Exception, "INTERNAL ERROR: no visitor for node type `%s'"% (
-            node.__class__.__name__)
+        raise Exception("INTERNAL ERROR: no visitor for node type `%s'" %
+                        (node.__class__.__name__))
 
     def visitTranslationUnit(self, tu):
         for cxxInc in tu.cxxIncludes:
             cxxInc.accept(self)
         for inc in tu.includes:
             inc.accept(self)
         for su in tu.structsAndUnions:
             su.accept(self)
         for using in tu.builtinUsing:
             using.accept(self)
         for using in tu.using:
             using.accept(self)
         if tu.protocol:
             tu.protocol.accept(self)
 
-
     def visitCxxInclude(self, inc):
         pass
 
     def visitInclude(self, inc):
         # Note: we don't visit the child AST here, because that needs delicate
         # and pass-specific handling
         pass
 
@@ -83,237 +81,282 @@ class Visitor:
         pass
 
     def visitTypeSpec(self, ts):
         pass
 
     def visitDecl(self, d):
         pass
 
+
 class Loc:
     def __init__(self, filename='<??>', lineno=0):
         assert filename
         self.filename = filename
         self.lineno = lineno
+
     def __repr__(self):
-        return '%r:%r'% (self.filename, self.lineno)
+        return '%r:%r' % (self.filename, self.lineno)
+
     def __str__(self):
-        return '%s:%s'% (self.filename, self.lineno)
+        return '%s:%s' % (self.filename, self.lineno)
+
 
 Loc.NONE = Loc(filename='<??>', lineno=0)
 
+
 class _struct:
     pass
 
+
 class Node:
     def __init__(self, loc=Loc.NONE):
         self.loc = loc
 
     def accept(self, visitor):
-        visit = getattr(visitor, 'visit'+ self.__class__.__name__, None)
+        visit = getattr(visitor, 'visit' + self.__class__.__name__, None)
         if visit is None:
             return getattr(visitor, 'defaultVisit')(self)
         return visit(self)
 
     def addAttrs(self, attrsName):
         if not hasattr(self, attrsName):
             setattr(self, attrsName, _struct())
 
 
 class NamespacedNode(Node):
     def __init__(self, loc=Loc.NONE, name=None):
         Node.__init__(self, loc)
         self.name = name
-        self.namespaces = [ ]
+        self.namespaces = []
 
     def addOuterNamespace(self, namespace):
         self.namespaces.insert(0, namespace)
 
     def qname(self):
         return QualifiedId(self.loc, self.name,
-                           [ ns.name for ns in self.namespaces ])
+                           [ns.name for ns in self.namespaces])
+
 
 class TranslationUnit(NamespacedNode):
     def __init__(self, type, name):
         NamespacedNode.__init__(self, name=name)
         self.filetype = type
         self.filename = None
-        self.cxxIncludes = [ ]
-        self.includes = [ ]
-        self.builtinUsing = [ ]
-        self.using = [ ]
-        self.structsAndUnions = [ ]
+        self.cxxIncludes = []
+        self.includes = []
+        self.builtinUsing = []
+        self.using = []
+        self.structsAndUnions = []
         self.protocol = None
 
     def addCxxInclude(self, cxxInclude): self.cxxIncludes.append(cxxInclude)
+
     def addInclude(self, inc): self.includes.append(inc)
+
     def addStructDecl(self, struct): self.structsAndUnions.append(struct)
+
     def addUnionDecl(self, union): self.structsAndUnions.append(union)
+
     def addUsingStmt(self, using): self.using.append(using)
 
     def setProtocol(self, protocol): self.protocol = protocol
 
+
 class CxxInclude(Node):
     def __init__(self, loc, cxxFile):
         Node.__init__(self, loc)
         self.file = cxxFile
 
+
 class Include(Node):
     def __init__(self, loc, type, name):
         Node.__init__(self, loc)
         suffix = 'ipdl'
         if type == 'header':
             suffix += 'h'
         self.file = "%s.%s" % (name, suffix)
 
+
 class UsingStmt(Node):
     def __init__(self, loc, cxxTypeSpec, cxxHeader=None, kind=None, refcounted=False):
         Node.__init__(self, loc)
         assert not isinstance(cxxTypeSpec, str)
-        assert cxxHeader is None or isinstance(cxxHeader, str);
+        assert cxxHeader is None or isinstance(cxxHeader, str)
         assert kind is None or kind == 'class' or kind == 'struct'
         self.type = cxxTypeSpec
         self.header = cxxHeader
         self.kind = kind
         self.refcounted = refcounted
+
     def canBeForwardDeclared(self):
         return self.isClass() or self.isStruct()
+
     def isClass(self):
         return self.kind == 'class'
+
     def isStruct(self):
         return self.kind == 'struct'
+
     def isRefcounted(self):
         return self.refcounted
 
 # "singletons"
+
+
 class PrettyPrinted:
     @classmethod
     def __hash__(cls): return hash(cls.pretty)
+
     @classmethod
-    def __str__(cls):  return cls.pretty
+    def __str__(cls): return cls.pretty
+
 
 class ASYNC(PrettyPrinted):
     pretty = 'async'
+
+
 class INTR(PrettyPrinted):
     pretty = 'intr'
+
+
 class SYNC(PrettyPrinted):
     pretty = 'sync'
 
+
 class INOUT(PrettyPrinted):
     pretty = 'inout'
+
+
 class IN(PrettyPrinted):
     pretty = 'in'
+
+
 class OUT(PrettyPrinted):
     pretty = 'out'
 
 
 class Namespace(Node):
     def __init__(self, loc, namespace):
         Node.__init__(self, loc)
         self.name = namespace
 
+
 class Protocol(NamespacedNode):
     def __init__(self, loc):
         NamespacedNode.__init__(self, loc)
         self.sendSemantics = ASYNC
         self.nested = NOT_NESTED
-        self.managers = [ ]
-        self.managesStmts = [ ]
-        self.messageDecls = [ ]
+        self.managers = []
+        self.managesStmts = []
+        self.messageDecls = []
+
 
 class StructField(Node):
     def __init__(self, loc, type, name):
         Node.__init__(self, loc)
         self.typespec = type
         self.name = name
 
+
 class StructDecl(NamespacedNode):
     def __init__(self, loc, name, fields):
         NamespacedNode.__init__(self, loc, name)
         self.fields = fields
 
+
 class UnionDecl(NamespacedNode):
     def __init__(self, loc, name, components):
         NamespacedNode.__init__(self, loc, name)
         self.components = components
 
+
 class Manager(Node):
     def __init__(self, loc, managerName):
         Node.__init__(self, loc)
         self.name = managerName
 
+
 class ManagesStmt(Node):
     def __init__(self, loc, managedName):
         Node.__init__(self, loc)
         self.name = managedName
 
+
 class MessageDecl(Node):
     def __init__(self, loc):
         Node.__init__(self, loc)
         self.name = None
         self.sendSemantics = ASYNC
         self.nested = NOT_NESTED
         self.prio = NORMAL_PRIORITY
         self.direction = None
-        self.inParams = [ ]
-        self.outParams = [ ]
+        self.inParams = []
+        self.outParams = []
         self.compress = ''
         self.verify = ''
 
     def addInParams(self, inParamsList):
         self.inParams += inParamsList
 
     def addOutParams(self, outParamsList):
         self.outParams += outParamsList
 
     def addModifiers(self, modifiers):
         for modifier in modifiers:
             if modifier.startswith('compress'):
                 self.compress = modifier
             elif modifier == 'verify':
                 self.verify = modifier
             elif modifier != '':
-                raise Exception, "Unexpected message modifier `%s'"% modifier
+                raise Exception("Unexpected message modifier `%s'" % modifier)
+
 
 class Param(Node):
     def __init__(self, loc, typespec, name):
         Node.__init__(self, loc)
         self.name = name
         self.typespec = typespec
 
+
 class TypeSpec(Node):
     def __init__(self, loc, spec):
         Node.__init__(self, loc)
         self.spec = spec                # QualifiedId
         self.array = 0                  # bool
         self.nullable = 0               # bool
+
     def basename(self):
         return self.spec.baseid
 
-    def __str__(self):  return str(self.spec)
+    def __str__(self): return str(self.spec)
+
 
 class QualifiedId:              # FIXME inherit from node?
-    def __init__(self, loc, baseid, quals=[ ]):
+    def __init__(self, loc, baseid, quals=[]):
         assert isinstance(baseid, str)
-        for qual in quals: assert isinstance(qual, str)
+        for qual in quals:
+            assert isinstance(qual, str)
 
         self.loc = loc
         self.baseid = baseid
         self.quals = quals
 
     def qualify(self, id):
         self.quals.append(self.baseid)
         self.baseid = id
 
     def __str__(self):
         if 0 == len(self.quals):
             return self.baseid
-        return '::'.join(self.quals) +'::'+ self.baseid
+        return '::'.join(self.quals) + '::' + self.baseid
 
 # added by type checking passes
+
+
 class Decl(Node):
     def __init__(self, loc):
         Node.__init__(self, loc)
         self.progname = None    # what the programmer typed, if relevant
         self.shortname = None   # shortest way to refer to this decl
         self.fullname = None    # full way to refer to this decl
         self.loc = loc
         self.type = None
--- a/ipc/ipdl/ipdl/cgen.py
+++ b/ipc/ipdl/ipdl/cgen.py
@@ -1,98 +1,105 @@
 # 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/.
 
-import os, sys
+import sys
 
 from ipdl.ast import Visitor
 
+
 class CodePrinter:
     def __init__(self, outf=sys.stdout, indentCols=4):
         self.outf = outf
         self.col = 0
         self.indentCols = indentCols
 
     def write(self, str):
         self.outf.write(str)
 
     def printdent(self, str=''):
-        self.write((' '* self.col) + str)
+        self.write((' ' * self.col) + str)
 
     def println(self, str=''):
-        self.write(str +'\n')
+        self.write(str + '\n')
 
     def printdentln(self, str):
-        self.write((' '* self.col) + str +'\n')
+        self.write((' ' * self.col) + str + '\n')
 
     def indent(self):  self.col += self.indentCols
+
     def dedent(self):  self.col -= self.indentCols
 
 
-##-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 class IPDLCodeGen(CodePrinter, Visitor):
     '''Spits back out equivalent IPDL to the code that generated this.
 Also known as pretty-printing.'''
 
     def __init__(self, outf=sys.stdout, indentCols=4, printed=set()):
         CodePrinter.__init__(self, outf, indentCols)
         self.printed = printed
 
     def visitTranslationUnit(self, tu):
         self.printed.add(tu.filename)
         self.println('//\n// Automatically generated by ipdlc\n//')
-        CodeGen.visitTranslationUnit(self, tu)
+        CodeGen.visitTranslationUnit(self, tu)  # NOQA: F821
 
     def visitCxxInclude(self, inc):
-        self.println('include "'+ inc.file +'";')
+        self.println('include "' + inc.file + '";')
 
     def visitProtocolInclude(self, inc):
-        self.println('include protocol "'+ inc.file +'";')
+        self.println('include protocol "' + inc.file + '";')
         if inc.tu.filename not in self.printed:
             self.println('/* Included file:')
             IPDLCodeGen(outf=self.outf, indentCols=self.indentCols,
                         printed=self.printed).visitTranslationUnit(inc.tu)
 
             self.println('*/')
 
     def visitProtocol(self, p):
         self.println()
-        for namespace in p.namespaces:  namespace.accept(self)
+        for namespace in p.namespaces:
+            namespace.accept(self)
 
-        self.println('%s protocol %s\n{'% (p.sendSemantics[0], p.name))
+        self.println('%s protocol %s\n{' % (p.sendSemantics[0], p.name))
         self.indent()
 
         for mgs in p.managesStmts:
             mgs.accept(self)
-        if len(p.managesStmts):  self.println()
+        if len(p.managesStmts):
+            self.println()
 
-        for msgDecl in p.messageDecls:  msgDecl.accept(self)
+        for msgDecl in p.messageDecls:
+            msgDecl.accept(self)
         self.println()
 
         self.dedent()
         self.println('}')
-        self.write('}\n'* len(p.namespaces))
+        self.write('}\n' * len(p.namespaces))
 
     def visitManagerStmt(self, mgr):
-        self.printdentln('manager '+ mgr.name +';')
+        self.printdentln('manager ' + mgr.name + ';')
 
     def visitManagesStmt(self, mgs):
-        self.printdentln('manages '+ mgs.name +';')
+        self.printdentln('manages ' + mgs.name + ';')
 
     def visitMessageDecl(self, msg):
-        self.printdent('%s %s %s('% (msg.sendSemantics[0], msg.direction[0], msg.name))
+        self.printdent('%s %s %s(' % (msg.sendSemantics[0], msg.direction[0], msg.name))
         for i, inp in enumerate(msg.inParams):
             inp.accept(self)
-            if i != (len(msg.inParams) - 1):  self.write(', ')
+            if i != (len(msg.inParams) - 1):
+                self.write(', ')
         self.write(')')
         if 0 == len(msg.outParams):
             self.println(';')
             return
 
         self.println()
         self.indent()
         self.printdent('returns (')
         for i, outp in enumerate(msg.outParams):
             outp.accept(self)
-            if i != (len(msg.outParams) - 1):  self.write(', ')
+            if i != (len(msg.outParams) - 1):
+                self.write(', ')
         self.println(');')
         self.dedent()
--- a/ipc/ipdl/ipdl/checker.py
+++ b/ipc/ipdl/ipdl/checker.py
@@ -1,20 +1,22 @@
 # vim: set ts=4 sw=4 tw=99 et:
 # 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/.
 
 import sys
 from ipdl.ast import Visitor, ASYNC
 
+
 class SyncMessageChecker(Visitor):
     syncMsgList = []
     seenProtocols = []
     seenSyncMessages = []
+
     def __init__(self, syncMsgList):
         SyncMessageChecker.syncMsgList = syncMsgList
         self.errors = []
 
     def prettyMsgName(self, msg):
         return "%s::%s" % (self.currentProtocol, msg)
 
     def errorUnknownSyncMessage(self, loc, msg):
@@ -39,25 +41,27 @@ class SyncMessageChecker(Visitor):
             SyncMessageChecker.seenSyncMessages.append(pn)
         elif pn in SyncMessageChecker.syncMsgList:
             self.errorAsyncMessageCanRemove(md.loc, pn)
 
     @staticmethod
     def getFixedSyncMessages():
         return set(SyncMessageChecker.syncMsgList) - set(SyncMessageChecker.seenSyncMessages)
 
+
 def checkSyncMessage(tu, syncMsgList, errout=sys.stderr):
     checker = SyncMessageChecker(syncMsgList)
     tu.accept(checker)
     if len(checker.errors):
         for error in checker.errors:
             print >>errout, error
         return False
     return True
 
+
 def checkFixedSyncMessages(config, errout=sys.stderr):
     fixed = SyncMessageChecker.getFixedSyncMessages()
     error_free = True
     for item in fixed:
         protocol = item.split('::')[0]
         # Ignore things like sync messages in test protocols we didn't compile.
         # Also, ignore platform-specific IPC messages.
         if protocol in SyncMessageChecker.seenProtocols and \
--- a/ipc/ipdl/ipdl/cxx/__init__.py
+++ b/ipc/ipdl/ipdl/cxx/__init__.py
@@ -1,6 +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/.
-
-import ipdl.cxx.ast
-import ipdl.cxx.cgen
--- a/ipc/ipdl/ipdl/cxx/ast.py
+++ b/ipc/ipdl/ipdl/cxx/ast.py
@@ -1,18 +1,19 @@
 # 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/.
 
-import copy, sys
+import copy
+
 
 class Visitor:
     def defaultVisit(self, node):
-        raise Exception, "INTERNAL ERROR: no visitor for node type `%s'"% (
-            node.__class__.__name__)
+        raise Exception("INTERNAL ERROR: no visitor for node type `%s'" %
+                        (node.__class__.__name__))
 
     def visitWhitespace(self, ws):
         pass
 
     def visitFile(self, f):
         for thing in f.stuff:
             thing.accept(self)
 
@@ -214,90 +215,105 @@ class Visitor:
 
     def visitStmtExpr(self, se):
         se.expr.accept(self)
 
     def visitStmtReturn(self, sr):
         if sr.expr is not None:
             sr.expr.accept(self)
 
-##------------------------------
+# ------------------------------
+
+
 class Node:
     def __init__(self):
         pass
 
     def accept(self, visitor):
-        visit = getattr(visitor, 'visit'+ self.__class__.__name__, None)
+        visit = getattr(visitor, 'visit' + self.__class__.__name__, None)
         if visit is None:
             return getattr(visitor, 'defaultVisit')(self)
         return visit(self)
 
+
 class Whitespace(Node):
     # yes, this is silly.  but we need to stick comments in the
     # generated code without resorting to more serious hacks
     def __init__(self, ws, indent=0):
         Node.__init__(self)
         self.ws = ws
         self.indent = indent
+
+
 Whitespace.NL = Whitespace('\n')
 
+
 class File(Node):
     def __init__(self, filename):
         Node.__init__(self)
         self.name = filename
         # array of stuff in the file --- stmts and preprocessor thingies
-        self.stuff = [ ]
+        self.stuff = []
 
     def addthing(self, thing):
         assert thing is not None
         assert not isinstance(thing, list)
         self.stuff.append(thing)
 
     def addthings(self, things):
-        for t in things:  self.addthing(t)
+        for t in things:
+            self.addthing(t)
 
     # "look like" a Block so code doesn't have to care whether they're
     # in global scope or not
     def addstmt(self, stmt):
         assert stmt is not None
         assert not isinstance(stmt, list)
         self.stuff.append(stmt)
 
     def addstmts(self, stmts):
-        for s in stmts:  self.addstmt(s)
+        for s in stmts:
+            self.addstmt(s)
+
 
 class CppDirective(Node):
     '''represents |#[directive] [rest]|, where |rest| is any string'''
+
     def __init__(self, directive, rest=None):
         Node.__init__(self)
         self.directive = directive
         self.rest = rest
 
+
 class Block(Node):
     def __init__(self):
         Node.__init__(self)
-        self.stmts = [ ]
+        self.stmts = []
 
     def addstmt(self, stmt):
         assert stmt is not None
         assert not isinstance(stmt, tuple)
         self.stmts.append(stmt)
 
     def addstmts(self, stmts):
-        for s in stmts:  self.addstmt(s)
+        for s in stmts:
+            self.addstmt(s)
 
-##------------------------------
+# ------------------------------
 # type and decl thingies
+
+
 class Namespace(Block):
     def __init__(self, name):
         assert isinstance(name, str)
 
         Block.__init__(self)
         self.name = name
 
+
 class Type(Node):
     def __init__(self, name, const=0,
                  ptr=0, ptrconst=0, ptrptr=0, ptrconstptr=0,
                  ref=0,
                  hasimplicitcopyctor=True,
                  T=None,
                  inner=None):
         """
@@ -326,186 +342,210 @@ Any type, naked or pointer, can be const
         self.ptrptr = ptrptr
         self.ptrconstptr = ptrconstptr
         self.ref = ref
         self.hasimplicitcopyctor = hasimplicitcopyctor
         self.T = T
         self.inner = inner
         # XXX could get serious here with recursive types, but shouldn't
         # need that for this codegen
+
     def __deepcopy__(self, memo):
         return Type(self.name,
                     const=self.const,
                     ptr=self.ptr, ptrconst=self.ptrconst,
                     ptrptr=self.ptrptr, ptrconstptr=self.ptrconstptr,
                     ref=self.ref,
                     T=copy.deepcopy(self.T, memo),
                     inner=copy.deepcopy(self.inner, memo))
+
+
 Type.BOOL = Type('bool')
 Type.INT = Type('int')
 Type.INT32 = Type('int32_t')
 Type.INTPTR = Type('intptr_t')
 Type.NSRESULT = Type('nsresult')
 Type.UINT32 = Type('uint32_t')
 Type.UINT32PTR = Type('uint32_t', ptr=1)
 Type.SIZE = Type('size_t')
 Type.VOID = Type('void')
 Type.VOIDPTR = Type('void', ptr=1)
 Type.AUTO = Type('auto')
 
+
 class TypeArray(Node):
     def __init__(self, basetype, nmemb):
         '''the type |basetype DECLNAME[nmemb]|.  |nmemb| is an Expr'''
         self.basetype = basetype
         self.nmemb = nmemb
-    def __deepcopy__(self, memo):
-        return TypeArray(deepcopy(self.basetype, memo), nmemb)
+
 
 class TypeEnum(Node):
     def __init__(self, name=None):
         '''name can be None'''
         Node.__init__(self)
         self.name = name
-        self.idnums = [ ]    # pairs of ('Foo', [num]) or ('Foo', None)
+        self.idnums = []    # pairs of ('Foo', [num]) or ('Foo', None)
 
     def addId(self, id, num=None):
         self.idnums.append((id, num))
 
+
 class TypeUnion(Node):
     def __init__(self, name=None):
         Node.__init__(self)
         self.name = name
-        self.components = [ ]           # [ Decl ]
+        self.components = []           # [ Decl ]
 
     def addComponent(self, type, name):
         self.components.append(Decl(type, name))
 
+
 class TypeFunction(Node):
-    def __init__(self, params=[ ], ret=Type('void')):
+    def __init__(self, params=[], ret=Type('void')):
         '''Anonymous function type std::function<>'''
         self.params = params
         self.ret = ret
 
+
 class Typedef(Node):
     def __init__(self, fromtype, totypename, templateargs=[]):
         assert isinstance(totypename, str)
 
         Node.__init__(self)
         self.fromtype = fromtype
         self.totypename = totypename
         self.templateargs = templateargs
 
     def __cmp__(self, o):
         return cmp(self.totypename, o.totypename)
+
     def __eq__(self, o):
         return (self.__class__ == o.__class__
                 and 0 == cmp(self, o))
+
     def __hash__(self):
         return hash(self.totypename)
 
+
 class Using(Node):
     def __init__(self, type):
         Node.__init__(self)
         self.type = type
 
+
 class ForwardDecl(Node):
     def __init__(self, pqname, cls=0, struct=0):
         assert (not cls and struct) or (cls and not struct)
 
         self.pqname = pqname
         self.cls = cls
         self.struct = struct
 
+
 class Decl(Node):
     '''represents |Foo bar|, e.g. in a function signature'''
+
     def __init__(self, type, name):
         assert type is not None
         assert not isinstance(type, str)
         assert isinstance(name, str)
 
         Node.__init__(self)
         self.type = type
         self.name = name
+
     def __deepcopy__(self, memo):
         return Decl(copy.deepcopy(self.type, memo), self.name)
 
+
 class Param(Decl):
     def __init__(self, type, name, default=None):
         Decl.__init__(self, type, name)
         self.default = default
+
     def __deepcopy__(self, memo):
         return Param(copy.deepcopy(self.type, memo), self.name,
                      copy.deepcopy(self.default, memo))
 
-##------------------------------
+# ------------------------------
 # class stuff
+
+
 class Class(Block):
-    def __init__(self, name, inherits=[ ],
+    def __init__(self, name, inherits=[],
                  interface=0, abstract=0, final=0,
                  specializes=None, struct=0):
         assert not (interface and abstract)
         assert not (abstract and final)
         assert not (interface and final)
         assert not (inherits and specializes)
 
         Block.__init__(self)
         self.name = name
         self.inherits = inherits        # [ Type ]
         self.interface = interface      # bool
         self.abstract = abstract        # bool
         self.final = final              # bool
         self.specializes = specializes  # Type or None
         self.struct = struct            # bool
 
+
 class Inherit(Node):
     def __init__(self, type, viz='public'):
         assert isinstance(viz, str)
         Node.__init__(self)
         self.type = type
         self.viz = viz
 
+
 class FriendClassDecl(Node):
     def __init__(self, friend):
         Node.__init__(self)
         self.friend = friend
 
 # Python2 polyfill for Python3's Enum() functional API.
+
+
 def make_enum(name, members_str):
     members_list = members_str.split()
     members_dict = {}
     member_value = 1
     for member in members_list:
         members_dict[member] = member_value
         member_value += 1
     return type(name, (), members_dict)
 
+
 MethodSpec = make_enum('MethodSpec', 'NONE VIRTUAL PURE OVERRIDE STATIC')
 
+
 class MethodDecl(Node):
-    def __init__(self, name, params=[ ], ret=Type('void'),
+    def __init__(self, name, params=[], ret=Type('void'),
                  methodspec=MethodSpec.NONE, const=0, warn_unused=0,
                  force_inline=0, typeop=None, T=None, cls=None):
         assert not (name and typeop)
         assert name is None or isinstance(name, str)
         assert not isinstance(ret, list)
-        for decl in params:  assert not isinstance(decl, str)
+        for decl in params:
+            assert not isinstance(decl, str)
         assert not isinstance(T, int)
 
         if typeop is not None:
             assert methodspec == MethodSpec.NONE
             ret = None
 
         Node.__init__(self)
         self.name = name
         self.params = params            # [ Param ]
         self.ret = ret                  # Type or None
         self.methodspec = methodspec    # enum
         self.const = const              # bool
         self.warn_unused = warn_unused  # bool
-        self.force_inline = (force_inline or T) # bool
+        self.force_inline = (force_inline or T)  # bool
         self.typeop = typeop            # Type or None
         self.T = T                      # Type or None
         self.cls = cls                  # Class or None
         self.only_for_definition = False
 
     def __deepcopy__(self, memo):
         return MethodDecl(
             self.name,
@@ -513,291 +553,337 @@ class MethodDecl(Node):
             ret=copy.deepcopy(self.ret, memo),
             methodspec=self.methodspec,
             const=self.const,
             warn_unused=self.warn_unused,
             force_inline=self.force_inline,
             typeop=copy.deepcopy(self.typeop, memo),
             T=copy.deepcopy(self.T, memo))
 
+
 class MethodDefn(Block):
     def __init__(self, decl):
         Block.__init__(self)
         self.decl = decl
 
+
 class FunctionDecl(MethodDecl):
-    def __init__(self, name, params=[ ], ret=Type('void'),
+    def __init__(self, name, params=[], ret=Type('void'),
                  methodspec=MethodSpec.NONE, warn_unused=0,
                  force_inline=0, T=None):
         assert methodspec == MethodSpec.NONE or methodspec == MethodSpec.STATIC
         MethodDecl.__init__(self, name, params=params, ret=ret,
                             methodspec=methodspec, warn_unused=warn_unused,
                             force_inline=force_inline, T=T)
 
+
 class FunctionDefn(MethodDefn):
     def __init__(self, decl):
         MethodDefn.__init__(self, decl)
 
+
 class ConstructorDecl(MethodDecl):
-    def __init__(self, name, params=[ ], explicit=0, force_inline=0):
+    def __init__(self, name, params=[], explicit=0, force_inline=0):
         MethodDecl.__init__(self, name, params=params, ret=None,
                             force_inline=force_inline)
         self.explicit = explicit
 
     def __deepcopy__(self, memo):
         return ConstructorDecl(self.name,
                                copy.deepcopy(self.params, memo),
                                self.explicit)
 
+
 class ConstructorDefn(MethodDefn):
-    def __init__(self, decl, memberinits=[ ]):
+    def __init__(self, decl, memberinits=[]):
         MethodDefn.__init__(self, decl)
         self.memberinits = memberinits
 
+
 class DestructorDecl(MethodDecl):
     def __init__(self, name, methodspec=MethodSpec.NONE, force_inline=0):
         # C++ allows pure or override destructors, but ipdl cgen does not.
         assert methodspec == MethodSpec.NONE or methodspec == MethodSpec.VIRTUAL
-        MethodDecl.__init__(self, name, params=[ ], ret=None,
+        MethodDecl.__init__(self, name, params=[], ret=None,
                             methodspec=methodspec, force_inline=force_inline)
 
     def __deepcopy__(self, memo):
         return DestructorDecl(self.name,
                               methodspec=self.methodspec,
                               force_inline=self.force_inline)
 
+
 class DestructorDefn(MethodDefn):
     def __init__(self, decl):  MethodDefn.__init__(self, decl)
 
-##------------------------------
+# ------------------------------
 # expressions
+
+
 class ExprVar(Node):
     def __init__(self, name):
         assert isinstance(name, str)
-        
+
         Node.__init__(self)
         self.name = name
+
+
 ExprVar.THIS = ExprVar('this')
 
+
 class ExprLiteral(Node):
     def __init__(self, value, type):
         '''|type| is a Python format specifier; 'd' for example'''
         Node.__init__(self)
         self.value = value
         self.type = type
 
     @staticmethod
-    def Int(i):  return ExprLiteral(i, 'd')
+    def Int(i): return ExprLiteral(i, 'd')
+
+    @staticmethod
+    def String(s): return ExprLiteral('"' + s + '"', 's')
 
     @staticmethod
-    def String(s):  return ExprLiteral('"'+ s +'"', 's')
-
-    @staticmethod
-    def WString(s):  return ExprLiteral('L"'+ s +'"', 's')
+    def WString(s): return ExprLiteral('L"' + s + '"', 's')
 
     def __str__(self):
-        return ('%'+ self.type)% (self.value)
+        return ('%' + self.type) % (self.value)
+
+
 ExprLiteral.ZERO = ExprLiteral.Int(0)
 ExprLiteral.ONE = ExprLiteral.Int(1)
 ExprLiteral.NULL = ExprVar('nullptr')
 ExprLiteral.TRUE = ExprVar('true')
 ExprLiteral.FALSE = ExprVar('false')
 
+
 class ExprPrefixUnop(Node):
     def __init__(self, expr, op):
         assert not isinstance(expr, tuple)
         self.expr = expr
         self.op = op
 
+
 class ExprNot(ExprPrefixUnop):
     def __init__(self, expr):
         ExprPrefixUnop.__init__(self, expr, '!')
 
+
 class ExprAddrOf(ExprPrefixUnop):
     def __init__(self, expr):
         ExprPrefixUnop.__init__(self, expr, '&')
 
+
 class ExprDeref(ExprPrefixUnop):
     def __init__(self, expr):
         ExprPrefixUnop.__init__(self, expr, '*')
 
+
 class ExprCast(Node):
     def __init__(self, expr, type,
                  dynamic=0, static=0, reinterpret=0, const=0, C=0):
-        assert 1 == reduce(lambda a, x: a+x, [ dynamic, static, reinterpret, const, C ])
+        assert 1 == reduce(lambda a, x: a+x, [dynamic, static, reinterpret, const, C])
 
         Node.__init__(self)
         self.expr = expr
         self.type = type
         self.dynamic = dynamic
         self.static = static
         self.reinterpret = reinterpret
         self.const = const
         self.C = C
 
+
 class ExprBinary(Node):
     def __init__(self, left, op, right):
         Node.__init__(self)
         self.left = left
         self.op = op
         self.right = right
 
+
 class ExprConditional(Node):
     def __init__(self, cond, ife, elsee):
         Node.__init__(self)
         self.cond = cond
         self.ife = ife
         self.elsee = elsee
 
+
 class ExprIndex(Node):
     def __init__(self, arr, idx):
         Node.__init__(self)
         self.arr = arr
         self.idx = idx
 
+
 class ExprSelect(Node):
     def __init__(self, obj, op, field):
         assert obj and op and field
         assert not isinstance(obj, str)
         assert isinstance(op, str)
-        
+
         Node.__init__(self)
         self.obj = obj
         self.op = op
         if isinstance(field, str):
             self.field = ExprVar(field)
         else:
             self.field = field
 
+
 class ExprAssn(Node):
     def __init__(self, lhs, rhs, op='='):
         Node.__init__(self)
         self.lhs = lhs
         self.op = op
         self.rhs = rhs
 
+
 class ExprCall(Node):
-    def __init__(self, func, args=[ ]):
+    def __init__(self, func, args=[]):
         assert hasattr(func, 'accept')
         assert isinstance(args, list)
-        for arg in args:  assert arg and not isinstance(arg, str)
+        for arg in args:
+            assert arg and not isinstance(arg, str)
 
         Node.__init__(self)
         self.func = func
         self.args = args
 
+
 class ExprMove(ExprCall):
     def __init__(self, arg):
         ExprCall.__init__(self, ExprVar("std::move"), args=[arg])
 
+
 class ExprNew(Node):
     # XXX taking some poetic license ...
-    def __init__(self, ctype, args=[ ], newargs=None):
+    def __init__(self, ctype, args=[], newargs=None):
         assert not (ctype.const or ctype.ref)
 
         Node.__init__(self)
         self.ctype = ctype
         self.args = args
         self.newargs = newargs
 
+
 class ExprDelete(Node):
     def __init__(self, obj):
         Node.__init__(self)
         self.obj = obj
 
+
 class ExprMemberInit(ExprCall):
-    def __init__(self, member, args=[ ]):
+    def __init__(self, member, args=[]):
         ExprCall.__init__(self, member, args)
 
+
 class ExprSizeof(ExprCall):
     def __init__(self, t):
-        ExprCall.__init__(self, ExprVar('sizeof'), [ t ])
+        ExprCall.__init__(self, ExprVar('sizeof'), [t])
+
 
 class ExprLambda(Block):
-    def __init__(self, captures=[ ], params=[ ], ret=None):
+    def __init__(self, captures=[], params=[], ret=None):
         Block.__init__(self)
         assert isinstance(captures, list)
         assert isinstance(params, list)
         self.captures = captures
         self.params = params
         self.ret = ret
 
-##------------------------------
+# ------------------------------
 # statements etc.
+
+
 class StmtBlock(Block):
-    def __init__(self, stmts=[ ]):
+    def __init__(self, stmts=[]):
         Block.__init__(self)
         self.addstmts(stmts)
 
+
 class StmtDecl(Node):
     def __init__(self, decl, init=None, initargs=None):
         assert not (init and initargs)
-        assert not isinstance(init, str) # easy to confuse with Decl
+        assert not isinstance(init, str)  # easy to confuse with Decl
         assert not isinstance(init, list)
         assert not isinstance(decl, tuple)
-        
+
         Node.__init__(self)
         self.decl = decl
         self.init = init
         self.initargs = initargs
 
+
 class Label(Node):
     def __init__(self, name):
         Node.__init__(self)
         self.name = name
+
+
 Label.PUBLIC = Label('public')
 Label.PROTECTED = Label('protected')
 Label.PRIVATE = Label('private')
 
+
 class CaseLabel(Node):
     def __init__(self, name):
         Node.__init__(self)
         self.name = name
 
+
 class DefaultLabel(Node):
     def __init__(self):
         Node.__init__(self)
 
+
 class StmtIf(Node):
     def __init__(self, cond):
         Node.__init__(self)
         self.cond = cond
         self.ifb = Block()
         self.elseb = None
 
     def addifstmt(self, stmt):
         self.ifb.addstmt(stmt)
 
     def addifstmts(self, stmts):
         self.ifb.addstmts(stmts)
-        
+
     def addelsestmt(self, stmt):
-        if self.elseb is None: self.elseb = Block()
+        if self.elseb is None:
+            self.elseb = Block()
         self.elseb.addstmt(stmt)
 
     def addelsestmts(self, stmts):
-        if self.elseb is None: self.elseb = Block()
+        if self.elseb is None:
+            self.elseb = Block()
         self.elseb.addstmts(stmts)
 
+
 class StmtFor(Block):
     def __init__(self, init=None, cond=None, update=None):
         Block.__init__(self)
         self.init = init
         self.cond = cond
         self.update = update
 
+
 class StmtRangedFor(Block):
     def __init__(self, var, iteree):
         assert isinstance(var, ExprVar)
         assert iteree
 
         Block.__init__(self)
         self.var = var
         self.iteree = iteree
 
+
 class StmtSwitch(Block):
     def __init__(self, expr):
         Block.__init__(self)
         self.expr = expr
         self.nr_cases = 0
 
     def addcase(self, case, block):
         '''NOTE: |case| is not checked for uniqueness'''
@@ -811,26 +897,30 @@ class StmtSwitch(Block):
         self.addstmt(case)
         self.addstmt(block)
         self.nr_cases += 1
 
     def addfallthrough(self, case):
         self.addstmt(case)
         self.nr_cases += 1
 
+
 class StmtBreak(Node):
     def __init__(self):
         Node.__init__(self)
 
+
 class StmtExpr(Node):
     def __init__(self, expr):
         assert expr is not None
-        
+
         Node.__init__(self)
         self.expr = expr
 
+
 class StmtReturn(Node):
     def __init__(self, expr=None):
         Node.__init__(self)
         self.expr = expr
 
+
 StmtReturn.TRUE = StmtReturn(ExprLiteral.TRUE)
 StmtReturn.FALSE = StmtReturn(ExprLiteral.FALSE)
--- a/ipc/ipdl/ipdl/cxx/cgen.py
+++ b/ipc/ipdl/ipdl/cxx/cgen.py
@@ -2,38 +2,39 @@
 # 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/.
 
 import sys
 
 from ipdl.cgen import CodePrinter
 from ipdl.cxx.ast import MethodSpec, TypeArray, Visitor, DestructorDecl
 
+
 class CxxCodeGen(CodePrinter, Visitor):
     def __init__(self, outf=sys.stdout, indentCols=4):
         CodePrinter.__init__(self, outf, indentCols)
 
     def cgen(self, cxxfile):
         cxxfile.accept(self)
 
     def visitWhitespace(self, ws):
         if ws.indent:
             self.printdent('')
         self.write(ws.ws)
 
     def visitCppDirective(self, cd):
         if cd.rest:
-            self.println('#%s %s'% (cd.directive, cd.rest))
+            self.println('#%s %s' % (cd.directive, cd.rest))
         else:
-            self.println('#%s'% (cd.directive))
+            self.println('#%s' % (cd.directive))
 
     def visitNamespace(self, ns):
-        self.println('namespace '+ ns.name +' {')
+        self.println('namespace ' + ns.name + ' {')
         self.visitBlock(ns)
-        self.println('} // namespace '+ ns.name)
+        self.println('} // namespace ' + ns.name)
 
     def visitType(self, t):
         if t.const:
             self.write('const ')
 
         self.write(t.name)
 
         if t.T is not None:
@@ -47,47 +48,51 @@ class CxxCodeGen(CodePrinter, Visitor):
                 t.T.accept(self)
             self.write('>')
 
         if t.inner is not None:
             self.write('::')
             t.inner.accept(self)
 
         ts = ''
-        if t.ptr:            ts += '*'
-        elif t.ptrconst:     ts += '* const'
-        elif t.ptrptr:       ts += '**'
-        elif t.ptrconstptr:  ts += '* const*'
+        if t.ptr:
+            ts += '*'
+        elif t.ptrconst:
+            ts += '* const'
+        elif t.ptrptr:
+            ts += '**'
+        elif t.ptrconstptr:
+            ts += '* const*'
 
         ts += '&' * t.ref
 
         self.write(ts)
 
     def visitTypeEnum(self, te):
         self.write('enum')
         if te.name:
-            self.write(' '+ te.name)
+            self.write(' ' + te.name)
         self.println(' {')
 
         self.indent()
         nids = len(te.idnums)
         for i, (id, num) in enumerate(te.idnums):
             self.printdent(id)
             if num:
-                self.write(' = '+ str(num))
+                self.write(' = ' + str(num))
             if i != (nids-1):
                 self.write(',')
             self.println()
         self.dedent()
         self.printdent('}')
 
     def visitTypeUnion(self, u):
         self.write('union')
         if u.name:
-            self.write(' '+ u.name)
+            self.write(' ' + u.name)
         self.println(' {')
 
         self.indent()
         for decl in u.components:
             self.printdent()
             decl.accept(self)
             self.println(';')
         self.dedent()
@@ -98,46 +103,48 @@ class CxxCodeGen(CodePrinter, Visitor):
         self.write('std::function<')
         fn.ret.accept(self)
         self.write('(')
         self.writeDeclList(fn.params)
         self.write(')>')
 
     def visitTypedef(self, td):
         if td.templateargs:
-            formals = ', '.join([ 'class ' + T for T in td.templateargs ])
+            formals = ', '.join(['class ' + T for T in td.templateargs])
             args = ', '.join(td.templateargs)
             self.printdent('template<' + formals + '> using ' + td.totypename + ' = ')
             td.fromtype.accept(self)
             self.println('<' + args + '>;')
         else:
             self.printdent('typedef ')
             td.fromtype.accept(self)
-            self.println(' '+ td.totypename +';')
+            self.println(' ' + td.totypename + ';')
 
     def visitUsing(self, us):
         self.printdent('using ')
         us.type.accept(self)
         self.println(';')
 
     def visitForwardDecl(self, fd):
-        if fd.cls:      self.printdent('class ')
-        elif fd.struct: self.printdent('struct ')
+        if fd.cls:
+            self.printdent('class ')
+        elif fd.struct:
+            self.printdent('struct ')
         self.write(str(fd.pqname))
         self.println(';')
 
     def visitDecl(self, d):
         # C-syntax arrays make code generation much more annoying
         if isinstance(d.type, TypeArray):
             d.type.basetype.accept(self)
         else:
             d.type.accept(self)
 
         if d.name:
-            self.write(' '+ d.name)
+            self.write(' ' + d.name)
 
         if isinstance(d.type, TypeArray):
             self.write('[')
             d.type.nmemb.accept(self)
             self.write(']')
 
     def visitParam(self, p):
         self.visitDecl(p)
@@ -148,17 +155,17 @@ class CxxCodeGen(CodePrinter, Visitor):
     def visitClass(self, c):
         if c.specializes is not None:
             self.printdentln('template<>')
 
         if c.struct:
             self.printdent('struct')
         else:
             self.printdent('class')
-        self.write(' '+ c.name)
+        self.write(' ' + c.name)
         if c.final:
             self.write(' final')
 
         if c.specializes is not None:
             self.write(' <')
             c.specializes.accept(self)
             self.write('>')
 
@@ -178,38 +185,37 @@ class CxxCodeGen(CodePrinter, Visitor):
         self.indent()
 
         self.visitBlock(c)
 
         self.dedent()
         self.printdentln('};')
 
     def visitInherit(self, inh):
-        self.write(inh.viz +' ')
+        self.write(inh.viz + ' ')
         inh.type.accept(self)
 
     def visitFriendClassDecl(self, fcd):
-        self.printdentln('friend class '+ fcd.friend +';')
-
+        self.printdentln('friend class ' + fcd.friend + ';')
 
     def visitMethodDecl(self, md):
         if md.T:
             self.write('template<')
             self.write('typename ')
             md.T.accept(self)
             self.println('>')
             self.printdent()
 
         if md.warn_unused:
             self.write('MOZ_MUST_USE ')
 
         if md.methodspec == MethodSpec.STATIC:
             self.write('static ')
         elif md.methodspec == MethodSpec.VIRTUAL or \
-             md.methodspec == MethodSpec.PURE:
+                md.methodspec == MethodSpec.PURE:
             self.write('virtual ')
 
         if md.ret:
             if md.only_for_definition:
                 self.write('auto ')
             else:
                 md.ret.accept(self)
                 self.println()
@@ -243,32 +249,30 @@ class CxxCodeGen(CodePrinter, Visitor):
             self.write(' -> ')
             md.ret.accept(self)
 
         if md.methodspec == MethodSpec.OVERRIDE:
             self.write(' override')
         elif md.methodspec == MethodSpec.PURE:
             self.write(' = 0')
 
-
     def visitMethodDefn(self, md):
         if md.decl.methodspec == MethodSpec.PURE:
             return
 
         self.printdent()
         md.decl.accept(self)
         self.println()
 
         self.printdentln('{')
         self.indent()
         self.visitBlock(md)
         self.dedent()
         self.printdentln('}')
 
-
     def visitConstructorDecl(self, cd):
         if cd.explicit:
             self.write('explicit ')
         else:
             self.write('MOZ_IMPLICIT ')
         self.visitMethodDecl(cd)
 
     def visitConstructorDefn(self, cd):
@@ -289,65 +293,68 @@ class CxxCodeGen(CodePrinter, Visitor):
         self.printdentln('{')
         self.indent()
 
         self.visitBlock(cd)
 
         self.dedent()
         self.printdentln('}')
 
-
     def visitDestructorDecl(self, dd):
         self.visitMethodDecl(dd)
 
     def visitDestructorDefn(self, dd):
         self.printdent()
         dd.decl.accept(self)
         self.println()
 
         self.printdentln('{')
         self.indent()
 
         self.visitBlock(dd)
 
         self.dedent()
         self.printdentln('}')
 
-
     def visitExprLiteral(self, el):
         self.write(str(el))
 
     def visitExprVar(self, ev):
         self.write(ev.name)
 
     def visitExprPrefixUnop(self, e):
         self.write('(')
         self.write(e.op)
         self.write('(')
         e.expr.accept(self)
         self.write(')')
         self.write(')')
 
     def visitExprCast(self, c):
         pfx, sfx = '', ''
-        if c.dynamic:        pfx, sfx = 'dynamic_cast<', '>'
-        elif c.static:       pfx, sfx = 'static_cast<', '>'
-        elif c.reinterpret:  pfx, sfx = 'reinterpret_cast<', '>'
-        elif c.const:        pfx, sfx = 'const_cast<', '>'
-        elif c.C:            pfx, sfx = '(', ')'
+        if c.dynamic:
+            pfx, sfx = 'dynamic_cast<', '>'
+        elif c.static:
+            pfx, sfx = 'static_cast<', '>'
+        elif c.reinterpret:
+            pfx, sfx = 'reinterpret_cast<', '>'
+        elif c.const:
+            pfx, sfx = 'const_cast<', '>'
+        elif c.C:
+            pfx, sfx = '(', ')'
         self.write(pfx)
         c.type.accept(self)
-        self.write(sfx +'(')
+        self.write(sfx + '(')
         c.expr.accept(self)
         self.write(')')
 
     def visitExprBinary(self, e):
         self.write('(')
         e.left.accept(self)
-        self.write(') '+ e.op +' (')
+        self.write(') ' + e.op + ' (')
         e.right.accept(self)
         self.write(')')
 
     def visitExprConditional(self, c):
         self.write('(')
         c.cond.accept(self)
         self.write(' ? ')
         c.ife.accept(self)
@@ -365,17 +372,17 @@ class CxxCodeGen(CodePrinter, Visitor):
         self.write('(')
         es.obj.accept(self)
         self.write(')')
         self.write(es.op)
         es.field.accept(self)
 
     def visitExprAssn(self, ea):
         ea.lhs.accept(self)
-        self.write(' '+ ea.op +' ')
+        self.write(' ' + ea.op + ' ')
         ea.rhs.accept(self)
 
     def visitExprCall(self, ec):
         ec.func.accept(self)
         self.write('(')
         self.writeExprList(ec.args)
         self.write(')')
 
@@ -421,47 +428,45 @@ class CxxCodeGen(CodePrinter, Visitor):
         self.printdentln('{')
         self.indent()
         self.visitBlock(b)
         self.dedent()
         self.printdentln('}')
 
     def visitLabel(self, label):
         self.dedent()           # better not be at global scope ...
-        self.printdentln(label.name +':')
+        self.printdentln(label.name + ':')
         self.indent()
 
     def visitCaseLabel(self, cl):
         self.dedent()
-        self.printdentln('case '+ cl.name +':')
+        self.printdentln('case ' + cl.name + ':')
         self.indent()
 
     def visitDefaultLabel(self, dl):
         self.dedent()
         self.printdentln('default:')
         self.indent()
 
-
     def visitStmtIf(self, si):
         self.printdent('if (')
         si.cond.accept(self)
         self.println(') {')
         self.indent()
         si.ifb.accept(self)
         self.dedent()
         self.printdentln('}')
 
         if si.elseb is not None:
             self.printdentln('else {')
             self.indent()
             si.elseb.accept(self)
             self.dedent()
             self.printdentln('}')
 
-
     def visitStmtFor(self, sf):
         self.printdent('for (')
         if sf.init is not None:
             sf.init.accept(self)
         self.write('; ')
         if sf.cond is not None:
             sf.cond.accept(self)
         self.write('; ')
@@ -469,70 +474,64 @@ class CxxCodeGen(CodePrinter, Visitor):
             sf.update.accept(self)
         self.println(') {')
 
         self.indent()
         self.visitBlock(sf)
         self.dedent()
         self.printdentln('}')
 
-
     def visitStmtRangedFor(self, rf):
         self.printdent('for (auto& ')
         rf.var.accept(self)
         self.write(' : ')
         rf.iteree.accept(self)
         self.println(') {')
 
         self.indent()
         self.visitBlock(rf)
         self.dedent()
         self.printdentln('}')
 
-
     def visitStmtSwitch(self, sw):
         self.printdent('switch (')
         sw.expr.accept(self)
         self.println(') {')
         self.indent()
         self.visitBlock(sw)
         self.dedent()
         self.printdentln('}')
 
     def visitStmtBreak(self, sb):
         self.printdentln('break;')
 
-
     def visitStmtDecl(self, sd):
         self.printdent()
         sd.decl.accept(self)
         if sd.initargs is not None:
             self.write('(')
             self.writeDeclList(sd.initargs)
             self.write(')')
         if sd.init is not None:
             self.write(' = ')
             sd.init.accept(self)
         self.println(';')
 
-
     def visitStmtExpr(self, se):
         self.printdent()
         se.expr.accept(self)
         self.println(';')
 
-
     def visitStmtReturn(self, sr):
         self.printdent('return')
         if sr.expr:
-            self.write (' ')
+            self.write(' ')
             sr.expr.accept(self)
         self.println(';')
 
-
     def writeDeclList(self, decls):
         # FIXME/cjones: try to do nice formatting of these guys
 
         ndecls = len(decls)
         if 0 == ndecls:
             return
         elif 1 == ndecls:
             decls[0].accept(self)
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -1,448 +1,531 @@
 # 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/.
 
-import os, re, sys
+import re
 from copy import deepcopy
 from collections import OrderedDict
 
 import ipdl.ast
 import ipdl.builtin
 from ipdl.cxx.ast import *
 from ipdl.type import ActorType, UnionType, TypeVisitor, builtinHeaderIncludes
 
-##-----------------------------------------------------------------------------
-## "Public" interface to lowering
+# -----------------------------------------------------------------------------
+# "Public" interface to lowering
 ##
+
+
 class LowerToCxx:
     def lower(self, tu, segmentcapacitydict):
         '''returns |[ header: File ], [ cpp : File ]| representing the
 lowered form of |tu|'''
         # annotate the AST with IPDL/C++ IR-type stuff used later
         tu.accept(_DecorateWithCxxStuff())
 
         # Any modifications to the filename scheme here need corresponding
         # modifications in the ipdl.py driver script.
         name = tu.name
-        pheader, pcpp = File(name +'.h'), File(name +'.cpp')
+        pheader, pcpp = File(name + '.h'), File(name + '.cpp')
 
         _GenerateProtocolCode().lower(tu, pheader, pcpp, segmentcapacitydict)
-        headers = [ pheader ]
-        cpps = [ pcpp ]
+        headers = [pheader]
+        cpps = [pcpp]
 
         if tu.protocol:
             pname = tu.protocol.name
 
-            parentheader, parentcpp = File(pname +'Parent.h'), File(pname +'Parent.cpp')
+            parentheader, parentcpp = File(pname + 'Parent.h'), File(pname + 'Parent.cpp')
             _GenerateProtocolParentCode().lower(
                 tu, pname+'Parent', parentheader, parentcpp)
 
-            childheader, childcpp = File(pname +'Child.h'), File(pname +'Child.cpp')
+            childheader, childcpp = File(pname + 'Child.h'), File(pname + 'Child.cpp')
             _GenerateProtocolChildCode().lower(
                 tu, pname+'Child', childheader, childcpp)
 
-            headers += [ parentheader, childheader ]
-            cpps += [ parentcpp, childcpp ]
+            headers += [parentheader, childheader]
+            cpps += [parentcpp, childcpp]
 
         return headers, cpps
 
 
-##-----------------------------------------------------------------------------
-## Helper code
+# -----------------------------------------------------------------------------
+# Helper code
 ##
 
 def hashfunc(value):
     h = hash(value) % 2**32
-    if h < 0: h += 2**32
+    if h < 0:
+        h += 2**32
     return h
 
+
 _NULL_ACTOR_ID = ExprLiteral.ZERO
 _FREED_ACTOR_ID = ExprLiteral.ONE
 
 _DISCLAIMER = Whitespace('''//
 // Automatically generated by ipdlc.
 // Edit at your own risk
 //
 
 ''')
 
 
-class _struct: pass
+class _struct:
+    pass
+
 
 def _namespacedHeaderName(name, namespaces):
-    pfx = '/'.join([ ns.name for ns in namespaces ])
+    pfx = '/'.join([ns.name for ns in namespaces])
     if pfx:
-        return pfx +'/'+ name
+        return pfx + '/' + name
     else:
         return name
 
+
 def _ipdlhHeaderName(tu):
     assert tu.filetype == 'header'
     return _namespacedHeaderName(tu.name, tu.namespaces)
 
+
 def _protocolHeaderName(p, side=''):
-    if side: side = side.title()
+    if side:
+        side = side.title()
     base = p.name + side
     return _namespacedHeaderName(base, p.namespaces)
 
+
 def _includeGuardMacroName(headerfile):
     return re.sub(r'[./]', '_', headerfile.name)
 
+
 def _includeGuardStart(headerfile):
     guard = _includeGuardMacroName(headerfile)
-    return [ CppDirective('ifndef', guard),
-             CppDirective('define', guard)  ]
+    return [CppDirective('ifndef', guard),
+            CppDirective('define', guard)]
+
 
 def _includeGuardEnd(headerfile):
     guard = _includeGuardMacroName(headerfile)
-    return [ CppDirective('endif', '// ifndef '+ guard) ]
+    return [CppDirective('endif', '// ifndef ' + guard)]
+
 
 def _messageStartName(ptype):
-    return ptype.name() +'MsgStart'
+    return ptype.name() + 'MsgStart'
+
 
 def _protocolId(ptype):
     return ExprVar(_messageStartName(ptype))
 
+
 def _protocolIdType():
     return Type.INT32
 
+
 def _actorName(pname, side):
     """|pname| is the protocol name. |side| is 'Parent' or 'Child'."""
     tag = side
-    if not tag[0].isupper():  tag = side.title()
+    if not tag[0].isupper():
+        tag = side.title()
     return pname + tag
 
+
 def _actorIdType():
     return Type.INT32
 
+
 def _actorTypeTagType():
     return Type.INT32
 
+
 def _actorId(actor=None):
     if actor is not None:
         return ExprCall(ExprSelect(actor, '->', 'Id'))
     return ExprCall(ExprVar('Id'))
 
+
 def _actorHId(actorhandle):
     return ExprSelect(actorhandle, '.', 'mId')
 
+
 def _actorManager(actor):
     return ExprCall(ExprSelect(actor, '->', 'Manager'), args=[])
 
+
 def _actorState(actor):
     return ExprSelect(actor, '->', 'mState')
 
+
 def _backstagePass():
     return ExprCall(ExprVar('mozilla::ipc::PrivateIPDLInterface'))
 
+
 def _iterType(ptr):
     return Type('PickleIterator', ptr=ptr)
 
+
 def _deleteId():
     return ExprVar('Msg___delete____ID')
 
+
 def _deleteReplyId():
     return ExprVar('Reply___delete____ID')
 
+
 def _lookupListener(idexpr):
-    return ExprCall(ExprVar('Lookup'), args=[ idexpr ])
+    return ExprCall(ExprVar('Lookup'), args=[idexpr])
+
 
 def _makeForwardDeclForQClass(clsname, quals, cls=1, struct=0):
     fd = ForwardDecl(clsname, cls=cls, struct=struct)
     if 0 == len(quals):
         return fd
 
     outerns = Namespace(quals[0])
     innerns = outerns
     for ns in quals[1:]:
         tmpns = Namespace(ns)
         innerns.addstmt(tmpns)
         innerns = tmpns
 
     innerns.addstmt(fd)
     return outerns
 
+
 def _makeForwardDeclForActor(ptype, side):
     return _makeForwardDeclForQClass(_actorName(ptype.qname.baseid, side),
                                      ptype.qname.quals)
 
+
 def _makeForwardDecl(type):
     return _makeForwardDeclForQClass(type.name(), type.qname.quals)
 
 
 def _putInNamespaces(cxxthing, namespaces):
     """|namespaces| is in order [ outer, ..., inner ]"""
-    if 0 == len(namespaces):  return cxxthing
+    if 0 == len(namespaces):
+        return cxxthing
 
     outerns = Namespace(namespaces[0].name)
     innerns = outerns
     for ns in namespaces[1:]:
         newns = Namespace(ns.name)
         innerns.addstmt(newns)
         innerns = newns
     innerns.addstmt(cxxthing)
     return outerns
 
+
 def _sendPrefix(msgtype):
     """Prefix of the name of the C++ method that sends |msgtype|."""
     if msgtype.isInterrupt():
         return 'Call'
     return 'Send'
 
+
 def _recvPrefix(msgtype):
     """Prefix of the name of the C++ method that handles |msgtype|."""
     if msgtype.isInterrupt():
         return 'Answer'
     return 'Recv'
 
+
 def _flatTypeName(ipdltype):
     """Return a 'flattened' IPDL type name that can be used as an
 identifier.
 E.g., |Foo[]| --> |ArrayOfFoo|."""
     # NB: this logic depends heavily on what IPDL types are allowed to
     # be constructed; e.g., Foo[][] is disallowed.  needs to be kept in
     # sync with grammar.
     if ipdltype.isIPDL() and ipdltype.isArray():
-        return 'ArrayOf'+ ipdltype.basetype.name()
+        return 'ArrayOf' + ipdltype.basetype.name()
     return ipdltype.name()
 
 
 def _hasVisibleActor(ipdltype):
     """Return true iff a C++ decl of |ipdltype| would have an Actor* type.
 For example: |Actor[]| would turn into |Array<ActorParent*>|, so this
 function would return true for |Actor[]|."""
     return (ipdltype.isIPDL()
             and (ipdltype.isActor()
                  or (ipdltype.isArray()
                      and _hasVisibleActor(ipdltype.basetype))))
 
+
 def _abortIfFalse(cond, msg):
     return StmtExpr(ExprCall(
         ExprVar('MOZ_RELEASE_ASSERT'),
-        [ cond, ExprLiteral.String(msg) ]))
+        [cond, ExprLiteral.String(msg)]))
+
 
 def _refptr(T, ptr=0, ref=0):
     return Type('RefPtr', T=T, ptr=ptr, ref=ref)
 
+
 def _refptrGet(expr):
     return ExprCall(ExprSelect(expr, '.', 'get'))
 
+
 def _refptrForget(expr):
     return ExprCall(ExprSelect(expr, '.', 'forget'))
 
+
 def _refptrTake(expr):
     return ExprCall(ExprSelect(expr, '.', 'take'))
 
+
 def _uniqueptr(T):
     return Type('UniquePtr', T=T)
 
+
 def _uniqueptrGet(expr):
     return ExprCall(ExprSelect(expr, '.', 'get'))
 
+
 def _tuple(types, const=0, ref=0):
     return Type('Tuple', T=types, const=const, ref=ref)
 
+
 def _promise(resolvetype, rejecttype, tail, resolver=False):
     inner = Type('Private') if resolver else None
     return Type('MozPromise', T=[resolvetype, rejecttype, tail], inner=inner)
 
+
 def _makePromise(returns, side, resolver=False):
     if len(returns) > 1:
         resolvetype = _tuple([d.bareType(side) for d in returns])
     else:
         resolvetype = returns[0].bareType(side)
 
     needmove = not all(d.isCopyable() for d in returns)
 
     return _promise(resolvetype,
                     _ResponseRejectReason.Type(),
                     ExprLiteral.TRUE if needmove else ExprLiteral.FALSE,
                     resolver=resolver)
 
+
 def _makeResolver(returns, side):
     if len(returns) > 1:
         resolvetype = _tuple([d.moveType(side) for d in returns])
     else:
         resolvetype = returns[0].moveType(side)
     return TypeFunction([Decl(resolvetype, '')])
 
+
 def _cxxArrayType(basetype, const=0, ref=0):
     return Type('nsTArray', T=basetype, const=const, ref=ref, hasimplicitcopyctor=False)
 
+
 def _cxxManagedContainerType(basetype, const=0, ref=0):
     return Type('ManagedContainer', T=basetype,
                 const=const, ref=ref, hasimplicitcopyctor=False)
 
+
 def _callCxxArrayLength(arr):
     return ExprCall(ExprSelect(arr, '.', 'Length'))
 
+
 def _callCxxArraySetLength(arr, lenexpr, sel='.'):
     return ExprCall(ExprSelect(arr, sel, 'SetLength'),
-                    args=[ lenexpr ])
+                    args=[lenexpr])
+
 
 def _callCxxSwapArrayElements(arr1, arr2, sel='.'):
     return ExprCall(ExprSelect(arr1, sel, 'SwapElements'),
-                    args=[ arr2 ])
+                    args=[arr2])
+
 
 def _callInsertManagedActor(managees, actor):
     return ExprCall(ExprSelect(managees, '.', 'PutEntry'),
-                    args=[ actor ])
+                    args=[actor])
+
 
 def _callRemoveManagedActor(managees, actor):
     return ExprCall(ExprSelect(managees, '.', 'RemoveEntry'),
-                    args=[ actor ])
+                    args=[actor])
+
 
 def _callClearManagedActors(managees):
     return ExprCall(ExprSelect(managees, '.', 'Clear'))
 
+
 def _callHasManagedActor(managees, actor):
-    return ExprCall(ExprSelect(managees, '.', 'Contains'), args=[ actor ])
+    return ExprCall(ExprSelect(managees, '.', 'Contains'), args=[actor])
+
 
 def _otherSide(side):
-    if side == 'child':  return 'parent'
-    if side == 'parent':  return 'child'
+    if side == 'child':
+        return 'parent'
+    if side == 'parent':
+        return 'child'
     assert 0
 
+
 def _ifLogging(topLevelProtocol, stmts):
     iflogging = StmtIf(ExprCall(ExprVar('mozilla::ipc::LoggingEnabledFor'),
-                                args=[ topLevelProtocol ]))
+                                args=[topLevelProtocol]))
     iflogging.addifstmts(stmts)
     return iflogging
 
 # XXX we need to remove these and install proper error handling
+
+
 def _printErrorMessage(msg):
     if isinstance(msg, str):
         msg = ExprLiteral.String(msg)
     return StmtExpr(
-        ExprCall(ExprVar('NS_ERROR'), args=[ msg ]))
+        ExprCall(ExprVar('NS_ERROR'), args=[msg]))
+
 
 def _protocolErrorBreakpoint(msg):
     if isinstance(msg, str):
         msg = ExprLiteral.String(msg)
     return StmtExpr(ExprCall(ExprVar('mozilla::ipc::ProtocolErrorBreakpoint'),
-                             args=[ msg ]))
+                             args=[msg]))
+
 
 def _printWarningMessage(msg):
     if isinstance(msg, str):
         msg = ExprLiteral.String(msg)
     return StmtExpr(
-        ExprCall(ExprVar('NS_WARNING'), args=[ msg ]))
+        ExprCall(ExprVar('NS_WARNING'), args=[msg]))
+
 
 def _fatalError(msg):
     return StmtExpr(
-        ExprCall(ExprVar('FatalError'), args=[ ExprLiteral.String(msg) ]))
+        ExprCall(ExprVar('FatalError'), args=[ExprLiteral.String(msg)]))
+
 
 def _logicError(msg):
     return StmtExpr(
-        ExprCall(ExprVar('mozilla::ipc::LogicError'), args=[ ExprLiteral.String(msg) ]))
+        ExprCall(ExprVar('mozilla::ipc::LogicError'), args=[ExprLiteral.String(msg)]))
+
 
 def _arrayLengthReadError(elementname):
     return StmtExpr(
         ExprCall(ExprVar('mozilla::ipc::ArrayLengthReadError'),
-                 args=[ ExprLiteral.String(elementname) ]))
+                 args=[ExprLiteral.String(elementname)]))
+
 
 def _unionTypeReadError(unionname):
     return StmtExpr(
         ExprCall(ExprVar('mozilla::ipc::UnionTypeReadError'),
-                 args=[ ExprLiteral.String(unionname) ]))
+                 args=[ExprLiteral.String(unionname)]))
+
 
 def _sentinelReadError(classname):
     return StmtExpr(
         ExprCall(ExprVar('mozilla::ipc::SentinelReadError'),
-                 args=[ ExprLiteral.String(classname) ]))
+                 args=[ExprLiteral.String(classname)]))
+
 
 def _killProcess(pid):
     return ExprCall(
         ExprVar('base::KillProcess'),
-        args=[ pid,
-               # XXX this is meaningless on POSIX
-               ExprVar('base::PROCESS_END_KILLED_BY_USER'),
-               ExprLiteral.FALSE ])
+        args=[pid,
+              # XXX this is meaningless on POSIX
+              ExprVar('base::PROCESS_END_KILLED_BY_USER'),
+              ExprLiteral.FALSE])
 
 # Results that IPDL-generated code returns back to *Channel code.
 # Users never see these
+
+
 class _Result:
     @staticmethod
     def Type():
         return Type('Result')
 
     Processed = ExprVar('MsgProcessed')
     NotKnown = ExprVar('MsgNotKnown')
     NotAllowed = ExprVar('MsgNotAllowed')
     PayloadError = ExprVar('MsgPayloadError')
     ProcessingError = ExprVar('MsgProcessingError')
     RouteError = ExprVar('MsgRouteError')
-    ValuError = ExprVar('MsgValueError') # [sic]
+    ValuError = ExprVar('MsgValueError')  # [sic]
 
 # these |errfn*| are functions that generate code to be executed on an
 # error, such as "bad actor ID".  each is given a Python string
 # containing a description of the error
 
 # used in user-facing Send*() methods
+
+
 def errfnSend(msg, errcode=ExprLiteral.FALSE):
     return [
         _fatalError(msg),
         StmtReturn(errcode)
     ]
 
-def errfnSendCtor(msg):  return errfnSend(msg, errcode=ExprLiteral.NULL)
+
+def errfnSendCtor(msg): return errfnSend(msg, errcode=ExprLiteral.NULL)
 
 # TODO should this error handling be strengthened for dtors?
+
+
 def errfnSendDtor(msg):
     return [
         _printErrorMessage(msg),
         StmtReturn.FALSE
     ]
 
 # used in |OnMessage*()| handlers that hand in-messages off to Recv*()
 # interface methods
+
+
 def errfnRecv(msg, errcode=_Result.ValuError):
     return [
         _fatalError(msg),
         StmtReturn(errcode)
     ]
 
+
 def errfnSentinel(rvalue=ExprLiteral.FALSE):
     def inner(msg):
-        return [ _sentinelReadError(msg), StmtReturn(rvalue) ]
+        return [_sentinelReadError(msg), StmtReturn(rvalue)]
     return inner
 
+
 def _destroyMethod():
     return ExprVar('ActorDestroy')
 
+
 def errfnUnreachable(msg):
     return [
         _logicError(msg)
     ]
 
+
 class _DestroyReason:
     @staticmethod
-    def Type():  return Type('ActorDestroyReason')
+    def Type(): return Type('ActorDestroyReason')
 
     Deletion = ExprVar('Deletion')
     AncestorDeletion = ExprVar('AncestorDeletion')
     NormalShutdown = ExprVar('NormalShutdown')
     AbnormalShutdown = ExprVar('AbnormalShutdown')
     FailedConstructor = ExprVar('FailedConstructor')
 
+
 class _ResponseRejectReason:
     @staticmethod
     def Type():
         return Type('ResponseRejectReason')
 
     SendError = ExprVar('ResponseRejectReason::SendError')
     ChannelClosed = ExprVar('ResponseRejectReason::ChannelClosed')
     HandlerRejected = ExprVar('ResponseRejectReason::HandlerRejected')
     ActorDestroyed = ExprVar('ResponseRejectReason::ActorDestroyed')
 
 
-##-----------------------------------------------------------------------------
-## Intermediate representation (IR) nodes used during lowering
+# -----------------------------------------------------------------------------
+# Intermediate representation (IR) nodes used during lowering
 
 class _ConvertToCxxType(TypeVisitor):
     def __init__(self, side, fq):
         self.side = side
         self.fq = fq
 
     def typename(self, thing):
         if self.fq:
@@ -476,28 +559,34 @@ class _ConvertToCxxType(TypeVisitor):
 
     def visitFDType(self, s):
         return Type(self.typename(s))
 
     def visitEndpointType(self, s):
         return Type(self.typename(s))
 
     def visitProtocolType(self, p): assert 0
+
     def visitMessageType(self, m): assert 0
+
     def visitVoidType(self, v): assert 0
+
     def visitStateType(self, st): assert 0
 
+
 def _cxxBareType(ipdltype, side, fq=0):
     return ipdltype.accept(_ConvertToCxxType(side, fq))
 
+
 def _cxxRefType(ipdltype, side):
     t = _cxxBareType(ipdltype, side)
     t.ref = 1
     return t
 
+
 def _cxxConstRefType(ipdltype, side):
     t = _cxxBareType(ipdltype, side)
     if ipdltype.isIPDL() and ipdltype.isActor():
         return t
     if ipdltype.isIPDL() and ipdltype.isShmem():
         t.ref = 1
         return t
     if ipdltype.isIPDL() and ipdltype.isByteBuf():
@@ -512,71 +601,82 @@ def _cxxConstRefType(ipdltype, side):
         # Use T* instead of const RefPtr<T>&
         t = t.T
         t.ptr = 1
         return t
     t.const = 1
     t.ref = 1
     return t
 
+
 def _cxxTypeNeedsMove(ipdltype):
     return ipdltype.isIPDL() and (ipdltype.isArray() or
                                   ipdltype.isShmem() or
                                   ipdltype.isByteBuf() or
                                   ipdltype.isEndpoint())
 
+
 def _cxxTypeCanMove(ipdltype):
     return not (ipdltype.isIPDL() and ipdltype.isActor())
 
+
 def _cxxMoveRefType(ipdltype, side):
     t = _cxxBareType(ipdltype, side)
     if _cxxTypeNeedsMove(ipdltype):
         t.ref = 2
         return t
     return _cxxConstRefType(ipdltype, side)
 
+
 def _cxxForceMoveRefType(ipdltype, side):
     assert _cxxTypeCanMove(ipdltype)
     t = _cxxBareType(ipdltype, side)
     t.ref = 2
     return t
 
+
 def _cxxPtrToType(ipdltype, side):
     t = _cxxBareType(ipdltype, side)
     if ipdltype.isIPDL() and ipdltype.isActor():
         t.ptr = 0
         t.ptrptr = 1
         return t
     t.ptr = 1
     return t
 
+
 def _cxxConstPtrToType(ipdltype, side):
     t = _cxxBareType(ipdltype, side)
     if ipdltype.isIPDL() and ipdltype.isActor():
         t.ptr = 0
         t.ptrconstptr = 1
         return t
     t.const = 1
     t.ptr = 1
     return t
 
+
 def _allocMethod(ptype, side):
     return ExprVar('Alloc' + ptype.name() + side.title())
 
+
 def _deallocMethod(ptype, side):
     return ExprVar('Dealloc' + ptype.name() + side.title())
 
 ##
-## A _HybridDecl straddles IPDL and C++ decls.  It knows which C++
-## types correspond to which IPDL types, and it also knows how
-## serialize and deserialize "special" IPDL C++ types.
+# A _HybridDecl straddles IPDL and C++ decls.  It knows which C++
+# types correspond to which IPDL types, and it also knows how
+# serialize and deserialize "special" IPDL C++ types.
 ##
+
+
 class _HybridDecl:
     """A hybrid decl stores both an IPDL type and all the C++ type
 info needed by later passes, along with a basic name for the decl."""
+
     def __init__(self, ipdltype, name):
         self.ipdltype = ipdltype
         self.name = name
         self.idnum = 0
 
     def isCopyable(self):
         return not _cxxTypeNeedsMove(self.ipdltype)
 
@@ -616,69 +716,79 @@ necessarily a C++ reference."""
         if self.ipdltype.isIPDL() and self.ipdltype.isActor():
             return self.bareType(side)
         return self.constRefType(side)
 
     def moveType(self, side):
         """Return this decl's C++ Type with move semantics."""
         if self.ipdltype.isIPDL() and self.ipdltype.isActor():
             return self.bareType(side)
-        return self.rvalueRefType(side);
+        return self.rvalueRefType(side)
 
     def outType(self, side):
         """Return this decl's C++ Type with outparam semantics."""
         t = self.bareType(side)
         if self.ipdltype.isIPDL() and self.ipdltype.isActor():
-            t.ptr = 0;  t.ptrptr = 1
+            t.ptr = 0
+            t.ptrptr = 1
             return t
         t.ptr = 1
         return t
 
     def forceMoveType(self, side):
         """Return this decl's C++ Type with forced move semantics."""
         assert _cxxTypeCanMove(self.ipdltype)
         return _cxxForceMoveRefType(self.ipdltype, side)
 
-##--------------------------------------------------
+# --------------------------------------------------
+
 
 class HasFQName:
     def fqClassName(self):
         return self.decl.type.fullname()
 
+
 class _CompoundTypeComponent(_HybridDecl):
     def __init__(self, ipdltype, name, side, ct):
         _HybridDecl.__init__(self, ipdltype, name)
         self.side = side
         self.special = _hasVisibleActor(ipdltype)
 
     # @override the following methods to pass |self.side| instead of
     # forcing the caller to remember which side we're declared to
     # represent.
     def bareType(self, side=None, fq=0):
         return _HybridDecl.bareType(self, self.side, fq=fq)
+
     def refType(self, side=None):
         return _HybridDecl.refType(self, self.side)
+
     def constRefType(self, side=None):
         return _HybridDecl.constRefType(self, self.side)
+
     def ptrToType(self, side=None):
         return _HybridDecl.ptrToType(self, self.side)
+
     def constPtrToType(self, side=None):
         return _HybridDecl.constPtrToType(self, self.side)
+
     def inType(self, side=None):
         return _HybridDecl.inType(self, self.side)
+
     def forceMoveType(self, side=None):
         return _HybridDecl.forceMoveType(self, self.side)
 
 
 class StructDecl(ipdl.ast.StructDecl, HasFQName):
     @staticmethod
     def upgrade(structDecl):
         assert isinstance(structDecl, ipdl.ast.StructDecl)
         structDecl.__class__ = StructDecl
 
+
 class _StructField(_CompoundTypeComponent):
     def __init__(self, ipdltype, name, sd, side=None):
         self.basename = name
         fname = name
         special = _hasVisibleActor(ipdltype)
         if special:
             fname += side.title()
 
@@ -709,17 +819,17 @@ class _StructField(_CompoundTypeComponen
             refexpr = ExprCast(refexpr, Type('Shmem', ref=1), const=1)
         if 'ByteBuf' == self.ipdltype.name():
             refexpr = ExprCast(refexpr, Type('ByteBuf', ref=1), const=1)
         if 'FileDescriptor' == self.ipdltype.name():
             refexpr = ExprCast(refexpr, Type('FileDescriptor', ref=1), const=1)
         return refexpr
 
     def argVar(self):
-        return ExprVar('_'+ self.name)
+        return ExprVar('_' + self.name)
 
     def memberVar(self):
         return ExprVar(self.name + '_')
 
 
 class UnionDecl(ipdl.ast.UnionDecl, HasFQName):
     def callType(self, var=None):
         func = ExprVar('type')
@@ -731,40 +841,41 @@ class UnionDecl(ipdl.ast.UnionDecl, HasF
     def upgrade(unionDecl):
         assert isinstance(unionDecl, ipdl.ast.UnionDecl)
         unionDecl.__class__ = UnionDecl
 
 
 class _UnionMember(_CompoundTypeComponent):
     """Not in the AFL sense, but rather a member (e.g. |int;|) of an
 IPDL union type."""
+
     def __init__(self, ipdltype, ud, side=None, other=None):
         flatname = _flatTypeName(ipdltype)
         special = _hasVisibleActor(ipdltype)
         if special:
             flatname += side.title()
 
-        _CompoundTypeComponent.__init__(self, ipdltype, 'V'+ flatname, side, ud)
+        _CompoundTypeComponent.__init__(self, ipdltype, 'V' + flatname, side, ud)
         self.flattypename = flatname
         if special:
             if other is not None:
                 self.other = other
             else:
                 self.other = _UnionMember(ipdltype, ud, _otherSide(side), self)
 
         # To create a finite object with a mutually recursive type, a union must
         # be present somewhere in the recursive loop. Because of that we only
         # need to care about introducing indirections inside unions.
         self.recursive = ud.decl.type.mutuallyRecursiveWith(ipdltype)
 
     def enum(self):
         return 'T' + self.flattypename
 
     def pqEnum(self):
-        return self.ud.name +'::'+ self.enum()
+        return self.ud.name + '::' + self.enum()
 
     def enumvar(self):
         return ExprVar(self.enum())
 
     def internalType(self):
         if self.recursive:
             return self.ptrToType()
         else:
@@ -777,17 +888,17 @@ IPDL union type."""
         else:
             return Type('mozilla::AlignedStorage2', T=self.internalType())
 
     def unionValue(self):
         # NB: knows that Union's storage C union is named |mValue|
         return ExprSelect(ExprVar('mValue'), '.', self.name)
 
     def typedef(self):
-        return self.flattypename +'__tdef'
+        return self.flattypename + '__tdef'
 
     def callGetConstPtr(self):
         """Return an expression of type self.constptrToSelfType()"""
         return ExprCall(ExprVar(self.getConstPtrName()))
 
     def callGetPtr(self):
         """Return an expression of type self.ptrToSelfType()"""
         return ExprCall(ExprVar(self.getPtrName()))
@@ -798,43 +909,45 @@ IPDL union type."""
         return ExprAssn(ExprDeref(self.callGetPtr()), rhs)
 
     def callCtor(self, expr=None):
         assert not isinstance(expr, list)
 
         if expr is None:
             args = None
         elif self.ipdltype.isIPDL() and self.ipdltype.isActor():
-            args = [ ExprCast(expr, self.bareType(), const=1) ]
+            args = [ExprCast(expr, self.bareType(), const=1)]
         else:
-            args = [ expr ]
+            args = [expr]
 
         if self.recursive:
             return ExprAssn(self.callGetPtr(),
                             ExprNew(self.bareType(self.side),
                                     args=args))
         else:
             return ExprNew(self.bareType(self.side),
                            args=args,
-                           newargs=[ ExprVar('mozilla::KnownNotNull'), self.callGetPtr() ])
+                           newargs=[ExprVar('mozilla::KnownNotNull'), self.callGetPtr()])
 
     def callDtor(self):
         if self.recursive:
             return ExprDelete(self.callGetPtr())
         else:
             return ExprCall(
-                ExprSelect(self.callGetPtr(), '->', '~'+ self.typedef()))
-
-    def getTypeName(self): return 'get_'+ self.flattypename
-    def getConstTypeName(self): return 'get_'+ self.flattypename
-
-    def getOtherTypeName(self): return 'get_'+ self.otherflattypename
-
-    def getPtrName(self): return 'ptr_'+ self.flattypename
-    def getConstPtrName(self): return 'constptr_'+ self.flattypename
+                ExprSelect(self.callGetPtr(), '->', '~' + self.typedef()))
+
+    def getTypeName(self): return 'get_' + self.flattypename
+
+    def getConstTypeName(self): return 'get_' + self.flattypename
+
+    def getOtherTypeName(self): return 'get_' + self.otherflattypename
+
+    def getPtrName(self): return 'ptr_' + self.flattypename
+
+    def getConstPtrName(self): return 'constptr_' + self.flattypename
 
     def ptrToSelfExpr(self):
         """|*ptrToSelfExpr()| has type |self.bareType()|"""
         v = self.unionValue()
         if self.recursive:
             return v
         else:
             return ExprCall(ExprSelect(v, '.', 'addr'))
@@ -869,17 +982,18 @@ IPDL union type."""
         if 'ByteBuf' == self.ipdltype.name():
             v = ExprCast(v, Type('ByteBuf', ref=1), const=1)
         if 'Shmem' == self.ipdltype.name():
             v = ExprCast(v, Type('Shmem', ref=1), const=1)
         if 'FileDescriptor' == self.ipdltype.name():
             v = ExprCast(v, Type('FileDescriptor', ref=1), const=1)
         return v
 
-##--------------------------------------------------
+# --------------------------------------------------
+
 
 class MessageDecl(ipdl.ast.MessageDecl):
     def baseName(self):
         return self.name
 
     def recvMethod(self):
         name = _recvPrefix(self.decl.type) + self.baseName()
         if self.decl.type.isCtor():
@@ -897,37 +1011,39 @@ class MessageDecl(ipdl.ast.MessageDecl):
                 or self.decl.type.isCtor()
                 or self.decl.type.isDtor())
 
     def hasAsyncReturns(self):
         return (self.decl.type.isAsync() and
                 self.returns)
 
     def msgCtorFunc(self):
-        return 'Msg_%s'% (self.decl.progname)
+        return 'Msg_%s' % (self.decl.progname)
 
     def prettyMsgName(self, pfx=''):
         return pfx + self.msgCtorFunc()
 
     def pqMsgCtorFunc(self):
-        return '%s::%s'% (self.namespace, self.msgCtorFunc())
-
-    def msgId(self):  return self.msgCtorFunc()+ '__ID'
+        return '%s::%s' % (self.namespace, self.msgCtorFunc())
+
+    def msgId(self): return self.msgCtorFunc() + '__ID'
+
     def pqMsgId(self):
-        return '%s::%s'% (self.namespace, self.msgId())
+        return '%s::%s' % (self.namespace, self.msgId())
 
     def replyCtorFunc(self):
-        return 'Reply_%s'% (self.decl.progname)
+        return 'Reply_%s' % (self.decl.progname)
 
     def pqReplyCtorFunc(self):
-        return '%s::%s'% (self.namespace, self.replyCtorFunc())
-
-    def replyId(self):  return self.replyCtorFunc()+ '__ID'
+        return '%s::%s' % (self.namespace, self.replyCtorFunc())
+
+    def replyId(self): return self.replyCtorFunc() + '__ID'
+
     def pqReplyId(self):
-        return '%s::%s'% (self.namespace, self.replyId())
+        return '%s::%s' % (self.namespace, self.replyId())
 
     def prettyReplyName(self, pfx=''):
         return pfx + self.replyCtorFunc()
 
     def promiseName(self):
         name = self.baseName()
         if self.decl.type.isCtor():
             name += 'Constructor'
@@ -947,156 +1063,163 @@ class MessageDecl(ipdl.ast.MessageDecl):
 
         def makeDecl(d, sems):
             if sems is 'in':
                 return Decl(d.inType(side), d.name)
             elif sems is 'move':
                 return Decl(d.moveType(side), d.name)
             elif sems is 'out':
                 return Decl(d.outType(side), d.name)
-            else: assert 0
+            else:
+                assert 0
 
         def makeResolverDecl(returns):
             return Decl(Type(self.resolverName(), ref=2), 'aResolve')
 
         def makeCallbackResolveDecl(returns):
             if len(returns) > 1:
                 resolvetype = _tuple([d.bareType(side) for d in returns])
             else:
                 resolvetype = returns[0].bareType(side)
 
             return Decl(Type("mozilla::ipc::ResolveCallback", T=resolvetype, ref=2),
                         'aResolve')
 
         def makeCallbackRejectDecl(returns):
             return Decl(Type("mozilla::ipc::RejectCallback", ref=2), 'aReject')
 
-        cxxparams = [ ]
+        cxxparams = []
         if paramsems is not None:
-            cxxparams.extend([ makeDecl(d, paramsems) for d in self.params ])
+            cxxparams.extend([makeDecl(d, paramsems) for d in self.params])
 
         if returnsems is 'promise' and self.returns:
             pass
         elif returnsems is 'callback' and self.returns:
-            cxxparams.extend([ makeCallbackResolveDecl(self.returns),
-                               makeCallbackRejectDecl(self.returns) ])
+            cxxparams.extend([makeCallbackResolveDecl(self.returns),
+                              makeCallbackRejectDecl(self.returns)])
         elif returnsems is 'resolver' and self.returns:
-            cxxparams.extend([ makeResolverDecl(self.returns) ])
+            cxxparams.extend([makeResolverDecl(self.returns)])
         elif returnsems is not None:
-            cxxparams.extend([ makeDecl(r, returnsems) for r in self.returns ])
+            cxxparams.extend([makeDecl(r, returnsems) for r in self.returns])
 
         if not implicit and self.decl.type.hasImplicitActorParam():
             cxxparams = cxxparams[1:]
 
         return cxxparams
 
     def makeCxxArgs(self, paramsems='in', retsems='out', retcallsems='out',
                     implicit=1):
-        assert not retcallsems or retsems # retcallsems => returnsems
-        cxxargs = [ ]
+        assert not retcallsems or retsems  # retcallsems => returnsems
+        cxxargs = []
 
         if paramsems is 'move':
-            cxxargs.extend([ p.mayMoveExpr() for p in self.params ])
+            cxxargs.extend([p.mayMoveExpr() for p in self.params])
         elif paramsems is 'in':
-            cxxargs.extend([ p.var() for p in self.params ])
+            cxxargs.extend([p.var() for p in self.params])
         else:
             assert False
 
         for ret in self.returns:
             if retsems is 'in':
                 if retcallsems is 'in':
                     cxxargs.append(ret.var())
                 elif retcallsems is 'out':
                     cxxargs.append(ExprAddrOf(ret.var()))
-                else: assert 0
+                else:
+                    assert 0
             elif retsems is 'out':
                 if retcallsems is 'in':
                     cxxargs.append(ExprDeref(ret.var()))
                 elif retcallsems is 'out':
                     cxxargs.append(ret.var())
-                else: assert 0
+                else:
+                    assert 0
             elif retsems is 'resolver':
                 pass
         if retsems is 'resolver':
             cxxargs.append(ExprMove(ExprVar('resolver')))
 
         if not implicit:
             assert self.decl.type.hasImplicitActorParam()
             cxxargs = cxxargs[1:]
 
         return cxxargs
 
-
     @staticmethod
     def upgrade(messageDecl):
         assert isinstance(messageDecl, ipdl.ast.MessageDecl)
         if messageDecl.decl.type.hasImplicitActorParam():
             messageDecl.params.insert(
                 0,
                 _HybridDecl(
                     ipdl.type.ActorType(
                         messageDecl.decl.type.constructedType()),
                     'actor'))
         messageDecl.__class__ = MessageDecl
 
 
-##--------------------------------------------------
+# --------------------------------------------------
 def _usesShmem(p):
     for md in p.messageDecls:
         for param in md.inParams:
             if ipdl.type.hasshmem(param.type):
                 return True
         for ret in md.outParams:
             if ipdl.type.hasshmem(ret.type):
                 return True
     return False
 
+
 def _subtreeUsesShmem(p):
     if _usesShmem(p):
         return True
 
     ptype = p.decl.type
     for mgd in ptype.manages:
         if ptype is not mgd:
             if _subtreeUsesShmem(mgd._ast):
                 return True
     return False
 
+
 def _stateType(hasReentrantDelete):
     if hasReentrantDelete:
         return Type('mozilla::ipc::ReEntrantDeleteState')
     else:
         return Type('mozilla::ipc::State')
 
+
 def _startState(hasReentrantDelete):
     pfx = _stateType(hasReentrantDelete).name + '::'
     return ExprVar(pfx + 'Start')
 
 
 class Protocol(ipdl.ast.Protocol):
     def cxxTypedefs(self):
         return self.decl.cxxtypedefs
 
     def channelSel(self):
-        if self.decl.type.isToplevel():  return '.'
+        if self.decl.type.isToplevel():
+            return '.'
         return '->'
 
     def channelType(self):
         return Type('MessageChannel', ptr=not self.decl.type.isToplevel())
 
     def managerInterfaceType(self, ptr=0):
         return Type('mozilla::ipc::IProtocol', ptr=ptr)
 
     def openedProtocolInterfaceType(self, ptr=0):
         return Type('mozilla::ipc::IToplevelProtocol',
                     ptr=ptr)
 
     def _ipdlmgrtype(self):
         assert 1 == len(self.decl.type.managers)
-        for mgr in self.decl.type.managers:  return mgr
+        for mgr in self.decl.type.managers:
+            return mgr
 
     def managerActorType(self, side, ptr=0):
         return Type(_actorName(self._ipdlmgrtype().name(), side),
                     ptr=ptr)
 
     def registerMethod(self):
         return ExprVar('Register')
 
@@ -1217,21 +1340,21 @@ class Protocol(ipdl.ast.Protocol):
         return mvar
 
     def managedCxxType(self, actortype, side):
         assert self.decl.type.isManagerOf(actortype)
         return Type(_actorName(actortype.name(), side), ptr=1)
 
     def managedMethod(self, actortype, side):
         assert self.decl.type.isManagerOf(actortype)
-        return ExprVar('Managed'+  _actorName(actortype.name(), side))
+        return ExprVar('Managed' + _actorName(actortype.name(), side))
 
     def managedVar(self, actortype, side):
         assert self.decl.type.isManagerOf(actortype)
-        return ExprVar('mManaged'+ _actorName(actortype.name(), side))
+        return ExprVar('mManaged' + _actorName(actortype.name(), side))
 
     def managedVarType(self, actortype, side, const=0, ref=0):
         assert self.decl.type.isManagerOf(actortype)
         return _cxxManagedContainerType(Type(_actorName(actortype.name(), side)),
                                         const=const, ref=ref)
 
     # XXX this is sucky, fix
     def usesShmem(self):
@@ -1248,46 +1371,46 @@ class Protocol(ipdl.ast.Protocol):
 
 class TranslationUnit(ipdl.ast.TranslationUnit):
     @staticmethod
     def upgrade(tu):
         assert isinstance(tu, ipdl.ast.TranslationUnit)
         tu.__class__ = TranslationUnit
 
 
-##-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 
 class _DecorateWithCxxStuff(ipdl.ast.Visitor):
     """Phase 1 of lowering: decorate the IPDL AST with information
 relevant to C++ code generation.
 
 This pass results in an AST that is a poor man's "IR"; in reality, a
 "hybrid" AST mainly consisting of IPDL nodes with new C++ info along
 with some new IPDL/C++ nodes that are tuned for C++ codegen."""
 
     def __init__(self):
         self.visitedTus = set()
         # the set of typedefs that allow generated classes to
         # reference known C++ types by their "short name" rather than
         # fully-qualified name. e.g. |Foo| rather than |a::b::Foo|.
-        self.typedefs = [ ]
-        self.typedefSet = set([ Typedef(Type('mozilla::ipc::ActorHandle'),
-                                        'ActorHandle'),
-                                Typedef(Type('base::ProcessId'),
-                                        'ProcessId'),
-                                Typedef(Type('mozilla::ipc::ProtocolId'),
-                                        'ProtocolId'),
-                                Typedef(Type('mozilla::ipc::Transport'),
-                                        'Transport'),
-                                Typedef(Type('mozilla::ipc::Endpoint'),
-                                        'Endpoint', ['FooSide']),
-                                Typedef(Type('mozilla::ipc::TransportDescriptor'),
-                                        'TransportDescriptor'),
-                                Typedef(Type('mozilla::ipc::ResponseRejectReason'),
-                                        'ResponseRejectReason') ])
+        self.typedefs = []
+        self.typedefSet = set([Typedef(Type('mozilla::ipc::ActorHandle'),
+                                       'ActorHandle'),
+                               Typedef(Type('base::ProcessId'),
+                                       'ProcessId'),
+                               Typedef(Type('mozilla::ipc::ProtocolId'),
+                                       'ProtocolId'),
+                               Typedef(Type('mozilla::ipc::Transport'),
+                                       'Transport'),
+                               Typedef(Type('mozilla::ipc::Endpoint'),
+                                       'Endpoint', ['FooSide']),
+                               Typedef(Type('mozilla::ipc::TransportDescriptor'),
+                                       'TransportDescriptor'),
+                               Typedef(Type('mozilla::ipc::ResponseRejectReason'),
+                                       'ResponseRejectReason')])
         self.protocolName = None
 
     def visitTranslationUnit(self, tu):
         if tu not in self.visitedTus:
             self.visitedTus.add(tu)
             ipdl.ast.Visitor.visitTranslationUnit(self, tu)
             if not isinstance(tu, TranslationUnit):
                 TranslationUnit.upgrade(tu)
@@ -1298,26 +1421,25 @@ with some new IPDL/C++ nodes that are tu
             inc.tu.accept(self)
 
     def visitProtocol(self, pro):
         self.protocolName = pro.name
         pro.decl.cxxtypedefs = self.typedefs
         Protocol.upgrade(pro)
         return ipdl.ast.Visitor.visitProtocol(self, pro)
 
-
     def visitUsingStmt(self, using):
         if using.decl.fullname is not None:
             self.typedefSet.add(Typedef(Type(using.decl.fullname),
                                         using.decl.shortname))
 
     def visitStructDecl(self, sd):
         if not isinstance(sd, StructDecl):
             sd.decl.special = 0
-            newfields = [ ]
+            newfields = []
             for f in sd.fields:
                 ftype = f.decl.type
                 if _hasVisibleActor(ftype):
                     sd.decl.special = 1
                     # if ftype has a visible actor, we need both
                     # |ActorParent| and |ActorChild| fields
                     newfields.append(_StructField(ftype, f.name, sd,
                                                   side='parent'))
@@ -1326,63 +1448,63 @@ with some new IPDL/C++ nodes that are tu
                 else:
                     newfields.append(_StructField(ftype, f.name, sd))
             sd.fields = newfields
             StructDecl.upgrade(sd)
 
         if sd.decl.fullname is not None:
             self.typedefSet.add(Typedef(Type(sd.fqClassName()), sd.name))
 
-
     def visitUnionDecl(self, ud):
         ud.decl.special = 0
-        newcomponents = [ ]
+        newcomponents = []
         for ctype in ud.decl.type.components:
             if _hasVisibleActor(ctype):
                 ud.decl.special = 1
                 # if ctype has a visible actor, we need both
                 # |ActorParent| and |ActorChild| union members
                 newcomponents.append(_UnionMember(ctype, ud, side='parent'))
                 newcomponents.append(_UnionMember(ctype, ud, side='child'))
             else:
                 newcomponents.append(_UnionMember(ctype, ud))
         ud.components = newcomponents
         UnionDecl.upgrade(ud)
 
         if ud.decl.fullname is not None:
             self.typedefSet.add(Typedef(Type(ud.fqClassName()), ud.name))
 
-
     def visitDecl(self, decl):
         return _HybridDecl(decl.type, decl.progname)
 
     def visitMessageDecl(self, md):
         md.namespace = self.protocolName
-        md.params = [ param.accept(self) for param in md.inParams ]
-        md.returns = [ ret.accept(self) for ret in md.outParams ]
+        md.params = [param.accept(self) for param in md.inParams]
+        md.returns = [ret.accept(self) for ret in md.outParams]
         MessageDecl.upgrade(md)
 
 
-##-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 
 def msgenums(protocol, pretty=False):
     msgenum = TypeEnum('MessageType')
-    msgstart = _messageStartName(protocol.decl.type) +' << 16'
+    msgstart = _messageStartName(protocol.decl.type) + ' << 16'
     msgenum.addId(protocol.name + 'Start', msgstart)
 
     for md in protocol.messageDecls:
-        msgenum.addId(md.prettyMsgName() if pretty else  md.msgId())
+        msgenum.addId(md.prettyMsgName() if pretty else md.msgId())
         if md.hasReply():
             msgenum.addId(md.prettyReplyName() if pretty else md.replyId())
 
-    msgenum.addId(protocol.name +'End')
+    msgenum.addId(protocol.name + 'End')
     return msgenum
 
+
 class _GenerateProtocolCode(ipdl.ast.Visitor):
     '''Creates code common to both the parent and child actors.'''
+
     def __init__(self):
         self.protocol = None     # protocol we're generating a class for
         self.hdrfile = None      # what will become Protocol.h
         self.cppfile = None      # what will become Protocol.cpp
         self.cppIncludeHeaders = []
         self.structUnionDefns = []
         self.funcDefns = []
 
@@ -1424,17 +1546,17 @@ class _GenerateProtocolCode(ipdl.ast.Vis
                     c.ipdltype.accept(typedeps)
 
             for typename in [t.fromtype.name for t in typedeps.usingTypedefs]:
                 if typename in typesToIncludes:
                     aggregateTypeIncludes.add(typesToIncludes[typename])
 
         if len(aggregateTypeIncludes) != 0:
             hf.addthing(Whitespace.NL)
-            hf.addthings([ Whitespace("// Headers for typedefs"), Whitespace.NL ])
+            hf.addthings([Whitespace("// Headers for typedefs"), Whitespace.NL])
 
             for headername in sorted(iter(aggregateTypeIncludes)):
                 hf.addthing(CppDirective('include', '"' + headername + '"'))
 
         # Manually run Visitor.visitTranslationUnit. For dependency resolution
         # we need to handle structs and unions separately.
         for cxxInc in tu.cxxIncludes:
             cxxInc.accept(self)
@@ -1451,43 +1573,42 @@ class _GenerateProtocolCode(ipdl.ast.Vis
         if tu.filetype == 'header':
             self.cppIncludeHeaders.append(_ipdlhHeaderName(tu) + '.h')
 
         hf.addthing(Whitespace.NL)
         hf.addthings(_includeGuardEnd(hf))
 
         cf = self.cppfile
         cf.addthings((
-            [ _DISCLAIMER, Whitespace.NL ]
-            + [ CppDirective('include','"'+h+'"')
-                for h in self.cppIncludeHeaders ]
-            + [ Whitespace.NL ]
+            [_DISCLAIMER, Whitespace.NL]
+            + [CppDirective('include', '"'+h+'"')
+                for h in self.cppIncludeHeaders]
+            + [Whitespace.NL]
         ))
 
         if self.protocol:
             # construct the namespace into which we'll stick all our defns
             ns = Namespace(self.protocol.name)
             cf.addthing(_putInNamespaces(ns, self.protocol.namespaces))
-            ns.addstmts(([ Whitespace.NL]
+            ns.addstmts(([Whitespace.NL]
                          + self.funcDefns
-                         +[ Whitespace.NL ]))
+                         + [Whitespace.NL]))
 
         cf.addthings(self.structUnionDefns)
 
-
     def visitBuiltinCxxInclude(self, inc):
-        self.hdrfile.addthing(CppDirective('include', '"'+ inc.file +'"'))
+        self.hdrfile.addthing(CppDirective('include', '"' + inc.file + '"'))
 
     def visitCxxInclude(self, inc):
         self.cppIncludeHeaders.append(inc.file)
 
     def visitInclude(self, inc):
         if inc.tu.filetype == 'header':
             self.hdrfile.addthing(CppDirective(
-                    'include', '"'+ _ipdlhHeaderName(inc.tu) +'.h"'))
+                'include', '"' + _ipdlhHeaderName(inc.tu) + '.h"'))
         else:
             self.cppIncludeHeaders += [
                 _protocolHeaderName(inc.tu.protocol, 'parent') + '.h',
                 _protocolHeaderName(inc.tu.protocol, 'child') + '.h',
             ]
 
     def generateStructsAndUnions(self, tu):
         '''Generate the definitions for all structs and unions. This will
@@ -1506,34 +1627,34 @@ class _GenerateProtocolCode(ipdl.ast.Vis
                 traitsdecl, traitsdefns = _ParamTraits.unionPickling(su.decl.type)
 
             clsdecl, methoddefns = _splitClassDeclDefn(cls)
 
             # Store the declarations in the decls map so we can emit in
             # dependency order.
             decls[su.decl.type] = (
                 fulldecltypes,
-                [  Whitespace.NL ]
+                [Whitespace.NL]
                 + forwarddecls
-                + [ Whitespace("""
+                + [Whitespace("""
 //-----------------------------------------------------------------------------
 // Declaration of the IPDL type |%s %s|
 //
-"""% (which, su.name)),
+""" % (which, su.name)),
                     _putInNamespaces(clsdecl, su.namespaces),
                 ]
-                + [ Whitespace.NL,
-                    traitsdecl ])
+                + [Whitespace.NL,
+                    traitsdecl])
 
             self.structUnionDefns.extend([
                 Whitespace("""
 //-----------------------------------------------------------------------------
 // Method definitions for the IPDL type |%s %s|
 //
-"""% (which, su.name)),
+""" % (which, su.name)),
                 _putInNamespaces(methoddefns, su.namespaces),
                 Whitespace.NL,
                 traitsdefns,
             ])
 
         # Generate the declarations structs in dependency order.
         def gen_struct(deps, defn):
             for dep in deps:
@@ -1555,30 +1676,30 @@ class _GenerateProtocolCode(ipdl.ast.Vis
             _makeForwardDeclForActor(p.decl.type, 'Parent'),
             _makeForwardDeclForActor(p.decl.type, 'Child')
         ])
 
         self.hdrfile.addthing(Whitespace("""
 //-----------------------------------------------------------------------------
 // Code common to %sChild and %sParent
 //
-"""% (p.name, p.name)))
+""" % (p.name, p.name)))
 
         # construct the namespace into which we'll stick all our decls
         ns = Namespace(self.protocol.name)
         self.hdrfile.addthing(_putInNamespaces(ns, p.namespaces))
         ns.addstmt(Whitespace.NL)
 
         edecl, edefn = _splitFuncDeclDefn(self.genEndpointFunc())
-        ns.addstmts([ edecl, Whitespace.NL ])
+        ns.addstmts([edecl, Whitespace.NL])
         self.funcDefns.append(edefn)
 
         # spit out message type enum and classes
         msgenum = msgenums(self.protocol)
-        ns.addstmts([ StmtDecl(Decl(msgenum, '')), Whitespace.NL ])
+        ns.addstmts([StmtDecl(Decl(msgenum, '')), Whitespace.NL])
 
         for md in p.messageDecls:
             decls = []
 
             # Look up the segment capacity used for serializing this
             # message. If the capacity is not specified, use '0' for
             # the default capacity (defined in ipc_message.cc)
             name = '%s::%s' % (md.namespace, md.decl.progname)
@@ -1594,49 +1715,49 @@ class _GenerateProtocolCode(ipdl.ast.Vis
                 rfDecl, rfDefn = _splitFuncDeclDefn(
                     _generateMessageConstructor(md, 0, p, forReply=True))
                 decls.append(rfDecl)
                 self.funcDefns.append(rfDefn)
 
             decls.append(Whitespace.NL)
             ns.addstmts(decls)
 
-        ns.addstmts([ Whitespace.NL, Whitespace.NL ])
-
+        ns.addstmts([Whitespace.NL, Whitespace.NL])
 
     # Generate code for PFoo::CreateEndpoints.
     def genEndpointFunc(self):
         p = self.protocol.decl.type
         tparent = _cxxBareType(ActorType(p), 'Parent', fq=1)
         tchild = _cxxBareType(ActorType(p), 'Child', fq=1)
         methodvar = ExprVar('CreateEndpoints')
         rettype = Type.NSRESULT
         parentpidvar = ExprVar('aParentDestPid')
         childpidvar = ExprVar('aChildDestPid')
         parentvar = ExprVar('aParent')
         childvar = ExprVar('aChild')
 
         openfunc = MethodDefn(MethodDecl(
             methodvar.name,
-            params=[ Decl(Type('base::ProcessId'), parentpidvar.name),
-                     Decl(Type('base::ProcessId'), childpidvar.name),
-                     Decl(Type('mozilla::ipc::Endpoint<' + tparent.name + '>', ptr=1), parentvar.name),
-                     Decl(Type('mozilla::ipc::Endpoint<' + tchild.name + '>', ptr=1), childvar.name) ],
+            params=[Decl(Type('base::ProcessId'), parentpidvar.name),
+                    Decl(Type('base::ProcessId'), childpidvar.name),
+                    Decl(Type('mozilla::ipc::Endpoint<' + tparent.name + '>', ptr=1),
+                         parentvar.name),
+                    Decl(Type('mozilla::ipc::Endpoint<' + tchild.name + '>', ptr=1),
+                         childvar.name)],
             ret=rettype))
         openfunc.addstmt(StmtReturn(ExprCall(
             ExprVar('mozilla::ipc::CreateEndpoints'),
-            args=[ _backstagePass(),
-                   parentpidvar, childpidvar,