Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Margareta Eliza Balazs 2018-07-18 12:40:51 +03:00
commit 9de29c1f5a
226 changed files with 5148 additions and 4065 deletions

View File

@ -7,6 +7,13 @@ exclude =
browser/moz.configure, browser/moz.configure,
build/moz.configure/*.configure, build/moz.configure/*.configure,
build/pymake/, 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, js/*.configure,
memory/moz.configure, memory/moz.configure,
mobile/android/*.configure, mobile/android/*.configure,

View File

@ -209,7 +209,8 @@ SelectionManager::ProcessSelectionChanged(SelData* aSelData)
HyperTextAccessible* text = nsAccUtils::GetTextContainer(cntrNode); HyperTextAccessible* text = nsAccUtils::GetTextContainer(cntrNode);
if (!text) { 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; return;
} }

View File

@ -146,12 +146,12 @@
<vbox flex="1"> <vbox flex="1">
<listbox> <richlistbox>
<listitem label="listitem1" id="listitem1"/> <richlistitem id="listitem1"/>
<listitem label="listitem2" id="listitem2" type="checkbox"/> <richlistitem id="listitem2"><label value="listitem2"/></richlistitem>
<listitem label="listitem3" id="listitem3" type="checkbox"/> <richlistitem id="listitem3"/>
<listitem label="listitem4" id="listitem4"/> <richlistitem id="listitem4"><label value="listitem4"/></richlistitem>
</listbox> </richlistbox>
<menubar> <menubar>
<menu label="item1" id="menu_item1"> <menu label="item1" id="menu_item1">

View File

@ -63,10 +63,10 @@
<vbox flex="1"> <vbox flex="1">
<label control="listbox1" value="listbox: "/> <label control="listbox1" value="listbox: "/>
<listbox id="listbox1"> <richlistbox id="listbox1">
<listitem label="item1" id="item1"/> <richlistitem id="item1"><label value="item1"/></richlistitem>
<listitem label="item2" id="item2"/> <richlistitem id="item1"><label value="item2"/></richlistitem>
</listbox> </richlistbox>
</vbox> </vbox>
</hbox> </hbox>

View File

@ -30,16 +30,6 @@
// Test focus events. // Test focus events.
gQueue = new eventQueue(); 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 synthFocus("richlistbox", new focusChecker("rlb_item1")));
gQueue.push(new synthDownKey("rlb_item1", new focusChecker("rlb_item2"))); gQueue.push(new synthDownKey("rlb_item1", new focusChecker("rlb_item2")));
gQueue.push(new synthFocus("multiselrichlistbox", new focusChecker("msrlb_item1"))); gQueue.push(new synthFocus("multiselrichlistbox", new focusChecker("msrlb_item1")));
@ -70,9 +60,8 @@ if (!MAC) {
// no focus events for unfocused list controls when current item is // no focus events for unfocused list controls when current item is
// changed. // 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")); gQueue.push(new changeCurrentItem("richlistbox", "rlb_item1"));
if (!MAC) { if (!MAC) {
gQueue.push(new changeCurrentItem("menulist", WIN ? "ml_marmalade" : "ml_tangerine")); gQueue.push(new changeCurrentItem("menulist", WIN ? "ml_marmalade" : "ml_tangerine"));
@ -110,48 +99,6 @@ if (!MAC) {
</body> </body>
<vbox flex="1"> <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"> <richlistbox id="richlistbox">
<richlistitem id="rlb_item1"> <richlistitem id="rlb_item1">
<description>A XUL Description!</description> <description>A XUL Description!</description>

View File

@ -166,9 +166,12 @@
gQueue.push(new advanceTab("tabs", 1, "tab3")); gQueue.push(new advanceTab("tabs", 1, "tab3"));
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// listbox // single selection listbox, the first item is selected by default
gQueue.push(new synthClick("lb1_item1",
new invokerChecker(EVENT_SELECTION, "lb1_item1"))); 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", gQueue.push(new synthDownKey("lb1_item1",
new invokerChecker(EVENT_SELECTION, "lb1_item2"))); new invokerChecker(EVENT_SELECTION, "lb1_item2")));
@ -234,20 +237,20 @@
</tabpanels> </tabpanels>
</tabbox> </tabbox>
<listbox id="listbox"> <richlistbox id="listbox">
<listitem id="lb1_item1" label="item1"/> <richlistitem id="lb1_item1"><label value="item1"/></richlistitem>
<listitem id="lb1_item2" label="item2"/> <richlistitem id="lb1_item2"><label value="item2"/></richlistitem>
</listbox> </richlistbox>
<listbox id="listbox2" seltype="multiple"> <richlistbox id="listbox2" seltype="multiple">
<listitem id="lb2_item1" label="item1"/> <richlistitem id="lb2_item1"><label value="item1"/></richlistitem>
<listitem id="lb2_item2" label="item2"/> <richlistitem id="lb2_item2"><label value="item2"/></richlistitem>
<listitem id="lb2_item3" label="item3"/> <richlistitem id="lb2_item3"><label value="item3"/></richlistitem>
<listitem id="lb2_item4" label="item4"/> <richlistitem id="lb2_item4"><label value="item4"/></richlistitem>
<listitem id="lb2_item5" label="item5"/> <richlistitem id="lb2_item5"><label value="item5"/></richlistitem>
<listitem id="lb2_item6" label="item6"/> <richlistitem id="lb2_item6"><label value="item6"/></richlistitem>
<listitem id="lb2_item7" label="item7"/> <richlistitem id="lb2_item7"><label value="item7"/></richlistitem>
</listbox> </richlistbox>
</hbox> </hbox>
</window> </window>

View File

@ -95,10 +95,10 @@
<treechildren id="treechildren"/> <treechildren id="treechildren"/>
</tree> </tree>
<listbox id="listbox"> <richlistbox id="listbox">
<listitem id="listitem1">item1</listitem> <richlistitem id="listitem1"><label value="item1"/></richlistitem>
<listitem id="listitem2">item2</listitem> <richlistitem id="listitem2"><label value="item2"/></richlistitem>
</listbox> </richlistbox>
<vbox id="eventdump"/> <vbox id="eventdump"/>
</vbox> </vbox>

View File

@ -276,10 +276,11 @@
label="labeled element"/> label="labeled element"/>
<!-- nsIDOMXULSelectControlItemElement --> <!-- nsIDOMXULSelectControlItemElement -->
<listbox> <richlistbox>
<listitem id="li_nsIDOMXULSelectControlItemElement" <richlistitem id="li_nsIDOMXULSelectControlItemElement">
label="select control item"/> <label value="select control item"/>
</listbox> </richlistitem>
</richlistbox>
<!-- not nsIDOMXULSelectControlElement --> <!-- not nsIDOMXULSelectControlElement -->
<box id="box_not_nsIDOMXULSelectControlElement" role="group" label="box"/> <box id="box_not_nsIDOMXULSelectControlElement" role="group" label="box"/>
@ -359,11 +360,12 @@
<!-- bug 441991; create name from other menuitem label listitem's own label --> <!-- bug 441991; create name from other menuitem label listitem's own label -->
<hbox> <hbox>
<listbox> <richlistbox>
<listitem id="li_labelledby" <richlistitem id="li_labelledby"
label="The moment the event starts" aria-labelledby="menuitem-DISPLAY li_labelledby">
aria-labelledby="menuitem-DISPLAY li_labelledby"/> <label value="The moment the event starts"/>
</listbox> </richlistitem>
</richlistbox>
<menulist> <menulist>
<menupopup> <menupopup>
<menuitem id="menuitem-DISPLAY" <menuitem id="menuitem-DISPLAY"

View File

@ -32,13 +32,14 @@
function doTest() function doTest()
{ {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// single selectable listbox // single selectable listbox, the first item is selected by default
var id = "listbox"; var id = "listbox";
ok(isAccessible(id, [nsIAccessibleSelectable]), ok(isAccessible(id, [nsIAccessibleSelectable]),
"No selectable accessible for list of " + id); "No selectable accessible for list of " + id);
var select = getAccessible(id, [nsIAccessibleSelectable]); var select = getAccessible(id, [nsIAccessibleSelectable]);
select.removeItemFromSelection(0);
testSelectableSelection(select, [ ]); testSelectableSelection(select, [ ]);
select.addItemToSelection(1); select.addItemToSelection(1);
@ -114,35 +115,27 @@
</body> </body>
<vbox flex="1"> <vbox flex="1">
<listbox id="listbox"> <richlistbox id="listbox">
<listcols> <richlistitem id="lb1_item1">
<listcol flex="1"/> <label value="cell0"/>
<listcol flex="1"/> <label value="cell1"/>
</listcols> </richlistitem>
<listitem id="lb1_item1"> <richlistitem id="lb1_item2">
<listcell label="cell0"/> <label value="cell3"/>
<listcell label="cell1"/> <label value="cell4"/>
</listitem> </richlistitem>
<listitem id="lb1_item2"> </richlistbox>
<listcell label="cell3"/>
<listcell label="cell4"/>
</listitem>
</listbox>
<listbox id="listbox2" seltype="multiple"> <richlistbox id="listbox2" seltype="multiple">
<listcols> <richlistitem id="lb2_item1">
<listcol flex="1"/> <label value="cell0"/>
<listcol flex="1"/> <label value="cell1"/>
</listcols> </richlistitem>
<listitem id="lb2_item1"> <richlistitem id="lb2_item2">
<listcell label="cell0"/> <label value="cell3"/>
<listcell label="cell1"/> <label value="cell4"/>
</listitem> </richlistitem>
<listitem id="lb2_item2"> </richlistbox>
<listcell label="cell3"/>
<listcell label="cell4"/>
</listitem>
</listbox>
<vbox id="debug"/> <vbox id="debug"/>
</vbox> </vbox>

View File

@ -155,7 +155,7 @@ function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
"Mixed element cannot be state checked!"); "Mixed element cannot be state checked!");
// selected/selectable // selected/selectable
if (state & STATE_SELECTED) { if ((state & STATE_SELECTED) && !(aAbsentState & STATE_SELECTABLE)) {
isState(state & STATE_SELECTABLE, STATE_SELECTABLE, false, isState(state & STATE_SELECTABLE, STATE_SELECTABLE, false,
"Selected element must be selectable!"); "Selected element must be selectable!");
} }

View File

@ -64,9 +64,9 @@
testStates("combobox", STATE_FOCUSABLE | STATE_HASPOPUP, 0, STATE_UNAVAILABLE); testStates("combobox", STATE_FOCUSABLE | STATE_HASPOPUP, 0, STATE_UNAVAILABLE);
testStates("combobox-disabled", STATE_UNAVAILABLE | STATE_HASPOPUP, 0, STATE_FOCUSABLE); testStates("combobox-disabled", STATE_UNAVAILABLE | STATE_HASPOPUP, 0, STATE_FOCUSABLE);
testStates("listbox", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE); 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("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("menubar", 0, 0, STATE_FOCUSABLE);
testStates("menu", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE); testStates("menu", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
testStates("menu-disabled", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE | STATE_SELECTABLE); testStates("menu-disabled", STATE_UNAVAILABLE, 0, STATE_FOCUSABLE | STATE_SELECTABLE);
@ -135,13 +135,17 @@
</menupopup> </menupopup>
</menulist> </menulist>
<listbox id="listbox"> <richlistbox id="listbox">
<listitem id="listitem" label="list item"/> <richlistitem id="listitem">
</listbox> <label value="list item"/>
</richlistitem>
</richlistbox>
<listbox id="listbox-disabled" disabled="true"> <richlistbox id="listbox-disabled" disabled="true">
<listitem id="listitem-disabledlistbox" label="list item"/> <richlistitem id="listitem-disabledlistbox">
</listbox> <label value="list item"/>
</richlistitem>
</richlistbox>
<toolbox> <toolbox>
<menubar id="menubar"> <menubar id="menubar">

View File

@ -5,22 +5,18 @@ support-files =
[test_css_tables.html] [test_css_tables.html]
[test_headers_ariagrid.html] [test_headers_ariagrid.html]
[test_headers_ariatable.html] [test_headers_ariatable.html]
[test_headers_listbox.xul]
[test_headers_table.html] [test_headers_table.html]
[test_headers_tree.xul] [test_headers_tree.xul]
[test_indexes_ariagrid.html] [test_indexes_ariagrid.html]
[test_indexes_listbox.xul]
[test_indexes_table.html] [test_indexes_table.html]
[test_indexes_tree.xul] [test_indexes_tree.xul]
[test_layoutguess.html] [test_layoutguess.html]
[test_mtable.html] [test_mtable.html]
[test_sels_ariagrid.html] [test_sels_ariagrid.html]
[test_sels_listbox.xul]
[test_sels_table.html] [test_sels_table.html]
[test_sels_tree.xul] [test_sels_tree.xul]
[test_struct_ariagrid.html] [test_struct_ariagrid.html]
[test_struct_ariatreegrid.html] [test_struct_ariatreegrid.html]
[test_struct_listbox.xul]
[test_struct_table.html] [test_struct_table.html]
[test_struct_tree.xul] [test_struct_tree.xul]
[test_table_1.html] [test_table_1.html]

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -25,8 +25,10 @@
{ {
this.listboxNode = getNode(aListboxID); this.listboxNode = getNode(aListboxID);
this.listitemNode = document.createElement("listitem"); this.listitemNode = document.createElement("richlistitem");
this.listitemNode.setAttribute("label", "item1"); var label = document.createElement("label");
label.setAttribute("value", "item1");
this.listitemNode.appendChild(label);
this.eventSeq = [ this.eventSeq = [
new invokerChecker(EVENT_SHOW, this.listitemNode), new invokerChecker(EVENT_SHOW, this.listitemNode),
@ -168,11 +170,11 @@
</body> </body>
<vbox flex="1"> <vbox flex="1">
<listbox id="listbox" rows="2"> <richlistbox id="listbox">
<listitem label="item2"/> <richlistitem><label value="item2"/></richlistitem>
<listitem label="item3"/> <richlistitem><label value="item3"/></richlistitem>
<listitem label="item4"/> <richlistitem><label value="item4"/></richlistitem>
</listbox> </richlistbox>
</vbox> </vbox>
</hbox> </hbox>

View File

@ -45,6 +45,7 @@ const whitelist = {
"resource://gre/modules/Log.jsm", "resource://gre/modules/Log.jsm",
// Session store // Session store
"resource:///modules/sessionstore/ContentSessionStore.jsm",
"resource://gre/modules/sessionstore/SessionHistory.jsm", "resource://gre/modules/sessionstore/SessionHistory.jsm",
// Forms and passwords // Forms and passwords

File diff suppressed because it is too large Load Diff

View File

@ -6,976 +6,6 @@
"use strict"; "use strict";
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this); ChromeUtils.import("resource:///modules/sessionstore/ContentSessionStore.jsm");
ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
ChromeUtils.defineModuleGetter(this, "TelemetryStopwatch", void new ContentSessionStore(this);
"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);
}
};
/**
* 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.
});

View File

@ -22,6 +22,7 @@ EXTRA_COMPONENTS += [
EXTRA_JS_MODULES.sessionstore = [ EXTRA_JS_MODULES.sessionstore = [
'ContentRestore.jsm', 'ContentRestore.jsm',
'ContentSessionStore.jsm',
'DocShellCapabilities.jsm', 'DocShellCapabilities.jsm',
'GlobalState.jsm', 'GlobalState.jsm',
'RecentlyClosedTabsAndWindowsMenuUtils.jsm', 'RecentlyClosedTabsAndWindowsMenuUtils.jsm',

View File

@ -12,6 +12,8 @@
ChromeUtils.import("resource://gre/modules/Services.jsm"); ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm"); ChromeUtils.import("resource://formautofill/FormAutofillContent.jsm");
ChromeUtils.defineModuleGetter(this, "setTimeout",
"resource://gre/modules/Timer.jsm");
ChromeUtils.defineModuleGetter(this, "FormAutofill", ChromeUtils.defineModuleGetter(this, "FormAutofill",
"resource://formautofill/FormAutofill.jsm"); "resource://formautofill/FormAutofill.jsm");
ChromeUtils.defineModuleGetter(this, "FormAutofillUtils", ChromeUtils.defineModuleGetter(this, "FormAutofillUtils",

View File

@ -12,14 +12,14 @@
#include "nsIObjectOutputStream.h" #include "nsIObjectOutputStream.h"
#include "nsIStandardURL.h" #include "nsIStandardURL.h"
#include "ContentPrincipal.h"
#include "ExpandedPrincipal.h" #include "ExpandedPrincipal.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsIURIWithPrincipal.h" #include "nsIURIWithPrincipal.h"
#include "NullPrincipal.h"
#include "nsScriptSecurityManager.h" #include "nsScriptSecurityManager.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "mozilla/ContentPrincipal.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/dom/ChromeUtils.h" #include "mozilla/dom/ChromeUtils.h"
#include "mozilla/dom/CSPDictionariesBinding.h" #include "mozilla/dom/CSPDictionariesBinding.h"
#include "mozilla/dom/ToJSValue.h" #include "mozilla/dom/ToJSValue.h"

View File

@ -3,8 +3,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef ContentPrincipal_h #ifndef mozilla_ContentPrincipal_h
#define ContentPrincipal_h #define mozilla_ContentPrincipal_h
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsJSPrincipals.h" #include "nsJSPrincipals.h"
@ -16,7 +16,9 @@
#include "mozilla/BasePrincipal.h" #include "mozilla/BasePrincipal.h"
#include "mozilla/extensions/WebExtensionPolicy.h" #include "mozilla/extensions/WebExtensionPolicy.h"
class ContentPrincipal final : public mozilla::BasePrincipal namespace mozilla {
class ContentPrincipal final : public BasePrincipal
{ {
public: public:
NS_DECL_NSISERIALIZABLE NS_DECL_NSISERIALIZABLE
@ -35,7 +37,7 @@ public:
// Init() must be called before the principal is in a usable state. // Init() must be called before the principal is in a usable state.
nsresult Init(nsIURI* aCodebase, nsresult Init(nsIURI* aCodebase,
const mozilla::OriginAttributes& aOriginAttributes, const OriginAttributes& aOriginAttributes,
const nsACString& aOriginNoSuffix); const nsACString& aOriginNoSuffix);
virtual nsresult GetScriptLocation(nsACString& aStr) override; virtual nsresult GetScriptLocation(nsACString& aStr) override;
@ -43,7 +45,7 @@ public:
static nsresult static nsresult
GenerateOriginNoSuffixFromURI(nsIURI* aURI, nsACString& aOrigin); GenerateOriginNoSuffixFromURI(nsIURI* aURI, nsACString& aOrigin);
mozilla::extensions::WebExtensionPolicy* AddonPolicy(); extensions::WebExtensionPolicy* AddonPolicy();
nsCOMPtr<nsIURI> mDomain; nsCOMPtr<nsIURI> mDomain;
nsCOMPtr<nsIURI> mCodebase; nsCOMPtr<nsIURI> mCodebase;
@ -56,12 +58,14 @@ protected:
bool MayLoadInternal(nsIURI* aURI) override; bool MayLoadInternal(nsIURI* aURI) override;
private: 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_CONTRACTID "@mozilla.org/principal;1"
#define NS_PRINCIPAL_CID \ #define NS_PRINCIPAL_CID \
{ 0x653e0e4d, 0x3ee4, 0x45fa, \ { 0x653e0e4d, 0x3ee4, 0x45fa, \
{ 0xb2, 0x72, 0x97, 0xc2, 0x0b, 0xc0, 0x1e, 0xb8 } } { 0xb2, 0x72, 0x97, 0xc2, 0x0b, 0xc0, 0x1e, 0xb8 } }
#endif // ContentPrincipal_h #endif // mozilla_ContentPrincipal_h

View File

@ -69,7 +69,7 @@ NullPrincipal::Create(const OriginAttributes& aOriginAttributes, nsIURI* aURI)
/* static */ already_AddRefed<NullPrincipal> /* static */ already_AddRefed<NullPrincipal>
NullPrincipal::CreateWithoutOriginAttributes() NullPrincipal::CreateWithoutOriginAttributes()
{ {
return NullPrincipal::Create(mozilla::OriginAttributes(), nullptr); return NullPrincipal::Create(OriginAttributes(), nullptr);
} }
nsresult nsresult

View File

@ -9,8 +9,8 @@
* same-origin with anything but themselves. * same-origin with anything but themselves.
*/ */
#ifndef NullPrincipal_h #ifndef mozilla_NullPrincipal_h
#define NullPrincipal_h #define mozilla_NullPrincipal_h
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "nsJSPrincipals.h" #include "nsJSPrincipals.h"
@ -30,7 +30,9 @@ class nsIURI;
#define NS_NULLPRINCIPAL_SCHEME "moz-nullprincipal" #define NS_NULLPRINCIPAL_SCHEME "moz-nullprincipal"
class NullPrincipal final : public mozilla::BasePrincipal namespace mozilla {
class NullPrincipal final : public BasePrincipal
{ {
public: public:
// This should only be used by deserialization, and the factory constructor. // This should only be used by deserialization, and the factory constructor.
@ -64,13 +66,13 @@ public:
CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty = false); CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty = false);
static already_AddRefed<NullPrincipal> static already_AddRefed<NullPrincipal>
Create(const mozilla::OriginAttributes& aOriginAttributes, Create(const OriginAttributes& aOriginAttributes,
nsIURI* aURI = nullptr); nsIURI* aURI = nullptr);
static already_AddRefed<NullPrincipal> static already_AddRefed<NullPrincipal>
CreateWithoutOriginAttributes(); CreateWithoutOriginAttributes();
nsresult Init(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes(), nsresult Init(const OriginAttributes& aOriginAttributes = OriginAttributes(),
nsIURI* aURI = nullptr); nsIURI* aURI = nullptr);
virtual nsresult GetScriptLocation(nsACString &aStr) override; virtual nsresult GetScriptLocation(nsACString &aStr) override;
@ -91,7 +93,9 @@ private:
// If aIsFirstParty is true, this NullPrincipal will be initialized base on // If aIsFirstParty is true, this NullPrincipal will be initialized base on
// the aOriginAttributes with FirstPartyDomain set to an unique value, and this // the aOriginAttributes with FirstPartyDomain set to an unique value, and this
// value is generated from mURI.path, with ".mozilla" appending at the end. // 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

View File

@ -15,6 +15,8 @@
#include "nsCRT.h" #include "nsCRT.h"
#include "nsIUUIDGenerator.h" #include "nsIUUIDGenerator.h"
using namespace mozilla;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
//// NullPrincipalURI //// NullPrincipalURI
@ -406,13 +408,13 @@ NullPrincipalURI::Deserialize(const mozilla::ipc::URIParams& aParams)
//// nsISizeOf //// nsISizeOf
size_t size_t
NullPrincipalURI::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const NullPrincipalURI::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{ {
return mPath.SizeOfExcludingThisIfUnshared(aMallocSizeOf); return mPath.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
} }
size_t size_t
NullPrincipalURI::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const NullPrincipalURI::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{ {
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
} }

View File

@ -8,8 +8,8 @@
* This wraps nsSimpleURI so that all calls to it are done on the main thread. * This wraps nsSimpleURI so that all calls to it are done on the main thread.
*/ */
#ifndef __NullPrincipalURI_h__ #ifndef mozilla_NullPrincipalURI_h
#define __NullPrincipalURI_h__ #define mozilla_NullPrincipalURI_h
#include "nsIURI.h" #include "nsIURI.h"
#include "nsISizeOf.h" #include "nsISizeOf.h"
@ -27,8 +27,8 @@
{0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} } {0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} }
namespace mozilla { namespace mozilla {
class Encoding; class Encoding;
}
class NullPrincipalURI final : public nsIURI class NullPrincipalURI final : public nsIURI
, public nsISizeOf , public nsISizeOf
@ -40,8 +40,8 @@ public:
NS_DECL_NSIIPCSERIALIZABLEURI NS_DECL_NSIIPCSERIALIZABLEURI
// nsISizeOf // nsISizeOf
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override; virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override; virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
// Returns null on failure. // Returns null on failure.
static already_AddRefed<NullPrincipalURI> Create(); static already_AddRefed<NullPrincipalURI> Create();
@ -69,7 +69,7 @@ private:
nsresult SetRef(const nsACString &input); nsresult SetRef(const nsACString &input);
nsresult SetFilePath(const nsACString &input); nsresult SetFilePath(const nsACString &input);
nsresult SetQuery(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&); bool Deserialize(const mozilla::ipc::URIParams&);
public: public:
@ -110,4 +110,6 @@ public:
friend class BaseURIMutator<NullPrincipalURI>; friend class BaseURIMutator<NullPrincipalURI>;
}; };
#endif // __NullPrincipalURI_h__ } // mozilla namespace
#endif // mozilla_NullPrincipalURI_h

View File

@ -18,6 +18,8 @@
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
#include "pratom.h" #include "pratom.h"
using namespace mozilla;
NS_IMPL_CLASSINFO(SystemPrincipal, nullptr, NS_IMPL_CLASSINFO(SystemPrincipal, nullptr,
nsIClassInfo::SINGLETON | nsIClassInfo::MAIN_THREAD_ONLY, nsIClassInfo::SINGLETON | nsIClassInfo::MAIN_THREAD_ONLY,
NS_SYSTEMPRINCIPAL_CID) NS_SYSTEMPRINCIPAL_CID)

View File

@ -6,8 +6,8 @@
/* The privileged system principal. */ /* The privileged system principal. */
#ifndef SystemPrincipal_h #ifndef mozilla_SystemPrincipal_h
#define SystemPrincipal_h #define mozilla_SystemPrincipal_h
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "nsJSPrincipals.h" #include "nsJSPrincipals.h"
@ -19,8 +19,9 @@
{ 0xb7, 0x65, 0x0, 0x60, 0xb0, 0xb6, 0xce, 0xcb }} { 0xb7, 0x65, 0x0, 0x60, 0xb0, 0xb6, 0xce, 0xcb }}
#define NS_SYSTEMPRINCIPAL_CONTRACTID "@mozilla.org/systemprincipal;1" #define NS_SYSTEMPRINCIPAL_CONTRACTID "@mozilla.org/systemprincipal;1"
namespace mozilla {
class SystemPrincipal final : public mozilla::BasePrincipal class SystemPrincipal final : public BasePrincipal
{ {
SystemPrincipal() SystemPrincipal()
: BasePrincipal(eSystemPrincipal) : BasePrincipal(eSystemPrincipal)
@ -63,4 +64,6 @@ protected:
} }
}; };
#endif // SystemPrincipal_h } // mozilla namespace
#endif // mozilla_SystemPrincipal_h

View File

@ -24,17 +24,17 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'caps' XPIDL_MODULE = 'caps'
EXPORTS += [ EXPORTS += [
'ContentPrincipal.h',
'nsJSPrincipals.h', 'nsJSPrincipals.h',
'nsScriptSecurityManager.h', 'nsScriptSecurityManager.h',
'NullPrincipal.h',
'NullPrincipalURI.h',
'SystemPrincipal.h',
] ]
EXPORTS.mozilla = [ EXPORTS.mozilla = [
'BasePrincipal.h', 'BasePrincipal.h',
'ContentPrincipal.h',
'NullPrincipal.h',
'NullPrincipalURI.h',
'OriginAttributes.h', 'OriginAttributes.h',
'SystemPrincipal.h',
] ]
SOURCES += [ SOURCES += [

View File

@ -23,7 +23,6 @@
#include "mozilla/BasePrincipal.h" #include "mozilla/BasePrincipal.h"
#include "ExpandedPrincipal.h" #include "ExpandedPrincipal.h"
#include "SystemPrincipal.h" #include "SystemPrincipal.h"
#include "NullPrincipal.h"
#include "DomainPolicy.h" #include "DomainPolicy.h"
#include "nsString.h" #include "nsString.h"
#include "nsCRT.h" #include "nsCRT.h"
@ -59,6 +58,7 @@
#include "nsIAsyncVerifyRedirectCallback.h" #include "nsIAsyncVerifyRedirectCallback.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/BindingUtils.h"
#include "mozilla/NullPrincipal.h"
#include <stdint.h> #include <stdint.h>
#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ScriptSettings.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"

View File

@ -21,10 +21,10 @@
class nsIIOService; class nsIIOService;
class nsIStringBundle; class nsIStringBundle;
class SystemPrincipal;
namespace mozilla { namespace mozilla {
class OriginAttributes; class OriginAttributes;
class SystemPrincipal;
} // namespace mozilla } // namespace mozilla
///////////////////////////// /////////////////////////////
@ -50,7 +50,7 @@ public:
// Invoked exactly once, by XPConnect. // Invoked exactly once, by XPConnect.
static void InitStatics(); static void InitStatics();
static already_AddRefed<SystemPrincipal> static already_AddRefed<mozilla::SystemPrincipal>
SystemPrincipalSingletonConstructor(); SystemPrincipalSingletonConstructor();
/** /**

View File

@ -7,6 +7,7 @@
const { const {
CLEAR_FLEXBOX, CLEAR_FLEXBOX,
UPDATE_FLEXBOX, UPDATE_FLEXBOX,
UPDATE_FLEXBOX_COLOR,
UPDATE_FLEXBOX_HIGHLIGHTED, UPDATE_FLEXBOX_HIGHLIGHTED,
} = require("./index"); } = require("./index");
@ -31,6 +32,19 @@ module.exports = {
}; };
}, },
/**
* 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. * Updates the flexbox highlighted state.
* *

View File

@ -14,6 +14,9 @@ createEnum([
// Updates the flexbox state with the newly selected flexbox. // Updates the flexbox state with the newly selected flexbox.
"UPDATE_FLEXBOX", "UPDATE_FLEXBOX",
// Update the color used for the overlay of a flexbox.
"UPDATE_FLEXBOX_COLOR",
// Updates the flexbox highlighted state. // Updates the flexbox highlighted state.
"UPDATE_FLEXBOX_HIGHLIGHTED", "UPDATE_FLEXBOX_HIGHLIGHTED",

View File

@ -17,8 +17,10 @@ class Flexbox extends PureComponent {
static get propTypes() { static get propTypes() {
return { return {
flexbox: PropTypes.shape(Types.flexbox).isRequired, flexbox: PropTypes.shape(Types.flexbox).isRequired,
getSwatchColorPickerTooltip: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired, setSelectedNode: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired, onHideBoxModelHighlighter: PropTypes.func.isRequired,
onSetFlexboxOverlayColor: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired, onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
onToggleFlexboxHighlighter: PropTypes.func.isRequired, onToggleFlexboxHighlighter: PropTypes.func.isRequired,
}; };
@ -27,8 +29,10 @@ class Flexbox extends PureComponent {
render() { render() {
const { const {
flexbox, flexbox,
getSwatchColorPickerTooltip,
setSelectedNode, setSelectedNode,
onHideBoxModelHighlighter, onHideBoxModelHighlighter,
onSetFlexboxOverlayColor,
onShowBoxModelHighlighterForNode, onShowBoxModelHighlighterForNode,
onToggleFlexboxHighlighter, onToggleFlexboxHighlighter,
} = this.props; } = this.props;
@ -46,8 +50,10 @@ class Flexbox extends PureComponent {
FlexboxItem({ FlexboxItem({
key: flexbox.id, key: flexbox.id,
flexbox, flexbox,
getSwatchColorPickerTooltip,
setSelectedNode, setSelectedNode,
onHideBoxModelHighlighter, onHideBoxModelHighlighter,
onSetFlexboxOverlayColor,
onShowBoxModelHighlighterForNode, onShowBoxModelHighlighterForNode,
onToggleFlexboxHighlighter, onToggleFlexboxHighlighter,
}) })

View File

@ -7,6 +7,7 @@
const { PureComponent } = require("devtools/client/shared/vendor/react"); const { PureComponent } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories"); const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); 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"); const { translateNodeFrontToGrip } = require("devtools/client/inspector/shared/utils");
// Reps // Reps
@ -20,8 +21,10 @@ class FlexboxItem extends PureComponent {
static get propTypes() { static get propTypes() {
return { return {
flexbox: PropTypes.shape(Types.flexbox).isRequired, flexbox: PropTypes.shape(Types.flexbox).isRequired,
getSwatchColorPickerTooltip: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired, setSelectedNode: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired, onHideBoxModelHighlighter: PropTypes.func.isRequired,
onSetFlexboxOverlayColor: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired, onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
onToggleFlexboxHighlighter: PropTypes.func.isRequired, onToggleFlexboxHighlighter: PropTypes.func.isRequired,
}; };
@ -29,10 +32,46 @@ class FlexboxItem extends PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
this.setFlexboxColor = this.setFlexboxColor.bind(this);
this.onFlexboxCheckboxClick = this.onFlexboxCheckboxClick.bind(this); this.onFlexboxCheckboxClick = this.onFlexboxCheckboxClick.bind(this);
this.onFlexboxInspectIconClick = this.onFlexboxInspectIconClick.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) { onFlexboxCheckboxClick(e) {
// If the click was on the svg icon to select the node in the inspector, bail out. // If the click was on the svg icon to select the node in the inspector, bail out.
const originalTarget = e.nativeEvent && e.nativeEvent.explicitOriginalTarget; const originalTarget = e.nativeEvent && e.nativeEvent.explicitOriginalTarget;
@ -65,6 +104,7 @@ class FlexboxItem extends PureComponent {
} = this.props; } = this.props;
const { const {
actorID, actorID,
color,
highlighted, highlighted,
nodeFront, nodeFront,
} = flexbox; } = flexbox;
@ -91,7 +131,21 @@ class FlexboxItem extends PureComponent {
onInspectIconClick: () => this.onFlexboxInspectIconClick(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)
); );
} }
} }

View File

@ -9,9 +9,15 @@ const { throttle } = require("devtools/client/inspector/shared/utils");
const { const {
clearFlexbox, clearFlexbox,
updateFlexbox, updateFlexbox,
updateFlexboxColor,
updateFlexboxHighlighted, updateFlexboxHighlighted,
} = require("./actions/flexbox"); } = 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 { class FlexboxInspector {
constructor(inspector, window) { constructor(inspector, window) {
this.document = window.document; this.document = window.document;
@ -22,6 +28,7 @@ class FlexboxInspector {
this.onHighlighterShown = this.onHighlighterShown.bind(this); this.onHighlighterShown = this.onHighlighterShown.bind(this);
this.onHighlighterHidden = this.onHighlighterHidden.bind(this); this.onHighlighterHidden = this.onHighlighterHidden.bind(this);
this.onReflow = throttle(this.onReflow, 500, this); this.onReflow = throttle(this.onReflow, 500, this);
this.onSetFlexboxOverlayColor = this.onSetFlexboxOverlayColor.bind(this);
this.onSidebarSelect = this.onSidebarSelect.bind(this); this.onSidebarSelect = this.onSidebarSelect.bind(this);
this.onToggleFlexboxHighlighter = this.onToggleFlexboxHighlighter.bind(this); this.onToggleFlexboxHighlighter = this.onToggleFlexboxHighlighter.bind(this);
this.onUpdatePanel = this.onUpdatePanel.bind(this); this.onUpdatePanel = this.onUpdatePanel.bind(this);
@ -86,10 +93,21 @@ class FlexboxInspector {
getComponentProps() { getComponentProps() {
return { return {
getSwatchColorPickerTooltip: this.getSwatchColorPickerTooltip,
onSetFlexboxOverlayColor: this.onSetFlexboxOverlayColor,
onToggleFlexboxHighlighter: this.onToggleFlexboxHighlighter, 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. * Returns true if the layout panel is visible, and false otherwise.
*/ */
@ -190,6 +208,31 @@ class FlexboxInspector {
this.update(flexboxFront); 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 * Handler for the inspector sidebar "select" event. Updates the flexbox panel if it
* is visible. * is visible.
@ -241,7 +284,7 @@ class FlexboxInspector {
* with new flexbox data. * with new flexbox data.
* *
* @param {FlexboxFront|Null} flexboxFront * @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) { async update(flexboxFront) {
// Stop refreshing if the inspector or store is already destroyed or no node is // Stop refreshing if the inspector or store is already destroyed or no node is
@ -292,8 +335,16 @@ class FlexboxInspector {
const highlighted = this._highlighters && const highlighted = this._highlighters &&
nodeFront == this.highlighters.flexboxHighlighterShown; 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({ this.store.dispatch(updateFlexbox({
actorID: flexboxFront.actorID, actorID: flexboxFront.actorID,
color,
highlighted, highlighted,
nodeFront, nodeFront,
})); }));

View File

@ -7,12 +7,15 @@
const { const {
CLEAR_FLEXBOX, CLEAR_FLEXBOX,
UPDATE_FLEXBOX, UPDATE_FLEXBOX,
UPDATE_FLEXBOX_COLOR,
UPDATE_FLEXBOX_HIGHLIGHTED, UPDATE_FLEXBOX_HIGHLIGHTED,
} = require("../actions/index"); } = require("../actions/index");
const INITIAL_FLEXBOX = { const INITIAL_FLEXBOX = {
// The actor ID of the flex container. // The actor ID of the flex container.
actorID: null, actorID: null,
// The color of the flexbox highlighter overlay.
color: "",
// Whether or not the flexbox highlighter is highlighting the flex container. // Whether or not the flexbox highlighter is highlighting the flex container.
highlighted: false, highlighted: false,
// The NodeFront of the flex container. // The NodeFront of the flex container.
@ -29,6 +32,12 @@ const reducers = {
return flexbox; return flexbox;
}, },
[UPDATE_FLEXBOX_COLOR](flexbox, { color }) {
return Object.assign({}, flexbox, {
color,
});
},
[UPDATE_FLEXBOX_HIGHLIGHTED](flexbox, { highlighted }) { [UPDATE_FLEXBOX_HIGHLIGHTED](flexbox, { highlighted }) {
return Object.assign({}, flexbox, { return Object.assign({}, flexbox, {
highlighted, highlighted,

View File

@ -9,7 +9,10 @@ const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
exports.flexbox = { exports.flexbox = {
// The actor ID of the flex container. // 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. // Whether or not the flexbox highlighter is highlighting the flex container.
highlighted: PropTypes.bool, highlighted: PropTypes.bool,

View File

@ -19,7 +19,6 @@ const {
} = require("./actions/highlighter-settings"); } = require("./actions/highlighter-settings");
loader.lazyRequireGetter(this, "compareFragmentsGeometry", "devtools/client/inspector/grids/utils/utils", true); 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, "parseURL", "devtools/client/shared/source-utils", true);
loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage"); loader.lazyRequireGetter(this, "asyncStorage", "devtools/shared/async-storage");
@ -57,7 +56,6 @@ class GridInspector {
this.telemetry = inspector.telemetry; this.telemetry = inspector.telemetry;
this.walker = this.inspector.walker; this.walker = this.inspector.walker;
this.getSwatchColorPickerTooltip = this.getSwatchColorPickerTooltip.bind(this);
this.updateGridPanel = this.updateGridPanel.bind(this); this.updateGridPanel = this.updateGridPanel.bind(this);
this.onHighlighterShown = this.onHighlighterShown.bind(this); this.onHighlighterShown = this.onHighlighterShown.bind(this);
@ -83,21 +81,9 @@ class GridInspector {
return this._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 * Initializes the grid inspector by fetching the LayoutFront from the walker and
* the highlighter settings and initalizing the SwatchColorPicker instance. * loading the highlighter settings.
*/ */
async init() { async init() {
if (!this.inspector) { if (!this.inspector) {
@ -138,13 +124,6 @@ class GridInspector {
this.inspector.reflowTracker.untrackReflows(this, this.onReflow); 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._highlighters = null;
this.document = null; this.document = null;
this.inspector = null; this.inspector = null;
@ -155,7 +134,6 @@ class GridInspector {
getComponentProps() { getComponentProps() {
return { return {
getSwatchColorPickerTooltip: this.getSwatchColorPickerTooltip,
onSetGridOverlayColor: this.onSetGridOverlayColor, onSetGridOverlayColor: this.onSetGridOverlayColor,
onShowGridOutlineHighlight: this.onShowGridOutlineHighlight, onShowGridOutlineHighlight: this.onShowGridOutlineHighlight,
onToggleGridHighlighter: this.onToggleGridHighlighter, onToggleGridHighlighter: this.onToggleGridHighlighter,
@ -215,13 +193,6 @@ class GridInspector {
return null; 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 * Given a list of new grid fronts, and if we have a currently highlighted grid, check
* if its fragments have changed. * if its fragments have changed.

View File

@ -20,10 +20,10 @@ const TEST_URI = `
add_task(async function() { add_task(async function() {
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); 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 { document: doc } = gridInspector;
const { store } = inspector; const { store } = inspector;
const cPicker = gridInspector.getSwatchColorPickerTooltip(); const cPicker = layoutView.getSwatchColorPickerTooltip();
const spectrum = cPicker.spectrum; const spectrum = cPicker.spectrum;
const swatch = doc.querySelector(".grid-color-swatch"); const swatch = doc.querySelector(".grid-color-swatch");

View File

@ -20,10 +20,10 @@ const TEST_URI = `
add_task(async function() { add_task(async function() {
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); 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 { document: doc } = gridInspector;
const { store } = inspector; const { store } = inspector;
const cPicker = gridInspector.getSwatchColorPickerTooltip(); const cPicker = layoutView.getSwatchColorPickerTooltip();
const spectrum = cPicker.spectrum; const spectrum = cPicker.spectrum;
const swatch = doc.querySelector(".grid-color-swatch"); const swatch = doc.querySelector(".grid-color-swatch");

View File

@ -20,10 +20,10 @@ const TEST_URI = `
add_task(async function() { add_task(async function() {
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); 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 { document: doc } = gridInspector;
const { store } = inspector; const { store } = inspector;
const cPicker = gridInspector.getSwatchColorPickerTooltip(); const cPicker = layoutView.getSwatchColorPickerTooltip();
const spectrum = cPicker.spectrum; const spectrum = cPicker.spectrum;
const swatch = doc.querySelector(".grid-color-swatch"); const swatch = doc.querySelector(".grid-color-swatch");

View File

@ -20,10 +20,10 @@ const TEST_URI = `
add_task(async function() { add_task(async function() {
await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); 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 { document: doc } = gridInspector;
const { store } = inspector; const { store } = inspector;
const cPicker = gridInspector.getSwatchColorPickerTooltip(); const cPicker = layoutView.getSwatchColorPickerTooltip();
const swatch = doc.querySelector(".grid-color-swatch"); const swatch = doc.querySelector(".grid-color-swatch");
info("Scrolling into view of the #grid color swatch."); info("Scrolling into view of the #grid color swatch.");

View File

@ -42,6 +42,7 @@ class LayoutApp extends PureComponent {
setSelectedNode: PropTypes.func.isRequired, setSelectedNode: PropTypes.func.isRequired,
showBoxModelProperties: PropTypes.bool.isRequired, showBoxModelProperties: PropTypes.bool.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired, onHideBoxModelHighlighter: PropTypes.func.isRequired,
onSetFlexboxOverlayColor: PropTypes.func.isRequired,
onSetGridOverlayColor: PropTypes.func.isRequired, onSetGridOverlayColor: PropTypes.func.isRequired,
onShowBoxModelEditor: PropTypes.func.isRequired, onShowBoxModelEditor: PropTypes.func.isRequired,
onShowBoxModelHighlighter: PropTypes.func.isRequired, onShowBoxModelHighlighter: PropTypes.func.isRequired,

View File

@ -15,6 +15,7 @@ const INSPECTOR_L10N =
loader.lazyRequireGetter(this, "FlexboxInspector", "devtools/client/inspector/flexbox/flexbox"); loader.lazyRequireGetter(this, "FlexboxInspector", "devtools/client/inspector/flexbox/flexbox");
loader.lazyRequireGetter(this, "GridInspector", "devtools/client/inspector/grids/grid-inspector"); loader.lazyRequireGetter(this, "GridInspector", "devtools/client/inspector/grids/grid-inspector");
loader.lazyRequireGetter(this, "SwatchColorPickerTooltip", "devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip");
class LayoutView { class LayoutView {
constructor(inspector, window) { constructor(inspector, window) {
@ -22,6 +23,8 @@ class LayoutView {
this.inspector = inspector; this.inspector = inspector;
this.store = inspector.store; this.store = inspector.store;
this.getSwatchColorPickerTooltip = this.getSwatchColorPickerTooltip.bind(this);
this.init(); this.init();
} }
@ -42,15 +45,14 @@ class LayoutView {
onToggleGeometryEditor, onToggleGeometryEditor,
} = this.inspector.getPanel("boxmodel").getComponentProps(); } = this.inspector.getPanel("boxmodel").getComponentProps();
this.flexboxInspector = new FlexboxInspector(this.inspector, this.flexboxInspector = new FlexboxInspector(this.inspector, this.inspector.panelWin);
this.inspector.panelWin);
const { const {
onSetFlexboxOverlayColor,
onToggleFlexboxHighlighter, onToggleFlexboxHighlighter,
} = this.flexboxInspector.getComponentProps(); } = this.flexboxInspector.getComponentProps();
this.gridInspector = new GridInspector(this.inspector, this.inspector.panelWin); this.gridInspector = new GridInspector(this.inspector, this.inspector.panelWin);
const { const {
getSwatchColorPickerTooltip,
onSetGridOverlayColor, onSetGridOverlayColor,
onShowGridOutlineHighlight, onShowGridOutlineHighlight,
onToggleGridHighlighter, onToggleGridHighlighter,
@ -60,7 +62,7 @@ class LayoutView {
} = this.gridInspector.getComponentProps(); } = this.gridInspector.getComponentProps();
const layoutApp = LayoutApp({ const layoutApp = LayoutApp({
getSwatchColorPickerTooltip, getSwatchColorPickerTooltip: this.getSwatchColorPickerTooltip,
setSelectedNode, setSelectedNode,
/** /**
* Shows the box model properties under the box model if true, otherwise, hidden by * Shows the box model properties under the box model if true, otherwise, hidden by
@ -68,6 +70,7 @@ class LayoutView {
*/ */
showBoxModelProperties: true, showBoxModelProperties: true,
onHideBoxModelHighlighter, onHideBoxModelHighlighter,
onSetFlexboxOverlayColor,
onSetGridOverlayColor, onSetGridOverlayColor,
onShowBoxModelEditor, onShowBoxModelEditor,
onShowBoxModelHighlighter, onShowBoxModelHighlighter,
@ -96,6 +99,11 @@ class LayoutView {
* Destruction function called when the inspector is destroyed. Cleans up references. * Destruction function called when the inspector is destroyed. Cleans up references.
*/ */
destroy() { destroy() {
if (this._swatchColorPickerTooltip) {
this._swatchColorPickerTooltip.destroy();
this._swatchColorPickerTooltip = null;
}
this.flexboxInspector.destroy(); this.flexboxInspector.destroy();
this.gridInspector.destroy(); this.gridInspector.destroy();
@ -103,6 +111,25 @@ class LayoutView {
this.inspector = null; this.inspector = null;
this.store = 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; module.exports = LayoutView;

View File

@ -215,6 +215,18 @@ class HighlightersOverlay {
} }
} }
/**
* 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. * Toggle the flexbox highlighter for the given flexbox container element.
* *
@ -246,6 +258,8 @@ class HighlightersOverlay {
return; return;
} }
options = Object.assign({}, options, this.getFlexboxHighlighterSettings(node));
const isShown = await highlighter.show(node, options); const isShown = await highlighter.show(node, options);
if (!isShown) { if (!isShown) {
return; return;

View File

@ -151,6 +151,7 @@ function openLayoutView() {
inspector: data.inspector, inspector: data.inspector,
boxmodel: data.inspector.getPanel("boxmodel"), boxmodel: data.inspector.getPanel("boxmodel"),
gridInspector: data.inspector.layoutview.gridInspector, gridInspector: data.inspector.layoutview.gridInspector,
layoutView: data.inspector.layoutview,
testActor: data.testActor testActor: data.testActor
}; };
}); });

View File

@ -28,6 +28,7 @@ function runCodeMirrorTest(browser) {
// setting a timeout to check again if not. // setting a timeout to check again if not.
/* eslint-disable max-len */ /* eslint-disable max-len */
mm.loadFrameScript("data:," + mm.loadFrameScript("data:," +
"ChromeUtils.import('resource://gre/modules/Timer.jsm');" +
"content.wrappedJSObject.mozilla_setStatus = function(statusMsg, type, customMsg) {" + "content.wrappedJSObject.mozilla_setStatus = function(statusMsg, type, customMsg) {" +
" sendSyncMessage('setStatus', {statusMsg: statusMsg, type: type, customMsg: customMsg});" + " sendSyncMessage('setStatus', {statusMsg: statusMsg, type: type, customMsg: customMsg});" +
"};" + "};" +

View File

@ -130,9 +130,10 @@
} }
/** /**
* Grid Item * Flexbox and Grid Item
*/ */
.flexbox-color-swatch,
.grid-color-swatch { .grid-color-swatch {
width: 12px; width: 12px;
height: 12px; height: 12px;
@ -144,6 +145,7 @@
vertical-align: middle; vertical-align: middle;
} }
.flexbox-color-value,
.grid-color-value { .grid-color-value {
display: none; display: none;
} }

View File

@ -60,12 +60,15 @@ const JUSTIFY_CONTENT = "justify-content";
* display: [inline-]flex elements. * display: [inline-]flex elements.
* *
* Available Options: * Available Options:
* - color(colorValue)
* @param {String} colorValue
* The color that should be used to draw the highlighter for this flexbox.
* - showAlignment(isShown) * - showAlignment(isShown)
* @param {Boolean} isShown * @param {Boolean} isShown
* Shows the alignment in the flexbox highlighter. * Shows the alignment in the flexbox highlighter.
* - showFlexBasis(isShown) * - showFlexBasis(isShown)
* @param {Boolean} isShown * @param {Boolean} isShown
* Shows the flex basis in the flexbox highlighter. * Shows the flex basis in the flexbox highlighter.
*/ */
class FlexboxHighlighter extends AutoRefreshHighlighter { class FlexboxHighlighter extends AutoRefreshHighlighter {
constructor(highlighterEnv) { constructor(highlighterEnv) {
@ -169,6 +172,10 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
return this.getElement("canvas"); return this.getElement("canvas");
} }
get color() {
return this.options.color || DEFAULT_COLOR;
}
get ctx() { get ctx() {
return this.canvas.getCanvasContext("2d"); return this.canvas.getCanvasContext("2d");
} }
@ -211,7 +218,7 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
ctx.moveTo(0, 0); ctx.moveTo(0, 0);
ctx.lineTo(width, height); ctx.lineTo(width, height);
ctx.strokeStyle = DEFAULT_COLOR; ctx.strokeStyle = this.color;
ctx.stroke(); ctx.stroke();
ctx.restore(); ctx.restore();
@ -258,7 +265,7 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
ctx.moveTo(0, height); ctx.moveTo(0, height);
ctx.lineTo(width, 0); ctx.lineTo(width, 0);
ctx.strokeStyle = DEFAULT_COLOR; ctx.strokeStyle = this.color;
ctx.stroke(); ctx.stroke();
ctx.restore(); ctx.restore();
@ -393,7 +400,7 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
this.ctx.translate(offset - canvasX, offset - canvasY); this.ctx.translate(offset - canvasX, offset - canvasY);
this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.alignItems.lineDash); this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.alignItems.lineDash);
this.ctx.lineWidth = lineWidth * 3; this.ctx.lineWidth = lineWidth * 3;
this.ctx.strokeStyle = DEFAULT_COLOR; this.ctx.strokeStyle = this.color;
const { bounds } = this.currentQuads.content[0]; const { bounds } = this.currentQuads.content[0];
const isColumn = this.flexDirection.startsWith("column"); const isColumn = this.flexDirection.startsWith("column");
@ -493,7 +500,7 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
this.ctx.translate(offset - canvasX, offset - canvasY); this.ctx.translate(offset - canvasX, offset - canvasY);
this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.edge.lineDash); this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.edge.lineDash);
this.ctx.lineWidth = lineWidth; this.ctx.lineWidth = lineWidth;
this.ctx.strokeStyle = DEFAULT_COLOR; this.ctx.strokeStyle = this.color;
const { bounds } = this.currentQuads.content[0]; const { bounds } = this.currentQuads.content[0];
drawRect(this.ctx, 0, 0, bounds.width, bounds.height, this.currentMatrix); drawRect(this.ctx, 0, 0, bounds.width, bounds.height, this.currentMatrix);
@ -517,7 +524,7 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
this.ctx.translate(offset - canvasX, offset - canvasY); this.ctx.translate(offset - canvasX, offset - canvasY);
this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.edge.lineDash); this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.edge.lineDash);
this.ctx.lineWidth = 0; this.ctx.lineWidth = 0;
this.ctx.strokeStyle = DEFAULT_COLOR; this.ctx.strokeStyle = this.color;
this.ctx.fillStyle = this.getFlexContainerPattern(devicePixelRatio); this.ctx.fillStyle = this.getFlexContainerPattern(devicePixelRatio);
const { bounds } = this.currentQuads.content[0]; const { bounds } = this.currentQuads.content[0];
@ -572,7 +579,7 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
this.ctx.translate(offset - canvasX, offset - canvasY); this.ctx.translate(offset - canvasX, offset - canvasY);
this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.item.lineDash); this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.item.lineDash);
this.ctx.lineWidth = lineWidth; this.ctx.lineWidth = lineWidth;
this.ctx.strokeStyle = DEFAULT_COLOR; this.ctx.strokeStyle = this.color;
const { bounds } = this.currentQuads.content[0]; const { bounds } = this.currentQuads.content[0];
@ -615,7 +622,7 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
this.ctx.save(); this.ctx.save();
this.ctx.translate(offset - canvasX, offset - canvasY); this.ctx.translate(offset - canvasX, offset - canvasY);
this.ctx.lineWidth = lineWidth; this.ctx.lineWidth = lineWidth;
this.ctx.strokeStyle = DEFAULT_COLOR; this.ctx.strokeStyle = this.color;
const { bounds } = this.currentQuads.content[0]; const { bounds } = this.currentQuads.content[0];
const isColumn = this.flexDirection.startsWith("column"); const isColumn = this.flexDirection.startsWith("column");

View File

@ -199,8 +199,8 @@
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "GeckoProfiler.h" #include "GeckoProfiler.h"
#include "mozilla/NullPrincipal.h"
#include "Navigator.h" #include "Navigator.h"
#include "NullPrincipal.h"
#include "prenv.h" #include "prenv.h"
#include "URIUtils.h" #include "URIUtils.h"

View File

@ -19,8 +19,8 @@
#include "nsDOMJSUtils.h" #include "nsDOMJSUtils.h"
#include "nsError.h" #include "nsError.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "NullPrincipal.h"
#include "mozilla/LoadInfo.h" #include "mozilla/LoadInfo.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ScriptSettings.h"

View File

@ -31,7 +31,7 @@
#include "nsGlobalWindow.h" #include "nsGlobalWindow.h"
#include "mozilla/Likely.h" #include "mozilla/Likely.h"
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
#include "NullPrincipal.h" #include "mozilla/NullPrincipal.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "mozilla/dom/LocationBinding.h" #include "mozilla/dom/LocationBinding.h"
#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ScriptSettings.h"

View File

@ -158,6 +158,7 @@
#include "nsIMIMEService.h" #include "nsIMIMEService.h"
#include "nsINode.h" #include "nsINode.h"
#include "mozilla/dom/NodeInfo.h" #include "mozilla/dom/NodeInfo.h"
#include "mozilla/NullPrincipal.h"
#include "nsIObjectLoadingContent.h" #include "nsIObjectLoadingContent.h"
#include "nsIObserver.h" #include "nsIObserver.h"
#include "nsIObserverService.h" #include "nsIObserverService.h"
@ -187,7 +188,6 @@
#include "nsNetCID.h" #include "nsNetCID.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsNodeInfoManager.h" #include "nsNodeInfoManager.h"
#include "NullPrincipal.h"
#include "nsParserCIID.h" #include "nsParserCIID.h"
#include "nsParserConstants.h" #include "nsParserConstants.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"

View File

@ -110,7 +110,7 @@
#include "nsIPermissionManager.h" #include "nsIPermissionManager.h"
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "ExpandedPrincipal.h" #include "ExpandedPrincipal.h"
#include "NullPrincipal.h" #include "mozilla/NullPrincipal.h"
#include "nsIDOMWindow.h" #include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"

View File

@ -44,7 +44,6 @@
#include "nsIXULWindow.h" #include "nsIXULWindow.h"
#include "nsIMozBrowserFrame.h" #include "nsIMozBrowserFrame.h"
#include "nsISHistory.h" #include "nsISHistory.h"
#include "NullPrincipal.h"
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "nsGlobalWindow.h" #include "nsGlobalWindow.h"
#include "nsHTMLDocument.h" #include "nsHTMLDocument.h"
@ -76,6 +75,7 @@
#include "mozilla/BasePrincipal.h" #include "mozilla/BasePrincipal.h"
#include "mozilla/GuardObjects.h" #include "mozilla/GuardObjects.h"
#include "mozilla/HTMLEditor.h" #include "mozilla/HTMLEditor.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "mozilla/dom/ChromeMessageSender.h" #include "mozilla/dom/ChromeMessageSender.h"
@ -102,7 +102,7 @@
#include "mozilla/dom/HTMLBodyElement.h" #include "mozilla/dom/HTMLBodyElement.h"
#include "ContentPrincipal.h" #include "mozilla/ContentPrincipal.h"
#ifdef XP_WIN #ifdef XP_WIN
#include "mozilla/plugins/PPluginWidgetParent.h" #include "mozilla/plugins/PPluginWidgetParent.h"

View File

@ -13,6 +13,7 @@
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "mozilla/dom/NodeInfo.h" #include "mozilla/dom/NodeInfo.h"
#include "mozilla/dom/NodeInfoInlines.h" #include "mozilla/dom/NodeInfoInlines.h"
#include "mozilla/NullPrincipal.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsString.h" #include "nsString.h"
#include "nsAtom.h" #include "nsAtom.h"
@ -30,7 +31,6 @@
#include "nsNameSpaceManager.h" #include "nsNameSpaceManager.h"
#include "nsDocument.h" #include "nsDocument.h"
#include "nsWindowSizes.h" #include "nsWindowSizes.h"
#include "NullPrincipal.h"
using namespace mozilla; using namespace mozilla;
using mozilla::dom::NodeInfo; using mozilla::dom::NodeInfo;

View File

@ -14,6 +14,7 @@
#include "mozilla/dom/CSSRuleList.h" #include "mozilla/dom/CSSRuleList.h"
#include "mozilla/dom/DocumentFragment.h" #include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/SRIMetadata.h" #include "mozilla/dom/SRIMetadata.h"
#include "mozilla/NullPrincipal.h"
#include "nsCSSPropertyID.h" #include "nsCSSPropertyID.h"
#include "nsUnicharInputStream.h" #include "nsUnicharInputStream.h"
#include "nsAttrName.h" #include "nsAttrName.h"
@ -21,7 +22,6 @@
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "NullPrincipal.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsIParserUtils.h" #include "nsIParserUtils.h"
#include "nsIDocument.h" #include "nsIDocument.h"

View File

@ -10,13 +10,13 @@
#include "js/Class.h" #include "js/Class.h"
#include "nsJSPrincipals.h" #include "nsJSPrincipals.h"
#include "NullPrincipal.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "xpcprivate.h" #include "xpcprivate.h"
#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ScriptSettings.h"
#include "mozilla/NullPrincipal.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {

View File

@ -8,7 +8,7 @@
#include "ConsoleCommon.h" #include "ConsoleCommon.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#include "NullPrincipal.h" #include "mozilla/NullPrincipal.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {

View File

@ -23,12 +23,12 @@
#include "js/Date.h" #include "js/Date.h"
#include "js/StructuredClone.h" #include "js/StructuredClone.h"
#include "KeyPath.h" #include "KeyPath.h"
#include "NullPrincipal.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#include "mozilla/EndianUtils.h" #include "mozilla/EndianUtils.h"
#include "mozilla/ErrorResult.h" #include "mozilla/ErrorResult.h"
#include "mozilla/JSObjectHolder.h" #include "mozilla/JSObjectHolder.h"
#include "mozilla/Move.h" #include "mozilla/Move.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentParent.h"

View File

@ -17,6 +17,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/BackgroundHangMonitor.h" #include "mozilla/BackgroundHangMonitor.h"
#include "mozilla/LookAndFeel.h" #include "mozilla/LookAndFeel.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/ProcessHangMonitorIPC.h" #include "mozilla/ProcessHangMonitorIPC.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
@ -85,7 +86,6 @@
#include "mozilla/HangDetails.h" #include "mozilla/HangDetails.h"
#include "imgLoader.h" #include "imgLoader.h"
#include "GMPServiceChild.h" #include "GMPServiceChild.h"
#include "NullPrincipal.h"
#include "nsISimpleEnumerator.h" #include "nsISimpleEnumerator.h"
#include "nsIStringBundle.h" #include "nsIStringBundle.h"
#include "nsIWorkerDebuggerManager.h" #include "nsIWorkerDebuggerManager.h"

View File

@ -95,10 +95,10 @@
#include "ImageOps.h" #include "ImageOps.h"
#include "UnitTransforms.h" #include "UnitTransforms.h"
#include <algorithm> #include <algorithm>
#include "mozilla/NullPrincipal.h"
#include "mozilla/WebBrowserPersistDocumentParent.h" #include "mozilla/WebBrowserPersistDocumentParent.h"
#include "ProcessPriorityManager.h" #include "ProcessPriorityManager.h"
#include "nsString.h" #include "nsString.h"
#include "NullPrincipal.h"
#ifdef XP_WIN #ifdef XP_WIN
#include "mozilla/plugins/PluginWidgetParent.h" #include "mozilla/plugins/PluginWidgetParent.h"

View File

@ -36,6 +36,7 @@
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "mozilla/EventStateManager.h" #include "mozilla/EventStateManager.h"
#include "mozilla/MozPromise.h" #include "mozilla/MozPromise.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "mozilla/Types.h" #include "mozilla/Types.h"
#include "mozilla/PeerIdentity.h" #include "mozilla/PeerIdentity.h"
@ -57,7 +58,6 @@
#include "ThreadSafeRefcountingWithMainThreadDestruction.h" #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
#include "Latency.h" #include "Latency.h"
#include "nsProxyRelease.h" #include "nsProxyRelease.h"
#include "NullPrincipal.h"
#include "nsVariant.h" #include "nsVariant.h"
// For snprintf // For snprintf

View File

@ -50,6 +50,7 @@
#include "nsIWritablePropertyBag2.h" #include "nsIWritablePropertyBag2.h"
#include "nsICategoryManager.h" #include "nsICategoryManager.h"
#include "nsPluginStreamListenerPeer.h" #include "nsPluginStreamListenerPeer.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
@ -96,7 +97,6 @@
#include "nsIImageLoadingContent.h" #include "nsIImageLoadingContent.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "nsVersionComparator.h" #include "nsVersionComparator.h"
#include "NullPrincipal.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"

View File

@ -31,7 +31,7 @@
#include "GeckoProfiler.h" #include "GeckoProfiler.h"
#include "nsPluginInstanceOwner.h" #include "nsPluginInstanceOwner.h"
#include "nsDataHashtable.h" #include "nsDataHashtable.h"
#include "NullPrincipal.h" #include "mozilla/NullPrincipal.h"
// nsPluginStreamListenerPeer // nsPluginStreamListenerPeer

View File

@ -13,7 +13,9 @@
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsIPrincipal.h" #include "nsIPrincipal.h"
#include "nsScriptSecurityManager.h" #include "nsScriptSecurityManager.h"
#include "NullPrincipal.h" #include "mozilla/NullPrincipal.h"
using namespace mozilla;
static const uint32_t kURIMaxLength = 64; static const uint32_t kURIMaxLength = 64;

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/BasePrincipal.h" #include "mozilla/BasePrincipal.h"
#include "mozilla/ContentPrincipal.h"
#include "mozilla/Services.h" #include "mozilla/Services.h"
#include "mozilla/SystemGroup.h" #include "mozilla/SystemGroup.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
@ -44,7 +45,6 @@
#include "nsIObserverService.h" #include "nsIObserverService.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "mozilla/AbstractThread.h" #include "mozilla/AbstractThread.h"
#include "ContentPrincipal.h"
#include "ExpandedPrincipal.h" #include "ExpandedPrincipal.h"
static nsPermissionManager *gPermissionManager = nullptr; static nsPermissionManager *gPermissionManager = nullptr;

View File

@ -16,15 +16,16 @@
#include "nspr.h" #include "nspr.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/NullPrincipal.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
#include "nsJSPrincipals.h" #include "nsJSPrincipals.h"
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "js/Wrapper.h" #include "js/Wrapper.h"
#include "NullPrincipal.h"
extern mozilla::LazyLogModule MCD; extern mozilla::LazyLogModule MCD;
using mozilla::AutoSafeJSContext; using mozilla::AutoSafeJSContext;
using mozilla::NullPrincipal;
using mozilla::dom::AutoJSAPI; using mozilla::dom::AutoJSAPI;
//***************************************************************************** //*****************************************************************************

View File

@ -472,6 +472,7 @@ GetD2D1PropsForIntSize(FilterType aType, uint32_t aIndex, UINT32 *aPropWidth, UI
static inline REFCLSID GetCLDIDForFilterType(FilterType aType) static inline REFCLSID GetCLDIDForFilterType(FilterType aType)
{ {
switch (aType) { switch (aType) {
case FilterType::OPACITY:
case FilterType::COLOR_MATRIX: case FilterType::COLOR_MATRIX:
return CLSID_D2D1ColorMatrix; return CLSID_D2D1ColorMatrix;
case FilterType::TRANSFORM: case FilterType::TRANSFORM:
@ -585,6 +586,10 @@ FilterNodeD2D1::Create(ID2D1DeviceContext *aDC, FilterType aType)
effect->SetValue(D2D1_ARITHMETICCOMPOSITE_PROP_CLAMP_OUTPUT, TRUE); effect->SetValue(D2D1_ARITHMETICCOMPOSITE_PROP_CLAMP_OUTPUT, TRUE);
} }
if (aType == FilterType::OPACITY) {
return MakeAndAddRef<FilterNodeOpacityD2D1>(effect, aType);
}
RefPtr<FilterNodeD2D1> filter = new FilterNodeD2D1(effect, aType); RefPtr<FilterNodeD2D1> filter = new FilterNodeD2D1(effect, aType);
if (HasUnboundedOutputRegion(aType)) { if (HasUnboundedOutputRegion(aType)) {
@ -870,6 +875,20 @@ FilterNodeD2D1::SetAttribute(uint32_t aIndex, const Matrix &aMatrix)
mEffect->SetValue(input, D2DMatrix(aMatrix)); 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) FilterNodeConvolveD2D1::FilterNodeConvolveD2D1(ID2D1DeviceContext *aDC)
: FilterNodeD2D1(nullptr, FilterType::CONVOLVE_MATRIX) : FilterNodeD2D1(nullptr, FilterType::CONVOLVE_MATRIX)
, mEdgeMode(EDGE_MODE_DUPLICATE) , mEdgeMode(EDGE_MODE_DUPLICATE)

View File

@ -108,6 +108,17 @@ private:
IntRect mSourceRect; 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 class FilterNodeExtendInputAdapterD2D1 : public FilterNodeD2D1
{ {
public: public:

View File

@ -514,6 +514,9 @@ FilterNodeSoftware::Create(FilterType aType)
case FilterType::UNPREMULTIPLY: case FilterType::UNPREMULTIPLY:
filter = new FilterNodeUnpremultiplySoftware(); filter = new FilterNodeUnpremultiplySoftware();
break; break;
case FilterType::OPACITY:
filter = new FilterNodeOpacitySoftware();
break;
case FilterType::POINT_DIFFUSE: case FilterType::POINT_DIFFUSE:
filter = new FilterNodeLightingSoftware<PointLightSoftware, DiffuseLightingSoftware>("FilterNodeLightingSoftware<PointLight, DiffuseLighting>"); filter = new FilterNodeLightingSoftware<PointLightSoftware, DiffuseLightingSoftware>("FilterNodeLightingSoftware<PointLight, DiffuseLighting>");
break; break;
@ -1432,6 +1435,44 @@ Unpremultiply(DataSourceSurface* aSurface)
return target.forget(); 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> already_AddRefed<DataSourceSurface>
FilterNodeColorMatrixSoftware::Render(const IntRect& aRect) FilterNodeColorMatrixSoftware::Render(const IntRect& aRect)
{ {
@ -3212,6 +3253,44 @@ FilterNodeUnpremultiplySoftware::GetOutputRectInRect(const IntRect& aRect)
return GetInputRectInRect(IN_UNPREMULTIPLY_IN, 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 bool
PointLightSoftware::SetAttribute(uint32_t aIndex, const Point3D &aPoint) PointLightSoftware::SetAttribute(uint32_t aIndex, const Point3D &aPoint)
{ {

View File

@ -688,6 +688,22 @@ protected:
virtual void RequestFromInputsForRect(const IntRect &aRect) 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> template<typename LightType, typename LightingType>
class FilterNodeLightingSoftware : public FilterNodeSoftware class FilterNodeLightingSoftware : public FilterNodeSoftware
{ {

View File

@ -236,6 +236,34 @@ FilterProcessing::DoUnpremultiplicationCalculation(const IntSize& aSize,
} }
} }
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> already_AddRefed<DataSourceSurface>
FilterProcessing::RenderTurbulence(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, FilterProcessing::RenderTurbulence(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect) int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect)

View File

@ -59,6 +59,14 @@ public:
static void DoUnpremultiplicationCalculation(const IntSize& aSize, static void DoUnpremultiplicationCalculation(const IntSize& aSize,
uint8_t* aTargetData, int32_t aTargetStride, uint8_t* aTargetData, int32_t aTargetStride,
uint8_t* aSourceData, int32_t aSourceStride); 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> static already_AddRefed<DataSourceSurface>
RenderTurbulence(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, RenderTurbulence(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect); int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect);
@ -87,6 +95,14 @@ protected:
static void DoUnpremultiplicationCalculation_Scalar(const IntSize& aSize, static void DoUnpremultiplicationCalculation_Scalar(const IntSize& aSize,
uint8_t* aTargetData, int32_t aTargetStride, uint8_t* aTargetData, int32_t aTargetStride,
uint8_t* aSourceData, int32_t aSourceStride); 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> static already_AddRefed<DataSourceSurface>
RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect); int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect);
@ -115,6 +131,10 @@ protected:
static void DoUnpremultiplicationCalculation_SSE2(const IntSize& aSize, static void DoUnpremultiplicationCalculation_SSE2(const IntSize& aSize,
uint8_t* aTargetData, int32_t aTargetStride, uint8_t* aTargetData, int32_t aTargetStride,
uint8_t* aSourceData, int32_t aSourceStride); 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> static already_AddRefed<DataSourceSurface>
RenderTurbulence_SSE2(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, RenderTurbulence_SSE2(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect); int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect);

View File

@ -982,6 +982,38 @@ DoUnpremultiplicationCalculation_SIMD(const IntSize& aSize,
} }
} }
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> template<typename f32x4_t, typename i32x4_t, typename u8x16_t>
static already_AddRefed<DataSourceSurface> static already_AddRefed<DataSourceSurface>
RenderTurbulence_SIMD(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, RenderTurbulence_SIMD(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,

View File

@ -96,6 +96,15 @@ FilterProcessing::DoUnpremultiplicationCalculation_SSE2(
DoUnpremultiplicationCalculation_SIMD<__m128i,__m128i>(aSize, aTargetData, aTargetStride, aSourceData, 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> already_AddRefed<DataSourceSurface>
FilterProcessing::RenderTurbulence_SSE2(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, FilterProcessing::RenderTurbulence_SSE2(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect) int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect)

View File

@ -227,6 +227,46 @@ FilterProcessing::DoUnpremultiplicationCalculation_Scalar(
} }
} }
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> already_AddRefed<DataSourceSurface>
FilterProcessing::RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency, FilterProcessing::RenderTurbulence_Scalar(const IntSize &aSize, const Point &aOffset, const Size &aBaseFrequency,
int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect) int32_t aSeed, int aNumOctaves, TurbulenceType aType, bool aStitch, const Rect &aTileRect)

View File

@ -476,6 +476,16 @@ enum UnpremultiplyInputs
IN_UNPREMULTIPLY_IN = 0 IN_UNPREMULTIPLY_IN = 0
}; };
enum OpacityAtts
{
ATT_OPACITY_VALUE = 0
};
enum OpacityInputs
{
IN_OPACITY_IN = 0
};
class FilterNode : public external::AtomicRefCounted<FilterNode> class FilterNode : public external::AtomicRefCounted<FilterNode>
{ {
public: public:

View File

@ -128,7 +128,8 @@ enum class FilterType : int8_t {
DISTANT_SPECULAR, DISTANT_SPECULAR,
CROP, CROP,
PREMULTIPLY, PREMULTIPLY,
UNPREMULTIPLY UNPREMULTIPLY,
OPACITY
}; };
enum class DrawTargetType : int8_t { enum class DrawTargetType : int8_t {

View File

@ -22,6 +22,7 @@
################################################################################ ################################################################################
# includes # includes
from __future__ import print_function
import os import os
import sys import sys
import xml.etree.ElementTree import xml.etree.ElementTree
@ -34,7 +35,6 @@ class GLConstHeader:
def __init__(self, f): def __init__(self, f):
self.f = f self.f = f
def write(self, arg): def write(self, arg):
if isinstance(arg, list): if isinstance(arg, list):
self.f.write('\n'.join(arg) + '\n') self.f.write('\n'.join(arg) + '\n')
@ -43,7 +43,6 @@ class GLConstHeader:
else: else:
self.f.write(str(arg) + '\n') self.f.write(str(arg) + '\n')
def formatFileBegin(self): def formatFileBegin(self):
self.write([ self.write([
'/* This Source Code Form is subject to the terms of the Mozilla Public', '/* This Source Code Form is subject to the terms of the Mozilla Public',
@ -63,12 +62,10 @@ class GLConstHeader:
'' ''
]) ])
def formatLibBegin(self, lib): def formatLibBegin(self, lib):
# lib would be 'GL', 'EGL', 'GLX' or 'WGL' # lib would be 'GL', 'EGL', 'GLX' or 'WGL'
self.write('// ' + lib) self.write('// ' + lib)
def formatLibConstant(self, lib, name, value): def formatLibConstant(self, lib, name, value):
# lib would be 'GL', 'EGL', 'GLX' or 'WGL' # lib would be 'GL', 'EGL', 'GLX' or 'WGL'
# name is the name of the const (example: MAX_TEXTURE_SIZE) # name is the name of the const (example: MAX_TEXTURE_SIZE)
@ -76,23 +73,21 @@ class GLConstHeader:
define = '#define LOCAL_' + lib + '_' + name define = '#define LOCAL_' + lib + '_' + name
whitespace = 60 - len(define) whitespace = 60 - len(define)
if whitespace < 0: if whitespace < 0:
whitespace = whitespace % 8 whitespace = whitespace % 8
self.write(define + ' ' * whitespace + ' ' + value)
self.write(define + ' ' * whitespace + ' ' + value)
def formatLibEnd(self, lib): def formatLibEnd(self, lib):
# lib would be 'GL', 'EGL', 'GLX' or 'WGL' # lib would be 'GL', 'EGL', 'GLX' or 'WGL'
self.write(2) self.write(2)
def formatFileEnd(self): def formatFileEnd(self):
self.write([ self.write([
'', '',
'#endif // GLCONSTS_H_' '#endif // GLCONSTS_H_'
]) ])
################################################################################ ################################################################################
@ -132,12 +127,11 @@ class GLDatabase:
# there is no vendor="EXT" and vendor="ATI" in gl.xml, # there is no vendor="EXT" and vendor="ATI" in gl.xml,
# so we manualy declare them # so we manualy declare them
def loadXML(self, path): def loadXML(self, path):
xmlPath = getXMLDir() + path xmlPath = getXMLDir() + path
if not os.path.isfile(xmlPath): if not os.path.isfile(xmlPath):
print 'missing file "' + xmlPath + '"' print('missing file "' + xmlPath + '"')
return False return False
tree = xml.etree.ElementTree.parse(xmlPath) tree = xml.etree.ElementTree.parse(xmlPath)
@ -179,9 +173,8 @@ class GLDatabase:
return True return True
def exportConsts(self, path): def exportConsts(self, path):
with open(getScriptDir() + path,'w') as f: with open(getScriptDir() + path, 'w') as f:
headerFile = GLConstHeader(f) headerFile = GLConstHeader(f)
headerFile.formatFileBegin() headerFile.formatFileBegin()

View File

@ -12,19 +12,22 @@ import tempfile
import yaml import yaml
import buildconfig 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()
with open(args.output, 'w') as out_file: def shell_main():
process_manifest(out_file, args.manifest) 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)
def main(output_fp, input_filename): 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 HEADER = """// AUTOGENERATED - DO NOT EDIT
namespace mozilla { namespace mozilla {
@ -36,123 +39,133 @@ FOOTER = """
} // namespace layers } // namespace layers
} // namespace mozilla""" } // namespace mozilla"""
def process_manifest(output_fp, manifest_filename): def process_manifest(output_fp, manifest_filename):
with codecs.open(manifest_filename, 'r', 'UTF-8') as in_fp: with codecs.open(manifest_filename, 'r', 'UTF-8') as in_fp:
manifest = yaml.safe_load(in_fp) manifest = yaml.safe_load(in_fp)
shader_folder, _ = os.path.split(manifest_filename) shader_folder, _ = os.path.split(manifest_filename)
output_fp.write(HEADER) output_fp.write(HEADER)
deps = set() deps = set()
for block in manifest: for block in manifest:
if 'type' not in block: if 'type' not in block:
raise Exception("Expected 'type' key with shader mode") raise Exception("Expected 'type' key with shader mode")
if 'file' not in block: if 'file' not in block:
raise Exception("Expected 'file' key with shader file") raise Exception("Expected 'file' key with shader file")
if 'shaders' not in block: if 'shaders' not in block:
raise Exception("Expected 'shaders' key with shader name list") raise Exception("Expected 'shaders' key with shader name list")
shader_file = os.path.join(shader_folder, block['file']) shader_file = os.path.join(shader_folder, block['file'])
deps.add(shader_file) deps.add(shader_file)
shader_model = block['type'] shader_model = block['type']
for shader_name in block['shaders']: for shader_name in block['shaders']:
new_deps = run_fxc( new_deps = run_fxc(
shader_model = shader_model, shader_model=shader_model,
shader_file = shader_file, shader_file=shader_file,
shader_name = shader_name, shader_name=shader_name,
output_fp = output_fp) output_fp=output_fp)
deps |= new_deps deps |= new_deps
output_fp.write(FOOTER)
return deps
output_fp.write(FOOTER)
return deps
def run_fxc(shader_model, def run_fxc(shader_model,
shader_file, shader_file,
shader_name, shader_name,
output_fp): output_fp):
fxc_location = buildconfig.substs['FXC'] fxc_location = buildconfig.substs['FXC']
argv = [ argv = [
fxc_location, fxc_location,
'-nologo', '-nologo',
'-T{0}'.format(shader_model), '-T{0}'.format(shader_model),
shader_file, shader_file,
'-E{0}'.format(shader_name), '-E{0}'.format(shader_name),
'-Vn{0}'.format(shader_name), '-Vn{0}'.format(shader_name),
'-Vi', '-Vi',
] ]
if 'Linux' in buildconfig.substs['HOST_OS_ARCH']: if 'Linux' in buildconfig.substs['HOST_OS_ARCH']:
argv.insert(0, buildconfig.substs['WINE']) argv.insert(0, buildconfig.substs['WINE'])
if shader_model.startswith('vs_'): if shader_model.startswith('vs_'):
argv += ['-DVERTEX_SHADER'] argv += ['-DVERTEX_SHADER']
elif shader_model.startswith('ps_'): elif shader_model.startswith('ps_'):
argv += ['-DPIXEL_SHADER'] argv += ['-DPIXEL_SHADER']
deps = None deps = None
with ScopedTempFilename() as temp_filename: with ScopedTempFilename() as temp_filename:
argv += ['-Fh{0}'.format(temp_filename)] argv += ['-Fh{0}'.format(temp_filename)]
sys.stdout.write('{0}\n'.format(' '.join(argv))) sys.stdout.write('{0}\n'.format(' '.join(argv)))
proc_stdout = subprocess.check_output(argv) proc_stdout = subprocess.check_output(argv)
proc_stdout = decode_console_text(sys.stdout, proc_stdout) proc_stdout = decode_console_text(sys.stdout, proc_stdout)
deps = find_dependencies(proc_stdout) deps = find_dependencies(proc_stdout)
assert 'fxc2' in fxc_location or len(deps) > 0 assert 'fxc2' in fxc_location or len(deps) > 0
with open(temp_filename, 'r') as temp_fp: with open(temp_filename, 'r') as temp_fp:
output_fp.write(temp_fp.read()) 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): def find_dependencies(fxc_output):
# Dependencies look like this: # Dependencies look like this:
# Resolved to [<path>] # Resolved to [<path>]
# #
# Microsoft likes to change output strings based on the user's language, so # 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 # instead of pattern matching on that string, we take everything in between
# brackets. We filter out potentially bogus strings later. # brackets. We filter out potentially bogus strings later.
deps = set() deps = set()
for line in fxc_output.split('\n'): for line in fxc_output.split('\n'):
m = re.search(r"\[([^\]]+)\]", line) m = re.search(r"\[([^\]]+)\]", line)
if m is None: if m is None:
continue continue
dep_path = m.group(1) dep_path = m.group(1)
dep_path = os.path.normpath(dep_path) dep_path = os.path.normpath(dep_path)
if os.path.isfile(dep_path): if os.path.isfile(dep_path):
deps.add(dep_path) deps.add(dep_path)
return deps return deps
# Python reads the raw bytes from stdout, so we need to try our best to # Python reads the raw bytes from stdout, so we need to try our best to
# capture that as a valid Python string. # capture that as a valid Python string.
def decode_console_text(pipe, text): def decode_console_text(pipe, text):
try: try:
if pipe.encoding: if pipe.encoding:
return text.decode(pipe.encoding, 'replace') return text.decode(pipe.encoding, 'replace')
except: except Exception:
pass pass
try: try:
return text.decode(locale.getpreferredencoding(), 'replace') return text.decode(locale.getpreferredencoding(), 'replace')
except: except Exception:
return text.decode('utf8', 'replace') return text.decode('utf8', 'replace')
# Allocate a temporary file name and delete it when done. We need an extra # Allocate a temporary file name and delete it when done. We need an extra
# wrapper for this since TemporaryNamedFile holds the file open. # wrapper for this since TemporaryNamedFile holds the file open.
class ScopedTempFilename(object): class ScopedTempFilename(object):
def __init__(self): def __init__(self):
self.name = None self.name = None
def __enter__(self):
with tempfile.NamedTemporaryFile(delete = False) as tmp: def __enter__(self):
self.name = tmp.name with tempfile.NamedTemporaryFile(delete=False) as tmp:
return self.name self.name = tmp.name
def __exit__(self, type, value, traceback): return self.name
if not self.name:
return def __exit__(self, type, value, traceback):
try: if not self.name:
os.unlink(self.name) return
except: try:
pass os.unlink(self.name)
except Exception:
pass
if __name__ == '__main__': if __name__ == '__main__':
shell_main() shell_main()

View File

@ -862,6 +862,17 @@ FilterNodeFromPrimitiveDescription(const FilterPrimitiveDescription& aDescriptio
return lastFilter.forget(); 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: case PrimitiveType::ConvolveMatrix:
{ {
RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::CONVOLVE_MATRIX); RefPtr<FilterNode> filter = aDT->CreateFilter(FilterType::CONVOLVE_MATRIX);
@ -1394,6 +1405,7 @@ ResultChangeRegionForPrimitive(const FilterPrimitiveDescription& aDescription,
case PrimitiveType::Blend: case PrimitiveType::Blend:
case PrimitiveType::Composite: case PrimitiveType::Composite:
case PrimitiveType::Merge: case PrimitiveType::Merge:
case PrimitiveType::Opacity:
return UnionOfRegions(aInputChangeRegions); return UnionOfRegions(aInputChangeRegions);
case PrimitiveType::ColorMatrix: case PrimitiveType::ColorMatrix:
@ -1614,6 +1626,14 @@ FilterSupport::PostFilterExtentsForPrimitive(const FilterPrimitiveDescription& a
return aInputExtents[0]; return aInputExtents[0];
} }
case PrimitiveType::Opacity:
{
if (atts.GetFloat(eOpacityOpacity) == 0.0f) {
return IntRect();
}
return ResultChangeRegionForPrimitive(aDescription, aInputExtents);
}
case PrimitiveType::Turbulence: case PrimitiveType::Turbulence:
case PrimitiveType::Image: case PrimitiveType::Image:
case PrimitiveType::DiffuseLighting: case PrimitiveType::DiffuseLighting:
@ -1692,6 +1712,7 @@ SourceNeededRegionForPrimitive(const FilterPrimitiveDescription& aDescription,
case PrimitiveType::ColorMatrix: case PrimitiveType::ColorMatrix:
case PrimitiveType::ComponentTransfer: case PrimitiveType::ComponentTransfer:
case PrimitiveType::ToAlpha: case PrimitiveType::ToAlpha:
case PrimitiveType::Opacity:
return aResultNeededRegion; return aResultNeededRegion;
case PrimitiveType::Morphology: case PrimitiveType::Morphology:

View File

@ -95,6 +95,7 @@ enum AttributeName {
eColorMatrixValues, eColorMatrixValues,
eFloodColor, eFloodColor,
eTileSourceRect, eTileSourceRect,
eOpacityOpacity,
eComponentTransferFunctionR, eComponentTransferFunctionR,
eComponentTransferFunctionG, eComponentTransferFunctionG,
eComponentTransferFunctionB, eComponentTransferFunctionB,
@ -277,6 +278,7 @@ enum class PrimitiveType {
Flood, Flood,
Tile, Tile,
ComponentTransfer, ComponentTransfer,
Opacity,
ConvolveMatrix, ConvolveMatrix,
Offset, Offset,
DisplacementMap, DisplacementMap,

View File

@ -17,7 +17,7 @@ while True:
line = f.readline() line = f.readline()
if not line: if not line:
break break
if not 'CJK COMPATIBILITY IDEOGRAPH-' in line: if 'CJK COMPATIBILITY IDEOGRAPH-' not in line:
continue continue
m = r.search(line) m = r.search(line)
@ -25,7 +25,7 @@ while True:
vs = int(m.group(2), 16) vs = int(m.group(2), 16)
compat = int(m.group(3), 16) compat = int(m.group(3), 16)
if not vs in vsdict: if vs not in vsdict:
vsdict[vs] = {} vsdict[vs] = {}
vsdict[vs][unified] = compat vsdict[vs][unified] = compat

View File

@ -15,7 +15,6 @@
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "nsIPresShell.h" #include "nsIPresShell.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "NullPrincipal.h"
#include "nsIInputStream.h" #include "nsIInputStream.h"
#include "nsStringStream.h" #include "nsStringStream.h"
#include "nsStreamUtils.h" #include "nsStreamUtils.h"
@ -25,6 +24,7 @@
#include "mozilla/dom/FontTableURIProtocolHandler.h" #include "mozilla/dom/FontTableURIProtocolHandler.h"
#include "mozilla/dom/SVGDocument.h" #include "mozilla/dom/SVGDocument.h"
#include "mozilla/LoadInfo.h" #include "mozilla/LoadInfo.h"
#include "mozilla/NullPrincipal.h"
#include "nsSVGUtils.h" #include "nsSVGUtils.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "gfxFont.h" #include "gfxFont.h"

View File

@ -5,6 +5,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/NullPrincipal.h"
#include "nsMimeTypes.h" #include "nsMimeTypes.h"
#include "nsIURL.h" #include "nsIURL.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
@ -13,7 +14,6 @@
#include "nsIStringStream.h" #include "nsIStringStream.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "NullPrincipal.h"
NS_IMPL_ISUPPORTS(nsIconChannel, NS_IMPL_ISUPPORTS(nsIconChannel,
nsIRequest, nsIRequest,

View File

@ -10,6 +10,7 @@
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "mozilla/EndianUtils.h" #include "mozilla/EndianUtils.h"
#include "mozilla/NullPrincipal.h"
#include <algorithm> #include <algorithm>
#include <gio/gio.h> #include <gio/gio.h>
@ -25,7 +26,6 @@
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "nsIStringStream.h" #include "nsIStringStream.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "NullPrincipal.h"
#include "nsIURL.h" #include "nsIURL.h"
#include "prlink.h" #include "prlink.h"
#include "gfxPlatform.h" #include "gfxPlatform.h"
@ -106,7 +106,8 @@ moz_gdk_pixbuf_to_channel(GdkPixbuf* aPixbuf, nsIURI* aURI,
// nsIconProtocolHandler::NewChannel2 will provide the correct loadInfo for // nsIconProtocolHandler::NewChannel2 will provide the correct loadInfo for
// this iconChannel. Use the most restrictive security settings for the // this iconChannel. Use the most restrictive security settings for the
// temporary loadInfo to make sure the channel can not be openend. // 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, return NS_NewInputStreamChannel(aChannel,
aURI, aURI,
stream.forget(), stream.forget(),

View File

@ -9,11 +9,11 @@
#include "ImageLogging.h" #include "ImageLogging.h"
#include "imgLoader.h" #include "imgLoader.h"
#include "NullPrincipal.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#include "mozilla/Move.h" #include "mozilla/Move.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/ChaosMode.h" #include "mozilla/ChaosMode.h"
#include "mozilla/LoadInfo.h" #include "mozilla/LoadInfo.h"

View File

@ -84,11 +84,11 @@ def try_run(name, command, cwd=None, **kwargs):
try: try:
with tempfile.NamedTemporaryFile(prefix=name, delete=False) as f: with tempfile.NamedTemporaryFile(prefix=name, delete=False) as f:
subprocess.check_call(command, cwd=cwd, stdout=f, subprocess.check_call(command, cwd=cwd, stdout=f,
stderr=subprocess.STDOUT, **kwargs) stderr=subprocess.STDOUT, **kwargs)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
print('''Error running "{}" in directory {} print('''Error running "{}" in directory {}
See output in {}'''.format(' '.join(command), cwd, f.name), See output in {}'''.format(' '.join(command), cwd, f.name),
file=sys.stderr) file=sys.stderr)
return False return False
else: else:
os.unlink(f.name) os.unlink(f.name)
@ -151,7 +151,7 @@ def update_data_file(topsrcdir):
shutil.copy(new_data_file, tree_data_path) shutil.copy(new_data_file, tree_data_path)
try: try:
shutil.rmtree(objdir) shutil.rmtree(objdir)
except: except Exception:
print('Warning: failed to remove %s' % objdir, file=sys.stderr) print('Warning: failed to remove %s' % objdir, file=sys.stderr)
return True return True

View File

@ -2,26 +2,24 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
import sys
def main(header, propFile): def main(header, propFile):
mappings = {} mappings = {}
with open(propFile, 'r') as f: with open(propFile, 'r') as f:
for line in f: for line in f:
line = line.strip() line = line.strip()
if not line.startswith('#'): if not line.startswith('#'):
parts = line.split("=", 1) parts = line.split("=", 1)
if len(parts) == 2 and len(parts[0]) > 0: if len(parts) == 2 and len(parts[0]) > 0:
mappings[parts[0].strip()] = parts[1].strip() mappings[parts[0].strip()] = parts[1].strip()
keys = mappings.keys()
keys.sort()
header.write("// This is a generated file. Please do not edit.\n") keys = mappings.keys()
header.write("// Please edit the corresponding .properties file instead.\n") keys.sort()
entries = ['{ "%s", "%s", %d }' header.write("// This is a generated file. Please do not edit.\n")
% (key, mappings[key], len(mappings[key])) for key in keys] header.write("// Please edit the corresponding .properties file instead.\n")
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')

View File

@ -9,6 +9,8 @@
#include "MainThreadUtils.h" #include "MainThreadUtils.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/BasePrincipal.h" #include "mozilla/BasePrincipal.h"
#include "mozilla/ContentPrincipal.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h" #include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "mozilla/ipc/URIUtils.h" #include "mozilla/ipc/URIUtils.h"
#include "mozilla/net/NeckoChannelParams.h" #include "mozilla/net/NeckoChannelParams.h"
@ -17,8 +19,6 @@
#include "nsIURI.h" #include "nsIURI.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "mozilla/LoadInfo.h" #include "mozilla/LoadInfo.h"
#include "ContentPrincipal.h"
#include "NullPrincipal.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsString.h" #include "nsString.h"
#include "nsTArray.h" #include "nsTArray.h"

View File

@ -11,12 +11,12 @@
#include "mozilla/ArrayUtils.h" #include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/dom/BlobURL.h" #include "mozilla/dom/BlobURL.h"
#include "mozilla/NullPrincipalURI.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "nsDebug.h" #include "nsDebug.h"
#include "nsID.h" #include "nsID.h"
#include "nsJARURI.h" #include "nsJARURI.h"
#include "nsIIconURI.h" #include "nsIIconURI.h"
#include "NullPrincipalURI.h"
#include "nsJSProtocolHandler.h" #include "nsJSProtocolHandler.h"
#include "nsNetCID.h" #include "nsNetCID.h"
#include "nsSimpleNestedURI.h" #include "nsSimpleNestedURI.h"

5
ipc/ipdl/.flake8 Normal file
View File

@ -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

View File

@ -1,22 +1,24 @@
# This Source Code Form is subject to the terms of the Mozilla Public # 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 # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
import optparse
import optparse, os, re, sys import os
import sys
from cStringIO import StringIO from cStringIO import StringIO
import mozpack.path as mozpath
from ConfigParser import RawConfigParser from ConfigParser import RawConfigParser
import ipdl import ipdl
def log(minv, fmt, *args): def log(minv, fmt, *args):
if _verbosity >= minv: if _verbosity >= minv:
print fmt % args print(fmt % args)
# process command line # process command line
op = optparse.OptionParser(usage='ipdl.py [options] IPDLfiles...') 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', action='append',
help='Additional directory to search for included protocol specifications') help='Additional directory to search for included protocol specifications')
op.add_option('-s', '--sync-msg-list', dest='syncMsgList', default='sync-messages.ini', op.add_option('-s', '--sync-msg-list', dest='syncMsgList', default='sync-messages.ini',
@ -44,7 +46,7 @@ syncMsgList = options.syncMsgList
msgMetadata = options.msgMetadata msgMetadata = options.msgMetadata
headersdir = options.headersdir headersdir = options.headersdir
cppdir = options.cppdir 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): if not len(files):
op.error("No IPDL files specified") op.error("No IPDL files specified")
@ -59,11 +61,13 @@ allmessages = {}
allmessageprognames = [] allmessageprognames = []
allprotocols = [] allprotocols = []
def normalizedFilename(f): def normalizedFilename(f):
if f == '-': if f == '-':
return '<stdin>' return '<stdin>'
return f return f
log(2, 'Reading sync message list') log(2, 'Reading sync message list')
parser = RawConfigParser() parser = RawConfigParser()
parser.readfp(open(options.syncMsgList)) parser.readfp(open(options.syncMsgList))
@ -104,7 +108,7 @@ for f in files:
sys.exit(1) sys.exit(1)
if not ipdl.checkSyncMessage(ast, syncMsgList): 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) sys.exit(1)
if not ipdl.checkFixedSyncMessages(parser): if not ipdl.checkFixedSyncMessages(parser):

View File

@ -2,10 +2,11 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
__all__ = [ 'gencxx', 'genipdl', 'parse', 'typecheck', 'writeifmodified', __all__ = ['gencxx', 'genipdl', 'parse', 'typecheck', 'writeifmodified',
'checkSyncMessage', 'checkFixedSyncMessages' ] 'checkSyncMessage', 'checkFixedSyncMessages']
import os, sys import os
import sys
from cStringIO import StringIO from cStringIO import StringIO
from ipdl.cgen import IPDLCodeGen from ipdl.cgen import IPDLCodeGen
@ -17,7 +18,7 @@ from ipdl.checker import checkSyncMessage, checkFixedSyncMessages
from ipdl.cxx.cgen import CxxCodeGen 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| '''Return an IPDL AST if parsing was successful. Print errors to |errout|
if it is not.''' if it is not.'''
# The file type and name are later enforced by the type checker. # The file type and name are later enforced by the type checker.
@ -35,6 +36,7 @@ def parse(specstring, filename='/stdin', includedirs=[ ], errout=sys.stderr):
print >>errout, p print >>errout, p
return None return None
def typecheck(ast, errout=sys.stderr): def typecheck(ast, errout=sys.stderr):
'''Return True iff |ast| is well typed. Print errors to |errout| if '''Return True iff |ast| is well typed. Print errors to |errout| if
it is not.''' it is not.'''
@ -51,11 +53,12 @@ def gencxx(ipdlfilename, ast, outheadersdir, outcppdir, segmentcapacitydict):
outheadersdir, outheadersdir,
*([ns.name for ns in ast.namespaces] + [hdr.name])) *([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 ] def resolveCpp(cpp):
+ [ resolveCpp(cpp) for cpp in cpps ]): 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() tempfile = StringIO()
CxxCodeGen(tempfile).cgen(ast) CxxCodeGen(tempfile).cgen(ast)
writeifmodified(tempfile.getvalue(), filename) writeifmodified(tempfile.getvalue(), filename)
@ -68,6 +71,7 @@ def genipdl(ast, outdir):
def genmsgenum(ast): def genmsgenum(ast):
return msgenums(ast.protocol, pretty=True) return msgenums(ast.protocol, pretty=True)
def writeifmodified(contents, file): def writeifmodified(contents, file):
dir = os.path.dirname(file) dir = os.path.dirname(file)
os.path.exists(dir) or os.makedirs(dir) os.path.exists(dir) or os.makedirs(dir)

View File

@ -2,8 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
import sys
NOT_NESTED = 1 NOT_NESTED = 1
INSIDE_SYNC_NESTED = 2 INSIDE_SYNC_NESTED = 2
INSIDE_CPOW_NESTED = 3 INSIDE_CPOW_NESTED = 3
@ -12,10 +10,11 @@ NORMAL_PRIORITY = 1
INPUT_PRIORITY = 2 INPUT_PRIORITY = 2
HIGH_PRIORITY = 3 HIGH_PRIORITY = 3
class Visitor: class Visitor:
def defaultVisit(self, node): def defaultVisit(self, node):
raise Exception, "INTERNAL ERROR: no visitor for node type `%s'"% ( raise Exception("INTERNAL ERROR: no visitor for node type `%s'" %
node.__class__.__name__) (node.__class__.__name__))
def visitTranslationUnit(self, tu): def visitTranslationUnit(self, tu):
for cxxInc in tu.cxxIncludes: for cxxInc in tu.cxxIncludes:
@ -31,7 +30,6 @@ class Visitor:
if tu.protocol: if tu.protocol:
tu.protocol.accept(self) tu.protocol.accept(self)
def visitCxxInclude(self, inc): def visitCxxInclude(self, inc):
pass pass
@ -88,27 +86,33 @@ class Visitor:
def visitDecl(self, d): def visitDecl(self, d):
pass pass
class Loc: class Loc:
def __init__(self, filename='<??>', lineno=0): def __init__(self, filename='<??>', lineno=0):
assert filename assert filename
self.filename = filename self.filename = filename
self.lineno = lineno self.lineno = lineno
def __repr__(self): def __repr__(self):
return '%r:%r'% (self.filename, self.lineno) return '%r:%r' % (self.filename, self.lineno)
def __str__(self): def __str__(self):
return '%s:%s'% (self.filename, self.lineno) return '%s:%s' % (self.filename, self.lineno)
Loc.NONE = Loc(filename='<??>', lineno=0) Loc.NONE = Loc(filename='<??>', lineno=0)
class _struct: class _struct:
pass pass
class Node: class Node:
def __init__(self, loc=Loc.NONE): def __init__(self, loc=Loc.NONE):
self.loc = loc self.loc = loc
def accept(self, visitor): def accept(self, visitor):
visit = getattr(visitor, 'visit'+ self.__class__.__name__, None) visit = getattr(visitor, 'visit' + self.__class__.__name__, None)
if visit is None: if visit is None:
return getattr(visitor, 'defaultVisit')(self) return getattr(visitor, 'defaultVisit')(self)
return visit(self) return visit(self)
@ -122,40 +126,47 @@ class NamespacedNode(Node):
def __init__(self, loc=Loc.NONE, name=None): def __init__(self, loc=Loc.NONE, name=None):
Node.__init__(self, loc) Node.__init__(self, loc)
self.name = name self.name = name
self.namespaces = [ ] self.namespaces = []
def addOuterNamespace(self, namespace): def addOuterNamespace(self, namespace):
self.namespaces.insert(0, namespace) self.namespaces.insert(0, namespace)
def qname(self): def qname(self):
return QualifiedId(self.loc, self.name, return QualifiedId(self.loc, self.name,
[ ns.name for ns in self.namespaces ]) [ns.name for ns in self.namespaces])
class TranslationUnit(NamespacedNode): class TranslationUnit(NamespacedNode):
def __init__(self, type, name): def __init__(self, type, name):
NamespacedNode.__init__(self, name=name) NamespacedNode.__init__(self, name=name)
self.filetype = type self.filetype = type
self.filename = None self.filename = None
self.cxxIncludes = [ ] self.cxxIncludes = []
self.includes = [ ] self.includes = []
self.builtinUsing = [ ] self.builtinUsing = []
self.using = [ ] self.using = []
self.structsAndUnions = [ ] self.structsAndUnions = []
self.protocol = None self.protocol = None
def addCxxInclude(self, cxxInclude): self.cxxIncludes.append(cxxInclude) def addCxxInclude(self, cxxInclude): self.cxxIncludes.append(cxxInclude)
def addInclude(self, inc): self.includes.append(inc) def addInclude(self, inc): self.includes.append(inc)
def addStructDecl(self, struct): self.structsAndUnions.append(struct) def addStructDecl(self, struct): self.structsAndUnions.append(struct)
def addUnionDecl(self, union): self.structsAndUnions.append(union) def addUnionDecl(self, union): self.structsAndUnions.append(union)
def addUsingStmt(self, using): self.using.append(using) def addUsingStmt(self, using): self.using.append(using)
def setProtocol(self, protocol): self.protocol = protocol def setProtocol(self, protocol): self.protocol = protocol
class CxxInclude(Node): class CxxInclude(Node):
def __init__(self, loc, cxxFile): def __init__(self, loc, cxxFile):
Node.__init__(self, loc) Node.__init__(self, loc)
self.file = cxxFile self.file = cxxFile
class Include(Node): class Include(Node):
def __init__(self, loc, type, name): def __init__(self, loc, type, name):
Node.__init__(self, loc) Node.__init__(self, loc)
@ -164,43 +175,61 @@ class Include(Node):
suffix += 'h' suffix += 'h'
self.file = "%s.%s" % (name, suffix) self.file = "%s.%s" % (name, suffix)
class UsingStmt(Node): class UsingStmt(Node):
def __init__(self, loc, cxxTypeSpec, cxxHeader=None, kind=None, refcounted=False): def __init__(self, loc, cxxTypeSpec, cxxHeader=None, kind=None, refcounted=False):
Node.__init__(self, loc) Node.__init__(self, loc)
assert not isinstance(cxxTypeSpec, str) 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' assert kind is None or kind == 'class' or kind == 'struct'
self.type = cxxTypeSpec self.type = cxxTypeSpec
self.header = cxxHeader self.header = cxxHeader
self.kind = kind self.kind = kind
self.refcounted = refcounted self.refcounted = refcounted
def canBeForwardDeclared(self): def canBeForwardDeclared(self):
return self.isClass() or self.isStruct() return self.isClass() or self.isStruct()
def isClass(self): def isClass(self):
return self.kind == 'class' return self.kind == 'class'
def isStruct(self): def isStruct(self):
return self.kind == 'struct' return self.kind == 'struct'
def isRefcounted(self): def isRefcounted(self):
return self.refcounted return self.refcounted
# "singletons" # "singletons"
class PrettyPrinted: class PrettyPrinted:
@classmethod @classmethod
def __hash__(cls): return hash(cls.pretty) def __hash__(cls): return hash(cls.pretty)
@classmethod @classmethod
def __str__(cls): return cls.pretty def __str__(cls): return cls.pretty
class ASYNC(PrettyPrinted): class ASYNC(PrettyPrinted):
pretty = 'async' pretty = 'async'
class INTR(PrettyPrinted): class INTR(PrettyPrinted):
pretty = 'intr' pretty = 'intr'
class SYNC(PrettyPrinted): class SYNC(PrettyPrinted):
pretty = 'sync' pretty = 'sync'
class INOUT(PrettyPrinted): class INOUT(PrettyPrinted):
pretty = 'inout' pretty = 'inout'
class IN(PrettyPrinted): class IN(PrettyPrinted):
pretty = 'in' pretty = 'in'
class OUT(PrettyPrinted): class OUT(PrettyPrinted):
pretty = 'out' pretty = 'out'
@ -210,14 +239,16 @@ class Namespace(Node):
Node.__init__(self, loc) Node.__init__(self, loc)
self.name = namespace self.name = namespace
class Protocol(NamespacedNode): class Protocol(NamespacedNode):
def __init__(self, loc): def __init__(self, loc):
NamespacedNode.__init__(self, loc) NamespacedNode.__init__(self, loc)
self.sendSemantics = ASYNC self.sendSemantics = ASYNC
self.nested = NOT_NESTED self.nested = NOT_NESTED
self.managers = [ ] self.managers = []
self.managesStmts = [ ] self.managesStmts = []
self.messageDecls = [ ] self.messageDecls = []
class StructField(Node): class StructField(Node):
def __init__(self, loc, type, name): def __init__(self, loc, type, name):
@ -225,26 +256,31 @@ class StructField(Node):
self.typespec = type self.typespec = type
self.name = name self.name = name
class StructDecl(NamespacedNode): class StructDecl(NamespacedNode):
def __init__(self, loc, name, fields): def __init__(self, loc, name, fields):
NamespacedNode.__init__(self, loc, name) NamespacedNode.__init__(self, loc, name)
self.fields = fields self.fields = fields
class UnionDecl(NamespacedNode): class UnionDecl(NamespacedNode):
def __init__(self, loc, name, components): def __init__(self, loc, name, components):
NamespacedNode.__init__(self, loc, name) NamespacedNode.__init__(self, loc, name)
self.components = components self.components = components
class Manager(Node): class Manager(Node):
def __init__(self, loc, managerName): def __init__(self, loc, managerName):
Node.__init__(self, loc) Node.__init__(self, loc)
self.name = managerName self.name = managerName
class ManagesStmt(Node): class ManagesStmt(Node):
def __init__(self, loc, managedName): def __init__(self, loc, managedName):
Node.__init__(self, loc) Node.__init__(self, loc)
self.name = managedName self.name = managedName
class MessageDecl(Node): class MessageDecl(Node):
def __init__(self, loc): def __init__(self, loc):
Node.__init__(self, loc) Node.__init__(self, loc)
@ -253,8 +289,8 @@ class MessageDecl(Node):
self.nested = NOT_NESTED self.nested = NOT_NESTED
self.prio = NORMAL_PRIORITY self.prio = NORMAL_PRIORITY
self.direction = None self.direction = None
self.inParams = [ ] self.inParams = []
self.outParams = [ ] self.outParams = []
self.compress = '' self.compress = ''
self.verify = '' self.verify = ''
@ -271,7 +307,8 @@ class MessageDecl(Node):
elif modifier == 'verify': elif modifier == 'verify':
self.verify = modifier self.verify = modifier
elif modifier != '': elif modifier != '':
raise Exception, "Unexpected message modifier `%s'"% modifier raise Exception("Unexpected message modifier `%s'" % modifier)
class Param(Node): class Param(Node):
def __init__(self, loc, typespec, name): def __init__(self, loc, typespec, name):
@ -279,21 +316,25 @@ class Param(Node):
self.name = name self.name = name
self.typespec = typespec self.typespec = typespec
class TypeSpec(Node): class TypeSpec(Node):
def __init__(self, loc, spec): def __init__(self, loc, spec):
Node.__init__(self, loc) Node.__init__(self, loc)
self.spec = spec # QualifiedId self.spec = spec # QualifiedId
self.array = 0 # bool self.array = 0 # bool
self.nullable = 0 # bool self.nullable = 0 # bool
def basename(self): def basename(self):
return self.spec.baseid return self.spec.baseid
def __str__(self): return str(self.spec) def __str__(self): return str(self.spec)
class QualifiedId: # FIXME inherit from node? class QualifiedId: # FIXME inherit from node?
def __init__(self, loc, baseid, quals=[ ]): def __init__(self, loc, baseid, quals=[]):
assert isinstance(baseid, str) assert isinstance(baseid, str)
for qual in quals: assert isinstance(qual, str) for qual in quals:
assert isinstance(qual, str)
self.loc = loc self.loc = loc
self.baseid = baseid self.baseid = baseid
@ -306,9 +347,11 @@ class QualifiedId: # FIXME inherit from node?
def __str__(self): def __str__(self):
if 0 == len(self.quals): if 0 == len(self.quals):
return self.baseid return self.baseid
return '::'.join(self.quals) +'::'+ self.baseid return '::'.join(self.quals) + '::' + self.baseid
# added by type checking passes # added by type checking passes
class Decl(Node): class Decl(Node):
def __init__(self, loc): def __init__(self, loc):
Node.__init__(self, loc) Node.__init__(self, loc)

View File

@ -2,10 +2,11 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
import os, sys import sys
from ipdl.ast import Visitor from ipdl.ast import Visitor
class CodePrinter: class CodePrinter:
def __init__(self, outf=sys.stdout, indentCols=4): def __init__(self, outf=sys.stdout, indentCols=4):
self.outf = outf self.outf = outf
@ -16,19 +17,20 @@ class CodePrinter:
self.outf.write(str) self.outf.write(str)
def printdent(self, str=''): def printdent(self, str=''):
self.write((' '* self.col) + str) self.write((' ' * self.col) + str)
def println(self, str=''): def println(self, str=''):
self.write(str +'\n') self.write(str + '\n')
def printdentln(self, str): def printdentln(self, str):
self.write((' '* self.col) + str +'\n') self.write((' ' * self.col) + str + '\n')
def indent(self): self.col += self.indentCols def indent(self): self.col += self.indentCols
def dedent(self): self.col -= self.indentCols def dedent(self): self.col -= self.indentCols
##----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
class IPDLCodeGen(CodePrinter, Visitor): class IPDLCodeGen(CodePrinter, Visitor):
'''Spits back out equivalent IPDL to the code that generated this. '''Spits back out equivalent IPDL to the code that generated this.
Also known as pretty-printing.''' Also known as pretty-printing.'''
@ -40,13 +42,13 @@ Also known as pretty-printing.'''
def visitTranslationUnit(self, tu): def visitTranslationUnit(self, tu):
self.printed.add(tu.filename) self.printed.add(tu.filename)
self.println('//\n// Automatically generated by ipdlc\n//') self.println('//\n// Automatically generated by ipdlc\n//')
CodeGen.visitTranslationUnit(self, tu) CodeGen.visitTranslationUnit(self, tu) # NOQA: F821
def visitCxxInclude(self, inc): def visitCxxInclude(self, inc):
self.println('include "'+ inc.file +'";') self.println('include "' + inc.file + '";')
def visitProtocolInclude(self, inc): def visitProtocolInclude(self, inc):
self.println('include protocol "'+ inc.file +'";') self.println('include protocol "' + inc.file + '";')
if inc.tu.filename not in self.printed: if inc.tu.filename not in self.printed:
self.println('/* Included file:') self.println('/* Included file:')
IPDLCodeGen(outf=self.outf, indentCols=self.indentCols, IPDLCodeGen(outf=self.outf, indentCols=self.indentCols,
@ -56,33 +58,37 @@ Also known as pretty-printing.'''
def visitProtocol(self, p): def visitProtocol(self, p):
self.println() 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() self.indent()
for mgs in p.managesStmts: for mgs in p.managesStmts:
mgs.accept(self) 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.println()
self.dedent() self.dedent()
self.println('}') self.println('}')
self.write('}\n'* len(p.namespaces)) self.write('}\n' * len(p.namespaces))
def visitManagerStmt(self, mgr): def visitManagerStmt(self, mgr):
self.printdentln('manager '+ mgr.name +';') self.printdentln('manager ' + mgr.name + ';')
def visitManagesStmt(self, mgs): def visitManagesStmt(self, mgs):
self.printdentln('manages '+ mgs.name +';') self.printdentln('manages ' + mgs.name + ';')
def visitMessageDecl(self, msg): 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): for i, inp in enumerate(msg.inParams):
inp.accept(self) inp.accept(self)
if i != (len(msg.inParams) - 1): self.write(', ') if i != (len(msg.inParams) - 1):
self.write(', ')
self.write(')') self.write(')')
if 0 == len(msg.outParams): if 0 == len(msg.outParams):
self.println(';') self.println(';')
@ -93,6 +99,7 @@ Also known as pretty-printing.'''
self.printdent('returns (') self.printdent('returns (')
for i, outp in enumerate(msg.outParams): for i, outp in enumerate(msg.outParams):
outp.accept(self) outp.accept(self)
if i != (len(msg.outParams) - 1): self.write(', ') if i != (len(msg.outParams) - 1):
self.write(', ')
self.println(');') self.println(');')
self.dedent() self.dedent()

Some files were not shown because too many files have changed in this diff Show More