Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2016-09-28 16:29:56 +02:00
commit 3624cf2823
512 changed files with 7809 additions and 6192 deletions

View File

@ -1287,6 +1287,10 @@ pref("identity.fxaccounts.remote.signin.uri", "https://accounts.firefox.com/sign
// The remote content URL where FxAccountsWebChannel messages originate.
pref("identity.fxaccounts.remote.webchannel.uri", "https://accounts.firefox.com/");
// The value of the context query parameter passed in some fxa requests when config
// discovery is enabled.
pref("identity.fxaccounts.contextParam", "fx_desktop_v3");
// The URL we take the user to when they opt to "manage" their Firefox Account.
// Note that this will always need to be in the same TLD as the
// "identity.fxaccounts.remote.signup.uri" pref.
@ -1452,7 +1456,7 @@ pref("dom.ipc.cpows.forbid-unsafe-from-browser", true);
pref("dom.ipc.cpows.forbid-cpows-in-compat-addons", true);
// ...except for these add-ons:
pref("dom.ipc.cpows.allow-cpows-in-compat-addons", "{b9db16a4-6edc-47ec-a1f4-b86292ed211d},privateTab@infocatcher,mousegesturessuite@lemon_juice.addons.mozilla.org,firegestures@xuldev.org,treestyletab@piro.sakura.ne.jp,{DDC359D1-844A-42a7-9AA1-88A850A938A8},ich@maltegoetz.de,{AE93811A-5C9A-4d34-8462-F7B864FC4696}");
pref("dom.ipc.cpows.allow-cpows-in-compat-addons", "{b9db16a4-6edc-47ec-a1f4-b86292ed211d},firegestures@xuldev.org,{DDC359D1-844A-42a7-9AA1-88A850A938A8},privateTab@infocatcher,mousegesturessuite@lemon_juice.addons.mozilla.org,treestyletab@piro.sakura.ne.jp,cliqz@cliqz.com,{AE93811A-5C9A-4d34-8462-F7B864FC4696},contextsearch2@lwz.addons.mozilla.org,{EF522540-89F5-46b9-B6FE-1829E2B572C6},{677a8f98-fd64-40b0-a883-b8c95d0cbf17},images@wink.su,fx-devtools,toolkit/require,url_advisor@kaspersky.com,{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d},{dc572301-7619-498c-a57d-39143191b318},dta@downthemall.net,{86095750-AD15-46d8-BF32-C0789F7E6A32},screenwise-prod@google.com,{91aa5abe-9de4-4347-b7b5-322c38dd9271},secureLogin@blueimp.net,ich@maltegoetz.de,come.back.block.image.from@cat-in-136.blogspot.com,{7b1bf0b6-a1b9-42b0-b75d-252036438bdc},s3crypto@data,{1e0fd655-5aea-4b4c-a583-f76ef1e3af9c},akahuku.fx.sp@toshiakisp.github.io,{aff87fa2-a58e-4edd-b852-0a20203c1e17},{1018e4d6-728f-4b20-ad56-37578a4de76b},rehostimage@engy.us,lazarus@interclue.com,{b2e69492-2358-071a-7056-24ad0c3defb1},flashstopper@byo.co.il,{e4a8a97b-f2ed-450b-b12d-ee082ba24781},jid1-f3mYMbCpz2AZYl@jetpack,{8c550e28-88c9-4764-bb52-aa489cf2efcd},{37fa1426-b82d-11db-8314-0800200c9a66},{ac2cfa60-bc96-11e0-962b-0800200c9a66},igetter@presenta.net,killspinners@byo.co.il,abhere2@moztw.org,{fc6339b8-9581-4fc7-b824-dffcb091fcb7},wampi@wink.su,backtrack@byalexv.co.uk,Gladiator_X@mail.ru,{73a6fe31-595d-460b-a920-fcc0f8843232},{46551EC9-40F0-4e47-8E18-8E5CF550CFB8},acewebextension_unlisted@acestream.org,@screen_maker,yasearch@yandex.ru,sp@avast.com,s3google@translator,igetterextension@presenta.net,{C1A2A613-35F1-4FCF-B27F-2840527B6556},screenwise-testing@google.com,helper-sig@savefrom.net,browser-loader,ImageSaver@Merci.chao,proxtube@abz.agency,wrc@avast.com,{9AA46F4F-4DC7-4c06-97AF-5035170634FE},jid1-CikLKKPVkw6ipw@jetpack,artur.dubovoy@gmail.com,nlgfeb@nlgfeb.ext,{A065A84F-95B6-433A-A0C8-4C040B77CE8A},fdm_ffext@freedownloadmanager.org");
// Enable e10s hang monitoring (slow script checking and plugin hang
// detection).

View File

@ -9,7 +9,7 @@ html, body {
display: none;
}
#networkError, #manage, #intro, #stage {
#networkError, #manage, #intro, #stage, #configError {
display: none;
}

View File

@ -164,14 +164,14 @@ var wrapper = {
// so avoid doing that more than once
if (failure && aStatus != Components.results.NS_BINDING_ABORTED) {
aRequest.cancel(Components.results.NS_BINDING_ABORTED);
setErrorPage();
setErrorPage("networkError");
}
},
onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags) {
if (aRequest && aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) {
aRequest.cancel(Components.results.NS_BINDING_ABORTED);
setErrorPage();
setErrorPage("networkError");
}
},
@ -294,18 +294,17 @@ var wrapper = {
},
injectData: function (type, content) {
let authUrl;
try {
authUrl = fxAccounts.getAccountsSignUpURI();
} catch (e) {
error("Couldn't inject data: " + e.message);
return;
}
let data = {
type: type,
content: content
};
this.iframe.contentWindow.postMessage(data, authUrl);
return fxAccounts.promiseAccountsSignUpURI().then(authUrl => {
let data = {
type: type,
content: content
};
this.iframe.contentWindow.postMessage(data, authUrl);
})
.catch(e => {
console.log("Failed to inject data", e);
setErrorPage("configError");
});
},
};
@ -344,7 +343,7 @@ function init() {
// tests in particular might cause the window to start closing before
// getSignedInUser has returned.
if (window.closed) {
return;
return Promise.resolve();
}
updateDisplayedEmail(user);
@ -361,8 +360,10 @@ function init() {
// asking to sign-in when already signed in just shows manage.
show("stage", "manage");
} else {
show("remote");
wrapper.init(fxAccounts.getAccountsSignInURI(), urlParams);
return fxAccounts.promiseAccountsSignInURI().then(url => {
show("remote");
wrapper.init(url, urlParams);
});
}
break;
case "signup":
@ -370,8 +371,10 @@ function init() {
// asking to sign-up when already signed in just shows manage.
show("stage", "manage");
} else {
show("remote");
wrapper.init(fxAccounts.getAccountsSignUpURI(), urlParams);
return fxAccounts.promiseAccountsSignUpURI().then(url => {
show("remote");
wrapper.init(url, urlParams);
});
}
break;
case "reauth":
@ -379,11 +382,10 @@ function init() {
// "must reauthenticate" state - but we don't.
// As the email address will be included in the URL returned from
// promiseAccountsForceSigninURI, just always show it.
fxAccounts.promiseAccountsForceSigninURI().then(url => {
return fxAccounts.promiseAccountsForceSigninURI().then(url => {
show("remote");
wrapper.init(url, urlParams);
});
break;
default:
// No action specified.
if (user) {
@ -391,23 +393,27 @@ function init() {
} else {
// Attempt a migration if enabled or show the introductory page
// otherwise.
migrateToDevEdition(urlParams).then(migrated => {
return migrateToDevEdition(urlParams).then(migrated => {
if (!migrated) {
show("stage", "intro");
// load the remote frame in the background
wrapper.init(fxAccounts.getAccountsSignUpURI(), urlParams);
return fxAccounts.promiseAccountsSignUpURI().then(uri =>
wrapper.init(uri, urlParams));
}
return Promise.resolve();
});
}
break;
}
return Promise.resolve();
}).catch(err => {
error("Failed to get the signed in user: " + err);
console.log("Configuration or sign in error", err);
setErrorPage("configError");
});
}
function setErrorPage() {
show("stage", "networkError");
function setErrorPage(errorType) {
show("stage", errorType);
}
// Causes the "top-level" element with |id| to be shown - all other top-level
@ -470,7 +476,12 @@ function migrateToDevEdition(urlParams) {
log("Failed to migrate FX Account: " + error);
show("stage", "intro");
// load the remote frame in the background
wrapper.init(fxAccounts.getAccountsSignUpURI(), urlParams);
fxAccounts.promiseAccountsSignUpURI().then(uri => {
wrapper.init(uri, urlParams)
}).catch(e => {
console.log("Failed to load signup page", e);
setErrorPage("configError");
});
}).then(() => {
// Reset the pref after migration.
Services.prefs.setBoolPref("identity.fxaccounts.migrateToDevEdition", false);

View File

@ -87,6 +87,19 @@
</section>
</div>
<div id="configError">
<header>
<h1>&aboutAccounts.badConfig.title;</h1>
</header>
<section>
<div class="graphic graphic-sync-intro"> </div>
<div class="description">&aboutAccounts.badConfig.description;</div>
</section>
</div>
</div>
<iframe mozframetype="content" id="remote" />

View File

@ -201,10 +201,6 @@ const TELEMETRY_DDSTAT_CLICKED_FIRST = 3;
const TELEMETRY_DDSTAT_SOLVED = 4;
let gDecoderDoctorHandler = {
shouldShowLearnMoreButton() {
return AppConstants.platform == "win";
},
getLabelForNotificationBox(type) {
if (type == "adobe-cdm-not-found" &&
AppConstants.platform == "win") {
@ -235,6 +231,19 @@ let gDecoderDoctorHandler = {
return gNavigatorBundle.getString("decoder.noCodecsLinux.message");
}
}
if (type == "cannot-initialize-pulseaudio") {
return gNavigatorBundle.getString("decoder.noPulseAudio.message");
}
return "";
},
getSumoForLearnHowButton(type) {
if (AppConstants.platform == "win") {
return "fix-video-audio-problems-firefox-windows";
}
if (type == "cannot-initialize-pulseaudio") {
return "fix-common-audio-and-video-issues";
}
return "";
},
@ -306,7 +315,8 @@ let gDecoderDoctorHandler = {
histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_SHOWN);
let buttons = [];
if (gDecoderDoctorHandler.shouldShowLearnMoreButton()) {
let sumo = gDecoderDoctorHandler.getSumoForLearnHowButton(type);
if (sumo) {
buttons.push({
label: gNavigatorBundle.getString("decoder.noCodecs.button"),
accessKey: gNavigatorBundle.getString("decoder.noCodecs.accesskey"),
@ -320,7 +330,7 @@ let gDecoderDoctorHandler = {
histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_CLICKED);
let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
openUILinkIn(baseURL + "fix-video-audio-problems-firefox-windows", "tab");
openUILinkIn(baseURL + sumo, "tab");
}
});
}

View File

@ -1128,6 +1128,7 @@ var gBrowserInit = {
// [4]: allowThirdPartyFixup (bool)
// [5]: referrerPolicy (int)
// [6]: userContextId (int)
// [7]: originPrincipal (nsIPrincipal)
else if (window.arguments.length >= 3) {
let referrerURI = window.arguments[2];
if (typeof(referrerURI) == "string") {
@ -1142,7 +1143,10 @@ var gBrowserInit = {
let userContextId = (window.arguments[6] != undefined ?
window.arguments[6] : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID);
loadURI(uriToLoad, referrerURI, window.arguments[3] || null,
window.arguments[4] || false, referrerPolicy, userContextId);
window.arguments[4] || false, referrerPolicy, userContextId,
// pass the origin principal (if any) and force its use to create
// an initial about:blank viewer if present:
window.arguments[7], !!window.arguments[7]);
window.focus();
}
// Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
@ -2033,14 +2037,17 @@ function BrowserTryToCloseWindow()
}
function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy,
userContextId) {
userContextId, originPrincipal, forceAboutBlankViewerInCurrent) {
try {
openLinkIn(uri, "current",
{ referrerURI: referrer,
referrerPolicy: referrerPolicy,
postData: postData,
allowThirdPartyFixup: allowThirdPartyFixup,
userContextId: userContextId });
userContextId: userContextId,
originPrincipal,
forceAboutBlankViewerInCurrent,
});
} catch (e) {}
}
@ -5584,11 +5591,14 @@ function handleLinkClick(event, href, linkNode) {
}
urlSecurityCheck(href, doc.nodePrincipal);
let params = { charset: doc.characterSet,
allowMixedContent: persistAllowMixedContentInChildTab,
referrerURI: referrerURI,
referrerPolicy: referrerPolicy,
noReferrer: BrowserUtils.linkHasNoReferrer(linkNode) };
let params = {
charset: doc.characterSet,
allowMixedContent: persistAllowMixedContentInChildTab,
referrerURI: referrerURI,
referrerPolicy: referrerPolicy,
noReferrer: BrowserUtils.linkHasNoReferrer(linkNode),
originPrincipal: doc.nodePrincipal,
};
// The new tab/window must use the same userContextId
if (doc.nodePrincipal.originAttributes.userContextId) {

View File

@ -507,6 +507,7 @@ var ClickEventHandler = {
json.allowMixedContent = true;
} catch (e) {}
}
json.originPrincipal = ownerDoc.nodePrincipal;
sendAsyncMessage("Content:Click", json);
return;

View File

@ -965,6 +965,7 @@ nsContextMenu.prototype = {
_openLinkInParameters : function (extra) {
let params = { charset: gContextMenuContentData.charSet,
originPrincipal: this.principal,
referrerURI: gContextMenuContentData.documentURIObject,
referrerPolicy: gContextMenuContentData.referrerPolicy,
noReferrer: this.linkHasNoReferrer };

View File

@ -1500,6 +1500,7 @@
var aNoReferrer;
var aUserContextId;
var aRelatedBrowser;
var aOriginPrincipal;
if (arguments.length == 2 &&
typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) {
@ -1518,6 +1519,7 @@
aNoReferrer = params.noReferrer;
aUserContextId = params.userContextId;
aRelatedBrowser = params.relatedBrowser;
aOriginPrincipal = params.originPrincipal;
}
var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
@ -1537,6 +1539,7 @@
forceNotRemote: aForceNotRemote,
noReferrer: aNoReferrer,
userContextId: aUserContextId,
originPrincipal: aOriginPrincipal,
relatedBrowser: aRelatedBrowser });
if (!bgLoad)
this.selectedTab = tab;
@ -2043,6 +2046,7 @@
var aUserContextId;
var aEventDetail;
var aRelatedBrowser;
var aOriginPrincipal;
if (arguments.length == 2 &&
typeof arguments[1] == "object" &&
!(arguments[1] instanceof Ci.nsIURI)) {
@ -2062,6 +2066,7 @@
aUserContextId = params.userContextId;
aEventDetail = params.eventDetail;
aRelatedBrowser = params.relatedBrowser;
aOriginPrincipal = params.originPrincipal;
}
// if we're adding tabs, we're past interrupt mode, ditch the owner
@ -2141,6 +2146,10 @@
var evt = new CustomEvent("TabOpen", { bubbles: true, detail });
t.dispatchEvent(evt);
if (!usingPreloadedContent && aOriginPrincipal) {
b.createAboutBlankContentViewer(aOriginPrincipal);
}
// If we didn't swap docShells with a preloaded browser
// then let's just continue loading the page normally.
if (!usingPreloadedContent && !uriIsAboutBlank) {
@ -3669,7 +3678,11 @@
assert: function(cond) {
if (!cond) {
dump("Assertion failure\n" + Error().stack);
throw new Error("Assertion failure");
// Don't break a user's browser if an assertion fails.
if (this.tabbrowser.AppConstants.DEBUG) {
throw new Error("Assertion failure");
}
}
},

View File

@ -118,6 +118,7 @@ support-files =
file_bug1045809_2.html
file_csp_block_all_mixedcontent.html
file_csp_block_all_mixedcontent.js
!/image/test/mochitest/blue.png
!/toolkit/components/passwordmgr/test/browser/form_basic.html
!/toolkit/components/passwordmgr/test/browser/insecure_test.html
!/toolkit/components/passwordmgr/test/browser/insecure_test_subframe.html
@ -342,6 +343,7 @@ subsuite = clipboard
[browser_mixed_content_cert_override.js]
[browser_mixedcontent_securityflags.js]
tags = mcb
[browser_modifiedclick_inherit_principal.js]
[browser_offlineQuotaNotification.js]
skip-if = buildapp == 'mulet'
[browser_feed_discovery.js]

View File

@ -318,7 +318,7 @@ var gTests = [
let response = yield readyPromise;
// We are expecting the iframe to be on the "signup" URL
let expected = fxAccounts.getAccountsSignUpURI();
let expected = yield fxAccounts.promiseAccountsSignUpURI();
is(response.data.url, expected);
// and expect no signed in user.

View File

@ -37,7 +37,8 @@ function* test_decoder_doctor_notification(type, notificationMessage, options) {
"notification button should have accesskey");
let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
let url = baseURL + "fix-video-audio-problems-firefox-windows";
let url = baseURL + ((options && options.sumo) ||
"fix-video-audio-problems-firefox-windows");
let awaitNewTab = BrowserTestUtils.waitForNewTab(gBrowser, url);
button.click();
let sumoTab = yield awaitNewTab;
@ -95,3 +96,15 @@ add_task(function* test_platform_decoder_not_found() {
message,
{noLearnMoreButton: isLinux});
});
add_task(function* test_cannot_initialize_pulseaudio() {
// This is only sent on Linux.
if (AppConstants.platform != "linux") {
return;
}
let message = gNavigatorBundle.getString("decoder.noPulseAudio.message");
yield test_decoder_doctor_notification("cannot-initialize-pulseaudio",
message,
{sumo: "fix-common-audio-and-video-issues"});
});

View File

@ -0,0 +1,30 @@
"use strict";
const kURL =
"http://example.com/browser/browser/base/content/test/general/dummy_page.html";
"data:text/html,<a href=''>Middle-click me</a>";
/*
* Check that when manually opening content JS links in new tabs/windows,
* we use the correct principal, and we don't clear the URL bar.
*/
add_task(function* () {
yield BrowserTestUtils.withNewTab(kURL, function* (browser) {
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
yield ContentTask.spawn(browser, null, function* () {
let a = content.document.createElement("a");
a.href = "javascript:document.write('spoof'); void(0);";
a.textContent = "Some link";
content.document.body.appendChild(a);
});
info("Added element");
yield BrowserTestUtils.synthesizeMouseAtCenter("a", {button: 1}, browser);
let newTab = yield newTabPromise;
is(newTab.linkedBrowser.contentPrincipal.origin, "http://example.com",
"Principal should be for example.com");
yield BrowserTestUtils.switchTab(gBrowser, newTab);
info(gURLBar.value);
isnot(gURLBar.value, "", "URL bar should not be empty.");
yield BrowserTestUtils.removeTab(newTab);
});
});

View File

@ -222,6 +222,9 @@ function openLinkIn(url, where, params) {
var aAllowPopups = !!params.allowPopups;
var aUserContextId = params.userContextId;
var aIndicateErrorPageLoad = params.indicateErrorPageLoad;
var aPrincipal = params.originPrincipal;
var aForceAboutBlankViewerInCurrent =
params.forceAboutBlankViewerInCurrent;
if (where == "save") {
// TODO(1073187): propagate referrerPolicy.
@ -290,6 +293,7 @@ function openLinkIn(url, where, params) {
sa.AppendElement(allowThirdPartyFixupSupports);
sa.AppendElement(referrerPolicySupports);
sa.AppendElement(userContextIdSupports);
sa.AppendElement(aPrincipal);
let features = "chrome,dialog=no,all";
if (aIsPrivate) {
@ -357,6 +361,10 @@ function openLinkIn(url, where, params) {
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ERROR_LOAD_CHANGES_RV;
}
if (aForceAboutBlankViewerInCurrent) {
w.gBrowser.selectedBrowser.createAboutBlankContentViewer(aPrincipal);
}
w.gBrowser.loadURIWithFlags(url, {
flags: flags,
referrerURI: aNoReferrer ? null : aReferrerURI,
@ -380,7 +388,8 @@ function openLinkIn(url, where, params) {
skipAnimation: aSkipTabAnimation,
allowMixedContent: aAllowMixedContent,
noReferrer: aNoReferrer,
userContextId: aUserContextId
userContextId: aUserContextId,
originPrincipal: aPrincipal,
});
break;
}

View File

@ -12,3 +12,5 @@
<!ENTITY aboutAccounts.noConnection.title "No connection">
<!ENTITY aboutAccounts.noConnection.description "You must be connected to the Internet to sign in.">
<!ENTITY aboutAccounts.noConnection.retry "Try again">
<!ENTITY aboutAccounts.badConfig.title "Bad configuration">
<!ENTITY aboutAccounts.badConfig.description "Unable to determine your Firefox Account server configuration. Please try again later.">

View File

@ -734,6 +734,7 @@ decoder.noCodecsXP.message = To play video, you may need to enable Adobes Pri
decoder.noCodecsLinux.message = To play video, you may need to install the required video codecs.
decoder.noHWAcceleration.message = To improve video quality, you may need to install Microsofts Media Feature Pack.
decoder.noHWAccelerationVista.message = To improve video quality, you may need to install Microsofts Platform Update Supplement for Windows Vista.
decoder.noPulseAudio.message = To play audio, you may need to install the required PulseAudio software.
permissions.remove.tooltip = Clear this permission and ask again

View File

@ -77,12 +77,15 @@ var ContentClick = {
// Todo(903022): code for where == save
let params = { charset: browser.characterSet,
referrerURI: browser.documentURI,
referrerPolicy: json.referrerPolicy,
noReferrer: json.noReferrer,
allowMixedContent: json.allowMixedContent,
isContentWindowPrivate: json.isContentWindowPrivate};
let params = {
charset: browser.characterSet,
referrerURI: browser.documentURI,
referrerPolicy: json.referrerPolicy,
noReferrer: json.noReferrer,
allowMixedContent: json.allowMixedContent,
isContentWindowPrivate: json.isContentWindowPrivate,
originPrincipal: json.originPrincipal,
};
// The new tab/window must use the same userContextId.
if (json.originAttributes.userContextId) {

View File

@ -191,22 +191,11 @@ toolbar[brighttext] #downloads-indicator-counter {
box-shadow: none !important;
}
:root[devtoolstheme="dark"] #identity-icon:-moz-lwtheme {
--identity-icon-normal: url(chrome://browser/skin/identity-icon.svg#normal-white);
--identity-icon-hover: url(chrome://browser/skin/identity-icon.svg#hover-white);
--identity-icon-notice: url(chrome://browser/skin/identity-icon.svg#notice-white);
--identity-icon-notice-hover: url(chrome://browser/skin/identity-icon.svg#notice-hover-white);
}
:root[devtoolstheme="dark"] #tracking-protection-icon:-moz-lwtheme {
--tracking-protection-icon-enabled: url(chrome://browser/skin/tracking-protection-16.svg#enabled-white);
--tracking-protection-icon-disabled: url(chrome://browser/skin/tracking-protection-16.svg#disabled-white);
}
:root[devtoolstheme="dark"] #connection-icon:-moz-lwtheme {
--connection-icon-mixed-passive-loaded: url(chrome://browser/skin/connection-mixed-passive-loaded.svg#icon-white);
--connection-icon-mixed-active-loaded: url(chrome://browser/skin/connection-mixed-active-loaded.svg#icon-white);
}
%filter substitution
%define selectorPrefix :root[devtoolstheme="dark"]
%define selectorSuffix :-moz-lwtheme
%define iconVariant -white
%include identity-block/icons.inc.css
#urlbar {
border-inline-start: none !important;

View File

@ -0,0 +1,62 @@
%if 0
/* 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/. */
%endif
@selectorPrefix@#identity-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/identity-icon.svg#normal@iconVariant@);
}
@selectorPrefix@#identity-box:hover > #identity-icon:not(.no-hover)@selectorSuffix@,
@selectorPrefix@#identity-box[open=true] > #identity-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/identity-icon.svg#hover@iconVariant@);
}
@selectorPrefix@#identity-box.grantedPermissions > #identity-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/identity-icon.svg#notice@iconVariant@);
}
@selectorPrefix@#identity-box.grantedPermissions:hover > #identity-icon:not(.no-hover)@selectorSuffix@,
@selectorPrefix@#identity-box.grantedPermissions[open=true] > #identity-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/identity-icon.svg#notice-hover@iconVariant@);
}
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.chromeUI > #identity-icon@selectorSuffix@ {
list-style-image: url(chrome://branding/content/identity-icons-brand.svg);
}
@selectorPrefix@#tracking-protection-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/tracking-protection-16.svg#enabled@iconVariant@);
}
@selectorPrefix@#tracking-protection-icon[state="loaded-tracking-content"]@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/tracking-protection-16.svg#disabled@iconVariant@);
}
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.verifiedDomain > #connection-icon@selectorSuffix@,
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity > #connection-icon@selectorSuffix@,
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.mixedActiveBlocked > #connection-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/connection-secure.svg);
visibility: visible;
}
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.certUserOverridden > #connection-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/connection-mixed-passive-loaded.svg#icon@iconVariant@);
visibility: visible;
}
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.insecureLoginForms > #connection-icon@selectorSuffix@,
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.mixedActiveContent > #connection-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/connection-mixed-active-loaded.svg#icon@iconVariant@);
visibility: visible;
}
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.weakCipher > #connection-icon@selectorSuffix@,
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.mixedDisplayContent > #connection-icon@selectorSuffix@,
@selectorPrefix@#urlbar[pageproxystate="valid"] > #identity-box.mixedDisplayContentLoadedActiveBlocked > #connection-icon@selectorSuffix@ {
list-style-image: url(chrome://browser/skin/connection-mixed-passive-loaded.svg#icon@iconVariant@);
visibility: visible;
}

View File

@ -4,6 +4,18 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%endif
%filter substitution
%define selectorPrefix
%define selectorSuffix
%define iconVariant
%include icons.inc.css
%define selectorPrefix
%define selectorSuffix :-moz-lwtheme
%define iconVariant -black
%include icons.inc.css
#identity-box {
font-size: .9em;
padding: 3px 5px;
@ -52,39 +64,8 @@
/* MAIN IDENTITY ICON */
#identity-icon {
--identity-icon-normal: url(chrome://browser/skin/identity-icon.svg#normal);
--identity-icon-hover: url(chrome://browser/skin/identity-icon.svg#hover);
--identity-icon-notice: url(chrome://browser/skin/identity-icon.svg#notice);
--identity-icon-notice-hover: url(chrome://browser/skin/identity-icon.svg#notice-hover);
width: 16px;
height: 16px;
list-style-image: var(--identity-icon-normal);
}
#identity-icon:-moz-lwtheme {
--identity-icon-normal: url(chrome://browser/skin/identity-icon.svg#normal-black);
--identity-icon-hover: url(chrome://browser/skin/identity-icon.svg#hover-black);
--identity-icon-notice: url(chrome://browser/skin/identity-icon.svg#notice-black);
--identity-icon-notice-hover: url(chrome://browser/skin/identity-icon.svg#notice-hover-black);
}
#identity-box:hover > #identity-icon:not(.no-hover),
#identity-box[open=true] > #identity-icon {
list-style-image: var(--identity-icon-hover);
}
#identity-box.grantedPermissions > #identity-icon {
list-style-image: var(--identity-icon-notice);
}
#identity-box.grantedPermissions:hover > #identity-icon:not(.no-hover),
#identity-box.grantedPermissions[open=true] > #identity-icon {
list-style-image: var(--identity-icon-notice-hover);
}
#urlbar[pageproxystate="valid"] > #identity-box.chromeUI > #identity-icon {
list-style-image: url(chrome://branding/content/identity-icons-brand.svg);
}
#urlbar[pageproxystate="invalid"] > #identity-box > #identity-icon {
@ -142,23 +123,10 @@
/* TRACKING PROTECTION ICON */
#tracking-protection-icon {
--tracking-protection-icon-enabled: url(chrome://browser/skin/tracking-protection-16.svg#enabled);
--tracking-protection-icon-disabled: url(chrome://browser/skin/tracking-protection-16.svg#disabled);
width: 16px;
height: 16px;
margin-inline-start: 2px;
margin-inline-end: 0;
list-style-image: var(--tracking-protection-icon-enabled);
}
#tracking-protection-icon:-moz-lwtheme {
--tracking-protection-icon-enabled: url(chrome://browser/skin/tracking-protection-16.svg#enabled-black);
--tracking-protection-icon-disabled: url(chrome://browser/skin/tracking-protection-16.svg#disabled-black);
}
#tracking-protection-icon[state="loaded-tracking-content"] {
list-style-image: var(--tracking-protection-icon-disabled);
}
#tracking-protection-icon[animate] {
@ -184,37 +152,5 @@
height: 16px;
margin-inline-start: 2px;
visibility: collapse;
--connection-icon-mixed-passive-loaded: url(chrome://browser/skin/connection-mixed-passive-loaded.svg#icon);
--connection-icon-mixed-active-loaded: url(chrome://browser/skin/connection-mixed-active-loaded.svg#icon);
}
#connection-icon:-moz-lwtheme {
--connection-icon-mixed-passive-loaded: url(chrome://browser/skin/connection-mixed-passive-loaded.svg#icon-black);
--connection-icon-mixed-active-loaded: url(chrome://browser/skin/connection-mixed-active-loaded.svg#icon-black);
}
#urlbar[pageproxystate="valid"] > #identity-box.verifiedDomain > #connection-icon,
#urlbar[pageproxystate="valid"] > #identity-box.verifiedIdentity > #connection-icon,
#urlbar[pageproxystate="valid"] > #identity-box.mixedActiveBlocked > #connection-icon {
list-style-image: url(chrome://browser/skin/connection-secure.svg);
visibility: visible;
}
#urlbar[pageproxystate="valid"] > #identity-box.certUserOverridden > #connection-icon {
list-style-image: var(--connection-icon-mixed-passive-loaded);
visibility: visible;
}
#urlbar[pageproxystate="valid"] > #identity-box.insecureLoginForms > #connection-icon,
#urlbar[pageproxystate="valid"] > #identity-box.mixedActiveContent > #connection-icon {
list-style-image: var(--connection-icon-mixed-active-loaded);
visibility: visible;
}
#urlbar[pageproxystate="valid"] > #identity-box.weakCipher > #connection-icon,
#urlbar[pageproxystate="valid"] > #identity-box.mixedDisplayContent > #connection-icon,
#urlbar[pageproxystate="valid"] > #identity-box.mixedDisplayContentLoadedActiveBlocked > #connection-icon {
list-style-image: var(--connection-icon-mixed-passive-loaded);
visibility: visible;
}

View File

@ -18,13 +18,14 @@
# - `check_msg` is the message to be printed to accompany compiling the test
# program.
@template
def try_compile(includes=None, body='', language='C++', flags=None, check_msg=None):
def try_compile(includes=None, body='', language='C++', flags=None, check_msg=None,
when=None):
compiler = {
'C': c_compiler,
'C++': cxx_compiler,
}[language]
return compiler.try_compile(includes, body, flags, check_msg)
return compiler.try_compile(includes, body, flags, check_msg, when=when)
# Checks for the presence of the given header on the target system by compiling
@ -52,10 +53,8 @@ def check_header(header, language='C++', flags=None, includes=None, when=None):
includes = []
includes.append(header)
@depends_when(try_compile(includes=includes, language=language, flags=flags,
check_msg='for %s' % header), when=when)
def have_header(value):
return value
have_header = try_compile(includes=includes, language=language, flags=flags,
check_msg='for %s' % header, when=when)
header_var = 'HAVE_%s' % (header.upper()
.replace('-', '_')
.replace('/', '_')

View File

@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=995943
SimpleTest.waitForExplicitFinish();
SimpleTest.requestCompleteLog();
if (navigator.userAgent.indexOf("Mac OS X 10.10") != -1)
SimpleTest.expectAssertions(6, 9); // See bug 1067022
SimpleTest.expectAssertions(5, 9); // See bug 1067022
else if (Services.appinfo.OS == "WINNT")
SimpleTest.expectAssertions(0, 1); // See bug 1067022

View File

@ -0,0 +1,63 @@
# vim: set ts=8 sts=4 et sw=4 tw=99:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#----------------------------------------------------------------------------
# This script checks encoding of the files that define JSErrorFormatStrings.
#
# JSErrorFormatString.format member should be in ASCII encoding.
#----------------------------------------------------------------------------
from __future__ import print_function
import os
import sys
from check_utils import get_all_toplevel_filenames
scriptname = os.path.basename(__file__);
expected_encoding = 'ascii'
# The following files don't define JSErrorFormatString.
ignore_files = [
'dom/base/domerr.msg',
'js/xpconnect/src/xpc.msg',
]
def log_pass(filename, text):
print('TEST-PASS | {} | {} | {}'.format(scriptname, filename, text))
def log_fail(filename, text):
print('TEST-UNEXPECTED-FAIL | {} | {} | {}'.format(scriptname, filename,
text))
def check_single_file(filename):
with open(filename, 'rb') as f:
data = f.read()
try:
data.decode(expected_encoding)
except:
log_fail(filename, 'not in {} encoding'.format(expected_encoding))
log_pass(filename, 'ok')
return True
def check_files():
result = True
for filename in get_all_toplevel_filenames():
if filename.endswith('.msg'):
if filename not in ignore_files:
if not check_single_file(filename):
result = False
return result
def main():
if not check_files():
sys.exit(1)
sys.exit(0)
if __name__ == '__main__':
main()

View File

@ -679,6 +679,7 @@ SSL_OptionSet
SSL_OptionSetDefault
SSL_PeerCertificate
SSL_PeerCertificateChain
SSL_PeerSignedCertTimestamps
SSL_PeerStapledOCSPResponses
SSL_ResetHandshake
SSL_SendAdditionalKeyShares

View File

@ -934,9 +934,12 @@ cargo_build_flags += --verbose
# We need to run cargo unconditionally, because cargo is the only thing that
# has full visibility into how changes in Rust sources might affect the final
# build.
#
# XXX: We're passing `-C debuginfo=1` to rustc to work around an llvm-dsymutil
# crash (bug 1301751). This should be temporary until we upgrade to Rust 1.12.
force-cargo-build:
$(REPORT_BUILD)
env CARGO_TARGET_DIR=. RUSTC=$(RUSTC) $(CARGO) build $(cargo_build_flags) --
env CARGO_TARGET_DIR=. RUSTC=$(RUSTC) RUSTFLAGS='-C debuginfo=1' $(CARGO) build $(cargo_build_flags) --
$(RUST_LIBRARY_FILE): force-cargo-build
endif # CARGO_FILE

View File

@ -61,6 +61,7 @@ var DomTree = React.createClass({
let renderValue = props => {
return Rep(Object.assign({}, props, {
defaultRep: Grip,
cropLimit: 50,
}));
};

View File

@ -26,7 +26,7 @@
<script type="application/javascript;version=1.8"
src="chrome://devtools/content/shared/theme-switching.js"></script>
</head>
<body class="theme-body devtools-monospace" role="application">
<body class="theme-body" role="application">
<div class="inspector-responsive-container theme-body inspector">
<!-- Main Panel Content -->

View File

@ -7,7 +7,6 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="chrome://devtools/content/inspector/markup/markup.css" type="text/css"/>
<link rel="stylesheet" href="chrome://devtools/skin/markup.css" type="text/css"/>
<script type="application/javascript;version=1.8"

View File

@ -93,7 +93,9 @@ define(function (require, exports, module) {
}
// Render the value (summary) using Reps library.
return Rep(props);
return Rep(Object.assign({}, props, {
cropLimit: 50,
}));
},
renderTree: function () {

View File

@ -8,6 +8,8 @@ DevToolsModules(
'jit-optimizations.js',
'recording-button.js',
'recording-controls.js',
'recording-list-item.js',
'recording-list.js',
'waterfall-header.js',
'waterfall-tree-row.js',
'waterfall-tree.js',

View File

@ -0,0 +1,49 @@
/* 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/. */
"use strict";
const {DOM, createClass} = require("devtools/client/shared/vendor/react");
const {div, li, span, button} = DOM;
const {L10N} = require("devtools/client/performance/modules/global");
module.exports = createClass({
displayName: "Recording List Item",
render() {
const {
label,
duration,
onSelect,
onSave,
isLoading,
isSelected,
isRecording
} = this.props;
const className = `recording-list-item ${isSelected ? "selected" : ""}`;
let durationText;
if (isLoading) {
durationText = L10N.getStr("recordingsList.loadingLabel");
} else if (isRecording) {
durationText = L10N.getStr("recordingsList.recordingLabel");
} else {
durationText = L10N.getFormatStr("recordingsList.durationLabel", duration);
}
return (
li({ className, onClick: onSelect },
div({ className: "recording-list-item-label" },
label
),
div({ className: "recording-list-item-footer" },
span({ className: "recording-list-item-duration" }, durationText),
button({ className: "recording-list-item-save", onClick: onSave },
L10N.getStr("recordingsList.saveLabel")
)
)
)
);
}
});

View File

@ -0,0 +1,23 @@
/* 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/. */
"use strict";
const {DOM, createClass} = require("devtools/client/shared/vendor/react");
const {L10N} = require("devtools/client/performance/modules/global");
const {ul, div} = DOM;
module.exports = createClass({
displayName: "Recording List",
render() {
const {
items,
itemComponent: Item,
} = this.props;
return items.length > 0
? ul({ className: "recording-list" }, ...items.map(Item))
: div({ className: "recording-list-empty" }, L10N.getStr("noRecordingsText"));
}
});

View File

@ -27,13 +27,16 @@ Object.defineProperty(this, "EVENTS", {
});
/* exported React, ReactDOM, JITOptimizationsView, RecordingControls, RecordingButton,
Waterfall, Services, promise, EventEmitter, DevToolsUtils, system */
RecordingList, RecordingListItem, Services, Waterfall, promise, EventEmitter,
DevToolsUtils, system */
var React = require("devtools/client/shared/vendor/react");
var ReactDOM = require("devtools/client/shared/vendor/react-dom");
var Waterfall = React.createFactory(require("devtools/client/performance/components/waterfall"));
var JITOptimizationsView = React.createFactory(require("devtools/client/performance/components/jit-optimizations"));
var RecordingControls = React.createFactory(require("devtools/client/performance/components/recording-controls"));
var RecordingButton = React.createFactory(require("devtools/client/performance/components/recording-button"));
var RecordingList = React.createFactory(require("devtools/client/performance/components/recording-list"));
var RecordingListItem = React.createFactory(require("devtools/client/performance/components/recording-list-item"));
var Services = require("Services");
var promise = require("promise");

View File

@ -84,7 +84,9 @@
<hbox id="recordings-controls">
<html:div id='recording-controls-mount'/>
</hbox>
<vbox id="recordings-list" class="theme-sidebar" flex="1"/>
<vbox id="recordings-list" class="theme-sidebar" flex="1">
<html:div id="recording-list-mount"/>
</vbox>
</vbox>
<!-- Main panel content -->

View File

@ -34,11 +34,18 @@ add_task(function* () {
JsCallTreeView._populateCallTree(threadNode);
JsCallTreeView.emit(EVENTS.UI_JS_CALL_TREE_RENDERED);
let firstTreeItem = $("#js-calltree-view .call-tree-item");
// DE-XUL: There are focus issues with XUL. Focus first, then synthesize the clicks
// so that keyboard events work correctly.
firstTreeItem.focus();
let count = 0;
let onFocus = () => count++;
JsCallTreeView.on("focus", onFocus);
click($("#js-calltree-view .call-tree-item"));
click(firstTreeItem);
key("VK_DOWN");
key("VK_DOWN");
key("VK_DOWN");

View File

@ -10,6 +10,7 @@
const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInTab, initConsoleInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { waitUntil } = require("devtools/client/performance/test/helpers/wait-utils");
const { getSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { target, console } = yield initConsoleInNewTab({
@ -21,7 +22,7 @@ add_task(function* () {
yield console.profileEnd("rust");
let { panel } = yield initPerformanceInTab({ tab: target.tab });
let { PerformanceController, RecordingsView, WaterfallView } = panel.panelWin;
let { PerformanceController, WaterfallView } = panel.panelWin;
yield waitUntil(() => PerformanceController.getRecordings().length == 1);
yield waitUntil(() => WaterfallView.wasRenderedAtLeastOnce);
@ -31,9 +32,11 @@ add_task(function* () {
is(recordings[0].isConsole(), true, "Recording came from console.profile.");
is(recordings[0].getLabel(), "rust", "Correct label in the recording model.");
is(RecordingsView.selectedItem.attachment, recordings[0],
const selected = getSelectedRecording(panel);
is(selected, recordings[0],
"The profile from console should be selected as it's the only one.");
is(RecordingsView.selectedItem.attachment.getLabel(), "rust",
is(selected.getLabel(), "rust",
"The profile label for the first recording is correct.");
yield teardownToolboxAndRemoveTab(panel);

View File

@ -13,6 +13,7 @@ const { initPerformanceInTab, initConsoleInNewTab, teardownToolboxAndRemoveTab }
const { waitForRecordingStoppedEvents } = require("devtools/client/performance/test/helpers/actions");
const { waitUntil } = require("devtools/client/performance/test/helpers/wait-utils");
const { times } = require("devtools/client/performance/test/helpers/event-utils");
const { getSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { target, console } = yield initConsoleInNewTab({
@ -24,7 +25,7 @@ add_task(function* () {
yield console.profile("rust2");
let { panel } = yield initPerformanceInTab({ tab: target.tab });
let { EVENTS, PerformanceController, OverviewView, RecordingsView } = panel.panelWin;
let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
yield waitUntil(() => PerformanceController.getRecordings().length == 2);
@ -37,9 +38,10 @@ add_task(function* () {
is(recordings[1].getLabel(), "rust2", "Correct label in the recording model (2).");
is(recordings[1].isRecording(), true, "Recording is still recording (2).");
is(RecordingsView.selectedItem.attachment, recordings[0],
const selected = getSelectedRecording(panel);
is(selected, recordings[0],
"The first console recording should be selected.");
is(RecordingsView.selectedItem.attachment.getLabel(), "rust",
is(selected.getLabel(), "rust",
"The profile label for the first recording is correct.");
// Ensure overview is still rendering.

View File

@ -11,6 +11,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInTab, initConsoleInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { waitForRecordingStoppedEvents } = require("devtools/client/performance/test/helpers/actions");
const { waitUntil } = require("devtools/client/performance/test/helpers/wait-utils");
const { getSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { target, console } = yield initConsoleInNewTab({
@ -23,7 +24,7 @@ add_task(function* () {
yield console.profile("rust2");
let { panel } = yield initPerformanceInTab({ tab: target.tab });
let { PerformanceController, RecordingsView, WaterfallView } = panel.panelWin;
let { PerformanceController, WaterfallView } = panel.panelWin;
yield waitUntil(() => PerformanceController.getRecordings().length == 2);
yield waitUntil(() => WaterfallView.wasRenderedAtLeastOnce);
@ -37,9 +38,10 @@ add_task(function* () {
is(recordings[1].getLabel(), "rust2", "Correct label in the recording model (2).");
is(recordings[1].isRecording(), true, "Recording is still recording (2).");
is(RecordingsView.selectedItem.attachment, recordings[0],
const selected = getSelectedRecording(panel);
is(selected, recordings[0],
"The first console recording should be selected.");
is(RecordingsView.selectedItem.attachment.getLabel(), "rust",
is(selected.getLabel(), "rust",
"The profile label for the first recording is correct.");
let stopped = waitForRecordingStoppedEvents(panel, {

View File

@ -12,6 +12,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInTab, initConsoleInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { waitForRecordingStartedEvents, waitForRecordingStoppedEvents } = require("devtools/client/performance/test/helpers/actions");
const { times } = require("devtools/client/performance/test/helpers/event-utils");
const { getSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { target, console } = yield initConsoleInNewTab({
@ -20,7 +21,7 @@ add_task(function* () {
});
let { panel } = yield initPerformanceInTab({ tab: target.tab });
let { EVENTS, PerformanceController, OverviewView, RecordingsView } = panel.panelWin;
let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
let started = waitForRecordingStartedEvents(panel, {
// only emitted for manual recordings
@ -35,9 +36,10 @@ add_task(function* () {
is(recordings[0].getLabel(), "rust", "Correct label in the recording model.");
is(recordings[0].isRecording(), true, "Recording is still recording.");
is(RecordingsView.selectedItem.attachment, recordings[0],
const selected = getSelectedRecording(panel);
is(selected, recordings[0],
"The profile from console should be selected as it's the only one.");
is(RecordingsView.selectedItem.attachment.getLabel(), "rust",
is(selected.getLabel(), "rust",
"The profile label for the first recording is correct.");
// Ensure overview is still rendering.

View File

@ -12,6 +12,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInTab, initConsoleInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { waitForRecordingStartedEvents, waitForRecordingStoppedEvents } = require("devtools/client/performance/test/helpers/actions");
const { times } = require("devtools/client/performance/test/helpers/event-utils");
const { getSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { target, console } = yield initConsoleInNewTab({
@ -20,7 +21,7 @@ add_task(function* () {
});
let { panel } = yield initPerformanceInTab({ tab: target.tab });
let { EVENTS, PerformanceController, OverviewView, RecordingsView } = panel.panelWin;
let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
let started = waitForRecordingStartedEvents(panel, {
// only emitted for manual recordings
@ -35,9 +36,10 @@ add_task(function* () {
is(recordings[0].getLabel(), "rust", "Correct label in the recording model (1).");
is(recordings[0].isRecording(), true, "Recording is still recording (1).");
is(RecordingsView.selectedItem.attachment, recordings[0],
let selected = getSelectedRecording(panel);
is(selected, recordings[0],
"The profile from console should be selected as it's the only one.");
is(RecordingsView.selectedItem.attachment.getLabel(), "rust",
is(selected.getLabel(), "rust",
"The profile label for the first recording is correct.");
// Ensure overview is still rendering.
@ -70,9 +72,10 @@ add_task(function* () {
is(recordings[1].getLabel(), "rust", "Correct label in the recording model (2).");
is(recordings[1].isRecording(), true, "Recording is still recording (2).");
is(RecordingsView.selectedItem.attachment, recordings[0],
selected = getSelectedRecording(panel);
is(selected, recordings[0],
"The profile from console should still be selected");
is(RecordingsView.selectedItem.attachment.getLabel(), "rust",
is(selected.getLabel(), "rust",
"The profile label for the first recording is correct.");
stopped = waitForRecordingStoppedEvents(panel, {

View File

@ -11,6 +11,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInTab, initConsoleInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { waitForRecordingStartedEvents, waitForRecordingStoppedEvents } = require("devtools/client/performance/test/helpers/actions");
const { times } = require("devtools/client/performance/test/helpers/event-utils");
const { getSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { target, console } = yield initConsoleInNewTab({
@ -19,7 +20,7 @@ add_task(function* () {
});
let { panel } = yield initPerformanceInTab({ tab: target.tab });
let { EVENTS, PerformanceController, OverviewView, RecordingsView } = panel.panelWin;
let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
let started = waitForRecordingStartedEvents(panel, {
// only emitted for manual recordings
@ -30,7 +31,7 @@ add_task(function* () {
let recordings = PerformanceController.getRecordings();
is(recordings.length, 1, "A recording found in the performance panel.");
is(RecordingsView.selectedItem.attachment, recordings[0],
is(getSelectedRecording(panel), recordings[0],
"The first console recording should be selected.");
// Ensure overview is still rendering.
@ -52,7 +53,7 @@ add_task(function* () {
recordings = PerformanceController.getRecordings();
is(recordings.length, 2, "Two recordings found in the performance panel.");
is(RecordingsView.selectedItem.attachment, recordings[0],
is(getSelectedRecording(panel), recordings[0],
"The first console recording should still be selected.");
// Ensure overview is still rendering.
@ -69,7 +70,7 @@ add_task(function* () {
recordings = PerformanceController.getRecordings();
is(recordings.length, 2, "Two recordings found in the performance panel.");
is(RecordingsView.selectedItem.attachment, recordings[0],
is(getSelectedRecording(panel), recordings[0],
"The first console recording should still be selected.");
is(recordings[0].isRecording(), false,
"The first console recording should no longer be recording.");
@ -86,7 +87,7 @@ add_task(function* () {
recordings = PerformanceController.getRecordings();
is(recordings.length, 2, "Two recordings found in the performance panel.");
is(RecordingsView.selectedItem.attachment, recordings[0],
is(getSelectedRecording(panel), recordings[0],
"The first console recording should still be selected.");
is(recordings[1].isRecording(), false,
"The second console recording should no longer be recording.");

View File

@ -12,6 +12,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInTab, initConsoleInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { waitForRecordingStartedEvents, waitForRecordingStoppedEvents } = require("devtools/client/performance/test/helpers/actions");
const { idleWait } = require("devtools/client/performance/test/helpers/wait-utils");
const { getSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { target, console } = yield initConsoleInNewTab({
@ -20,7 +21,7 @@ add_task(function* () {
});
let { panel } = yield initPerformanceInTab({ tab: target.tab });
let { PerformanceController, RecordingsView } = panel.panelWin;
let { PerformanceController } = panel.panelWin;
let started = waitForRecordingStartedEvents(panel, {
// only emitted for manual recordings
@ -54,11 +55,12 @@ add_task(function* () {
yield started;
let recordings = PerformanceController.getRecordings();
let selected = getSelectedRecording(panel);
is(recordings.length, 3, "Three recordings found in the performance panel.");
is(recordings[0].getLabel(), "", "Checking label of recording 1");
is(recordings[1].getLabel(), "1", "Checking label of recording 2");
is(recordings[2].getLabel(), "2", "Checking label of recording 3");
is(RecordingsView.selectedItem.attachment, recordings[0],
is(selected, recordings[0],
"The first console recording should be selected.");
is(recordings[0].isRecording(), true,
@ -81,9 +83,10 @@ add_task(function* () {
yield console.profileEnd();
yield stopped;
selected = getSelectedRecording(panel);
recordings = PerformanceController.getRecordings();
is(recordings.length, 3, "Three recordings found in the performance panel.");
is(RecordingsView.selectedItem.attachment, recordings[0],
is(selected, recordings[0],
"The first console recording should still be selected.");
is(recordings[0].isRecording(), true, "The not most recent recording should not stop " +
@ -97,9 +100,10 @@ add_task(function* () {
console.profileEnd("fxos");
yield idleWait(1000);
selected = getSelectedRecording(panel);
recordings = PerformanceController.getRecordings();
is(recordings.length, 3, "Three recordings found in the performance panel.");
is(RecordingsView.selectedItem.attachment, recordings[0],
is(selected, recordings[0],
"The first console recording should still be selected.");
is(recordings[0].isRecording(), true,
@ -122,9 +126,10 @@ add_task(function* () {
yield console.profileEnd();
yield stopped;
selected = getSelectedRecording(panel);
recordings = PerformanceController.getRecordings();
is(recordings.length, 3, "Three recordings found in the performance panel.");
is(RecordingsView.selectedItem.attachment, recordings[0],
is(selected, recordings[0],
"The first console recording should still be selected.");
is(recordings[0].isRecording(), true,
@ -141,9 +146,10 @@ add_task(function* () {
yield console.profileEnd();
yield stopped;
selected = getSelectedRecording(panel);
recordings = PerformanceController.getRecordings();
is(recordings.length, 3, "Three recordings found in the performance panel.");
is(RecordingsView.selectedItem.attachment, recordings[0],
is(selected, recordings[0],
"The first console recording should be selected.");
is(recordings[0].isRecording(), false,

View File

@ -13,6 +13,31 @@ const { initPerformanceInTab, initConsoleInNewTab, teardownToolboxAndRemoveTab }
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { waitForRecordingStartedEvents, waitForRecordingStoppedEvents } = require("devtools/client/performance/test/helpers/actions");
const { once, times } = require("devtools/client/performance/test/helpers/event-utils");
const { setSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
/**
* The following are bit flag constants that are used to represent the state of a
* recording.
*/
// Represents a manually recorded profile, if a user hit the record button.
const MANUAL = 0;
// Represents a recorded profile from console.profile().
const CONSOLE = 1;
// Represents a profile that is currently recording.
const RECORDING = 2;
// Represents a profile that is currently selected.
const SELECTED = 4;
/**
* Utility function to provide a meaningful inteface for testing that the bits
* match for the recording state.
* @param {integer} expected - The expected bit values packed in an integer.
* @param {integer} actual - The actual bit values packed in an integer.
*/
function hasBitFlag(expected, actual) {
return !!(expected & actual);
}
add_task(function* () {
// This test seems to take a very long time to finish on Linux VMs.
@ -24,22 +49,27 @@ add_task(function* () {
});
let { panel } = yield initPerformanceInTab({ tab: target.tab });
let { EVENTS, PerformanceController, RecordingsView, OverviewView } = panel.panelWin;
let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
info("Starting console.profile()...");
info("Recording 1 - Starting console.profile()...");
let started = waitForRecordingStartedEvents(panel, {
// only emitted for manual recordings
skipWaitingForBackendReady: true
});
yield console.profile("rust");
yield started;
testRecordings(PerformanceController, [C + S + R]);
testRecordings(PerformanceController, [
CONSOLE + SELECTED + RECORDING
]);
info("Starting manual recording...");
info("Recording 2 - Starting manual recording...");
yield startRecording(panel);
testRecordings(PerformanceController, [C + R, R + S]);
testRecordings(PerformanceController, [
CONSOLE + RECORDING,
MANUAL + RECORDING + SELECTED
]);
info("Starting console.profile(\"3\")...");
info("Recording 3 - Starting console.profile(\"3\")...");
started = waitForRecordingStartedEvents(panel, {
// only emitted for manual recordings
skipWaitingForBackendReady: true,
@ -51,9 +81,13 @@ add_task(function* () {
});
yield console.profile("3");
yield started;
testRecordings(PerformanceController, [C + R, R + S, C + R]);
testRecordings(PerformanceController, [
CONSOLE + RECORDING,
MANUAL + RECORDING + SELECTED,
CONSOLE + RECORDING
]);
info("Starting console.profile(\"4\")...");
info("Recording 4 - Starting console.profile(\"4\")...");
started = waitForRecordingStartedEvents(panel, {
// only emitted for manual recordings
skipWaitingForBackendReady: true,
@ -65,9 +99,14 @@ add_task(function* () {
});
yield console.profile("4");
yield started;
testRecordings(PerformanceController, [C + R, R + S, C + R, C + R]);
testRecordings(PerformanceController, [
CONSOLE + RECORDING,
MANUAL + RECORDING + SELECTED,
CONSOLE + RECORDING,
CONSOLE + RECORDING
]);
info("Ending console.profileEnd()...");
info("Recording 4 - Ending console.profileEnd()...");
let stopped = waitForRecordingStoppedEvents(panel, {
// only emitted for manual recordings
skipWaitingForBackendReady: true,
@ -80,27 +119,48 @@ add_task(function* () {
});
yield console.profileEnd();
yield stopped;
testRecordings(PerformanceController, [C + R, R + S, C + R, C]);
testRecordings(PerformanceController, [
CONSOLE + RECORDING,
MANUAL + RECORDING + SELECTED,
CONSOLE + RECORDING,
CONSOLE
]);
info("Select last recording...");
info("Recording 4 - Select last recording...");
let recordingSelected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 3;
setSelectedRecording(panel, 3);
yield recordingSelected;
testRecordings(PerformanceController, [C + R, R, C + R, C + S]);
testRecordings(PerformanceController, [
CONSOLE + RECORDING,
MANUAL + RECORDING,
CONSOLE + RECORDING,
CONSOLE + SELECTED
]);
ok(!OverviewView.isRendering(),
"Stop rendering overview when a completed recording is selected.");
info("Stop manual recording...");
info("Recording 2 - Stop manual recording.");
yield stopRecording(panel);
testRecordings(PerformanceController, [C + R, S, C + R, C]);
testRecordings(PerformanceController, [
CONSOLE + RECORDING,
MANUAL + SELECTED,
CONSOLE + RECORDING,
CONSOLE
]);
ok(!OverviewView.isRendering(),
"Stop rendering overview when a completed recording is selected.");
info("Select first recording...");
info("Recording 1 - Select first recording.");
recordingSelected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield recordingSelected;
testRecordings(PerformanceController, [C + R + S, 0, C + R, C]);
testRecordings(PerformanceController, [
CONSOLE + RECORDING + SELECTED,
MANUAL,
CONSOLE + RECORDING,
CONSOLE
]);
ok(OverviewView.isRendering(),
"Should be rendering overview a recording in progress is selected.");
@ -122,7 +182,12 @@ add_task(function* () {
});
yield console.profileEnd();
yield stopped;
testRecordings(PerformanceController, [C + R + S, 0, C, C]);
testRecordings(PerformanceController, [
CONSOLE + RECORDING + SELECTED,
MANUAL,
CONSOLE,
CONSOLE
]);
ok(OverviewView.isRendering(),
"Should be rendering overview a recording in progress is selected.");
@ -131,9 +196,15 @@ add_task(function* () {
expectedArgs: { "1": Constants.FRAMERATE_GRAPH_LOW_RES_INTERVAL }
});
info("Start one more manual recording...");
info("Recording 5 - Start one more manual recording.");
yield startRecording(panel);
testRecordings(PerformanceController, [C + R, 0, C, C, R + S]);
testRecordings(PerformanceController, [
CONSOLE + RECORDING,
MANUAL,
CONSOLE,
CONSOLE,
MANUAL + RECORDING + SELECTED
]);
ok(OverviewView.isRendering(),
"Should be rendering overview a recording in progress is selected.");
@ -142,13 +213,19 @@ add_task(function* () {
expectedArgs: { "1": Constants.FRAMERATE_GRAPH_LOW_RES_INTERVAL }
});
info("Stop manual recording...");
info("Recording 5 - Stop manual recording.");
yield stopRecording(panel);
testRecordings(PerformanceController, [C + R, 0, C, C, S]);
testRecordings(PerformanceController, [
CONSOLE + RECORDING,
MANUAL,
CONSOLE,
CONSOLE,
MANUAL + SELECTED
]);
ok(!OverviewView.isRendering(),
"Stop rendering overview when a completed recording is selected.");
info("Ending console.profileEnd()...");
info("Recording 1 - Ending console.profileEnd()...");
stopped = waitForRecordingStoppedEvents(panel, {
// only emitted for manual recordings
skipWaitingForBackendReady: true,
@ -161,31 +238,31 @@ add_task(function* () {
});
yield console.profileEnd();
yield stopped;
testRecordings(PerformanceController, [C, 0, C, C, S]);
testRecordings(PerformanceController, [
CONSOLE,
MANUAL,
CONSOLE,
CONSOLE,
MANUAL + SELECTED
]);
ok(!OverviewView.isRendering(),
"Stop rendering overview when a completed recording is selected.");
yield teardownToolboxAndRemoveTab(panel);
});
// is console
const C = 1;
// is recording
const R = 2;
// is selected
const S = 4;
function testRecordings(controller, expected) {
function testRecordings(controller, expectedBitFlags) {
let recordings = controller.getRecordings();
let current = controller.getCurrentRecording();
is(recordings.length, expected.length, "Expected number of recordings.");
is(recordings.length, expectedBitFlags.length, "Expected number of recordings.");
recordings.forEach((recording, i) => {
ok(recording.isConsole() == !!(expected[i] & C),
const expected = expectedBitFlags[i];
is(recording.isConsole(), hasBitFlag(expected, CONSOLE),
`Recording ${i + 1} has expected console state.`);
ok(recording.isRecording() == !!(expected[i] & R),
is(recording.isRecording(), hasBitFlag(expected, RECORDING),
`Recording ${i + 1} has expected console state.`);
ok((recording == current) == !!(expected[i] & S),
is((recording == current), hasBitFlag(expected, SELECTED),
`Recording ${i + 1} has expected selected state.`);
});
}

View File

@ -14,6 +14,7 @@ const { UI_ENABLE_ALLOCATIONS_PREF } = require("devtools/client/performance/test
const { initPerformanceInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { once } = require("devtools/client/performance/test/helpers/event-utils");
const { setSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPerformanceInNewTab({
@ -24,7 +25,6 @@ add_task(function* () {
let {
EVENTS,
$,
RecordingsView,
DetailsView,
WaterfallView,
MemoryCallTreeView,
@ -80,7 +80,7 @@ add_task(function* () {
// Select the first recording with no memory data.
selected = once(DetailsView, EVENTS.UI_DETAILS_VIEW_SELECTED);
rendered = once(WaterfallView, EVENTS.UI_WATERFALL_RENDERED);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield selected;
yield rendered;
@ -94,7 +94,7 @@ add_task(function* () {
// Go back to the recording with memory data.
rendered = once(WaterfallView, EVENTS.UI_WATERFALL_RENDERED);
RecordingsView.selectedIndex = 1;
setSelectedRecording(panel, 1);
yield rendered;
ok(DetailsView.isViewSelected(WaterfallView),

View File

@ -11,6 +11,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { once } = require("devtools/client/performance/test/helpers/event-utils");
const { setSelectedRecording, getSelectedRecordingIndex } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPerformanceInNewTab({
@ -22,7 +23,6 @@ add_task(function* () {
EVENTS,
$,
PerformanceController,
RecordingsView,
WaterfallView
} = panel.panelWin;
@ -84,11 +84,12 @@ add_task(function* () {
let selected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
let rendered = once(WaterfallView, EVENTS.UI_WATERFALL_RENDERED);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield selected;
yield rendered;
is(RecordingsView.selectedIndex, 0,
let selectedIndex = getSelectedRecordingIndex(panel);
is(selectedIndex, 0,
"The first recording was selected again.");
is(waterfallBtn.hidden, false,
@ -103,10 +104,11 @@ add_task(function* () {
"The `memory-calltree` button is hidden when first recording selected.");
selected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 1;
setSelectedRecording(panel, 1);
yield selected;
is(RecordingsView.selectedIndex, 1,
selectedIndex = getSelectedRecordingIndex(panel);
is(selectedIndex, 1,
"The second recording was selected again.");
is(waterfallBtn.hidden, true,
@ -124,7 +126,8 @@ add_task(function* () {
yield stopRecording(panel);
yield rendered;
is(RecordingsView.selectedIndex, 1,
selectedIndex = getSelectedRecordingIndex(panel);
is(selectedIndex, 1,
"The second recording is still selected.");
is(waterfallBtn.hidden, false,

View File

@ -11,6 +11,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { once } = require("devtools/client/performance/test/helpers/event-utils");
const { getSelectedRecording, getDurationLabelText } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPerformanceInNewTab({
@ -18,12 +19,11 @@ add_task(function* () {
win: window
});
let { EVENTS, L10N, $, PerformanceController, RecordingsView } = panel.panelWin;
let { EVENTS, L10N, PerformanceController } = panel.panelWin;
yield startRecording(panel);
let durationLabel = $(".recording-item-duration", RecordingsView.selectedItem.target);
is(durationLabel.getAttribute("value"),
is(getDurationLabelText(panel, 0),
L10N.getStr("recordingsList.recordingLabel"),
"The duration node should show the 'recording' message while recording");
@ -36,14 +36,15 @@ add_task(function* () {
let everythingStopped = stopRecording(panel);
yield recordingStopping;
is(durationLabel.getAttribute("value"),
is(getDurationLabelText(panel, 0),
L10N.getStr("recordingsList.loadingLabel"),
"The duration node should show the 'loading' message while stopping");
yield recordingStopped;
is(durationLabel.getAttribute("value"),
const selected = getSelectedRecording(panel);
is(getDurationLabelText(panel, 0),
L10N.getFormatStr("recordingsList.durationLabel",
RecordingsView.selectedItem.attachment.getDuration().toFixed(0)),
selected.getDuration().toFixed(0)),
"The duration node should show the duration after the record has stopped");
yield everythingStopped;

View File

@ -13,6 +13,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { once } = require("devtools/client/performance/test/helpers/event-utils");
const { getSelectedRecordingIndex, setSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPerformanceInNewTab({
@ -20,7 +21,7 @@ add_task(function* () {
win: window
});
let { EVENTS, $, PerformanceController, RecordingsView } = panel.panelWin;
let { EVENTS, $, PerformanceController } = panel.panelWin;
let detailsContainer = $("#details-pane-container");
let recordingNotice = $("#recording-notice");
let loadingNotice = $("#loading-notice");
@ -52,7 +53,7 @@ add_task(function* () {
info("While the 2nd record is still going, switch to the first one.");
let recordingSelected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield recordingSelected;
recordingStopping = once(PerformanceController, EVENTS.RECORDING_STATE_CHANGE, {
@ -66,14 +67,14 @@ add_task(function* () {
yield recordingStopping;
is(detailsContainer.selectedPanel, detailsPane,
"The details panel is still shown while the 2nd record is being stopped.");
is(RecordingsView.selectedIndex, 0,
is(getSelectedRecordingIndex(panel), 0,
"The first record is still selected.");
yield recordingStopped;
is(detailsContainer.selectedPanel, detailsPane,
"The details panel is still shown after the 2nd record has stopped.");
is(RecordingsView.selectedIndex, 1,
is(getSelectedRecordingIndex(panel), 1,
"The second record is now selected.");
yield everythingStopped;

View File

@ -9,13 +9,13 @@ requestLongerTimeout(2);
* Tests that the JIT Optimizations view renders optimization data
* if on, and displays selected frames on focus.
*/
const { setSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
Services.prefs.setBoolPref(INVERT_PREF, false);
function* spawnTest() {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, $, $$, window, PerformanceController } = panel.panelWin;
let { OverviewView, DetailsView, OptimizationsListView, JsCallTreeView, RecordingsView } = panel.panelWin;
let { OverviewView, DetailsView, OptimizationsListView, JsCallTreeView } = panel.panelWin;
let profilerData = { threads: [gThread] };
@ -58,14 +58,14 @@ function* spawnTest() {
let select = once(PerformanceController, EVENTS.RECORDING_SELECTED);
rendered = once(JsCallTreeView, EVENTS.UI_JS_CALL_TREE_RENDERED);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield Promise.all([select, rendered]);
isHidden = $("#jit-optimizations-view").classList.contains("hidden");
ok(isHidden, "opts view is hidden when switching recordings");
rendered = once(JsCallTreeView, EVENTS.UI_JS_CALL_TREE_RENDERED);
RecordingsView.selectedIndex = 1;
setSelectedRecording(panel, 1);
yield rendered;
rendered = once(JsCallTreeView, "focus");

View File

@ -13,6 +13,7 @@ const { initPerformanceInNewTab, teardownToolboxAndRemoveTab } = require("devtoo
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { waitUntil } = require("devtools/client/performance/test/helpers/wait-utils");
const { isVisible } = require("devtools/client/performance/test/helpers/dom-utils");
const { setSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPerformanceInNewTab({
@ -20,7 +21,7 @@ add_task(function* () {
win: window
});
let { $, EVENTS, PerformanceController, RecordingsView, OverviewView } = panel.panelWin;
let { $, EVENTS, PerformanceController, OverviewView } = panel.panelWin;
// Enable memory to test.
Services.prefs.setBoolPref(UI_ENABLE_MEMORY_PREF, true);
@ -53,12 +54,12 @@ add_task(function* () {
"Overview graphs hidden again when starting new recording.");
is(updated, 1, "Overview graphs have not been updated again.");
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
is(isVisible($("#overview-pane")), true,
"Overview graphs no longer hidden when switching back to complete recording.");
is(updated, 1, "Overview graphs have not been updated again.");
RecordingsView.selectedIndex = 1;
setSelectedRecording(panel, 1);
is(isVisible($("#overview-pane")), false,
"Overview graphs hidden again when going back to inprogress recording.");
is(updated, 1, "Overview graphs have not been updated again.");

View File

@ -11,6 +11,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { once } = require("devtools/client/performance/test/helpers/event-utils");
const { setSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPerformanceInNewTab({
@ -23,7 +24,6 @@ add_task(function* () {
$,
PerformanceController,
PerformanceView,
RecordingsView
} = panel.panelWin;
let MAIN_CONTAINER = $("#performance-view");
@ -42,7 +42,7 @@ add_task(function* () {
is(DETAILS_CONTAINER.selectedPanel, RECORDING, "Showing recording panel.");
let selected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield selected;
is(PerformanceView.getState(), "recorded",
@ -51,7 +51,7 @@ add_task(function* () {
is(DETAILS_CONTAINER.selectedPanel, DETAILS, "Showing recorded panel.");
selected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 1;
setSelectedRecording(panel, 1);
yield selected;
is(PerformanceView.getState(), "recording",

View File

@ -15,6 +15,7 @@ const { initPerformanceInTab, initConsoleInNewTab, teardownToolboxAndRemoveTab }
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { waitUntil } = require("devtools/client/performance/test/helpers/wait-utils");
const { once } = require("devtools/client/performance/test/helpers/event-utils");
const { setSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
// Make sure the profiler module is stopped so we can set a new buffer limit.
@ -36,7 +37,6 @@ add_task(function* () {
$,
PerformanceController,
PerformanceView,
RecordingsView
} = panel.panelWin;
// Set a fast profiler-status update interval.
@ -88,7 +88,7 @@ add_task(function* () {
// Select the console recording.
let selected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 1;
setSelectedRecording(panel, 1);
yield selected;
yield waitUntil(function* () {
@ -109,7 +109,7 @@ add_task(function* () {
yield console.profileEnd("rust");
selected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield selected;
yield waitUntil(function* () {

View File

@ -11,6 +11,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { once } = require("devtools/client/performance/test/helpers/event-utils");
const { setSelectedRecording, getRecordingsCount, getSelectedRecordingIndex } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPerformanceInNewTab({
@ -18,7 +19,7 @@ add_task(function* () {
win: window
});
let { EVENTS, PerformanceController, RecordingsView } = panel.panelWin;
let { EVENTS, PerformanceController } = panel.panelWin;
yield startRecording(panel);
yield stopRecording(panel);
@ -26,18 +27,18 @@ add_task(function* () {
yield startRecording(panel);
yield stopRecording(panel);
is(RecordingsView.itemCount, 2,
is(getRecordingsCount(panel), 2,
"There should be two recordings visible.");
is(RecordingsView.selectedIndex, 1,
is(getSelectedRecordingIndex(panel), 1,
"The second recording item should be selected.");
let selected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield selected;
is(RecordingsView.itemCount, 2,
is(getRecordingsCount(panel), 2,
"There should still be two recordings visible.");
is(RecordingsView.selectedIndex, 0,
is(getSelectedRecordingIndex(panel), 0,
"The first recording item should be selected.");
yield teardownToolboxAndRemoveTab(panel);

View File

@ -11,6 +11,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { once } = require("devtools/client/performance/test/helpers/event-utils");
const { getSelectedRecordingIndex, setSelectedRecording, getRecordingsCount } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
// This test seems to take a very long time to finish on Linux VMs.
@ -21,38 +22,37 @@ add_task(function* () {
win: window
});
let { EVENTS, PerformanceController, RecordingsView } = panel.panelWin;
let { EVENTS, PerformanceController } = panel.panelWin;
yield startRecording(panel);
yield stopRecording(panel);
yield startRecording(panel);
is(RecordingsView.itemCount, 2,
is(getRecordingsCount(panel), 2,
"There should be two recordings visible.");
is(RecordingsView.selectedIndex, 1,
is(getSelectedRecordingIndex(panel), 1,
"The new recording item should be selected.");
let selected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield selected;
is(RecordingsView.itemCount, 2,
is(getRecordingsCount(panel), 2,
"There should still be two recordings visible.");
is(RecordingsView.selectedIndex, 0,
is(getSelectedRecordingIndex(panel), 0,
"The first recording item should be selected now.");
selected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 1;
setSelectedRecording(panel, 1);
yield selected;
is(RecordingsView.itemCount, 2,
is(getRecordingsCount(panel), 2,
"There should still be two recordings visible.");
is(RecordingsView.selectedIndex, 1,
is(getSelectedRecordingIndex(panel), 1,
"The second recording item should be selected again.");
yield stopRecording(panel);
yield teardownToolboxAndRemoveTab(panel);
});

View File

@ -12,6 +12,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPerformanceInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { once } = require("devtools/client/performance/test/helpers/event-utils");
const { setSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPerformanceInNewTab({
@ -19,7 +20,7 @@ add_task(function* () {
win: window
});
let { $, EVENTS, PerformanceController, RecordingsView } = panel.panelWin;
let { $, EVENTS, PerformanceController } = panel.panelWin;
yield startRecording(panel);
yield stopRecording(panel);
@ -29,7 +30,7 @@ add_task(function* () {
info("Selecting recording #0 and waiting for it to be displayed.");
let selected = once(PerformanceController, EVENTS.RECORDING_SELECTED);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield selected;
ok($("#main-record-button").classList.contains("checked"),

View File

@ -10,6 +10,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { UI_ENABLE_MEMORY_PREF, UI_ENABLE_ALLOCATIONS_PREF } = require("devtools/client/performance/test/helpers/prefs");
const { initPerformanceInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording, waitForAllWidgetsRendered } = require("devtools/client/performance/test/helpers/actions");
const { setSelectedRecording } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPerformanceInNewTab({
@ -17,7 +18,7 @@ add_task(function* () {
win: window
});
let { DetailsView, DetailsSubview, RecordingsView } = panel.panelWin;
let { DetailsView, DetailsSubview } = panel.panelWin;
// Enable memory to test the memory overview.
Services.prefs.setBoolPref(UI_ENABLE_MEMORY_PREF, true);
@ -43,13 +44,13 @@ add_task(function* () {
yield stopRecording(panel);
let rerender = waitForAllWidgetsRendered(panel);
RecordingsView.selectedIndex = 0;
setSelectedRecording(panel, 0);
yield rerender;
ok(true, "All widgets were rendered when selecting the first recording.");
rerender = waitForAllWidgetsRendered(panel);
RecordingsView.selectedIndex = 1;
setSelectedRecording(panel, 1);
yield rerender;
ok(true, "All widgets were rendered when selecting the second recording.");

View File

@ -10,6 +10,7 @@
const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPanelInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { getRecordingsCount } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPanelInNewTab({
@ -18,13 +19,13 @@ add_task(function* () {
win: window
});
let { PerformanceController, PerformanceView, RecordingsView } = panel.panelWin;
let { PerformanceController, PerformanceView } = panel.panelWin;
yield startRecording(panel);
yield stopRecording(panel);
is(RecordingsView.itemCount, 1,
"RecordingsView should have one recording.");
is(getRecordingsCount(panel), 1,
"The recordings list should have one recording.");
isnot(PerformanceView.getState(), "empty",
"PerformanceView should not be in an empty state.");
isnot(PerformanceController.getCurrentRecording(), null,
@ -33,8 +34,8 @@ add_task(function* () {
yield startRecording(panel);
yield stopRecording(panel);
is(RecordingsView.itemCount, 2,
"RecordingsView should have two recordings.");
is(getRecordingsCount(panel), 2,
"The recordings list should have two recordings.");
isnot(PerformanceView.getState(), "empty",
"PerformanceView should not be in an empty state.");
isnot(PerformanceController.getCurrentRecording(), null,
@ -42,8 +43,8 @@ add_task(function* () {
yield PerformanceController.clearRecordings();
is(RecordingsView.itemCount, 0,
"RecordingsView should be empty.");
is(getRecordingsCount(panel), 0,
"The recordings list should be empty.");
is(PerformanceView.getState(), "empty",
"PerformanceView should be in an empty state.");
is(PerformanceController.getCurrentRecording(), null,

View File

@ -11,6 +11,7 @@ const { SIMPLE_URL } = require("devtools/client/performance/test/helpers/urls");
const { initPanelInNewTab, teardownToolboxAndRemoveTab } = require("devtools/client/performance/test/helpers/panel-utils");
const { startRecording, stopRecording } = require("devtools/client/performance/test/helpers/actions");
const { times, once } = require("devtools/client/performance/test/helpers/event-utils");
const { getRecordingsCount } = require("devtools/client/performance/test/helpers/recording-utils");
add_task(function* () {
let { panel } = yield initPanelInNewTab({
@ -19,13 +20,13 @@ add_task(function* () {
win: window
});
let { EVENTS, PerformanceController, PerformanceView, RecordingsView } = panel.panelWin;
let { EVENTS, PerformanceController, PerformanceView } = panel.panelWin;
yield startRecording(panel);
yield stopRecording(panel);
is(RecordingsView.itemCount, 1,
"RecordingsView should have one recording.");
is(getRecordingsCount(panel), 1,
"The recordings list should have one recording.");
isnot(PerformanceView.getState(), "empty",
"PerformanceView should not be in an empty state.");
isnot(PerformanceController.getCurrentRecording(), null,
@ -33,8 +34,8 @@ add_task(function* () {
yield startRecording(panel);
is(RecordingsView.itemCount, 2,
"RecordingsView should have two recordings.");
is(getRecordingsCount(panel), 2,
"The recordings list should have two recordings.");
isnot(PerformanceView.getState(), "empty",
"PerformanceView should not be in an empty state.");
isnot(PerformanceController.getCurrentRecording(), null,
@ -50,8 +51,8 @@ add_task(function* () {
yield recordingDeleted;
yield recordingStopped;
is(RecordingsView.itemCount, 0,
"RecordingsView should be empty.");
is(getRecordingsCount(panel), 0,
"The recordings list should be empty.");
is(PerformanceView.getState(), "empty",
"PerformanceView should be in an empty state.");
is(PerformanceController.getCurrentRecording(), null,
@ -61,8 +62,8 @@ add_task(function* () {
yield startRecording(panel);
yield stopRecording(panel);
is(RecordingsView.itemCount, 1,
"RecordingsView should have one recording.");
is(getRecordingsCount(panel), 1,
"The recordings list should have one recording.");
yield teardownToolboxAndRemoveTab(panel);
});

View File

@ -12,7 +12,7 @@ var { CATEGORY_MASK } = require("devtools/client/performance/modules/categories"
function* spawnTest() {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, $, $$, window, PerformanceController } = panel.panelWin;
let { OverviewView, DetailsView, JsCallTreeView, RecordingsView } = panel.panelWin;
let { OverviewView, DetailsView, JsCallTreeView } = panel.panelWin;
let profilerData = { threads: [gThread] };

View File

@ -12,6 +12,7 @@ DevToolsModules(
'panel-utils.js',
'prefs.js',
'profiler-mm-utils.js',
'recording-utils.js',
'synth-utils.js',
'tab-utils.js',
'urls.js',

View File

@ -0,0 +1,54 @@
/* 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/. */
"use strict";
/**
* These utilities provide a functional interface for accessing the particulars
* about the recording's details.
*/
/**
* Access the selected view from the panel's recording list.
*
* @param {object} panel - The current panel.
* @return {object} The recording model.
*/
exports.getSelectedRecording = function (panel) {
const view = panel.panelWin.RecordingsView;
return view.selected;
};
/**
* Set the selected index of the recording via the panel.
*
* @param {object} panel - The current panel.
* @return {number} index
*/
exports.setSelectedRecording = function (panel, index) {
const view = panel.panelWin.RecordingsView;
view.setSelectedByIndex(index);
return index;
};
/**
* Access the selected view from the panel's recording list.
*
* @param {object} panel - The current panel.
* @return {number} index
*/
exports.getSelectedRecordingIndex = function (panel) {
const view = panel.panelWin.RecordingsView;
return view.getSelectedIndex();
};
exports.getDurationLabelText = function (panel, elementIndex) {
const { $$ } = panel.panelWin;
const elements = $$(".recording-list-item-duration", panel.panelWin.document);
return elements[elementIndex].innerHTML;
};
exports.getRecordingsCount = function (panel) {
const { $$ } = panel.panelWin;
return $$(".recording-list-item", panel.panelWin.document).length;
};

View File

@ -9,13 +9,11 @@
/**
* Functions handling the recordings UI.
*/
var RecordingsView = Heritage.extend(WidgetMethods, {
var RecordingsView = {
/**
* Initialization function, called when the tool is started.
*/
initialize: function () {
this.widget = new SideMenuWidget($("#recordings-list"));
this._onSelect = this._onSelect.bind(this);
this._onRecordingStateChange = this._onRecordingStateChange.bind(this);
this._onNewRecording = this._onNewRecording.bind(this);
@ -23,13 +21,75 @@ var RecordingsView = Heritage.extend(WidgetMethods, {
this._onRecordingDeleted = this._onRecordingDeleted.bind(this);
this._onRecordingExported = this._onRecordingExported.bind(this);
this.emptyText = L10N.getStr("noRecordingsText");
PerformanceController.on(EVENTS.RECORDING_STATE_CHANGE, this._onRecordingStateChange);
PerformanceController.on(EVENTS.RECORDING_ADDED, this._onNewRecording);
PerformanceController.on(EVENTS.RECORDING_DELETED, this._onRecordingDeleted);
PerformanceController.on(EVENTS.RECORDING_EXPORTED, this._onRecordingExported);
this.widget.addEventListener("select", this._onSelect, false);
// DE-XUL: Begin migrating the recording sidebar to React. Temporarily hold state
// here.
this._listState = {
recordings: [],
labels: new WeakMap(),
selected: null,
};
this._listMount = PerformanceUtils.createHtmlMount($("#recording-list-mount"));
this._renderList();
},
/**
* Get the index of the currently selected recording. Only used by tests.
* @return {integer} index
*/
getSelectedIndex() {
const { recordings, selected } = this._listState;
return recordings.indexOf(selected);
},
/**
* Set the currently selected recording via its index. Only used by tests.
* @param {integer} index
*/
setSelectedByIndex(index) {
this._onSelect(this._listState.recordings[index]);
this._renderList();
},
/**
* DE-XUL: During the migration, this getter will access the selected recording from
* the private _listState object so that tests will continue to pass.
*/
get selected() {
return this._listState.selected;
},
/**
* DE-XUL: During the migration, this getter will access the number of recordings.
*/
get itemCount() {
return this._listState.recordings.length;
},
/**
* DE-XUL: Render the recording list using React.
*/
_renderList: function () {
const {recordings, labels, selected} = this._listState;
const recordingList = RecordingList({
itemComponent: RecordingListItem,
items: recordings.map(recording => ({
onSelect: () => this._onSelect(recording),
onSave: () => this._onSaveButtonClick(recording),
isLoading: !recording.isRecording() && !recording.isCompleted(),
isRecording: recording.isRecording(),
isSelected: recording === selected,
duration: recording.getDuration().toFixed(0),
label: labels.get(recording),
}))
});
ReactDOM.render(recordingList, this._listMount);
},
/**
@ -41,56 +101,6 @@ var RecordingsView = Heritage.extend(WidgetMethods, {
PerformanceController.off(EVENTS.RECORDING_ADDED, this._onNewRecording);
PerformanceController.off(EVENTS.RECORDING_DELETED, this._onRecordingDeleted);
PerformanceController.off(EVENTS.RECORDING_EXPORTED, this._onRecordingExported);
this.widget.removeEventListener("select", this._onSelect, false);
},
/**
* Adds an empty recording to this container.
*
* @param RecordingModel recording
* A model for the new recording item created.
*/
addEmptyRecording: function (recording) {
let titleNode = document.createElement("label");
titleNode.className = "plain recording-item-title";
titleNode.setAttribute("crop", "end");
titleNode.setAttribute("value", recording.getLabel() ||
L10N.getFormatStr("recordingsList.itemLabel", this.itemCount + 1));
let durationNode = document.createElement("label");
durationNode.className = "plain recording-item-duration";
durationNode.setAttribute("value",
L10N.getStr("recordingsList.recordingLabel"));
let saveNode = document.createElement("label");
saveNode.className = "plain recording-item-save";
saveNode.addEventListener("click", this._onSaveButtonClick);
let hspacer = document.createElement("spacer");
hspacer.setAttribute("flex", "1");
let footerNode = document.createElement("hbox");
footerNode.className = "recording-item-footer";
footerNode.appendChild(durationNode);
footerNode.appendChild(hspacer);
footerNode.appendChild(saveNode);
let vspacer = document.createElement("spacer");
vspacer.setAttribute("flex", "1");
let contentsNode = document.createElement("vbox");
contentsNode.className = "recording-item";
contentsNode.setAttribute("flex", "1");
contentsNode.appendChild(titleNode);
contentsNode.appendChild(vspacer);
contentsNode.appendChild(footerNode);
// Append a recording item to this container.
return this.push([contentsNode], {
// Store the recording model that contains all the data to be
// rendered in the item.
attachment: recording
});
},
/**
@ -112,85 +122,55 @@ var RecordingsView = Heritage.extend(WidgetMethods, {
* Model of the recording that was started.
*/
_onRecordingStateChange: function (_, state, recording) {
let recordingItem = this.getItemForPredicate(e => e.attachment === recording);
if (!recordingItem) {
recordingItem = this.addEmptyRecording(recording);
const { recordings, labels } = this._listState;
if (!recordings.includes(recording)) {
recordings.push(recording);
labels.set(recording, recording.getLabel() ||
L10N.getFormatStr("recordingsList.itemLabel", recordings.length));
// If this is a manual recording, immediately select it, or
// select a console profile if its the only one
if (!recording.isConsole() || this.selectedIndex === -1) {
this.selectedItem = recordingItem;
if (!recording.isConsole() || !this._listState.selected) {
this._onSelect(recording);
}
}
recordingItem.isRecording = recording.isRecording();
// This recording is in the process of stopping.
if (!recording.isRecording() && !recording.isCompleted()) {
// Mark the corresponding item as loading.
let durationNode = $(".recording-item-duration", recordingItem.target);
durationNode.setAttribute("value", L10N.getStr("recordingsList.loadingLabel"));
// Determine if the recording needs to be selected.
const isCompletedManualRecording = !recording.isConsole() && recording.isCompleted();
if (recording.isImported() || isCompletedManualRecording) {
this._onSelect(recording);
}
// Render the recording item with finalized information (timing, etc)
if (recording.isCompleted() && !recordingItem.finalized) {
this.finalizeRecording(recordingItem);
// Select the recording if it was a manual recording only
if (!recording.isConsole()) {
this.forceSelect(recordingItem);
}
}
// Auto select imported items.
if (recording.isImported()) {
this.selectedItem = recordingItem;
}
this._renderList();
},
/**
* Clears out all non-console recordings.
*/
_onRecordingDeleted: function (_, recording) {
let recordingItem = this.getItemForPredicate(e => e.attachment === recording);
this.remove(recordingItem);
},
/**
* Adds recording data to a recording item in this container.
*
* @param Item recordingItem
* An item inserted via `RecordingsView.addEmptyRecording`.
*/
finalizeRecording: function (recordingItem) {
let model = recordingItem.attachment;
recordingItem.finalized = true;
let saveNode = $(".recording-item-save", recordingItem.target);
saveNode.setAttribute("value",
L10N.getStr("recordingsList.saveLabel"));
let durationMillis = model.getDuration().toFixed(0);
let durationNode = $(".recording-item-duration", recordingItem.target);
durationNode.setAttribute("value",
L10N.getFormatStr("recordingsList.durationLabel", durationMillis));
const { recordings } = this._listState;
const index = recordings.indexOf(recording);
if (index === -1) {
throw new Error("Attempting to remove a recording that doesn't exist.");
}
recordings.splice(index, 1);
this._renderList();
},
/**
* The select listener for this container.
*/
_onSelect: Task.async(function* ({ detail: recordingItem }) {
if (!recordingItem) {
return;
}
let model = recordingItem.attachment;
this.emit(EVENTS.UI_RECORDING_SELECTED, model);
_onSelect: Task.async(function* (recording) {
this._listState.selected = recording;
this.emit(EVENTS.UI_RECORDING_SELECTED, recording);
this._renderList();
}),
/**
* The click listener for the "save" button of each item in this container.
*/
_onSaveButtonClick: function (e) {
_onSaveButtonClick: function (recording) {
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(window, L10N.getStr("recordingsList.saveDialogTitle"),
Ci.nsIFilePicker.modeSave);
@ -202,8 +182,7 @@ var RecordingsView = Heritage.extend(WidgetMethods, {
if (result == Ci.nsIFilePicker.returnCancel) {
return;
}
let recordingItem = this.getItemForElement(e.target);
this.emit(EVENTS.UI_EXPORT_RECORDING, recordingItem.attachment, fp.file);
this.emit(EVENTS.UI_EXPORT_RECORDING, recording, fp.file);
}});
},
@ -211,13 +190,11 @@ var RecordingsView = Heritage.extend(WidgetMethods, {
if (recording.isConsole()) {
return;
}
let recordingItem = this.getItemForPredicate(e => e.attachment === recording);
let titleNode = $(".recording-item-title", recordingItem.target);
titleNode.setAttribute("value", file.leafName.replace(/\..+$/, ""));
},
toString: () => "[object RecordingsView]"
});
const name = file.leafName.replace(/\..+$/, "");
this._listState.labels.set(recording, name);
this._renderList();
}
};
/**
* Convenient way of emitting events from the RecordingsView.

View File

@ -48,13 +48,8 @@ define(function (require, exports, module) {
// Make sure it's a string.
text = text + "";
// Use default limit if necessary.
if (!limit) {
limit = 50;
}
// Crop the string only if a limit is actually specified.
if (limit <= 0) {
if (!limit || limit <= 0) {
return text;
}

View File

@ -36,7 +36,7 @@ window.onload = Task.async(function* () {
function testMultiline() {
const renderedComponent = renderComponent(StringRep.rep, { object: getGripStub("testMultiline") });
is(renderedComponent.textContent, "\"aaaaaaaaaaaaaaaaaaaaa\\nbbbbbbbbb\\ncccccccccccccccc\\n\"", "String rep has expected text content for multiline string");
is(renderedComponent.textContent, "\"aaaaaaaaaaaaaaaaaaaaa\\nbbbbbbbbbbbbbbbbbbb\\ncccccccccccccccc\\n\"", "String rep has expected text content for multiline string");
}
function testMultilineLimit() {

View File

@ -144,33 +144,81 @@
line-height: 0;
}
#recordings-list {
max-width: 300px;
.theme-sidebar {
position: relative;
}
.recording-item {
padding: 4px;
/**
* DE-XUL: This is probably only needed for the html:div inside of a vbox.
*/
#recordings-list > div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
}
.recording-item-title {
.recording-list {
width: var(--sidebar-width);
min-width: var(--sidebar-width);
margin: 0;
padding: 0;
background-color: var(--theme-sidebar-background);
border-inline-end: 1px solid var(--theme-splitter-color);
}
.recording-list-item {
display: flex;
flex-direction: column;
color: var(--theme-body-color);
border-bottom: 1px solid rgba(128,128,128,0.15);
padding: 8px;
cursor: default;
}
.recording-list-item.selected {
background-color: var(--theme-selection-background);
color: var(--theme-selection-color);
}
.recording-list-empty {
padding: 8px;
}
.recording-list-item-label {
font-size: 110%;
}
.recording-item-footer {
.recording-list-item-footer {
padding-top: 4px;
font-size: 90%;
display: flex;
justify-content: space-between;
}
.recording-item-save {
.recording-list-item-save {
background: none;
border: none;
text-decoration: underline;
cursor: pointer;
font-size: 90%;
padding:0;
}
.recording-item-duration,
.recording-item-save {
.recording-list-item-duration,
.recording-list-item-save {
color: var(--theme-body-color-alt);
}
.recording-list-item.selected .recording-list-item-duration,
.recording-list-item.selected .recording-list-item-save {
color: var(--theme-body-color-alt);
color: var(--theme-selection-color);
}
#recordings-list .selected label {
/* Text inside a selected item should not be custom colored. */
color: inherit !important;

View File

@ -77,7 +77,9 @@ var PostTab = React.createClass({
columns: [{id: "value"}],
object: json,
mode: "tiny",
renderValue: props => Rep(props)
renderValue: props => Rep(Object.assign({}, props, {
cropLimit: 50,
})),
}),
name: Locale.$STR("jsonScopeName")
};

View File

@ -105,7 +105,9 @@ var ResponseTab = React.createClass({
columns: [{id: "value"}],
object: json,
mode: "tiny",
renderValue: props => Rep(props)
renderValue: props => Rep(Object.assign({}, props, {
cropLimit: 50,
})),
}),
name: Locale.$STR("jsonScopeName")
};

View File

@ -60,7 +60,9 @@ function pushPrefEnv() {
let options = {
"set": [
["security.mixed_content.block_active_content", true],
["security.mixed_content.block_display_content", true]
["security.mixed_content.block_display_content", true],
["security.mixed_content.use_hsts", false],
["security.mixed_content.send_hsts_priming", false],
]
};
SpecialPowers.pushPrefEnv(options, deferred.resolve);

View File

@ -94,6 +94,13 @@ function testXhrWarn() {
});
let lastRequest = yield waitForFinishedRequest(XHR_WARN_REQUEST_PREDICATE);
if (lastRequest.request.method == "HEAD") {
// in non-e10s, we get the HEAD request that priming sends, so make sure
// a priming request should be sent, and then get the actual request
is(Services.prefs.getBoolPref("security.mixed_content.send_hsts_priming"),
true, "Found HSTS Priming Request");
lastRequest = yield waitForFinishedRequest(XHR_WARN_REQUEST_PREDICATE);
}
ok(lastRequest, "testXhrWarn() was logged");
is(lastRequest.request.method, "GET", "Method is correct");

View File

@ -380,7 +380,8 @@ exports.defineLazyGetter(this, "NetworkHelper", () => {
* - window: the window to get the loadGroup from
* - charset: the charset to use if the channel doesn't provide one
* - principal: the principal to use, if omitted, the request is loaded
* with the system principal
* with a codebase principal corresponding to the url being
* loaded, using the origin attributes of the window, if any.
* - cacheKey: when loading from cache, use this key to retrieve a cache
* specific to a given SHEntry. (Allows loading POST
* requests from cache)
@ -526,51 +527,44 @@ function mainThreadFetch(aURL, aOptions = { loadFromCache: true,
*/
function newChannelForURL(url, { policy, window, principal }) {
var securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
if (window) {
// Respect private browsing.
var req = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocumentLoader)
.loadGroup;
if (req) {
var nc = req.notificationCallbacks;
if (nc) {
try {
var lc = nc.getInterface(Ci.nsILoadContext);
if (lc) {
if (lc.usePrivateBrowsing) {
securityFlags |= Ci.nsILoadInfo.SEC_FORCE_PRIVATE_BROWSING;
}
}
} catch (ex) {}
}
}
}
let channelOptions = {
contentPolicyType: policy,
securityFlags: securityFlags,
uri: url
};
if (principal) {
// contentPolicyType is required when loading with a custom principal
if (!channelOptions.contentPolicyType) {
channelOptions.contentPolicyType = Ci.nsIContentPolicy.TYPE_OTHER;
}
channelOptions.loadingPrincipal = principal;
} else {
channelOptions.loadUsingSystemPrincipal = true;
}
let uri;
try {
return NetUtil.newChannel(channelOptions);
uri = Services.io.newURI(url, null, null);
} catch (e) {
// In the xpcshell tests, the script url is the absolute path of the test
// file, which will make a malformed URI error be thrown. Add the file
// scheme to see if it helps.
channelOptions.uri = "file://" + url;
uri = Services.io.newURI("file://" + url, null, null);
}
let channelOptions = {
contentPolicyType: policy,
securityFlags: securityFlags,
uri: uri
};
let prin = principal;
if (!prin) {
let oa = {};
if (window) {
oa = window.document.nodePrincipal.originAttributes;
}
prin = Services.scriptSecurityManager
.createCodebasePrincipal(uri, oa);
}
// contentPolicyType is required when specifying a principal
if (!channelOptions.contentPolicyType) {
channelOptions.contentPolicyType = Ci.nsIContentPolicy.TYPE_OTHER;
}
channelOptions.loadingPrincipal = prin;
try {
return NetUtil.newChannel(channelOptions);
} catch (e) {
// In xpcshell tests on Windows, nsExternalProtocolHandler::NewChannel()
// can throw NS_ERROR_UNKNOWN_PROTOCOL if the external protocol isn't
// supported by Windows, so we also need to handle the exception here if
// parsing the URL above doesn't throw.
return newChannelForURL("file://" + url, { policy, window, principal });
}
}

View File

@ -4986,10 +4986,10 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI,
flags, &isStsHost);
flags, nullptr, &isStsHost);
NS_ENSURE_SUCCESS(rv, rv);
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HPKP, aURI,
flags, &isPinnedHost);
flags, nullptr, &isPinnedHost);
NS_ENSURE_SUCCESS(rv, rv);
} else {
mozilla::dom::ContentChild* cc =
@ -9862,6 +9862,25 @@ nsDocShell::InternalLoad(nsIURI* aURI,
return NS_ERROR_CONTENT_BLOCKED;
}
// If HSTS priming was set by nsMixedContentBlocker::ShouldLoad, and we
// would block due to mixed content, go ahead and block here. If we try to
// proceed with priming, we will error out later on.
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(context);
NS_ENSURE_TRUE(docShell, NS_OK);
if (docShell) {
nsIDocument* document = docShell->GetDocument();
NS_ENSURE_TRUE(document, NS_OK);
HSTSPrimingState state = document->GetHSTSPrimingStateForLocation(aURI);
if (state == HSTSPrimingState::eHSTS_PRIMING_BLOCK) {
// HSTS Priming currently disabled for InternalLoad, so we need to clear
// the location that was added by nsMixedContentBlocker::ShouldLoad
// Bug 1269815 will address images loaded via InternalLoad
document->ClearHSTSPrimingLocation(aURI);
return NS_ERROR_CONTENT_BLOCKED;
}
}
nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
//
// Get a principal from the current document if necessary. Note that we only
@ -10838,10 +10857,6 @@ nsDocShell::DoURILoad(nsIURI* aURI,
securityFlags |= nsILoadInfo::SEC_SANDBOXED;
}
if (UsePrivateBrowsing()) {
securityFlags |= nsILoadInfo::SEC_FORCE_PRIVATE_BROWSING;
}
nsCOMPtr<nsILoadInfo> loadInfo =
(aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) ?
new LoadInfo(loadingWindow, triggeringPrincipal,

View File

@ -21,7 +21,8 @@
#include "nsIUUIDGenerator.h"
#include "nsPIDOMWindow.h" // for use in inline functions
#include "nsPropertyTable.h" // for member
#include "nsTHashtable.h" // for member
#include "nsDataHashtable.h" // for member
#include "nsURIHashKey.h" // for member
#include "mozilla/net/ReferrerPolicy.h" // for member
#include "nsWeakReference.h"
#include "mozilla/UseCounter.h"
@ -175,6 +176,13 @@ enum DocumentFlavor {
DocumentFlavorPlain, // Just a Document
};
// Enum for HSTS priming states
enum class HSTSPrimingState {
eNO_HSTS_PRIMING = 0, // don't do HSTS Priming
eHSTS_PRIMING_ALLOW = 1, // if HSTS priming fails, allow the load to proceed
eHSTS_PRIMING_BLOCK = 2 // if HSTS priming fails, block the load
};
// Document states
// RTL locale: specific to the XUL localedir attribute
@ -364,6 +372,34 @@ public:
mReferrer = aReferrer;
}
/**
* Check to see if a subresource we want to load requires HSTS priming
* to be done.
*/
HSTSPrimingState GetHSTSPrimingStateForLocation(nsIURI* aContentLocation) const
{
HSTSPrimingState state;
if (mHSTSPrimingURIList.Get(aContentLocation, &state)) {
return state;
}
return HSTSPrimingState::eNO_HSTS_PRIMING;
}
/**
* Add a subresource to the HSTS priming list. If this URI is
* not in the HSTS cache, it will trigger an HSTS priming request
* when we try to load it.
*/
void AddHSTSPrimingLocation(nsIURI* aContentLocation, HSTSPrimingState aState)
{
mHSTSPrimingURIList.Put(aContentLocation, aState);
}
void ClearHSTSPrimingLocation(nsIURI* aContentLocation)
{
mHSTSPrimingURIList.Remove(aContentLocation);
}
/**
* Set the principal responsible for this document.
*/
@ -2768,16 +2804,6 @@ public:
return mHasScrollLinkedEffect;
}
bool MayHavePluginFramesForPrinting()
{
return mMayHavePluginFramesForPrinting;
}
void SetMayHavePluginFramesForPrinting()
{
mMayHavePluginFramesForPrinting = true;
}
protected:
bool GetUseCounter(mozilla::UseCounter aUseCounter)
{
@ -2866,6 +2892,11 @@ protected:
bool mUpgradeInsecureRequests;
bool mUpgradeInsecurePreloads;
// if nsMixedContentBlocker requires sending an HSTS priming request,
// temporarily store that in the document so that it can be propogated to the
// LoadInfo and eventually the HTTP Channel
nsDataHashtable<nsURIHashKey, HSTSPrimingState> mHSTSPrimingURIList;
mozilla::WeakPtr<nsDocShell> mDocumentContainer;
nsCString mCharacterSet;
@ -3074,10 +3105,6 @@ protected:
// True is document has ever been in a foreground window.
bool mEverInForeground : 1;
// True if this document is a static clone for printing and may
// have elements referring to plugins in the original document.
bool mMayHavePluginFramesForPrinting : 1;
enum Type {
eUnknown, // should never be used
eHTML,

View File

@ -1765,7 +1765,8 @@ nsINode::Before(const Sequence<OwningNodeOrString>& aNodes,
return;
}
nsINode* viablePreviousSibling = FindViablePreviousSibling(*this, aNodes);
nsCOMPtr<nsINode> viablePreviousSibling =
FindViablePreviousSibling(*this, aNodes);
nsCOMPtr<nsINode> node =
ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);
@ -1788,7 +1789,7 @@ nsINode::After(const Sequence<OwningNodeOrString>& aNodes,
return;
}
nsINode* viableNextSibling = FindViableNextSibling(*this, aNodes);
nsCOMPtr<nsINode> viableNextSibling = FindViableNextSibling(*this, aNodes);
nsCOMPtr<nsINode> node =
ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);
@ -1808,7 +1809,7 @@ nsINode::ReplaceWith(const Sequence<OwningNodeOrString>& aNodes,
return;
}
nsINode* viableNextSibling = FindViableNextSibling(*this, aNodes);
nsCOMPtr<nsINode> viableNextSibling = FindViableNextSibling(*this, aNodes);
nsCOMPtr<nsINode> node =
ConvertNodesOrStringsIntoNode(aNodes, OwnerDoc(), aRv);

View File

@ -2907,13 +2907,9 @@ nsObjectLoadingContent::CreateStaticClone(nsObjectLoadingContent* aDest) const
aDest->mPrintFrame = const_cast<nsObjectLoadingContent*>(this)->GetExistingFrame();
}
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(aDest));
if (aDest->mPrintFrame) {
content->OwnerDoc()->SetMayHavePluginFramesForPrinting();
}
if (mFrameLoader) {
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(aDest));
nsFrameLoader* fl = nsFrameLoader::Create(content->AsElement(), false);
if (fl) {
aDest->mFrameLoader = fl;

View File

@ -194,6 +194,12 @@ function createPolicyTest(policy, optionalEarlierPolicy) {
}
function handleRequest(request, response) {
if (request.method == 'HEAD') {
// respond to a HEAD request with a 418 so that we can easily distinguish
// HSTS priming responses and ignore them
response.setStatusLine('1.1', 418, "I'm a teapot");
return;
}
var sharedKey = 'bug704320.sjs';
var params = request.queryString.split('&');
var action = params[0].split('=')[1];

View File

@ -25,6 +25,9 @@ function doXHR(url, onSuccess, onFail) {
xhr.onload = function () {
if (xhr.status == 200) {
onSuccess(xhr);
} else if (xhr.status == 418) {
// Ignore HSTS priming responses
return;
} else {
onFail(xhr);
}

View File

@ -94,7 +94,7 @@ MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, JSEXN_TYPEERR, "{0} can't be a typed array on SharedArrayBuffer")
MSG_DEF(MSG_CACHE_ADD_FAILED_RESPONSE, 3, JSEXN_TYPEERR, "Cache got {0} response with bad status {1} while trying to add request {2}")
MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 2, JSEXN_TYPEERR, "Failed to update the ServiceWorker for scope {0] because the registration has been {1} since the update was scheduled.")
MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 2, JSEXN_TYPEERR, "Failed to update the ServiceWorker for scope {0} because the registration has been {1} since the update was scheduled.")
MSG_DEF(MSG_INVALID_DURATION_ERROR, 1, JSEXN_TYPEERR, "Invalid duration '{0}'.")
MSG_DEF(MSG_INVALID_EASING_ERROR, 1, JSEXN_TYPEERR, "Invalid easing '{0}'.")
MSG_DEF(MSG_INVALID_SPACING_MODE_ERROR, 1, JSEXN_TYPEERR, "Invalid spacing '{0}'.")

View File

@ -5768,6 +5768,8 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t aX, int32_t aY, uint32_t
//uint8_t *src = aArray->Data();
uint8_t *dst = imgsurf->Data();
uint8_t* srcLine = aArray->Data() + copyY * (aW * 4) + copyX * 4;
// For opaque canvases, we must still premultiply the RGB components, but write the alpha as opaque.
uint8_t alphaMask = mOpaque ? 255 : 0;
#if 0
printf("PutImageData_explicit: dirty x=%d y=%d w=%d h=%d copy x=%d y=%d w=%d h=%d ext x=%d y=%d w=%d h=%d\n",
dirtyRect.x, dirtyRect.y, copyWidth, copyHeight,
@ -5787,9 +5789,9 @@ CanvasRenderingContext2D::PutImageData_explicit(int32_t aX, int32_t aY, uint32_t
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + b];
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + g];
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + r];
*dst++ = a;
*dst++ = a | alphaMask;
#else
*dst++ = a;
*dst++ = a | alphaMask;
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + r];
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + g];
*dst++ = gfxUtils::sPremultiplyTable[a * 256 + b];

View File

@ -569,7 +569,7 @@ BaseCaps(const WebGLContextOptions& options, WebGLContext* webgl)
if (!forwarder)
break;
baseCaps.surfaceAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
baseCaps.surfaceAllocator = forwarder->GetTextureForwarder();
} while (false);
#endif

View File

@ -0,0 +1,5 @@
<canvas id='cid'></canvas>
<script>
var x=document.getElementById('cid').getContext('2d',{alpha: false});
x.putImageData(x.createImageData(250,27434.63),Number.MAX_SAFE_INTEGER,23);
</script>

View File

@ -37,4 +37,5 @@ load 1290628-1.html
load 1283113-1.html
load 1286458-1.html
load 1299062-1.html
load 1305312-1.html

View File

@ -439,10 +439,16 @@ TextComposition::GetSelectionStartOffset()
{
nsCOMPtr<nsIWidget> widget = mPresContext->GetRootWidget();
WidgetQueryContentEvent selectedTextEvent(true, eQuerySelectedText, widget);
if (mRanges && mRanges->HasClauses()) {
// Due to a bug of widget, mRanges may not be nullptr even though composition
// string is empty. So, we need to check it here for avoiding to return
// odd start offset.
if (!mLastData.IsEmpty() && mRanges && mRanges->HasClauses()) {
selectedTextEvent.InitForQuerySelectedText(
ToSelectionType(mRanges->GetFirstClause()->mRangeType));
} else {
NS_WARNING_ASSERTION(
!mLastData.IsEmpty() || !mRanges || !mRanges->HasClauses(),
"Shouldn't have empty clause info when composition string is empty");
selectedTextEvent.InitForQuerySelectedText(SelectionType::eNormal);
}

View File

@ -3442,7 +3442,7 @@ HTMLInputElement::Focus(ErrorResult& aError)
return;
}
#if defined(XP_WIN) || defined(XP_LINUX)
#if !defined(ANDROID) && !defined(XP_MACOSX)
bool
HTMLInputElement::IsNodeApzAwareInternal() const
{
@ -4538,7 +4538,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
}
break;
}
#if defined(XP_WIN) || defined(XP_LINUX)
#if !defined(ANDROID) && !defined(XP_MACOSX)
case eWheel: {
// Handle wheel events as increasing / decreasing the input element's
// value when it's focused and it's type is number or range.
@ -6203,7 +6203,7 @@ FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
void
HTMLInputElement::UpdateApzAwareFlag()
{
#if defined(XP_WIN) || defined(XP_LINUX)
#if !defined(ANDROID) && !defined(XP_MACOSX)
if ((mType == NS_FORM_INPUT_NUMBER) || (mType == NS_FORM_INPUT_RANGE)) {
SetMayBeApzAware();
}

View File

@ -135,7 +135,7 @@ public:
virtual void Focus(ErrorResult& aError) override;
// nsINode
#if defined(XP_WIN) || defined(XP_LINUX)
#if !defined(ANDROID) && !defined(XP_MACOSX)
virtual bool IsNodeApzAwareInternal() const override;
#endif

View File

@ -565,16 +565,6 @@ public:
? nsIContentPolicy::TYPE_INTERNAL_AUDIO :
nsIContentPolicy::TYPE_INTERNAL_VIDEO;
nsCOMPtr<nsIDocShell> docShell = aElement->OwnerDoc()->GetDocShell();
if (docShell) {
nsDocShell* docShellPtr = nsDocShell::Cast(docShell);
bool privateBrowsing;
docShellPtr->GetUsePrivateBrowsing(&privateBrowsing);
if (privateBrowsing) {
securityFlags |= nsILoadInfo::SEC_FORCE_PRIVATE_BROWSING;
}
}
nsCOMPtr<nsILoadGroup> loadGroup = aElement->GetDocumentLoadGroup();
nsCOMPtr<nsIChannel> channel;
nsresult rv = NS_NewChannel(getter_AddRefs(channel),

View File

@ -622,11 +622,11 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
[test_bug1250401.html]
[test_bug1260664.html]
[test_bug1261673.html]
skip-if = (os != 'win' && os != 'linux')
skip-if = (os == 'android' || os == 'mac')
[test_bug1261674-1.html]
skip-if = (os != 'win' && os != 'linux')
skip-if = (os == 'android' || os == 'mac')
[test_bug1261674-2.html]
skip-if = (os != 'win' && os != 'linux')
skip-if = (os == 'android' || os == 'mac')
[test_bug1260704.html]
[test_allowMedia.html]
[test_bug1292522_same_domain_with_different_port_number.html]

View File

@ -41,11 +41,14 @@ let tests = [
Services.prefs.setBoolPref("browser.send_pings", true);
Services.prefs.setIntPref("browser.send_pings.max_per_link", -1);
Services.prefs.setBoolPref("security.mixed_content.block_active_content", false);
// The server we create can't handle the priming HEAD requests
Services.prefs.setBoolPref("security.mixed_content.send_hsts_priming", false);
SimpleTest.registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.send_pings");
Services.prefs.clearUserPref("browser.send_pings.max_per_link");
Services.prefs.clearUserPref("security.mixed_content.block_active_content");
Services.prefs.clearUserPref("security.mixed_content.send_hsts_priming");
});
},

View File

@ -5314,7 +5314,7 @@ private:
struct IdleThreadInfo;
struct ThreadInfo;
class ThreadRunnable;
struct TransactionInfo;
class TransactionInfo;
struct TransactionInfoPair;
// This mutex guards mDatabases, see below.
@ -5621,7 +5621,7 @@ protected:
IdleResource(const TimeStamp& aIdleTime);
explicit
IdleResource(const IdleResource& aOther);
IdleResource(const IdleResource& aOther) = delete;
~IdleResource();
};
@ -5636,7 +5636,7 @@ public:
IdleDatabaseInfo(DatabaseInfo* aDatabaseInfo);
explicit
IdleDatabaseInfo(const IdleDatabaseInfo& aOther);
IdleDatabaseInfo(const IdleDatabaseInfo& aOther) = delete;
~IdleDatabaseInfo();
@ -5665,7 +5665,7 @@ public:
IdleThreadInfo(const ThreadInfo& aThreadInfo);
explicit
IdleThreadInfo(const IdleThreadInfo& aOther);
IdleThreadInfo(const IdleThreadInfo& aOther) = delete;
~IdleThreadInfo();
@ -5713,10 +5713,14 @@ private:
NS_DECL_NSIRUNNABLE
};
struct ConnectionPool::TransactionInfo final
class ConnectionPool::TransactionInfo final
{
friend class nsAutoPtr<TransactionInfo>;
nsTHashtable<nsPtrHashKey<TransactionInfo>> mBlocking;
nsTArray<TransactionInfo*> mBlockingOrdered;
public:
DatabaseInfo* mDatabaseInfo;
const nsID mBackgroundChildLoggingId;
const nsCString mDatabaseId;
@ -5724,7 +5728,6 @@ struct ConnectionPool::TransactionInfo final
const int64_t mLoggingSerialNumber;
const nsTArray<nsString> mObjectStoreNames;
nsTHashtable<nsPtrHashKey<TransactionInfo>> mBlockedOn;
nsTHashtable<nsPtrHashKey<TransactionInfo>> mBlocking;
nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables;
const bool mIsWriteTransaction;
bool mRunning;
@ -5743,10 +5746,16 @@ struct ConnectionPool::TransactionInfo final
TransactionDatabaseOperationBase* aTransactionOp);
void
Schedule();
AddBlockingTransaction(TransactionInfo* aTransactionInfo);
void
RemoveBlockingTransactions();
private:
~TransactionInfo();
void
MaybeUnblock(TransactionInfo* aTransactionInfo);
};
struct ConnectionPool::TransactionInfoPair final
@ -11745,7 +11754,7 @@ ConnectionPool::Start(const nsID& aBackgroundChildLoggingId,
// Mark what we are blocking on.
if (TransactionInfo* blockingRead = blockInfo->mLastBlockingReads) {
transactionInfo->mBlockedOn.PutEntry(blockingRead);
blockingRead->mBlocking.PutEntry(transactionInfo);
blockingRead->AddBlockingTransaction(transactionInfo);
}
if (aIsWriteTransaction) {
@ -11756,7 +11765,7 @@ ConnectionPool::Start(const nsID& aBackgroundChildLoggingId,
MOZ_ASSERT(blockingWrite);
transactionInfo->mBlockedOn.PutEntry(blockingWrite);
blockingWrite->mBlocking.PutEntry(transactionInfo);
blockingWrite->AddBlockingTransaction(transactionInfo);
}
}
@ -12288,18 +12297,7 @@ ConnectionPool::NoteFinishedTransaction(uint64_t aTransactionId)
blockInfo->mLastBlockingWrites.RemoveElement(transactionInfo);
}
for (auto iter = transactionInfo->mBlocking.Iter();
!iter.Done();
iter.Next()) {
TransactionInfo* blockedInfo = iter.Get()->GetKey();
MOZ_ASSERT(blockedInfo);
MOZ_ASSERT(blockedInfo->mBlockedOn.Contains(transactionInfo));
blockedInfo->mBlockedOn.RemoveEntry(transactionInfo);
if (!blockedInfo->mBlockedOn.Count()) {
blockedInfo->Schedule();
}
}
transactionInfo->RemoveBlockingTransactions();
if (transactionInfo->mIsWriteTransaction) {
MOZ_ASSERT(dbInfo->mWriteTransactionCount);
@ -12969,16 +12967,6 @@ IdleResource::IdleResource(const TimeStamp& aIdleTime)
MOZ_COUNT_CTOR(ConnectionPool::IdleResource);
}
ConnectionPool::
IdleResource::IdleResource(const IdleResource& aOther)
: mIdleTime(aOther.mIdleTime)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(!aOther.mIdleTime.IsNull());
MOZ_COUNT_CTOR(ConnectionPool::IdleResource);
}
ConnectionPool::
IdleResource::~IdleResource()
{
@ -13001,17 +12989,6 @@ IdleDatabaseInfo::IdleDatabaseInfo(DatabaseInfo* aDatabaseInfo)
MOZ_COUNT_CTOR(ConnectionPool::IdleDatabaseInfo);
}
ConnectionPool::
IdleDatabaseInfo::IdleDatabaseInfo(const IdleDatabaseInfo& aOther)
: IdleResource(aOther)
, mDatabaseInfo(aOther.mDatabaseInfo)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(mDatabaseInfo);
MOZ_COUNT_CTOR(ConnectionPool::IdleDatabaseInfo);
}
ConnectionPool::
IdleDatabaseInfo::~IdleDatabaseInfo()
{
@ -13034,18 +13011,6 @@ IdleThreadInfo::IdleThreadInfo(const ThreadInfo& aThreadInfo)
MOZ_COUNT_CTOR(ConnectionPool::IdleThreadInfo);
}
ConnectionPool::
IdleThreadInfo::IdleThreadInfo(const IdleThreadInfo& aOther)
: IdleResource(aOther)
, mThreadInfo(aOther.mThreadInfo)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(mThreadInfo.mRunnable);
MOZ_ASSERT(mThreadInfo.mThread);
MOZ_COUNT_CTOR(ConnectionPool::IdleThreadInfo);
}
ConnectionPool::
IdleThreadInfo::~IdleThreadInfo()
{
@ -13101,18 +13066,55 @@ TransactionInfo::~TransactionInfo()
void
ConnectionPool::
TransactionInfo::Schedule()
TransactionInfo::AddBlockingTransaction(TransactionInfo* aTransactionInfo)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(mDatabaseInfo);
MOZ_ASSERT(aTransactionInfo);
ConnectionPool* connectionPool = mDatabaseInfo->mConnectionPool;
MOZ_ASSERT(connectionPool);
connectionPool->AssertIsOnOwningThread();
if (!mBlocking.Contains(aTransactionInfo)) {
mBlocking.PutEntry(aTransactionInfo);
mBlockingOrdered.AppendElement(aTransactionInfo);
}
}
Unused <<
connectionPool->ScheduleTransaction(this,
/* aFromQueuedTransactions */ false);
void
ConnectionPool::
TransactionInfo::RemoveBlockingTransactions()
{
AssertIsOnBackgroundThread();
for (uint32_t index = 0, count = mBlockingOrdered.Length();
index < count;
index++) {
TransactionInfo* blockedInfo = mBlockingOrdered[index];
MOZ_ASSERT(blockedInfo);
blockedInfo->MaybeUnblock(this);
}
mBlocking.Clear();
mBlockingOrdered.Clear();
}
void
ConnectionPool::
TransactionInfo::MaybeUnblock(TransactionInfo* aTransactionInfo)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(mBlockedOn.Contains(aTransactionInfo));
mBlockedOn.RemoveEntry(aTransactionInfo);
if (!mBlockedOn.Count()) {
MOZ_ASSERT(mDatabaseInfo);
ConnectionPool* connectionPool = mDatabaseInfo->mConnectionPool;
MOZ_ASSERT(connectionPool);
connectionPool->AssertIsOnOwningThread();
Unused <<
connectionPool->ScheduleTransaction(this,
/* aFromQueuedTransactions */ false);
}
}
ConnectionPool::

View File

@ -1554,7 +1554,8 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBObjectStore)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexes);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexes)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeletedIndexes)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBObjectStore)
@ -1562,7 +1563,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBObjectStore)
// Don't unlink mTransaction!
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexes);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexes)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDeletedIndexes)
tmp->mCachedKeyPath.setUndefined();
@ -1774,13 +1776,11 @@ IDBObjectStore::CreateIndex(const nsAString& aName,
}
IDBTransaction* transaction = IDBTransaction::GetCurrent();
if (!transaction || transaction != mTransaction) {
if (!transaction || transaction != mTransaction || !transaction->IsOpen()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return nullptr;
}
MOZ_ASSERT(transaction->IsOpen());
auto& indexes = const_cast<nsTArray<IndexMetadata>&>(mSpec->indexes());
for (uint32_t count = indexes.Length(), index = 0;
index < count;
@ -1888,13 +1888,11 @@ IDBObjectStore::DeleteIndex(const nsAString& aName, ErrorResult& aRv)
}
IDBTransaction* transaction = IDBTransaction::GetCurrent();
if (!transaction || transaction != mTransaction) {
if (!transaction || transaction != mTransaction || !transaction->IsOpen()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return;
}
MOZ_ASSERT(transaction->IsOpen());
auto& metadataArray = const_cast<nsTArray<IndexMetadata>&>(mSpec->indexes());
int64_t foundId = 0;
@ -1916,6 +1914,11 @@ IDBObjectStore::DeleteIndex(const nsAString& aName, ErrorResult& aRv)
if (index->Id() == foundId) {
index->NoteDeletion();
RefPtr<IDBIndex>* deletedIndex =
mDeletedIndexes.AppendElement();
deletedIndex->swap(mIndexes[indexIndex]);
mIndexes.RemoveElementAt(indexIndex);
break;
}
@ -2130,6 +2133,12 @@ IDBObjectStore::RefreshSpec(bool aMayDelete)
mIndexes[idxIndex]->RefreshMetadata(aMayDelete);
}
for (uint32_t idxCount = mDeletedIndexes.Length(), idxIndex = 0;
idxIndex < idxCount;
idxIndex++) {
mDeletedIndexes[idxIndex]->RefreshMetadata(false);
}
found = true;
break;
}
@ -2202,13 +2211,11 @@ IDBObjectStore::SetName(const nsAString& aName, ErrorResult& aRv)
}
IDBTransaction* transaction = IDBTransaction::GetCurrent();
if (!transaction || transaction != mTransaction) {
if (!transaction || transaction != mTransaction || !transaction->IsOpen()) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
return;
}
MOZ_ASSERT(transaction->IsOpen());
if (aName == mSpec->metadata().name()) {
return;
}

View File

@ -67,6 +67,7 @@ class IDBObjectStore final
nsAutoPtr<ObjectStoreSpec> mDeletedSpec;
nsTArray<RefPtr<IDBIndex>> mIndexes;
nsTArray<RefPtr<IDBIndex>> mDeletedIndexes;
const int64_t mId;
bool mRooted;

View File

@ -653,6 +653,12 @@ IDBTransaction::AbortInternal(nsresult aAbortCode,
mDatabase->RevertToPreviousState();
}
// We do the reversion only for the mObjectStores/mDeletedObjectStores but
// not for the mIndexes/mDeletedIndexes of each IDBObjectStore because it's
// time-consuming(O(m*n)) and mIndexes/mDeletedIndexes won't be used anymore
// in IDBObjectStore::(Create|Delete)Index() and IDBObjectStore::Index() in
// which all the executions are returned earlier by !transaction->IsOpen().
const nsTArray<ObjectStoreSpec>& specArray =
mDatabase->Spec()->objectStores();

View File

@ -19,6 +19,8 @@ support-files =
service_worker_client.html
third_party_iframe1.html
third_party_iframe2.html
unit/test_abort_deleted_index.js
unit/test_abort_deleted_objectStore.js
unit/test_add_put.js
unit/test_add_twice_failure.js
unit/test_advance.js
@ -115,6 +117,10 @@ support-files =
webapp_clearBrowserData_appFrame.html
webapp_clearBrowserData_browserFrame.html
[test_abort_deleted_index.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_abort_deleted_objectStore.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_add_put.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_add_twice_failure.html]

View File

@ -0,0 +1,19 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Abort Deleted Index Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7" src="unit/test_abort_deleted_index.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -0,0 +1,19 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Abort Deleted ObjectStore Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7" src="unit/test_abort_deleted_objectStore.js"></script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>

View File

@ -0,0 +1,78 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
const name = this.window ? window.location.pathname : "Splendid Test";
const storeName = "test store";
const indexName_ToBeDeleted = "test index to be deleted";
info("Create index in v1.");
let request = indexedDB.open(name, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = unexpectedSuccessHandler;
let event = yield undefined;
let db = event.target.result;
let txn = event.target.transaction;
is(db.objectStoreNames.length, 0, "Correct objectStoreNames list");
let objectStore = db.createObjectStore(storeName, { keyPath: "foo" });
is(db.objectStoreNames.length, 1, "Correct objectStoreNames list");
is(db.objectStoreNames.item(0), objectStore.name, "Correct object store name");
// create index to be deleted later in v2.
objectStore.createIndex(indexName_ToBeDeleted, "foo");
ok(objectStore.index(indexName_ToBeDeleted), "Index created.");
txn.oncomplete = continueToNextStepSync;
yield undefined;
request.onsuccess = continueToNextStep;
yield undefined;
db.close();
info("Delete index in v2.");
request = indexedDB.open(name, 2);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = unexpectedSuccessHandler;
event = yield undefined;
db = event.target.result;
txn = event.target.transaction;
objectStore = txn.objectStore(storeName);
let index = objectStore.index(indexName_ToBeDeleted);
ok(index, "index is valid.");
objectStore.deleteIndex(indexName_ToBeDeleted);
// Aborting the transaction.
request.onerror = expectedErrorHandler("AbortError");
txn.abort();
try {
index.get('foo');
ok(false, "TransactionInactiveError shall be thrown right after a deletion of an index is aborted.");
} catch (e) {
ok(e instanceof DOMException, "got a database exception");
is(e.name, "TransactionInactiveError", "TransactionInactiveError shall be thrown right after a deletion of an index is aborted.");
}
yield undefined;
try {
index.get('foo');
ok(false, "TransactionInactiveError shall be thrown after the transaction is inactive.");
} catch (e) {
ok(e instanceof DOMException, "got a database exception");
is(e.name, "TransactionInactiveError", "TransactionInactiveError shall be thrown after the transaction is inactive.");
}
finishTest();
yield undefined;
}

View File

@ -0,0 +1,74 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
const name = this.window ? window.location.pathname : "Splendid Test";
const storeName_ToBeDeleted = "test store to be deleted";
info("Create objectStore in v1.");
let request = indexedDB.open(name, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = unexpectedSuccessHandler;
let event = yield undefined;
let db = event.target.result;
let txn = event.target.transaction;
is(db.objectStoreNames.length, 0, "Correct objectStoreNames list");
// create objectstore to be deleted later in v2.
db.createObjectStore(storeName_ToBeDeleted, { keyPath: "foo" });
is(db.objectStoreNames.length, 1, "Correct objectStoreNames list");
ok(db.objectStoreNames.contains(storeName_ToBeDeleted), "Correct name");
txn.oncomplete = continueToNextStepSync;
yield undefined;
request.onsuccess = continueToNextStep;
yield undefined;
db.close();
info("Delete objectStore in v2.");
request = indexedDB.open(name, 2);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = unexpectedSuccessHandler;
event = yield undefined;
db = event.target.result;
txn = event.target.transaction;
let objectStore = txn.objectStore(storeName_ToBeDeleted);
ok(objectStore, "objectStore is available");
db.deleteObjectStore(storeName_ToBeDeleted);
// Aborting the transaction.
request.onerror = expectedErrorHandler("AbortError");
txn.abort();
try {
objectStore.get('foo');
ok(false, "TransactionInactiveError shall be thrown if the transaction is inactive.");
} catch (e) {
ok(e instanceof DOMException, "got a database exception");
is(e.name, "TransactionInactiveError", "correct error");
}
yield undefined;
try {
objectStore.get('foo');
ok(false, "TransactionInactiveError shall be thrown if the transaction is inactive.");
} catch (e) {
ok(e instanceof DOMException, "got a database exception");
is(e.name, "TransactionInactiveError", "correct error");
}
finishTest();
yield undefined;
}

View File

@ -2,6 +2,8 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
[test_abort_deleted_index.js]
[test_abort_deleted_objectStore.js]
[test_add_put.js]
[test_add_twice_failure.js]
[test_advance.js]

View File

@ -3574,10 +3574,7 @@ BlobChild::SetMysteryBlobInfo(const nsString& aContentType, uint64_t aLength)
MOZ_ASSERT(mBlobImpl);
MOZ_ASSERT(mRemoteBlobImpl);
nsString voidString;
voidString.SetIsVoid(true);
mBlobImpl->SetLazyData(voidString, aContentType, aLength, INT64_MAX);
mBlobImpl->SetLazyData(NullString(), aContentType, aLength, INT64_MAX);
NormalBlobConstructorParams params(aContentType,
aLength,
@ -4400,10 +4397,7 @@ BlobParent::RecvResolveMystery(const ResolveMysteryParams& aParams)
return false;
}
nsString voidString;
voidString.SetIsVoid(true);
mBlobImpl->SetLazyData(voidString,
mBlobImpl->SetLazyData(NullString(),
params.contentType(),
params.length(),
INT64_MAX);

View File

@ -822,14 +822,15 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
renderFrame = nullptr;
}
ShowInfo showInfo(EmptyString(), false, false, true, false, 0, 0);
ShowInfo showInfo(EmptyString(), false, false, true, false, 0, 0, 0);
auto* opener = nsPIDOMWindowOuter::From(aParent);
nsIDocShell* openerShell;
if (opener && (openerShell = opener->GetDocShell())) {
nsCOMPtr<nsILoadContext> context = do_QueryInterface(openerShell);
showInfo = ShowInfo(EmptyString(), false,
context->UsePrivateBrowsing(), true, false,
aTabOpener->mDPI, aTabOpener->mDefaultScale);
aTabOpener->mDPI, aTabOpener->mRounding,
aTabOpener->mDefaultScale);
}
// Unfortunately we don't get a window unless we've shown the frame. That's

View File

@ -3901,18 +3901,18 @@ ContentParent::RecvIsSecureURI(const uint32_t& type,
if (!ourURI) {
return false;
}
nsresult rv = sss->IsSecureURI(type, ourURI, flags, isSecureURI);
nsresult rv = sss->IsSecureURI(type, ourURI, flags, nullptr, isSecureURI);
return NS_SUCCEEDED(rv);
}
bool
ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive)
ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool& aActive, const bool& aHSTSPriming)
{
nsCOMPtr<nsIURI> ourURI = DeserializeURI(aURI);
if (!ourURI) {
return false;
}
nsMixedContentBlocker::AccumulateMixedContentHSTS(ourURI, aActive);
nsMixedContentBlocker::AccumulateMixedContentHSTS(ourURI, aActive, aHSTSPriming);
return true;
}

View File

@ -789,7 +789,8 @@ private:
const uint32_t& aFlags, bool* aIsSecureURI) override;
virtual bool RecvAccumulateMixedContentHSTS(const URIParams& aURI,
const bool& aActive) override;
const bool& aActive,
const bool& aHSTSPriming) override;
virtual bool DeallocPHalParent(PHalParent*) override;

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