зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central. r=merge a=merge
MozReview-Commit-ID: JSRVc5yW6Kx
This commit is contained in:
Коммит
8eb249afcc
|
@ -1503,6 +1503,7 @@ DocAccessible::DoInitialUpdate()
|
|||
|
||||
#if defined(XP_WIN)
|
||||
IAccessibleHolder holder(CreateHolderFromAccessible(this));
|
||||
MOZ_DIAGNOSTIC_ASSERT(!holder.IsNull());
|
||||
int32_t childID = AccessibleWrap::GetChildIDFor(this);
|
||||
#else
|
||||
int32_t holder = 0, childID = 0;
|
||||
|
|
|
@ -409,11 +409,8 @@ pref("browser.search.context.loadInBackground", false);
|
|||
// comma seperated list of of engines to hide in the search panel.
|
||||
pref("browser.search.hiddenOneOffs", "");
|
||||
|
||||
// Mirrors whether the search-container widget is in the navigation toolbar. The
|
||||
// default value of this preference must match the DEFAULT_AREA_PLACEMENTS of
|
||||
// UITelemetry.jsm, the navbarPlacements of CustomizableUI.jsm, and the
|
||||
// position and attributes of the search-container element in browser.xul.
|
||||
pref("browser.search.widget.inNavBar", true);
|
||||
// Mirrors whether the search-container widget is in the navigation toolbar.
|
||||
pref("browser.search.widget.inNavBar", false);
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
pref("browser.search.reset.enabled", true);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
@namespace svg url("http://www.w3.org/2000/svg");
|
||||
|
||||
:root {
|
||||
--panelui-subview-transition-duration: 150ms;
|
||||
|
|
|
@ -437,9 +437,9 @@
|
|||
position="bottomcenter topright"
|
||||
tabspecific="true"
|
||||
noautofocus="true"
|
||||
copyURL-title="©URLCmd.label;"
|
||||
copyURL-title="&pageAction.copyLink.label;"
|
||||
emailLink-title="&emailPageCmd.label;"
|
||||
sendToDevice-title="&sendToDevice.label3;"
|
||||
sendToDevice-title="&pageAction.sendTabToDevice.label;"
|
||||
sendToDevice-notReadyTitle="&sendToDevice.syncNotReady.label;">
|
||||
<photonpanelmultiview id="pageActionPanelMultiView"
|
||||
mainViewId="pageActionPanelMainView"
|
||||
|
@ -910,7 +910,7 @@
|
|||
class="urlbar-icon urlbar-page-action"
|
||||
role="button"
|
||||
tooltiptext="&pageActionButton.tooltip;"
|
||||
onclick="BrowserPageActions.mainButtonClicked(event);"/>
|
||||
onmousedown="BrowserPageActions.mainButtonClicked(event);"/>
|
||||
<hbox id="star-button-box"
|
||||
hidden="true"
|
||||
class="urlbar-icon-wrapper urlbar-page-action"
|
||||
|
@ -932,12 +932,6 @@
|
|||
</textbox>
|
||||
</toolbaritem>
|
||||
|
||||
<toolbaritem id="search-container" title="&searchItem.title;"
|
||||
align="center" class="chromeclass-toolbar-additional panel-wide-item"
|
||||
cui-areatype="toolbar"
|
||||
flex="100" persist="width" removable="true">
|
||||
<searchbar id="searchbar" flex="1"/>
|
||||
</toolbaritem>
|
||||
<toolbarspring cui-areatype="toolbar" class="chromeclass-toolbar-additional"/>
|
||||
|
||||
<!-- This is a placeholder for the Downloads Indicator. It is visible
|
||||
|
@ -946,7 +940,7 @@
|
|||
<toolbarbutton id="downloads-button"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional badged-button"
|
||||
key="key_openDownloads"
|
||||
oncommand="DownloadsIndicatorView.onCommand(event);"
|
||||
onmousedown="DownloadsIndicatorView.onCommand(event);"
|
||||
ondrop="DownloadsIndicatorView.onDrop(event);"
|
||||
ondragover="DownloadsIndicatorView.onDragOver(event);"
|
||||
ondragenter="DownloadsIndicatorView.onDragOver(event);"
|
||||
|
@ -957,7 +951,7 @@
|
|||
|
||||
<toolbarbutton id="library-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
removable="true"
|
||||
oncommand="PanelUI.showSubView('appMenu-libraryView', this, null, event);"
|
||||
onmousedown="PanelUI.showSubView('appMenu-libraryView', this, null, event);"
|
||||
closemenu="none"
|
||||
cui-areatype="toolbar"
|
||||
tooltiptext="&libraryButton.tooltip;"
|
||||
|
@ -1089,7 +1083,6 @@
|
|||
|
||||
<toolbarbutton id="bookmarks-menu-button"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
removable="true"
|
||||
type="menu"
|
||||
label="&bookmarksMenuButton2.label;"
|
||||
tooltip="dynamic-shortcut-tooltip"
|
||||
|
@ -1098,7 +1091,6 @@
|
|||
ondragover="PlacesMenuDNDHandler.onDragOver(event);"
|
||||
ondragleave="PlacesMenuDNDHandler.onDragLeave(event);"
|
||||
ondrop="PlacesMenuDNDHandler.onDrop(event);"
|
||||
cui-areatype="toolbar"
|
||||
oncommand="BookmarkingUI.onCommand(event);">
|
||||
<observes element="bookmarkThisPageBroadcaster" attribute="starred"/>
|
||||
<observes element="bookmarkThisPageBroadcaster" attribute="buttontooltiptext"/>
|
||||
|
@ -1184,6 +1176,15 @@
|
|||
key="manBookmarkKb"/>
|
||||
</menupopup>
|
||||
</toolbarbutton>
|
||||
|
||||
<toolbaritem id="search-container"
|
||||
class="chromeclass-toolbar-additional panel-wide-item"
|
||||
title="&searchItem.title;"
|
||||
align="center"
|
||||
flex="100"
|
||||
persist="width">
|
||||
<searchbar id="searchbar" flex="1"/>
|
||||
</toolbaritem>
|
||||
</toolbarpalette>
|
||||
<box id="library-animatable-box" class="toolbarbutton-animatable-box">
|
||||
<image class="toolbarbutton-animatable-image"/>
|
||||
|
|
|
@ -483,6 +483,8 @@ add_task(async function() {
|
|||
add_task(async function() {
|
||||
info("Cmd+k should focus the search box in the toolbar when it's present");
|
||||
|
||||
Services.prefs.setBoolPref("browser.search.widget.inNavBar", true);
|
||||
|
||||
await BrowserTestUtils.withNewTab({ gBrowser, url: "about:home" }, async function(browser) {
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter("#brandLogo", {}, browser);
|
||||
|
||||
|
@ -494,6 +496,8 @@ add_task(async function() {
|
|||
await promiseWaitForCondition(() => doc.activeElement === searchInput);
|
||||
is(searchInput, doc.activeElement, "Search bar should be the active element.");
|
||||
});
|
||||
|
||||
Services.prefs.clearUserPref("browser.search.widget.inNavBar");
|
||||
});
|
||||
|
||||
add_task(async function() {
|
||||
|
|
|
@ -397,6 +397,7 @@ support-files = test_offline_gzip.html gZipOfflineChild.cacheManifest gZipOfflin
|
|||
[browser_plainTextLinks.js]
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
[browser_printpreview.js]
|
||||
skip-if = os == 'win' # Bug 1384127
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
[browser_private_browsing_window.js]
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
|
|
|
@ -2,16 +2,10 @@
|
|||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(async function() {
|
||||
// Remove the search bar from toolbar
|
||||
CustomizableUI.removeWidgetFromArea("search-container");
|
||||
|
||||
// Test that Ctrl/Cmd + K will focus the url bar
|
||||
let focusPromise = BrowserTestUtils.waitForEvent(gURLBar, "focus");
|
||||
EventUtils.synthesizeKey("k", { accelKey: true });
|
||||
await focusPromise;
|
||||
Assert.equal(document.activeElement, gURLBar.inputField, "URL Bar should be focused");
|
||||
|
||||
// Reset changes made to toolbar
|
||||
CustomizableUI.reset();
|
||||
});
|
||||
|
||||
|
|
|
@ -193,7 +193,6 @@ var CustomizableUIInternal = {
|
|||
"home-button",
|
||||
"spring",
|
||||
"urlbar-container",
|
||||
"search-container",
|
||||
"spring",
|
||||
"downloads-button",
|
||||
"library-button",
|
||||
|
@ -4181,7 +4180,7 @@ OverflowableToolbar.prototype = {
|
|||
|
||||
let chevronId = this._toolbar.getAttribute("overflowbutton");
|
||||
this._chevron = doc.getElementById(chevronId);
|
||||
this._chevron.addEventListener("command", this);
|
||||
this._chevron.addEventListener("mousedown", this);
|
||||
this._chevron.addEventListener("dragover", this);
|
||||
this._chevron.addEventListener("dragend", this);
|
||||
|
||||
|
@ -4230,7 +4229,7 @@ OverflowableToolbar.prototype = {
|
|||
case "aftercustomization":
|
||||
this._enable();
|
||||
break;
|
||||
case "command":
|
||||
case "mousedown":
|
||||
if (aEvent.target == this._chevron) {
|
||||
this._onClickChevron(aEvent);
|
||||
} else {
|
||||
|
|
|
@ -36,6 +36,10 @@ const SearchWidgetTracker = {
|
|||
CustomizableUI.addListener(this);
|
||||
Services.prefs.addObserver(PREF_NAME,
|
||||
() => this.syncWidgetWithPreference());
|
||||
|
||||
// The placement of the widget always takes priority, and the preference
|
||||
// should always match the actual placement when the browser starts up.
|
||||
this.syncPreferenceWithWidget();
|
||||
},
|
||||
|
||||
onCustomizeEnd() {
|
||||
|
|
|
@ -475,7 +475,7 @@
|
|||
checkboxhidden="true"
|
||||
hidden="true">
|
||||
<popupnotificationcontent id="update-restart-notification-content" orient="vertical">
|
||||
<description id="update-restart-description">&updateRestart.message;</description>
|
||||
<description id="update-restart-description">&updateRestart.message2;</description>
|
||||
</popupnotificationcontent>
|
||||
</popupnotification>
|
||||
</panel>
|
||||
|
|
|
@ -7,15 +7,8 @@ const WIDGET_ID = "search-container";
|
|||
const PREF_NAME = "browser.search.widget.inNavBar";
|
||||
|
||||
function checkDefaults() {
|
||||
// If the following defaults change, then the DEFAULT_AREA_PLACEMENTS of
|
||||
// UITelemetry.jsm, the navbarPlacements of CustomizableUI.jsm, and the
|
||||
// position and attributes of the search-container element in browser.xul
|
||||
// should also change at the same time.
|
||||
ok(Services.prefs.getBoolPref(PREF_NAME));
|
||||
let placement = CustomizableUI.getPlacementOfWidget(WIDGET_ID);
|
||||
is(placement.area, CustomizableUI.AREA_NAVBAR);
|
||||
is(placement.position,
|
||||
CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1);
|
||||
ok(!Services.prefs.getBoolPref(PREF_NAME));
|
||||
is(CustomizableUI.getPlacementOfWidget(WIDGET_ID), null);
|
||||
}
|
||||
|
||||
add_task(async function test_defaults() {
|
||||
|
@ -24,23 +17,27 @@ add_task(async function test_defaults() {
|
|||
});
|
||||
|
||||
add_task(async function test_syncPreferenceWithWidget() {
|
||||
// Moving the widget to any position outside of the navigation toolbar should
|
||||
// turn the preference to false.
|
||||
CustomizableUI.addWidgetToArea(WIDGET_ID, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
|
||||
ok(!Services.prefs.getBoolPref(PREF_NAME));
|
||||
|
||||
// Moving the widget back to any position in the navigation toolbar should
|
||||
// turn the preference to true again.
|
||||
// Moving the widget to any position in the navigation toolbar should turn the
|
||||
// preference to true.
|
||||
CustomizableUI.addWidgetToArea(WIDGET_ID, CustomizableUI.AREA_NAVBAR);
|
||||
ok(Services.prefs.getBoolPref(PREF_NAME));
|
||||
|
||||
// Moving the widget to any position outside of the navigation toolbar should
|
||||
// turn the preference back to false.
|
||||
CustomizableUI.addWidgetToArea(WIDGET_ID, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
|
||||
ok(!Services.prefs.getBoolPref(PREF_NAME));
|
||||
});
|
||||
|
||||
add_task(async function test_syncWidgetWithPreference() {
|
||||
// This should move the widget the customization palette.
|
||||
Services.prefs.setBoolPref(PREF_NAME, false);
|
||||
is(CustomizableUI.getPlacementOfWidget(WIDGET_ID), null);
|
||||
|
||||
// This should return the widget to its default placement.
|
||||
// setting the preference should move the widget to the navigation toolbar and
|
||||
// place it right after the location bar.
|
||||
Services.prefs.setBoolPref(PREF_NAME, true);
|
||||
let placement = CustomizableUI.getPlacementOfWidget(WIDGET_ID);
|
||||
is(placement.area, CustomizableUI.AREA_NAVBAR);
|
||||
is(placement.position,
|
||||
CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1);
|
||||
|
||||
// This should move the widget back to the customization palette.
|
||||
Services.prefs.setBoolPref(PREF_NAME, false);
|
||||
checkDefaults();
|
||||
});
|
||||
|
|
|
@ -16,10 +16,8 @@ async function waitForSearchBarFocus() {
|
|||
|
||||
// Ctrl+K should open the menu panel and focus the search bar if the search bar is in the panel.
|
||||
add_task(async function() {
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
gCustomizeMode.addToPanel(searchbar);
|
||||
let placement = CustomizableUI.getPlacementOfWidget("search-container");
|
||||
is(placement.area, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, "Should be in panel");
|
||||
CustomizableUI.addWidgetToArea("search-container",
|
||||
CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
|
||||
|
||||
let shownPanelPromise = promiseOverflowShown(window);
|
||||
sendWebSearchKeyCommand();
|
||||
|
@ -35,10 +33,8 @@ add_task(async function() {
|
|||
|
||||
// Ctrl+K should give focus to the searchbar when the searchbar is in the menupanel and the panel is already opened.
|
||||
add_task(async function() {
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
gCustomizeMode.addToPanel(searchbar);
|
||||
let placement = CustomizableUI.getPlacementOfWidget("search-container");
|
||||
is(placement.area, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, "Should be in panel");
|
||||
CustomizableUI.addWidgetToArea("search-container",
|
||||
CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
|
||||
|
||||
await document.getElementById("nav-bar").overflowable.show();
|
||||
|
||||
|
@ -59,7 +55,9 @@ add_task(async function() {
|
|||
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
|
||||
ok(CustomizableUI.inDefaultState, "Should start in default state.");
|
||||
|
||||
window.resizeTo(360, window.outerHeight);
|
||||
Services.prefs.setBoolPref("browser.search.widget.inNavBar", true);
|
||||
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.getAttribute("overflowing") == "true");
|
||||
ok(!navbar.querySelector("#search-container"), "Search container should be overflowing");
|
||||
|
||||
|
@ -75,6 +73,9 @@ add_task(async function() {
|
|||
let hiddenPanelPromise = promiseOverflowHidden(window);
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
await hiddenPanelPromise;
|
||||
|
||||
Services.prefs.setBoolPref("browser.search.widget.inNavBar", false);
|
||||
|
||||
navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
|
||||
window.resizeTo(this.originalWindowWidth, window.outerHeight);
|
||||
await waitForCondition(() => !navbar.hasAttribute("overflowing"));
|
||||
|
@ -83,12 +84,15 @@ add_task(async function() {
|
|||
|
||||
// Ctrl+K should focus the search bar if it is in the navbar and not overflowing.
|
||||
add_task(async function() {
|
||||
Services.prefs.setBoolPref("browser.search.widget.inNavBar", true);
|
||||
let placement = CustomizableUI.getPlacementOfWidget("search-container");
|
||||
is(placement.area, CustomizableUI.AREA_NAVBAR, "Should be in nav-bar");
|
||||
|
||||
sendWebSearchKeyCommand();
|
||||
|
||||
await waitForSearchBarFocus();
|
||||
|
||||
Services.prefs.setBoolPref("browser.search.widget.inNavBar", false);
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ add_task(async function() {
|
|||
let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
|
||||
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
|
||||
let oldChildCount = navbar.customizationTarget.childElementCount;
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ add_task(async function() {
|
|||
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
|
||||
ok(CustomizableUI.inDefaultState, "Should start in default state.");
|
||||
let oldChildCount = navbar.customizationTarget.childElementCount;
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
|
||||
is(navbar.currentSet, oldCurrentSet, "Currentset should be the same when overflowing.");
|
||||
|
|
|
@ -23,7 +23,7 @@ add_task(async function() {
|
|||
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
|
||||
ok(CustomizableUI.inDefaultState, "Should start in default state.");
|
||||
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
|
||||
ok(!navbar.querySelector("#" + kSidebarBtn), "Sidebar button should no longer be in the navbar");
|
||||
|
@ -65,7 +65,7 @@ add_task(async function() {
|
|||
CustomizableUI.addWidgetToArea(kTestBtn2, navbar.id);
|
||||
ok(!navbar.hasAttribute("overflowing"), "Should still have a non-overflowing toolbar.");
|
||||
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
|
||||
ok(!navbar.querySelector("#" + kTestBtn2), "Test button should not be in the navbar");
|
||||
|
@ -94,7 +94,7 @@ add_task(async function() {
|
|||
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
|
||||
ok(CustomizableUI.inDefaultState, "Should start in default state.");
|
||||
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
|
||||
ok(!navbar.querySelector("#" + kSidebarBtn), "Sidebar button should no longer be in the navbar");
|
||||
|
|
|
@ -9,11 +9,11 @@ add_task(async function() {
|
|||
await startCustomizing();
|
||||
let devButton = document.getElementById("developer-button");
|
||||
let downloadsButton = document.getElementById("downloads-button");
|
||||
let searchBox = document.getElementById("search-container");
|
||||
let homeButton = document.getElementById("home-button");
|
||||
let palette = document.getElementById("customization-palette");
|
||||
ok(devButton && downloadsButton && searchBox && palette, "Stuff should exist");
|
||||
ok(devButton && downloadsButton && homeButton && palette, "Stuff should exist");
|
||||
simulateItemDrag(devButton, downloadsButton);
|
||||
simulateItemDrag(searchBox, palette);
|
||||
simulateItemDrag(homeButton, palette);
|
||||
await gCustomizeMode.reset();
|
||||
ok(CustomizableUI.inDefaultState, "Should be back in default state");
|
||||
await endCustomizing();
|
||||
|
|
|
@ -69,14 +69,14 @@ add_task(async function menu_button_popup() {
|
|||
});
|
||||
|
||||
add_task(async function searchbar_in_panel() {
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
gCustomizeMode.addToPanel(searchbar);
|
||||
let placement = CustomizableUI.getPlacementOfWidget("search-container");
|
||||
is(placement.area, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, "Should be in panel");
|
||||
CustomizableUI.addWidgetToArea("search-container",
|
||||
CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
|
||||
|
||||
await waitForOverflowButtonShown();
|
||||
|
||||
await document.getElementById("nav-bar").overflowable.show();
|
||||
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
await waitForCondition(() => "value" in searchbar && searchbar.value === "");
|
||||
|
||||
// Focusing a non-empty searchbox will cause us to open the
|
||||
|
|
|
@ -12,7 +12,7 @@ add_task(async function() {
|
|||
let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
|
||||
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
|
||||
ok(CustomizableUI.inDefaultState, "Should start in default state.");
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ add_task(async function() {
|
|||
}
|
||||
|
||||
let originalWindowWidth = window.outerWidth;
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
|
||||
let testWidgetId = kTestWidgetPrefix + 3;
|
||||
|
@ -116,7 +116,7 @@ add_task(async function() {
|
|||
}
|
||||
|
||||
let originalWindowWidth = window.outerWidth;
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
|
||||
let testWidgetId = kTestWidgetPrefix + 3;
|
||||
|
@ -166,7 +166,7 @@ add_task(async function() {
|
|||
}
|
||||
|
||||
let originalWindowWidth = window.outerWidth;
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
|
||||
let testWidgetId = kTestWidgetPrefix + 3;
|
||||
|
@ -225,7 +225,7 @@ add_task(async function() {
|
|||
}
|
||||
|
||||
let originalWindowWidth = window.outerWidth;
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
|
||||
// Find last widget that doesn't allow overflowing
|
||||
|
@ -286,7 +286,7 @@ add_task(async function() {
|
|||
ok(!toolbarNode.hasAttribute("overflowing"), "Toolbar shouldn't overflow to start with.");
|
||||
|
||||
let originalWindowWidth = window.outerWidth;
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => toolbarNode.hasAttribute("overflowing"));
|
||||
ok(toolbarNode.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
|
||||
|
||||
|
@ -337,7 +337,7 @@ add_task(async function() {
|
|||
ok(!toolbarNode.hasAttribute("overflowing"), "Toolbar shouldn't overflow to start with.");
|
||||
|
||||
let originalWindowWidth = window.outerWidth;
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => toolbarNode.hasAttribute("overflowing"));
|
||||
ok(toolbarNode.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
|
||||
|
||||
|
@ -386,7 +386,7 @@ add_task(async function() {
|
|||
ok(!toolbarNode.hasAttribute("overflowing"), "Toolbar shouldn't overflow to start with.");
|
||||
|
||||
let originalWindowWidth = window.outerWidth;
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => toolbarNode.hasAttribute("overflowing"));
|
||||
ok(toolbarNode.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ add_task(async function addOverflowingToolbar() {
|
|||
|
||||
isnot(oldChildCount, 0, "Toolbar should have non-overflowing widgets");
|
||||
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => toolbarNode.hasAttribute("overflowing"));
|
||||
ok(toolbarNode.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
|
||||
ok(toolbarNode.customizationTarget.childElementCount < oldChildCount, "Should have fewer children.");
|
||||
|
|
|
@ -10,7 +10,6 @@ var gOverflowList = document.getElementById(gNavBar.getAttribute("overflowtarget
|
|||
const kBookmarksButton = "bookmarks-menu-button";
|
||||
const kBookmarksItems = "personal-bookmarks";
|
||||
const kOriginalWindowWidth = window.outerWidth;
|
||||
const kSmallWidth = 400;
|
||||
|
||||
/**
|
||||
* Helper function that opens the bookmarks menu, and returns a Promise that
|
||||
|
@ -141,7 +140,7 @@ function checkBookmarksItemsChevronContextMenu() {
|
|||
*/
|
||||
function overflowEverything() {
|
||||
info("Waiting for overflow");
|
||||
window.resizeTo(kSmallWidth, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
return waitForCondition(() => gNavBar.hasAttribute("overflowing"));
|
||||
}
|
||||
|
||||
|
|
|
@ -145,6 +145,11 @@ add_task(async function urlbar_context() {
|
|||
// Right-click on the searchbar and moving it to the menu
|
||||
// and back should move the search-container instead.
|
||||
add_task(async function searchbar_context_move_to_panel_and_back() {
|
||||
// This is specifically testing the addToPanel function for the search bar, so
|
||||
// we have to move it to its correct position in the navigation toolbar first.
|
||||
// The preference will be restored when the customizations are reset later.
|
||||
Services.prefs.setBoolPref("browser.search.widget.inNavBar", true);
|
||||
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
gCustomizeMode.addToPanel(searchbar);
|
||||
let placement = CustomizableUI.getPlacementOfWidget("search-container");
|
||||
|
@ -167,7 +172,7 @@ add_task(async function searchbar_context_move_to_panel_and_back() {
|
|||
is(placement, null, "Should be in palette");
|
||||
CustomizableUI.reset();
|
||||
placement = CustomizableUI.getPlacementOfWidget("search-container");
|
||||
is(placement.area, CustomizableUI.AREA_NAVBAR, "Should be in navbar");
|
||||
is(placement, null, "Should be in palette");
|
||||
});
|
||||
|
||||
// Right-click on an item within the panel should
|
||||
|
|
|
@ -128,7 +128,7 @@ add_task(async function test_panelui_customize_to_toolbar() {
|
|||
CustomizableUI.reset();
|
||||
});
|
||||
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
|
||||
// Mac will update the enabled state even when the buttons are overflowing,
|
||||
|
|
|
@ -23,7 +23,7 @@ add_task(async function check_developer_subview_in_overflow() {
|
|||
|
||||
let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
|
||||
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
|
||||
window.resizeTo(400, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
|
||||
await waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ var {synthesizeDragStart, synthesizeDrop} = EventUtils;
|
|||
const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const kTabEventFailureTimeoutInMs = 20000;
|
||||
|
||||
const kForceOverflowWidthPx = 300;
|
||||
|
||||
function createDummyXULButton(id, label, win = window) {
|
||||
let btn = document.createElementNS(kNSXUL, "toolbarbutton");
|
||||
btn.id = id;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// This is the same value used by CustomizableUI tests.
|
||||
const kForceOverflowWidthPx = 200;
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
// Clean up when the test finishes.
|
||||
await task_resetState();
|
||||
|
@ -24,20 +27,18 @@ add_task(async function test_overflow_anchor() {
|
|||
.forWindow(window);
|
||||
ok(!button.overflowed, "Downloads button should not be overflowed.");
|
||||
|
||||
// Hack - we lock the size of the default flex-y items in the nav-bar,
|
||||
// namely, the URL and search inputs. That way we can resize the
|
||||
// window without worrying about them flexing.
|
||||
const kFlexyItems = ["urlbar-container", "search-container"];
|
||||
// Hack - we lock the size of the default flex-y items in the nav-bar, namely,
|
||||
// the URL input. That way we can resize the window without worrying about it
|
||||
// flexing.
|
||||
const kFlexyItems = ["urlbar-container"];
|
||||
registerCleanupFunction(() => unlockWidth(kFlexyItems));
|
||||
lockWidth(kFlexyItems);
|
||||
|
||||
// Resize the window to half of its original size. That should
|
||||
// be enough to overflow the downloads button.
|
||||
window.resizeTo(oldWidth / 2, window.outerHeight);
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForOverflowed(button, true);
|
||||
|
||||
let promise = promisePanelOpened();
|
||||
button.node.doCommand();
|
||||
button.node.dispatchEvent(new Event("mousedown"));
|
||||
await promise;
|
||||
|
||||
let panel = DownloadsPanel.panel;
|
||||
|
@ -57,7 +58,7 @@ add_task(async function test_overflow_anchor() {
|
|||
|
||||
// Now try opening the panel again.
|
||||
promise = promisePanelOpened();
|
||||
button.node.doCommand();
|
||||
button.node.dispatchEvent(new Event("mousedown"));
|
||||
await promise;
|
||||
|
||||
is(panel.anchorNode.id, "downloads-indicator-anchor");
|
||||
|
|
|
@ -549,7 +549,7 @@
|
|||
}
|
||||
]]></handler>
|
||||
|
||||
<handler event="click" button="0">
|
||||
<handler event="mousedown" button="0">
|
||||
<![CDATA[
|
||||
// Ignore clicks on the search go button.
|
||||
if (event.originalTarget.getAttribute("anonid") == "search-go-button") {
|
||||
|
|
|
@ -131,6 +131,12 @@ async function prepareTest() {
|
|||
await focusPromise;
|
||||
}
|
||||
|
||||
add_task(async function testSetup() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
});
|
||||
|
||||
add_task(async function testSetupEngine() {
|
||||
await promiseSetEngine();
|
||||
});
|
||||
|
|
|
@ -123,13 +123,15 @@ async function testSearchEngine(engineDetails) {
|
|||
name: "search bar search",
|
||||
searchURL: base + engineDetails.codes.submission,
|
||||
run() {
|
||||
Services.prefs.setBoolPref("browser.search.widget.inNavBar", true);
|
||||
let sb = BrowserSearch.searchBar;
|
||||
sb.focus();
|
||||
sb.value = "foo";
|
||||
registerCleanupFunction(function() {
|
||||
sb.value = "";
|
||||
});
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
},
|
||||
postTest() {
|
||||
BrowserSearch.searchBar.value = "";
|
||||
Services.prefs.setBoolPref("browser.search.widget.inNavBar", false);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -169,6 +171,10 @@ async function testSearchEngine(engineDetails) {
|
|||
let receivedURI = await stateChangePromise;
|
||||
|
||||
Assert.equal(receivedURI, test.searchURL);
|
||||
|
||||
if (test.postTest) {
|
||||
await test.postTest(tab);
|
||||
}
|
||||
}
|
||||
|
||||
engine.alias = undefined;
|
||||
|
|
|
@ -120,6 +120,12 @@ add_task(async function tests() {
|
|||
let engine = Services.search.getEngineByName("Google");
|
||||
ok(engine, "Google");
|
||||
|
||||
// Show the search bar after initializing the search service, to avoid the
|
||||
// synchronous initialization to interfere.
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
let base = "https://www.google.com/search?q=foo&ie=utf-8&oe=utf-8&client=firefox-b";
|
||||
|
||||
// Keyword uses a slightly different code
|
||||
|
|
|
@ -120,6 +120,12 @@ add_task(async function tests() {
|
|||
let engine = Services.search.getEngineByName("Google");
|
||||
ok(engine, "Google");
|
||||
|
||||
// Show the search bar after initializing the search service, to avoid the
|
||||
// synchronous initialization to interfere.
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
let base = "https://www.google.com/search?q=foo&ie=utf-8&oe=utf-8";
|
||||
|
||||
let url;
|
||||
|
|
|
@ -9,7 +9,9 @@ function test() {
|
|||
waitForExplicitFinish();
|
||||
resetPreferences();
|
||||
|
||||
let calledTestTelemetry = false;
|
||||
function testTelemetry() {
|
||||
calledTestTelemetry = true;
|
||||
// Find the right bucket for the "Foo" engine.
|
||||
let engine = Services.search.getEngineByName("Foo");
|
||||
let histogramKey = (engine.identifier || "other-Foo") + ".searchbar";
|
||||
|
@ -58,8 +60,11 @@ function test() {
|
|||
break;
|
||||
|
||||
case "engine-current":
|
||||
is(Services.search.currentEngine.name, "Foo", "Current engine is Foo");
|
||||
testTelemetry();
|
||||
// We may be called again when resetting the engine at the end.
|
||||
if (!calledTestTelemetry) {
|
||||
is(Services.search.currentEngine.name, "Foo", "Current engine is Foo");
|
||||
testTelemetry();
|
||||
}
|
||||
break;
|
||||
|
||||
case "engine-removed":
|
||||
|
@ -70,7 +75,10 @@ function test() {
|
|||
}
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified");
|
||||
SpecialPowers.pushPrefEnv({set: [["toolkit.telemetry.enabled", true]]}).then(function() {
|
||||
SpecialPowers.pushPrefEnv({set: [
|
||||
["toolkit.telemetry.enabled", true],
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]}).then(function() {
|
||||
Services.search.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
|
||||
null, "data:image/x-icon,%00", false);
|
||||
});
|
||||
|
|
|
@ -3,18 +3,26 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
// Tests that keyboard navigation in the search panel works as designed.
|
||||
|
||||
const searchbar = document.getElementById("searchbar");
|
||||
const textbox = searchbar._textbox;
|
||||
const searchPopup = document.getElementById("PopupSearchAutoComplete");
|
||||
const searchIcon = document.getAnonymousElementByAttribute(searchbar, "anonid",
|
||||
"searchbar-search-button");
|
||||
|
||||
const diacritic_engine = "Foo \u2661";
|
||||
|
||||
var Preferences =
|
||||
Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
|
||||
|
||||
let searchbar;
|
||||
let searchIcon;
|
||||
|
||||
add_task(async function init() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
searchbar = document.getElementById("searchbar");
|
||||
searchIcon = document.getAnonymousElementByAttribute(
|
||||
searchbar, "anonid", "searchbar-search-button"
|
||||
);
|
||||
|
||||
let currentEngine = Services.search.currentEngine;
|
||||
await promiseNewEngine("testEngine_diacritics.xml", {setAsCurrent: false});
|
||||
registerCleanupFunction(() => {
|
||||
|
|
|
@ -3,11 +3,7 @@
|
|||
const TEST_ENGINE_NAME = "Foo";
|
||||
const TEST_ENGINE_BASENAME = "testEngine.xml";
|
||||
|
||||
const searchbar = document.getElementById("searchbar");
|
||||
const searchPopup = document.getElementById("PopupSearchAutoComplete");
|
||||
const searchIcon = document.getAnonymousElementByAttribute(
|
||||
searchbar, "anonid", "searchbar-search-button"
|
||||
);
|
||||
const oneOffBinding = document.getAnonymousElementByAttribute(
|
||||
searchPopup, "anonid", "search-one-off-buttons"
|
||||
);
|
||||
|
@ -21,7 +17,19 @@ const searchInNewTabMenuItem = document.getAnonymousElementByAttribute(
|
|||
oneOffBinding, "anonid", "search-one-offs-context-open-in-new-tab"
|
||||
);
|
||||
|
||||
let searchbar;
|
||||
let searchIcon;
|
||||
|
||||
add_task(async function init() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
searchbar = document.getElementById("searchbar");
|
||||
searchIcon = document.getAnonymousElementByAttribute(
|
||||
searchbar, "anonid", "searchbar-search-button"
|
||||
);
|
||||
|
||||
await promiseNewEngine(TEST_ENGINE_BASENAME, {
|
||||
setAsCurrent: false,
|
||||
});
|
||||
|
|
|
@ -6,13 +6,9 @@ const SEARCHBAR_BASE_ID = "searchbar-engine-one-off-item-";
|
|||
const URLBAR_BASE_ID = "urlbar-engine-one-off-item-";
|
||||
const ONEOFF_URLBAR_PREF = "browser.urlbar.oneOffSearches";
|
||||
|
||||
const searchbar = document.getElementById("searchbar");
|
||||
const urlbar = document.getElementById("urlbar");
|
||||
const searchPopup = document.getElementById("PopupSearchAutoComplete");
|
||||
const urlbarPopup = document.getElementById("PopupAutoCompleteRichResult");
|
||||
const searchIcon = document.getAnonymousElementByAttribute(
|
||||
searchbar, "anonid", "searchbar-search-button"
|
||||
);
|
||||
const searchOneOffBinding = document.getAnonymousElementByAttribute(
|
||||
searchPopup, "anonid", "search-one-off-buttons"
|
||||
);
|
||||
|
@ -28,7 +24,19 @@ function resetEngine() {
|
|||
|
||||
registerCleanupFunction(resetEngine);
|
||||
|
||||
let searchbar;
|
||||
let searchIcon;
|
||||
|
||||
add_task(async function init() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
searchbar = document.getElementById("searchbar");
|
||||
searchIcon = document.getAnonymousElementByAttribute(
|
||||
searchbar, "anonid", "searchbar-search-button"
|
||||
);
|
||||
|
||||
await promiseNewEngine(TEST_ENGINE_BASENAME, {
|
||||
setAsCurrent: false,
|
||||
});
|
||||
|
|
|
@ -5,11 +5,7 @@
|
|||
|
||||
const isMac = ("nsILocalFileMac" in Ci);
|
||||
|
||||
const searchbar = document.getElementById("searchbar");
|
||||
const textbox = searchbar._textbox;
|
||||
const searchPopup = document.getElementById("PopupSearchAutoComplete");
|
||||
const searchIcon = document.getAnonymousElementByAttribute(searchbar, "anonid",
|
||||
"searchbar-search-button");
|
||||
|
||||
const oneOffsContainer =
|
||||
document.getAnonymousElementByAttribute(searchPopup, "anonid",
|
||||
|
@ -55,8 +51,19 @@ function synthesizeNativeMouseMove(aElement) {
|
|||
});
|
||||
}
|
||||
|
||||
let searchbar;
|
||||
let searchIcon;
|
||||
|
||||
add_task(async function init() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
searchbar = document.getElementById("searchbar");
|
||||
searchIcon = document.getAnonymousElementByAttribute(
|
||||
searchbar, "anonid", "searchbar-search-button"
|
||||
);
|
||||
|
||||
await promiseNewEngine("testEngine.xml");
|
||||
});
|
||||
|
||||
|
@ -92,9 +99,9 @@ add_task(async function test_notext() {
|
|||
});
|
||||
|
||||
add_task(async function test_text() {
|
||||
textbox.value = "foo";
|
||||
searchbar._textbox.value = "foo";
|
||||
registerCleanupFunction(() => {
|
||||
textbox.value = "";
|
||||
searchbar._textbox.value = "";
|
||||
});
|
||||
|
||||
let promise = promiseEvent(searchPopup, "popupshown");
|
||||
|
@ -133,7 +140,8 @@ add_task(async function test_text() {
|
|||
EventUtils.synthesizeMouseAtCenter(searchbarEngine, {});
|
||||
});
|
||||
|
||||
let url = Services.search.currentEngine.getSubmission(textbox.value).uri.spec;
|
||||
let url = Services.search.currentEngine
|
||||
.getSubmission(searchbar._textbox.value).uri.spec;
|
||||
await promiseTabLoadEvent(gBrowser.selectedTab, url);
|
||||
|
||||
// Move the cursor out of the panel area to avoid messing with other tests.
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
// whether there is an autocomplete entry for the private search.
|
||||
|
||||
add_task(async function() {
|
||||
// Don't use about:home as the homepage for new windows
|
||||
Services.prefs.setIntPref("browser.startup.page", 0);
|
||||
registerCleanupFunction(() => Services.prefs.clearUserPref("browser.startup.page"));
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
let windowsToClose = [];
|
||||
|
||||
|
|
|
@ -106,6 +106,12 @@ function promiseContentSearchReady(browser) {
|
|||
});
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
});
|
||||
|
||||
for (let engine of SEARCH_ENGINE_DETAILS) {
|
||||
add_task(async function() {
|
||||
let previouslySelectedEngine = Services.search.currentEngine;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Tests that keyboard navigation in the search panel works as designed.
|
||||
|
||||
const searchbar = document.getElementById("searchbar");
|
||||
const textbox = searchbar._textbox;
|
||||
const searchPopup = document.getElementById("PopupSearchAutoComplete");
|
||||
const oneOffsContainer =
|
||||
document.getAnonymousElementByAttribute(searchPopup, "anonid",
|
||||
|
@ -22,7 +20,17 @@ function getOpenSearchItems() {
|
|||
return os;
|
||||
}
|
||||
|
||||
let searchbar;
|
||||
let textbox;
|
||||
|
||||
add_task(async function init() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
searchbar = document.getElementById("searchbar");
|
||||
textbox = searchbar._textbox;
|
||||
|
||||
await promiseNewEngine("testEngine.xml");
|
||||
|
||||
// First cleanup the form history in case other tests left things there.
|
||||
|
|
|
@ -8,10 +8,6 @@ this._scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
|
|||
getService(Ci.mozIJSSubScriptLoader);
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
|
||||
|
||||
const searchbar = document.getElementById("searchbar");
|
||||
const searchIcon = document.getAnonymousElementByAttribute(searchbar, "anonid", "searchbar-search-button");
|
||||
const goButton = document.getAnonymousElementByAttribute(searchbar, "anonid", "search-go-button");
|
||||
const textbox = searchbar._textbox;
|
||||
const searchPopup = document.getElementById("PopupSearchAutoComplete");
|
||||
const kValues = ["long text", "long text 2", "long text 3"];
|
||||
|
||||
|
@ -62,7 +58,25 @@ async function startCustomizing(aWindow = window) {
|
|||
return eventPromise;
|
||||
}
|
||||
|
||||
let searchbar;
|
||||
let textbox;
|
||||
let searchIcon;
|
||||
let goButton;
|
||||
|
||||
add_task(async function init() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
searchbar = document.getElementById("searchbar");
|
||||
textbox = searchbar._textbox;
|
||||
searchIcon = document.getAnonymousElementByAttribute(
|
||||
searchbar, "anonid", "searchbar-search-button"
|
||||
);
|
||||
goButton = document.getAnonymousElementByAttribute(
|
||||
searchbar, "anonid", "search-go-button"
|
||||
);
|
||||
|
||||
await promiseNewEngine("testEngine.xml");
|
||||
|
||||
// First cleanup the form history in case other tests left things there.
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
// Tests that keyboard navigation in the search panel works as designed.
|
||||
|
||||
const searchbar = document.getElementById("searchbar");
|
||||
const textbox = searchbar._textbox;
|
||||
const searchPopup = document.getElementById("PopupSearchAutoComplete");
|
||||
const oneOffsContainer =
|
||||
document.getAnonymousElementByAttribute(searchPopup, "anonid",
|
||||
"search-one-off-buttons");
|
||||
const searchIcon = document.getAnonymousElementByAttribute(searchbar, "anonid",
|
||||
"searchbar-search-button");
|
||||
|
||||
const kValues = ["foo1", "foo2", "foo3"];
|
||||
|
||||
|
@ -23,7 +19,21 @@ function getOpenSearchItems() {
|
|||
return os;
|
||||
}
|
||||
|
||||
let searchbar;
|
||||
let textbox;
|
||||
let searchIcon;
|
||||
|
||||
add_task(async function init() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
searchbar = document.getElementById("searchbar");
|
||||
textbox = searchbar._textbox;
|
||||
searchIcon = document.getAnonymousElementByAttribute(
|
||||
searchbar, "anonid", "searchbar-search-button"
|
||||
);
|
||||
|
||||
await promiseNewEngine("testEngine.xml");
|
||||
|
||||
// First cleanup the form history in case other tests left things there.
|
||||
|
|
|
@ -4,13 +4,18 @@
|
|||
// popup shows a submenu that lists them instead of showing them in the popup
|
||||
// itself.
|
||||
|
||||
const searchbar = document.getElementById("searchbar");
|
||||
const searchPopup = document.getElementById("PopupSearchAutoComplete");
|
||||
const oneOffsContainer =
|
||||
document.getAnonymousElementByAttribute(searchPopup, "anonid",
|
||||
"search-one-off-buttons");
|
||||
|
||||
add_task(async function test() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
|
||||
let rootDir = getRootDirectory(gTestPath);
|
||||
let url = rootDir + "tooManyEnginesOffered.html";
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
|
|
|
@ -9,7 +9,11 @@
|
|||
|
||||
const BROWSER_SEARCH_PREF = "browser.search.";
|
||||
|
||||
function test() {
|
||||
add_task(async function test() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
let engine = Services.search.getEngineByName("Yahoo");
|
||||
ok(engine, "Yahoo");
|
||||
|
||||
|
@ -129,4 +133,4 @@ function test() {
|
|||
};
|
||||
|
||||
isSubObjectOf(EXPECTED_ENGINE, engine, "Yahoo");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -273,11 +273,18 @@ var tests = [
|
|||
is(icon.src, "", "Popup should have no icon");
|
||||
is(buttons.hasChildNodes(), false, "Popup should have no buttons");
|
||||
|
||||
// Place the search bar in the navigation toolbar temporarily.
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
await showInfoPromise("search", "search title", "search text");
|
||||
|
||||
is(popup.popupBoxObject.anchorNode, document.getElementById("searchbar"), "Popup should be anchored to the searchbar");
|
||||
is(title.textContent, "search title", "Popup should have correct title");
|
||||
is(desc.textContent, "search text", "Popup should have correct description text");
|
||||
|
||||
await SpecialPowers.popPrefEnv();
|
||||
}),
|
||||
function test_getConfigurationVersion(done) {
|
||||
function callback(result) {
|
||||
|
|
|
@ -162,6 +162,11 @@ add_UITour_task(async function test_getConfiguration_selectedSearchEngine() {
|
|||
});
|
||||
|
||||
add_UITour_task(async function test_setSearchTerm() {
|
||||
// Place the search bar in the navigation toolbar temporarily.
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
const TERM = "UITour Search Term";
|
||||
await gContentAPI.setSearchTerm(TERM);
|
||||
|
||||
|
@ -169,13 +174,22 @@ add_UITour_task(async function test_setSearchTerm() {
|
|||
// The UITour gets to the searchbar element through a promise, so the value setting
|
||||
// only happens after a tick.
|
||||
await waitForConditionPromise(() => searchbar.value == TERM, "Correct term set");
|
||||
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
add_UITour_task(async function test_clearSearchTerm() {
|
||||
// Place the search bar in the navigation toolbar temporarily.
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
await gContentAPI.setSearchTerm("");
|
||||
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
// The UITour gets to the searchbar element through a promise, so the value setting
|
||||
// only happens after a tick.
|
||||
await waitForConditionPromise(() => searchbar.value == "", "Search term cleared");
|
||||
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
|
|
@ -29,8 +29,6 @@ function getExpectedTargets() {
|
|||
"privateWindow",
|
||||
...(hasQuit ? ["quit"] : []),
|
||||
"readerMode-urlBar",
|
||||
"search",
|
||||
"searchIcon",
|
||||
"trackingProtection",
|
||||
"urlbar",
|
||||
];
|
||||
|
@ -62,17 +60,16 @@ add_UITour_task(async function test_availableTargets_changeWidgets() {
|
|||
"Targets should not be cached after reset");
|
||||
});
|
||||
|
||||
add_UITour_task(async function test_availableTargets_exceptionFromGetTarget() {
|
||||
// The query function for the "search" target will throw if it's not found.
|
||||
// Make sure the callback still fires with the other available targets.
|
||||
CustomizableUI.removeWidgetFromArea("search-container");
|
||||
let data = await getConfigurationPromise("availableTargets");
|
||||
let expecteds = getExpectedTargets();
|
||||
// Default minus "search" and "searchIcon"
|
||||
expecteds = expecteds.filter(target => target != "search" && target != "searchIcon");
|
||||
ok_targets(data, expecteds);
|
||||
|
||||
CustomizableUI.reset();
|
||||
add_UITour_task(async function test_availableTargets_search() {
|
||||
Services.prefs.setBoolPref("browser.search.widget.inNavBar", true);
|
||||
try {
|
||||
let data = await getConfigurationPromise("availableTargets");
|
||||
let expecteds = getExpectedTargets();
|
||||
expecteds = ["search", "searchIcon", ...expecteds];
|
||||
ok_targets(data, expecteds);
|
||||
} finally {
|
||||
Services.prefs.clearUserPref("browser.search.widget.inNavBar");
|
||||
}
|
||||
});
|
||||
|
||||
add_UITour_task(async function test_availableTargets_removeUrlbarPageActionsAll() {
|
||||
|
|
|
@ -13,15 +13,17 @@ function test() {
|
|||
|
||||
var tests = [
|
||||
function test_openSearchPanel(done) {
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
|
||||
// If suggestions are enabled, the panel will attempt to use the network to connect
|
||||
// to the suggestions provider, causing the test suite to fail.
|
||||
// If suggestions are enabled, the panel will attempt to use the network to
|
||||
// connect to the suggestions provider, causing the test suite to fail. We
|
||||
// also change the preference to display the search bar during the test.
|
||||
Services.prefs.setBoolPref("browser.search.widget.inNavBar", true);
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled", false);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("browser.search.widget.inNavBar");
|
||||
Services.prefs.clearUserPref("browser.search.suggest.enabled");
|
||||
});
|
||||
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
ok(!searchbar.textbox.open, "Popup starts as closed");
|
||||
gContentAPI.openSearchPanel(() => {
|
||||
ok(searchbar.textbox.open, "Popup was opened");
|
||||
|
|
|
@ -556,7 +556,7 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||
<!ENTITY bookmarkThisLinkCmd.accesskey "L">
|
||||
<!ENTITY bookmarkThisFrameCmd.label "Bookmark This Frame">
|
||||
<!ENTITY bookmarkThisFrameCmd.accesskey "m">
|
||||
<!ENTITY copyURLCmd.label "Copy URL">
|
||||
<!ENTITY pageAction.copyLink.label "Copy Link">
|
||||
<!ENTITY copyURLFeedback.label "Copied!">
|
||||
<!ENTITY emailPageCmd.label "Email Link…">
|
||||
<!ENTITY emailPageCmd.accesskey "E">
|
||||
|
@ -965,7 +965,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
|||
<!ENTITY updateManual.cancelButton.accesskey "N">
|
||||
<!ENTITY updateManual.panelUI.label "Download a fresh copy of &brandShorterName;">
|
||||
|
||||
<!ENTITY updateRestart.message "After a quick restart, &brandShorterName; will restore all your open tabs and windows.">
|
||||
<!ENTITY updateRestart.message2 "After a quick restart, &brandShorterName; will restore all your open tabs and windows that are not in Private Browsing mode.">
|
||||
<!ENTITY updateRestart.header.message2 "Restart to update &brandShorterName;.">
|
||||
<!ENTITY updateRestart.acceptButton.label "Restart and Restore">
|
||||
<!ENTITY updateRestart.acceptButton.accesskey "R">
|
||||
|
@ -977,7 +977,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
|||
<!ENTITY pageAction.addToUrlbar.label "Add to Address Bar">
|
||||
<!ENTITY pageAction.removeFromUrlbar.label "Remove from Address Bar">
|
||||
|
||||
<!ENTITY sendToDevice.label3 "Send Page to Device">
|
||||
<!ENTITY pageAction.sendTabToDevice.label "Send Tab to Device">
|
||||
<!ENTITY sendToDevice.syncNotReady.label "Syncing Devices…">
|
||||
|
||||
<!ENTITY libraryButton.tooltip "View history, saved bookmarks, and more">
|
||||
|
|
|
@ -55,7 +55,6 @@ XPCOMUtils.defineLazyGetter(this, "DEFAULT_AREA_PLACEMENTS", function() {
|
|||
"stop-reload-button",
|
||||
"home-button",
|
||||
"urlbar-container",
|
||||
"search-container",
|
||||
"downloads-button",
|
||||
"library-button",
|
||||
"sidebar-button",
|
||||
|
@ -88,6 +87,7 @@ XPCOMUtils.defineLazyGetter(this, "DEFAULT_AREAS", function() {
|
|||
XPCOMUtils.defineLazyGetter(this, "PALETTE_ITEMS", function() {
|
||||
let result = [
|
||||
"bookmarks-menu-button",
|
||||
"search-container",
|
||||
"open-file-button",
|
||||
"developer-button",
|
||||
"feed-button",
|
||||
|
|
|
@ -64,6 +64,10 @@ function clickSearchbarSuggestion(entryName) {
|
|||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({ set: [
|
||||
["browser.search.widget.inNavBar", true],
|
||||
]});
|
||||
|
||||
// Create two new search engines. Mark one as the default engine, so
|
||||
// the test don't crash. We need to engines for this test as the searchbar
|
||||
// doesn't display the default search engine among the one-off engines.
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
@namespace svg url("http://www.w3.org/2000/svg");
|
||||
|
||||
%include ../shared/browser.inc.css
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
@namespace svg url("http://www.w3.org/2000/svg");
|
||||
|
||||
%include ../shared/browser.inc.css
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
@namespace svg url("http://www.w3.org/2000/svg");
|
||||
|
||||
%include ../shared/browser.inc.css
|
||||
|
||||
|
|
|
@ -44,12 +44,6 @@ if not CONFIG['MOZ_SYSTEM_PNG']:
|
|||
if CONFIG['CPU_ARCH'] == 'arm':
|
||||
external_dirs += ['media/openmax_dl']
|
||||
|
||||
if CONFIG['MOZ_WEBSPEECH_POCKETSPHINX']:
|
||||
external_dirs += [
|
||||
'media/sphinxbase',
|
||||
'media/pocketsphinx',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_FFVPX']:
|
||||
external_dirs += ['media/ffvpx']
|
||||
|
||||
|
|
|
@ -3,17 +3,28 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* This file should not be modified and is a duplicate from the debugger.html project.
|
||||
* Any changes to this file should be imported from the upstream debugger.html project.
|
||||
* This file is a duplicate from the debugger.html project and has diverged in terms of
|
||||
* some of styles that are kept. Any changes to the styles in this file should be synced
|
||||
* back to the appropriate styles in the debugger.html project.
|
||||
* Create a pull request at https://github.com/devtools-html/debugger.html to sync
|
||||
* any changes to the existing styles.
|
||||
*/
|
||||
|
||||
:root {
|
||||
--accordion-header-background: var(--theme-toolbar-background);
|
||||
}
|
||||
|
||||
:root.theme-dark {
|
||||
--accordion-header-background: #141416;
|
||||
}
|
||||
|
||||
.accordion {
|
||||
background-color: var(--theme-body-background);
|
||||
background-color: var(--theme-sidebar-background);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.accordion ._header {
|
||||
background-color: var(--theme-toolbar-background);
|
||||
background-color: var(--accordion-header-background);
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<link rel="stylesheet" href="chrome://devtools/content/netmonitor/src/assets/styles/netmonitor.css"/>
|
||||
<script src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||
</head>
|
||||
<body class="theme-sidebar" role="application">
|
||||
<body class="theme-body" role="application">
|
||||
<div id="mount"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
@ -38,25 +38,36 @@
|
|||
window.Netmonitor = {
|
||||
bootstrap({ toolbox }) {
|
||||
this.mount = document.querySelector("#mount");
|
||||
|
||||
const connection = {
|
||||
tabConnection: {
|
||||
tabTarget: toolbox.target,
|
||||
},
|
||||
toolbox,
|
||||
};
|
||||
|
||||
const openLink = (link) => {
|
||||
let parentDoc = toolbox.doc;
|
||||
let iframe = parentDoc.getElementById("toolbox-panel-iframe-netmonitor");
|
||||
let top = iframe.ownerDocument.defaultView.top;
|
||||
top.openUILinkIn(link, "tab");
|
||||
};
|
||||
|
||||
const App = createFactory(require("./src/components/app"));
|
||||
const sourceMapService = toolbox.sourceMapURLService;
|
||||
render(Provider({ store }, App({ sourceMapService })), this.mount);
|
||||
const app = App({ sourceMapService, openLink });
|
||||
render(Provider({ store }, app), this.mount);
|
||||
return onFirefoxConnect(connection, actions, store.getState);
|
||||
},
|
||||
|
||||
destroy() {
|
||||
unmountComponentAtNode(this.mount);
|
||||
return onDisconnect();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Implement support for chrome://devtools/content/netmonitor/index.html?type=tab&id=1234 URLs
|
||||
// Implement support for:
|
||||
// chrome://devtools/content/netmonitor/index.html?type=tab&id=1234 URLs
|
||||
// where 1234 is the tab id, you can retrieve from about:debugging#tabs links.
|
||||
// Simply copy the id from about:devtools-toolbox?type=tab&id=1234 URLs.
|
||||
|
||||
|
@ -64,7 +75,8 @@
|
|||
let href = window.location.href.replace(/chrome:/, "http://");
|
||||
let url = new window.URL(href);
|
||||
|
||||
// If query parameters are given in a chrome tab, the inspector is running in standalone.
|
||||
// If query parameters are given in a chrome tab, the inspector
|
||||
// is running in standalone.
|
||||
if (window.location.protocol === "chrome:" && url.search.length > 1) {
|
||||
const { targetFromURL } = require("devtools/client/framework/target-from-url");
|
||||
|
||||
|
@ -83,7 +95,8 @@
|
|||
};
|
||||
window.Netmonitor.bootstrap({ toolbox });
|
||||
})().catch(e => {
|
||||
window.alert("Unable to start the network monitor:" + e.message + "\n" + e.stack);
|
||||
window.alert("Unable to start the network monitor:" +
|
||||
e.message + "\n" + e.stack);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -21,10 +21,14 @@ const { div } = DOM;
|
|||
* App component
|
||||
* The top level component for representing main panel
|
||||
*/
|
||||
function App({ statisticsOpen, sourceMapService }) {
|
||||
function App({
|
||||
openLink,
|
||||
sourceMapService,
|
||||
statisticsOpen,
|
||||
}) {
|
||||
return (
|
||||
div({ className: "network-monitor" },
|
||||
!statisticsOpen ? MonitorPanel({sourceMapService}) : StatisticsPanel()
|
||||
!statisticsOpen ? MonitorPanel({ openLink, sourceMapService }) : StatisticsPanel()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -32,9 +36,10 @@ function App({ statisticsOpen, sourceMapService }) {
|
|||
App.displayName = "App";
|
||||
|
||||
App.propTypes = {
|
||||
statisticsOpen: PropTypes.bool.isRequired,
|
||||
openLink: PropTypes.func,
|
||||
// Service to enable the source map feature.
|
||||
sourceMapService: PropTypes.object,
|
||||
statisticsOpen: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
module.exports = connect(
|
||||
|
|
|
@ -31,6 +31,7 @@ const SECTION_NAMES = [
|
|||
*/
|
||||
function CookiesPanel({
|
||||
request,
|
||||
openLink,
|
||||
}) {
|
||||
let {
|
||||
requestCookies = { cookies: [] },
|
||||
|
@ -62,6 +63,7 @@ function CookiesPanel({
|
|||
object,
|
||||
filterPlaceHolder: COOKIES_FILTER_TEXT,
|
||||
sectionNames: SECTION_NAMES,
|
||||
openLink,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -71,6 +73,7 @@ CookiesPanel.displayName = "CookiesPanel";
|
|||
|
||||
CookiesPanel.propTypes = {
|
||||
request: PropTypes.object.isRequired,
|
||||
openLink: PropTypes.func,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,7 +54,8 @@ const HeadersPanel = createClass({
|
|||
propTypes: {
|
||||
cloneSelectedRequest: PropTypes.func.isRequired,
|
||||
request: PropTypes.object.isRequired,
|
||||
renderValue: PropTypes.func
|
||||
renderValue: PropTypes.func,
|
||||
openLink: PropTypes.func,
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
|
@ -125,6 +126,7 @@ const HeadersPanel = createClass({
|
|||
|
||||
render() {
|
||||
const {
|
||||
openLink,
|
||||
cloneSelectedRequest,
|
||||
request: {
|
||||
fromCache,
|
||||
|
@ -256,6 +258,7 @@ const HeadersPanel = createClass({
|
|||
filterPlaceHolder: HEADERS_FILTER_TEXT,
|
||||
sectionNames: Object.keys(object),
|
||||
renderValue: this.renderValue,
|
||||
openLink,
|
||||
}),
|
||||
)
|
||||
);
|
||||
|
|
|
@ -40,6 +40,7 @@ const MonitorPanel = createClass({
|
|||
request: PropTypes.object,
|
||||
// Service to enable the source map feature.
|
||||
sourceMapService: PropTypes.object,
|
||||
openLink: PropTypes.func,
|
||||
updateRequest: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
|
@ -104,7 +105,13 @@ const MonitorPanel = createClass({
|
|||
},
|
||||
|
||||
render() {
|
||||
let { isEmpty, networkDetailsOpen, sourceMapService } = this.props;
|
||||
let {
|
||||
isEmpty,
|
||||
networkDetailsOpen,
|
||||
sourceMapService,
|
||||
openLink
|
||||
} = this.props;
|
||||
|
||||
let initialWidth = Services.prefs.getIntPref(
|
||||
"devtools.netmonitor.panes-network-details-width");
|
||||
let initialHeight = Services.prefs.getIntPref(
|
||||
|
@ -123,6 +130,7 @@ const MonitorPanel = createClass({
|
|||
endPanel: networkDetailsOpen && NetworkDetailsPanel({
|
||||
ref: "endPanel",
|
||||
sourceMapService,
|
||||
openLink,
|
||||
}),
|
||||
endPanelCollapsed: !networkDetailsOpen,
|
||||
endPanelControl: true,
|
||||
|
|
|
@ -28,6 +28,7 @@ function NetworkDetailsPanel({
|
|||
request,
|
||||
selectTab,
|
||||
sourceMapService,
|
||||
openLink,
|
||||
}) {
|
||||
if (!request) {
|
||||
return null;
|
||||
|
@ -38,10 +39,11 @@ function NetworkDetailsPanel({
|
|||
!request.isCustom ?
|
||||
TabboxPanel({
|
||||
activeTabId,
|
||||
cloneSelectedRequest,
|
||||
request,
|
||||
selectTab,
|
||||
sourceMapService,
|
||||
cloneSelectedRequest,
|
||||
openLink,
|
||||
}) :
|
||||
CustomRequestPanel({
|
||||
request,
|
||||
|
@ -60,6 +62,7 @@ NetworkDetailsPanel.propTypes = {
|
|||
selectTab: PropTypes.func.isRequired,
|
||||
// Service to enable the source map feature.
|
||||
sourceMapService: PropTypes.object,
|
||||
openLink: PropTypes.func,
|
||||
};
|
||||
|
||||
module.exports = connect(
|
||||
|
|
|
@ -34,7 +34,10 @@ const SECTION_NAMES = [
|
|||
* Params panel component
|
||||
* Displays the GET parameters and POST data of a request
|
||||
*/
|
||||
function ParamsPanel({ request }) {
|
||||
function ParamsPanel({
|
||||
openLink,
|
||||
request,
|
||||
}) {
|
||||
let {
|
||||
formDataSections,
|
||||
mimeType,
|
||||
|
@ -92,6 +95,7 @@ function ParamsPanel({ request }) {
|
|||
object,
|
||||
filterPlaceHolder: PARAMS_FILTER_TEXT,
|
||||
sectionNames: SECTION_NAMES,
|
||||
openLink,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -101,6 +105,7 @@ ParamsPanel.displayName = "ParamsPanel";
|
|||
|
||||
ParamsPanel.propTypes = {
|
||||
request: PropTypes.object.isRequired,
|
||||
openLink: PropTypes.func,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,6 +49,7 @@ const PropertiesView = createClass({
|
|||
expandableStrings: PropTypes.bool,
|
||||
filterPlaceHolder: PropTypes.string,
|
||||
sectionNames: PropTypes.array,
|
||||
openLink: PropTypes.func,
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
|
@ -148,6 +149,7 @@ const PropertiesView = createClass({
|
|||
renderRow,
|
||||
renderValue,
|
||||
sectionNames,
|
||||
openLink,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
|
@ -181,6 +183,7 @@ const PropertiesView = createClass({
|
|||
onFilter: (props) => this.onFilter(props, sectionNames),
|
||||
renderRow: renderRow || this.renderRowWithEditor,
|
||||
renderValue: renderValue || this.renderValueWithRep,
|
||||
openLink,
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -33,6 +33,7 @@ const ResponsePanel = createClass({
|
|||
|
||||
propTypes: {
|
||||
request: PropTypes.object.isRequired,
|
||||
openLink: PropTypes.func,
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
|
@ -110,7 +111,8 @@ const ResponsePanel = createClass({
|
|||
},
|
||||
|
||||
render() {
|
||||
let { responseContent, url } = this.props.request;
|
||||
let { openLink, request } = this.props;
|
||||
let { responseContent, url } = request;
|
||||
|
||||
if (!responseContent || typeof responseContent.content.text !== "string") {
|
||||
return null;
|
||||
|
@ -175,6 +177,7 @@ const ResponsePanel = createClass({
|
|||
object,
|
||||
filterPlaceHolder: JSON_FILTER_TEXT,
|
||||
sectionNames: Object.keys(object),
|
||||
openLink,
|
||||
}),
|
||||
)
|
||||
);
|
||||
|
|
|
@ -24,7 +24,10 @@ const { div, input, span } = DOM;
|
|||
* This contains details about the secure connection used including the protocol,
|
||||
* the cipher suite, and certificate details
|
||||
*/
|
||||
function SecurityPanel({ request }) {
|
||||
function SecurityPanel({
|
||||
openLink,
|
||||
request,
|
||||
}) {
|
||||
const { securityInfo, url } = request;
|
||||
|
||||
if (!securityInfo || !url) {
|
||||
|
@ -101,6 +104,7 @@ function SecurityPanel({ request }) {
|
|||
renderValue: (props) => renderValue(props, securityInfo.weaknessReasons),
|
||||
enableFilter: false,
|
||||
expandedNodes: TreeViewClass.getExpandedNodes(object),
|
||||
openLink,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -109,6 +113,7 @@ SecurityPanel.displayName = "SecurityPanel";
|
|||
|
||||
SecurityPanel.propTypes = {
|
||||
request: PropTypes.object.isRequired,
|
||||
openLink: PropTypes.func,
|
||||
};
|
||||
|
||||
function renderValue(props, weaknessReasons = []) {
|
||||
|
|
|
@ -16,7 +16,11 @@ const { div } = DOM;
|
|||
// Components
|
||||
const StackTrace = createFactory(require("devtools/client/shared/components/stack-trace"));
|
||||
|
||||
function StackTracePanel({ request, sourceMapService }) {
|
||||
function StackTracePanel({
|
||||
openLink,
|
||||
request,
|
||||
sourceMapService,
|
||||
}) {
|
||||
let { stacktrace } = request.cause;
|
||||
|
||||
return (
|
||||
|
@ -25,6 +29,7 @@ function StackTracePanel({ request, sourceMapService }) {
|
|||
stacktrace,
|
||||
onViewSourceInDebugger: ({ url, line }) => viewSourceInDebugger(url, line),
|
||||
sourceMapService,
|
||||
openLink,
|
||||
}),
|
||||
)
|
||||
);
|
||||
|
@ -36,6 +41,7 @@ StackTracePanel.propTypes = {
|
|||
request: PropTypes.object.isRequired,
|
||||
// Service to enable the source map feature.
|
||||
sourceMapService: PropTypes.object,
|
||||
openLink: PropTypes.func,
|
||||
};
|
||||
|
||||
module.exports = StackTracePanel;
|
||||
|
|
|
@ -41,6 +41,7 @@ function TabboxPanel({
|
|||
request,
|
||||
selectTab,
|
||||
sourceMapService,
|
||||
openLink,
|
||||
}) {
|
||||
if (!request) {
|
||||
return null;
|
||||
|
@ -58,25 +59,25 @@ function TabboxPanel({
|
|||
id: PANELS.HEADERS,
|
||||
title: HEADERS_TITLE,
|
||||
},
|
||||
HeadersPanel({ request, cloneSelectedRequest }),
|
||||
HeadersPanel({ request, cloneSelectedRequest, openLink }),
|
||||
),
|
||||
TabPanel({
|
||||
id: PANELS.COOKIES,
|
||||
title: COOKIES_TITLE,
|
||||
},
|
||||
CookiesPanel({ request }),
|
||||
CookiesPanel({ request, openLink }),
|
||||
),
|
||||
TabPanel({
|
||||
id: PANELS.PARAMS,
|
||||
title: PARAMS_TITLE,
|
||||
},
|
||||
ParamsPanel({ request }),
|
||||
ParamsPanel({ request, openLink }),
|
||||
),
|
||||
TabPanel({
|
||||
id: PANELS.RESPONSE,
|
||||
title: RESPONSE_TITLE,
|
||||
},
|
||||
ResponsePanel({ request }),
|
||||
ResponsePanel({ request, openLink }),
|
||||
),
|
||||
TabPanel({
|
||||
id: PANELS.TIMINGS,
|
||||
|
@ -89,14 +90,14 @@ function TabboxPanel({
|
|||
id: PANELS.STACK_TRACE,
|
||||
title: STACK_TRACE_TITLE,
|
||||
},
|
||||
StackTracePanel({ request, sourceMapService }),
|
||||
StackTracePanel({ request, sourceMapService, openLink }),
|
||||
),
|
||||
request.securityState && request.securityState !== "insecure" &&
|
||||
TabPanel({
|
||||
id: PANELS.SECURITY,
|
||||
title: SECURITY_TITLE,
|
||||
},
|
||||
SecurityPanel({ request }),
|
||||
SecurityPanel({ request, openLink }),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
@ -111,6 +112,7 @@ TabboxPanel.propTypes = {
|
|||
selectTab: PropTypes.func.isRequired,
|
||||
// Service to enable the source map feature.
|
||||
sourceMapService: PropTypes.object,
|
||||
openLink: PropTypes.func,
|
||||
};
|
||||
|
||||
module.exports = connect()(TabboxPanel);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
.tabs {
|
||||
height: 100%;
|
||||
background: var(--theme-body-background);
|
||||
background: var(--theme-sidebar-background);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
|
|
@ -117,7 +117,9 @@ window {
|
|||
border-bottom-width: 0px;
|
||||
border-top-width: 1px;
|
||||
border-top-color: var(--theme-splitter-color);
|
||||
background-color: var(--theme-toolbar-background);
|
||||
/* Bug 1262668 - Use the same background as the body so the breadcrumbs toolbar doesn't
|
||||
get mistaken as a splitter */
|
||||
background-color: var(--theme-body-background);
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
.theme-light {
|
||||
--rule-highlight-background-color: #ffee99;
|
||||
--rule-overridden-item-border-color: var(--theme-content-color3);
|
||||
--rule-header-background-color: var(--theme-toolbar-background);
|
||||
}
|
||||
|
||||
.theme-dark {
|
||||
--rule-highlight-background-color: #594724;
|
||||
--rule-overridden-item-border-color: var(--theme-content-color1);
|
||||
--rule-header-background-color: #141416;
|
||||
}
|
||||
|
||||
.theme-firebug {
|
||||
|
@ -18,6 +20,7 @@
|
|||
--rule-property-name: darkgreen;
|
||||
--rule-property-value: darkblue;
|
||||
--rule-overridden-item-border-color: var(--theme-content-color2);
|
||||
--rule-header-background-color: var(--theme-header-background);
|
||||
}
|
||||
|
||||
/* Rule View Tabpanel */
|
||||
|
@ -219,7 +222,7 @@
|
|||
}
|
||||
|
||||
.ruleview-header {
|
||||
background-color: var(--theme-toolbar-background);
|
||||
background-color: var(--rule-header-background-color);
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
font-size: 12px;
|
||||
padding: 4px;
|
||||
|
@ -239,7 +242,6 @@
|
|||
padding: 3px 4px 2px 4px;
|
||||
line-height: inherit;
|
||||
min-height: 0;
|
||||
background: var(--theme-header-background);
|
||||
}
|
||||
|
||||
:root[platform="win"] .ruleview-header,
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
|
||||
:root.theme-dark {
|
||||
--theme-body-background: var(--grey-80);
|
||||
--theme-sidebar-background: var(--grey-80);
|
||||
--theme-sidebar-background: var(--grey-90);
|
||||
--theme-contrast-background: #ffb35b;
|
||||
|
||||
/* Toolbar */
|
||||
|
|
|
@ -233,7 +233,7 @@
|
|||
/* The color of the thin line in the arrow-shaped separator between 2 unselected
|
||||
crumbs. There is no theme variable for this, this used to be an image. */
|
||||
--line-color: #ACACAC;
|
||||
--background-color: var(--theme-toolbar-background);
|
||||
--background-color: var(--theme-body-background);
|
||||
}
|
||||
|
||||
#debugger-toolbar .breadcrumbs-widget-item::before {
|
||||
|
|
|
@ -107,6 +107,7 @@ function NetworkEventMessage({
|
|||
activeTabId: networkMessageActiveTabId,
|
||||
request: networkMessageUpdate,
|
||||
sourceMapService: serviceContainer.sourceMapService,
|
||||
openLink: serviceContainer.openLink,
|
||||
selectTab: (tabId) => {
|
||||
dispatch(actions.selectNetworkMessageTab(tabId));
|
||||
},
|
||||
|
|
|
@ -80,7 +80,9 @@ NewConsoleOutputWrapper.prototype = {
|
|||
}]));
|
||||
},
|
||||
hudProxyClient: this.jsterm.hud.proxy.client,
|
||||
openLink: url => this.jsterm.hud.owner.openLink(url),
|
||||
openLink: url => {
|
||||
this.jsterm.hud.owner.openLink(url);
|
||||
},
|
||||
createElement: nodename => {
|
||||
return this.document.createElementNS("http://www.w3.org/1999/xhtml", nodename);
|
||||
},
|
||||
|
|
|
@ -915,6 +915,7 @@ function CssRule(cssSheet, domRule, element) {
|
|||
// parse domRule.selectorText on call to this.selectors
|
||||
this._selectors = null;
|
||||
this.line = domUtils.getRuleLine(this.domRule);
|
||||
this.column = domUtils.getRuleColumn(this.domRule);
|
||||
this.source = this._cssSheet.shortSource + ":" + this.line;
|
||||
if (this.mediaText) {
|
||||
this.source += " @media " + this.mediaText;
|
||||
|
@ -1107,6 +1108,16 @@ CssSelector.prototype = {
|
|||
return this.cssRule.line;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the column of the parent CSSStyleRule in the parent CSSStyleSheet.
|
||||
*
|
||||
* @return {number} the column of the parent CSSStyleRule in the parent
|
||||
* stylesheet.
|
||||
*/
|
||||
get ruleColumn() {
|
||||
return this.cssRule.column;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve specificity information for the current selector.
|
||||
*
|
||||
|
@ -1391,6 +1402,16 @@ CssSelectorInfo.prototype = {
|
|||
return this.selector.ruleLine;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the column of the parent CSSStyleRule in the parent CSSStyleSheet.
|
||||
*
|
||||
* @return {number} the column of the parent CSSStyleRule in the parent
|
||||
* stylesheet.
|
||||
*/
|
||||
get ruleColumn() {
|
||||
return this.selector.ruleColumn;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the selector comes from a browser-provided stylesheet.
|
||||
*
|
||||
|
@ -1458,6 +1479,13 @@ CssSelectorInfo.prototype = {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (this.ruleColumn > that.ruleColumn) {
|
||||
return -1;
|
||||
}
|
||||
if (that.ruleColumn > this.ruleColumn) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
.inheritable-rule {
|
||||
font-size: 15px;
|
||||
}
|
||||
/* Has to be on one line, is such for test */
|
||||
.column-rule { font-size: 20px; } .column-rule { font-size: 25px; }
|
||||
.uninheritable-rule {
|
||||
background-color: #f06;
|
||||
}
|
||||
|
@ -62,7 +64,7 @@
|
|||
</div>
|
||||
|
||||
<!-- Matched checks -->
|
||||
<div id="matched-parent" class="external-rule inheritable-rule uninheritable-rule" style="color: red;">
|
||||
<div id="matched-parent" class="external-rule inheritable-rule column-rule uninheritable-rule" style="color: red;">
|
||||
<div id="matched-test-node" style="font-size: 10px" class="external-rule">
|
||||
Here is the test node.
|
||||
</div>
|
||||
|
|
|
@ -52,17 +52,23 @@ addTest(function testMatchedStyles() {
|
|||
is(matched[0].rule.href, gInspectee.defaultView.location.href,
|
||||
"Node style comes from this document");
|
||||
|
||||
is(matched[1].sourceText, ".inheritable-rule", "Second match comes from a rule");
|
||||
is(matched[1].selector, ".inheritable-rule", "Second style has a selector");
|
||||
is(matched[1].value, "15px", "Second match has the expected value");
|
||||
is(matched[1].sourceText, ".column-rule",
|
||||
"Second match comes from a rule");
|
||||
is(matched[1].selector, ".column-rule",
|
||||
"Second match comes from highest line number");
|
||||
is(matched[1].value, "25px", "Second match comes from highest column");
|
||||
is(matched[1].status, CssLogic.STATUS.PARENT_MATCH,
|
||||
"Second match is from the parent");
|
||||
"Second match is from the parent");
|
||||
is(matched[1].rule.parentStyleSheet.href, null,
|
||||
"Inline stylesheet shouldn't have an href");
|
||||
"Inline stylesheet shouldn't have an href");
|
||||
is(matched[1].rule.parentStyleSheet.nodeHref, gInspectee.defaultView.location.href,
|
||||
"Inline stylesheet's nodeHref should match the current document");
|
||||
"Inline stylesheet's nodeHref should match the current document");
|
||||
ok(!matched[1].rule.parentStyleSheet.system,
|
||||
"Inline stylesheet shouldn't be a system stylesheet.");
|
||||
"Inline stylesheet shouldn't be a system stylesheet.");
|
||||
|
||||
// matched[2] is only there to test matched[1]; do not need to test
|
||||
|
||||
is(matched[3].value, "15px", "Third match has the expected value");
|
||||
}).then(runNextTest));
|
||||
});
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "nsArray.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsContentSecurityManager.h"
|
||||
#include "nsICaptivePortalService.h"
|
||||
#include "nsIDOMStorage.h"
|
||||
#include "nsIContentViewer.h"
|
||||
|
@ -221,6 +222,7 @@
|
|||
#include "mozilla/dom/PerformanceNavigation.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/Encoding.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "IUrlClassifierUITelemetry.h"
|
||||
|
||||
#ifdef MOZ_TOOLKIT_SEARCH
|
||||
|
@ -9942,36 +9944,13 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
|||
isTargetTopLevelDocShell = true;
|
||||
}
|
||||
|
||||
if (contentType == nsIContentPolicy::TYPE_DOCUMENT &&
|
||||
nsIOService::BlockToplevelDataUriNavigations()) {
|
||||
bool isDataURI =
|
||||
(NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI);
|
||||
// Let's block all toplevel document navigations to a data: URI.
|
||||
// In all cases where the toplevel document is navigated to a
|
||||
// data: URI the triggeringPrincipal is a codeBasePrincipal, or
|
||||
// a NullPrincipal. In other cases, e.g. typing a data: URL into
|
||||
// the URL-Bar, the triggeringPrincipal is a SystemPrincipal;
|
||||
// we don't want to block those loads. Only exception, loads coming
|
||||
// from an external applicaton (e.g. Thunderbird) don't load
|
||||
// using a codeBasePrincipal, but we want to block those loads.
|
||||
bool loadFromExternal = (aLoadType == LOAD_NORMAL_EXTERNAL);
|
||||
if (isDataURI && (loadFromExternal ||
|
||||
!nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal))) {
|
||||
NS_ConvertUTF8toUTF16 specUTF16(aURI->GetSpecOrDefault());
|
||||
if (specUTF16.Length() > 50) {
|
||||
specUTF16.Truncate(50);
|
||||
specUTF16.AppendLiteral("...");
|
||||
}
|
||||
const char16_t* params[] = { specUTF16.get() };
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DATA_URI_BLOCKED"),
|
||||
// no doc available, log to browser console
|
||||
nullptr,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"BlockTopLevelDataURINavigation",
|
||||
params, ArrayLength(params));
|
||||
return NS_OK;
|
||||
}
|
||||
if (!nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
|
||||
aURI,
|
||||
contentType,
|
||||
aTriggeringPrincipal,
|
||||
(aLoadType == LOAD_NORMAL_EXTERNAL))) {
|
||||
// logging to console happens within AllowTopLevelNavigationToDataURI
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If there's no targetDocShell, that means we are about to create a new
|
||||
|
@ -11726,6 +11705,11 @@ nsDocShell::DoChannelLoad(nsIChannel* aChannel,
|
|||
rv = aURILoader->OpenURI(aChannel, openFlags, this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We're about to load a new page and it may take time before necko
|
||||
// gives back any data, so main thread might have a chance to process a
|
||||
// collector slice
|
||||
nsJSContext::MaybeRunNextCollectorSlice(this, JS::gcreason::DOCSHELL);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,6 +111,10 @@ DocumentFragment::Constructor(const GlobalObject& aGlobal,
|
|||
return window->GetDoc()->CreateDocumentFragment();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(DocumentFragment,
|
||||
FragmentOrElement,
|
||||
mHost)
|
||||
|
||||
// QueryInterface implementation for DocumentFragment
|
||||
NS_INTERFACE_MAP_BEGIN(DocumentFragment)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
|
|
|
@ -43,6 +43,8 @@ public:
|
|||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DocumentFragment,
|
||||
FragmentOrElement)
|
||||
|
||||
// interface nsIDOMNode
|
||||
NS_FORWARD_NSIDOMNODE_TO_NSINODE
|
||||
|
@ -120,12 +122,12 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsIContent* GetHost() const
|
||||
Element* GetHost() const
|
||||
{
|
||||
return mHost;
|
||||
}
|
||||
|
||||
void SetHost(nsIContent* aHost)
|
||||
void SetHost(Element* aHost)
|
||||
{
|
||||
mHost = aHost;
|
||||
}
|
||||
|
@ -145,7 +147,7 @@ protected:
|
|||
|
||||
nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||
bool aPreallocateChildren) const override;
|
||||
nsIContent* mHost; // Weak
|
||||
nsCOMPtr<Element> mHost;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -59,14 +59,14 @@ NS_INTERFACE_MAP_END_INHERITING(DocumentFragment)
|
|||
NS_IMPL_ADDREF_INHERITED(ShadowRoot, DocumentFragment)
|
||||
NS_IMPL_RELEASE_INHERITED(ShadowRoot, DocumentFragment)
|
||||
|
||||
ShadowRoot::ShadowRoot(nsIContent* aContent,
|
||||
ShadowRoot::ShadowRoot(Element* aElement,
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
nsXBLPrototypeBinding* aProtoBinding)
|
||||
: DocumentFragment(aNodeInfo), mPoolHost(aContent),
|
||||
: DocumentFragment(aNodeInfo), mPoolHost(aElement),
|
||||
mProtoBinding(aProtoBinding), mShadowElement(nullptr),
|
||||
mInsertionPointChanged(false), mIsComposedDocParticipant(false)
|
||||
{
|
||||
SetHost(aContent);
|
||||
SetHost(aElement);
|
||||
|
||||
// Nodes in a shadow tree should never store a value
|
||||
// in the subtree root pointer, nodes in the shadow tree
|
||||
|
@ -75,7 +75,7 @@ ShadowRoot::ShadowRoot(nsIContent* aContent,
|
|||
|
||||
SetFlags(NODE_IS_IN_SHADOW_TREE);
|
||||
|
||||
ExtendedDOMSlots()->mBindingParent = aContent;
|
||||
ExtendedDOMSlots()->mBindingParent = aElement;
|
||||
ExtendedDOMSlots()->mContainingShadow = this;
|
||||
|
||||
// Add the ShadowRoot as a mutation observer on the host to watch
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
|
||||
ShadowRoot(nsIContent* aContent, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
ShadowRoot(Element* aElement, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
nsXBLPrototypeBinding* aProtoBinding);
|
||||
|
||||
void AddToIdTable(Element* aElement, nsIAtom* aId);
|
||||
|
|
|
@ -1438,7 +1438,7 @@ nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener *aListener)
|
|||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::RunNextCollectorTimer()
|
||||
{
|
||||
nsJSContext::RunNextCollectorTimer();
|
||||
nsJSContext::RunNextCollectorTimer(JS::gcreason::DOM_WINDOW_UTILS);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -12771,23 +12771,23 @@ nsDocument::DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const
|
|||
// PresShell, which contains the frame tree.
|
||||
nsIDocument::DocAddSizeOfExcludingThis(aWindowSizes);
|
||||
|
||||
aWindowSizes.mStyleSheetsSize +=
|
||||
aWindowSizes.mLayoutStyleSheetsSize +=
|
||||
SizeOfOwnedSheetArrayExcludingThis(mStyleSheets,
|
||||
aWindowSizes.mState.mMallocSizeOf);
|
||||
// Note that we do not own the sheets pointed to by mOnDemandBuiltInUASheets
|
||||
// (the nsLayoutStyleSheetCache singleton does).
|
||||
aWindowSizes.mStyleSheetsSize +=
|
||||
aWindowSizes.mLayoutStyleSheetsSize +=
|
||||
mOnDemandBuiltInUASheets.ShallowSizeOfExcludingThis(
|
||||
aWindowSizes.mState.mMallocSizeOf);
|
||||
for (auto& sheetArray : mAdditionalSheets) {
|
||||
aWindowSizes.mStyleSheetsSize +=
|
||||
aWindowSizes.mLayoutStyleSheetsSize +=
|
||||
SizeOfOwnedSheetArrayExcludingThis(sheetArray,
|
||||
aWindowSizes.mState.mMallocSizeOf);
|
||||
}
|
||||
// Lumping in the loader with the style-sheets size is not ideal,
|
||||
// but most of the things in there are in fact stylesheets, so it
|
||||
// doesn't seem worthwhile to separate it out.
|
||||
aWindowSizes.mStyleSheetsSize +=
|
||||
aWindowSizes.mLayoutStyleSheetsSize +=
|
||||
CSSLoader()->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
|
||||
|
||||
aWindowSizes.mDOMOtherSize += mAttrStyleSheet
|
||||
|
|
|
@ -340,8 +340,8 @@ interface nsIContentPolicy : nsISupports
|
|||
/* When adding new content types, please update nsContentBlocker,
|
||||
* NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
|
||||
* implementations, the static_assert in dom/cache/DBSchema.cpp,
|
||||
* and other things that are not listed here that are related to
|
||||
* nsIContentPolicy. */
|
||||
* ChannelWrapper.webidl, ChannelWrapper.cpp, and other things that
|
||||
* are not listed here that are related to nsIContentPolicy. */
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -83,10 +83,14 @@
|
|||
#include "mozilla/dom/asmjscache/AsmJSCache.h"
|
||||
#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
#include "nsCycleCollectionNoteRootCallback.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "mozilla/IdleTaskRunner.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsViewManager.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -216,12 +220,6 @@ static bool sCompactOnUserInactive;
|
|||
static uint32_t sCompactOnUserInactiveDelay = NS_DEAULT_INACTIVE_GC_DELAY;
|
||||
static bool sIsCompactingOnUserInactive = false;
|
||||
|
||||
// In testing, we call RunNextCollectorTimer() to ensure that the collectors are run more
|
||||
// aggressively than they would be in regular browsing. sExpensiveCollectorPokes keeps
|
||||
// us from triggering expensive full collections too frequently.
|
||||
static int32_t sExpensiveCollectorPokes = 0;
|
||||
static const int32_t kPokesBetweenExpensiveCollectorTriggers = 5;
|
||||
|
||||
static TimeDuration sGCUnnotifiedTotalTime;
|
||||
|
||||
static const char*
|
||||
|
@ -1980,62 +1978,98 @@ nsJSContext::LoadEnd()
|
|||
sLoadingInProgress = false;
|
||||
}
|
||||
|
||||
// Only trigger expensive timers when they have been checked a number of times.
|
||||
static bool
|
||||
ReadyToTriggerExpensiveCollectorTimer()
|
||||
{
|
||||
bool ready = kPokesBetweenExpensiveCollectorTriggers < ++sExpensiveCollectorPokes;
|
||||
if (ready) {
|
||||
sExpensiveCollectorPokes = 0;
|
||||
}
|
||||
return ready;
|
||||
}
|
||||
|
||||
|
||||
// Check all of the various collector timers/runners and see if they are waiting to fire.
|
||||
// For the synchronous collector timers/runners, sGCTimer and sCCRunner, we only want to
|
||||
// trigger the collection occasionally, because they are expensive. The incremental collector
|
||||
// timers, sInterSliceGCRunner and sICCRunner, are fast and need to be run many times, so
|
||||
// always run their corresponding timer.
|
||||
|
||||
// This does not check sFullGCTimer, as that's a more expensive collection we run
|
||||
// on a long timer.
|
||||
|
||||
// static
|
||||
void
|
||||
nsJSContext::RunNextCollectorTimer()
|
||||
nsJSContext::RunNextCollectorTimer(JS::gcreason::Reason aReason,
|
||||
mozilla::TimeStamp aDeadline)
|
||||
{
|
||||
if (sShuttingDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sGCTimer) {
|
||||
if (ReadyToTriggerExpensiveCollectorTimer()) {
|
||||
GCTimerFired(nullptr, reinterpret_cast<void *>(JS::gcreason::DOM_WINDOW_UTILS));
|
||||
}
|
||||
GCTimerFired(nullptr, reinterpret_cast<void*>(aReason));
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable;
|
||||
if (sInterSliceGCRunner) {
|
||||
InterSliceGCRunnerFired(TimeStamp(), nullptr);
|
||||
return;
|
||||
sInterSliceGCRunner->SetDeadline(aDeadline);
|
||||
runnable = sInterSliceGCRunner;
|
||||
} else {
|
||||
// Check the CC timers after the GC timers, because the CC timers won't do
|
||||
// anything if a GC is in progress.
|
||||
MOZ_ASSERT(!sCCLockedOut, "Don't check the CC timers if the CC is locked out.");
|
||||
}
|
||||
|
||||
// Check the CC timers after the GC timers, because the CC timers won't do
|
||||
// anything if a GC is in progress.
|
||||
MOZ_ASSERT(!sCCLockedOut, "Don't check the CC timers if the CC is locked out.");
|
||||
|
||||
if (sCCRunner) {
|
||||
if (ReadyToTriggerExpensiveCollectorTimer()) {
|
||||
CCRunnerFired(TimeStamp());
|
||||
}
|
||||
return;
|
||||
sCCRunner->SetDeadline(aDeadline);
|
||||
runnable = sCCRunner;
|
||||
}
|
||||
|
||||
if (sICCRunner) {
|
||||
ICCRunnerFired(TimeStamp());
|
||||
sICCRunner->SetDeadline(aDeadline);
|
||||
runnable = sICCRunner;
|
||||
}
|
||||
|
||||
if (runnable) {
|
||||
runnable->Run();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsJSContext::MaybeRunNextCollectorSlice(nsIDocShell* aDocShell,
|
||||
JS::gcreason::Reason aReason)
|
||||
{
|
||||
if (!aDocShell || !XRE_IsContentProcess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> root;
|
||||
aDocShell->GetSameTypeRootTreeItem(getter_AddRefs(root));
|
||||
if (root == aDocShell) {
|
||||
// We don't want to run collectors when loading the top level page.
|
||||
return;
|
||||
}
|
||||
|
||||
nsIDocument* rootDocument = root->GetDocument();
|
||||
if (!rootDocument ||
|
||||
rootDocument->GetReadyStateEnum() != nsIDocument::READYSTATE_COMPLETE ||
|
||||
rootDocument->IsInBackgroundWindow()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIPresShell* presShell = rootDocument->GetShell();
|
||||
if (!presShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsViewManager* vm = presShell->GetViewManager();
|
||||
if (!vm) {
|
||||
return;
|
||||
}
|
||||
|
||||
// GetLastUserEventTime returns microseconds.
|
||||
uint32_t lastEventTime = 0;
|
||||
vm->GetLastUserEventTime(lastEventTime);
|
||||
uint32_t currentTime =
|
||||
PR_IntervalToMicroseconds(PR_IntervalNow());
|
||||
// Only try to trigger collectors more often if user hasn't interacted with
|
||||
// the page for awhile.
|
||||
if ((currentTime - lastEventTime) >
|
||||
(NS_USER_INTERACTION_INTERVAL * PR_USEC_PER_MSEC)) {
|
||||
Maybe<TimeStamp> next = nsRefreshDriver::GetNextTickHint();
|
||||
// Try to not delay the next RefreshDriver tick, so give a reasonable
|
||||
// deadline for collectors.
|
||||
if (next.isSome()) {
|
||||
nsJSContext::RunNextCollectorTimer(aReason, next.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -2409,7 +2443,6 @@ mozilla::dom::StartupJSEnvironment()
|
|||
sDidShutdown = false;
|
||||
sShuttingDown = false;
|
||||
gCCStats.Init();
|
||||
sExpensiveCollectorPokes = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
class nsICycleCollectorListener;
|
||||
class nsScriptNameSpaceManager;
|
||||
class nsIDocShell;
|
||||
|
||||
namespace JS {
|
||||
class AutoValueVector;
|
||||
|
@ -101,7 +102,14 @@ public:
|
|||
static uint32_t GetMaxCCSliceTimeSinceClear();
|
||||
static void ClearMaxCCSliceTime();
|
||||
|
||||
static void RunNextCollectorTimer();
|
||||
// If there is some pending CC or GC timer/runner, this will run it.
|
||||
static void RunNextCollectorTimer(JS::gcreason::Reason aReason,
|
||||
mozilla::TimeStamp aDeadline = mozilla::TimeStamp());
|
||||
// If user has been idle and aDocShell is for an iframe being loaded in an
|
||||
// already loaded top level docshell, this will run a CC or GC
|
||||
// timer/runner if there is such pending.
|
||||
static void MaybeRunNextCollectorSlice(nsIDocShell* aDocShell,
|
||||
JS::gcreason::Reason aReason);
|
||||
|
||||
// The GC should probably run soon, in the zone of object aObj (if given).
|
||||
static void PokeGC(JS::gcreason::Reason aReason, JSObject* aObj, int aDelay = 0);
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "nsNodeInfoManager.h"
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/dom/NodeInfo.h"
|
||||
#include "mozilla/dom/NodeInfoInlines.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -420,9 +419,6 @@ nsNodeInfoManager::SetDocumentPrincipal(nsIPrincipal *aPrincipal)
|
|||
NS_ASSERTION(aPrincipal, "Must have principal by this point!");
|
||||
MOZ_DIAGNOSTIC_ASSERT(!nsContentUtils::IsExpandedPrincipal(aPrincipal),
|
||||
"Documents shouldn't have an expanded principal");
|
||||
if (nsContentUtils::IsExpandedPrincipal(aPrincipal)) {
|
||||
Telemetry::Accumulate(Telemetry::DOCUMENT_WITH_EXPANDED_PRINCIPAL, 1);
|
||||
}
|
||||
|
||||
mPrincipal = aPrincipal;
|
||||
}
|
||||
|
|
|
@ -1487,6 +1487,27 @@ nsRange::SetEnd(nsINode* aContainer, uint32_t aOffset)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::SelectNodesInContainer(nsINode* aContainer,
|
||||
nsIContent* aStartContent,
|
||||
nsIContent* aEndContent)
|
||||
{
|
||||
MOZ_ASSERT(aContainer);
|
||||
MOZ_ASSERT(aContainer->IndexOf(aStartContent) <= aContainer->IndexOf(aEndContent));
|
||||
MOZ_ASSERT(aStartContent && aContainer->IndexOf(aStartContent) != -1);
|
||||
MOZ_ASSERT(aEndContent && aContainer->IndexOf(aEndContent) != -1);
|
||||
|
||||
nsINode* newRoot = ComputeRootNode(aContainer, mMaySpanAnonymousSubtrees);
|
||||
MOZ_ASSERT(newRoot);
|
||||
if (!newRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
RawRangeBoundary start(aContainer, aStartContent->GetPreviousSibling());
|
||||
RawRangeBoundary end(aContainer, aEndContent);
|
||||
DoSetRange(start, end, newRoot);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRange::SetStartAndEnd(nsINode* aStartContainer, uint32_t aStartOffset,
|
||||
nsINode* aEndContainer, uint32_t aEndOffset)
|
||||
|
|
|
@ -172,6 +172,19 @@ public:
|
|||
nsresult SetStartAndEnd(nsINode* aStartContainer, uint32_t aStartOffset,
|
||||
nsINode* aEndContainer, uint32_t aEndOffset);
|
||||
|
||||
/**
|
||||
* Adds all nodes between |aStartContent| and |aEndContent| to the range.
|
||||
* The start offset will be set before |aStartContent|,
|
||||
* while the end offset will be set immediately after |aEndContent|.
|
||||
*
|
||||
* Caller must guarantee both nodes are non null and
|
||||
* children of |aContainer| and that |aEndContent| is after |aStartContent|.
|
||||
*/
|
||||
void
|
||||
SelectNodesInContainer(nsINode* aContainer,
|
||||
nsIContent* aStartContent,
|
||||
nsIContent* aEndContent);
|
||||
|
||||
/**
|
||||
* CollapseTo() works similar to call both SetStart() and SetEnd() with
|
||||
* same node and offset. This just calls SetStartAndParent() to set
|
||||
|
|
|
@ -35,7 +35,8 @@ const int32_t kTimeBetweenChecks = 45; /* seconds */
|
|||
nsWindowMemoryReporter::nsWindowMemoryReporter()
|
||||
: mLastCheckForGhostWindows(TimeStamp::NowLoRes()),
|
||||
mCycleCollectorIsRunning(false),
|
||||
mCheckTimerWaitingForCCEnd(false)
|
||||
mCheckTimerWaitingForCCEnd(false),
|
||||
mGhostWindowCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -120,8 +121,7 @@ nsWindowMemoryReporter::Init()
|
|||
/* weakRef = */ true);
|
||||
}
|
||||
|
||||
RegisterStrongMemoryReporter(new GhostWindowsReporter());
|
||||
RegisterGhostWindowsDistinguishedAmount(GhostWindowsReporter::DistinguishedAmount);
|
||||
RegisterGhostWindowsDistinguishedAmount(GhostWindowsDistinguishedAmount);
|
||||
}
|
||||
|
||||
/* static */ nsWindowMemoryReporter*
|
||||
|
@ -354,9 +354,10 @@ CollectWindowReports(nsGlobalWindow *aWindow,
|
|||
"other 'dom/' numbers.");
|
||||
aWindowTotalSizes->mDOMOtherSize += windowSizes.mDOMOtherSize;
|
||||
|
||||
REPORT_SIZE("/style-sheets", windowSizes.mStyleSheetsSize,
|
||||
REPORT_SIZE("/layout/style-sheets", windowSizes.mLayoutStyleSheetsSize,
|
||||
"Memory used by style sheets within a window.");
|
||||
aWindowTotalSizes->mStyleSheetsSize += windowSizes.mStyleSheetsSize;
|
||||
aWindowTotalSizes->mLayoutStyleSheetsSize +=
|
||||
windowSizes.mLayoutStyleSheetsSize;
|
||||
|
||||
REPORT_SIZE("/layout/pres-shell", windowSizes.mLayoutPresShellSize,
|
||||
"Memory used by layout's PresShell, along with any structures "
|
||||
|
@ -628,6 +629,17 @@ nsWindowMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
|
|||
aData);
|
||||
}
|
||||
|
||||
MOZ_COLLECT_REPORT(
|
||||
"ghost-windows", KIND_OTHER, UNITS_COUNT, ghostWindows.Count(),
|
||||
"The number of ghost windows present (the number of nodes underneath "
|
||||
"explicit/window-objects/top(none)/ghost, modulo race conditions). A ghost "
|
||||
"window is not shown in any tab, does not share a domain with any non-detached "
|
||||
"windows, and has met these criteria for at least "
|
||||
"memory.ghost_window_timeout_seconds, or has survived a round of "
|
||||
"about:memory's minimize memory usage button.\n\n"
|
||||
"Ghost windows can happen legitimately, but they are often indicative of "
|
||||
"leaks in the browser or add-ons.");
|
||||
|
||||
WindowPaths windowPaths;
|
||||
WindowPaths topWindowPaths;
|
||||
|
||||
|
@ -680,8 +692,9 @@ nsWindowMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
|
|||
REPORT("window-objects/dom/other", windowTotalSizes.mDOMOtherSize,
|
||||
"This is the sum of all windows' 'dom/other' numbers.");
|
||||
|
||||
REPORT("window-objects/style-sheets", windowTotalSizes.mStyleSheetsSize,
|
||||
"This is the sum of all windows' 'style-sheets' numbers.");
|
||||
REPORT("window-objects/layout/style-sheets",
|
||||
windowTotalSizes.mLayoutStyleSheetsSize,
|
||||
"This is the sum of all windows' 'layout/style-sheets' numbers.");
|
||||
|
||||
REPORT("window-objects/layout/pres-shell",
|
||||
windowTotalSizes.mLayoutPresShellSize,
|
||||
|
@ -921,6 +934,7 @@ nsWindowMemoryReporter::CheckForGhostWindows(
|
|||
KillCheckTimer();
|
||||
|
||||
nsTHashtable<nsCStringHashKey> nonDetachedWindowDomains;
|
||||
nsDataHashtable<nsISupportsHashKey, nsCString> domainMap;
|
||||
|
||||
// Populate nonDetachedWindowDomains.
|
||||
for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
|
||||
|
@ -935,8 +949,13 @@ nsWindowMemoryReporter::CheckForGhostWindows(
|
|||
nsCOMPtr<nsIURI> uri = GetWindowURI(window);
|
||||
nsAutoCString domain;
|
||||
if (uri) {
|
||||
tldService->GetBaseDomain(uri, 0, domain);
|
||||
domain = domainMap.LookupForAdd(uri).OrInsert([&]() {
|
||||
nsCString d;
|
||||
tldService->GetBaseDomain(uri, 0, d);
|
||||
return d;
|
||||
});
|
||||
}
|
||||
|
||||
nonDetachedWindowDomains.PutEntry(domain);
|
||||
}
|
||||
|
||||
|
@ -944,6 +963,7 @@ nsWindowMemoryReporter::CheckForGhostWindows(
|
|||
// if it's not null.
|
||||
uint32_t ghostTimeout = GetGhostTimeout();
|
||||
TimeStamp now = mLastCheckForGhostWindows;
|
||||
mGhostWindowCount = 0;
|
||||
for (auto iter = mDetachedWindows.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsWeakPtr weakKey = do_QueryInterface(iter.Key());
|
||||
nsCOMPtr<mozIDOMWindow> iwindow = do_QueryReferent(weakKey);
|
||||
|
@ -994,6 +1014,7 @@ nsWindowMemoryReporter::CheckForGhostWindows(
|
|||
} else if ((now - timeStamp).ToSeconds() > ghostTimeout) {
|
||||
// This definitely is a ghost window, so add it to aOutGhostIDs, if
|
||||
// that is not null.
|
||||
mGhostWindowCount++;
|
||||
if (aOutGhostIDs && window) {
|
||||
aOutGhostIDs->PutEntry(window->WindowID());
|
||||
}
|
||||
|
@ -1002,15 +1023,10 @@ nsWindowMemoryReporter::CheckForGhostWindows(
|
|||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsWindowMemoryReporter::GhostWindowsReporter,
|
||||
nsIMemoryReporter)
|
||||
|
||||
/* static */ int64_t
|
||||
nsWindowMemoryReporter::GhostWindowsReporter::DistinguishedAmount()
|
||||
nsWindowMemoryReporter::GhostWindowsDistinguishedAmount()
|
||||
{
|
||||
nsTHashtable<nsUint64HashKey> ghostWindows;
|
||||
sWindowReporter->CheckForGhostWindows(&ghostWindows);
|
||||
return ghostWindows.Count();
|
||||
return sWindowReporter->mGhostWindowCount;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -103,40 +103,11 @@ public:
|
|||
static nsWindowMemoryReporter* Get();
|
||||
void ObserveDOMWindowDetached(nsGlobalWindow* aWindow);
|
||||
|
||||
static int64_t GhostWindowsDistinguishedAmount();
|
||||
|
||||
private:
|
||||
~nsWindowMemoryReporter();
|
||||
|
||||
/**
|
||||
* nsGhostWindowReporter generates the "ghost-windows" report, which counts
|
||||
* the number of ghost windows present.
|
||||
*/
|
||||
class GhostWindowsReporter final : public nsIMemoryReporter
|
||||
{
|
||||
~GhostWindowsReporter() {}
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
static int64_t DistinguishedAmount();
|
||||
|
||||
NS_IMETHOD
|
||||
CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
|
||||
bool aAnonymize) override
|
||||
{
|
||||
MOZ_COLLECT_REPORT(
|
||||
"ghost-windows", KIND_OTHER, UNITS_COUNT, DistinguishedAmount(),
|
||||
"The number of ghost windows present (the number of nodes underneath "
|
||||
"explicit/window-objects/top(none)/ghost, modulo race conditions). A ghost "
|
||||
"window is not shown in any tab, does not share a domain with any non-detached "
|
||||
"windows, and has met these criteria for at least "
|
||||
"memory.ghost_window_timeout_seconds, or has survived a round of "
|
||||
"about:memory's minimize memory usage button.\n\n"
|
||||
"Ghost windows can happen legitimately, but they are often indicative of "
|
||||
"leaks in the browser or add-ons.");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
// Protect ctor, use Init() instead.
|
||||
nsWindowMemoryReporter();
|
||||
|
||||
|
@ -199,6 +170,8 @@ private:
|
|||
bool mCycleCollectorIsRunning;
|
||||
|
||||
bool mCheckTimerWaitingForCCEnd;
|
||||
|
||||
int64_t mGhostWindowCount;
|
||||
};
|
||||
|
||||
#endif // nsWindowMemoryReporter_h__
|
||||
|
|
|
@ -173,7 +173,7 @@ class nsWindowSizes
|
|||
macro(DOM, mDOMPerformanceUserEntries) \
|
||||
macro(DOM, mDOMPerformanceResourceEntries) \
|
||||
macro(DOM, mDOMOtherSize) \
|
||||
macro(Style, mStyleSheetsSize) \
|
||||
macro(Style, mLayoutStyleSheetsSize) \
|
||||
macro(Other, mLayoutPresShellSize) \
|
||||
macro(Style, mLayoutGeckoStyleSets) \
|
||||
macro(Style, mLayoutServoStyleSetsStylistRuleTree) \
|
||||
|
|
|
@ -135,6 +135,10 @@ DOMInterfaces = {
|
|||
'nativeType': 'nsDOMCaretPosition',
|
||||
},
|
||||
|
||||
'ChannelWrapper': {
|
||||
'nativeType': 'mozilla::extensions::ChannelWrapper',
|
||||
},
|
||||
|
||||
'CharacterData': {
|
||||
'nativeType': 'nsGenericDOMDataNode',
|
||||
'concrete': False
|
||||
|
|
|
@ -33,7 +33,8 @@ MSG_DEF(MSG_METHOD_THIS_UNWRAPPING_DENIED, 1, JSEXN_TYPEERR, "Permission to call
|
|||
MSG_DEF(MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 1, JSEXN_TYPEERR, "\"this\" object does not implement interface {0}.")
|
||||
MSG_DEF(MSG_NOT_IN_UNION, 2, JSEXN_TYPEERR, "{0} could not be converted to any of: {1}.")
|
||||
MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, JSEXN_TYPEERR, "Illegal constructor.")
|
||||
MSG_DEF(MSG_ILLEGAL_PR_CONSTRUCTOR, 1, JSEXN_TYPEERR, "TypeError:{0}")
|
||||
MSG_DEF(MSG_ILLEGAL_TYPE_PR_CONSTRUCTOR, 1, JSEXN_TYPEERR, "TypeError:{0}")
|
||||
MSG_DEF(MSG_ILLEGAL_RANGE_PR_CONSTRUCTOR, 1, JSEXN_RANGEERR, "RangeError:{0}")
|
||||
MSG_DEF(MSG_CONSTRUCTOR_WITHOUT_NEW, 1, JSEXN_TYPEERR, "Constructor {0} requires 'new'")
|
||||
MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, JSEXN_TYPEERR, "Non-finite value is out of range for {0}.")
|
||||
MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "Value is out of range for {0}.")
|
||||
|
|
|
@ -107,8 +107,6 @@ using namespace dom;
|
|||
|
||||
//#define DEBUG_DOCSHELL_FOCUS
|
||||
|
||||
#define NS_USER_INTERACTION_INTERVAL 5000 // ms
|
||||
|
||||
static const LayoutDeviceIntPoint kInvalidRefPoint = LayoutDeviceIntPoint(-1,-1);
|
||||
|
||||
static uint32_t gMouseOrKeyboardEventCounter = 0;
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "nsIFrame.h"
|
||||
#include "Units.h"
|
||||
|
||||
#define NS_USER_INTERACTION_INTERVAL 5000 // ms
|
||||
|
||||
class nsFrameLoader;
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
|
|
|
@ -17,7 +17,7 @@ interface nsIArray;
|
|||
interface nsIEventListenerChange : nsISupports
|
||||
{
|
||||
readonly attribute nsIDOMEventTarget target;
|
||||
readonly attribute nsIArray changedListenerNames;
|
||||
[noscript] readonly attribute nsIArray changedListenerNames;
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(aa7c95f6-d3b5-44b3-9597-1d9f19b9c5f2)]
|
||||
|
|
|
@ -108,22 +108,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=524674
|
|||
var expected = expectedEventChanges[i];
|
||||
|
||||
if (current.target == expected.target) {
|
||||
// expected.target.listeners should be a subset of
|
||||
// current.changedListenerNames if all expected listener changes were
|
||||
// sent. We may get random other event listener changes here too, not
|
||||
// just the one from the test.
|
||||
is(current.target, expected.target, current.target + " = " + expected.target);
|
||||
|
||||
var eNames = current.changedListenerNames.enumerate();
|
||||
var listeners = [];
|
||||
while (eNames.hasMoreElements()) {
|
||||
var listenerName = eNames.getNext().QueryInterface(Ci.nsIAtom).toString();
|
||||
listeners.push(listenerName);
|
||||
}
|
||||
var matchAll = expected.listeners.every(function(val)
|
||||
{ return listeners.indexOf(val) >= 0; });
|
||||
if (!matchAll)
|
||||
return;
|
||||
++i;
|
||||
}
|
||||
} catch(ex) {
|
||||
|
|
|
@ -3567,13 +3567,17 @@ HTMLInputElement::NeedToInitializeEditorForEvent(
|
|||
// are lazily initialized. We don't need to initialize the control for
|
||||
// certain types of events, because we know that those events are safe to be
|
||||
// handled without the editor being initialized. These events include:
|
||||
// mousein/move/out, overflow/underflow, and DOM mutation events.
|
||||
// mousein/move/out, overflow/underflow, DOM mutation, and void events. Void
|
||||
// events are dispatched frequently by async keyboard scrolling to focused
|
||||
// elements, so it's important to handle them to prevent excessive DOM
|
||||
// mutations.
|
||||
if (!IsSingleLineTextControl(false) ||
|
||||
aVisitor.mEvent->mClass == eMutationEventClass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (aVisitor.mEvent->mMessage) {
|
||||
case eVoidEvent:
|
||||
case eMouseMove:
|
||||
case eMouseEnterIntoWidget:
|
||||
case eMouseExitFromWidget:
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче