MozReview-Commit-ID: LpxvieHR7VH
This commit is contained in:
Wes Kocher 2017-07-05 17:10:43 -07:00
Родитель b2b6270f16 a2ac9a50b5
Коммит 288405ee34
142 изменённых файлов: 3898 добавлений и 18864 удалений

Просмотреть файл

@ -110,5 +110,6 @@ static const AtkStateMap gAtkStateMap[] = { // Cross Platfor
{ ATK_STATE_SENSITIVE, kMapDirectly }, // states::SENSITIVE = 1 << 45
{ ATK_STATE_EXPANDABLE, kMapDirectly }, // states::EXPANDABLE = 1 << 46
{ kNone, kMapDirectly }, // states::PINNED = 1 << 47
{ kNone, kNoSuchState }, // = 1 << 48
{ ATK_STATE_ACTIVE, kMapDirectly }, // states::CURRENT = 1 << 48
{ kNone, kNoSuchState }, // = 1 << 49
};

Просмотреть файл

@ -597,6 +597,16 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
kGenericAccType,
kNoReqStates
},
{ // figure
&nsGkAtoms::figure,
roles::FIGURE,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // form
&nsGkAtoms::form,
roles::FORM,
@ -902,12 +912,12 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
},
{ // region
&nsGkAtoms::region,
roles::PANE,
roles::REGION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
eLandmark,
kNoReqStates
},
{ // row
@ -1202,6 +1212,7 @@ nsRoleMapEntry aria::gEmptyRoleMap = {
*/
static const EStateRule sWAIUnivStateMap[] = {
eARIABusy,
eARIACurrent,
eARIADisabled,
eARIAExpanded, // Currently under spec review but precedent exists
eARIAHasPopup, // Note this is technically a "property"

Просмотреть файл

@ -145,6 +145,16 @@ aria::MapToState(EStateRule aRule, dom::Element* aElement, uint64_t* aState)
return true;
}
case eARIACurrent:
{
static const TokenTypeData data(
nsGkAtoms::aria_current, eBoolType,
0, states::CURRENT);
MapTokenType(aElement, aState, data);
return true;
}
case eARIADisabled:
{
static const TokenTypeData data(
@ -354,10 +364,12 @@ MapTokenType(dom::Element* aElement, uint64_t* aState,
const TokenTypeData& aData)
{
if (nsAccUtils::HasDefinedARIAToken(aElement, aData.mAttrName)) {
if ((aData.mType & eMixedType) &&
aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
if (aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName,
nsGkAtoms::mixed, eCaseMatters)) {
if (aData.mType & eMixedType)
*aState |= aData.mPermanentState | states::MIXED;
else // unsupported use of 'mixed' is an authoring error
*aState |= aData.mPermanentState | aData.mFalseState;
return;
}

Просмотреть файл

@ -29,6 +29,7 @@ enum EStateRule
eARIACheckableBool,
eARIACheckableMixed,
eARIACheckedMixed,
eARIACurrent,
eARIADisabled,
eARIAExpanded,
eARIAHasPopup,

Просмотреть файл

@ -1007,7 +1007,15 @@ enum Role {
*/
ARTICLE = 172,
LAST_ROLE = ARTICLE
/**
* A perceivable section containing content that is relevant to a specific,
* author-specified purpose and sufficiently important that users will likely
* want to be able to navigate to the section easily and to have it listed in
* a summary of the page.
*/
REGION = 173,
LAST_ROLE = REGION
};
} // namespace role

Просмотреть файл

@ -1399,3 +1399,11 @@ ROLE(ARTICLE,
ROLE_SYSTEM_DOCUMENT,
ROLE_SYSTEM_DOCUMENT,
eNoNameRule)
ROLE(REGION,
"region",
ATK_ROLE_LANDMARK,
NSAccessibilityGroupRole,
USE_ROLE_STRING,
IA2_ROLE_LANDMARK,
eNoNameRule)

Просмотреть файл

@ -277,6 +277,12 @@ namespace states {
* The object is pinned, usually indicating it is fixed in place and has permanence.
*/
const uint64_t PINNED = ((uint64_t) 0x1) << 47;
/**
* The object is the current item within a container or set of related elements.
*/
const uint64_t CURRENT = ((uint64_t) 0x1) << 48;
} // namespace states
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -1054,6 +1054,13 @@ DocAccessible::ARIAAttributeChanged(Accessible* aAccessible, nsIAtom* aAttribute
return;
}
if (aAttribute == nsGkAtoms::aria_current) {
RefPtr<AccEvent> event =
new AccStateChangeEvent(aAccessible, states::CURRENT);
FireDelayedEvent(event);
return;
}
if (aAttribute == nsGkAtoms::aria_owns) {
mNotificationController->ScheduleRelocation(aAccessible);
}

Просмотреть файл

@ -1001,4 +1001,12 @@ interface nsIAccessibleRole : nsISupports
* e.g. in syndication.
*/
const unsigned long ROLE_ARTICLE = 172;
/**
* A perceivable section containing content that is relevant to a specific,
* author-specified purpose and sufficiently important that users will likely
* want to be able to navigate to the section easily and to have it listed in
* a summary of the page.
*/
const unsigned long ROLE_REGION = 173;
};

Просмотреть файл

@ -72,5 +72,6 @@ interface nsIAccessibleStates : nsISupports
const unsigned long EXT_STATE_SENSITIVE = 0x00004000; // Same as ENABLED for now
const unsigned long EXT_STATE_EXPANDABLE = 0x00008000; // If COLLAPSED or EXPANDED
const unsigned long EXT_STATE_PINNED = 0x00010000; // Indicates object is pinned.
const unsigned long EXT_STATE_CURRENT = 0x00020000; // Indicates object is the current item in its container
};

Просмотреть файл

@ -798,7 +798,7 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
if (roleAtom == nsGkAtoms::note_)
return @"AXDocumentNote";
if (roleAtom == nsGkAtoms::region)
return @"AXDocumentRegion";
return @"AXLandmarkRegion";
if (roleAtom == nsGkAtoms::status)
return @"AXApplicationStatus";
if (roleAtom == nsGkAtoms::tabpanel)
@ -952,7 +952,6 @@ static const RoleDescrMap sRoleDescrMap[] = {
{ @"AXDocumentArticle", NS_LITERAL_STRING("article") },
{ @"AXDocumentMath", NS_LITERAL_STRING("math") },
{ @"AXDocumentNote", NS_LITERAL_STRING("note") },
{ @"AXDocumentRegion", NS_LITERAL_STRING("region") },
{ @"AXLandmarkApplication", NS_LITERAL_STRING("application") },
{ @"AXLandmarkBanner", NS_LITERAL_STRING("banner") },
{ @"AXLandmarkComplementary", NS_LITERAL_STRING("complementary") },
@ -981,6 +980,9 @@ struct RoleDescrComparator
if (mRole == roles::DOCUMENT)
return utils::LocalizedString(NS_LITERAL_STRING("htmlContent"));
if (mRole == roles::FIGURE)
return utils::LocalizedString(NS_LITERAL_STRING("figure"));
if (mRole == roles::HEADING)
return utils::LocalizedString(NS_LITERAL_STRING("heading"));

Просмотреть файл

@ -34,6 +34,7 @@
testAttrs("feed", {"xml-roles": "feed"}, true);
testAttrs("article", {"xml-roles": "article"}, true);
testAttrs("main_element", {"xml-roles": "main"}, true);
testAttrs("figure", {"xml-roles": "figure"}, true);
testAttrs("search", {"xml-roles": "searchbox"}, true);
@ -140,6 +141,12 @@
title="ARIA 1.1: Support role 'searchbox'">
Bug 1121518
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1356049"
title="Map ARIA figure role">
Bug 1356049
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -163,6 +170,7 @@
<div id="feed" role="feed">a feed</div>
<article id="article">article</article>
<main id="main_element">another main area</main>
<div id="figure" role="figure">a figure</div>
<input id="search" type="search"/>

Просмотреть файл

@ -68,6 +68,25 @@
};
}
function makeCurrent(aID, aIsCurrent, aValue)
{
this.DOMNode = getNode(aID);
this.eventSeq = [
new stateChangeChecker(EXT_STATE_CURRENT, true, aIsCurrent, this.DOMNode)
];
this.invoke = function makeCurrent_invoke()
{
this.DOMNode.setAttribute("aria-current", aValue);
};
this.getID = function makeCurrent_getID()
{
return prettyName(aID) + " aria-current changed to " + aValue;
};
}
function setAttrOfMixedType(aID, aAttr, aState, aValue)
{
this.DOMNode = getNode(aID);
@ -148,6 +167,12 @@
buildQueueForAttrOfMixedType(gQueue, "checkable", setChecked);
buildQueueForAttrOfBoolType(gQueue, "checkableBool", setChecked);
gQueue.push(new makeCurrent("current_page_1", false, "false"));
gQueue.push(new makeCurrent("current_page_2", true, "page"));
gQueue.push(new makeCurrent("current_page_2", false, "false"));
gQueue.push(new makeCurrent("current_page_3", true, "true"));
gQueue.push(new makeCurrent("current_page_3", false, ""));
gQueue.invoke(); // Will call SimpleTest.finish();
}
@ -183,6 +208,11 @@
title="Support ARIA 1.1 switch role">
Mozilla Bug 1136563
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1355921"
title="Elements with a defined, non-false value for aria-current should expose ATK_STATE_ACTIVE">
Mozilla Bug 1355921
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -204,5 +234,10 @@
<!-- aria-checked -->
<div id="checkable" role="checkbox"></div>
<div id="checkableBool" role="switch"></div>
<!-- aria-current -->
<div id="current_page_1" role="link" aria-current="page">1</div>
<div id="current_page_2" role="link" aria-current="false">2</div>
<div id="current_page_3" role="link">3</div>
</body>
</html>

Просмотреть файл

@ -100,6 +100,7 @@ const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON;
const ROLE_RADIO_GROUP = nsIAccessibleRole.ROLE_RADIO_GROUP;
const ROLE_RADIO_MENU_ITEM = nsIAccessibleRole.ROLE_RADIO_MENU_ITEM;
const ROLE_REGION = nsIAccessibleRole.ROLE_REGION;
const ROLE_RICH_OPTION = nsIAccessibleRole.ROLE_RICH_OPTION;
const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;

Просмотреть файл

@ -31,6 +31,7 @@
testRole("aria_document", ROLE_DOCUMENT);
testRole("aria_form", ROLE_FORM);
testRole("aria_feed", ROLE_GROUPING);
testRole("aria_figure", ROLE_FIGURE);
testRole("aria_grid", ROLE_TABLE);
testRole("aria_gridcell", ROLE_GRID_CELL);
testRole("aria_group", ROLE_GROUPING);
@ -53,7 +54,7 @@
testRole("aria_progressbar", ROLE_PROGRESSBAR);
testRole("aria_radio", ROLE_RADIOBUTTON);
testRole("aria_radiogroup", ROLE_RADIO_GROUP);
testRole("aria_region", ROLE_PANE);
testRole("aria_region", ROLE_REGION);
testRole("aria_row", ROLE_ROW);
testRole("aria_rowheader", ROLE_ROWHEADER);
testRole("aria_scrollbar", ROLE_SCROLLBAR);
@ -191,6 +192,11 @@
title="Support ARIA 1.1 searchbox role">
Bug 1121518
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1356049"
title="Map ARIA figure role">
Bug 1356049
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
@ -209,6 +215,7 @@
<span id="aria_document" role="document"/>
<span id="aria_form" role="form"/>
<span id="aria_feed" role="feed"/>
<span id="aria_figure" role="figure"/>
<span id="aria_grid" role="grid"/>
<span id="aria_gridcell" role="gridcell"/>
<span id="aria_group" role="group"/>

Просмотреть файл

@ -37,6 +37,7 @@ const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
const EXT_STATE_CURRENT = nsIAccessibleStates.EXT_STATE_CURRENT;
const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
const EXT_STATE_ENABLED = nsIAccessibleStates.EXT_STATE_ENABLED;

Просмотреть файл

@ -94,6 +94,7 @@
testStates("aria_mixed_checkbox", STATE_MIXED);
testStates("aria_checked_switch", STATE_CHECKED);
testStates("aria_mixed_switch", 0, 0, STATE_MIXED); // unsupported
testStates("aria_mixed_switch", 0, 0, STATE_CHECKED); // not checked due to being unsupported
// test disabled group and all its descendants to see if they are
// disabled, too. See bug 429285.
@ -266,6 +267,13 @@
testStates("aria_progressbar_valuenow", 0, 0, STATE_MIXED);
testStates("aria_progressbar_valuetext", 0, 0, STATE_MIXED);
// aria-current
testStates("current_page_1", 0, EXT_STATE_CURRENT);
testStates("page_2", 0, 0, EXT_STATE_CURRENT);
testStates("page_3", 0, 0, EXT_STATE_CURRENT);
testStates("page_4", 0, 0, EXT_STATE_CURRENT);
testStates("current_foo", 0, EXT_STATE_CURRENT);
testStates("aria_listbox", STATE_FOCUSABLE);
testStates("aria_grid", STATE_FOCUSABLE);
testStates("aria_tree", STATE_FOCUSABLE);
@ -360,6 +368,11 @@
title="Support ARIA 1.1 switch role">
Mozilla Bug 1136563
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1355921"
title="Elements with a defined, non-false value for aria-current should expose ATK_STATE_ACTIVE">
Mozilla Bug 1355921
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -631,5 +644,11 @@
<!-- Test that directory is readonly -->
<div id="aria_directory" role="directory"></div>
<!-- aria-current -->
<div id="current_page_1" role="link" aria-current="page">1</div>
<div id="page_2" role="link" aria-current="false">2</div>
<div id="page_3" role="link">3</div>
<div id="page_4" role="link" aria-current="">4</div>
<div id="current_foo" aria-current="foo">foo</div>
</body>
</html>

Просмотреть файл

@ -36,6 +36,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
// test (checkbox) checkable and checked states
testStates("checkbox_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("checkbox_checked_mixed", (STATE_CHECKABLE | STATE_MIXED), 0, STATE_CHECKED);
testStates("checkbox_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("checkbox_checked_empty", STATE_CHECKABLE , 0, STATE_CHECKED);
testStates("checkbox_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
@ -98,6 +99,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
// test (menuitem) checkable and checked states, which are unsupported on this role
testStates("menuitem_checked_true", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_mixed", 0, 0, (STATE_CHECKABLE | STATE_CHECKED | STATE_MIXED));
testStates("menuitem_checked_false", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_empty", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_undefined", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
@ -105,6 +107,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
// test (menuitemcheckbox) checkable and checked states
testStates("menuitemcheckbox_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitemcheckbox_checked_mixed", (STATE_CHECKABLE | STATE_MIXED), 0, STATE_CHECKED);
testStates("menuitemcheckbox_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemcheckbox_checked_empty", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemcheckbox_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
@ -119,6 +122,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
// test (menuitemradio) checkable and checked states
testStates("menuitemradio_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitemradio_checked_mixed", STATE_CHECKABLE, 0, (STATE_MIXED | STATE_CHECKED));
testStates("menuitemradio_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemradio_checked_empty", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemradio_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
@ -133,6 +137,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
// test (radio) checkable and checked states
testStates("radio_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("radio_checked_mixed", STATE_CHECKABLE, 0, (STATE_MIXED | STATE_CHECKED));
testStates("radio_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("radio_checked_empty", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("radio_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
@ -235,6 +240,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
<div id="button_pressed_absent" role="button">This button has <emph>no</emph> aria-pressed attribute and should <emph>not</emph> get ROLE_TOGGLE_BUTTON.</div>
<div id="checkbox_checked_true" role="checkbox" aria-checked="true">This checkbox has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_checked.</div>
<div id="checkbox_checked_mixed" role="checkbox" aria-checked="mixed">This checkbox has aria-checked="mixed" and should get STATE_CHECKABLE. It should also get STATE_MIXED.</div>
<div id="checkbox_checked_false" role="checkbox" aria-checked="false">This checkbox has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="checkbox_checked_empty" role="checkbox" aria-checked="">This checkbox has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="checkbox_checked_undefined" role="checkbox" aria-checked="undefined">This checkbox has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
@ -296,12 +302,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
<div role="menu">
<div id="menuitem_checked_true" role="menuitem" aria-checked="true">Generic menuitems don't support aria-checked.</div>
<div id="menuitem_checked_mixed" role="menuitem" aria-checked="mixed">Generic menuitems don't support aria-checked.</div>
<div id="menuitem_checked_false" role="menuitem" aria-checked="false">Generic menuitems don't support aria-checked.</div>
<div id="menuitem_checked_empty" role="menuitem" aria-checked="">Generic menuitems don't support aria-checked.</div>
<div id="menuitem_checked_undefined" role="menuitem" aria-checked="undefined">Generic menuitems don't support aria-checked.</div>
<div id="menuitem_checked_absent" role="menuitem">Generic menuitems don't support aria-checked.</div>
<div id="menuitemcheckbox_checked_true" role="menuitemcheckbox" aria-checked="true">This menuitemcheckbox has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_checked.</div>
<div id="menuitemcheckbox_checked_mixed" role="menuitemcheckbox" aria-checked="mixed">This menuitemcheckbox has aria-checked="mixed" and should get STATE_CHECKABLE. It should also get STATE_MIXED.</div>
<div id="menuitemcheckbox_checked_false" role="menuitemcheckbox" aria-checked="false">This menuitemcheckbox has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="menuitemcheckbox_checked_empty" role="menuitemcheckbox" aria-checked="">This menuitemcheckbox has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitemcheckbox_checked_undefined" role="menuitemcheckbox" aria-checked="undefined">This menuitemcheckbox has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
@ -314,6 +322,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
<div id="menuitemcheckbox_readonly_absent" role="menuitemcheckbox">This menuitemcheckbox has <emph>no</emph> aria-readonly attribute and should <emph>not</emph> get STATE_READONLY.</div>
<div id="menuitemradio_checked_true" role="menuitemradio" aria-checked="true">This menuitem has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_checked.</div>
<div id="menuitemradio_checked_mixed" role="menuitemradio" aria-checked="mixed">This menuitem has aria-checked="mixed" and should get STATE_CHECKABLE. It should not get STATE_MIXED.</div>
<div id="menuitemradio_checked_false" role="menuitemradio" aria-checked="false">This menuitem has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="menuitemradio_checked_empty" role="menuitemradio" aria-checked="">This menuitem has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitemradio_checked_undefined" role="menuitemradio" aria-checked="undefined">This menuitem has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
@ -327,6 +336,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
<div id="menuitemradio_readonly_absent" role="menuitemradio">This menuitemradio has <emph>no</emph> aria-readonly attribute and should <emph>not</emph> get STATE_READONLY.</div>
<div id="radio_checked_true" role="radio" aria-checked="true">This menuitem has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_CHECKED.</div>
<div id="radio_checked_mixed" role="radio" aria-checked="mixed">This radio button has aria-checked="mixed" and should get STATE_CHECKABLE. It should not get STATE_MIXED.</div>
<div id="radio_checked_false" role="radio" aria-checked="false">This menuitem has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="radio_checked_empty" role="radio" aria-checked="">This menuitem has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="radio_checked_undefined" role="radio" aria-checked="undefined">This menuitem has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>

Просмотреть файл

@ -868,7 +868,23 @@ this.PanelMultiView = class {
// sense for all platforms. If the arrow visuals change significantly,
// this value will be easy to adjust.
const EXTRA_MARGIN_PX = 20;
this._viewStack.style.maxHeight = (maxHeight - EXTRA_MARGIN_PX) + "px";
maxHeight -= EXTRA_MARGIN_PX;
this._viewStack.style.maxHeight = maxHeight + "px";
// When using block-in-box layout inside a scrollable frame, like in the
// main menu contents scroller, if we allow the contents to scroll then
// it will not cause its container to expand. Thus, we layout first
// without any scrolling (using "display: flex;"), and only if the view
// exceeds the available space we set the height explicitly and enable
// scrolling.
if (this._mainView.hasAttribute("blockinboxworkaround")) {
let mainViewHeight =
this._dwu.getBoundsWithoutFlushing(this._mainView).height;
if (mainViewHeight > maxHeight) {
this._mainView.style.height = maxHeight + "px";
this._mainView.setAttribute("exceeding", "true");
}
}
break;
case "popupshown":
// Now that the main view is visible, we can check the height of the
@ -890,6 +906,12 @@ this.PanelMultiView = class {
this._resetKeyNavigation();
this._mainViewHeight = 0;
}
// Always try to layout the panel normally when reopening it. This is
// also the layout that will be used in customize mode.
if (this._mainView.hasAttribute("blockinboxworkaround")) {
this._mainView.style.removeProperty("height");
this._mainView.removeAttribute("exceeding");
}
break;
}
}

Просмотреть файл

@ -12,7 +12,7 @@
<panelmultiview id="PanelUI-multiView" mainViewId="PanelUI-mainView"
viewCacheId="appMenu-viewCache">
<panelview id="PanelUI-mainView" context="customizationPanelContextMenu"
descriptionheightworkaround="true">
descriptionheightworkaround="true" blockinboxworkaround="true">
<vbox id="PanelUI-contents-scroller">
<vbox id="PanelUI-contents" class="panelUI-grid"/>
</vbox>

Просмотреть файл

@ -250,11 +250,6 @@ photonpanelmultiview .panel-subview-header {
-moz-box-pack: center;
}
#PanelUI-mainView {
display: flex;
flex-direction: column;
}
#appMenu-popup > arrowscrollbox > autorepeatbutton,
#PanelUI-popup > arrowscrollbox > autorepeatbutton {
display: none;
@ -381,12 +376,18 @@ photonpanelmultiview .panel-subview-body {
}
#PanelUI-contents-scroller {
-moz-box-flex: 1;
overflow-y: auto;
overflow-x: hidden;
width: @menuPanelWidth@;
padding-left: 5px;
padding-right: 5px;
flex: auto;
-moz-box-align: center;
}
/* Allow box layout to take over when the view exceeds the available space. */
#PanelUI-mainView:not([exceeding]) > #PanelUI-contents-scroller {
display: flex;
}
.toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton > .toolbarbutton-icon {

Просмотреть файл

@ -23,8 +23,6 @@ case "$target" in
dnl undefined symbol (present on the hardware, just not in the
dnl NDK.)
LDFLAGS="-L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform -Wl,--allow-shlib-undefined $LDFLAGS"
dnl Add -llog by default, since we use it all over the place.
LIBS="-llog $LIBS"
ANDROID_PLATFORM="${android_platform}"
AC_DEFINE(ANDROID)

Просмотреть файл

@ -991,13 +991,18 @@ set_config('COLOR_CFLAGS', color_cflags)
# we are properly managing visibility ourselves) and avoid this whole mess.
# Note that we don't need to do this with gcc, as libc++ detects gcc and
# effectively does the same thing we are doing here.
#
# _LIBCPP_ALWAYS_INLINE needs similar workarounds, since it too declares
# hidden visibility.
@depends(c_compiler, target)
def libcxx_inline_visibility(c_compiler, target):
def libcxx_override_visibility(c_compiler, target):
if c_compiler.type == 'clang' and target.os == 'Android':
return ''
set_define('_LIBCPP_INLINE_VISIBILITY', libcxx_inline_visibility)
set_define('_LIBCPP_INLINE_VISIBILITY_EXCEPT_GCC49', libcxx_inline_visibility)
set_define('_LIBCPP_INLINE_VISIBILITY', libcxx_override_visibility)
set_define('_LIBCPP_INLINE_VISIBILITY_EXCEPT_GCC49', libcxx_override_visibility)
set_define('_LIBCPP_ALWAYS_INLINE', libcxx_override_visibility)
set_define('_LIBCPP_ALWAYS_INLINE_EXCEPT_GCC49', libcxx_override_visibility)
@depends(target, check_build_environment)
def visibility_flags(target, env):

Просмотреть файл

@ -21,6 +21,10 @@ def Binary():
if CONFIG['STLPORT_LIBS']:
OS_LIBS += [CONFIG['STLPORT_LIBS']]
# Add -llog by default, since we use it all over the place.
if CONFIG['OS_TARGET'] == 'Android':
OS_LIBS += ['log']
@template
def Program(name):

Просмотреть файл

@ -130,7 +130,6 @@ HOST_LIBRARY := $(LIB_PREFIX)$(HOST_LIBRARY_NAME).$(LIB_SUFFIX)
endif
endif
ifdef LIBRARY
ifdef FORCE_SHARED_LIB
ifdef MKSHLIB
@ -142,7 +141,6 @@ EMBED_MANIFEST_AT=2
endif # MKSHLIB
endif # FORCE_SHARED_LIB
endif # LIBRARY
ifeq ($(OS_ARCH),WINNT)
ifndef GNU_CC
@ -908,15 +906,7 @@ ifdef MOZ_USING_SCCACHE
sccache_wrap := RUSTC_WRAPPER='$(CCACHE)'
endif
# This function is intended to be called by:
#
# $(call CARGO_BUILD,EXTRA_ENV_VAR1=X EXTRA_ENV_VAR2=Y ...)
#
# but, given the idiosyncracies of make, can also be called without arguments:
#
# $(call CARGO_BUILD)
define CARGO_BUILD
define RUN_CARGO
env $(environment_cleaner) $(rust_unlock_unstable) $(rustflags_override) $(sccache_wrap) \
CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) \
RUSTC=$(RUSTC) \
@ -927,8 +917,23 @@ env $(environment_cleaner) $(rust_unlock_unstable) $(rustflags_override) $(sccac
PKG_CONFIG_ALLOW_CROSS=1 \
RUST_BACKTRACE=1 \
MOZ_TOPOBJDIR=$(topobjdir) \
$(1) \
$(CARGO) build $(cargo_build_flags)
$(2) \
$(CARGO) $(1) $(cargo_build_flags)
endef
# This function is intended to be called by:
#
# $(call CARGO_BUILD,EXTRA_ENV_VAR1=X EXTRA_ENV_VAR2=Y ...)
#
# but, given the idiosyncracies of make, can also be called without arguments:
#
# $(call CARGO_BUILD)
define CARGO_BUILD
$(call RUN_CARGO,build,$(1))
endef
define CARGO_CHECK
$(call RUN_CARGO,check,$(1))
endef
cargo_linker_env_var := CARGO_TARGET_$(RUST_TARGET_ENV_NAME)_LINKER
@ -972,6 +977,12 @@ force-cargo-library-build:
$(call CARGO_BUILD,$(target_cargo_env_vars)) --lib $(cargo_target_flag) $(rust_features_flag)
$(RUST_LIBRARY_FILE): force-cargo-library-build
force-cargo-library-check:
$(call CARGO_CHECK,$(target_cargo_env_vars)) --lib $(cargo_target_flag) $(rust_features_flag)
else
force-cargo-library-check:
@true
endif # RUST_LIBRARY_FILE
ifdef HOST_RUST_LIBRARY_FILE
@ -985,6 +996,12 @@ force-cargo-host-library-build:
$(call CARGO_BUILD) --lib $(cargo_host_flag) $(host_rust_features_flag)
$(HOST_RUST_LIBRARY_FILE): force-cargo-host-library-build
force-cargo-host-library-check:
$(call CARGO_CHECK) --lib $(cargo_host_flag) $(host_rust_features_flag)
else
force-cargo-host-library-check:
@true
endif # HOST_RUST_LIBRARY_FILE
ifdef RUST_PROGRAMS
@ -993,6 +1010,12 @@ force-cargo-program-build:
$(call CARGO_BUILD,$(target_cargo_env_vars)) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag)
$(RUST_PROGRAMS): force-cargo-program-build
force-cargo-program-check:
$(call CARGO_CHECK,$(target_cargo_env_vars)) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag)
else
force-cargo-program-check:
@true
endif # RUST_PROGRAMS
ifdef HOST_RUST_PROGRAMS
force-cargo-host-program-build:
@ -1000,6 +1023,13 @@ force-cargo-host-program-build:
$(call CARGO_BUILD) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(cargo_host_flag)
$(HOST_RUST_PROGRAMS): force-cargo-host-program-build
force-cargo-host-program-check:
$(REPORT_BUILD)
$(call CARGO_CHECK) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(cargo_host_flag)
else
force-cargo-host-program-check:
@true
endif # HOST_RUST_PROGRAMS
$(SOBJS):

Просмотреть файл

@ -1628,16 +1628,16 @@ html .toggle-button-end.vertical svg {
color: var(--theme-highlight-blue);
text-decoration: underline;
}
.popover .preview .header .link:hover {
cursor: pointer;
}
.selected-token {
.selection, .debug-expression.selection {
background-color: var(--theme-highlight-yellow);
color: var(--theme-selection-color);
}
.selected-token:hover {
.selection:hover {
cursor: pointer;
}
@ -1711,14 +1711,14 @@ html .toggle-button-end.vertical svg {
cursor: pointer;
}
.editor-wrapper {
--debug-line-background: rgba(226, 236, 247, 0.5);
--debug-line-border: rgb(145, 188, 219);
--debug-expression-background: rgba(202, 227, 255, 0.5);
--editor-searchbar-height: 27px;
--editor-second-searchbar-height: 27px;
}
.theme-dark .editor-wrapper {
--debug-line-background: rgb(73, 82, 103);
--debug-expression-background: rgb(73, 82, 103);
--debug-line-border: rgb(119, 134, 162);
}
@ -1872,13 +1872,13 @@ html[dir="rtl"] .editor-mount {
color: var(--theme-content-color3);
}
.new-debug-line .CodeMirror-line {
background-color: var(--debug-line-background) !important;
outline: var(--debug-line-border) solid 1px;
.debug-expression {
background-color: var(--debug-expression-background);
}
.new-debug-line .CodeMirror-linenumber {
.new-debug-line .CodeMirror-line {
background-color: transparent !important;
outline: var(--debug-line-border) solid 1px;
}
/* Don't display the highlight color since the debug line

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -29952,6 +29952,7 @@ return /******/ (function(modules) { // webpackBootstrap
}
this.worker.removeEventListener("message", listener);
if (result.error) {
reject(result.error);
} else {
@ -30540,7 +30541,8 @@ return /******/ (function(modules) { // webpackBootstrap
symbols.functions.push({
name: (0, _getFunctionName2.default)(path),
location: path.node.loc,
parameterNames: getFunctionParameterNames(path)
parameterNames: getFunctionParameterNames(path),
identifier: path.node.id
});
}
@ -30803,7 +30805,11 @@ return /******/ (function(modules) { // webpackBootstrap
enter(path) {
var node = path.node;
if (t.isMemberExpression(node) && node.property.name === token && (0, _helpers.nodeContainsPosition)(node, location)) {
if (!(0, _helpers.nodeContainsPosition)(node, location)) {
return path.skip();
}
if (t.isMemberExpression(node) && node.property.name === token) {
var memberExpression = (0, _helpers.getMemberExpression)(node);
expression = {
expression: memberExpression,
@ -30837,7 +30843,11 @@ return /******/ (function(modules) { // webpackBootstrap
(0, _ast.traverseAst)(source, {
enter(path) {
if ((0, _helpers.isLexicalScope)(path) && (0, _helpers.nodeContainsPosition)(path.node, location)) {
if (!(0, _helpers.nodeContainsPosition)(path.node, location)) {
return path.skip();
}
if ((0, _helpers.isLexicalScope)(path)) {
closestPath = path;
}
}
@ -30855,9 +30865,10 @@ return /******/ (function(modules) { // webpackBootstrap
(0, _ast.traverseAst)(source, {
enter(path) {
if ((0, _helpers.nodeContainsPosition)(path.node, location)) {
closestPath = path;
if (!(0, _helpers.nodeContainsPosition)(path.node, location)) {
return path.skip();
}
closestPath = path;
}
});
@ -30961,31 +30972,23 @@ return /******/ (function(modules) { // webpackBootstrap
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _get = __webpack_require__(1073);
var _get2 = _interopRequireDefault(_get);
var _helpers = __webpack_require__(1052);
var _ast = __webpack_require__(1051);
var _getSymbols = __webpack_require__(1050);
var _getSymbols2 = _interopRequireDefault(_getSymbols);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Returns all functions (declarations, expressions, arrows) for the given
* source
*/
function findFunctions(source) {
var fns = [];
(0, _ast.traverseAst)(source, {
enter(path) {
if ((0, _helpers.isFunction)(path)) {
fns.push(path);
}
}
});
return fns;
var symbols = (0, _getSymbols2.default)(source);
return symbols.functions;
}
/**
@ -30994,19 +30997,18 @@ return /******/ (function(modules) { // webpackBootstrap
* but before the function parameters.
*/
var getLocation = path => {
var location = Object.assign({}, (0, _get2.default)("node.loc", path));
function getLocation(func) {
var location = _extends({}, func.location);
// if the function has an identifier, start the block after it so the
// identifier is included in the "scope" of its parent
var identifierEnd = (0, _get2.default)("node.id.loc.end", path);
var identifierEnd = (0, _get2.default)("identifier.loc.end", func);
if (identifierEnd) {
location.start = identifierEnd;
}
return location;
};
}
/**
* Reduces an array of locations to remove items that are completely enclosed

Просмотреть файл

@ -5922,6 +5922,7 @@ return /******/ (function(modules) { // webpackBootstrap
}
this.worker.removeEventListener("message", listener);
if (result.error) {
reject(result.error);
} else {

Просмотреть файл

@ -556,6 +556,7 @@ return /******/ (function(modules) { // webpackBootstrap
}
this.worker.removeEventListener("message", listener);
if (result.error) {
reject(result.error);
} else {

Просмотреть файл

@ -45,6 +45,7 @@ support-files =
[browser_dbg-breaking.js]
[browser_dbg-breaking-from-console.js]
[browser_dbg-breakpoints.js]
[browser_dbg-breakpoints-reloading.js]
[browser_dbg-breakpoints-cond.js]
[browser_dbg-call-stack.js]
[browser_dbg-expressions.js]
@ -68,6 +69,9 @@ skip-if = os == "linux" # bug 1351952
[browser_dbg-searching.js]
skip-if = true
[browser_dbg-sourcemaps.js]
[browser_dbg-sourcemaps-reloading.js]
[browser_dbg-sourcemaps2.js]
[browser_dbg-sourcemaps-bogus.js]
[browser_dbg-sources.js]
[browser_dbg-tabs.js]
[browser_dbg-toggling-tools.js]

Просмотреть файл

@ -0,0 +1,39 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests pending breakpoints when reloading
// Utilities for interacting with the editor
function clickGutter(dbg, line) {
clickElement(dbg, "gutter", line);
}
function getLineEl(dbg, line) {
const lines = dbg.win.document.querySelectorAll(".CodeMirror-code > div");
return lines[line - 1];
}
function addBreakpoint(dbg, line) {
clickGutter(dbg, line);
return waitForDispatch(dbg, "ADD_BREAKPOINT");
}
function assertEditorBreakpoint(dbg, line) {
const exists = !!getLineEl(dbg, line).querySelector(".new-breakpoint");
ok(exists, `Breakpoint exists on line ${line}`);
}
add_task(function*() {
const dbg = yield initDebugger("doc-scripts.html");
const { selectors: { getBreakpoints, getBreakpoint }, getState } = dbg;
const source = findSource(dbg, "simple1.js");
yield selectSource(dbg, source.url);
yield addBreakpoint(dbg, 5);
yield addBreakpoint(dbg, 2);
yield reload(dbg, "simple1");
yield waitForSelectedSource(dbg);
assertEditorBreakpoint(dbg, 4);
assertEditorBreakpoint(dbg, 5);
});

Просмотреть файл

@ -0,0 +1,52 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(function*() {
// NOTE: the CORS call makes the test run times inconsistent
requestLongerTimeout(2);
const dbg = yield initDebugger("doc-sourcemaps.html");
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
yield waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js");
ok(true, "Original sources exist");
const entrySrc = findSource(dbg, "entry.js");
yield selectSource(dbg, entrySrc);
ok(
dbg.win.cm.getValue().includes("window.keepMeAlive"),
"Original source text loaded correctly"
);
// Test that breakpoint sliding is not attempted. The breakpoint
// should not move anywhere.
yield addBreakpoint(dbg, entrySrc, 13);
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
ok(
getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
"Breakpoint has correct line"
);
yield addBreakpoint(dbg, entrySrc, 15);
yield disableBreakpoint(dbg, entrySrc, 15);
// Test reloading the debugger
yield reload(dbg, "opts.js");
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
is(getBreakpoints(getState()).size, 2, "One breakpoint exists");
ok(
getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
"Breakpoint has correct line"
);
ok(
getBreakpoint(getState(), {
sourceId: entrySrc.id,
line: 15,
disabled: true
}),
"Breakpoint has correct line"
);
});

Просмотреть файл

@ -0,0 +1,39 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests adding and removing tabs
function countTabs(dbg) {
return findElement(dbg, "sourceTabs").children.length;
}
add_task(function*() {
let dbg = yield initDebugger("doc-scripts.html");
yield selectSource(dbg, "simple1");
yield selectSource(dbg, "simple2");
is(countTabs(dbg), 2);
// Test reloading the debugger
yield reload(dbg, "simple1", "simple2");
is(countTabs(dbg), 2);
yield waitForSelectedSource(dbg);
// Test reloading the debuggee a second time
yield reload(dbg, "simple1", "simple2");
is(countTabs(dbg), 2);
yield waitForSelectedSource(dbg);
});
add_task(function*() {
let dbg = yield initDebugger("doc-scripts.html", "simple1", "simple2");
yield selectSource(dbg, "simple1");
yield selectSource(dbg, "simple2");
closeTab(dbg, "simple1");
closeTab(dbg, "simple2");
// Test reloading the debugger
yield reload(dbg, "simple1", "simple2");
is(countTabs(dbg), 0);
});

Просмотреть файл

@ -0,0 +1,38 @@
// Return a promise with a reference to jsterm, opening the split
// console if necessary. This cleans up the split console pref so
// it won't pollute other tests.
function getSplitConsole(dbg) {
const { toolbox, win } = dbg;
registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");
});
if (!win) {
win = toolbox.win;
}
if (!toolbox.splitConsole) {
pressKey(dbg, "Escape");
}
return new Promise(resolve => {
toolbox.getPanelWhenReady("webconsole").then(() => {
ok(toolbox.splitConsole, "Split console is shown.");
let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
resolve(jsterm);
});
});
}
add_task(function*() {
const dbg = yield initDebugger("doc-scripts.html");
yield selectSource(dbg, "long");
dbg.win.cm.scrollTo(0, 284);
pressKey(dbg, "inspector");
pressKey(dbg, "debugger");
is(dbg.win.cm.getScrollInfo().top, 284);
});

Просмотреть файл

@ -191,6 +191,13 @@ function waitForElement(dbg, selector) {
return waitUntil(() => findElementWithSelector(dbg, selector));
}
function waitForSelectedSource(dbg) {
return waitForState(dbg, state => {
const source = dbg.selectors.getSelectedSource(state);
return source && source.has("loading") && !source.get("loading");
});
}
/**
* Assert that the debugger is paused at the correct location.
*
@ -215,10 +222,20 @@ function assertPausedLocation(dbg, source, line) {
is(location.line, line);
// Check the debug line
const lineInfo = getCM(dbg).lineInfo(line - 1);
ok(
getCM(dbg).lineInfo(line - 1).wrapClass.includes("debug-line"),
lineInfo.wrapClass.includes("debug-line"),
"Line is highlighted as paused"
);
const markedSpans = lineInfo.handle.markedSpans;
if (markedSpans && markedSpans.length > 0) {
const marker = markedSpans[0].marker;
ok(
marker.className.includes("debug-expression"),
"expression is highlighted as paused"
);
}
}
/**
@ -381,12 +398,13 @@ function findSource(dbg, url) {
function selectSource(dbg, url, line) {
info("Selecting source: " + url);
const source = findSource(dbg, url);
const hasText = !!source.text && !source.loading;
dbg.actions.selectSource(source.id, { line });
if (!hasText) {
return waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
return dbg.actions.selectSource(source.id, { line });
}
function closeTab(dbg, url) {
info("Closing tab: " + url);
const source = findSource(dbg, url);
return dbg.actions.closeTab(source.url);
}
/**
@ -460,7 +478,7 @@ function deleteExpression(dbg, input) {
* @static
*/
function reload(dbg, ...sources) {
return dbg.client.reload().then(() => waitForSources(...sources));
return dbg.client.reload().then(() => waitForSources(dbg, ...sources));
}
/**
@ -496,6 +514,13 @@ function addBreakpoint(dbg, source, line, col) {
return waitForDispatch(dbg, "ADD_BREAKPOINT");
}
function disableBreakpoint(dbg, source, line, col) {
source = findSource(dbg, source);
const sourceId = source.id;
dbg.actions.disableBreakpoint({ sourceId, line, col });
return waitForDispatch(dbg, "DISABLE_BREAKPOINT");
}
/**
* Removes a breakpoint from a source at line/col.
*
@ -558,6 +583,10 @@ function invokeInTab(fnc) {
const isLinux = Services.appinfo.OS === "Linux";
const isMac = Services.appinfo.OS === "Darwin";
const cmdOrCtrl = isLinux ? { ctrlKey: true } : { metaKey: true };
const shiftOrAlt = isMac
? { accelKey: true, shiftKey: true }
: { accelKey: true, altKey: true };
// On Mac, going to beginning/end only works with meta+left/right. On
// Windows, it only works with home/end. On Linux, apparently, either
// ctrl+left/right or home/end work.
@ -567,7 +596,10 @@ const endKey = isMac
const startKey = isMac
? { code: "VK_LEFT", modifiers: cmdOrCtrl }
: { code: "VK_HOME" };
const keyMappings = {
debugger: { code: "s", modifiers: shiftOrAlt },
inspector: { code: "c", modifiers: shiftOrAlt },
sourceSearch: { code: "p", modifiers: cmdOrCtrl },
fileSearch: { code: "f", modifiers: cmdOrCtrl },
Enter: { code: "VK_RETURN" },
@ -640,6 +672,7 @@ const selectors = {
highlightLine: ".CodeMirror-code > .highlight-line",
codeMirror: ".CodeMirror",
resume: ".resume.active",
sourceTabs: `.source-tabs`,
stepOver: ".stepOver.active",
stepOut: ".stepOut.active",
stepIn: ".stepIn.active",

Просмотреть файл

@ -29,6 +29,7 @@ devtools.jar:
content/sourceeditor/codemirror/codemirror.bundle.js (sourceeditor/codemirror/codemirror.bundle.js)
content/sourceeditor/codemirror/lib/codemirror.css (sourceeditor/codemirror/lib/codemirror.css)
content/sourceeditor/codemirror/mozilla.css (sourceeditor/codemirror/mozilla.css)
content/sourceeditor/codemirror/cmiframe.html (sourceeditor/codemirror/cmiframe.html)
content/sourceeditor/codemirror/old-debugger.css (sourceeditor/codemirror/old-debugger.css)
content/debugger/new/index.html (debugger/new/index.html)
content/debugger/debugger.xul (debugger/debugger.xul)

Просмотреть файл

@ -115,7 +115,7 @@ const RequestListHeader = createClass({
id: `requests-list-${name}-button`,
className: `requests-list-header-button`,
"data-sorted": sorted,
title: sortedTitle,
title: sortedTitle ? `${label} (${sortedTitle})` : label,
onClick: () => sortBy(name),
},
name === "waterfall"

Просмотреть файл

@ -72,6 +72,7 @@ support-files =
[browser_net_charts-06.js]
[browser_net_charts-07.js]
[browser_net_clear.js]
[browser_net_column_headers_tooltips.js]
[browser_net_columns_last_column.js]
[browser_net_columns_pref.js]
[browser_net_columns_reset.js]

Просмотреть файл

@ -0,0 +1,25 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Bug 1377094 - Test that all column headers have tooltips.
*/
add_task(function* () {
let { monitor } = yield initNetMonitor(SIMPLE_URL);
info("Starting test... ");
let { document } = monitor.panelWin;
let headers = document.querySelectorAll(".requests-list-header-button");
for (let header of headers) {
const buttonText = header.querySelector(".button-text").textContent;
const tooltip = header.getAttribute("title");
is(buttonText, tooltip,
"The " + header.id + " header has the button text in its 'title' attribute.");
}
yield teardown(monitor);
});

Просмотреть файл

@ -117,15 +117,19 @@ add_task(function* () {
if (header != target) {
ok(!header.hasAttribute("data-sorted"),
"The " + header.id + " header does not have a 'data-sorted' attribute.");
ok(!header.getAttribute("title"),
"The " + header.id + " header does not have a 'title' attribute.");
ok(!header.getAttribute("title").includes(L10N.getStr("networkMenu.sortedAsc")) &&
!header.getAttribute("title").includes(L10N.getStr("networkMenu.sortedDesc")),
"The " + header.id +
" header does not include any sorting in the 'title' attribute.");
} else {
is(header.getAttribute("data-sorted"), direction,
"The " + header.id + " header has a correct 'data-sorted' attribute.");
is(header.getAttribute("title"), direction == "ascending"
const sorted = direction == "ascending"
? L10N.getStr("networkMenu.sortedAsc")
: L10N.getStr("networkMenu.sortedDesc"),
"The " + header.id + " header has a correct 'title' attribute.");
: L10N.getStr("networkMenu.sortedDesc");
ok(header.getAttribute("title").includes(sorted),
"The " + header.id +
" header includes the used sorting in the 'title' attribute.");
}
}
}

Просмотреть файл

@ -208,15 +208,19 @@ add_task(function* () {
if (header != target) {
ok(!header.hasAttribute("data-sorted"),
"The " + header.id + " header does not have a 'data-sorted' attribute.");
ok(!header.getAttribute("title"),
"The " + header.id + " header does not have a 'title' attribute.");
ok(!header.getAttribute("title").includes(L10N.getStr("networkMenu.sortedAsc")) &&
!header.getAttribute("title").includes(L10N.getStr("networkMenu.sortedDesc")),
"The " + header.id +
" header does not include any sorting in the 'title' attribute.");
} else {
is(header.getAttribute("data-sorted"), direction,
"The " + header.id + " header has a correct 'data-sorted' attribute.");
is(header.getAttribute("title"), direction == "ascending"
const sorted = direction == "ascending"
? L10N.getStr("networkMenu.sortedAsc")
: L10N.getStr("networkMenu.sortedDesc"),
"The " + header.id + " header has a correct 'title' attribute.");
: L10N.getStr("networkMenu.sortedDesc");
ok(header.getAttribute("title").includes(sorted),
"The " + header.id +
" header includes the used sorting in the 'title' attribute.");
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html dir='ltr'>
<head>
<style id="cmBaseStyle">
html, body { height: 100%; }
body { margin: 0; overflow: hidden; }
.CodeMirror { width: 100% !important; line-height: 1.25 !important; }
</style>
<link rel='stylesheet' href="chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css">
<link rel='stylesheet' href="chrome://devtools/content/sourceeditor/codemirror/addon/dialog/dialog.css">
<link rel='stylesheet' href="chrome://devtools/content/sourceeditor/codemirror/mozilla.css">
<link rel='stylesheet' href="chrome://devtools/content/sourceeditor/codemirror/old-debugger.css">
</head>
<body class='theme-body devtools-monospace'></body>
</html>

Просмотреть файл

@ -48,37 +48,14 @@ const {
const { OS } = Services.appinfo;
// CM_STYLES, CM_SCRIPTS and CM_IFRAME represent the HTML,
// JavaScript and CSS that is injected into an iframe in
// order to initialize a CodeMirror instance.
const CM_STYLES = [
"chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css",
"chrome://devtools/content/sourceeditor/codemirror/addon/dialog/dialog.css",
"chrome://devtools/content/sourceeditor/codemirror/mozilla.css"
];
CM_STYLES.push(
"chrome://devtools/content/sourceeditor/codemirror/old-debugger.css"
);
// CM_SCRIPTS and CM_IFRAME represent the HTML and JavaScript that is
// injected into an iframe in order to initialize a CodeMirror instance.
const CM_SCRIPTS = [
"chrome://devtools/content/sourceeditor/codemirror/codemirror.bundle.js",
];
const CM_IFRAME =
"data:text/html;charset=utf8,<!DOCTYPE html>" +
"<html dir='ltr'>" +
" <head>" +
" <style>" +
" html, body { height: 100%; }" +
" body { margin: 0; overflow: hidden; }" +
" .CodeMirror { width: 100% !important; line-height: 1.25 !important; }" +
" </style>" +
CM_STYLES.map(style => "<link rel='stylesheet' href='" + style + "'>").join("\n") +
" </head>" +
" <body class='theme-body devtools-monospace'></body>" +
"</html>";
const CM_IFRAME = "chrome://devtools/content/sourceeditor/codemirror/cmiframe.html";
const CM_MAPPING = [
"focus",

Просмотреть файл

@ -8,8 +8,9 @@ function test() {
waitForExplicitFinish();
setup((ed, win) => {
// appendTo
let src = win.document.querySelector("iframe").getAttribute("src");
ok(~src.indexOf(".CodeMirror"), "correct iframe is there");
let cmFrame = win.document.querySelector("iframe");
let cmStyle = cmFrame.contentDocument.getElementById("cmBaseStyle");
ok(~cmStyle.innerHTML.indexOf(".CodeMirror"), "correct iframe is there");
// getOption/setOption
ok(ed.getOption("styleActiveLine"), "getOption works");

Просмотреть файл

@ -197,7 +197,8 @@ Link::LinkState() const
// If we have not yet registered for notifications and need to,
// due to our href changing, register now!
if (!mRegistered && mNeedsRegistration && element->IsInComposedDoc()) {
if (!mRegistered && mNeedsRegistration && element->IsInComposedDoc() &&
!HasPendingLinkUpdate()) {
// Only try and register once.
self->mNeedsRegistration = false;

Просмотреть файл

@ -126,7 +126,7 @@ public:
void TryDNSPrefetchPreconnectOrPrefetchOrPrerender();
void CancelPrefetch();
bool HasPendingLinkUpdate() { return mHasPendingLinkUpdate; }
bool HasPendingLinkUpdate() const { return mHasPendingLinkUpdate; }
void SetHasPendingLinkUpdate() { mHasPendingLinkUpdate = true; }
void ClearHasPendingLinkUpdate() { mHasPendingLinkUpdate = false; }

196
dom/base/XPathGenerator.cpp Normal file
Просмотреть файл

@ -0,0 +1,196 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "XPathGenerator.h"
#include "nsGkAtoms.h"
#include "Element.h"
#include "nsTArray.h"
/**
* Check whether a character is a non-word character. A non-word character is a
* character that isn't in ('a'..'z') or in ('A'..'Z') or a number or an underscore.
* */
bool IsNonWordCharacter(const char16_t& aChar)
{
if (((char16_t('A') <= aChar) && (aChar <= char16_t('Z'))) ||
((char16_t('a') <= aChar) && (aChar <= char16_t('z'))) ||
((char16_t('0') <= aChar) && (aChar <= char16_t('9'))) ||
(aChar == char16_t('_'))) {
return false;
} else {
return true;
}
}
/**
* Check whether a string contains a non-word character.
* */
bool ContainNonWordCharacter(const nsAString& aStr)
{
const char16_t* cur = aStr.BeginReading();
const char16_t* end = aStr.EndReading();
for (; cur < end; ++cur) {
if (IsNonWordCharacter(*cur)) {
return true;
}
}
return false;
}
/**
* Get the prefix according to the given namespace and assign the result to aResult.
* */
void GetPrefix(const nsINode* aNode, nsAString& aResult)
{
if (aNode->IsXULElement()) {
aResult.Assign(NS_LITERAL_STRING("xul"));
} else if (aNode->IsHTMLElement()) {
aResult.Assign(NS_LITERAL_STRING("xhtml"));
}
}
void GetNameAttribute(const nsINode* aNode, nsAString& aResult)
{
if (aNode->HasName()) {
const Element* elem = aNode->AsElement();
elem->GetAttr(kNameSpaceID_None, nsGkAtoms::name, aResult);
}
}
/**
* Put all sequences of ' in a string in between '," and ",' . And then put
* the result string in between concat(' and ').
*
* For example, a string 'a'' will return result concat('',"'",'a',"''",'')
* */
void GenerateConcatExpression(const nsAString& aStr, nsAString& aResult)
{
const char16_t* cur = aStr.BeginReading();
const char16_t* end = aStr.EndReading();
// Put all sequences of ' in between '," and ",'
nsAutoString result;
const char16_t* nonQuoteBeginPtr = nullptr;
const char16_t* quoteBeginPtr = nullptr;
for (; cur < end; ++cur) {
if (char16_t('\'') == *cur) {
if (nonQuoteBeginPtr) {
result.Append(nonQuoteBeginPtr, cur - nonQuoteBeginPtr);
nonQuoteBeginPtr = nullptr;
}
if (!quoteBeginPtr) {
result.Append(NS_LITERAL_STRING("\',\""));
quoteBeginPtr = cur;
}
} else {
if (!nonQuoteBeginPtr) {
nonQuoteBeginPtr = cur;
}
if (quoteBeginPtr) {
result.Append(quoteBeginPtr, cur - quoteBeginPtr);
result.Append(NS_LITERAL_STRING("\",\'"));
quoteBeginPtr = nullptr;
}
}
}
if (quoteBeginPtr) {
result.Append(quoteBeginPtr, cur - quoteBeginPtr);
result.Append(NS_LITERAL_STRING("\",\'"));
} else if (nonQuoteBeginPtr) {
result.Append(nonQuoteBeginPtr, cur - nonQuoteBeginPtr);
}
// Prepend concat(' and append ').
aResult.Assign(NS_LITERAL_STRING("concat(\'") + result + NS_LITERAL_STRING("\')"));
}
void XPathGenerator::QuoteArgument(const nsAString& aArg, nsAString& aResult)
{
if (!aArg.Contains('\'')) {
aResult.Assign(NS_LITERAL_STRING("\'") + aArg + NS_LITERAL_STRING("\'"));
} else if (!aArg.Contains('\"')) {
aResult.Assign(NS_LITERAL_STRING("\"") + aArg + NS_LITERAL_STRING("\""));
} else {
GenerateConcatExpression(aArg, aResult);
}
}
void XPathGenerator::EscapeName(const nsAString& aName, nsAString& aResult)
{
if (ContainNonWordCharacter(aName)) {
nsAutoString quotedArg;
QuoteArgument(aName, quotedArg);
aResult.Assign(NS_LITERAL_STRING("*[local-name()=") + quotedArg + NS_LITERAL_STRING("]"));
} else {
aResult.Assign(aName);
}
}
void XPathGenerator::Generate(const nsINode* aNode, nsAString& aResult)
{
if (!aNode->GetParentNode()) {
aResult.Truncate();
return;
}
nsAutoString nodeNamespaceURI;
aNode->GetNamespaceURI(nodeNamespaceURI);
const nsString& nodeLocalName = aNode->LocalName();
nsAutoString prefix;
nsAutoString tag;
nsAutoString nodeEscapeName;
GetPrefix(aNode, prefix);
EscapeName(nodeLocalName, nodeEscapeName);
if (prefix.IsEmpty()) {
tag.Assign(nodeEscapeName);
} else {
tag.Assign(prefix + NS_LITERAL_STRING(":") + nodeEscapeName);
}
if (aNode->HasID()) {
// this must be an element
const Element* elem = aNode->AsElement();
nsAutoString elemId;
nsAutoString quotedArgument;
elem->GetId(elemId);
QuoteArgument(elemId, quotedArgument);
aResult.Assign(NS_LITERAL_STRING("//") + tag + NS_LITERAL_STRING("[@id=") +
quotedArgument + NS_LITERAL_STRING("]"));
return;
}
int32_t count = 1;
nsAutoString nodeNameAttribute;
GetNameAttribute(aNode, nodeNameAttribute);
for (const Element* e = aNode->GetPreviousElementSibling(); e; e = e->GetPreviousElementSibling()) {
nsAutoString elementNamespaceURI;
e->GetNamespaceURI(elementNamespaceURI);
nsAutoString elementNameAttribute;
GetNameAttribute(e, elementNameAttribute);
if (e->LocalName().Equals(nodeLocalName) && elementNamespaceURI.Equals(nodeNamespaceURI) &&
(nodeNameAttribute.IsEmpty() || elementNameAttribute.Equals(nodeNameAttribute))) {
++count;
}
}
nsAutoString namePart;
nsAutoString countPart;
if (!nodeNameAttribute.IsEmpty()) {
nsAutoString quotedArgument;
QuoteArgument(nodeNameAttribute, quotedArgument);
namePart.Assign(NS_LITERAL_STRING("[@name=") + quotedArgument + NS_LITERAL_STRING("]"));
}
if (count != 1) {
countPart.Assign(NS_LITERAL_STRING("["));
countPart.AppendInt(count);
countPart.Append(NS_LITERAL_STRING("]"));
}
Generate(aNode->GetParentNode(), aResult);
aResult.Append(NS_LITERAL_STRING("/") + tag + namePart + countPart);
}

31
dom/base/XPathGenerator.h Normal file
Просмотреть файл

@ -0,0 +1,31 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef XPATHGENERATOR_H__
#define XPATHGENERATOR_H__
#include "nsString.h"
#include "nsINode.h"
class XPathGenerator
{
public:
/**
* Return a properly quoted string to insert into an XPath
* */
static void QuoteArgument(const nsAString& aArg, nsAString& aResult);
/**
* Return a valid XPath for the given node (usually the local name itself)
* */
static void EscapeName(const nsAString& aName, nsAString& aResult);
/**
* Generate an approximate XPath query to an (X)HTML node
* */
static void Generate(const nsINode* aNode, nsAString& aResult);
};
#endif

Просмотреть файл

@ -128,6 +128,7 @@ EXPORTS += [
'nsWrapperCache.h',
'nsWrapperCacheInlines.h',
'nsXMLNameSpaceMap.h',
'XPathGenerator.h',
]
if CONFIG['MOZ_WEBRTC']:
@ -362,6 +363,7 @@ UNIFIED_SOURCES += [
'WebSocket.cpp',
'WindowNamedPropertiesHandler.cpp',
'WindowOrientationObserver.cpp',
'XPathGenerator.cpp',
]
if CONFIG['MOZ_WEBRTC']:

Просмотреть файл

@ -13,6 +13,7 @@
#include "nsGkAtoms.h"
#include "nsGlobalWindow.h"
#include "nsContentUtils.h"
#include "nsIContentParent.h"
#include "nsIDocument.h"
#include "nsIEditor.h"
#include "nsPIDOMWindow.h"

Просмотреть файл

@ -113,6 +113,7 @@ GK_ATOM(aria_autocomplete, "aria-autocomplete")
GK_ATOM(aria_busy, "aria-busy")
GK_ATOM(aria_checked, "aria-checked")
GK_ATOM(aria_controls, "aria-controls")
GK_ATOM(aria_current, "aria-current")
GK_ATOM(aria_describedby, "aria-describedby")
GK_ATOM(aria_disabled, "aria-disabled")
GK_ATOM(aria_dropeffect, "aria-dropeffect")

Просмотреть файл

@ -108,6 +108,8 @@
#include "mozilla/dom/NodeBinding.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "XPathGenerator.h"
#ifdef ACCESSIBILITY
#include "mozilla/dom/AccessibleNode.h"
#endif
@ -3023,6 +3025,12 @@ nsINode::AddAnimationObserverUnlessExists(
OwnerDoc()->SetMayHaveAnimationObservers();
}
void
nsINode::GenerateXPath(nsAString& aResult)
{
XPathGenerator::Generate(this, aResult);
}
bool
nsINode::IsApzAware() const
{

Просмотреть файл

@ -1751,6 +1751,7 @@ public:
void UnbindObject(nsISupports* aObject);
void GetBoundMutationObservers(nsTArray<RefPtr<nsDOMMutationObserver> >& aResult);
void GenerateXPath(nsAString& aResult);
already_AddRefed<mozilla::dom::AccessibleNode> GetAccessibleNode();

Просмотреть файл

@ -0,0 +1,140 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "XPathGenerator.h"
#include "nsString.h"
TEST(TestXPathGenerator, TestQuoteArgumentWithoutQuote)
{
nsAutoString arg;
arg.Assign(NS_LITERAL_STRING("testing"));
nsAutoString expectedResult;
expectedResult.Assign(NS_LITERAL_STRING("\'testing\'"));
nsAutoString result;
XPathGenerator::QuoteArgument(arg, result);
ASSERT_TRUE(expectedResult.Equals(result));
}
TEST(TestXPathGenerator, TestQuoteArgumentWithSingleQuote)
{
nsAutoString arg;
arg.Assign(NS_LITERAL_STRING("\'testing\'"));
nsAutoString expectedResult;
expectedResult.Assign(NS_LITERAL_STRING("\"\'testing\'\""));
nsAutoString result;
XPathGenerator::QuoteArgument(arg, result);
ASSERT_TRUE(expectedResult.Equals(result));
}
TEST(TestXPathGenerator, TestQuoteArgumentWithDoubleQuote)
{
nsAutoString arg;
arg.Assign(NS_LITERAL_STRING("\"testing\""));
nsAutoString expectedResult;
expectedResult.Assign(NS_LITERAL_STRING("\'\"testing\"\'"));
nsAutoString result;
XPathGenerator::QuoteArgument(arg, result);
ASSERT_TRUE(expectedResult.Equals(result));
}
TEST(TestXPathGenerator, TestQuoteArgumentWithSingleAndDoubleQuote)
{
nsAutoString arg;
arg.Assign(NS_LITERAL_STRING("\'testing\""));
nsAutoString expectedResult;
expectedResult.Assign(NS_LITERAL_STRING("concat(\'\',\"\'\",\'testing\"\')"));
nsAutoString result;
XPathGenerator::QuoteArgument(arg, result);
printf("Result: %s\nExpected: %s\n", NS_ConvertUTF16toUTF8(result).get(), NS_ConvertUTF16toUTF8(expectedResult).get());
ASSERT_TRUE(expectedResult.Equals(result));
}
TEST(TestXPathGenerator, TestQuoteArgumentWithDoubleQuoteAndASequenceOfSingleQuote)
{
nsAutoString arg;
arg.Assign(NS_LITERAL_STRING("\'\'\'\'testing\""));
nsAutoString expectedResult;
expectedResult.Assign(NS_LITERAL_STRING("concat(\'\',\"\'\'\'\'\",\'testing\"\')"));
nsAutoString result;
XPathGenerator::QuoteArgument(arg, result);
printf("Result: %s\nExpected: %s\n", NS_ConvertUTF16toUTF8(result).get(), NS_ConvertUTF16toUTF8(expectedResult).get());
ASSERT_TRUE(expectedResult.Equals(result));
}
TEST(TestXPathGenerator, TestQuoteArgumentWithDoubleQuoteAndTwoSequencesOfSingleQuote)
{
nsAutoString arg;
arg.Assign(NS_LITERAL_STRING("\'\'\'\'testing\'\'\'\'\'\'\""));
nsAutoString expectedResult;
expectedResult.Assign(NS_LITERAL_STRING("concat(\'\',\"\'\'\'\'\",\'testing\',\"\'\'\'\'\'\'\",\'\"\')"));
nsAutoString result;
XPathGenerator::QuoteArgument(arg, result);
printf("Result: %s\nExpected: %s\n", NS_ConvertUTF16toUTF8(result).get(), NS_ConvertUTF16toUTF8(expectedResult).get());
ASSERT_TRUE(expectedResult.Equals(result));
}
TEST(TestXPathGenerator, TestQuoteArgumentWithDoubleQuoteAndTwoSequencesOfSingleQuoteInMiddle)
{
nsAutoString arg;
arg.Assign(NS_LITERAL_STRING("t\'\'\'\'estin\'\'\'\'\'\'\"g"));
nsAutoString expectedResult;
expectedResult.Assign(NS_LITERAL_STRING("concat(\'t\',\"\'\'\'\'\",\'estin\',\"\'\'\'\'\'\'\",\'\"g\')"));
nsAutoString result;
XPathGenerator::QuoteArgument(arg, result);
printf("Result: %s\nExpected: %s\n", NS_ConvertUTF16toUTF8(result).get(), NS_ConvertUTF16toUTF8(expectedResult).get());
ASSERT_TRUE(expectedResult.Equals(result));
}
TEST(TestXPathGenerator, TestEscapeNameWithNormalCharacters)
{
nsAutoString arg;
arg.Assign(NS_LITERAL_STRING("testing"));
nsAutoString expectedResult;
expectedResult.Assign(NS_LITERAL_STRING("testing"));
nsAutoString result;
XPathGenerator::EscapeName(arg, result);
ASSERT_TRUE(expectedResult.Equals(result));
}
TEST(TestXPathGenerator, TestEscapeNameWithSpecialCharacters)
{
nsAutoString arg;
arg.Assign(NS_LITERAL_STRING("^testing!"));
nsAutoString expectedResult;
expectedResult.Assign(NS_LITERAL_STRING("*[local-name()=\'^testing!\']"));
nsAutoString result;
XPathGenerator::EscapeName(arg, result);
printf("Result: %s\nExpected: %s\n", NS_ConvertUTF16toUTF8(result).get(), NS_ConvertUTF16toUTF8(expectedResult).get());
ASSERT_TRUE(expectedResult.Equals(result));
}

Просмотреть файл

@ -8,6 +8,7 @@ UNIFIED_SOURCES += [
'TestNativeXMLHttpRequest.cpp',
'TestParserDialogOptions.cpp',
'TestPlainTextSerializer.cpp',
'TestXPathGenerator.cpp',
]
LOCAL_INCLUDES += [

Просмотреть файл

@ -0,0 +1,65 @@
function run_test()
{
test_generate_xpath();
}
// TEST CODE
function test_generate_xpath()
{
let docString = `
<html>
<body>
<label><input type="checkbox" id="input1" />Input 1</label>
<label><input type="checkbox" id="input2'" />Input 2</label>
<label><input type="checkbox" id='"input3"' />Input 3</label>
<label><input type="checkbox"/>Input 4</label>
<label><input type="checkbox" />Input 5</label>
</body>
</html>
`;
let doc = DOMParser().parseFromString(docString, "text/html");
// Test generate xpath for body.
do_print("Test generate xpath for body node");
let body = doc.getElementsByTagName("body")[0];
let bodyXPath = body.generateXPath();
let bodyExpXPath = "/xhtml:html/xhtml:body";
equal(bodyExpXPath, bodyXPath, " xpath generated for body");
// Test generate xpath for input with id.
do_print("Test generate xpath for input with id");
let inputWithId = doc.getElementById("input1");
let inputWithIdXPath = inputWithId.generateXPath();
let inputWithIdExpXPath = "//xhtml:input[@id='input1']";
equal(inputWithIdExpXPath, inputWithIdXPath, " xpath generated for input with id");
// Test generate xpath for input with id has single quote.
do_print("Test generate xpath for input with id has single quote");
let inputWithIdSingleQuote = doc.getElementsByTagName("input")[1];
let inputWithIdXPathSingleQuote = inputWithIdSingleQuote.generateXPath();
let inputWithIdExpXPathSingleQuote = '//xhtml:input[@id="input2\'"]';
equal(inputWithIdExpXPathSingleQuote, inputWithIdXPathSingleQuote, " xpath generated for input with id");
// Test generate xpath for input with id has double quote.
do_print("Test generate xpath for input with id has double quote");
let inputWithIdDoubleQuote = doc.getElementsByTagName("input")[2];
let inputWithIdXPathDoubleQuote = inputWithIdDoubleQuote.generateXPath();
let inputWithIdExpXPathDoubleQuote = "//xhtml:input[@id='\"input3\"']";
equal(inputWithIdExpXPathDoubleQuote, inputWithIdXPathDoubleQuote, " xpath generated for input with id");
// Test generate xpath for input with id has both single and double quote.
do_print("Test generate xpath for input with id has single and double quote");
let inputWithIdSingleDoubleQuote = doc.getElementsByTagName("input")[3];
inputWithIdSingleDoubleQuote.setAttribute("id", "\"input'4");
let inputWithIdXPathSingleDoubleQuote = inputWithIdSingleDoubleQuote.generateXPath();
let inputWithIdExpXPathSingleDoubleQuote = "//xhtml:input[@id=concat('\"input',\"'\",'4')]";
equal(inputWithIdExpXPathSingleDoubleQuote, inputWithIdXPathSingleDoubleQuote, " xpath generated for input with id");
// Test generate xpath for input without id.
do_print("Test generate xpath for input without id");
let inputNoId = doc.getElementsByTagName("input")[4];
let inputNoIdXPath = inputNoId.generateXPath();
let inputNoIdExpXPath = "/xhtml:html/xhtml:body/xhtml:label[5]/xhtml:input";
equal(inputNoIdExpXPath, inputNoIdXPath, " xpath generated for input without id");
}

Просмотреть файл

@ -52,3 +52,6 @@ head = head_xml.js
[test_xmlserializer.js]
[test_cancelPrefetch.js]
[test_chromeutils_base64.js]
[test_generate_xpath.js]
head = head_xml.js

Просмотреть файл

@ -764,7 +764,7 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
// different process if we have noopener set, but we also might if we can't
// load in the current process.
bool loadInDifferentProcess = aForceNoOpener && sNoopenerNewProcess;
if (aTabOpener && !loadInDifferentProcess) {
if (aTabOpener && !loadInDifferentProcess && aURI) {
nsCOMPtr<nsIWebBrowserChrome3> browserChrome3;
rv = aTabOpener->GetWebBrowserChrome(getter_AddRefs(browserChrome3));
if (NS_SUCCEEDED(rv) && browserChrome3) {

Просмотреть файл

@ -40,6 +40,9 @@ alert = alert
alertDialog = alert dialog
article = article
document = document
# The (spoken) role description for the WAI-ARIA figure role
# https://w3c.github.io/aria/core-aam/core-aam.html#role-map-figure
figure = figure
# The (spoken) role description for the WAI-ARIA heading role
# https://w3c.github.io/aria/core-aam/core-aam.html#role-map-heading
heading = heading

Просмотреть файл

@ -325,13 +325,10 @@ URLMainThread::UpdateURLSearchParams()
}
nsAutoCString search;
nsCOMPtr<nsIURL> url(do_QueryInterface(mURI));
if (url) {
nsresult rv = url->GetQuery(search);
nsresult rv = mURI->GetQuery(search);
if (NS_WARN_IF(NS_FAILED(rv))) {
search.Truncate();
}
}
mSearchParams->ParseInput(search);
}

Просмотреть файл

@ -47,8 +47,14 @@ function testURL() {
url.searchParams.set('e', 'f');
ok(url.href.indexOf('e=f') != 1, 'URL right');
url = new URL('mailto:a@b.com?subject=Hi');
ok(url.searchParams, "URL searchParams exists!");
ok(url.searchParams.has('subject'), "Hi");
runTest();
}
function testParserURLSearchParams() {
var checks = [
{ input: '', data: {} },

Просмотреть файл

@ -3,6 +3,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// This file defines dictionaries used by about:networking page.
dictionary SocketElement {
DOMString host = "";
unsigned long port = 0;
@ -76,8 +78,18 @@ dictionary ConnStatusDict {
DOMString status = "";
};
dictionary RcwnPerfStats {
unsigned long avgShort = 0;
unsigned long avgLong = 0;
unsigned long stddevLong = 0;
};
dictionary RcwnStatus {
unsigned long totalNetworkRequests = 0;
unsigned long rcwnCacheWonCount = 0;
unsigned long rcwnNetWonCount = 0;
unsigned long cacheSlowCount = 0;
unsigned long cacheNotSlowCount = 0;
// Sequence is indexed by CachePerfStats::EDataType
sequence<RcwnPerfStats> perfStats;
};

Просмотреть файл

@ -108,6 +108,8 @@ interface Node : EventTarget {
readonly attribute URI? baseURIObject;
[ChromeOnly]
sequence<MutationObserver> getBoundMutationObservers();
[ChromeOnly]
DOMString generateXPath();
#ifdef ACCESSIBILITY
[Pref="accessibility.AOM.enabled"]

Просмотреть файл

@ -185,6 +185,10 @@ GetPrincipalFromOrigin(const nsACString& aOrigin, nsIPrincipal** aPrincipal)
return NS_ERROR_FAILURE;
}
// mPrivateBrowsingId must be set to false because PermissionManager is not supposed to have
// any knowledge of private browsing. Allowing it to be true changes the suffix being hashed.
attrs.mPrivateBrowsingId = 0;
// Disable userContext and firstParty isolation for permissions.
attrs.StripAttributes(mozilla::OriginAttributes::STRIP_USER_CONTEXT_ID |
mozilla::OriginAttributes::STRIP_FIRST_PARTY_DOMAIN);
@ -3230,6 +3234,12 @@ nsPermissionManager::GetKeyForOrigin(const nsACString& aOrigin, nsACString& aKey
aKey.Truncate();
return;
}
// mPrivateBrowsingId must be set to false because PermissionManager is not supposed to have
// any knowledge of private browsing. Allowing it to be true changes the suffix being hashed.
attrs.mPrivateBrowsingId = 0;
// Disable userContext and firstParty isolation for permissions.
attrs.StripAttributes(OriginAttributes::STRIP_USER_CONTEXT_ID |
OriginAttributes::STRIP_FIRST_PARTY_DOMAIN);

Просмотреть файл

@ -471,8 +471,29 @@ gfxFontconfigFontEntry::ReleaseGrFace(gr_face* aFace)
double
gfxFontconfigFontEntry::GetAspect()
{
if (mAspect == 0.0) {
// default to aspect = 0.5
if (mAspect != 0.0) {
return mAspect;
}
// try to compute aspect from OS/2 metrics if available
AutoTable os2Table(this, TRUETYPE_TAG('O','S','/','2'));
if (os2Table) {
uint16_t upem = UnitsPerEm();
if (upem != kInvalidUPEM) {
uint32_t len;
auto os2 = reinterpret_cast<const OS2Table*>
(hb_blob_get_data(os2Table, &len));
if (uint16_t(os2->version) >= 2) {
if (len >= offsetof(OS2Table, sxHeight) + sizeof(int16_t) &&
int16_t(os2->sxHeight) > 0.1 * upem) {
mAspect = double(int16_t(os2->sxHeight)) / upem;
return mAspect;
}
}
}
}
// default to aspect = 0.5 if the code below fails
mAspect = 0.5;
// create a font to calculate x-height / em-height
@ -490,7 +511,7 @@ gfxFontconfigFontEntry::GetAspect()
mAspect = metrics.xHeight / metrics.emHeight;
}
}
}
return mAspect;
}

Просмотреть файл

@ -62,4 +62,7 @@ USE_LIBS += [
'mozavutil'
]
if CONFIG['OS_TARGET'] != 'WINNT':
OS_LIBS += ['m']
include("../ffvpxcommon.mozbuild")

Просмотреть файл

@ -54,5 +54,7 @@ SYMBOLS_FILE = 'avutil.symbols'
NO_VISIBILITY_FLAGS = True
OS_LIBS += CONFIG['REALTIME_LIBS']
if CONFIG['OS_TARGET'] != 'WINNT':
OS_LIBS += ['m']
include("../ffvpxcommon.mozbuild")

Просмотреть файл

@ -370,11 +370,14 @@ PeerConnectionMedia::InitProxy()
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIEventTarget> target = mParent->GetWindow()
? mParent->GetWindow()->EventTargetFor(TaskCategory::Network)
: nullptr;
RefPtr<ProtocolProxyQueryHandler> handler = new ProtocolProxyQueryHandler(this);
rv = pps->AsyncResolve(channel,
nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL,
handler, getter_AddRefs(mProxyRequest));
handler, target, getter_AddRefs(mProxyRequest));
if (NS_FAILED(rv)) {
CSFLogError(logTag, "%s: Failed to resolve protocol proxy: %d", __FUNCTION__, (int)rv);
return NS_ERROR_FAILURE;

Просмотреть файл

@ -20,6 +20,7 @@
#include "nsURLHelper.h"
#include "mozilla/Logging.h"
#include "nsIOService.h"
#include "../cache2/CacheFileUtils.h"
using mozilla::AutoSafeJSContext;
using mozilla::dom::Sequence;
@ -822,6 +823,28 @@ Dashboard::GetRcwnData(RcwnData *aData)
dict.mRcwnCacheWonCount = gIOService->GetCacheWonRequestNumber();
dict.mRcwnNetWonCount = gIOService->GetNetWonRequestNumber();
uint32_t cacheSlow, cacheNotSlow;
CacheFileUtils::CachePerfStats::GetSlowStats(&cacheSlow, &cacheNotSlow);
dict.mCacheSlowCount = cacheSlow;
dict.mCacheNotSlowCount = cacheNotSlow;
dict.mPerfStats.Construct();
Sequence<mozilla::dom::RcwnPerfStats> &perfStats = dict.mPerfStats.Value();
uint32_t length = CacheFileUtils::CachePerfStats::LAST;
if (!perfStats.SetCapacity(length, fallible)) {
JS_ReportOutOfMemory(cx);
return NS_ERROR_OUT_OF_MEMORY;
}
for (uint32_t i = 0; i < length; i++) {
CacheFileUtils::CachePerfStats::EDataType perfType =
static_cast<CacheFileUtils::CachePerfStats::EDataType>(i);
dom::RcwnPerfStats &elem = *perfStats.AppendElement(fallible);
elem.mAvgShort = CacheFileUtils::CachePerfStats::GetAverage(perfType, false);
elem.mAvgLong = CacheFileUtils::CachePerfStats::GetAverage(perfType, true);
elem.mStddevLong = CacheFileUtils::CachePerfStats::GetStdDev(perfType, true);
}
JS::RootedValue val(cx);
if (!ToJSValue(cx, dict, &val)) {
return NS_ERROR_FAILURE;

Просмотреть файл

@ -269,8 +269,9 @@ class PACResolver final : public nsIDNSListener
public:
NS_DECL_THREADSAFE_ISUPPORTS
PACResolver()
explicit PACResolver(nsIEventTarget *aTarget)
: mStatus(NS_ERROR_FAILURE)
, mMainThreadEventTarget(aTarget)
{
}
@ -303,6 +304,7 @@ public:
nsCOMPtr<nsICancelable> mRequest;
nsCOMPtr<nsIDNSRecord> mResponse;
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
private:
~PACResolver() {}
@ -405,7 +407,7 @@ ProxyAutoConfig::ResolveAddress(const nsCString &aHostName,
if (!dns)
return false;
RefPtr<PACResolver> helper = new PACResolver();
RefPtr<PACResolver> helper = new PACResolver(mMainThreadEventTarget);
OriginAttributes attrs;
if (NS_FAILED(dns->AsyncResolveNative(aHostName,
@ -420,6 +422,7 @@ ProxyAutoConfig::ResolveAddress(const nsCString &aHostName,
if (!mTimer)
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
if (mTimer) {
mTimer->SetTarget(mMainThreadEventTarget);
mTimer->InitWithCallback(helper, aTimeout, nsITimer::TYPE_ONE_SHOT);
helper->mTimer = mTimer;
}
@ -678,13 +681,15 @@ nsresult
ProxyAutoConfig::Init(const nsCString &aPACURI,
const nsCString &aPACScript,
bool aIncludePath,
uint32_t aExtraHeapSize)
uint32_t aExtraHeapSize,
nsIEventTarget *aEventTarget)
{
mPACURI = aPACURI;
mPACScript = sPacUtils;
mPACScript.Append(aPACScript);
mIncludePath = aIncludePath;
mExtraHeapSize = aExtraHeapSize;
mMainThreadEventTarget = aEventTarget;
if (!GetRunning())
return SetupJS();

Просмотреть файл

@ -10,6 +10,7 @@
#include "nsString.h"
#include "nsCOMPtr.h"
class nsIEventTarget;
class nsITimer;
namespace JS {
class CallArgs;
@ -32,7 +33,8 @@ public:
nsresult Init(const nsCString &aPACURI,
const nsCString &aPACScript,
bool aIncludePath,
uint32_t aExtraHeapSize);
uint32_t aExtraHeapSize,
nsIEventTarget *aEventTarget);
void SetThreadLocalIndex(uint32_t index);
void Shutdown();
void GC();
@ -98,6 +100,7 @@ private:
uint32_t mExtraHeapSize;
nsCString mRunningHost;
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
};
} // namespace net

Просмотреть файл

@ -63,15 +63,20 @@ nsAsyncRedirectVerifyHelper::~nsAsyncRedirectVerifyHelper()
}
nsresult
nsAsyncRedirectVerifyHelper::Init(nsIChannel* oldChan, nsIChannel* newChan,
uint32_t flags, bool synchronize)
nsAsyncRedirectVerifyHelper::Init(nsIChannel* oldChan,
nsIChannel* newChan,
uint32_t flags,
nsIEventTarget* mainThreadEventTarget,
bool synchronize)
{
LOG(("nsAsyncRedirectVerifyHelper::Init() "
"oldChan=%p newChan=%p", oldChan, newChan));
mOldChan = oldChan;
mNewChan = newChan;
mFlags = flags;
mCallbackEventTarget = GetCurrentThreadEventTarget();
mCallbackEventTarget = NS_IsMainThread() && mainThreadEventTarget
? mainThreadEventTarget
: GetCurrentThreadEventTarget();
if (!(flags & (nsIChannelEventSink::REDIRECT_INTERNAL |
nsIChannelEventSink::REDIRECT_STS_UPGRADE))) {
@ -85,8 +90,11 @@ nsAsyncRedirectVerifyHelper::Init(nsIChannel* oldChan, nsIChannel* newChan,
if (synchronize)
mWaitingForRedirectCallback = true;
nsCOMPtr<nsIRunnable> runnable = this;
nsresult rv;
rv = NS_DispatchToMainThread(this);
rv = mainThreadEventTarget
? mainThreadEventTarget->Dispatch(runnable.forget())
: GetMainThreadEventTarget()->Dispatch(runnable.forget());
NS_ENSURE_SUCCESS(rv, rv);
if (synchronize) {

Просмотреть файл

@ -59,6 +59,8 @@ public:
* target of the redirect channel
* @param flags
* redirect flags
* @param mainThreadEventTarget
* a labeled event target for dispatching runnables
* @param synchronize
* set to TRUE if you want the Init method wait synchronously for
* all redirect callbacks
@ -66,6 +68,7 @@ public:
nsresult Init(nsIChannel* oldChan,
nsIChannel* newChan,
uint32_t flags,
nsIEventTarget* mainThreadEventTarget,
bool synchronize = false);
protected:

Просмотреть файл

@ -52,7 +52,8 @@ private:
// nsBaseChannel
nsBaseChannel::nsBaseChannel()
: mPumpingData(false)
: NeckoTargetHolder(nullptr)
, mPumpingData(false)
, mLoadFlags(LOAD_NORMAL)
, mQueriedProgressSink(true)
, mSynthProgressEvents(false)
@ -138,12 +139,13 @@ nsBaseChannel::Redirect(nsIChannel *newChannel, uint32_t redirectFlags,
new nsAsyncRedirectVerifyHelper();
bool checkRedirectSynchronously = !openNewChannel;
nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
mRedirectChannel = newChannel;
mRedirectFlags = redirectFlags;
mOpenRedirectChannel = openNewChannel;
nsresult rv = redirectCallbackHelper->Init(this, newChannel, redirectFlags,
checkRedirectSynchronously);
target, checkRedirectSynchronously);
if (NS_FAILED(rv))
return rv;
@ -261,7 +263,8 @@ nsBaseChannel::BeginPumpingData()
NS_ASSERTION(!stream || !channel, "Got both a channel and a stream?");
if (channel) {
rv = NS_DispatchToCurrentThread(new RedirectRunnable(this, channel));
nsCOMPtr<nsIRunnable> runnable = new RedirectRunnable(this, channel);
rv = Dispatch(runnable.forget());
if (NS_SUCCEEDED(rv))
mWaitingOnAsyncRedirect = true;
return rv;
@ -273,8 +276,7 @@ nsBaseChannel::BeginPumpingData()
// and especially when we call into the loadgroup. Our caller takes care to
// release mPump if we return an error.
nsCOMPtr<nsIEventTarget> target =
nsContentUtils::GetEventTargetByLoadInfo(mLoadInfo, TaskCategory::Other);
nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
rv = nsInputStreamPump::Create(getter_AddRefs(mPump), stream, -1, -1, 0, 0,
true, target);
if (NS_SUCCEEDED(rv)) {
@ -503,6 +505,9 @@ NS_IMETHODIMP
nsBaseChannel::SetLoadInfo(nsILoadInfo* aLoadInfo)
{
mLoadInfo = aLoadInfo;
// Need to update |mNeckoTarget| when load info has changed.
SetupNeckoTarget();
return NS_OK;
}
@ -683,6 +688,8 @@ nsBaseChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
NS_ENSURE_ARG(listener);
SetupNeckoTarget();
// Skip checking for chrome:// sub-resources.
nsAutoCString scheme;
mURI->GetScheme(scheme);
@ -923,7 +930,7 @@ nsBaseChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
nsCOMPtr<nsIRunnable> runnable =
new OnTransportStatusAsyncEvent(this, prog, mContentLength);
NS_DispatchToMainThread(runnable);
Dispatch(runnable.forget());
}
}
@ -982,3 +989,10 @@ nsBaseChannel::CheckListenerChain()
return listener->CheckListenerChain();
}
void
nsBaseChannel::SetupNeckoTarget()
{
mNeckoTarget =
nsContentUtils::GetEventTargetByLoadInfo(mLoadInfo, TaskCategory::Other);
}

Просмотреть файл

@ -6,6 +6,7 @@
#ifndef nsBaseChannel_h__
#define nsBaseChannel_h__
#include "mozilla/net/NeckoTargetHolder.h"
#include "nsString.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
@ -47,6 +48,7 @@ class nsBaseChannel : public nsHashPropertyBag
, public nsITransportEventSink
, public nsIAsyncVerifyRedirectCallback
, public mozilla::net::PrivateBrowsingChannel<nsBaseChannel>
, public mozilla::net::NeckoTargetHolder
, protected nsIStreamListener
, protected nsIThreadRetargetableStreamListener
{
@ -227,6 +229,8 @@ protected:
mAllowThreadRetargeting = false;
}
virtual void SetupNeckoTarget();
private:
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER

Просмотреть файл

@ -1892,9 +1892,11 @@ nsIOService::SpeculativeConnectInternal(nsIURI *aURI,
new IOServiceProxyCallback(aCallbacks, this);
nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
if (pps2) {
return pps2->AsyncResolve2(channel, 0, callback, getter_AddRefs(cancelable));
return pps2->AsyncResolve2(channel, 0, callback, nullptr,
getter_AddRefs(cancelable));
}
return pps->AsyncResolve(channel, 0, callback, getter_AddRefs(cancelable));
return pps->AsyncResolve(channel, 0, callback, nullptr,
getter_AddRefs(cancelable));
}
NS_IMETHODIMP

Просмотреть файл

@ -13,6 +13,7 @@ interface nsIProtocolProxyChannelFilter;
interface nsIProxyInfo;
interface nsIChannel;
interface nsIURI;
interface nsIEventTarget;
/**
* nsIProtocolProxyService provides methods to access information about
@ -79,6 +80,8 @@ interface nsIProtocolProxyService : nsISupports
* not correspond to a RESOLVE_ flag are reserved for future use.
* @param aCallback
* The object to be notified when the result is available.
* @param aMainThreadTarget
* A labelled event target for dispatching runnables to main thread.
*
* @return An object that can be used to cancel the asychronous operation.
* If canceled, the cancelation status (aReason) will be forwarded
@ -99,7 +102,8 @@ interface nsIProtocolProxyService : nsISupports
* @see nsIProxiedProtocolHandler::newProxiedChannel
*/
nsICancelable asyncResolve(in nsISupports aChannelOrURI, in unsigned long aFlags,
in nsIProtocolProxyCallback aCallback);
in nsIProtocolProxyCallback aCallback,
[optional] in nsIEventTarget aMainThreadTarget);
/**
* This method may be called to construct a nsIProxyInfo instance from

Просмотреть файл

@ -26,5 +26,6 @@ interface nsIProtocolProxyService2 : nsIProtocolProxyService
* The nsICancelable return value will be null in that case.
*/
nsICancelable asyncResolve2(in nsIChannel aChannel, in unsigned long aFlags,
in nsIProtocolProxyCallback aCallback);
in nsIProtocolProxyCallback aCallback,
[optional] in nsIEventTarget aMainThreadTarget);
};

Просмотреть файл

@ -242,13 +242,15 @@ public:
if (mSetupPAC) {
mSetupPAC = false;
nsCOMPtr<nsIEventTarget> target = mPACMan->GetNeckoTarget();
mPACMan->mPAC.Init(mSetupPACURI,
mSetupPACData,
mPACMan->mIncludePath,
mExtraHeapSize);
mExtraHeapSize,
target);
RefPtr<PACLoadComplete> runnable = new PACLoadComplete(mPACMan);
NS_DispatchToMainThread(runnable);
mPACMan->Dispatch(runnable.forget());
return NS_OK;
}
@ -293,7 +295,7 @@ PendingPACQuery::Complete(nsresult status, const nsCString &pacString)
RefPtr<ExecuteCallback> runnable = new ExecuteCallback(mCallback, status);
runnable->SetPACString(pacString);
if (mOnMainThreadOnly)
NS_DispatchToMainThread(runnable);
mPACMan->Dispatch(runnable.forget());
else
runnable->Run();
}
@ -307,7 +309,7 @@ PendingPACQuery::UseAlternatePACFile(const nsCString &pacURL)
RefPtr<ExecuteCallback> runnable = new ExecuteCallback(mCallback, NS_OK);
runnable->SetPACURL(pacURL);
if (mOnMainThreadOnly)
NS_DispatchToMainThread(runnable);
mPACMan->Dispatch(runnable.forget());
else
runnable->Run();
}
@ -328,8 +330,9 @@ static uint32_t sThreadLocalIndex = 0xdeadbeef; // out of range
static const char *kPACIncludePath =
"network.proxy.autoconfig_url.include_path";
nsPACMan::nsPACMan()
: mLoadPending(false)
nsPACMan::nsPACMan(nsIEventTarget *mainThreadEventTarget)
: NeckoTargetHolder(mainThreadEventTarget)
, mLoadPending(false)
, mShutdown(false)
, mLoadFailureCount(0)
, mInProgress(false)
@ -351,7 +354,7 @@ nsPACMan::~nsPACMan()
}
else {
RefPtr<ShutdownThread> runnable = new ShutdownThread(mPACThread);
NS_DispatchToMainThread(runnable);
Dispatch(runnable.forget());
}
}
@ -371,7 +374,7 @@ nsPACMan::Shutdown()
PostCancelPendingQ(NS_ERROR_ABORT);
RefPtr<WaitForThreadShutdown> runnable = new WaitForThreadShutdown(this);
NS_DispatchToMainThread(runnable);
Dispatch(runnable.forget());
}
nsresult
@ -438,9 +441,12 @@ nsPACMan::LoadPACFromURI(const nsCString &spec)
// queries the enter between now and when we actually load the PAC file.
if (!mLoadPending) {
nsresult rv;
if (NS_FAILED(rv = NS_DispatchToCurrentThread(NewRunnableMethod("nsPACMan::StartLoading",
this, &nsPACMan::StartLoading))))
nsCOMPtr<nsIRunnable> runnable =
NewRunnableMethod("nsPACMan::StartLoading", this, &nsPACMan::StartLoading);
nsresult rv = NS_IsMainThread()
? Dispatch(runnable.forget())
: GetCurrentThreadEventTarget()->Dispatch(runnable.forget());
if (NS_FAILED(rv))
return rv;
mLoadPending = true;
}

Просмотреть файл

@ -21,6 +21,7 @@
#include "mozilla/TimeStamp.h"
#include "mozilla/Logging.h"
#include "mozilla/Atomics.h"
#include "mozilla/net/NeckoTargetHolder.h"
class nsISystemProxySettings;
class nsIThread;
@ -90,11 +91,12 @@ private:
class nsPACMan final : public nsIStreamLoaderObserver
, public nsIInterfaceRequestor
, public nsIChannelEventSink
, public NeckoTargetHolder
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
nsPACMan();
explicit nsPACMan(nsIEventTarget *mainThreadEventTarget);
/**
* This method may be called to shutdown the PAC manager. Any async queries

Просмотреть файл

@ -1147,7 +1147,7 @@ nsProtocolProxyService::IsProxyDisabled(nsProxyInfo *pi)
}
nsresult
nsProtocolProxyService::SetupPACThread()
nsProtocolProxyService::SetupPACThread(nsIEventTarget *mainThreadEventTarget)
{
if (mIsShutdown) {
return NS_ERROR_FAILURE;
@ -1156,7 +1156,7 @@ nsProtocolProxyService::SetupPACThread()
if (mPACMan)
return NS_OK;
mPACMan = new nsPACMan();
mPACMan = new nsPACMan(mainThreadEventTarget);
bool mainThreadOnly;
nsresult rv;
@ -1319,7 +1319,8 @@ nsresult
nsProtocolProxyService::AsyncResolveInternal(nsIChannel *channel, uint32_t flags,
nsIProtocolProxyCallback *callback,
nsICancelable **result,
bool isSyncOK)
bool isSyncOK,
nsIEventTarget *mainThreadEventTarget)
{
NS_ENSURE_ARG_POINTER(channel);
NS_ENSURE_ARG_POINTER(callback);
@ -1350,6 +1351,11 @@ nsProtocolProxyService::AsyncResolveInternal(nsIChannel *channel, uint32_t flags
}
}
rv = SetupPACThread(mainThreadEventTarget);
if (NS_FAILED(rv)) {
return rv;
}
// SystemProxySettings and PAC files can block the main thread
// but if neither of them are in use, we can just do the work
// right here and directly invoke the callback
@ -1386,14 +1392,17 @@ nsProtocolProxyService::AsyncResolveInternal(nsIChannel *channel, uint32_t flags
NS_IMETHODIMP
nsProtocolProxyService::AsyncResolve2(nsIChannel *channel, uint32_t flags,
nsIProtocolProxyCallback *callback,
nsIEventTarget *mainThreadEventTarget,
nsICancelable **result)
{
return AsyncResolveInternal(channel, flags, callback, result, true);
return AsyncResolveInternal(channel, flags, callback,
result, true, mainThreadEventTarget);
}
NS_IMETHODIMP
nsProtocolProxyService::AsyncResolve(nsISupports *channelOrURI, uint32_t flags,
nsIProtocolProxyCallback *callback,
nsIEventTarget *mainThreadEventTarget,
nsICancelable **result)
{
@ -1424,7 +1433,8 @@ nsProtocolProxyService::AsyncResolve(nsISupports *channelOrURI, uint32_t flags,
NS_ENSURE_SUCCESS(rv, rv);
}
return AsyncResolveInternal(channel, flags, callback, result, false);
return AsyncResolveInternal(channel, flags, callback,
result, false, mainThreadEventTarget);
}
NS_IMETHODIMP
@ -1914,9 +1924,6 @@ nsProtocolProxyService::Resolve_Internal(nsIChannel *channel,
nsIProxyInfo **result)
{
NS_ENSURE_ARG_POINTER(channel);
nsresult rv = SetupPACThread();
if (NS_FAILED(rv))
return rv;
*usePACThread = false;
*result = nullptr;
@ -1925,7 +1932,7 @@ nsProtocolProxyService::Resolve_Internal(nsIChannel *channel,
return NS_OK; // Can't proxy this (filters may not override)
nsCOMPtr<nsIURI> uri;
rv = GetProxyURI(channel, getter_AddRefs(uri));
nsresult rv = GetProxyURI(channel, getter_AddRefs(uri));
if (NS_FAILED(rv)) return rv;
// See bug #586908.

Просмотреть файл

@ -298,7 +298,7 @@ protected:
void MaybeDisableDNSPrefetch(nsIProxyInfo *aProxy);
private:
nsresult SetupPACThread();
nsresult SetupPACThread(nsIEventTarget *mainThreadEventTarget = nullptr);
nsresult ResetPACThread();
nsresult ReloadNetworkPAC();
@ -406,7 +406,8 @@ private:
nsresult AsyncResolveInternal(nsIChannel *channel, uint32_t flags,
nsIProtocolProxyCallback *callback,
nsICancelable **result,
bool isSyncOK);
bool isSyncOK,
nsIEventTarget *mainThreadEventTarget);
bool mIsShutdown;
nsCOMPtr<nsIThread> mProxySettingThread;
};

Просмотреть файл

@ -900,6 +900,16 @@ CacheFile::OpenOutputStream(CacheOutputCloseListener *aCloseListener, nsIOutputS
return NS_ERROR_NOT_AVAILABLE;
}
if (NS_FAILED(mStatus)) {
LOG(("CacheFile::OpenOutputStream() - CacheFile is in a failure state "
"[this=%p, status=0x%08" PRIx32 "]", this,
static_cast<uint32_t>(mStatus)));
// The CacheFile is already doomed. It make no sense to allow to write any
// data to such entry.
return mStatus;
}
// Fail if there is any input stream opened for alternative data
for (uint32_t i = 0; i < mInputs.Length(); ++i) {
if (mInputs[i]->IsAlternativeData()) {
@ -958,6 +968,16 @@ CacheFile::OpenAlternativeOutputStream(CacheOutputCloseListener *aCloseListener,
return NS_ERROR_NOT_AVAILABLE;
}
if (NS_FAILED(mStatus)) {
LOG(("CacheFile::OpenAlternativeOutputStream() - CacheFile is in a failure "
"state [this=%p, status=0x%08" PRIx32 "]", this,
static_cast<uint32_t>(mStatus)));
// The CacheFile is already doomed. It make no sense to allow to write any
// data to such entry.
return mStatus;
}
// Fail if there is any input stream opened for alternative data
for (uint32_t i = 0; i < mInputs.Length(); ++i) {
if (mInputs[i]->IsAlternativeData()) {
@ -1982,9 +2002,9 @@ CacheFile::Truncate(int64_t aOffset)
MOZ_RELEASE_ASSERT(bytesInNewLastChunk == kChunkSize);
newLastChunk++;
bytesInNewLastChunk = 0;
LOG(("CacheFileTruncate() - chunk %p is still in use, using newLastChunk=%u"
" and bytesInNewLastChunk=%u", mChunks.GetWeak(newLastChunk),
newLastChunk, bytesInNewLastChunk));
LOG(("CacheFile::Truncate() - chunk %p is still in use, using "
"newLastChunk=%u and bytesInNewLastChunk=%u",
mChunks.GetWeak(newLastChunk), newLastChunk, bytesInNewLastChunk));
}
// Discard all truncated chunks in mChunks

Просмотреть файл

@ -567,7 +567,6 @@ CacheFileChunk::Index() const
CacheHash::Hash16_t
CacheFileChunk::Hash() const
{
MOZ_ASSERT(!mListener);
MOZ_ASSERT(IsReady());
return CacheHash::Hash16(mBuf->Buf(), mBuf->DataSize());

Просмотреть файл

@ -513,6 +513,8 @@ DetailedCacheHitTelemetry::AddRecord(ERecType aType, TimeStamp aLoadStart)
StaticMutex CachePerfStats::sLock;
CachePerfStats::PerfData CachePerfStats::sData[CachePerfStats::LAST];
uint32_t CachePerfStats::sCacheSlowCnt = 0;
uint32_t CachePerfStats::sCacheNotSlowCnt = 0;
CachePerfStats::MMA::MMA(uint32_t aTotalWeight, bool aFilter)
: mSum(0)
@ -636,6 +638,14 @@ CachePerfStats::GetAverage(EDataType aType, bool aFiltered)
return sData[aType].GetAverage(aFiltered);
}
// static
uint32_t
CachePerfStats::GetStdDev(EDataType aType, bool aFiltered)
{
StaticMutexAutoLock lock(sLock);
return sData[aType].GetStdDev(aFiltered);
}
//static
bool
CachePerfStats::IsCacheSlow()
@ -654,13 +664,26 @@ CachePerfStats::IsCacheSlow()
uint32_t maxdiff = (avgLong / 4) + (2 * stddevLong);
if (avgShort > avgLong + maxdiff) {
LOG(("CachePerfStats::IsCacheSlow() - result is slow based on perf "
"type %u [avgShort=%u, avgLong=%u, stddevLong=%u]", i, avgShort,
avgLong, stddevLong));
++sCacheSlowCnt;
return true;
}
}
++sCacheNotSlowCnt;
return false;
}
//static
void
CachePerfStats::GetSlowStats(uint32_t *aSlow, uint32_t *aNotSlow)
{
*aSlow = sCacheSlowCnt;
*aNotSlow = sCacheNotSlowCnt;
}
void
FreeBuffer(void *aBuf) {
#ifndef NS_FREE_PERMANENT_DATA

Просмотреть файл

@ -150,6 +150,8 @@ private:
class CachePerfStats {
public:
// perfStatTypes in displayRcwnStats() in toolkit/content/aboutNetworking.js
// must match EDataType
enum EDataType {
IO_OPEN = 0,
IO_READ = 1,
@ -160,7 +162,9 @@ public:
static void AddValue(EDataType aType, uint32_t aValue, bool aShortOnly);
static uint32_t GetAverage(EDataType aType, bool aFiltered);
static uint32_t GetStdDev(EDataType aType, bool aFiltered);
static bool IsCacheSlow();
static void GetSlowStats(uint32_t *aSlow, uint32_t *aNotSlow);
private:
@ -211,6 +215,8 @@ private:
static StaticMutex sLock;
static PerfData sData[LAST];
static uint32_t sCacheSlowCnt;
static uint32_t sCacheNotSlowCnt;
};
void

Просмотреть файл

@ -5,7 +5,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/SystemGroup.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/ChannelDiverterChild.h"
#include "mozilla/net/FTPChannelChild.h"
@ -34,8 +33,7 @@ namespace mozilla {
namespace net {
FTPChannelChild::FTPChannelChild(nsIURI* uri)
: NeckoTargetHolder(nullptr)
, mIPCOpen(false)
: mIPCOpen(false)
, mUnknownDecoderInvolved(false)
, mCanceled(false)
, mSuspendCount(0)
@ -206,7 +204,7 @@ FTPChannelChild::AsyncOpen(::nsIStreamListener* listener, nsISupports* aContext)
NS_ENSURE_SUCCESS(rv, rv);
// This must happen before the constructor message is sent.
EnsureNeckoTarget();
SetupNeckoTarget();
gNeckoChild->
SendPFTPChannelConstructor(this, tabChild, IPC::SerializedLoadContext(this),
@ -615,15 +613,7 @@ FTPChannelChild::DoOnStopRequest(const nsresult& aChannelStatus,
NS_ConvertASCIItoUTF16(aErrorMsg));
}
if (mNeckoTarget) {
mNeckoTarget->Dispatch(alertEvent.forget(),
nsIEventTarget::DISPATCH_NORMAL);
} else {
// In case |mNeckoTarget| is null, dispatch by SystemGroup.
SystemGroup::Dispatch("FTPAlertEvent",
TaskCategory::Other,
alertEvent.forget());
}
Dispatch(alertEvent.forget());
}
}
@ -837,7 +827,7 @@ FTPChannelChild::ConnectParent(uint32_t id)
}
// This must happen before the constructor message is sent.
EnsureNeckoTarget();
SetupNeckoTarget();
// The socket transport in the chrome process now holds a logical ref to us
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
@ -946,7 +936,7 @@ FTPChannelChild::GetDivertingToParent(bool* aDiverting)
}
void
FTPChannelChild::EnsureNeckoTarget()
FTPChannelChild::SetupNeckoTarget()
{
if (mNeckoTarget) {
return;

Просмотреть файл

@ -11,7 +11,6 @@
#include "mozilla/UniquePtr.h"
#include "mozilla/net/PFTPChannelChild.h"
#include "mozilla/net/ChannelEventQueue.h"
#include "mozilla/net/NeckoTargetHolder.h"
#include "nsBaseChannel.h"
#include "nsIFTPChannel.h"
#include "nsIUploadChannel.h"
@ -43,7 +42,6 @@ class FTPChannelChild final : public PFTPChannelChild
, public nsIProxiedChannel
, public nsIChildChannel
, public nsIDivertableChannel
, public NeckoTargetHolder
{
public:
typedef ::nsIStreamListener nsIStreamListener;
@ -120,6 +118,8 @@ protected:
void DoFailedAsyncOpen(const nsresult& statusCode);
void DoDeleteSelf();
void SetupNeckoTarget() override;
friend class FTPStartRequestEvent;
friend class FTPDataAvailableEvent;
friend class MaybeDivertOnDataFTPEvent;
@ -158,8 +158,6 @@ private:
// Set if SendSuspend is called. Determines if SendResume is needed when
// diverting callbacks to parent.
bool mSuspendSent;
void EnsureNeckoTarget();
};
inline bool

Просмотреть файл

@ -1706,7 +1706,7 @@ nsFtpState::Init(nsFtpChannel *channel)
do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
if (pps && !mChannel->ProxyInfo()) {
pps->AsyncResolve(static_cast<nsIChannel*>(mChannel), 0, this,
pps->AsyncResolve(static_cast<nsIChannel*>(mChannel), 0, this, nullptr,
getter_AddRefs(mProxyRequest));
}

Просмотреть файл

@ -1629,7 +1629,14 @@ HttpChannelChild::Redirect1Begin(const uint32_t& registrarId,
}
mRedirectChannelChild->ConnectParent(registrarId);
}
rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, redirectFlags);
nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
MOZ_ASSERT(target);
rv = gHttpHandler->AsyncOnChannelRedirect(this,
newChannel,
redirectFlags,
target);
}
if (NS_FAILED(rv))
@ -1659,9 +1666,13 @@ HttpChannelChild::BeginNonIPCRedirect(nsIURI* responseURI,
httpChannelChild->OverrideSecurityInfoForNonIPCRedirect(mSecurityInfo);
}
nsCOMPtr<nsIEventTarget> target = GetNeckoTarget();
MOZ_ASSERT(target);
rv = gHttpHandler->AsyncOnChannelRedirect(this,
newChannel,
nsIChannelEventSink::REDIRECT_INTERNAL);
nsIChannelEventSink::REDIRECT_INTERNAL,
target);
}
if (NS_FAILED(rv))

Просмотреть файл

@ -302,6 +302,7 @@ nsHttpChannel::nsHttpChannel()
, mIsReadingFromCache(false)
, mOnCacheAvailableCalled(false)
, mRaceCacheWithNetwork(false)
, mRaceDelay(0)
, mCacheAsyncOpenCalled(false)
, mDidReval(false)
{
@ -3012,11 +3013,11 @@ nsHttpChannel::ResolveProxy()
// then it is ok to use that version.
nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
if (pps2) {
rv = pps2->AsyncResolve2(this, mProxyResolveFlags,
this, getter_AddRefs(mProxyRequest));
rv = pps2->AsyncResolve2(this, mProxyResolveFlags, this,
nullptr, getter_AddRefs(mProxyRequest));
} else {
rv = pps->AsyncResolve(static_cast<nsIChannel*>(this), mProxyResolveFlags,
this, getter_AddRefs(mProxyRequest));
this, nullptr, getter_AddRefs(mProxyRequest));
}
return rv;
@ -8982,29 +8983,37 @@ nsHttpChannel::ReportRcwnStats(nsIRequest* firstResponseRequest, bool isFromNet)
kDidNotRaceUsedNetwork = 0,
kDidNotRaceUsedCache = 1,
kRaceUsedNetwork = 2,
kRaceUsedCache = 3
kRaceUsedCache = 3,
kDelayedRaceUsedNetwork = 4,
kDelayedRaceUsedCache = 5
};
static const Telemetry::HistogramID kRcwnTelemetry[4] = {
static const Telemetry::HistogramID kRcwnTelemetry[6] = {
Telemetry::NETWORK_RACE_CACHE_BANDWIDTH_NOT_RACE,
Telemetry::NETWORK_RACE_CACHE_BANDWIDTH_NOT_RACE,
Telemetry::NETWORK_RACE_CACHE_BANDWIDTH_RACE_NETWORK_WIN,
Telemetry::NETWORK_RACE_CACHE_BANDWIDTH_RACE_CACHE_WIN,
Telemetry::NETWORK_RACE_CACHE_BANDWIDTH_RACE_NETWORK_WIN,
Telemetry::NETWORK_RACE_CACHE_BANDWIDTH_RACE_CACHE_WIN
};
RaceCacheAndNetStatus rcwnStatus = kDidNotRaceUsedNetwork;
if (isFromNet) {
rcwnStatus = mRaceCacheWithNetwork ? kRaceUsedNetwork : kDidNotRaceUsedNetwork;
rcwnStatus = mRaceCacheWithNetwork ?
(mRaceDelay ? kDelayedRaceUsedNetwork : kRaceUsedNetwork) :
kDidNotRaceUsedNetwork;
} else if (firstResponseRequest == mCachePump) {
rcwnStatus = mRaceCacheWithNetwork ? kRaceUsedCache : kDidNotRaceUsedCache;
rcwnStatus = mRaceCacheWithNetwork ?
(mRaceDelay ? kDelayedRaceUsedCache : kRaceUsedCache) :
kDidNotRaceUsedCache;
}
Telemetry::Accumulate(Telemetry::NETWORK_RACE_CACHE_WITH_NETWORK_USAGE,
rcwnStatus);
Telemetry::Accumulate(kRcwnTelemetry[rcwnStatus], mTransferSize);
gIOService->IncrementRequestNumber();
if (rcwnStatus == kRaceUsedCache) {
if (rcwnStatus == kRaceUsedCache || rcwnStatus == kDelayedRaceUsedCache) {
gIOService->IncrementCacheWonRequestNumber();
} else if (rcwnStatus == kRaceUsedNetwork) {
} else if (rcwnStatus == kRaceUsedNetwork || rcwnStatus == kDelayedRaceUsedNetwork) {
gIOService->IncrementNetWonRequestNumber();
}
}
@ -9232,24 +9241,23 @@ nsHttpChannel::MaybeRaceCacheWithNetwork()
return NS_OK;
}
uint32_t delay;
if (CacheFileUtils::CachePerfStats::IsCacheSlow()) {
// If the cache is slow, trigger the network request immediately.
delay = 0;
mRaceDelay = 0;
} else {
// Give cache a headstart of 3 times the average cache entry open time.
delay = CacheFileUtils::CachePerfStats::GetAverage(
mRaceDelay = CacheFileUtils::CachePerfStats::GetAverage(
CacheFileUtils::CachePerfStats::ENTRY_OPEN, true) * 3;
// We use microseconds in CachePerfStats but we need milliseconds
// for TriggerNetwork.
delay /= 1000;
mRaceDelay /= 1000;
}
MOZ_ASSERT(sRCWNEnabled, "The pref must be truned on.");
LOG(("nsHttpChannel::MaybeRaceCacheWithNetwork [this=%p, delay=%u]\n",
this, delay));
this, mRaceDelay));
return TriggerNetwork(delay);
return TriggerNetwork(mRaceDelay);
}
NS_IMETHODIMP

Просмотреть файл

@ -708,6 +708,7 @@ private:
// Will be true if the onCacheEntryAvailable callback is not called by the
// time we send the network request
Atomic<bool> mRaceCacheWithNetwork;
uint32_t mRaceDelay;
bool mCacheAsyncOpenCalled;
protected:

Просмотреть файл

@ -770,14 +770,19 @@ nsHttpHandler::NotifyObservers(nsIHttpChannel *chan, const char *event)
}
nsresult
nsHttpHandler::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
uint32_t flags)
nsHttpHandler::AsyncOnChannelRedirect(nsIChannel* oldChan,
nsIChannel* newChan,
uint32_t flags,
nsIEventTarget* mainThreadEventTarget)
{
// TODO E10S This helper has to be initialized on the other process
RefPtr<nsAsyncRedirectVerifyHelper> redirectCallbackHelper =
new nsAsyncRedirectVerifyHelper();
return redirectCallbackHelper->Init(oldChan, newChan, flags);
return redirectCallbackHelper->Init(oldChan,
newChan,
flags,
mainThreadEventTarget);
}
/* static */ nsresult

Просмотреть файл

@ -331,9 +331,11 @@ public:
// Called by channels before a redirect happens. This notifies both the
// channel's and the global redirect observers.
MOZ_MUST_USE nsresult AsyncOnChannelRedirect(nsIChannel* oldChan,
MOZ_MUST_USE nsresult AsyncOnChannelRedirect(
nsIChannel* oldChan,
nsIChannel* newChan,
uint32_t flags);
uint32_t flags,
nsIEventTarget* mainThreadEventTarget = nullptr);
// Called by the channel when the response is read from the cache without
// communicating with the server.

Просмотреть файл

@ -2932,7 +2932,7 @@ WebSocketChannel::ApplyForAdmission()
rv = pps->AsyncResolve(mHttpChannel,
nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL,
this, getter_AddRefs(mCancelable));
this, nullptr, getter_AddRefs(mCancelable));
NS_ASSERTION(NS_FAILED(rv) || mCancelable,
"nsIProtocolProxyService::AsyncResolve succeeded but didn't "
"return a cancelable object!");

Просмотреть файл

@ -133,17 +133,6 @@ but you may be able to get a recent enough version from a software install
tool or package manager on your system, or directly from https://rust-lang.org/
'''
STYLO_MOZCONFIG = '''
To enable Stylo in your builds, paste the lines between the chevrons
(>>> and <<<) into your mozconfig file:
<<<
ac_add_options --enable-stylo
export LLVM_CONFIG=%s/clang/bin/llvm-config
>>>
'''
BROWSER_ARTIFACT_MODE_MOZCONFIG = '''
Paste the lines between the chevrons (>>> and <<<) into your mozconfig file:
@ -170,7 +159,6 @@ class BaseBootstrapper(object):
def __init__(self, no_interactive=False):
self.package_manager_updated = False
self.no_interactive = no_interactive
self.stylo = False
self.state_dir = None
def install_system_packages(self):
@ -199,8 +187,7 @@ class BaseBootstrapper(object):
Firefox for Desktop can in simple cases determine its build environment
entirely from configure.
'''
if self.stylo:
print(STYLO_MOZCONFIG % self.state_dir)
pass
def install_browser_artifact_mode_packages(self):
'''

Просмотреть файл

@ -92,18 +92,6 @@ Would you like to create this directory?
Your choice: '''
STYLO_DEVELOPMENT_INFO = '''
Stylo is an experimental rewrite of the Gecko style system in Rust to
be faster and make better use of modern computer hardware.
Would you like to download packages for working on Stylo? If you're
not sure, select "No".
1. Yes
2. No
Your choice: '''
STYLO_DIRECTORY_MESSAGE = '''
Stylo packages require a directory to store shared, persistent state.
On this machine, that directory is:
@ -315,28 +303,20 @@ class Bootstrapper(object):
# Install the clang packages needed for developing stylo.
if not self.instance.no_interactive:
choice = self.instance.prompt_int(
prompt=STYLO_DEVELOPMENT_INFO,
low=1,
high=2)
# The best place to install our packages is in the state directory
# we have. If the user doesn't have one, we need them to re-run
# bootstrap and create the directory.
#
# XXX Android bootstrap just assumes the existence of the state
# directory and writes the NDK into it. Should we do the same?
wants_stylo = choice == 1
if wants_stylo and not state_dir_available:
if not state_dir_available:
print(STYLO_DIRECTORY_MESSAGE.format(statedir=state_dir))
sys.exit(1)
if wants_stylo and not have_clone:
if not have_clone:
print(STYLO_REQUIRES_CLONE)
sys.exit(1)
self.instance.stylo = wants_stylo
if wants_stylo:
self.instance.state_dir = state_dir
self.instance.ensure_stylo_packages(state_dir, checkout_root)

Просмотреть файл

@ -4,15 +4,6 @@
from mozboot.base import BaseBootstrapper
STYLO_MOZCONFIG = '''
To enable Stylo in your builds, paste the lines between the chevrons
(>>> and <<<) into your mozconfig file:
<<<
ac_add_options --enable-stylo
>>>
'''
class FreeBSDBootstrapper(BaseBootstrapper):
def __init__(self, version, flavor, **kwargs):
BaseBootstrapper.__init__(self, **kwargs)
@ -72,9 +63,5 @@ class FreeBSDBootstrapper(BaseBootstrapper):
def ensure_stylo_packages(self, state_dir, checkout_root):
self.pkg_install('llvm40')
def suggest_browser_mozconfig(self):
if self.stylo:
print(STYLO_MOZCONFIG)
def upgrade_mercurial(self, current):
self.pkg_install('mercurial')

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше