зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. CLOSED TREE
--HG-- extra : amend_source : d757a37614ac9d59e154d34ede3ca871a643cdb7
This commit is contained in:
Коммит
2b0bec5ab3
|
@ -16,6 +16,8 @@ ChromeUtils.defineModuleGetter(this, "WebNavigationFrames",
|
|||
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]);
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gPipNSSBundle", function() {
|
||||
return Services.strings.createBundle("chrome://pipnss/locale/pipnss.properties");
|
||||
});
|
||||
|
@ -330,6 +332,7 @@ class NetErrorChild extends ActorChild {
|
|||
detailLink.append(input.data.codeString);
|
||||
detailLink.title = input.data.codeString;
|
||||
detailLink.id = "errorCode";
|
||||
detailLink.dataset.telemetryId = "error_code_link";
|
||||
let fragment = BrowserUtils.getLocalizedFragment(doc, linkPrefix, detailLink);
|
||||
technicalInfo.appendChild(fragment);
|
||||
var errorCode = doc.getElementById("errorCode");
|
||||
|
@ -364,6 +367,12 @@ class NetErrorChild extends ActorChild {
|
|||
// This is set to true later if the user's system clock is at fault for this error.
|
||||
let clockSkew = false;
|
||||
|
||||
doc.body.setAttribute("code", msg.data.codeString);
|
||||
|
||||
// Need to do this here (which is not exactly at load but a few ticks later),
|
||||
// because this is the first time we have access to the error code.
|
||||
this.recordLoadEvent(doc);
|
||||
|
||||
switch (msg.data.code) {
|
||||
case SSL_ERROR_BAD_CERT_DOMAIN:
|
||||
case SEC_ERROR_OCSP_INVALID_SIGNING_CERT:
|
||||
|
@ -556,11 +565,13 @@ class NetErrorChild extends ActorChild {
|
|||
case "click":
|
||||
if (aEvent.button == 0) {
|
||||
if (this.isAboutCertError(doc)) {
|
||||
this.recordClick(aEvent.originalTarget);
|
||||
this.onCertError(aEvent.originalTarget, doc.defaultView);
|
||||
} else {
|
||||
this.onClick(aEvent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -722,6 +733,38 @@ class NetErrorChild extends ActorChild {
|
|||
});
|
||||
}
|
||||
|
||||
getCSSClass(doc) {
|
||||
let searchParams = new URL(doc.documentURI).searchParams;
|
||||
return searchParams.get("s");
|
||||
}
|
||||
|
||||
recordLoadEvent(doc) {
|
||||
let cssClass = this.getCSSClass(doc);
|
||||
// Telemetry values for events are max. 80 bytes.
|
||||
let errorCode = doc.body.getAttribute("code").substring(0, 40);
|
||||
Services.telemetry.recordEvent("security.ui.certerror", "load", "aboutcerterror", errorCode, {
|
||||
"has_sts": (cssClass == "badStsCert").toString(),
|
||||
"is_frame": (doc.ownerGlobal.parent != doc.ownerGlobal).toString(),
|
||||
});
|
||||
}
|
||||
|
||||
recordClick(element) {
|
||||
let telemetryId = element.dataset.telemetryId;
|
||||
if (!telemetryId) {
|
||||
return;
|
||||
}
|
||||
let doc = element.ownerDocument;
|
||||
let cssClass = this.getCSSClass(doc);
|
||||
// Telemetry values for events are max. 80 bytes.
|
||||
let errorCode = doc.body.getAttribute("code").substring(0, 40);
|
||||
let panel = doc.getElementById("badCertAdvancedPanel");
|
||||
Services.telemetry.recordEvent("security.ui.certerror", "click", telemetryId, errorCode, {
|
||||
"panel_open": (panel.style.display == "none").toString(),
|
||||
"has_sts": (cssClass == "badStsCert").toString(),
|
||||
"is_frame": (doc.ownerGlobal.parent != doc.ownerGlobal).toString(),
|
||||
});
|
||||
}
|
||||
|
||||
onClick(event) {
|
||||
let {documentURI} = event.target.ownerDocument;
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ pref("extensions.getAddons.compatOverides.url", "https://services.addons.mozilla
|
|||
pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/search?q=%TERMS%&platform=%OS%&appver=%VERSION%");
|
||||
pref("extensions.webservice.discoverURL", "https://discovery.addons.mozilla.org/%LOCALE%/firefox/discovery/pane/%VERSION%/%OS%/%COMPATIBILITY_MODE%");
|
||||
pref("extensions.getAddons.link.url", "https://addons.mozilla.org/%LOCALE%/firefox/");
|
||||
pref("extensions.getAddons.themes.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes/?src=firefox");
|
||||
pref("extensions.getAddons.langpacks.url", "https://services.addons.mozilla.org/api/v3/addons/language-tools/?app=firefox&type=language&appversion=%VERSION%");
|
||||
|
||||
pref("extensions.update.autoUpdateDefault", true);
|
||||
|
@ -953,6 +952,8 @@ pref("browser.security.newcerterrorpage.enabled", true);
|
|||
pref("browser.security.newcerterrorpage.enabled", false);
|
||||
#endif
|
||||
|
||||
pref("security.certerrors.recordEventTelemetry", true);
|
||||
|
||||
// Whether to start the private browsing mode at application startup
|
||||
pref("browser.privatebrowsing.autostart", false);
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@
|
|||
<div id="errorLongDesc" />
|
||||
|
||||
<div id="learnMoreContainer">
|
||||
<p><a href="https://support.mozilla.org/kb/what-does-your-connection-is-not-secure-mean" id="learnMoreLink" target="new">&errorReporting.learnMore;</a></p>
|
||||
<p><a href="https://support.mozilla.org/kb/what-does-your-connection-is-not-secure-mean" id="learnMoreLink" target="new" data-telemetry-id="learn_more_link">&errorReporting.learnMore;</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -183,10 +183,10 @@
|
|||
</div>
|
||||
|
||||
<div id="certErrorAndCaptivePortalButtonContainer" class="button-container">
|
||||
<button id="returnButton" class="primary" autocomplete="off">&returnToPreviousPage1.label;</button>
|
||||
<button id="returnButton" class="primary" autocomplete="off" data-telemetry-id="return_button_top">&returnToPreviousPage1.label;</button>
|
||||
<button id="openPortalLoginPageButton" class="primary" autocomplete="off">&openPortalLoginPage.label2;</button>
|
||||
<button id="errorTryAgain" class="primary" autocomplete="off">&retry.label;</button>
|
||||
<button id="advancedButton" autocomplete="off">&continue2.label;</button>
|
||||
<button id="advancedButton" data-telemetry-id="advanced_button" autocomplete="off">&continue2.label;</button>
|
||||
<button id="moreInformationButton" autocomplete="off">&moreInformation.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -198,26 +198,27 @@
|
|||
<div id="advancedPanelContainer">
|
||||
<div id="badCertAdvancedPanel" class="advanced-panel">
|
||||
<p id="badCertTechnicalInfo"/>
|
||||
<a id="viewCertificate" href="javascript:void(0)">&viewCertificate.label;</a>
|
||||
<div id="advancedPanelButtonContainer" class="button-container">
|
||||
<button id="advancedPanelReturnButton" class="primary" autocomplete="off">&returnToPreviousPage1.label;</button>
|
||||
<button id="advancedPanelReturnButton" class="primary" autocomplete="off" data-telemetry-id="return_button_adv">&returnToPreviousPage1.label;</button>
|
||||
<button id="advancedPanelErrorTryAgain" class="primary" autocomplete="off">&retry.label;</button>
|
||||
<div class="exceptionDialogButtonContainer">
|
||||
<button id="exceptionDialogButton">&securityOverride.exceptionButton1Label;</button>
|
||||
<button id="exceptionDialogButton" data-telemetry-id="exception_button">&securityOverride.exceptionButton1Label;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="certificateErrorReporting">
|
||||
<p class="toggle-container-with-text">
|
||||
<input type="checkbox" id="automaticallyReportInFuture" role="checkbox" />
|
||||
<input type="checkbox" id="automaticallyReportInFuture" role="checkbox" data-telemetry-id="auto_report_cb"/>
|
||||
<label for="automaticallyReportInFuture" id="automaticallyReportInFuture">&errorReporting.automatic2;</label>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="certificateErrorDebugInformation">
|
||||
<button id="copyToClipboard">&certerror.copyToClipboard.label;</button>
|
||||
<button id="copyToClipboard" data-telemetry-id="clipboard_button_top">&certerror.copyToClipboard.label;</button>
|
||||
<div id="certificateErrorText"/>
|
||||
<button id="copyToClipboard">&certerror.copyToClipboard.label;</button>
|
||||
<button id="copyToClipboard" data-telemetry-id="clipboard_button_bot">&certerror.copyToClipboard.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
<div id="errorLongDesc" />
|
||||
|
||||
<div id="learnMoreContainer">
|
||||
<p><a href="https://support.mozilla.org/kb/what-does-your-connection-is-not-secure-mean" id="learnMoreLink" target="new">&errorReporting.learnMore;</a></p>
|
||||
<p><a href="https://support.mozilla.org/kb/what-does-your-connection-is-not-secure-mean" id="learnMoreLink" target="new" data-telemetry-id="learn_more_link">&errorReporting.learnMore;</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -141,7 +141,7 @@
|
|||
init for other error types .-->
|
||||
<div id="certificateErrorReporting">
|
||||
<p class="toggle-container-with-text">
|
||||
<input type="checkbox" id="automaticallyReportInFuture" role="checkbox" />
|
||||
<input type="checkbox" id="automaticallyReportInFuture" role="checkbox" data-telemetry-id="auto_report_cb"/>
|
||||
<label for="automaticallyReportInFuture" id="automaticallyReportInFuture">&errorReporting.automatic2;</label>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -152,9 +152,9 @@
|
|||
</div>
|
||||
|
||||
<div id="certErrorAndCaptivePortalButtonContainer" class="button-container">
|
||||
<button id="returnButton" class="primary" autocomplete="off">&returnToPreviousPage.label;</button>
|
||||
<button id="returnButton" class="primary" autocomplete="off" data-telemetry-id="return_button_top">&returnToPreviousPage.label;</button>
|
||||
<button id="openPortalLoginPageButton" class="primary" autocomplete="off">&openPortalLoginPage.label2;</button>
|
||||
<button id="advancedButton" autocomplete="off">&advanced.label;</button>
|
||||
<button id="advancedButton" data-telemetry-id="advanced_button" autocomplete="off">&advanced.label;</button>
|
||||
<button id="moreInformationButton" autocomplete="off">&moreInformation.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -170,14 +170,14 @@
|
|||
<button id="advancedPanelErrorTryAgain" class="primary" autocomplete="off">&retry.label;</button>
|
||||
</div>
|
||||
<div class="exceptionDialogButtonContainer">
|
||||
<button id="exceptionDialogButton">&securityOverride.exceptionButtonLabel;</button>
|
||||
<button id="exceptionDialogButton" data-telemetry-id="exception_button">&securityOverride.exceptionButtonLabel;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="certificateErrorDebugInformation">
|
||||
<button id="copyToClipboard">&certerror.copyToClipboard.label;</button>
|
||||
<button id="copyToClipboard" data-telemetry-id="clipboard_button_top">&certerror.copyToClipboard.label;</button>
|
||||
<div id="certificateErrorText"/>
|
||||
<button id="copyToClipboard">&certerror.copyToClipboard.label;</button>
|
||||
<button id="copyToClipboard" data-telemetry-id="clipboard_button_bot">&certerror.copyToClipboard.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3038,15 +3038,17 @@ var BrowserOnClick = {
|
|||
},
|
||||
|
||||
onCertError(browser, elementId, isTopFrame, location, securityInfoAsString, frameId) {
|
||||
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
|
||||
let securityInfo;
|
||||
let cert;
|
||||
|
||||
switch (elementId) {
|
||||
case "viewCertificate":
|
||||
securityInfo = getSecurityInfo(securityInfoAsString);
|
||||
cert = securityInfo.serverCert;
|
||||
Services.ww.openWindow(window, "chrome://pippki/content/certViewer.xul",
|
||||
"_blank", "centerscreen,chrome", cert);
|
||||
break;
|
||||
case "exceptionDialogButton":
|
||||
if (isTopFrame) {
|
||||
secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_CLICK_ADD_EXCEPTION);
|
||||
}
|
||||
|
||||
securityInfo = getSecurityInfo(securityInfoAsString);
|
||||
let params = { exceptionAdded: false,
|
||||
securityInfo };
|
||||
|
@ -3064,7 +3066,7 @@ var BrowserOnClick = {
|
|||
flags |= overrideService.ERROR_TIME;
|
||||
}
|
||||
let uri = Services.uriFixup.createFixupURI(location, 0);
|
||||
let cert = securityInfo.serverCert;
|
||||
cert = securityInfo.serverCert;
|
||||
overrideService.rememberValidityOverride(
|
||||
uri.asciiHost, uri.port,
|
||||
cert,
|
||||
|
@ -3095,9 +3097,6 @@ var BrowserOnClick = {
|
|||
break;
|
||||
|
||||
case "returnButton":
|
||||
if (isTopFrame) {
|
||||
secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_GET_ME_OUT_OF_HERE);
|
||||
}
|
||||
goBackFromErrorPage();
|
||||
break;
|
||||
|
||||
|
@ -3107,10 +3106,6 @@ var BrowserOnClick = {
|
|||
|
||||
case "advancedButton":
|
||||
case "moreInformationButton":
|
||||
if (isTopFrame) {
|
||||
secHistogram.add(Ci.nsISecurityUITelemetry.WARNING_BAD_CERT_TOP_UNDERSTAND_RISKS);
|
||||
}
|
||||
|
||||
securityInfo = getSecurityInfo(securityInfoAsString);
|
||||
let errorInfo = getDetailedCertErrorInfo(location,
|
||||
securityInfo);
|
||||
|
|
|
@ -130,7 +130,7 @@ window._gBrowser = {
|
|||
_browserBindingProperties: [
|
||||
"canGoBack", "canGoForward", "goBack", "goForward", "permitUnload",
|
||||
"reload", "reloadWithFlags", "stop", "loadURI",
|
||||
"gotoIndex", "currentURI", "documentURI",
|
||||
"gotoIndex", "currentURI", "documentURI", "remoteType",
|
||||
"preferences", "imageDocument", "isRemoteBrowser", "messageManager",
|
||||
"getTabBrowser", "finder", "fastFind", "sessionHistory", "contentTitle",
|
||||
"characterSet", "fullZoom", "textZoom", "webProgress",
|
||||
|
@ -1205,7 +1205,12 @@ window._gBrowser = {
|
|||
};
|
||||
},
|
||||
|
||||
setInitialTabTitle(aTab, aTitle, aOptions) {
|
||||
setInitialTabTitle(aTab, aTitle, aOptions = {}) {
|
||||
// Convert some non-content title (actually a url) to human readable title
|
||||
if (!aOptions.isContentTitle && isBlankPageURL(aTitle)) {
|
||||
aTitle = this.tabContainer.emptyTabTitle;
|
||||
}
|
||||
|
||||
if (aTitle) {
|
||||
if (!aTab.getAttribute("label")) {
|
||||
aTab._labelIsInitialTitle = true;
|
||||
|
@ -1990,6 +1995,22 @@ window._gBrowser = {
|
|||
gBrowser._insertBrowser(aTab);
|
||||
};
|
||||
break;
|
||||
case "remoteType":
|
||||
getter = () => {
|
||||
let url = SessionStore.getLazyTabValue(aTab, "url");
|
||||
// Avoid recreating the same nsIURI object over and over again...
|
||||
let uri;
|
||||
if (browser._cachedCurrentURI) {
|
||||
uri = browser._cachedCurrentURI;
|
||||
} else {
|
||||
uri = browser._cachedCurrentURI = Services.io.newURI(url);
|
||||
}
|
||||
return E10SUtils.getRemoteTypeForURI(url,
|
||||
gMultiProcessBrowser,
|
||||
undefined,
|
||||
uri);
|
||||
};
|
||||
break;
|
||||
case "userTypedValue":
|
||||
case "userTypedClear":
|
||||
getter = () => SessionStore.getLazyTabValue(aTab, name);
|
||||
|
@ -3179,7 +3200,10 @@ window._gBrowser = {
|
|||
var isPending = aOtherTab.hasAttribute("pending");
|
||||
|
||||
let otherTabListener = remoteBrowser._tabListeners.get(aOtherTab);
|
||||
let stateFlags = otherTabListener.mStateFlags;
|
||||
let stateFlags = 0;
|
||||
if (otherTabListener) {
|
||||
stateFlags = otherTabListener.mStateFlags;
|
||||
}
|
||||
|
||||
// Expedite the removal of the icon if it was already scheduled.
|
||||
if (aOtherTab._soundPlayingAttrRemovalTimer) {
|
||||
|
@ -3294,7 +3318,7 @@ window._gBrowser = {
|
|||
|
||||
this.setTabTitle(aOurTab);
|
||||
|
||||
// If the tab was already selected (this happpens in the scenario
|
||||
// If the tab was already selected (this happens in the scenario
|
||||
// of replaceTabWithWindow), notify onLocationChange, etc.
|
||||
if (aOurTab.selected)
|
||||
this.updateCurrentBrowser(true);
|
||||
|
@ -3575,14 +3599,13 @@ window._gBrowser = {
|
|||
return this.replaceTabWithWindow(tabs[0], aOptions);
|
||||
}
|
||||
|
||||
// The order of the tabs is reserved.
|
||||
// To avoid mutliple tab-switch, the active tab is "moved" lastly, if applicable.
|
||||
// The order of the tabs is preserved.
|
||||
// To avoid multiple tab-switch, the active tab is "moved" last, if applicable.
|
||||
// If applicable, the active tab remains active in the new window.
|
||||
let activeTab = gBrowser.selectedTab;
|
||||
let inactiveTabs = tabs.filter(t => t != activeTab);
|
||||
let activeTabNewIndex = tabs.indexOf(activeTab);
|
||||
|
||||
|
||||
// Play the closing animation for all selected tabs to give
|
||||
// immediate feedback while waiting for the new window to appear.
|
||||
if (this.animationsEnabled) {
|
||||
|
@ -3594,7 +3617,8 @@ window._gBrowser = {
|
|||
|
||||
let win;
|
||||
let firstInactiveTab = inactiveTabs[0];
|
||||
firstInactiveTab.linkedBrowser.addEventListener("EndSwapDocShells", function() {
|
||||
|
||||
let adoptRemainingTabs = () => {
|
||||
for (let i = 1; i < inactiveTabs.length; i++) {
|
||||
win.gBrowser.adoptTab(inactiveTabs[i], i);
|
||||
}
|
||||
|
@ -3608,7 +3632,14 @@ window._gBrowser = {
|
|||
let winTabLength = winVisibleTabs.length;
|
||||
win.gBrowser.addRangeToMultiSelectedTabs(winVisibleTabs[0],
|
||||
winVisibleTabs[winTabLength - 1]);
|
||||
}, { once: true });
|
||||
};
|
||||
|
||||
// Pending tabs don't get their docshell swapped, wait for their TabClose
|
||||
if (firstInactiveTab.hasAttribute("pending")) {
|
||||
firstInactiveTab.addEventListener("TabClose", adoptRemainingTabs, {once: true});
|
||||
} else {
|
||||
firstInactiveTab.linkedBrowser.addEventListener("EndSwapDocShells", adoptRemainingTabs, {once: true});
|
||||
}
|
||||
|
||||
win = this.replaceTabWithWindow(firstInactiveTab, aOptions);
|
||||
return win;
|
||||
|
|
|
@ -5,10 +5,10 @@ support-files =
|
|||
searchSuggestionEngine.sjs
|
||||
searchSuggestionEngine.xml
|
||||
POSTSearchEngine.xml
|
||||
dummy_page.html
|
||||
|
||||
[browser_aboutCertError.js]
|
||||
support-files =
|
||||
dummy_page.html
|
||||
[browser_aboutCertError_telemetry.js]
|
||||
[browser_aboutHome_search_POST.js]
|
||||
[browser_aboutHome_search_composing.js]
|
||||
[browser_aboutHome_search_searchbar.js]
|
||||
|
|
|
@ -7,47 +7,11 @@
|
|||
|
||||
const GOOD_PAGE = "https://example.com/";
|
||||
const GOOD_PAGE_2 = "https://example.org/";
|
||||
const DUMMY_PAGE = getRootDirectory(gTestPath).replace("chrome://mochitests/content", GOOD_PAGE) + "dummy_page.html";
|
||||
const BAD_CERT = "https://expired.example.com/";
|
||||
const UNKNOWN_ISSUER = "https://self-signed.example.com ";
|
||||
const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
|
||||
const {TabStateFlusher} = ChromeUtils.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
|
||||
|
||||
function injectErrorPageFrame(tab, src) {
|
||||
return ContentTask.spawn(tab.linkedBrowser, {frameSrc: src}, async function({frameSrc}) {
|
||||
let loaded = ContentTaskUtils.waitForEvent(content.wrappedJSObject, "DOMFrameContentLoaded");
|
||||
let iframe = content.document.createElement("iframe");
|
||||
iframe.src = frameSrc;
|
||||
content.document.body.appendChild(iframe);
|
||||
await loaded;
|
||||
// We will have race conditions when accessing the frame content after setting a src,
|
||||
// so we can't wait for AboutNetErrorLoad. Let's wait for the certerror class to
|
||||
// appear instead (which should happen at the same time as AboutNetErrorLoad).
|
||||
await ContentTaskUtils.waitForCondition(() =>
|
||||
iframe.contentDocument.body.classList.contains("certerror"));
|
||||
});
|
||||
}
|
||||
|
||||
async function openErrorPage(src, useFrame) {
|
||||
let tab;
|
||||
if (useFrame) {
|
||||
info("Loading cert error page in an iframe");
|
||||
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, DUMMY_PAGE);
|
||||
await injectErrorPageFrame(tab, src);
|
||||
} else {
|
||||
let certErrorLoaded;
|
||||
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, src);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
|
||||
}, false);
|
||||
info("Loading and waiting for the cert error");
|
||||
await certErrorLoaded;
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
add_task(async function checkReturnToAboutHome() {
|
||||
info("Loading a bad cert page directly and making sure 'return to previous page' goes to about:home");
|
||||
for (let useFrame of [false, true]) {
|
||||
|
@ -518,6 +482,32 @@ add_task(async function checkCautionClass() {
|
|||
}
|
||||
});
|
||||
|
||||
add_task(async function checkViewCertificate() {
|
||||
info("Loading a cert error and checking that the certificate can be shown.");
|
||||
for (let useFrame of [false, true]) {
|
||||
let tab = await openErrorPage(UNKNOWN_ISSUER, useFrame);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
let dialogOpened = BrowserTestUtils.domWindowOpened();
|
||||
|
||||
await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
|
||||
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
|
||||
let viewCertificate = doc.getElementById("viewCertificate");
|
||||
viewCertificate.click();
|
||||
});
|
||||
|
||||
let win = await dialogOpened;
|
||||
await BrowserTestUtils.waitForEvent(win, "load");
|
||||
is(win.document.documentURI, "chrome://pippki/content/certViewer.xul",
|
||||
"Opened the cert viewer dialog");
|
||||
is(win.document.getElementById("commonname").value, "self-signed.example.com",
|
||||
"Shows the correct certificate in the dialog");
|
||||
win.close();
|
||||
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
}
|
||||
});
|
||||
|
||||
function getCertChain(securityInfoAsString) {
|
||||
let certChain = "";
|
||||
const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
const BAD_CERT = "https://expired.example.com/";
|
||||
const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
|
||||
|
||||
add_task(async function checkTelemetryClickEvents() {
|
||||
info("Loading a bad cert page and verifying telemetry click events arrive.");
|
||||
|
||||
let oldCanRecord = Services.telemetry.canRecordExtended;
|
||||
Services.telemetry.canRecordExtended = true;
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.telemetry.canRecordExtended = oldCanRecord;
|
||||
});
|
||||
|
||||
// For obvious reasons event telemetry in the content processes updates with
|
||||
// the main processs asynchronously, so we need to wait for the main process
|
||||
// to catch up through the entire test.
|
||||
|
||||
// There's an arbitrary interval of 2 seconds in which the content
|
||||
// processes sync their event data with the parent process, we wait
|
||||
// this out to ensure that we clear everything that is left over from
|
||||
// previous tests and don't receive random events in the middle of our tests.
|
||||
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||
await new Promise(c => setTimeout(c, 2000));
|
||||
|
||||
// Clear everything.
|
||||
Services.telemetry.clearEvents();
|
||||
await TestUtils.waitForCondition(() => {
|
||||
let events = Services.telemetry.snapshotEvents(
|
||||
Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true).content;
|
||||
return !events || !events.length;
|
||||
});
|
||||
|
||||
// Now enable recording our telemetry. Even if this is disabled, content
|
||||
// processes will send event telemetry to the parent, thus we needed to ensure
|
||||
// we waited and cleared first. Sigh.
|
||||
Services.telemetry.setEventRecordingEnabled("security.ui.certerror", true);
|
||||
|
||||
for (let useFrame of [false, true]) {
|
||||
let recordedObjects = [
|
||||
"advanced_button",
|
||||
"learn_more_link",
|
||||
"auto_report_cb",
|
||||
"error_code_link",
|
||||
"clipboard_button_top",
|
||||
"clipboard_button_bot",
|
||||
"return_button_top",
|
||||
"return_button_adv",
|
||||
];
|
||||
|
||||
if (!useFrame) {
|
||||
recordedObjects.push("exception_button");
|
||||
}
|
||||
|
||||
for (let object of recordedObjects) {
|
||||
let tab = await openErrorPage(BAD_CERT, useFrame);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
let loadEvents = await TestUtils.waitForCondition(() => {
|
||||
let events = Services.telemetry.snapshotEvents(
|
||||
Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true).content;
|
||||
if (events && events.length) {
|
||||
events = events.filter(e => e[1] == "security.ui.certerror" && e[2] == "load");
|
||||
if (events.length == 1 && events[0][5].is_frame == useFrame.toString()) {
|
||||
return events;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, "recorded telemetry for the load");
|
||||
|
||||
is(loadEvents.length, 1, `recorded telemetry for the load testing ${object}, useFrame: ${useFrame}`);
|
||||
|
||||
await ContentTask.spawn(browser, {frame: useFrame, objectId: object}, async function({frame, objectId}) {
|
||||
let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
|
||||
|
||||
await ContentTaskUtils.waitForCondition(() => doc.body.classList.contains("certerror"), "Wait for certerror to be loaded");
|
||||
|
||||
let domElement = doc.querySelector(`[data-telemetry-id='${objectId}']`);
|
||||
domElement.click();
|
||||
});
|
||||
|
||||
let clickEvents = await TestUtils.waitForCondition(() => {
|
||||
let events = Services.telemetry.snapshotEvents(
|
||||
Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true).content;
|
||||
if (events && events.length) {
|
||||
events = events.filter(e => e[1] == "security.ui.certerror" && e[2] == "click" && e[3] == object);
|
||||
if (events.length == 1 && events[0][5].is_frame == useFrame.toString()) {
|
||||
return events;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, "Has captured telemetry events.");
|
||||
|
||||
is(clickEvents.length, 1, `recorded telemetry for the click on ${object}, useFrame: ${useFrame}`);
|
||||
|
||||
// We opened an extra tab for the SUMO page, need to close it.
|
||||
if (object == "learn_more_link") {
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
}
|
||||
|
||||
if (object == "exception_button") {
|
||||
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
|
||||
.getService(Ci.nsICertOverrideService);
|
||||
certOverrideService.clearValidityOverride("expired.example.com", -1);
|
||||
}
|
||||
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
}
|
||||
}
|
||||
|
||||
let enableCertErrorUITelemetry =
|
||||
Services.prefs.getBoolPref("security.certerrors.recordEventTelemetry");
|
||||
Services.telemetry.setEventRecordingEnabled("security.ui.certerror",
|
||||
enableCertErrorUITelemetry);
|
||||
});
|
|
@ -1,5 +1,42 @@
|
|||
/* eslint-env mozilla/frame-script */
|
||||
|
||||
function injectErrorPageFrame(tab, src) {
|
||||
return ContentTask.spawn(tab.linkedBrowser, {frameSrc: src}, async function({frameSrc}) {
|
||||
let loaded = ContentTaskUtils.waitForEvent(content.wrappedJSObject, "DOMFrameContentLoaded");
|
||||
let iframe = content.document.createElement("iframe");
|
||||
iframe.src = frameSrc;
|
||||
content.document.body.appendChild(iframe);
|
||||
await loaded;
|
||||
// We will have race conditions when accessing the frame content after setting a src,
|
||||
// so we can't wait for AboutNetErrorLoad. Let's wait for the certerror class to
|
||||
// appear instead (which should happen at the same time as AboutNetErrorLoad).
|
||||
await ContentTaskUtils.waitForCondition(() =>
|
||||
iframe.contentDocument.body.classList.contains("certerror"));
|
||||
});
|
||||
}
|
||||
|
||||
async function openErrorPage(src, useFrame) {
|
||||
let dummyPage = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com") + "dummy_page.html";
|
||||
|
||||
let tab;
|
||||
if (useFrame) {
|
||||
info("Loading cert error page in an iframe");
|
||||
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, dummyPage);
|
||||
await injectErrorPageFrame(tab, src);
|
||||
} else {
|
||||
let certErrorLoaded;
|
||||
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, src);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
|
||||
}, false);
|
||||
info("Loading and waiting for the cert error");
|
||||
await certErrorLoaded;
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
function waitForCondition(condition, nextTest, errorMsg, retryTimes) {
|
||||
retryTimes = typeof retryTimes !== "undefined" ? retryTimes : 30;
|
||||
var tries = 0;
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gXulStore",
|
||||
"@mozilla.org/xul/xulstore;1",
|
||||
"nsIXULStore");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetters(this, {
|
||||
gCertDB: ["@mozilla.org/security/x509certdb;1", "nsIX509CertDB"],
|
||||
gXulStore: ["@mozilla.org/xul/xulstore;1", "nsIXULStore"],
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
|
@ -19,6 +21,8 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
WebsiteFilter: "resource:///modules/policies/WebsiteFilter.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGlobalGetters(this, ["File", "FileReader"]);
|
||||
|
||||
const PREF_LOGLEVEL = "browser.policies.loglevel";
|
||||
const BROWSER_DOCUMENT_URL = AppConstants.BROWSER_CHROME_URL;
|
||||
|
||||
|
@ -134,6 +138,56 @@ var Policies = {
|
|||
if ("ImportEnterpriseRoots" in param) {
|
||||
setAndLockPref("security.enterprise_roots.enabled", param.ImportEnterpriseRoots);
|
||||
}
|
||||
if ("Install" in param) {
|
||||
(async () => {
|
||||
let dirs = [];
|
||||
let platform = AppConstants.platform;
|
||||
if (platform == "win") {
|
||||
dirs = [
|
||||
// Ugly, but there is no official way to get %USERNAME\AppData\Local\Mozilla.
|
||||
Services.dirsvc.get("XREUSysExt", Ci.nsIFile).parent,
|
||||
];
|
||||
} else if (platform == "macosx" || platform == "linux") {
|
||||
dirs = [
|
||||
// These two keys are named wrong. They return the Mozilla directory.
|
||||
Services.dirsvc.get("XREUserNativeManifests", Ci.nsIFile),
|
||||
Services.dirsvc.get("XRESysNativeManifests", Ci.nsIFile),
|
||||
];
|
||||
}
|
||||
for (let dir of dirs) {
|
||||
dir.append(platform == "linux" ? "certificates" : "Certificates");
|
||||
for (let certfilename of param.Install) {
|
||||
let certfile = dir.clone();
|
||||
certfile.append(certfilename);
|
||||
let file;
|
||||
try {
|
||||
file = await File.createFromNsIFile(certfile);
|
||||
} catch (e) {
|
||||
log.info(`Unable to open certificate - ${certfile.path}`);
|
||||
continue;
|
||||
}
|
||||
let reader = new FileReader();
|
||||
reader.onloadend = function() {
|
||||
if (reader.readyState != reader.DONE) {
|
||||
log.error(`Unable to read certificate - ${certfile.path}`);
|
||||
return;
|
||||
}
|
||||
let cert = reader.result;
|
||||
try {
|
||||
if (/-----BEGIN CERTIFICATE-----/.test(cert)) {
|
||||
gCertDB.addCertFromBase64(pemToBase64(cert), "CTu,CTu,");
|
||||
} else {
|
||||
gCertDB.addCert(cert, "CTu,CTu,");
|
||||
}
|
||||
} catch (e) {
|
||||
log.error(`Unable to add certificate - ${certfile.path}`);
|
||||
}
|
||||
};
|
||||
reader.readAsBinaryString(file);
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -1062,3 +1116,9 @@ function blockAllChromeURLs() {
|
|||
ChromeURLBlockPolicy.contractID,
|
||||
ChromeURLBlockPolicy.contractID, false, true);
|
||||
}
|
||||
|
||||
function pemToBase64(pem) {
|
||||
return pem.replace(/-----BEGIN CERTIFICATE-----/, "")
|
||||
.replace(/-----END CERTIFICATE-----/, "")
|
||||
.replace(/[\r\n]/g, "");
|
||||
}
|
||||
|
|
|
@ -235,6 +235,7 @@ function generateDocumentation() {
|
|||
// existing descriptions
|
||||
let string_mapping = {
|
||||
"DisableSetDesktopBackground": "DisableSetAsDesktopBackground",
|
||||
"Certificates": "CertificatesDescription",
|
||||
};
|
||||
|
||||
for (let policyName in schema.properties) {
|
||||
|
|
|
@ -95,6 +95,12 @@
|
|||
"properties": {
|
||||
"ImportEnterpriseRoots": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"Install": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -95,7 +95,6 @@ skip-if = (verify && (os == 'linux' || os == 'mac'))
|
|||
[browser_ext_devtools_page.js]
|
||||
[browser_ext_devtools_panel.js]
|
||||
[browser_ext_devtools_panels_elements.js]
|
||||
skip-if = true # Bug 1393760
|
||||
[browser_ext_devtools_panels_elements_sidebar.js]
|
||||
support-files =
|
||||
../../../../../devtools/client/inspector/extensions/test/head_devtools_inspector_sidebar.js
|
||||
|
|
|
@ -11,9 +11,6 @@ add_task(async function test_devtools_panels_elements_onSelectionChanged() {
|
|||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "http://mochi.test:8888/");
|
||||
|
||||
function devtools_page() {
|
||||
let isReloading = false;
|
||||
let collectedEvalResults = [];
|
||||
|
||||
browser.devtools.panels.elements.onSelectionChanged.addListener(async () => {
|
||||
const [
|
||||
evalResult, exceptionInfo,
|
||||
|
@ -24,13 +21,7 @@ add_task(async function test_devtools_panels_elements_onSelectionChanged() {
|
|||
JSON.stringify(exceptionInfo));
|
||||
}
|
||||
|
||||
collectedEvalResults.push(evalResult);
|
||||
|
||||
// The eval results that are happening during the reload are going to
|
||||
// be retrieved all at once using the "collected_devttols_eval_results:request".
|
||||
if (!isReloading) {
|
||||
browser.test.sendMessage("devtools_eval_result", evalResult);
|
||||
}
|
||||
browser.test.sendMessage("devtools_eval_result", evalResult);
|
||||
});
|
||||
|
||||
browser.test.onMessage.addListener(msg => {
|
||||
|
@ -38,18 +29,10 @@ add_task(async function test_devtools_panels_elements_onSelectionChanged() {
|
|||
case "inspectedWindow_reload": {
|
||||
// Force a reload to test that the expected onSelectionChanged events are sent
|
||||
// while the page is navigating and once it has been fully reloaded.
|
||||
isReloading = true;
|
||||
collectedEvalResults = [];
|
||||
browser.devtools.inspectedWindow.eval("window.location.reload();");
|
||||
break;
|
||||
}
|
||||
|
||||
case "collected_devtools_eval_results:request": {
|
||||
browser.test.sendMessage("collected_devtools_eval_results:reply",
|
||||
collectedEvalResults);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
browser.test.fail(`Received unexpected test.onMesssage: ${msg}`);
|
||||
}
|
||||
|
@ -90,8 +73,9 @@ add_task(async function test_devtools_panels_elements_onSelectionChanged() {
|
|||
|
||||
const inspector = toolbox.getPanel("inspector");
|
||||
|
||||
const evalResult = await extension.awaitMessage("devtools_eval_result");
|
||||
info("Waiting for the first onSelectionChanged event to be fired once the inspector is open");
|
||||
|
||||
const evalResult = await extension.awaitMessage("devtools_eval_result");
|
||||
is(evalResult, "BODY", "Got the expected onSelectionChanged once the inspector is selected");
|
||||
|
||||
// Reload the inspected tab and wait for the inspector markup view to have been
|
||||
|
@ -100,17 +84,17 @@ add_task(async function test_devtools_panels_elements_onSelectionChanged() {
|
|||
extension.sendMessage("inspectedWindow_reload");
|
||||
await onceMarkupReloaded;
|
||||
|
||||
// Retrieve the first and last collected eval result (the first is related to the
|
||||
// page navigating away, the last one is related to the updated inspector markup view
|
||||
// fully reloaded and the selection updated).
|
||||
extension.sendMessage("collected_devtools_eval_results:request");
|
||||
const collectedEvalResults = await extension.awaitMessage("collected_devtools_eval_results:reply");
|
||||
const evalResultNavigating = collectedEvalResults.shift();
|
||||
const evalResultOnceMarkupReloaded = collectedEvalResults.pop();
|
||||
info("Waiting for the two onSelectionChanged events fired before and after the navigation");
|
||||
|
||||
// Expect the eval result to be undefined on the first onSelectionChanged event
|
||||
// (fired when the page is navigating away, and so the current selection is undefined).
|
||||
const evalResultNavigating = await extension.awaitMessage("devtools_eval_result");
|
||||
is(evalResultNavigating, undefined,
|
||||
"Got the expected onSelectionChanged once the tab is navigating");
|
||||
|
||||
// Expect the eval result to be related to the body element on the second onSelectionChanged
|
||||
// event (fired when the page have been navigated to the new page).
|
||||
const evalResultOnceMarkupReloaded = await extension.awaitMessage("devtools_eval_result");
|
||||
is(evalResultOnceMarkupReloaded, "BODY",
|
||||
"Got the expected onSelectionChanged once the tab has been completely reloaded");
|
||||
|
||||
|
|
|
@ -1552,6 +1552,13 @@ BrowserGlue.prototype = {
|
|||
ContextualIdentityService.load();
|
||||
});
|
||||
|
||||
Services.tm.idleDispatchToMainThread(() => {
|
||||
let enableCertErrorUITelemetry =
|
||||
Services.prefs.getBoolPref("security.certerrors.recordEventTelemetry", false);
|
||||
Services.telemetry.setEventRecordingEnabled("security.ui.certerror",
|
||||
enableCertErrorUITelemetry);
|
||||
});
|
||||
|
||||
// Load the Login Manager data from disk off the main thread, some time
|
||||
// after startup. If the data is required before this runs, for example
|
||||
// because a restored page contains a password field, it will be loaded on
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[DEFAULT]
|
||||
head = head.js
|
||||
prefs =
|
||||
browser.pagethumbnails.capturing_disabled=true
|
||||
dom.payments.request.enabled=true
|
||||
skip-if = !e10s # Bug 1365964 - Payment Request isn't implemented for non-e10s
|
||||
support-files =
|
||||
|
|
|
@ -528,9 +528,6 @@ var SaveToPocket = {
|
|||
},
|
||||
|
||||
uninit() {
|
||||
// For speed sake, we should only do a shutdown if we're being disabled.
|
||||
// On an app shutdown, just let it fade away...
|
||||
Services.prefs.removeObserver("extensions.pocket.enabled", prefObserver);
|
||||
PocketOverlay.shutdown();
|
||||
},
|
||||
};
|
||||
|
|
|
@ -51,8 +51,8 @@
|
|||
permissions-remove-all.label,
|
||||
permissions-button-cancel.label,
|
||||
permissions-button-ok.label,
|
||||
permissions-exceptions-tracking-protection-window.title,
|
||||
permissions-exceptions-tracking-protection-desc,
|
||||
permissions-exceptions-content-blocking-window.title,
|
||||
permissions-exceptions-content-blocking-desc,
|
||||
"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
|
|
@ -23,6 +23,6 @@ add_task(async function() {
|
|||
*/
|
||||
add_task(async function() {
|
||||
await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
|
||||
await evaluateSearchResults("disabled Tracking Protection", "trackingGroup");
|
||||
await evaluateSearchResults("disabled content blocking", "trackingGroup");
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
|
|
@ -7,8 +7,8 @@ ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
|||
|
||||
const permissionExceptionsL10n = {
|
||||
"trackingprotection": {
|
||||
window: "permissions-exceptions-tracking-protection-window",
|
||||
description: "permissions-exceptions-tracking-protection-desc",
|
||||
window: "permissions-exceptions-content-blocking-window",
|
||||
description: "permissions-exceptions-content-blocking-desc",
|
||||
},
|
||||
"cookie": {
|
||||
window: "permissions-exceptions-cookie-window",
|
||||
|
|
|
@ -2767,7 +2767,7 @@ var SessionStoreInternal = {
|
|||
if (activePageData.title &&
|
||||
activePageData.title != activePageData.url) {
|
||||
win.gBrowser.setInitialTabTitle(tab, activePageData.title, { isContentTitle: true });
|
||||
} else if (activePageData.url != "about:blank") {
|
||||
} else {
|
||||
win.gBrowser.setInitialTabTitle(tab, activePageData.url);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -252,6 +252,7 @@ skip-if = !e10s
|
|||
[browser_async_window_flushing.js]
|
||||
[browser_focus_after_restore.js]
|
||||
[browser_forget_async_closings.js]
|
||||
[browser_movePendingTabToNewWindow.js]
|
||||
[browser_multiple_navigateAndRestore.js]
|
||||
run-if = e10s
|
||||
[browser_newtab_userTypedValue.js]
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* This tests the behaviour of moving pending tabs to a new window. These
|
||||
* pending tabs have yet to be restored and should be restored upon opening
|
||||
* in the new window. This test covers moving a single pending tab at once
|
||||
* as well as multiple tabs at the same time (using tab multiselection).
|
||||
*/
|
||||
add_task(async function test_movePendingTabToNewWindow() {
|
||||
const TEST_URIS = [
|
||||
"http://www.example.com/1",
|
||||
"http://www.example.com/2",
|
||||
"http://www.example.com/3",
|
||||
"http://www.example.com/4",
|
||||
];
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["browser.sessionstore.restore_on_demand", true],
|
||||
["toolkit.cosmeticAnimations.enabled", false],
|
||||
],
|
||||
});
|
||||
|
||||
let state = {
|
||||
windows: [{
|
||||
tabs: [
|
||||
{ entries: [{ url: TEST_URIS[0], triggeringPrincipal_base64 }] },
|
||||
{ entries: [{ url: TEST_URIS[1], triggeringPrincipal_base64 }] },
|
||||
{ entries: [{ url: TEST_URIS[2], triggeringPrincipal_base64 }] },
|
||||
{ entries: [{ url: TEST_URIS[3], triggeringPrincipal_base64 }] },
|
||||
],
|
||||
selected: 4,
|
||||
}],
|
||||
};
|
||||
|
||||
await promiseBrowserState(state);
|
||||
|
||||
is(gBrowser.visibleTabs.length, 4, "Three tabs are visible to start the test");
|
||||
|
||||
let tabToSelect = gBrowser.visibleTabs[1];
|
||||
ok(tabToSelect.hasAttribute("pending"), "Tab should be pending");
|
||||
|
||||
gBrowser.addRangeToMultiSelectedTabs(gBrowser.selectedTab, tabToSelect);
|
||||
ok(!gBrowser.visibleTabs[0].multiselected, "First tab not multiselected");
|
||||
ok(gBrowser.visibleTabs[1].multiselected, "Second tab multiselected");
|
||||
ok(gBrowser.visibleTabs[2].multiselected, "Third tab multiselected");
|
||||
ok(gBrowser.visibleTabs[3].multiselected, "Fourth tab multiselected");
|
||||
|
||||
let promiseNewWindow = BrowserTestUtils.waitForNewWindow();
|
||||
gBrowser.replaceTabsWithWindow(tabToSelect);
|
||||
|
||||
info("Waiting for new window");
|
||||
let newWindow = await promiseNewWindow;
|
||||
isnot(newWindow, gBrowser.ownerGlobal, "Tab moved to new window");
|
||||
|
||||
let newWindowTabs = newWindow.gBrowser.visibleTabs;
|
||||
await TestUtils.waitForCondition(() => {
|
||||
return newWindowTabs.length == 3 &&
|
||||
newWindowTabs[0].linkedBrowser.currentURI.spec == TEST_URIS[1] &&
|
||||
newWindowTabs[1].linkedBrowser.currentURI.spec == TEST_URIS[2] &&
|
||||
newWindowTabs[2].linkedBrowser.currentURI.spec == TEST_URIS[3];
|
||||
}, "Wait for all three tabs to move to new window and load");
|
||||
|
||||
is(newWindowTabs.length, 3, "Three tabs should be in new window");
|
||||
is(newWindowTabs[0].linkedBrowser.currentURI.spec, TEST_URIS[1], "Second tab moved");
|
||||
is(newWindowTabs[1].linkedBrowser.currentURI.spec, TEST_URIS[2], "Third tab moved");
|
||||
is(newWindowTabs[2].linkedBrowser.currentURI.spec, TEST_URIS[3], "Fourth tab moved");
|
||||
|
||||
ok(newWindowTabs[0].hasAttribute("pending"), "First tab in new window should still be pending");
|
||||
ok(newWindowTabs[1].hasAttribute("pending"), "Second tab in new window should still be pending");
|
||||
newWindow.gBrowser.clearMultiSelectedTabs(true);
|
||||
ok(newWindowTabs.every(t => !t.multiselected), "No multiselection should be present");
|
||||
|
||||
promiseNewWindow = BrowserTestUtils.waitForNewWindow();
|
||||
newWindow.gBrowser.replaceTabsWithWindow(newWindowTabs[0]);
|
||||
|
||||
info("Waiting for second new window");
|
||||
let secondNewWindow = await promiseNewWindow;
|
||||
await TestUtils.waitForCondition(() => secondNewWindow.gBrowser.selectedBrowser.currentURI.spec == TEST_URIS[1],
|
||||
"Wait until the URI is updated");
|
||||
is(secondNewWindow.gBrowser.visibleTabs.length, 1, "Only one tab in second new window");
|
||||
is(secondNewWindow.gBrowser.selectedBrowser.currentURI.spec, TEST_URIS[1], "First tab moved");
|
||||
|
||||
await BrowserTestUtils.closeWindow(secondNewWindow);
|
||||
await BrowserTestUtils.closeWindow(newWindow);
|
||||
});
|
|
@ -20,6 +20,7 @@ add_task(async function() {
|
|||
const ABOUT_ROBOTS_URI = "about:robots";
|
||||
const ABOUT_ROBOTS_TITLE = "Gort! Klaatu barada nikto!";
|
||||
const NO_TITLE_URL = "data:text/plain,foo";
|
||||
const EMPTY_TAB_TITLE = gBrowser.tabContainer.emptyTabTitle;
|
||||
|
||||
function observeLabelChanges(tab, expectedLabels) {
|
||||
let seenLabels = [tab.label];
|
||||
|
@ -44,10 +45,11 @@ add_task(async function() {
|
|||
{ entries: [{ url: ABOUT_ROBOTS_URI, triggeringPrincipal_base64 }] },
|
||||
{ entries: [{ url: REMOTE_URL, triggeringPrincipal_base64 }] },
|
||||
{ entries: [{ url: NO_TITLE_URL, triggeringPrincipal_base64 }] },
|
||||
{ entries: [{ url: "about:blank", triggeringPrincipal_base64 }] },
|
||||
],
|
||||
}],
|
||||
});
|
||||
let [tab1, tab2, tab3, tab4] = gBrowser.tabs;
|
||||
let [tab1, tab2, tab3, tab4, tab5] = gBrowser.tabs;
|
||||
is(gBrowser.selectedTab, tab1, "first tab is selected");
|
||||
|
||||
await browserLoadedPromise;
|
||||
|
@ -61,6 +63,7 @@ add_task(async function() {
|
|||
ok(tab2.hasAttribute("pending"), "second tab is pending");
|
||||
ok(tab3.hasAttribute("pending"), "third tab is pending");
|
||||
ok(tab4.hasAttribute("pending"), "fourth tab is pending");
|
||||
is(tab5.label, EMPTY_TAB_TITLE, "fifth tab dislpays empty tab title");
|
||||
|
||||
info("selecting the second tab");
|
||||
// The fix for bug 1364127 caused about: pages' initial tab titles to show
|
||||
|
@ -98,7 +101,7 @@ add_task(async function() {
|
|||
gBrowser.selectedTab = tab3;
|
||||
await TabStateFlusher.flushWindow(window);
|
||||
await promiseBrowserState(SessionStore.getBrowserState());
|
||||
[tab1, tab2, tab3, tab4] = gBrowser.tabs;
|
||||
[tab1, tab2, tab3, tab4, tab5] = gBrowser.tabs;
|
||||
is(tab3, gBrowser.selectedTab, "third tab is selected after restoring");
|
||||
ok(document.title.startsWith(REMOTE_TITLE), "title bar displays content title");
|
||||
ok(tab1.hasAttribute("pending"), "first tab is pending after restoring");
|
||||
|
@ -108,6 +111,7 @@ add_task(async function() {
|
|||
is(tab3.label, REMOTE_TITLE, "third tab displays content title in pending state");
|
||||
ok(tab4.hasAttribute("pending"), "fourth tab is pending after restoring");
|
||||
is(tab4.label, NO_TITLE_URL, "fourth tab displays URL");
|
||||
is(tab5.label, EMPTY_TAB_TITLE, "fifth tab still displays empty tab title");
|
||||
|
||||
info("selecting the first tab");
|
||||
finishObservingLabelChanges = observeLabelChanges(tab1, [REMOTE_TITLE]);
|
||||
|
|
|
@ -255,6 +255,11 @@ class UrlbarInput {
|
|||
this.inputField.value = val;
|
||||
this.formatValue();
|
||||
|
||||
// Dispatch ValueChange event for accessibility.
|
||||
let event = this.document.createEvent("Events");
|
||||
event.initEvent("ValueChange", true, true);
|
||||
this.inputField.dispatchEvent(event);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ policy-BlockAboutSupport = Block access to the about:support page.
|
|||
|
||||
policy-Bookmarks = Create bookmarks in the Bookmarks toolbar, Bookmarks menu, or a specified folder inside them.
|
||||
|
||||
policy-Certificates = Whether or not to use built-in certificates. This policy is Windows only at this time.
|
||||
policy-CertificatesDescription = Add certificates or use built-in certificates.
|
||||
|
||||
policy-Cookies = Allow or deny websites to set cookies.
|
||||
|
||||
|
|
|
@ -63,10 +63,10 @@ permissions-invalid-uri-label = Please enter a valid hostname
|
|||
|
||||
## Exceptions - Tracking Protection
|
||||
|
||||
permissions-exceptions-tracking-protection-window =
|
||||
.title = Exceptions - Tracking Protection
|
||||
permissions-exceptions-content-blocking-window =
|
||||
.title = Exceptions - Content Blocking
|
||||
.style = { permissions-window.style }
|
||||
permissions-exceptions-tracking-protection-desc = You have disabled Tracking Protection on these websites.
|
||||
permissions-exceptions-content-blocking-desc = You have disabled content blocking on these websites.
|
||||
|
||||
## Exceptions - Cookies
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<!ENTITY advanced.label "Advanced">
|
||||
<!ENTITY continue2.label "More…">
|
||||
<!ENTITY moreInformation.label "More Information">
|
||||
<!ENTITY viewCertificate.label "View Certificate">
|
||||
|
||||
<!-- Specific error messages -->
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ button:disabled {
|
|||
display: flex;
|
||||
justify-content: end;
|
||||
padding: 5px;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
body:not(.neterror) #certErrorAndCaptivePortalButtonContainer {
|
||||
|
@ -158,8 +159,12 @@ span#hostname {
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#viewCertificate {
|
||||
margin: 0 3em;
|
||||
}
|
||||
|
||||
#badCertTechnicalInfo {
|
||||
margin: 3em;
|
||||
margin: 3em 3em 1em;
|
||||
overflow: auto;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
|
|
@ -289,7 +289,7 @@ var TestRunner = {
|
|||
this.mochitestScope.info(
|
||||
`\tSkipped configuration ` +
|
||||
`[ ${combo.map((e) => e.name).join(", ")} ] ` +
|
||||
`for "${reason}" in ${config.name}.${func}`);
|
||||
`for "${reason}" in ${config.name}.${func}`);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -26,7 +26,11 @@ const MIXED_PASSIVE_CONTENT_URL = `https://example.com/${RESOURCE_PATH}/mixed_pa
|
|||
const TRACKING_PAGE = `http://tracking.example.org/${RESOURCE_PATH}/tracking.html`;
|
||||
|
||||
var ControlCenter = {
|
||||
init(libDir) { },
|
||||
init(libDir) {
|
||||
// Disable the FTU tours.
|
||||
Services.prefs.setIntPref("privacy.trackingprotection.introCount", 20);
|
||||
Services.prefs.setIntPref("browser.contentblocking.introCount", 20);
|
||||
},
|
||||
|
||||
configurations: {
|
||||
about: {
|
||||
|
@ -218,7 +222,6 @@ var ControlCenter = {
|
|||
selectors: ["#identity-popup"],
|
||||
async applyConfig() {
|
||||
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true);
|
||||
Services.prefs.setIntPref("privacy.trackingprotection.introCount", 20);
|
||||
await UrlClassifierTestUtils.addTestTrackers();
|
||||
|
||||
await loadPage(TRACKING_PAGE);
|
||||
|
@ -232,7 +235,6 @@ var ControlCenter = {
|
|||
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let gBrowser = browserWindow.gBrowser;
|
||||
Services.prefs.setBoolPref("privacy.trackingprotection.enabled", true);
|
||||
Services.prefs.setIntPref("privacy.trackingprotection.introCount", 20);
|
||||
await UrlClassifierTestUtils.addTestTrackers();
|
||||
|
||||
await loadPage(TRACKING_PAGE);
|
||||
|
|
|
@ -14,10 +14,12 @@ mozilla.pth:third_party/python/compare-locales
|
|||
mozilla.pth:third_party/python/configobj
|
||||
mozilla.pth:third_party/python/cram
|
||||
mozilla.pth:third_party/python/dlmanager
|
||||
mozilla.pth:third_party/python/enum34
|
||||
mozilla.pth:third_party/python/fluent
|
||||
mozilla.pth:third_party/python/funcsigs
|
||||
mozilla.pth:third_party/python/futures
|
||||
mozilla.pth:third_party/python/more-itertools
|
||||
mozilla.pth:third_party/python/mozilla-version
|
||||
mozilla.pth:third_party/python/gyp/pylib
|
||||
mozilla.pth:third_party/python/python-hglib
|
||||
mozilla.pth:third_party/python/pluggy
|
||||
|
|
|
@ -34,6 +34,8 @@ const {
|
|||
removeUSBRuntimesObserver,
|
||||
} = require("./src/modules/usb-runtimes");
|
||||
|
||||
loader.lazyRequireGetter(this, "adbAddon", "devtools/shared/adb/adb-addon", true);
|
||||
|
||||
const App = createFactory(require("./src/components/App"));
|
||||
|
||||
const { PAGES, RUNTIMES } = require("./src/constants");
|
||||
|
@ -46,6 +48,7 @@ const AboutDebugging = {
|
|||
return;
|
||||
}
|
||||
|
||||
this.onAdbAddonUpdated = this.onAdbAddonUpdated.bind(this);
|
||||
this.onNetworkLocationsUpdated = this.onNetworkLocationsUpdated.bind(this);
|
||||
this.onUSBRuntimesUpdated = this.onUSBRuntimesUpdated.bind(this);
|
||||
|
||||
|
@ -65,6 +68,9 @@ const AboutDebugging = {
|
|||
addNetworkLocationsObserver(this.onNetworkLocationsUpdated);
|
||||
addUSBRuntimesObserver(this.onUSBRuntimesUpdated);
|
||||
await enableUSBRuntimes();
|
||||
|
||||
adbAddon.on("update", this.onAdbAddonUpdated);
|
||||
this.onAdbAddonUpdated();
|
||||
},
|
||||
|
||||
async createMessageContexts() {
|
||||
|
@ -92,6 +98,10 @@ const AboutDebugging = {
|
|||
return contexts;
|
||||
},
|
||||
|
||||
onAdbAddonUpdated() {
|
||||
this.actions.updateAdbAddonStatus(adbAddon.status);
|
||||
},
|
||||
|
||||
onNetworkLocationsUpdated() {
|
||||
this.actions.updateNetworkLocations(getNetworkLocations());
|
||||
},
|
||||
|
@ -113,6 +123,7 @@ const AboutDebugging = {
|
|||
removeNetworkLocationsObserver(this.onNetworkLocationsUpdated);
|
||||
removeUSBRuntimesObserver(this.onUSBRuntimesUpdated);
|
||||
disableUSBRuntimes();
|
||||
adbAddon.off("update", this.onAdbAddonUpdated);
|
||||
setDebugTargetCollapsibilities(state.ui.debugTargetCollapsibilities);
|
||||
unmountComponentAtNode(this.mount);
|
||||
},
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const {
|
||||
ADB_ADDON_STATUS_UPDATED,
|
||||
DEBUG_TARGET_COLLAPSIBILITY_UPDATED,
|
||||
NETWORK_LOCATIONS_UPDATED,
|
||||
PAGE_SELECTED,
|
||||
|
@ -60,6 +61,10 @@ function removeNetworkLocation(location) {
|
|||
};
|
||||
}
|
||||
|
||||
function updateAdbAddonStatus(adbAddonStatus) {
|
||||
return { type: ADB_ADDON_STATUS_UPDATED, adbAddonStatus };
|
||||
}
|
||||
|
||||
function updateNetworkLocations(locations) {
|
||||
return { type: NETWORK_LOCATIONS_UPDATED, locations };
|
||||
}
|
||||
|
@ -68,6 +73,7 @@ module.exports = {
|
|||
addNetworkLocation,
|
||||
removeNetworkLocation,
|
||||
selectPage,
|
||||
updateAdbAddonStatus,
|
||||
updateDebugTargetCollapsibility,
|
||||
updateNetworkLocations,
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ const Sidebar = createFactory(require("./sidebar/Sidebar"));
|
|||
class App extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
adbAddonStatus: PropTypes.string,
|
||||
// The "dispatch" helper is forwarded to the App component via connect.
|
||||
// From that point, components are responsible for forwarding the dispatch
|
||||
// property to all components who need to dispatch actions.
|
||||
|
@ -51,6 +52,7 @@ class App extends PureComponent {
|
|||
|
||||
render() {
|
||||
const {
|
||||
adbAddonStatus,
|
||||
dispatch,
|
||||
messageContexts,
|
||||
runtimes,
|
||||
|
@ -61,7 +63,15 @@ class App extends PureComponent {
|
|||
{ messages: messageContexts },
|
||||
dom.div(
|
||||
{ className: "app" },
|
||||
Sidebar({ className: "app__sidebar", dispatch, runtimes, selectedPage }),
|
||||
Sidebar(
|
||||
{
|
||||
adbAddonStatus,
|
||||
className: "app__sidebar",
|
||||
dispatch,
|
||||
runtimes,
|
||||
selectedPage
|
||||
}
|
||||
),
|
||||
dom.main(
|
||||
{ className: "app__content" },
|
||||
this.getSelectedPageComponent()
|
||||
|
@ -73,6 +83,7 @@ class App extends PureComponent {
|
|||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
adbAddonStatus: state.ui.adbAddonStatus,
|
||||
runtimes: state.runtimes,
|
||||
networkLocations: state.ui.networkLocations,
|
||||
selectedPage: state.ui.selectedPage,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.sidebar__devices__no-devices-message {
|
||||
.sidebar__devices__message {
|
||||
color: var(--grey-40);
|
||||
display: inline-block;
|
||||
padding: 12px 0;
|
||||
|
|
|
@ -12,6 +12,7 @@ const FluentReact = require("devtools/client/shared/vendor/fluent-react");
|
|||
const Localized = createFactory(FluentReact.Localized);
|
||||
|
||||
const { PAGES, RUNTIMES } = require("../../constants");
|
||||
loader.lazyRequireGetter(this, "ADB_ADDON_STATES", "devtools/shared/adb/adb-addon", true);
|
||||
|
||||
const SidebarFixedItem = createFactory(require("./SidebarFixedItem"));
|
||||
const SidebarRuntimeItem = createFactory(require("./SidebarRuntimeItem"));
|
||||
|
@ -23,6 +24,7 @@ const USB_ICON = "chrome://devtools/skin/images/aboutdebugging-connect-icon.svg"
|
|||
class Sidebar extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
adbAddonStatus: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
runtimes: PropTypes.object.isRequired,
|
||||
|
@ -30,15 +32,31 @@ class Sidebar extends PureComponent {
|
|||
};
|
||||
}
|
||||
|
||||
renderAdbAddonStatus() {
|
||||
const isAddonInstalled = this.props.adbAddonStatus === ADB_ADDON_STATES.INSTALLED;
|
||||
const localizationId = isAddonInstalled ? "about-debugging-sidebar-usb-enabled" :
|
||||
"about-debugging-sidebar-usb-disabled";
|
||||
return Localized(
|
||||
{
|
||||
id: localizationId
|
||||
}, dom.aside(
|
||||
{
|
||||
className: "sidebar__devices__message js-sidebar-usb-status"
|
||||
},
|
||||
localizationId
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderDevices() {
|
||||
const { runtimes } = this.props;
|
||||
if (!runtimes.networkRuntimes.length && !runtimes.usbRuntimes.length) {
|
||||
return Localized(
|
||||
{
|
||||
id: "about-debugging-sidebar-no-devices"
|
||||
}, dom.span(
|
||||
}, dom.aside(
|
||||
{
|
||||
className: "sidebar__devices__no-devices-message js-sidebar-no-devices"
|
||||
className: "sidebar__devices__message js-sidebar-no-devices"
|
||||
},
|
||||
"No devices discovered"
|
||||
)
|
||||
|
@ -103,6 +121,7 @@ class Sidebar extends PureComponent {
|
|||
})
|
||||
),
|
||||
dom.hr(),
|
||||
this.renderAdbAddonStatus(),
|
||||
this.renderDevices()
|
||||
)
|
||||
);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const actionTypes = {
|
||||
ADB_ADDON_STATUS_UPDATED: "ADB_ADDON_STATUS_UPDATED",
|
||||
CONNECT_RUNTIME_FAILURE: "CONNECT_RUNTIME_FAILURE",
|
||||
CONNECT_RUNTIME_START: "CONNECT_RUNTIME_START",
|
||||
CONNECT_RUNTIME_SUCCESS: "CONNECT_RUNTIME_SUCCESS",
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const {
|
||||
ADB_ADDON_STATUS_UPDATED,
|
||||
DEBUG_TARGET_COLLAPSIBILITY_UPDATED,
|
||||
NETWORK_LOCATIONS_UPDATED,
|
||||
PAGE_SELECTED,
|
||||
|
@ -12,6 +13,7 @@ const {
|
|||
|
||||
function UiState(locations = [], debugTargetCollapsibilities = {}) {
|
||||
return {
|
||||
adbAddonStatus: null,
|
||||
debugTargetCollapsibilities,
|
||||
networkLocations: locations,
|
||||
selectedPage: null,
|
||||
|
@ -20,6 +22,11 @@ function UiState(locations = [], debugTargetCollapsibilities = {}) {
|
|||
|
||||
function uiReducer(state = UiState(), action) {
|
||||
switch (action.type) {
|
||||
case ADB_ADDON_STATUS_UPDATED: {
|
||||
const { adbAddonStatus } = action;
|
||||
return Object.assign({}, state, { adbAddonStatus });
|
||||
}
|
||||
|
||||
case DEBUG_TARGET_COLLAPSIBILITY_UPDATED: {
|
||||
const { isCollapsed, key } = action;
|
||||
const debugTargetCollapsibilities = new Map(state.debugTargetCollapsibilities);
|
||||
|
|
|
@ -5,6 +5,7 @@ support-files =
|
|||
debug-target-pane_collapsibilities_head.js
|
||||
head-addons-script.js
|
||||
head.js
|
||||
resources/test-adb-extension/*
|
||||
resources/test-temporary-extension/*
|
||||
!/devtools/client/shared/test/shared-head.js
|
||||
!/devtools/client/shared/test/telemetry-test-helpers.js
|
||||
|
@ -15,4 +16,6 @@ support-files =
|
|||
[browser_aboutdebugging_debug-target-pane_empty.js]
|
||||
[browser_aboutdebugging_navigate.js]
|
||||
[browser_aboutdebugging_sidebar_network_runtimes.js]
|
||||
[browser_aboutdebugging_sidebar_usb_status.js]
|
||||
skip-if = (os == 'linux' && bits == 32) # ADB start() fails on linux 32, see Bug 1499638
|
||||
[browser_aboutdebugging_thisfirefox.js]
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { adbAddon } = require("devtools/shared/adb/adb-addon");
|
||||
const { ADB } = require("devtools/shared/adb/adb");
|
||||
|
||||
/**
|
||||
* This test asserts that the sidebar shows a message describing the status of the USB
|
||||
* devices scanning.
|
||||
*/
|
||||
add_task(async function() {
|
||||
// Make sure the ADB addon is removed and ADB is stopped when the test ends.
|
||||
registerCleanupFunction(async function() {
|
||||
try {
|
||||
await adbAddon.uninstall();
|
||||
} catch (e) {
|
||||
// Will throw if the addon is already uninstalled, ignore exceptions here.
|
||||
}
|
||||
|
||||
await ADB.kill();
|
||||
});
|
||||
|
||||
await pushPref("devtools.remote.adb.extensionURL",
|
||||
CHROME_URL_ROOT + "resources/test-adb-extension/adb-extension-#OS#.xpi");
|
||||
|
||||
const { document, tab } = await openAboutDebugging();
|
||||
|
||||
const usbStatusElement = document.querySelector(".js-sidebar-usb-status");
|
||||
ok(usbStatusElement, "Sidebar shows the USB status element");
|
||||
ok(usbStatusElement.textContent.includes("USB devices disabled"),
|
||||
"USB status element has the expected content");
|
||||
|
||||
info("Install the adb extension and wait for the message to udpate");
|
||||
adbAddon.install();
|
||||
await waitUntil(() => usbStatusElement.textContent.includes("USB devices enabled"));
|
||||
|
||||
// Right now we are resuming as soon as "USB devices enabled" is displayed, but ADB
|
||||
// might still be starting up. If we move to uninstall directly, the ADB startup will
|
||||
// fail and we will have an unhandled promise rejection.
|
||||
// See Bug 1498469.
|
||||
info("Wait until ADB has started.");
|
||||
await waitUntil(() => ADB.ready);
|
||||
|
||||
info("Uninstall the adb extension and wait for the message to udpate");
|
||||
adbAddon.uninstall();
|
||||
await waitUntil(() => usbStatusElement.textContent.includes("USB devices disabled"));
|
||||
|
||||
await removeTab(tab);
|
||||
});
|
Двоичные данные
devtools/client/aboutdebugging-new/test/browser/resources/test-adb-extension/adb-extension-linux.xpi
Normal file
Двоичные данные
devtools/client/aboutdebugging-new/test/browser/resources/test-adb-extension/adb-extension-linux.xpi
Normal file
Двоичный файл не отображается.
Двоичные данные
devtools/client/aboutdebugging-new/test/browser/resources/test-adb-extension/adb-extension-linux64.xpi
Normal file
Двоичные данные
devtools/client/aboutdebugging-new/test/browser/resources/test-adb-extension/adb-extension-linux64.xpi
Normal file
Двоичный файл не отображается.
Двоичные данные
devtools/client/aboutdebugging-new/test/browser/resources/test-adb-extension/adb-extension-mac64.xpi
Normal file
Двоичные данные
devtools/client/aboutdebugging-new/test/browser/resources/test-adb-extension/adb-extension-mac64.xpi
Normal file
Двоичный файл не отображается.
Двоичные данные
devtools/client/aboutdebugging-new/test/browser/resources/test-adb-extension/adb-extension-win32.xpi
Normal file
Двоичные данные
devtools/client/aboutdebugging-new/test/browser/resources/test-adb-extension/adb-extension-win32.xpi
Normal file
Двоичный файл не отображается.
|
@ -13,6 +13,13 @@ about-debugging-sidebar-this-firefox =
|
|||
about-debugging-sidebar-connect =
|
||||
.name = Connect
|
||||
|
||||
# Text displayed in the about:debugging sidebar when USB devices discovery is enabled.
|
||||
about-debugging-sidebar-usb-enabled = USB devices enabled
|
||||
|
||||
# Text displayed in the about:debugging sidebar when USB devices discovery is disabled
|
||||
# (for instance because the mandatory ADB extension is not installed).
|
||||
about-debugging-sidebar-usb-disabled = USB devices disabled
|
||||
|
||||
# Connection status (connected) for runtime items in the sidebar
|
||||
aboutdebugging-sidebar-runtime-connection-status-connected = Connected
|
||||
# Connection status (disconnected) for runtime items in the sidebar
|
||||
|
|
|
@ -140,8 +140,16 @@ Selection.prototype = {
|
|||
nodeFront = parentNode;
|
||||
}
|
||||
|
||||
if (this._nodeFront == null && nodeFront == null) {
|
||||
// Avoid to notify multiple "unselected" events with a null/undefined nodeFront
|
||||
// (e.g. once when the webpage start to navigate away from the current webpage,
|
||||
// and then again while the new page is being loaded).
|
||||
return;
|
||||
}
|
||||
|
||||
this._isSlotted = isSlotted;
|
||||
this._nodeFront = nodeFront;
|
||||
|
||||
this.emit("new-node-front", nodeFront, this.reason);
|
||||
},
|
||||
|
||||
|
|
|
@ -3,15 +3,21 @@ tags = devtools
|
|||
subsuite = devtools
|
||||
support-files =
|
||||
doc_flexbox_simple.html
|
||||
doc_flexbox_pseudos.html
|
||||
head.js
|
||||
!/devtools/client/inspector/test/head.js
|
||||
!/devtools/client/inspector/test/shared-head.js
|
||||
!/devtools/client/shared/test/shared-head.js
|
||||
!/devtools/client/shared/test/telemetry-test-helpers.js
|
||||
!/devtools/client/shared/test/test-actor.js
|
||||
!/devtools/client/shared/test/test-actor-registry.js
|
||||
|
||||
[browser_flexbox_highlighter_color_picker_on_ESC.js]
|
||||
[browser_flexbox_highlighter_color_picker_on_RETURN.js]
|
||||
[browser_flexbox_item_outline_exists.js]
|
||||
[browser_flexbox_item_outline_has_correct_layout.js]
|
||||
[browser_flexbox_item_outline_rotates_for_column.js]
|
||||
[browser_flexbox_pseudo_elements_are_listed.js]
|
||||
[browser_flexbox_sizing_info_exists.js]
|
||||
[browser_flexbox_sizing_info_for_pseudos.js]
|
||||
[browser_flexbox_sizing_info_has_correct_sections.js]
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that pseudo-elements that are flex items do appear in the list of items.
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_flexbox_pseudos.html";
|
||||
|
||||
add_task(async function() {
|
||||
await addTab(TEST_URI);
|
||||
const { inspector, flexboxInspector } = await openLayoutView();
|
||||
const { document: doc } = flexboxInspector;
|
||||
|
||||
// Select the flex container in the inspector.
|
||||
const onItemsListRendered = waitForDOM(doc,
|
||||
"#layout-flexbox-container .flex-item-list");
|
||||
await selectNode(".container", inspector);
|
||||
const [flexItemList] = await onItemsListRendered;
|
||||
|
||||
const items = [...flexItemList.querySelectorAll("li")];
|
||||
is(items.length, 2, "There are 2 items displayed in the list");
|
||||
|
||||
is(items[0].textContent, "::before", "The first item is ::before");
|
||||
is(items[1].textContent, "::after", "The second item is ::after");
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the flex item sizing UI also appears for pseudo elements.
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_flexbox_pseudos.html";
|
||||
|
||||
add_task(async function() {
|
||||
await addTab(TEST_URI);
|
||||
const { inspector, flexboxInspector } = await openLayoutView();
|
||||
const { document: doc } = flexboxInspector;
|
||||
|
||||
info("Select the ::before pseudo-element in the inspector");
|
||||
const containerNode = await getNodeFront(".container", inspector);
|
||||
const { nodes } = await inspector.walker.children(containerNode);
|
||||
const beforeNode = nodes[0];
|
||||
|
||||
const onFlexItemSizingRendered = waitForDOM(doc, "ul.flex-item-sizing");
|
||||
const onFlexItemOutlineRendered = waitForDOM(doc, ".flex-outline-container");
|
||||
await selectNode(beforeNode, inspector);
|
||||
const [flexSizingContainer] = await onFlexItemSizingRendered;
|
||||
const [flexOutlineContainer] = await onFlexItemOutlineRendered;
|
||||
|
||||
ok(flexSizingContainer, "The flex sizing exists in the DOM");
|
||||
ok(flexOutlineContainer, "The flex outline exists in the DOM");
|
||||
|
||||
info("Check that the various sizing sections are displayed");
|
||||
const allSections = [...flexSizingContainer.querySelectorAll(".section")];
|
||||
ok(allSections.length, "Sizing sections are displayed");
|
||||
|
||||
info("Check that the various parts of the outline are displayed");
|
||||
const [basis, final] = [...flexOutlineContainer.querySelectorAll(
|
||||
".flex-outline-basis, .flex-outline-final")];
|
||||
ok(basis && final, "The final and basis parts of the outline exist");
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
.container {
|
||||
width: 300px;
|
||||
height: 150px;
|
||||
margin: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.container::before,
|
||||
.container::after {
|
||||
color: #f06;
|
||||
border: 1px solid #f06;
|
||||
background: gold;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.container::before {
|
||||
content: "::before pseudo-element item";
|
||||
}
|
||||
|
||||
.container::after {
|
||||
content: "::after pseudo-element item";
|
||||
}
|
||||
</style>
|
||||
<div class="container"></div>
|
|
@ -157,6 +157,7 @@ devtools.jar:
|
|||
skin/images/command-chevron.svg (themes/images/command-chevron.svg)
|
||||
skin/markup.css (themes/markup.css)
|
||||
skin/images/editor-error.png (themes/images/editor-error.png)
|
||||
skin/images/webconsole/globe.svg (themes/images/webconsole/globe.svg)
|
||||
skin/images/breakpoint.svg (themes/images/breakpoint.svg)
|
||||
skin/webconsole.css (themes/webconsole.css)
|
||||
skin/images/webconsole/alert.svg (themes/images/webconsole/alert.svg)
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
"use strict";
|
||||
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { MemoryFront } = require("devtools/shared/fronts/memory");
|
||||
const { Cu } = require("chrome");
|
||||
const HeapAnalysesClient = require("devtools/shared/heapsnapshot/HeapAnalysesClient");
|
||||
|
||||
|
@ -31,11 +30,7 @@ MemoryPanel.prototype = {
|
|||
|
||||
this.panelWin.gToolbox = this._toolbox;
|
||||
this.panelWin.gTarget = this.target;
|
||||
|
||||
const rootForm = await this.target.root;
|
||||
this.panelWin.gFront = new MemoryFront(this.target.client,
|
||||
this.target.form,
|
||||
rootForm);
|
||||
this.panelWin.gFront = this.target.getFront("memory");
|
||||
this.panelWin.gHeapAnalysesClient = new HeapAnalysesClient();
|
||||
|
||||
await this.panelWin.gFront.attach();
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg viewBox="0 0 24 24" fill="context-fill #0b0b0b" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.062 11a8.009 8.009 0 0 1 5.14-6.497c-.05.137-.1.28-.15.43C8.577 6.356 8.113 8.379 8.017 11H4.062zm6.887-5.434c.234-.702.465-1.22.632-1.555a8.138 8.138 0 0 1 .838 0c.167.335.398.853.632 1.555.412 1.237.835 3.047.93 5.434H10.02c.094-2.387.517-4.197.929-5.434zM13.98 13h-3.96c.094 2.387.517 4.197.929 5.434.234.701.465 1.22.632 1.555a8.07 8.07 0 0 0 .838 0c.167-.335.398-.854.632-1.555.412-1.237.835-3.047.93-5.434zm.819 6.497c.05-.137.1-.28.15-.43.473-1.422.937-3.444 1.033-6.067h3.956a8.009 8.009 0 0 1-5.14 6.497zM15.982 11c-.096-2.622-.56-4.645-1.033-6.066-.05-.15-.1-.294-.15-.43A8.009 8.009 0 0 1 19.939 11h-3.957zm-11.92 2h3.956c.096 2.623.56 4.645 1.033 6.066a15.91 15.91 0 0 0 .15.43A8.009 8.009 0 0 1 4.062 13zM12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2z"></path></svg>
|
После Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -218,6 +218,7 @@
|
|||
--theme-pane-collapse-image: url(chrome://devtools/skin/images/pane-collapse.svg);
|
||||
--theme-pane-expand-image: url(chrome://devtools/skin/images/pane-expand.svg);
|
||||
--theme-console-alert-image: url(chrome://devtools/skin/images/webconsole/alert.svg);
|
||||
--theme-console-navigation-image: url(chrome://devtools/skin/images/webconsole/globe.svg);
|
||||
--theme-console-info-image: url(chrome://devtools/skin/images/webconsole/info.svg);
|
||||
--theme-console-input-image: url(chrome://devtools/skin/images/webconsole/input.svg);
|
||||
--theme-console-return-image: url(chrome://devtools/skin/images/webconsole/return.svg);
|
||||
|
|
|
@ -102,6 +102,11 @@ a {
|
|||
background-color: var(--error-background-color);
|
||||
}
|
||||
|
||||
.message.navigationMarker {
|
||||
border-top: 1px solid var(--theme-emphasized-splitter-color);
|
||||
color: var(--object-color);
|
||||
}
|
||||
|
||||
.message.warn {
|
||||
color: var(--warning-color);
|
||||
background-color: var(--warning-background-color);
|
||||
|
@ -206,6 +211,11 @@ a {
|
|||
background-image: var(--theme-console-alert-image);
|
||||
}
|
||||
|
||||
.message.navigationMarker > .icon {
|
||||
color: var(--object-color);
|
||||
background-image: var(--theme-console-navigation-image);
|
||||
}
|
||||
|
||||
|
||||
.message > span.icon[title="Jump"] {
|
||||
background-image:var(--theme-console-jump-image);
|
||||
|
@ -319,7 +329,7 @@ a {
|
|||
flex: none;
|
||||
}
|
||||
|
||||
.message.network:not(.navigation-marker) .url {
|
||||
.message.network .url {
|
||||
flex: 1 1 auto;
|
||||
/* Make sure the URL is very small initially, let flex change width as needed. */
|
||||
width: 100px;
|
||||
|
@ -452,25 +462,6 @@ textarea.jsterm-input-node:focus {
|
|||
|
||||
/* Security styles */
|
||||
|
||||
.navigation-marker {
|
||||
color: #aaa;
|
||||
background: linear-gradient(#aaa, #aaa) no-repeat left 50%;
|
||||
background-size: 100% 2px;
|
||||
margin-block-start: 6px;
|
||||
margin-block-end: 6px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.navigation-marker .url {
|
||||
padding-inline-end: 9px;
|
||||
text-decoration: none;
|
||||
background: var(--theme-body-background);
|
||||
}
|
||||
|
||||
.theme-light .navigation-marker .url {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.stacktrace {
|
||||
display: none;
|
||||
overflow-y: auto;
|
||||
|
@ -723,7 +714,7 @@ a.learn-more-link.webconsole-learn-more-link {
|
|||
line-height: inherit;
|
||||
}
|
||||
|
||||
.webconsole-output-wrapper .message.network:not(.navigation-marker) .url {
|
||||
.webconsole-output-wrapper .message.network .url {
|
||||
color: var(--theme-comment);
|
||||
font-style: inherit;
|
||||
}
|
||||
|
|
|
@ -134,6 +134,7 @@ const chromeRDPEnums = {
|
|||
// Undocumented in Chrome RDP, but is used for messages that should not
|
||||
// output anything (e.g. `console.time()` calls).
|
||||
NULL_MESSAGE: "nullMessage",
|
||||
NAVIGATION_MARKER: "navigationMarker"
|
||||
},
|
||||
MESSAGE_LEVEL: {
|
||||
LOG: "log",
|
||||
|
|
|
@ -197,7 +197,7 @@ function transformNavigationMessagePacket(packet) {
|
|||
const { message } = packet;
|
||||
return new ConsoleMessage({
|
||||
source: MESSAGE_SOURCE.CONSOLE_API,
|
||||
type: MESSAGE_TYPE.LOG,
|
||||
type: MESSAGE_TYPE.NAVIGATION_MARKER,
|
||||
level: MESSAGE_LEVEL.LOG,
|
||||
messageText: l10n.getFormatStr("webconsole.navigated", [message.url]),
|
||||
timeStamp: message.timeStamp,
|
||||
|
|
|
@ -223,9 +223,7 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
|
|||
get displayType() {
|
||||
// Consider all non-element nodes as displayed.
|
||||
if (InspectorActorUtils.isNodeDead(this) ||
|
||||
this.rawNode.nodeType !== Node.ELEMENT_NODE ||
|
||||
isAfterPseudoElement(this.rawNode) ||
|
||||
isBeforePseudoElement(this.rawNode)) {
|
||||
this.rawNode.nodeType !== Node.ELEMENT_NODE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -171,7 +171,8 @@ const FlexItemActor = ActorClassWithSpec(flexItemSpec, {
|
|||
for (const name in properties) {
|
||||
let value = "";
|
||||
// Look first on the element style.
|
||||
if (this.element.style[name] && this.element.style[name] !== "auto") {
|
||||
if (this.element.style &&
|
||||
this.element.style[name] && this.element.style[name] !== "auto") {
|
||||
value = this.element.style[name];
|
||||
} else {
|
||||
// And then on the rules that apply to the element.
|
||||
|
|
|
@ -4,10 +4,7 @@
|
|||
|
||||
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const Services = require("Services");
|
||||
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
|
||||
const { DebuggerServer } = require("devtools/server/main");
|
||||
|
||||
const { MemoryFront } = require("devtools/shared/fronts/memory");
|
||||
const { TargetFactory } = require("devtools/client/framework/target");
|
||||
|
||||
// Always log packets when running tests.
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||
|
@ -18,26 +15,21 @@ SimpleTest.registerCleanupFunction(function() {
|
|||
Services.prefs.setBoolPref("privacy.reduceTimerPrecision", gReduceTimePrecision);
|
||||
});
|
||||
|
||||
function startServerAndGetSelectedTabMemory() {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.registerAllActors();
|
||||
const client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
|
||||
return client.connect()
|
||||
.then(() => client.listTabs())
|
||||
.then(response => {
|
||||
const form = response.tabs[response.selected];
|
||||
const memory = MemoryFront(client, form, response);
|
||||
|
||||
return { memory, client };
|
||||
});
|
||||
async function getTargetForSelectedTab() {
|
||||
const browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
const target = await TargetFactory.forTab(browserWindow.gBrowser.selectedTab);
|
||||
return target;
|
||||
}
|
||||
|
||||
function destroyServerAndFinish(client) {
|
||||
client.close().then(() => {
|
||||
DebuggerServer.destroy();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
async function startServerAndGetSelectedTabMemory() {
|
||||
const target = await getTargetForSelectedTab();
|
||||
const memory = target.getFront("memory");
|
||||
return {memory, target};
|
||||
}
|
||||
|
||||
async function destroyServerAndFinish(target) {
|
||||
await target.destroy();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function waitForTime(ms) {
|
||||
|
|
|
@ -19,7 +19,7 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
const measurement = await memory.measure();
|
||||
ok(measurement.total > 0, "total memory is valid");
|
||||
ok(measurement.domSize > 0, "domSize is valid");
|
||||
|
@ -30,7 +30,7 @@ window.onload = function() {
|
|||
ok(measurement.otherSize > 0, "otherSize is valid");
|
||||
ok(measurement.jsMilliseconds, "jsMilliseconds is valid");
|
||||
ok(measurement.nonJSMilliseconds, "nonJSMilliseconds is valid");
|
||||
destroyServerAndFinish(client);
|
||||
await destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,7 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
await memory.attach();
|
||||
|
||||
await memory.startRecordingAllocations();
|
||||
|
@ -95,7 +95,7 @@ window.onload = function() {
|
|||
"Should have found all the expected lines");
|
||||
|
||||
await memory.detach();
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,7 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
await memory.attach();
|
||||
|
||||
const allocs = [];
|
||||
|
@ -71,7 +71,7 @@ window.onload = function() {
|
|||
|
||||
memory.off("allocations", onAlloc);
|
||||
await memory.detach();
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,7 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
await memory.attach();
|
||||
|
||||
await memory.startRecordingAllocations();
|
||||
|
@ -71,7 +71,7 @@ window.onload = function() {
|
|||
}
|
||||
|
||||
await memory.detach();
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,7 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
await memory.attach();
|
||||
|
||||
const allocs = [];
|
||||
|
@ -53,7 +53,7 @@ window.onload = function() {
|
|||
// (js/src/jit-test/tests/debug/Memory-allocationsSamplingProbability-*.js).
|
||||
|
||||
await memory.detach();
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,7 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
await memory.attach();
|
||||
|
||||
const allocs = [];
|
||||
|
@ -84,7 +84,7 @@ window.onload = function() {
|
|||
}
|
||||
|
||||
await memory.detach();
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,7 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
await memory.attach();
|
||||
|
||||
const allocs = [];
|
||||
|
@ -42,7 +42,7 @@ window.onload = function() {
|
|||
"There should only be one entry in the allocations log.");
|
||||
|
||||
await memory.detach();
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,7 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
await memory.attach();
|
||||
|
||||
const allocs = [];
|
||||
|
@ -45,7 +45,7 @@ window.onload = function() {
|
|||
"every bytesize is a positive number");
|
||||
|
||||
await memory.detach();
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
|
||||
|
|
|
@ -19,12 +19,12 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
await memory.attach();
|
||||
ok(true, "Shouldn't have gotten an error attaching.");
|
||||
await memory.detach();
|
||||
ok(true, "Shouldn't have gotten an error detaching.");
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,7 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
|
||||
let e = null;
|
||||
try {
|
||||
|
@ -40,7 +40,7 @@ window.onload = function() {
|
|||
ok(e, "Should have hit the wrongState error");
|
||||
|
||||
await memory.detach();
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -19,14 +19,14 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
await memory.attach();
|
||||
|
||||
const census = await memory.takeCensus();
|
||||
is(typeof census, "object");
|
||||
|
||||
await memory.detach();
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,7 @@ window.onload = function() {
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
|
||||
let beforeGC, afterGC;
|
||||
|
||||
|
@ -41,7 +41,7 @@ window.onload = function() {
|
|||
|
||||
ok(true, "The amount of memory after GC should eventually decrease");
|
||||
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -21,7 +21,7 @@ window.onload = function() {
|
|||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
(async function() {
|
||||
const { memory, client } = await startServerAndGetSelectedTabMemory();
|
||||
const { memory, target } = await startServerAndGetSelectedTabMemory();
|
||||
await memory.attach();
|
||||
|
||||
const gotGcEvent = new Promise(resolve => {
|
||||
|
@ -35,7 +35,7 @@ window.onload = function() {
|
|||
await gotGcEvent;
|
||||
|
||||
await memory.detach();
|
||||
destroyServerAndFinish(client);
|
||||
destroyServerAndFinish(target);
|
||||
})();
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -8,8 +8,8 @@ const {AddonManager} = require("resource://gre/modules/AddonManager.jsm");
|
|||
const Services = require("Services");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
const ADB_LINK = Services.prefs.getCharPref("devtools.remote.adb.extensionURL");
|
||||
const ADB_ADDON_ID = Services.prefs.getCharPref("devtools.remote.adb.extensionID");
|
||||
const PREF_ADB_EXTENSION_URL = "devtools.remote.adb.extensionURL";
|
||||
const PREF_ADB_EXTENSION_ID = "devtools.remote.adb.extensionID";
|
||||
|
||||
// Extension ID for adb helper extension that might be installed on Firefox 63 or older.
|
||||
const OLD_ADB_ADDON_ID = "adbhelper@mozilla.org";
|
||||
|
@ -65,8 +65,13 @@ class ADBAddon extends EventEmitter {
|
|||
return this._status;
|
||||
}
|
||||
|
||||
async _getAddon() {
|
||||
const addonId = Services.prefs.getCharPref(PREF_ADB_EXTENSION_ID);
|
||||
return AddonManager.getAddonByID(addonId);
|
||||
}
|
||||
|
||||
async updateInstallStatus() {
|
||||
const addon = await AddonManager.getAddonByID(ADB_ADDON_ID);
|
||||
const addon = await this._getAddon();
|
||||
if (addon && !addon.userDisabled) {
|
||||
this.status = ADB_ADDON_STATES.INSTALLED;
|
||||
} else {
|
||||
|
@ -92,7 +97,8 @@ class ADBAddon extends EventEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
return ADB_LINK.replace(/#OS#/g, OS);
|
||||
const xpiLink = Services.prefs.getCharPref(PREF_ADB_EXTENSION_URL);
|
||||
return xpiLink.replace(/#OS#/g, OS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,7 +109,7 @@ class ADBAddon extends EventEmitter {
|
|||
* String passed to the AddonManager for telemetry.
|
||||
*/
|
||||
async install(source) {
|
||||
const addon = await AddonManager.getAddonByID(ADB_ADDON_ID);
|
||||
const addon = await this._getAddon();
|
||||
if (addon && !addon.userDisabled) {
|
||||
this.status = ADB_ADDON_STATES.INSTALLED;
|
||||
return;
|
||||
|
@ -124,7 +130,7 @@ class ADBAddon extends EventEmitter {
|
|||
}
|
||||
|
||||
async uninstall() {
|
||||
const addon = await AddonManager.getAddonByID(ADB_ADDON_ID);
|
||||
const addon = await this._getAddon();
|
||||
addon.uninstall();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,13 +12,11 @@ loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
|
|||
"devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
|
||||
|
||||
const MemoryFront = protocol.FrontClassWithSpec(memorySpec, {
|
||||
initialize: function(client, form, rootForm = null) {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
this._client = client;
|
||||
this.actorID = form.memoryActor;
|
||||
this.heapSnapshotFileActorID = rootForm
|
||||
? rootForm.heapSnapshotFileActor
|
||||
: null;
|
||||
this.heapSnapshotFileActorID = null;
|
||||
this.manage(this);
|
||||
},
|
||||
|
||||
|
@ -64,7 +62,8 @@ const MemoryFront = protocol.FrontClassWithSpec(memorySpec, {
|
|||
*/
|
||||
transferHeapSnapshot: protocol.custom(async function(snapshotId) {
|
||||
if (!this.heapSnapshotFileActorID) {
|
||||
throw new Error("MemoryFront initialized without a rootForm");
|
||||
const form = await this._client.mainRoot.rootForm;
|
||||
this.heapSnapshotFileActorID = form.heapSnapshotFileActor;
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -32,6 +32,8 @@ const OPEN_CLOSE_BODY = {
|
|||
"(": ")",
|
||||
};
|
||||
|
||||
const NO_AUTOCOMPLETE_PREFIXES = ["var", "const", "let", "function", "class"];
|
||||
|
||||
function hasArrayIndex(str) {
|
||||
return /\[\d+\]$/.test(str);
|
||||
}
|
||||
|
@ -66,6 +68,24 @@ function analyzeInputString(str) {
|
|||
|
||||
// Use an array in order to handle character with a length > 2 (e.g. 😎).
|
||||
const characters = Array.from(str);
|
||||
|
||||
const buildReturnObject = () => {
|
||||
let isElementAccess = false;
|
||||
if (bodyStack.length === 1 && bodyStack[0].token === "[") {
|
||||
start = bodyStack[0].start;
|
||||
isElementAccess = true;
|
||||
if ([STATE_DQUOTE, STATE_QUOTE, STATE_TEMPLATE_LITERAL].includes(state)) {
|
||||
state = STATE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
lastStatement: characters.slice(start).join(""),
|
||||
isElementAccess,
|
||||
};
|
||||
};
|
||||
|
||||
for (let i = 0; i < characters.length; i++) {
|
||||
c = characters[i];
|
||||
|
||||
|
@ -78,9 +98,11 @@ function analyzeInputString(str) {
|
|||
state = STATE_QUOTE;
|
||||
} else if (c == "`") {
|
||||
state = STATE_TEMPLATE_LITERAL;
|
||||
} else if (c == ";") {
|
||||
} else if (";,:=<>+-*/%|&^~?!".split("").includes(c)) {
|
||||
// If the character is an operator, we need to update the start position.
|
||||
start = i + 1;
|
||||
} else if (c == " ") {
|
||||
const currentLastStatement = characters.slice(start, i).join("");
|
||||
const before = characters.slice(0, i);
|
||||
const after = characters.slice(i + 1);
|
||||
const trimmedBefore = Array.from(before.join("").trimRight());
|
||||
|
@ -90,24 +112,23 @@ function analyzeInputString(str) {
|
|||
const nextNonSpaceCharIndex = after.indexOf(nextNonSpaceChar);
|
||||
const previousNonSpaceChar = trimmedBefore[trimmedBefore.length - 1];
|
||||
|
||||
// If the previous meaningful char was a dot and there is no meaningful char
|
||||
// after, we can break out of the loop.
|
||||
if (previousNonSpaceChar === "." && !nextNonSpaceChar) {
|
||||
break;
|
||||
// There's only spaces after that, so we can return.
|
||||
if (!nextNonSpaceChar) {
|
||||
return buildReturnObject();
|
||||
}
|
||||
|
||||
if (nextNonSpaceChar) {
|
||||
// If the previous char wasn't a dot, and the next one isn't a dot either,
|
||||
// update the start pos.
|
||||
if (previousNonSpaceChar !== "." && nextNonSpaceChar !== ".") {
|
||||
start = i + nextNonSpaceCharIndex;
|
||||
}
|
||||
// Let's jump to handle the next non-space char.
|
||||
i = i + nextNonSpaceCharIndex;
|
||||
} else {
|
||||
// There's only spaces after that, so we can break out of the loop.
|
||||
break;
|
||||
// If the previous char in't a dot, and the next one isn't a dot either,
|
||||
// and the current computed statement is not a variable/function/class
|
||||
// declaration, update the start position.
|
||||
if (
|
||||
previousNonSpaceChar !== "." && nextNonSpaceChar !== "."
|
||||
&& !NO_AUTOCOMPLETE_PREFIXES.includes(currentLastStatement)
|
||||
) {
|
||||
start = i + nextNonSpaceCharIndex;
|
||||
}
|
||||
|
||||
// Let's jump to handle the next non-space char.
|
||||
i = i + nextNonSpaceCharIndex;
|
||||
} else if (OPEN_BODY.includes(c)) {
|
||||
bodyStack.push({
|
||||
token: c,
|
||||
|
@ -166,20 +187,7 @@ function analyzeInputString(str) {
|
|||
}
|
||||
}
|
||||
|
||||
let isElementAccess = false;
|
||||
if (bodyStack.length === 1 && bodyStack[0].token === "[") {
|
||||
start = bodyStack[0].start;
|
||||
isElementAccess = true;
|
||||
if ([STATE_DQUOTE, STATE_QUOTE, STATE_TEMPLATE_LITERAL].includes(state)) {
|
||||
state = STATE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
lastStatement: characters.slice(start).join(""),
|
||||
isElementAccess,
|
||||
};
|
||||
return buildReturnObject();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,16 +245,22 @@ function JSPropertyProvider(dbgObject, anEnvironment, inputValue, cursor) {
|
|||
if (state != STATE_NORMAL) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Don't complete on just an empty string.
|
||||
if (lastStatement.trim() == "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (NO_AUTOCOMPLETE_PREFIXES.some(prefix => lastStatement.startsWith(prefix + " "))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const completionPart = lastStatement;
|
||||
const lastDotIndex = completionPart.lastIndexOf(".");
|
||||
const lastOpeningBracketIndex = isElementAccess ? completionPart.lastIndexOf("[") : -1;
|
||||
const lastCompletionCharIndex = Math.max(lastDotIndex, lastOpeningBracketIndex);
|
||||
const startQuoteRegex = /^('|"|`)/;
|
||||
|
||||
// Don't complete on just an empty string.
|
||||
if (completionPart.trim() == "") {
|
||||
return null;
|
||||
}
|
||||
// Catch literals like [1,2,3] or "foo" and return the matches from
|
||||
// their prototypes.
|
||||
// Don't run this is a worker, migrating to acorn should allow this
|
||||
|
|
|
@ -85,6 +85,8 @@
|
|||
'da\`ta\`test': "",
|
||||
"da'ta'test": "",
|
||||
}));
|
||||
|
||||
window.varify = true;
|
||||
`;
|
||||
await state.client.evaluateJSAsync(script);
|
||||
|
||||
|
@ -101,6 +103,8 @@
|
|||
doAutocompleteAfterOr,
|
||||
doInsensitiveAutocomplete,
|
||||
doElementAccessAutocomplete,
|
||||
doAutocompleteAfterOperator,
|
||||
dontAutocompleteAfterDeclaration,
|
||||
];
|
||||
|
||||
if (!isWorker) {
|
||||
|
@ -448,6 +452,74 @@
|
|||
matches = (await client.autocomplete(`window[;c`)).matches;
|
||||
ok(!matches.includes("cd") && !matches.includes("clear"), "commands are not returned");
|
||||
}
|
||||
|
||||
async function doAutocompleteAfterOperator(client) {
|
||||
const inputs = [
|
||||
"true;foob",
|
||||
"true,foob",
|
||||
"({key:foob",
|
||||
"a=foob",
|
||||
"if(a<foob",
|
||||
"if(a>foob",
|
||||
"1+foob",
|
||||
"1-foob",
|
||||
"++foob",
|
||||
"--foob",
|
||||
"1*foob",
|
||||
"2**foob",
|
||||
"1/foob",
|
||||
"1%foob",
|
||||
"1|foob",
|
||||
"1&foob",
|
||||
"1^foob",
|
||||
"~foob",
|
||||
"1<<foob",
|
||||
"1>>foob",
|
||||
"1>>>foob",
|
||||
"false||foob",
|
||||
"false&&foob",
|
||||
"x=true?foob",
|
||||
"x=false?1:foob",
|
||||
"!foob",
|
||||
];
|
||||
|
||||
for (const input of inputs) {
|
||||
info(`test autocomplete for "${input}"`);
|
||||
let matches = (await client.autocomplete(input)).matches;
|
||||
ok(matches.includes("foobarObject"), `Expected autocomplete result for ${input}"`);
|
||||
}
|
||||
}
|
||||
|
||||
async function dontAutocompleteAfterDeclaration(client) {
|
||||
info("test autocomplete for 'var win'");
|
||||
let matches = (await client.autocomplete("var win")).matches;
|
||||
is(matches.length, 0, "no autocompletion on a var declaration");
|
||||
|
||||
info("test autocomplete for 'const win'");
|
||||
matches = (await client.autocomplete("const win")).matches;
|
||||
is(matches.length, 0, "no autocompletion on a const declaration");
|
||||
|
||||
info("test autocomplete for 'let win'");
|
||||
matches = (await client.autocomplete("let win")).matches;
|
||||
is(matches.length, 0, "no autocompletion on a let declaration");
|
||||
|
||||
info("test autocomplete for 'function win'");
|
||||
matches = (await client.autocomplete("function win")).matches;
|
||||
is(matches.length, 0, "no autocompletion on a function declaration");
|
||||
|
||||
info("test autocomplete for 'class win'");
|
||||
matches = (await client.autocomplete("class win")).matches;
|
||||
is(matches.length, 0, "no autocompletion on a class declaration");
|
||||
|
||||
info("test autocomplete for 'const win = win'");
|
||||
matches = (await client.autocomplete("const win = win")).matches;
|
||||
ok(matches.includes("window"), "autocompletion still happens after the `=` sign");
|
||||
|
||||
info("test autocomplete for 'in var'");
|
||||
matches = (await client.autocomplete("in var")).matches;
|
||||
ok(matches.includes("varify"),
|
||||
"autocompletion still happens with a property name starting with 'var'");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -4545,15 +4545,6 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
|||
cssClass.AssignLiteral("badStsCert");
|
||||
}
|
||||
|
||||
uint32_t bucketId;
|
||||
if (isStsHost) {
|
||||
// measuring STS separately allows us to measure click through
|
||||
// rates easily
|
||||
bucketId = nsISecurityUITelemetry::WARNING_BAD_CERT_TOP_STS;
|
||||
} else {
|
||||
bucketId = nsISecurityUITelemetry::WARNING_BAD_CERT_TOP;
|
||||
}
|
||||
|
||||
// See if an alternate cert error page is registered
|
||||
nsAutoCString alternateErrorPage;
|
||||
nsresult rv =
|
||||
|
@ -4562,10 +4553,6 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
|||
if (NS_SUCCEEDED(rv)) {
|
||||
errorPage.Assign(alternateErrorPage);
|
||||
}
|
||||
|
||||
if (!IsFrame() && errorPage.EqualsIgnoreCase("certerror")) {
|
||||
Telemetry::Accumulate(mozilla::Telemetry::SECURITY_UI, bucketId);
|
||||
}
|
||||
} else {
|
||||
error = "nssFailure2";
|
||||
}
|
||||
|
|
|
@ -622,7 +622,7 @@ Element::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
|
|||
|
||||
if (bindingURL) {
|
||||
nsCOMPtr<nsIURI> uri = bindingURL->GetURI();
|
||||
nsCOMPtr<nsIPrincipal> principal = bindingURL->mExtraData->Principal();
|
||||
nsCOMPtr<nsIPrincipal> principal = bindingURL->ExtraData()->Principal();
|
||||
|
||||
// We have a binding that must be installed.
|
||||
bool dummy;
|
||||
|
|
|
@ -10794,33 +10794,10 @@ nsContentUtils::GetEventTargetByLoadInfo(nsILoadInfo* aLoadInfo, TaskCategory aC
|
|||
return target.forget();
|
||||
}
|
||||
|
||||
namespace {
|
||||
template<class T>
|
||||
bool IsLocalRefURL(const T& aString) {
|
||||
// Find the first non-"C0 controls + space" character.
|
||||
const typename T::char_type* current = aString.BeginReading();
|
||||
for (; current != aString.EndReading(); current++) {
|
||||
if (*current > 0x20) {
|
||||
// if the first non-"C0 controls + space" character is '#', this is a
|
||||
// local-ref URL.
|
||||
return *current == '#';
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsContentUtils::IsLocalRefURL(const nsString& aString)
|
||||
{
|
||||
return ::IsLocalRefURL(aString);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsContentUtils::IsLocalRefURL(const nsACString& aString)
|
||||
{
|
||||
return ::IsLocalRefURL(aString);
|
||||
return !aString.IsEmpty() && aString[0] == '#';
|
||||
}
|
||||
|
||||
static const uint64_t kIdProcessBits = 32;
|
||||
|
|
|
@ -3231,13 +3231,6 @@ public:
|
|||
static bool
|
||||
IsLocalRefURL(const nsString& aString);
|
||||
|
||||
/**
|
||||
* Detect whether a string is a local-url.
|
||||
* https://drafts.csswg.org/css-values/#local-urls
|
||||
*/
|
||||
static bool
|
||||
IsLocalRefURL(const nsACString& aString);
|
||||
|
||||
static bool
|
||||
IsCustomElementsEnabled() { return sIsCustomElementsEnabled; }
|
||||
|
||||
|
|
|
@ -13786,8 +13786,13 @@ nsIDocument::RequestStorageAccess(mozilla::ErrorResult& aRv)
|
|||
// Note: If this has returned true, the top-level document is guaranteed
|
||||
// to not be on the Content Blocking allow list.
|
||||
DebugOnly<bool> isOnAllowList = false;
|
||||
// If we have a parent document, it has to be non-private since we verified
|
||||
// earlier that our own document is non-private and a private document can
|
||||
// never have a non-private document as its child.
|
||||
MOZ_ASSERT_IF(parent, !nsContentUtils::IsInPrivateBrowsing(parent));
|
||||
MOZ_ASSERT_IF(NS_SUCCEEDED(AntiTrackingCommon::IsOnContentBlockingAllowList(
|
||||
parent->GetDocumentURI(),
|
||||
false,
|
||||
AntiTrackingCommon::eStorageChecks,
|
||||
isOnAllowList)),
|
||||
!isOnAllowList);
|
||||
|
|
|
@ -54,6 +54,11 @@ public:
|
|||
bool mFakeDeviceChangeEventOn;
|
||||
int32_t mChannels;
|
||||
|
||||
bool operator ==(const MediaEnginePrefs& aRhs)
|
||||
{
|
||||
return memcmp(this, &aRhs, sizeof(MediaEnginePrefs)) == 0;
|
||||
};
|
||||
|
||||
// mWidth and/or mHeight may be zero (=adaptive default), so use functions.
|
||||
|
||||
int32_t GetWidth(bool aHD = false) const {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -35,15 +35,12 @@ public:
|
|||
bool aDelayAgnostic,
|
||||
bool aExtendedFilter);
|
||||
|
||||
bool RequiresSharing() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool RequiresSharing() const override { return false; }
|
||||
|
||||
nsString GetName() const override;
|
||||
nsCString GetUUID() const override;
|
||||
|
||||
nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
|
||||
nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
|
||||
const MediaEnginePrefs& aPrefs,
|
||||
const nsString& aDeviceId,
|
||||
const ipc::PrincipalInfo& aPrincipalInfo,
|
||||
|
@ -95,45 +92,32 @@ protected:
|
|||
|
||||
private:
|
||||
/**
|
||||
* Reevaluates the aggregated constraints of all allocations and restarts the
|
||||
* underlying device if necessary.
|
||||
* From a set of constraints and about:config preferences, output the correct
|
||||
* set of preferences that can be sent to AudioInputProcessing.
|
||||
*
|
||||
* If the given AllocationHandle was already registered, its constraints will
|
||||
* be updated before reevaluation. If not, they will be added before
|
||||
* reevaluation.
|
||||
* This can fail if the number of channels requested is zero, negative, or
|
||||
* more than the device supports.
|
||||
*/
|
||||
nsresult ReevaluateAllocation(const RefPtr<AllocationHandle>& aHandle,
|
||||
const NormalizedConstraints* aConstraintsUpdate,
|
||||
const MediaEnginePrefs& aPrefs,
|
||||
const nsString& aDeviceId,
|
||||
const char** aOutBadConstraint);
|
||||
nsresult EvaluateSettings(const NormalizedConstraints& aConstraintsUpdate,
|
||||
const MediaEnginePrefs& aInPrefs,
|
||||
MediaEnginePrefs* aOutPrefs,
|
||||
const char** aOutBadConstraint);
|
||||
/**
|
||||
* From settings output by EvaluateSettings, send those settings to the
|
||||
* AudioInputProcessing instance and the main thread (for use in GetSettings).
|
||||
*/
|
||||
void ApplySettings(const MediaEnginePrefs& aPrefs);
|
||||
|
||||
/**
|
||||
* Updates the underlying (single) device with the aggregated constraints
|
||||
* aNetConstraints. If the chosen settings for the device changes based on
|
||||
* these new constraints, and capture is active, the device will be restarted.
|
||||
* Sent the AudioProcessingModule parameter for a given processing algorithm.
|
||||
*/
|
||||
nsresult UpdateSingleSource(const RefPtr<const AllocationHandle>& aHandle,
|
||||
const NormalizedConstraints& aNetConstraints,
|
||||
const MediaEnginePrefs& aPrefs,
|
||||
const nsString& aDeviceId,
|
||||
const char** aOutBadConstraint);
|
||||
|
||||
// These methods send a message to the AudioInputProcessing instance.
|
||||
void UpdateAECSettingsIfNeeded(bool aEnable, webrtc::EcModes aMode);
|
||||
void UpdateAGCSettingsIfNeeded(bool aEnable, webrtc::AgcModes aMode);
|
||||
void UpdateNSSettingsIfNeeded(bool aEnable, webrtc::NsModes aMode);
|
||||
void UpdateAPMExtraOptions(bool aExtendedFilter, bool aDelayAgnostic);
|
||||
void ApplySettings(const MediaEnginePrefs& aPrefs,
|
||||
RefPtr<MediaStreamGraphImpl> aGraph);
|
||||
|
||||
bool HasEnabledTrack() const;
|
||||
|
||||
RefPtr<AllocationHandle> mHandle;
|
||||
|
||||
TrackID mTrackID = TRACK_NONE;
|
||||
PrincipalHandle mPrincipal = PRINCIPAL_HANDLE_NONE;
|
||||
bool mEnabled = false;
|
||||
|
||||
const RefPtr<AudioDeviceInfo> mDeviceInfo;
|
||||
const bool mDelayAgnostic;
|
||||
|
@ -146,11 +130,8 @@ private:
|
|||
// The current settings for the underlying device.
|
||||
// Constructed on the MediaManager thread, and then only ever accessed on the
|
||||
// main thread.
|
||||
const nsMainThreadPtrHandle<media::Refcountable<dom::MediaTrackSettings>> mSettings;
|
||||
// To only update microphone when needed, we keep track of the prefs
|
||||
// representing the currently applied settings for this source. This is the
|
||||
// net result of the prefs across all allocations.
|
||||
MediaEnginePrefs mNetPrefs;
|
||||
const nsMainThreadPtrHandle<media::Refcountable<dom::MediaTrackSettings>>
|
||||
mSettings;
|
||||
|
||||
// Current state of the resource for this source.
|
||||
MediaEngineSourceState mState;
|
||||
|
@ -174,8 +155,7 @@ public:
|
|||
TrackID aTrackID,
|
||||
const PrincipalHandle& aPrincipalHandle);
|
||||
|
||||
void Pull(const RefPtr<const AllocationHandle>& aHandle,
|
||||
const RefPtr<SourceMediaStream>& aStream,
|
||||
void Pull(const RefPtr<SourceMediaStream>& aStream,
|
||||
TrackID aTrackID,
|
||||
StreamTime aDesiredTime,
|
||||
const PrincipalHandle& aPrincipalHandle);
|
||||
|
@ -283,17 +263,14 @@ private:
|
|||
bool mEnded;
|
||||
};
|
||||
|
||||
|
||||
class MediaEngineWebRTCAudioCaptureSource : public MediaEngineSource
|
||||
{
|
||||
public:
|
||||
explicit MediaEngineWebRTCAudioCaptureSource(const char* aUuid)
|
||||
{
|
||||
}
|
||||
explicit MediaEngineWebRTCAudioCaptureSource(const char* aUuid) {}
|
||||
nsString GetName() const override;
|
||||
nsCString GetUUID() const override;
|
||||
nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
|
||||
const MediaEnginePrefs &aPrefs,
|
||||
nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
|
||||
const MediaEnginePrefs& aPrefs,
|
||||
const nsString& aDeviceId,
|
||||
const ipc::PrincipalInfo& aPrincipalInfo,
|
||||
AllocationHandle** aOutHandle,
|
||||
|
|
|
@ -312,73 +312,6 @@ NormalizedConstraints::NormalizedConstraints(
|
|||
}
|
||||
}
|
||||
|
||||
// Merge constructor. Create net constraints out of merging a set of others.
|
||||
// This is only used to resolve competing constraints from concurrent requests,
|
||||
// something the spec doesn't cover.
|
||||
|
||||
NormalizedConstraints::NormalizedConstraints(
|
||||
const nsTArray<const NormalizedConstraints*>& aOthers)
|
||||
: NormalizedConstraintSet(*aOthers[0])
|
||||
, mBadConstraint(nullptr)
|
||||
{
|
||||
for (auto& entry : aOthers[0]->mAdvanced) {
|
||||
mAdvanced.push_back(entry);
|
||||
}
|
||||
|
||||
// Create a list of member pointers.
|
||||
nsTArray<MemberPtrType> list;
|
||||
NormalizedConstraints dummy(dom::MediaTrackConstraints(), &list);
|
||||
|
||||
// Do intersection of all required constraints, and average of ideals,
|
||||
|
||||
for (uint32_t i = 1; i < aOthers.Length(); i++) {
|
||||
auto& other = *aOthers[i];
|
||||
|
||||
for (auto& memberPtr : list) {
|
||||
auto& member = this->*memberPtr;
|
||||
auto& otherMember = other.*memberPtr;
|
||||
|
||||
if (!member.Merge(otherMember)) {
|
||||
mBadConstraint = member.mName;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& entry : other.mAdvanced) {
|
||||
mAdvanced.push_back(entry);
|
||||
}
|
||||
}
|
||||
for (auto& memberPtr : list) {
|
||||
(this->*memberPtr).FinalizeMerge();
|
||||
}
|
||||
|
||||
// ...except for resolution and frame rate where we take the highest ideal.
|
||||
// This is a bit of a hack based on the perception that people would be more
|
||||
// surprised if they were to get lower resolution than they ideally requested.
|
||||
//
|
||||
// The spec gives browsers leeway here, saying they "SHOULD use the one with
|
||||
// the smallest fitness distance", and also does not directly address the
|
||||
// problem of competing constraints at all. There is no real web interop issue
|
||||
// here since this is more about interop with other tabs on the same browser.
|
||||
//
|
||||
// We should revisit this logic once we support downscaling of resolutions and
|
||||
// decimating of frame rates, per track.
|
||||
|
||||
for (auto& other : aOthers) {
|
||||
mWidth.TakeHighestIdeal(other->mWidth);
|
||||
mHeight.TakeHighestIdeal(other->mHeight);
|
||||
|
||||
// Consider implicit 30 fps default in comparison of competing constraints.
|
||||
// Avoids 160x90x10 and 640x480 becoming 1024x768x10 (fitness distance flaw)
|
||||
// This pretty much locks in 30 fps or higher, except for single-tab use.
|
||||
auto frameRate = other->mFrameRate;
|
||||
if (frameRate.mIdeal.isNothing()) {
|
||||
frameRate.mIdeal.emplace(30);
|
||||
}
|
||||
mFrameRate.TakeHighestIdeal(frameRate);
|
||||
}
|
||||
}
|
||||
|
||||
FlattenedConstraints::FlattenedConstraints(const NormalizedConstraints& aOther)
|
||||
: NormalizedConstraintSet(aOther)
|
||||
{
|
||||
|
|
|
@ -283,10 +283,6 @@ struct NormalizedConstraints : public NormalizedConstraintSet
|
|||
explicit NormalizedConstraints(const dom::MediaTrackConstraints& aOther,
|
||||
nsTArray<MemberPtrType>* aList = nullptr);
|
||||
|
||||
// Merge constructor
|
||||
explicit NormalizedConstraints(
|
||||
const nsTArray<const NormalizedConstraints*>& aOthers);
|
||||
|
||||
std::vector<NormalizedConstraintSet> mAdvanced;
|
||||
const char* mBadConstraint;
|
||||
};
|
||||
|
|
|
@ -105,32 +105,6 @@ OSFileConstantsService::Paths
|
|||
nsString tmpDir;
|
||||
nsString profileDir;
|
||||
nsString localProfileDir;
|
||||
/**
|
||||
* The user's home directory
|
||||
*/
|
||||
nsString homeDir;
|
||||
/**
|
||||
* The user's 'application data' directory.
|
||||
* Windows:
|
||||
* HOME = Documents and Settings\$USER\Application Data
|
||||
* UAppData = $HOME[\$vendor]\$name
|
||||
*
|
||||
* Unix:
|
||||
* HOME = ~
|
||||
* UAppData = $HOME/.[$vendor/]$name
|
||||
*
|
||||
* Mac:
|
||||
* HOME = ~
|
||||
* UAppData = $HOME/Library/Application Support/$name
|
||||
*/
|
||||
nsString userApplicationDataDir;
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
/**
|
||||
* The user's Library directory.
|
||||
*/
|
||||
nsString macUserLibDir;
|
||||
#endif // defined(XP_MACOSX)
|
||||
|
||||
Paths()
|
||||
{
|
||||
|
@ -138,12 +112,6 @@ OSFileConstantsService::Paths
|
|||
tmpDir.SetIsVoid(true);
|
||||
profileDir.SetIsVoid(true);
|
||||
localProfileDir.SetIsVoid(true);
|
||||
homeDir.SetIsVoid(true);
|
||||
userApplicationDataDir.SetIsVoid(true);
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
macUserLibDir.SetIsVoid(true);
|
||||
#endif // defined(XP_MACOSX)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -251,16 +219,7 @@ OSFileConstantsService::InitOSFileConstants()
|
|||
}
|
||||
}
|
||||
|
||||
// For other directories, ignore errors (they may be undefined on
|
||||
// some platforms or in non-Firefox embeddings of Gecko).
|
||||
|
||||
GetPathToSpecialDir(NS_OS_TEMP_DIR, paths->tmpDir);
|
||||
GetPathToSpecialDir(NS_OS_HOME_DIR, paths->homeDir);
|
||||
GetPathToSpecialDir(XRE_USER_APP_DATA_DIR, paths->userApplicationDataDir);
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
GetPathToSpecialDir(NS_MAC_USER_LIB_DIR, paths->macUserLibDir);
|
||||
#endif // defined(XP_MACOSX)
|
||||
|
||||
mPaths = std::move(paths);
|
||||
|
||||
|
@ -935,20 +894,6 @@ OSFileConstantsService::DefineOSFileConstants(JSContext* aCx,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!SetStringProperty(aCx, objPath, "homeDir", mPaths->homeDir)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetStringProperty(aCx, objPath, "userApplicationDataDir", mPaths->userApplicationDataDir)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
if (!SetStringProperty(aCx, objPath, "macUserLibDir", mPaths->macUserLibDir)) {
|
||||
return false;
|
||||
}
|
||||
#endif // defined(XP_MACOSX)
|
||||
|
||||
// sqlite3 is linked from different places depending on the platform
|
||||
nsAutoString libsqlite3;
|
||||
#if defined(ANDROID)
|
||||
|
|
|
@ -2607,7 +2607,6 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent,
|
|||
, mDebugger(nullptr)
|
||||
, mJSContext(nullptr)
|
||||
, mPRThread(nullptr)
|
||||
, mMainThreadEventTarget(GetMainThreadEventTarget())
|
||||
, mWorkerControlEventTarget(new WorkerEventTarget(this,
|
||||
WorkerEventTarget::Behavior::ControlOnly))
|
||||
, mWorkerHybridEventTarget(new WorkerEventTarget(this,
|
||||
|
@ -2716,7 +2715,6 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent,
|
|||
// that ThrottledEventQueue can only be created on the main thread at the
|
||||
// moment.
|
||||
if (aParent) {
|
||||
mMainThreadThrottledEventQueue = aParent->mMainThreadThrottledEventQueue;
|
||||
mMainThreadEventTarget = aParent->mMainThreadEventTarget;
|
||||
return;
|
||||
}
|
||||
|
@ -2730,17 +2728,8 @@ WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent,
|
|||
}
|
||||
|
||||
// Throttle events to the main thread using a ThrottledEventQueue specific to
|
||||
// this worker thread. This may return nullptr during shutdown.
|
||||
mMainThreadThrottledEventQueue = ThrottledEventQueue::Create(target);
|
||||
|
||||
// If we were able to creat the throttled event queue, then use it for
|
||||
// dispatching our main thread runnables. Otherwise use our underlying
|
||||
// base target.
|
||||
if (mMainThreadThrottledEventQueue) {
|
||||
mMainThreadEventTarget = mMainThreadThrottledEventQueue;
|
||||
} else {
|
||||
mMainThreadEventTarget = target.forget();
|
||||
}
|
||||
// this tree of worker threads.
|
||||
mMainThreadEventTarget = ThrottledEventQueue::Create(target);
|
||||
}
|
||||
|
||||
WorkerPrivate::~WorkerPrivate()
|
||||
|
@ -3316,9 +3305,8 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
|
|||
// If the worker thread is spamming the main thread faster than it can
|
||||
// process the work, then pause the worker thread until the MT catches
|
||||
// up.
|
||||
if (mMainThreadThrottledEventQueue &&
|
||||
mMainThreadThrottledEventQueue->Length() > 5000) {
|
||||
mMainThreadThrottledEventQueue->AwaitIdle();
|
||||
if (mMainThreadEventTarget->Length() > 5000) {
|
||||
mMainThreadEventTarget->AwaitIdle();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1367,8 +1367,7 @@ private:
|
|||
nsTArray<WorkerPrivate*> mChildWorkers;
|
||||
nsTObserverArray<WorkerHolder*> mHolders;
|
||||
nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
|
||||
RefPtr<ThrottledEventQueue> mMainThreadThrottledEventQueue;
|
||||
nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
|
||||
RefPtr<ThrottledEventQueue> mMainThreadEventTarget;
|
||||
RefPtr<WorkerEventTarget> mWorkerControlEventTarget;
|
||||
RefPtr<WorkerEventTarget> mWorkerHybridEventTarget;
|
||||
|
||||
|
|
|
@ -2426,7 +2426,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle
|
|||
|
||||
RefPtr<nsXBLBinding> binding;
|
||||
rv = xblService->LoadBindings(aDocElement, display->mBinding->GetURI(),
|
||||
display->mBinding->mExtraData->Principal(),
|
||||
display->mBinding->ExtraData()->Principal(),
|
||||
getter_AddRefs(binding), &resolveStyle);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED) {
|
||||
// Binding will load asynchronously.
|
||||
|
@ -5580,7 +5580,7 @@ nsCSSFrameConstructor::LoadXBLBindingIfNeeded(nsIContent& aContent,
|
|||
bool resolveStyle;
|
||||
nsresult rv = xblService->LoadBindings(aContent.AsElement(),
|
||||
binding->GetURI(),
|
||||
binding->mExtraData->Principal(),
|
||||
binding->ExtraData()->Principal(),
|
||||
getter_AddRefs(newPendingBinding->mBinding),
|
||||
&resolveStyle);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<style>
|
||||
:root { background: green }
|
||||
</style>
|
|
@ -0,0 +1,6 @@
|
|||
<!doctype html>
|
||||
<style>
|
||||
@supports selector(div) {
|
||||
:root { background: green }
|
||||
}
|
||||
</style>
|
|
@ -2087,3 +2087,5 @@ fuzzy(0-1,0-625) == 1466638-1.html 1466638-1-ref.html
|
|||
test-pref(layout.css.contain.enabled,true) == 1483946.html 1483946-ref.html
|
||||
test-pref(layout.css.visited_links_enabled,false) == 1488155.html 1488155-ref.html
|
||||
== 1492660-1.html 1492660-1-ref.html
|
||||
pref(layout.css.supports-selector.enabled,true) == 1499386.html 1499386-ref.html
|
||||
pref(layout.css.supports-selector.enabled,false) != 1499386.html 1499386-ref.html
|
||||
|
|
|
@ -1102,10 +1102,11 @@ FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsACString& aFamilyName
|
|||
const URLValue* url = component.url._0;
|
||||
nsIURI* uri = url->GetURI();
|
||||
face->mURI = uri ? new gfxFontSrcURI(uri) : nullptr;
|
||||
face->mReferrer = url->mExtraData->GetReferrer();
|
||||
face->mReferrerPolicy = url->mExtraData->GetReferrerPolicy();
|
||||
URLExtraData* extraData = url->ExtraData();
|
||||
face->mReferrer = extraData->GetReferrer();
|
||||
face->mReferrerPolicy = extraData->GetReferrerPolicy();
|
||||
face->mOriginPrincipal =
|
||||
new gfxFontSrcPrincipal(url->mExtraData->Principal());
|
||||
new gfxFontSrcPrincipal(extraData->Principal());
|
||||
|
||||
// agent and user stylesheets are treated slightly differently,
|
||||
// the same-site origin check and access control headers are
|
||||
|
|
|
@ -1381,14 +1381,6 @@ Gecko_CounterStyle_GetAnonymous(const CounterStylePtr* aPtr)
|
|||
return aPtr->AsAnonymous();
|
||||
}
|
||||
|
||||
already_AddRefed<css::URLValue>
|
||||
ServoBundledURI::IntoCssUrl(CORSMode aCorsMode)
|
||||
{
|
||||
RefPtr<css::URLValue> urlValue =
|
||||
new css::URLValue(mURLString, do_AddRef(mExtraData), aCorsMode);
|
||||
return urlValue.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Gecko_SetNullImageValue(nsStyleImage* aImage)
|
||||
{
|
||||
|
@ -2005,9 +1997,9 @@ Gecko_nsStyleSVG_CopyContextProperties(nsStyleSVG* aDst, const nsStyleSVG* aSrc)
|
|||
|
||||
|
||||
css::URLValue*
|
||||
Gecko_URLValue_Create(ServoBundledURI aURI, mozilla::CORSMode aCORSMode)
|
||||
Gecko_URLValue_Create(RawServoCssUrlDataStrong aCssUrl, CORSMode aCORSMode)
|
||||
{
|
||||
RefPtr<css::URLValue> url = aURI.IntoCssUrl(aCORSMode);
|
||||
RefPtr<css::URLValue> url = new css::URLValue(aCssUrl.Consume(), aCORSMode);
|
||||
return url.forget().take();
|
||||
}
|
||||
|
||||
|
@ -2575,7 +2567,7 @@ LoadImportSheet(css::Loader* aLoader,
|
|||
NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:invalid"));
|
||||
}
|
||||
emptySheet->SetURIs(uri, uri, uri);
|
||||
emptySheet->SetPrincipal(aURL->mExtraData->Principal());
|
||||
emptySheet->SetPrincipal(aURL->ExtraData()->Principal());
|
||||
emptySheet->SetComplete();
|
||||
aParent->PrependStyleSheet(emptySheet);
|
||||
return emptySheet.forget();
|
||||
|
@ -2591,28 +2583,29 @@ Gecko_LoadStyleSheet(css::Loader* aLoader,
|
|||
StyleSheet* aParent,
|
||||
SheetLoadData* aParentLoadData,
|
||||
css::LoaderReusableStyleSheets* aReusableSheets,
|
||||
ServoBundledURI aServoURL,
|
||||
RawServoCssUrlDataStrong aCssUrl,
|
||||
RawServoMediaListStrong aMediaList)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// The CORS mode in the URLValue is irrelevant here.
|
||||
// (CORS_NONE is used for all imported sheets in Load::LoadChildSheet.)
|
||||
RefPtr<css::URLValue> url = aServoURL.IntoCssUrl(CORS_NONE);
|
||||
RefPtr<css::URLValue> url = new css::URLValue(aCssUrl.Consume(), CORS_NONE);
|
||||
return LoadImportSheet(aLoader, aParent, aParentLoadData, aReusableSheets,
|
||||
url, aMediaList.Consume()).take();
|
||||
}
|
||||
|
||||
void
|
||||
Gecko_LoadStyleSheetAsync(css::SheetLoadDataHolder* aParentData,
|
||||
ServoBundledURI aServoURL,
|
||||
RawServoCssUrlDataStrong aCssUrl,
|
||||
RawServoMediaListStrong aMediaList,
|
||||
RawServoImportRuleStrong aImportRule)
|
||||
{
|
||||
RefPtr<SheetLoadDataHolder> loadData = aParentData;
|
||||
// The CORS mode in the URLValue is irrelevant here.
|
||||
// (CORS_NONE is used for all imported sheets in Load::LoadChildSheet.)
|
||||
RefPtr<css::URLValue> urlVal = aServoURL.IntoCssUrl(CORS_NONE);
|
||||
RefPtr<css::URLValue> urlVal =
|
||||
new css::URLValue(aCssUrl.Consume(), CORS_NONE);
|
||||
RefPtr<RawServoMediaList> mediaList = aMediaList.Consume();
|
||||
RefPtr<RawServoImportRule> importRule = aImportRule.Consume();
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(__func__,
|
||||
|
|
|
@ -61,16 +61,6 @@ const bool GECKO_IS_NIGHTLY = false;
|
|||
void Gecko_Release##name_##ArbitraryThread(class_* aPtr) \
|
||||
{ NS_RELEASE(aPtr); }
|
||||
|
||||
class ServoBundledURI
|
||||
{
|
||||
public:
|
||||
// NOTE(emilio): Not calling IntoCssUrl will cause to leak the
|
||||
// string, so don't do that :)
|
||||
already_AddRefed<mozilla::css::URLValue> IntoCssUrl(mozilla::CORSMode);
|
||||
mozilla::ServoRawOffsetArc<RustString> mURLString;
|
||||
mozilla::URLExtraData* mExtraData;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Debugging stuff.
|
||||
|
@ -139,12 +129,12 @@ mozilla::StyleSheet* Gecko_LoadStyleSheet(
|
|||
mozilla::StyleSheet* parent,
|
||||
mozilla::css::SheetLoadData* parent_load_data,
|
||||
mozilla::css::LoaderReusableStyleSheets* reusable_sheets,
|
||||
ServoBundledURI url,
|
||||
RawServoCssUrlDataStrong url,
|
||||
RawServoMediaListStrong media_list);
|
||||
|
||||
void Gecko_LoadStyleSheetAsync(
|
||||
mozilla::css::SheetLoadDataHolder* parent_data,
|
||||
ServoBundledURI url,
|
||||
RawServoCssUrlDataStrong url,
|
||||
RawServoMediaListStrong media_list,
|
||||
RawServoImportRuleStrong import_rule);
|
||||
|
||||
|
@ -651,7 +641,7 @@ void Gecko_nsStyleSVG_CopyContextProperties(
|
|||
const nsStyleSVG* src);
|
||||
|
||||
mozilla::css::URLValue* Gecko_URLValue_Create(
|
||||
ServoBundledURI uri,
|
||||
RawServoCssUrlDataStrong url,
|
||||
mozilla::CORSMode aCORSMode);
|
||||
|
||||
size_t Gecko_URLValue_SizeOfIncludingThis(mozilla::css::URLValue* url);
|
||||
|
|
|
@ -483,8 +483,7 @@ ImageLoader::LoadImage(URLValue* aImage, nsIDocument* aLoadingDoc)
|
|||
int32_t loadFlags = nsIRequest::LOAD_NORMAL |
|
||||
nsContentUtils::CORSModeToLoadImageFlags(aImage->CorsMode());
|
||||
|
||||
URLExtraData* data = aImage->mExtraData;
|
||||
|
||||
URLExtraData* data = aImage->ExtraData();
|
||||
|
||||
RefPtr<imgRequestProxy> request;
|
||||
nsresult rv = nsContentUtils::LoadImage(uri, aLoadingDoc, aLoadingDoc,
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче