Update On Thu Feb 2 19:59:58 CET 2023

This commit is contained in:
github-action[bot] 2023-02-02 19:59:59 +01:00
parent e7c7490f12
commit 8a51308b35
1885 changed files with 39478 additions and 13405 deletions

19
Cargo.lock generated
View file

@ -2082,7 +2082,7 @@ dependencies = [
[[package]]
name = "geckodriver"
version = "0.32.0"
version = "0.32.1"
dependencies = [
"base64",
"chrono",
@ -2887,7 +2887,6 @@ version = "0.1.0"
dependencies = [
"jsrust_shared",
"mozglue-static",
"wasmparser",
"wast",
]
@ -3202,7 +3201,7 @@ dependencies = [
[[package]]
name = "marionette"
version = "0.2.0"
version = "0.2.1"
dependencies = [
"serde",
"serde_json",
@ -3507,7 +3506,7 @@ dependencies = [
[[package]]
name = "mozdevice"
version = "0.5.0"
version = "0.5.1"
dependencies = [
"log",
"once_cell",
@ -3545,14 +3544,14 @@ dependencies = [
[[package]]
name = "mozprofile"
version = "0.9.0"
version = "0.9.1"
dependencies = [
"tempfile",
]
[[package]]
name = "mozrunner"
version = "0.15.0"
version = "0.15.1"
dependencies = [
"dirs",
"log",
@ -3574,7 +3573,7 @@ dependencies = [
[[package]]
name = "mozversion"
version = "0.5.0"
version = "0.5.1"
dependencies = [
"regex",
"rust-ini",
@ -3597,7 +3596,7 @@ dependencies = [
[[package]]
name = "mp4parse"
version = "0.16.0"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=eb0b625bd7e888d05ebcfc7685e2501b34c3b374#eb0b625bd7e888d05ebcfc7685e2501b34c3b374"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=40763b69d75e14abaa25c6438271eb552dc2b9e9#40763b69d75e14abaa25c6438271eb552dc2b9e9"
dependencies = [
"bitreader",
"byteorder",
@ -3614,7 +3613,7 @@ version = "0.1.0"
[[package]]
name = "mp4parse_capi"
version = "0.16.0"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=eb0b625bd7e888d05ebcfc7685e2501b34c3b374#eb0b625bd7e888d05ebcfc7685e2501b34c3b374"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=40763b69d75e14abaa25c6438271eb552dc2b9e9#40763b69d75e14abaa25c6438271eb552dc2b9e9"
dependencies = [
"byteorder",
"fallible_collections",
@ -6176,7 +6175,7 @@ version = "0.3.100"
[[package]]
name = "webdriver"
version = "0.47.0"
version = "0.47.1"
dependencies = [
"base64",
"bytes 1.3.0",

View file

@ -847,11 +847,11 @@ function getTextFromClipboard() {
return "";
}
trans.addDataFlavor("text/unicode");
trans.addDataFlavor("text/plain");
Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
var str = {};
trans.getTransferData("text/unicode", str);
trans.getTransferData("text/plain", str);
if (str) {
str = str.value.QueryInterface(Ci.nsISupportsString);

View file

@ -1379,7 +1379,7 @@ var PlacesToolbarHelper = {
}
addData(PlacesUtils.TYPE_X_MOZ_URL, 0);
addData(PlacesUtils.TYPE_UNICODE, 0);
addData(PlacesUtils.TYPE_PLAINTEXT, 0);
addData(PlacesUtils.TYPE_HTML, 0);
},
};

View file

@ -3176,7 +3176,7 @@ function readFromClipboard() {
);
trans.init(getLoadContext());
trans.addDataFlavor("text/unicode");
trans.addDataFlavor("text/plain");
// If available, use selection clipboard, otherwise global one
let clipboard = Services.clipboard;
@ -3187,7 +3187,7 @@ function readFromClipboard() {
}
var data = {};
trans.getTransferData("text/unicode", data);
trans.getTransferData("text/plain", data);
if (data) {
data = data.value.QueryInterface(Ci.nsISupportsString);

View file

@ -329,7 +329,7 @@
return this._featureCalloutPanelId;
},
_instantiateFeatureCalloutTour(location, panelId) {
_instantiateFeatureCalloutTour(browser, panelId) {
this._featureCalloutPanelId = panelId;
const { FeatureCallout } = ChromeUtils.importESModule(
"resource:///modules/FeatureCallout.sys.mjs"
@ -338,6 +338,7 @@
// only use PDF.js pref value when navigating to PDF viewer
this._featureCallout = new FeatureCallout({
win: window,
browser,
prefName: "browser.pdfjs.feature-tour",
page: "chrome",
});
@ -1079,7 +1080,7 @@
this._featureCallout &&
this._featureCalloutPanelId !== newTab.linkedPanel
) {
this._featureCallout._endTour(true);
this._featureCallout.endTour(true);
this._featureCallout = null;
}
@ -1090,10 +1091,7 @@
!this._featureCallout &&
newBrowser.currentURI.spec.endsWith(".pdf")
) {
this._instantiateFeatureCalloutTour(
newBrowser.currentURI,
newTab.linkedPanel
);
this._instantiateFeatureCalloutTour(newBrowser, newTab.linkedPanel);
window.gBrowser.featureCallout.showFeatureCallout();
}
@ -6758,7 +6756,7 @@
gBrowser.selectedTab.linkedPanel ||
!aLocation.spec.endsWith(".pdf"))
) {
gBrowser.featureCallout._endTour(true);
gBrowser.featureCallout.endTour(true);
gBrowser.featureCallout = null;
}
@ -6767,7 +6765,7 @@
// for callout messages on every change of tab location.
if (!gBrowser.featureCallout && aLocation.spec.endsWith(".pdf")) {
gBrowser.instantiateFeatureCalloutTour(
aLocation,
gBrowser.selectedBrowser,
gBrowser.selectedTab.linkedPanel
);
gBrowser.featureCallout.showFeatureCallout();

View file

@ -93,9 +93,9 @@ add_task(async function test_contenteditable() {
"text/html",
PlacesUtils.toISupportsString("<strong>Bold text</strong>")
);
xferable.addDataFlavor("text/unicode");
xferable.addDataFlavor("text/plain");
xferable.setTransferData(
"text/unicode",
"text/plain",
PlacesUtils.toISupportsString("Bold text")
);
Services.clipboard.setData(

View file

@ -29,7 +29,7 @@ function getTransferableFromClipboard(asHTML) {
if (asHTML) {
trans.addDataFlavor("text/html");
} else {
trans.addDataFlavor("text/unicode");
trans.addDataFlavor("text/plain");
}
Services.clipboard.getData(trans, Ci.nsIClipboard.kGlobalClipboard);
return trans;

View file

@ -16,12 +16,12 @@ function setClipboard(path) {
trans.addDataFlavor("application/x-moz-file");
trans.setTransferData("application/x-moz-file", file);
trans.addDataFlavor("text/unicode");
trans.addDataFlavor("text/plain");
const str = Cc["@mozilla.org/supports-string;1"].createInstance(
Ci.nsISupportsString
);
str.data = "Alternate";
trans.setTransferData("text/unicode", str);
trans.setTransferData("text/plain", str);
// Write to clipboard.
Services.clipboard.setData(trans, null, Ci.nsIClipboard.kGlobalClipboard);

View file

@ -3517,7 +3517,7 @@ BrowserGlue.prototype = {
_migrateUI: function BG__migrateUI() {
// Use an increasing number to keep track of the current migration state.
// Completely unrelated to the current Firefox release number.
const UI_VERSION = 134;
const UI_VERSION = 135;
const BROWSER_DOCURL = AppConstants.BROWSER_CHROME_URL;
const PROFILE_DIR = Services.dirsvc.get("ProfD", Ci.nsIFile).path;
@ -4325,6 +4325,21 @@ BrowserGlue.prototype = {
// Migration 134 was removed because it was no longer necessary.
if (currentUIVersion < 135 && AppConstants.platform == "linux") {
// Avoid changing titlebar setting for users that used to had it off.
try {
if (!Services.prefs.prefHasUserValue("browser.tabs.inTitlebar")) {
let de = Services.appinfo.desktopEnvironment;
let oldDefault = de.includes("gnome") || de.includes("pantheon");
if (!oldDefault) {
Services.prefs.setIntPref("browser.tabs.inTitlebar", 0);
}
}
} catch (e) {
console.error("Error migrating tabsInTitlebar setting", e);
}
}
// Update the migration version.
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
},

View file

@ -639,7 +639,7 @@ DownloadsPlacesView.prototype = {
);
trans.init(null);
let flavors = ["text/x-moz-url", "text/unicode"];
let flavors = ["text/x-moz-url", "text/plain"];
flavors.forEach(trans.addDataFlavor);
Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);

View file

@ -471,7 +471,7 @@ var DownloadsPanel = {
Ci.nsITransferable
);
trans.init(null);
let flavors = ["text/x-moz-url", "text/unicode"];
let flavors = ["text/x-moz-url", "text/plain"];
flavors.forEach(trans.addDataFlavor);
Services.clipboard.getData(trans, Services.clipboard.kGlobalClipboard);
// Getting the data or creating the nsIURI might fail

View file

@ -439,7 +439,6 @@ add_task(async function feature_callout_dismiss_on_page_click() {
}
);
Services.prefs.clearUserPref("browser.firefox-view.view-count");
Services.prefs.clearUserPref("identity.fxaccounts.enabled");
sandbox.restore();
ASRouter.resetMessageState();
});
@ -519,6 +518,47 @@ add_task(async function feature_callout_advance_tour_on_page_click() {
);
});
add_task(async function feature_callout_dismiss_on_escape() {
await SpecialPowers.pushPrefEnv({
set: [[featureTourPref, `{"message":"","screen":"","complete":true}`]],
});
const screenId = "FIREFOX_VIEW_TAB_PICKUP_REMINDER";
let testMessage = getCalloutMessageById(screenId);
const sandbox = createSandboxWithCalloutTriggerStub(testMessage);
const spy = new TelemetrySpy(sandbox);
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: "about:firefoxview",
},
async browser => {
const { document } = browser.contentWindow;
info("Waiting for callout to render");
await waitForCalloutScreen(document, screenId);
info("Pressing escape");
// Press Escape to close
EventUtils.synthesizeKey("KEY_Escape", {}, browser.contentWindow);
await waitForCalloutRemoved(document);
// Test that appropriate telemetry is sent
spy.assertCalledWith({
event: "DISMISS",
event_context: {
source: "KEY_Escape",
page: "about:firefoxview",
},
message_id: screenId,
});
}
);
Services.prefs.clearUserPref("browser.firefox-view.view-count");
sandbox.restore();
ASRouter.resetMessageState();
});
add_task(async function test_firefox_view_spotlight_promo() {
// Prevent attempts to fetch CFR messages remotely.
const sandbox = sinon.createSandbox();

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const EXPORTED_SYMBOLS = ["AboutWelcomeDefaults", "DEFAULT_WELCOME_CONTENT"];
const EXPORTED_SYMBOLS = ["AboutWelcomeDefaults"];
const { XPCOMUtils } = ChromeUtils.importESModule(
"resource://gre/modules/XPCOMUtils.sys.mjs"
@ -36,234 +36,6 @@ XPCOMUtils.defineLazyPreferenceGetter(
0
);
const DEFAULT_WELCOME_CONTENT = {
id: "DEFAULT_ABOUTWELCOME_PROTON",
template: "multistage",
// Allow tests to easily disable transitions.
transitions: Services.prefs.getBoolPref(
"browser.aboutwelcome.transitions",
true
),
backdrop: "#212121",
screens: [
{
id: "AW_PIN_FIREFOX",
content: {
position: "corner",
logo: {},
title: {
string_id: "mr1-onboarding-pin-header",
},
hero_text: {
string_id: "mr1-welcome-screen-hero-text",
},
help_text: {
string_id: "mr1-onboarding-welcome-image-caption",
},
has_noodles: true,
primary_button: {
label: {
string_id: "mr1-onboarding-pin-primary-button-label",
},
action: {
navigate: true,
type: "PIN_FIREFOX_TO_TASKBAR",
},
},
secondary_button: {
label: {
string_id: "mr1-onboarding-set-default-secondary-button-label",
},
action: {
navigate: true,
},
},
secondary_button_top: {
label: {
string_id: "mr1-onboarding-sign-in-button-label",
},
action: {
data: {
entrypoint: "activity-stream-firstrun",
},
type: "SHOW_FIREFOX_ACCOUNTS",
addFlowParams: true,
},
},
},
},
{
id: "AW_LANGUAGE_MISMATCH",
content: {
logo: {},
title: { string_id: "onboarding-live-language-header" },
has_noodles: true,
languageSwitcher: {
downloading: {
string_id: "onboarding-live-language-button-label-downloading",
},
cancel: {
string_id: "onboarding-live-language-secondary-cancel-download",
},
waiting: { string_id: "onboarding-live-language-waiting-button" },
skip: { string_id: "onboarding-live-language-skip-button-label" },
action: {
navigate: true,
},
},
},
},
{
id: "AW_SET_DEFAULT",
content: {
logo: {},
title: {
string_id: "mr1-onboarding-default-header",
},
subtitle: {
string_id: "mr1-onboarding-default-subtitle",
},
has_noodles: true,
primary_button: {
label: {
string_id: "mr1-onboarding-default-primary-button-label",
},
action: {
navigate: true,
type: "SET_DEFAULT_BROWSER",
},
},
secondary_button: {
label: {
string_id: "mr1-onboarding-set-default-secondary-button-label",
},
action: {
navigate: true,
},
},
},
},
{
id: "AW_IMPORT_SETTINGS",
content: {
logo: {},
title: {
string_id: "mr1-onboarding-import-header",
},
subtitle: {
string_id: "mr1-onboarding-import-subtitle",
},
has_noodles: true,
primary_button: {
label: {
string_id:
"mr1-onboarding-import-primary-button-label-no-attribution",
},
action: {
type: "SHOW_MIGRATION_WIZARD",
data: {},
navigate: true,
},
},
secondary_button: {
label: {
string_id: "mr1-onboarding-import-secondary-button-label",
},
action: {
navigate: true,
},
},
},
},
{
id: "AW_CHOOSE_THEME",
content: {
logo: {},
title: {
string_id: "mr1-onboarding-theme-header",
},
subtitle: {
string_id: "mr1-onboarding-theme-subtitle",
},
has_noodles: true,
tiles: {
type: "theme",
action: {
theme: "<event>",
},
data: [
{
theme: "automatic",
label: {
string_id: "mr1-onboarding-theme-label-system",
},
tooltip: {
string_id: "mr1-onboarding-theme-tooltip-system",
},
description: {
string_id: "mr1-onboarding-theme-description-system",
},
},
{
theme: "light",
label: {
string_id: "mr1-onboarding-theme-label-light",
},
tooltip: {
string_id: "mr1-onboarding-theme-tooltip-light",
},
description: {
string_id: "mr1-onboarding-theme-description-light",
},
},
{
theme: "dark",
label: {
string_id: "mr1-onboarding-theme-label-dark",
},
tooltip: {
string_id: "mr1-onboarding-theme-tooltip-dark",
},
description: {
string_id: "mr1-onboarding-theme-description-dark",
},
},
{
theme: "alpenglow",
label: {
string_id: "mr1-onboarding-theme-label-alpenglow",
},
tooltip: {
string_id: "mr1-onboarding-theme-tooltip-alpenglow",
},
description: {
string_id: "mr1-onboarding-theme-description-alpenglow",
},
},
],
},
primary_button: {
label: {
string_id: "onboarding-theme-primary-button-label",
},
action: {
navigate: true,
},
},
secondary_button: {
label: {
string_id: "mr1-onboarding-theme-secondary-button-label",
},
action: {
theme: "automatic",
navigate: true,
},
},
},
},
],
};
// Message to be updated based on finalized MR designs
const MR_ABOUT_WELCOME_DEFAULT = {
id: "MR_WELCOME_DEFAULT",
@ -597,11 +369,8 @@ async function getAttributionContent() {
}
// Return default multistage welcome content
function getDefaults(templateMR = false) {
const defaultContent = templateMR
? MR_ABOUT_WELCOME_DEFAULT
: DEFAULT_WELCOME_CONTENT;
return Cu.cloneInto(defaultContent, {});
function getDefaults() {
return Cu.cloneInto(MR_ABOUT_WELCOME_DEFAULT, {});
}
let gSourceL10n = null;

View file

@ -160,6 +160,9 @@ export class _ContextMenuItem extends React.PureComponent {
onKeyDown={this.onKeyDown}
onKeyUp={this.onKeyUp}
ref={option.first ? this.focusFirst : null}
aria-haspopup={
option.id === "newtab-menu-edit-topsites" ? "dialog" : null
}
>
<span data-l10n-id={option.string_id || option.id} />
</button>

View file

@ -593,7 +593,7 @@ export class TopSitePlaceholder extends React.PureComponent {
isDraggable={false}
>
<button
aria-haspopup="true"
aria-haspopup="dialog"
className="context-menu-button edit-button icon"
data-l10n-id="newtab-menu-topsites-placeholder-tooltip"
onClick={this.onEditButtonClick}

View file

@ -260,6 +260,7 @@ export class TopSiteForm extends React.PureComponent {
value={this.state.label}
titleId="newtab-topsites-title-label"
placeholderId="newtab-topsites-title-input"
autoFocusOnOpen={true}
/>
<TopSiteFormInput
onChange={this.onUrlChange}

View file

@ -88,7 +88,7 @@ export class TopSiteFormInput extends React.PureComponent {
data-l10n-id={this.props.placeholderId}
// Set focus on error if the url field is valid or when the input is first rendered and is empty
// eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus={this.props.shouldFocus}
autoFocus={this.props.autoFocusOnOpen}
disabled={this.props.loading}
/>
{this.renderLoadingOrCloseButton()}

View file

@ -7699,7 +7699,8 @@ class _ContextMenuItem extends (external_React_default()).PureComponent {
onClick: this.onClick,
onKeyDown: this.onKeyDown,
onKeyUp: this.onKeyUp,
ref: option.first ? this.focusFirst : null
ref: option.first ? this.focusFirst : null,
"aria-haspopup": option.id === "newtab-menu-edit-topsites" ? "dialog" : null
}, /*#__PURE__*/external_React_default().createElement("span", {
"data-l10n-id": option.string_id || option.id
})));
@ -11678,7 +11679,7 @@ class TopSiteFormInput extends (external_React_default()).PureComponent {
"data-l10n-id": this.props.placeholderId // Set focus on error if the url field is valid or when the input is first rendered and is empty
// eslint-disable-next-line jsx-a11y/no-autofocus
,
autoFocus: this.props.shouldFocus,
autoFocus: this.props.autoFocusOnOpen,
disabled: this.props.loading
}), this.renderLoadingOrCloseButton(), validationError && /*#__PURE__*/external_React_default().createElement("aside", {
className: "error-tooltip",
@ -12386,7 +12387,7 @@ class TopSitePlaceholder extends (external_React_default()).PureComponent {
className: `placeholder ${this.props.className || ""}`,
isDraggable: false
}), /*#__PURE__*/external_React_default().createElement("button", {
"aria-haspopup": "true",
"aria-haspopup": "dialog",
className: "context-menu-button edit-button icon",
"data-l10n-id": "newtab-menu-topsites-placeholder-tooltip",
onClick: this.onEditButtonClick
@ -12865,7 +12866,8 @@ class TopSiteForm extends (external_React_default()).PureComponent {
onChange: this.onLabelChange,
value: this.state.label,
titleId: "newtab-topsites-title-label",
placeholderId: "newtab-topsites-title-input"
placeholderId: "newtab-topsites-title-input",
autoFocusOnOpen: true
}), /*#__PURE__*/external_React_default().createElement(TopSiteFormInput, {
onChange: this.onUrlChange,
shouldFocus: this.state.validationError && !this.validateUrl(this.state.url),

View file

@ -1291,7 +1291,7 @@ Feature Callout messages can include properties to listen for specific events on
### Feature Callout dismissal
A Feature Callout can be dismissed by clicking its dismiss button directly. With a page event listener, it can also be configured to dismiss the callout when an event in the page happens, such as clicking the target of the callout (see the page event ping above).
A Feature Callout can be dismissed by clicking its dismiss button directly or pressing the Escape key. With a page event listener, it can also be configured to dismiss the callout when an event in the page happens, such as clicking the target of the callout (see the page event ping above).
```js
{
@ -1301,7 +1301,11 @@ A Feature Callout can be dismissed by clicking its dismiss button directly. With
"release_channel": "default",
"event": "DISMISS",
"event_context": {
"source": ["dismiss_button", "PAGE_EVENT:button.primary#some-button"],
"source": [
"dismiss_button",
"KEY_Escape",
"PAGE_EVENT:button.primary#some-button"
],
"page": ["about:firefoxview", "chrome://browser/content/browser.xhtml"]
},
"message_id": "some_feature_callout_id",

View file

@ -532,7 +532,7 @@ const FEEDS_DATA = [
AT: ["de"],
IT: ["it"],
FR: ["fr"],
ES: ["es"],
ES: ["es-ES"],
PL: ["pl"],
JP: ["ja", "ja-JP-mac"],
}[geo];

View file

@ -927,15 +927,15 @@ const BASE_MESSAGES = () => [
icon: "chrome://browser/skin/controlcenter/3rdpartycookies.svg",
icon_class: "cfr-doorhanger-small-icon",
heading_text: {
string_id: "cfr-cookie-banner-handling-header",
string_id: "cfr-cookiebanner-header",
},
text: {
string_id: "cfr-cookie-banner-handling-body",
string_id: "cfr-cookiebanner-body",
},
buttons: {
primary: {
label: {
string_id: "cfr-cookie-banner-accept-button",
string_id: "cfr-cookiebanner-accept-button",
},
action: {
type: "MULTI_ACTION",
@ -959,6 +959,15 @@ const BASE_MESSAGES = () => [
},
},
},
{
type: "SET_PREF",
data: {
pref: {
name: "cookiebanners.service.detectOnly",
value: false,
},
},
},
],
},
},
@ -966,7 +975,7 @@ const BASE_MESSAGES = () => [
secondary: [
{
label: {
string_id: "cfr-cookie-banner-reject-button",
string_id: "cfr-cookiebanner-reject-button",
},
action: {
type: "CANCEL",
@ -983,7 +992,7 @@ const BASE_MESSAGES = () => [
trigger: {
id: "cookieBannerDetected",
},
targeting: `'cookiebanners.ui.desktop.enabled'|preferenceValue == true && 'cookiebanners.service.mode'|preferenceValue == 3`,
targeting: `'cookiebanners.ui.desktop.enabled'|preferenceValue == true && 'cookiebanners.service.detectOnly'|preferenceValue == true`,
},
];

View file

@ -178,7 +178,7 @@ add_task(async function test_multistage_aboutwelcome_proton() {
}
Assert.ok(
clickCall.args[1].message_id === "DEFAULT_ABOUTWELCOME_PROTON_0_AW_STEP1",
clickCall.args[1].message_id === "MR_WELCOME_DEFAULT_0_AW_STEP1",
"AboutWelcome proton message id joined with screen id"
);
@ -351,7 +351,7 @@ add_task(async function test_AWMultistage_Primary_Action() {
);
Assert.equal(
impressionCall.args[1].message_id,
"DEFAULT_ABOUTWELCOME_PROTON_SITES",
"MR_WELCOME_DEFAULT_SITES",
"SITES MessageId sent in impression event telemetry"
);
Assert.equal(
@ -390,7 +390,7 @@ add_task(async function test_AWMultistage_Primary_Action() {
);
Assert.equal(
performanceCall.args[1].message_id,
"DEFAULT_ABOUTWELCOME_PROTON",
"MR_WELCOME_DEFAULT",
"MessageId sent in performance event telemetry"
);
}
@ -412,7 +412,7 @@ add_task(async function test_AWMultistage_Primary_Action() {
);
Assert.equal(
clickCall.args[1].message_id,
"DEFAULT_ABOUTWELCOME_PROTON_0_AW_STEP1",
"MR_WELCOME_DEFAULT_0_AW_STEP1",
"MessageId sent in click event telemetry"
);
});

View file

@ -160,9 +160,9 @@ function eventsMatch(
}
const liveLanguageSwitchSelectors = [
".screen-1",
".screen.AW_LANGUAGE_MISMATCH",
`[data-l10n-id*="onboarding-live-language"]`,
`[data-l10n-id="onboarding-live-language-header"]`,
`[data-l10n-id="mr2022-onboarding-live-language-text"]`,
];
/**
@ -192,9 +192,9 @@ add_task(async function test_aboutwelcome_languageSwitcher_accept() {
// Expected selectors:
[
...liveLanguageSwitchSelectors,
`[data-l10n-id="onboarding-live-language-header"]`,
`[data-l10n-id="mr2022-onboarding-live-language-text"]`,
`button[disabled] [data-l10n-id="onboarding-live-language-waiting-button"]`,
`[data-l10n-id="onboarding-live-language-skip-button-label"]`,
`[data-l10n-id="mr2022-onboarding-secondary-skip-button-label"]`,
],
// Unexpected selectors:
[]
@ -216,8 +216,8 @@ add_task(async function test_aboutwelcome_languageSwitcher_accept() {
],
// Unexpected selectors:
[
`button[disabled] [data-l10n-id="onboarding-live-language-waiting-button"]`,
`[data-l10n-id="onboarding-live-language-skip-button-label"]`,
`button[disabled] [data-l10n-id="mr2022-onboarding-live-language-waiting-button"]`,
`[data-l10n-id="mr2022-onboarding-secondary-skip-button-label"]`,
]
);
@ -246,7 +246,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_accept() {
source: "download_langpack",
page: "about:welcome",
},
message_id: "DEFAULT_ABOUTWELCOME_PROTON_1_AW_LANGUAGE_MISMATCH",
message_id: "MR_WELCOME_DEFAULT_1_AW_LANGUAGE_MISMATCH",
},
]);
@ -258,7 +258,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_accept() {
browser,
"Language changed",
// Expected selectors:
[`.screen-2`],
[`.screen.AW_IMPORT_SETTINGS`],
// Unexpected selectors:
liveLanguageSwitchSelectors
);
@ -273,7 +273,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_accept() {
source: "download_complete",
page: "about:welcome",
},
message_id: "DEFAULT_ABOUTWELCOME_PROTON_1_AW_LANGUAGE_MISMATCH",
message_id: "MR_WELCOME_DEFAULT_1_AW_LANGUAGE_MISMATCH",
},
]);
});
@ -305,9 +305,9 @@ add_task(async function test_aboutwelcome_languageSwitcher_accept() {
// Expected selectors:
[
...liveLanguageSwitchSelectors,
`[data-l10n-id="onboarding-live-language-header"]`,
`[data-l10n-id="mr2022-onboarding-live-language-text"]`,
`button[disabled] [data-l10n-id="onboarding-live-language-waiting-button"]`,
`[data-l10n-id="onboarding-live-language-skip-button-label"]`,
`[data-l10n-id="mr2022-onboarding-secondary-skip-button-label"]`,
],
// Unexpected selectors:
[]
@ -330,7 +330,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_accept() {
// Unexpected selectors:
[
`button[disabled] [data-l10n-id="onboarding-live-language-waiting-button"]`,
`[data-l10n-id="onboarding-live-language-skip-button-label"]`,
`[data-l10n-id="mr2022-onboarding-secondary-skip-button-label"]`,
]
);
@ -359,7 +359,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_accept() {
source: "download_langpack",
page: "about:welcome",
},
message_id: "DEFAULT_ABOUTWELCOME_PROTON_1_AW_LANGUAGE_MISMATCH",
message_id: "MR_WELCOME_DEFAULT_1_AW_LANGUAGE_MISMATCH",
},
]);
@ -370,7 +370,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_accept() {
browser,
"Language selection accepted",
// Expected selectors:
[`.screen-2`],
[`.screen.AW_IMPORT_SETTINGS`],
// Unexpected selectors:
liveLanguageSwitchSelectors
);
@ -406,9 +406,9 @@ add_task(async function test_aboutwelcome_languageSwitcher_decline() {
// Expected selectors:
[
...liveLanguageSwitchSelectors,
`[data-l10n-id="onboarding-live-language-header"]`,
`[data-l10n-id="mr2022-onboarding-live-language-text"]`,
`button[disabled] [data-l10n-id="onboarding-live-language-waiting-button"]`,
`[data-l10n-id="onboarding-live-language-skip-button-label"]`,
`[data-l10n-id="mr2022-onboarding-secondary-skip-button-label"]`,
],
// Unexpected selectors:
[]
@ -432,7 +432,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_decline() {
// Unexpected selectors:
[
`button[disabled] [data-l10n-id="onboarding-live-language-waiting-button"]`,
`[data-l10n-id="onboarding-live-language-skip-button-label"]`,
`[data-l10n-id="mr2022-onboarding-secondary-skip-button-label"]`,
]
);
@ -445,7 +445,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_decline() {
browser,
"Language selection declined",
// Expected selectors:
[`.screen-2`],
[`.screen.AW_IMPORT_SETTINGS`],
// Unexpected selectors:
liveLanguageSwitchSelectors
);
@ -460,7 +460,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_decline() {
source: "decline",
page: "about:welcome",
},
message_id: "DEFAULT_ABOUTWELCOME_PROTON_1_AW_LANGUAGE_MISMATCH",
message_id: "MR_WELCOME_DEFAULT_1_AW_LANGUAGE_MISMATCH",
},
]);
});
@ -556,7 +556,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_noMatch() {
browser,
"Language selection skipped",
// Expected selectors:
[`.screen-1`],
[`.screen.AW_IMPORT_SETTINGS`],
// Unexpected selectors:
[
`[data-l10n-id*="onboarding-live-language"]`,
@ -587,7 +587,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_bidiNotSupported() {
browser,
"Language selection skipped for bidi",
// Expected selectors:
[`.screen-1`],
[`.screen.AW_IMPORT_SETTINGS`],
// Unexpected selectors:
[
`[data-l10n-id*="onboarding-live-language"]`,
@ -621,7 +621,7 @@ add_task(
browser,
"Language selection skipped for bidi",
// Expected selectors:
[`.screen-1`],
[`.screen.AW_IMPORT_SETTINGS`],
// Unexpected selectors:
[
`[data-l10n-id*="onboarding-live-language"]`,
@ -721,7 +721,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_cancelWaiting() {
browser,
"Language selection declined waiting",
// Expected selectors:
[`.screen-2`],
[`.screen.AW_IMPORT_SETTINGS`],
// Unexpected selectors:
liveLanguageSwitchSelectors
);
@ -733,7 +733,7 @@ add_task(async function test_aboutwelcome_languageSwitcher_cancelWaiting() {
source: "cancel_waiting",
page: "about:welcome",
},
message_id: "DEFAULT_ABOUTWELCOME_PROTON_1_AW_LANGUAGE_MISMATCH",
message_id: "MR_WELCOME_DEFAULT_1_AW_LANGUAGE_MISMATCH",
},
]);

View file

@ -20,7 +20,7 @@ const waitForCalloutScreen = async (doc, screenId) => {
const waitForRemoved = async doc => {
await BrowserTestUtils.waitForCondition(() => {
return !document.querySelector(calloutSelector);
return !doc.querySelector(calloutSelector);
});
};
@ -148,7 +148,7 @@ add_task(async function feature_callout_renders_in_browser_chrome_for_pdf() {
// click primary button to close
doc.querySelector(primaryButtonSelector).click();
await waitForRemoved();
await waitForRemoved(doc);
ok(
true,
"Feature callout removed from browser chrome after clicking button configured to navigate"
@ -236,7 +236,7 @@ add_task(
win.gBrowser,
"about:preferences"
);
await waitForRemoved();
await waitForRemoved(doc);
ok(
!doc.querySelector(`.${testMessageCalloutSelector}`),
@ -270,7 +270,7 @@ add_task(
);
BrowserTestUtils.removeTab(tab1);
await waitForRemoved();
await waitForRemoved(doc);
ok(
!doc.querySelector(`.${testMessageCalloutSelector}`),
@ -412,3 +412,67 @@ add_task(
sandbox.restore();
}
);
add_task(async function feature_callout_dismissed_on_escape() {
const sandbox = sinon.createSandbox();
const sendTriggerStub = sandbox.stub(ASRouter, "sendTriggerMessage");
sendTriggerStub.withArgs(pdfMatch).resolves(testMessage);
sendTriggerStub.callThrough();
const win = await BrowserTestUtils.openNewBrowserWindow();
await openURLInWindow(win, PDF_TEST_URL);
const doc = win.document;
await waitForCalloutScreen(doc, testMessageCalloutSelector);
const container = doc.querySelector(calloutSelector);
ok(
container,
"Feature Callout is rendered in the browser chrome with a new window when a message is available"
);
// Ensure the browser is focused
win.gBrowser.selectedBrowser.focus();
// Press Escape to close
EventUtils.synthesizeKey("KEY_Escape", {}, win);
await waitForRemoved(doc);
ok(true, "Feature callout dismissed after pressing Escape");
await BrowserTestUtils.closeWindow(win);
sandbox.restore();
});
add_task(
async function feature_callout_not_dismissed_on_escape_with_interactive_elm_focused() {
const sandbox = sinon.createSandbox();
const sendTriggerStub = sandbox.stub(ASRouter, "sendTriggerMessage");
sendTriggerStub.withArgs(pdfMatch).resolves(testMessage);
sendTriggerStub.callThrough();
const win = await BrowserTestUtils.openNewBrowserWindow();
await openURLInWindow(win, PDF_TEST_URL);
const doc = win.document;
await waitForCalloutScreen(doc, testMessageCalloutSelector);
const container = doc.querySelector(calloutSelector);
ok(
container,
"Feature Callout is rendered in the browser chrome with a new window when a message is available"
);
// Ensure an interactive element is focused
win.gURLBar.focus();
// Press Escape to close
EventUtils.synthesizeKey("KEY_Escape", {}, win);
await TestUtils.waitForTick();
// Wait 500ms for transition to complete
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
await new Promise(resolve => setTimeout(resolve, 500));
ok(
doc.querySelector(calloutSelector),
"Feature callout is not dismissed after pressing Escape because an interactive element is focused"
);
await BrowserTestUtils.closeWindow(win);
sandbox.restore();
}
);

View file

@ -284,11 +284,6 @@ describe("MultiStageAboutWelcomeProton module", () => {
assert.property(data, "skipFxA", true);
assert.notProperty(data.screens[0].content, "secondary_button_top");
});
it("should have an image caption", async () => {
const data = await prepConfig();
assert.property(data.screens[0].content, "help_text");
});
it("should remove the caption if deleteIfNotEn is true", async () => {
sandbox.stub(global.Services.locale, "appLocaleAsBCP47").value("de");

View file

@ -9,7 +9,7 @@ import {
import { Themes } from "content-src/aboutwelcome/components/Themes";
import React from "react";
import { shallow, mount } from "enzyme";
import { DEFAULT_WELCOME_CONTENT } from "aboutwelcome/lib/AboutWelcomeDefaults.jsm";
import { AboutWelcomeDefaults } from "aboutwelcome/lib/AboutWelcomeDefaults.jsm";
import { AboutWelcomeUtils } from "content-src/lib/aboutwelcome-utils";
describe("MultiStageAboutWelcome module", () => {
@ -17,7 +17,7 @@ describe("MultiStageAboutWelcome module", () => {
let sandbox;
const DEFAULT_PROPS = {
screens: DEFAULT_WELCOME_CONTENT.screens,
screens: AboutWelcomeDefaults.getDefaults().screens,
metricsFlowUri: "http://localhost/",
message_id: "DEFAULT_ABOUTWELCOME",
utm_term: "default",
@ -212,7 +212,7 @@ describe("MultiStageAboutWelcome module", () => {
describe("WelcomeScreen component", () => {
describe("get started screen", () => {
const screen = DEFAULT_WELCOME_CONTENT.screens.find(
const screen = AboutWelcomeDefaults.getDefaults().screens.find(
s => s.id === "AW_PIN_FIREFOX"
);

View file

@ -1793,7 +1793,7 @@ export var PlacesUIUtils = {
let contents = [
{ type: lazy.PlacesUtils.TYPE_X_MOZ_URL, entries: [] },
{ type: lazy.PlacesUtils.TYPE_HTML, entries: [] },
{ type: lazy.PlacesUtils.TYPE_UNICODE, entries: [] },
{ type: lazy.PlacesUtils.TYPE_PLAINTEXT, entries: [] },
];
contents.forEach(function(content) {
@ -2034,7 +2034,7 @@ XPCOMUtils.defineLazyGetter(PlacesUIUtils, "URI_FLAVORS", () => {
return [
lazy.PlacesUtils.TYPE_X_MOZ_URL,
TAB_DROP_TYPE,
lazy.PlacesUtils.TYPE_UNICODE,
lazy.PlacesUtils.TYPE_PLAINTEXT,
];
});
XPCOMUtils.defineLazyGetter(PlacesUIUtils, "SUPPORTED_FLAVORS", () => {
@ -2271,7 +2271,7 @@ function getTransactionsForCopy(items, insertionIndex, insertionParentGuid) {
});
} else {
let title =
item.type != lazy.PlacesUtils.TYPE_UNICODE ? item.title : item.uri;
item.type != lazy.PlacesUtils.TYPE_PLAINTEXT ? item.title : item.uri;
transaction = lazy.PlacesTransactions.NewBookmark({
index,
parentGuid: insertionParentGuid,

View file

@ -168,7 +168,7 @@ PlacesController.prototype = {
case "cmd_paste":
case "placesCmd_paste":
// If the clipboard contains a Places flavor it is definitely pasteable,
// otherwise we also allow pasting "text/unicode" and "text/x-moz-url" data.
// otherwise we also allow pasting "text/plain" and "text/x-moz-url" data.
// We don't check if the data is valid here, because the clipboard may
// contain very large blobs that would largely slowdown commands updating.
// Of course later paste() should ignore any invalid data.
@ -178,7 +178,7 @@ PlacesController.prototype = {
[
...PlacesUIUtils.PLACES_FLAVORS,
PlacesUtils.TYPE_X_MOZ_URL,
PlacesUtils.TYPE_UNICODE,
PlacesUtils.TYPE_PLAINTEXT,
],
Ci.nsIClipboard.kGlobalClipboard
)
@ -1049,7 +1049,7 @@ PlacesController.prototype = {
function addURIData(index) {
addData(PlacesUtils.TYPE_X_MOZ_URL, index);
addData(PlacesUtils.TYPE_UNICODE, index);
addData(PlacesUtils.TYPE_PLAINTEXT, index);
addData(PlacesUtils.TYPE_HTML, index);
}
@ -1131,7 +1131,7 @@ PlacesController.prototype = {
{ type: PlacesUtils.TYPE_X_MOZ_PLACE, entries: [] },
{ type: PlacesUtils.TYPE_X_MOZ_URL, entries: [] },
{ type: PlacesUtils.TYPE_HTML, entries: [] },
{ type: PlacesUtils.TYPE_UNICODE, entries: [] },
{ type: PlacesUtils.TYPE_PLAINTEXT, entries: [] },
];
// Avoid handling descendants of a copied node, the transactions take care
@ -1264,7 +1264,7 @@ PlacesController.prototype = {
[
PlacesUtils.TYPE_X_MOZ_PLACE,
PlacesUtils.TYPE_X_MOZ_URL,
PlacesUtils.TYPE_UNICODE,
PlacesUtils.TYPE_PLAINTEXT,
].forEach(type => xferable.addDataFlavor(type));
Services.clipboard.getData(xferable, Ci.nsIClipboard.kGlobalClipboard);
@ -1494,13 +1494,6 @@ var PlacesControllerDragHelper = {
}
}
// If no supported flavor is found, check if data includes text/plain
// contents. If so, request them as text/unicode, a conversion will happen
// automatically.
if (aFlavors.contains("text/plain")) {
return PlacesUtils.TYPE_UNICODE;
}
return null;
},
@ -1623,7 +1616,7 @@ var PlacesControllerDragHelper = {
// Following flavors may contain duplicated data.
let duplicable = new Map();
duplicable.set(PlacesUtils.TYPE_UNICODE, new Set());
duplicable.set(PlacesUtils.TYPE_PLAINTEXT, new Set());
duplicable.set(PlacesUtils.TYPE_X_MOZ_URL, new Set());
// Collect all data from the DataTransfer before processing it, as the

View file

@ -133,7 +133,7 @@ add_task(async function test() {
};
// Simulate a bookmark drop for all of the mime types and effects.
let mimeTypes = ["text/plain", "text/unicode", "text/x-moz-url"];
let mimeTypes = ["text/plain", "text/x-moz-url"];
let effects = ["move", "copy", "link"];
for (let effect of effects) {
for (let mimeType of mimeTypes) {

View file

@ -690,7 +690,7 @@ EngineStore.prototype = {
updateEngine(newEngine) {
let engineToUpdate = this._engines.findIndex(
e => e.originalEngine == newEngine
e => e.originalEngine.id == newEngine.id
);
if (engineToUpdate != -1) {
this.engines[engineToUpdate] = this._cloneEngine(newEngine);

View file

@ -10,7 +10,7 @@
proxy-title = Stay safe on public Wi-Fi
proxy-header-content = { -secure-proxy-brand-name } makes wireless hotspots more secure to protect you from hackers.
get-proxy-extension-link = Get the Extension
get-proxy-extension-link = Get the extension
vpn-title = Take privacy protections beyond the browser
vpn-header-content = Protect your entire device with { -mozilla-vpn-brand-name }. One tap encrypts all traffic and hides your location.

View file

@ -14,18 +14,43 @@ telemetry is relevant to Firefox as well as other consumers of Toolkit. See
telemetry
Glossary
--------
SAP
Search Access Point, a search that a user performs by visiting
via one of Firefox's access points using the associated partner codes.
SERP
A search engine results page.
Persisted Search
When a user has the following preference values:
- ``browser.urlbar.showSearchTerms.enabled``: ``true``
- ``browser.urlbar.showSearchTerms.featureGate``: ``true``
- ``browser.search.widget.inNavBar``: ``false``
and does the following:
- Starts a search from the urlbar or context menu.
- Loads the default search engine results page.
the search term will persist in the Urlbar, causing it to enter a Persisted Search state.
Definitions
-----------
* ``organic`` is a search that a user performs by visiting a search engine
directly.
* ``SAP`` (search access point) is a search that a user performs by visiting
via one of Firefox's access points, using the associated partner codes.
* ``sap-follow-on`` is a SAP search where the user has first accessed the site
via a SAP, and then performed an additional search.
* ``tagged`` refers to a page that is tagged with an associated partner code.
It may or may not have originated via an SAP.
* ``SERP`` refers to a search engine result page.
``organic``
A search that a user performs by visiting a search engine directly.
``tagged``
Refers to a page that is tagged with an associated partner code.
It may or may not have originated via a SAP.
``tagged-follow-on``
Refers to a page that is tagged with an associated partner code and has been identified
as a follow-on search. It may or may not have originated via a SAP.
Search probes relevant to front-end searches
--------------------------------------------
@ -57,6 +82,8 @@ SEARCH_COUNTS - SAP usage
- ``system``
- ``urlbar`` Except aliases and search mode.
- ``urlbar-handoff`` Used when searching from about:newtab.
- ``urlbar-persisted`` Used when searching from the Urlbar while it
was in a Persisted Search state.
- ``urlbar-searchmode`` Used when the Urlbar is in search mode.
- ``webextension``
@ -69,11 +96,8 @@ browser.engagement.navigation.*
- ``urlbar`` Except search mode.
- ``urlbar_handoff`` Used when searching from about:newtab.
- ``urlbar_persisted`` When `browser.urlbar.showSearchTerms.enabled` is `true`, and the
search bar is disabled, and a user conducts a search with their default search engine, the
terms used for the search will persist in the urlbar. When a user does a search with the
default search engine from the urlbar, and then from the context of the SERP, does
another search using the urlbar with their default search engine, this SAP will be used.
- ``urlbar_persisted`` Used when searching from the Urlbar while it
was in a Persisted Search state.
- ``urlbar_searchmode`` Used when the Urlbar is in search mode.
- ``searchbar``
- ``about_home``
@ -115,17 +139,12 @@ browser.search.content.*
These keyed scalar track counts of SERP page loads. The key format is
``<provider>:[tagged|tagged-follow-on|organic]:[<code>|other|none]``.
These will eventually replace the SEARCH_COUNTS - SERP results.
They are broken down by the originating SAP where known:
- ``urlbar`` Except search mode.
- ``urlbar_handoff`` Used when searching from about:newtab.
- ``urlbar_persisted`` When `browser.urlbar.showSearchTerms.enabled` is `true`, and the
search bar is disabled, and a user conducts a search with their default search engine, the
terms used for the search will persist in the urlbar. When a user does a search with the
default search engine from the urlbar, and then from the context of the SERP, does
another search using the urlbar with their default search engine, this SAP will be used.
- ``urlbar_persisted`` Used when searching from the Urlbar while it
was in a Persisted Search state.
- ``urlbar_searchmode`` Used when the Urlbar is in search mode.
- ``searchbar``
- ``about_home``

View file

@ -19,11 +19,11 @@ function getTextFromClipboard() {
Ci.nsITransferable
);
transferable.init(window.docShell.QueryInterface(Ci.nsILoadContext));
transferable.addDataFlavor("text/unicode");
transferable.addDataFlavor("text/plain");
Services.clipboard.getData(transferable, Services.clipboard.kGlobalClipboard);
const results = {};
transferable.getTransferData("text/unicode", results);
transferable.getTransferData("text/plain", results);
return results.value.QueryInterface(Ci.nsISupportsString)?.data ?? "";
}

View file

@ -3604,7 +3604,7 @@ export class UrlbarInput {
let title = this.window.gBrowser.contentTitle || href;
event.dataTransfer.setData("text/x-moz-url", `${href}\n${title}`);
event.dataTransfer.setData("text/unicode", href);
event.dataTransfer.setData("text/plain", href);
event.dataTransfer.setData("text/html", `<a href="${href}">${title}</a>`);
event.dataTransfer.effectAllowed = "copyLink";
event.stopPropagation();
@ -3709,7 +3709,7 @@ function getDroppableData(event) {
}
}
// Handle as text.
return event.dataTransfer.getData("text/unicode");
return event.dataTransfer.getData("text/plain");
}
/**

View file

@ -148,6 +148,7 @@ class ProviderQuickActions extends UrlbarProvider {
);
result.suggestedIndex = SUGGESTED_INDEX;
addCallback(this, result);
this.#resultFromLastQuery = result;
}
getViewTemplate(result) {
@ -228,6 +229,57 @@ class ProviderQuickActions extends UrlbarProvider {
}
}
/**
* Called when the user starts and ends an engagement with the urlbar. For
* details on parameters, see UrlbarProvider.onEngagement().
*
* @param {boolean} isPrivate
* True if the engagement is in a private context.
* @param {string} state
* The state of the engagement, one of: start, engagement, abandonment,
* discard
* @param {UrlbarQueryContext} queryContext
* The engagement's query context. This is *not* guaranteed to be defined
* when `state` is "start". It will always be defined for "engagement" and
* "abandonment".
* @param {object} details
* This is defined only when `state` is "engagement" or "abandonment", and
* it describes the search string and picked result.
*/
onEngagement(isPrivate, state, queryContext, details) {
let result = this.#resultFromLastQuery;
this.#resultFromLastQuery = null;
if (state == "engagement") {
// Find the quickaction result that's currently visible in the view.
// It's probably the result from the last query so check it first, but due
// to the async nature of how results are added to the view and made
// visible, it may not be.
if (
result &&
(result.rowIndex < 0 ||
queryContext.view?.visibleResults?.[result.rowIndex] != result)
) {
// The result from the last query isn't visible.
result = null;
}
// If the result isn't visible, find a visible one.
if (!result) {
result = queryContext.view?.visibleResults?.find(
r => r.providerName == this.name
);
}
result.payload.results.forEach(({ key }) => {
Services.telemetry.keyedScalarAdd(
`quickaction.impression`,
`${key}-${queryContext.trimmedSearchString.length}`,
1
);
});
}
}
/**
* Adds a new QuickAction.
*
@ -277,6 +329,9 @@ class ProviderQuickActions extends UrlbarProvider {
// The actions that have been added.
#actions = new Map();
// The result we added during the most recent query.
#resultFromLastQuery = null;
#loopOverPrefixes(commands, fun) {
for (const command of commands) {
// Loop over all the prefixes of the word, ie

View file

@ -127,10 +127,14 @@ const WEATHER_VIEW_TEMPLATE = {
name: "summaryTextSeparator",
tag: "span",
},
{
name: "highLow",
tag: "span",
},
],
},
{
name: "highLow",
name: "highLowWrap",
tag: "span",
},
],
@ -310,6 +314,16 @@ class ProviderQuickSuggest extends UrlbarProvider {
excludeArgsFromCacheKey: true,
},
},
highLowWrap: {
l10n: {
id: "firefox-suggest-weather-high-low",
args: {
high: result.payload.high,
low: result.payload.low,
unit: uppercaseUnit,
},
},
},
bottom: {
l10n: {
id: "firefox-suggest-weather-sponsored",

View file

@ -2550,7 +2550,9 @@ export class L10nCache {
* The string will be cached only by its ID. See `add()` for more.
*/
async ensure({ id, args = undefined, excludeArgsFromCacheKey = false }) {
if (!this.get({ id, args, excludeArgsFromCacheKey })) {
// Always re-cache if `excludeArgsFromCacheKey` is true. The values in
// `args` may be different from the values in the cached string.
if (excludeArgsFromCacheKey || !this.get({ id, args })) {
await this.add({ id, args, excludeArgsFromCacheKey });
}
}

View file

@ -2302,7 +2302,8 @@ export class UrlbarView {
#setElementOverflowing(element, overflowing) {
element.toggleAttribute("overflow", overflowing);
if (overflowing) {
if (overflowing && element._tooltip) {
element.setAttribute("title", element._tooltip);
} else {
element.removeAttribute("title");
@ -2848,7 +2849,11 @@ export class UrlbarView {
event.detail == 1 &&
(event.target.classList.contains("urlbarView-url") ||
event.target.classList.contains("urlbarView-title") ||
event.target.classList.contains("urlbarView-tags"))
event.target.classList.contains("urlbarView-tags") ||
event.target.classList.contains(
"urlbarView-dynamic-weather-middleNoWrap"
) ||
event.target.classList.contains("urlbarView-dynamic-weather-summary"))
) {
this.#setElementOverflowing(event.target, true);
}
@ -2859,7 +2864,11 @@ export class UrlbarView {
event.detail == 1 &&
(event.target.classList.contains("urlbarView-url") ||
event.target.classList.contains("urlbarView-title") ||
event.target.classList.contains("urlbarView-tags"))
event.target.classList.contains("urlbarView-tags") ||
event.target.classList.contains(
"urlbarView-dynamic-weather-middleNoWrap"
) ||
event.target.classList.contains("urlbarView-dynamic-weather-summary"))
) {
this.#setElementOverflowing(event.target, false);
}

View file

@ -393,6 +393,16 @@ urlbar.zeroprefix.exposure
the "top sites" view since normally it shows the user's top sites. This scalar
was introduced in Firefox 110.0 in bug 1806765.
urlbar.quickaction.impression
A uint recording the number of times the user was shown a quickaction, the
key is in the form $key-$n where $n is the number of characters the user typed
in order for the suggestion to show. See bug 1806024.
urlbar.quickaction.picked
A uint recording the number of times the user selected a quickaction, the
key is in the form $key-$n where $n is the number of characters the user typed
in order for the suggestion to show. See bug 1783155.
places.*
This is places related telemetry.

View file

@ -60,7 +60,7 @@ add_task(async function() {
}
let primaryAsText = SpecialPowers.getClipboardData(
"text/unicode",
"text/plain",
SpecialPowers.Ci.nsIClipboard.kSelectionClipboard
);
Assert.equal(primaryAsText, TEXT_FOR_PRIMARY);

View file

@ -60,7 +60,7 @@ add_task(async function test_selectByKey() {
function assertClipboard() {
Assert.equal(
SpecialPowers.getClipboardData("text/unicode"),
SpecialPowers.getClipboardData("text/plain"),
"100 cm",
"The result of conversion is copied to clipboard"
);

View file

@ -83,7 +83,7 @@ function checkPrimarySelection(expectedVal = "") {
)
) {
let primaryAsText = SpecialPowers.getClipboardData(
"text/unicode",
"text/plain",
SpecialPowers.Ci.nsIClipboard.kSelectionClipboard
);
Assert.equal(primaryAsText, expectedVal);

View file

@ -73,10 +73,55 @@ add_task(async function test() {
1
);
TelemetryTestUtils.assertKeyedScalar(
scalars,
"quickaction.impression",
"testaction-10",
1
);
// Clean up for subsequent tests.
gURLBar.handleRevert();
});
add_task(async function test_impressions() {
UrlbarProviderQuickActions.addAction("testaction2", {
commands: ["testaction2"],
label: "quickactions-downloads2",
onPick: () => {},
});
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "testaction",
waitForFocus,
fireInputEvent: true,
});
await UrlbarTestUtils.promisePopupClose(window, () => {
EventUtils.synthesizeKey("KEY_ArrowDown");
EventUtils.synthesizeKey("KEY_Enter");
});
let scalars = TelemetryTestUtils.getProcessScalars("parent", true, true);
TelemetryTestUtils.assertKeyedScalar(
scalars,
"quickaction.impression",
`testaction-10`,
1
);
TelemetryTestUtils.assertKeyedScalar(
scalars,
"quickaction.impression",
`testaction2-10`,
1
);
UrlbarProviderQuickActions.removeAction("testaction2");
gURLBar.handleRevert();
});
function snapshotHistograms() {
Services.telemetry.clearScalars();
Services.telemetry.clearEvents();

View file

@ -353,10 +353,37 @@ add_task(async function excludeArgsFromCacheKey() {
let cache = new L10nCache(l10n);
// Test cases. For each test case, we cache a string using one or more
// methods, `cache.add({ excludeArgsFromCacheKey: true })` and/or
// `cache.ensure({ excludeArgsFromCacheKey: true })`. After calling each
// method, we call `cache.get()` to get the cached string.
//
// Test cases are cumulative, so when `cache.add()` is called for a string and
// then `cache.ensure()` is called for the same string but with different l10n
// argument values, the string should be re-cached with the new values.
//
// Each item in the tests array is: `{ methods, obj, gets }`
//
// {array} methods
// Array of cache method names, one or more of: "add", "ensure"
// Methods are called in the order they are listed.
// {object} obj
// An l10n object that will be passed to the cache methods:
// `{ id, args, excludeArgsFromCacheKey }`
// {array} gets
// An array of objects that describes a series of calls to `cache.get()` and
// the expected return values: `{ obj, expected }`
//
// {object} obj
// An l10n object that will be passed to `cache.get():`
// `{ id, args, excludeArgsFromCacheKey }`
// {object} expected
// The expected return value from `get()`.
let tests = [
// string with no args and no attributes
// args0: string with no args and no attributes
{
add: {
methods: ["add", "ensure"],
obj: {
id: "args0",
excludeArgsFromCacheKey: true,
},
@ -378,25 +405,26 @@ add_task(async function excludeArgsFromCacheKey() {
],
},
// string with one arg and no attributes
// args1: string with one arg and no attributes
{
add: {
methods: ["add"],
obj: {
id: "args1",
args: { arg1: "foo" },
args: { arg1: "ADD" },
excludeArgsFromCacheKey: true,
},
gets: [
{
obj: { id: "args1" },
expected: {
value: "One arg value is foo",
value: "One arg value is ADD",
attributes: null,
},
},
{
obj: { id: "args1", excludeArgsFromCacheKey: true },
expected: {
value: "One arg value is foo",
value: "One arg value is ADD",
attributes: null,
},
},
@ -407,7 +435,49 @@ add_task(async function excludeArgsFromCacheKey() {
excludeArgsFromCacheKey: true,
},
expected: {
value: "One arg value is foo",
value: "One arg value is ADD",
attributes: null,
},
},
{
obj: {
id: "args1",
args: { arg1: "some other value" },
},
expected: undefined,
},
],
},
{
methods: ["ensure"],
obj: {
id: "args1",
args: { arg1: "ENSURE" },
excludeArgsFromCacheKey: true,
},
gets: [
{
obj: { id: "args1" },
expected: {
value: "One arg value is ENSURE",
attributes: null,
},
},
{
obj: { id: "args1", excludeArgsFromCacheKey: true },
expected: {
value: "One arg value is ENSURE",
attributes: null,
},
},
{
obj: {
id: "args1",
args: { arg1: "some other value" },
excludeArgsFromCacheKey: true,
},
expected: {
value: "One arg value is ENSURE",
attributes: null,
},
},
@ -421,9 +491,10 @@ add_task(async function excludeArgsFromCacheKey() {
],
},
// string with no args and one attribute
// attrs0: string with no args and one attribute
{
add: {
methods: ["add", "ensure"],
obj: {
id: "attrs0",
excludeArgsFromCacheKey: true,
},
@ -449,11 +520,12 @@ add_task(async function excludeArgsFromCacheKey() {
],
},
// string with one arg and two attributes
// attrs1: string with one arg and two attributes
{
add: {
methods: ["add"],
obj: {
id: "attrs1",
args: { arg1: "foo" },
args: { arg1: "ADD" },
excludeArgsFromCacheKey: true,
},
gets: [
@ -463,7 +535,7 @@ add_task(async function excludeArgsFromCacheKey() {
value: null,
attributes: {
label: "attrs1 label has zero args",
tooltiptext: "attrs1 tooltiptext arg value is foo",
tooltiptext: "attrs1 tooltiptext arg value is ADD",
},
},
},
@ -473,7 +545,7 @@ add_task(async function excludeArgsFromCacheKey() {
value: null,
attributes: {
label: "attrs1 label has zero args",
tooltiptext: "attrs1 tooltiptext arg value is foo",
tooltiptext: "attrs1 tooltiptext arg value is ADD",
},
},
},
@ -487,7 +559,58 @@ add_task(async function excludeArgsFromCacheKey() {
value: null,
attributes: {
label: "attrs1 label has zero args",
tooltiptext: "attrs1 tooltiptext arg value is foo",
tooltiptext: "attrs1 tooltiptext arg value is ADD",
},
},
},
{
obj: {
id: "attrs1",
args: { arg1: "some other value" },
},
expected: undefined,
},
],
},
{
methods: ["ensure"],
obj: {
id: "attrs1",
args: { arg1: "ENSURE" },
excludeArgsFromCacheKey: true,
},
gets: [
{
obj: { id: "attrs1" },
expected: {
value: null,
attributes: {
label: "attrs1 label has zero args",
tooltiptext: "attrs1 tooltiptext arg value is ENSURE",
},
},
},
{
obj: { id: "attrs1", excludeArgsFromCacheKey: true },
expected: {
value: null,
attributes: {
label: "attrs1 label has zero args",
tooltiptext: "attrs1 tooltiptext arg value is ENSURE",
},
},
},
{
obj: {
id: "attrs1",
args: { arg1: "some other value" },
excludeArgsFromCacheKey: true,
},
expected: {
value: null,
attributes: {
label: "attrs1 label has zero args",
tooltiptext: "attrs1 tooltiptext arg value is ENSURE",
},
},
},
@ -502,17 +625,33 @@ add_task(async function excludeArgsFromCacheKey() {
},
];
for (let { add, gets } of tests) {
info("Adding to cache: " + JSON.stringify(add));
await cache.add(add);
for (let { obj, expected } of gets) {
Assert.deepEqual(
cache.get(obj),
expected,
"Expected message for get: " + JSON.stringify(obj)
let sandbox = sinon.createSandbox();
let spy = sandbox.spy(cache, "add");
for (let { methods, obj, gets } of tests) {
for (let method of methods) {
info(`Calling method '${method}' with l10n obj: ` + JSON.stringify(obj));
await cache[method](obj);
// `add()` should always be called: We either just called it directly, or
// `ensure({ excludeArgsFromCacheKey: true })` called it.
Assert.ok(
spy.calledOnce,
"add() should have been called once: " + JSON.stringify(obj)
);
spy.resetHistory();
for (let { obj: getObj, expected } of gets) {
Assert.deepEqual(
cache.get(getObj),
expected,
"Expected message for get: " + JSON.stringify(getObj)
);
}
}
}
sandbox.restore();
});
/**

View file

@ -9,6 +9,3 @@ ac_add_options --target=aarch64-apple-darwin
# It may conflict with settings from mozconfig.override, but that seems
# unlikely.
ac_add_options --disable-optimize
# TODO: Remove in bug 1773743
export MACOS_SDK_DIR=$MOZ_FETCHES_DIR/MacOSX11.3.sdk

View file

@ -7,6 +7,3 @@ MOZ_AUTOMATION_BUILD_SYMBOLS=0
# It may conflict with settings from mozconfig.override, but that seems
# unlikely.
ac_add_options --disable-optimize
# TODO: Remove in bug 1773743
export MACOS_SDK_DIR=$MOZ_FETCHES_DIR/MacOSX11.3.sdk

View file

@ -1,2 +1 @@
ac_add_options --disable-release
export MACOS_SDK_DIR=$MOZ_FETCHES_DIR/MacOSX13.0.sdk

View file

@ -5,6 +5,9 @@
"use strict";
class PictureInPictureVideoWrapper {
isLive(video) {
return !!document.querySelector(".ytp-live");
}
setMuted(video, shouldMute) {
let muteButton = document.querySelector("#player .ytp-mute-button");
@ -14,6 +17,12 @@ class PictureInPictureVideoWrapper {
video.muted = shouldMute;
}
}
getDuration(video) {
if (this.isLive(video)) {
return Infinity;
}
return video.duration;
}
setCaptionContainerObserver(video, updateCaptionsFunction) {
let container = document.getElementById("ytp-caption-window-container");

View file

@ -64,31 +64,6 @@ cfr-doorhanger-extension-total-users =
*[other] { $total } users
}
## Cookie Banner Handling Onboarding
# Simplified version of the headline if the original text doesn't work
# in your language: `See fewer cookie requests`.
cfr-cookie-banner-handling-header = Cookie banners begone!
cfr-cookie-banner-handling-body = Allow { -brand-short-name } to automatically reject all cookie banner requests, when possible. Otherwise, all cookies will be accepted to dismiss even more banners.
cfr-cookie-banner-accept-button = Dismiss Requests
.accesskey = D
cfr-cookie-banner-reject-button = Not Now
.accesskey = N
cfr-cookie-banner-handling-header-variant-1 = See fewer cookie pop-ups
cfr-cookie-banner-handling-body-variant-1 = Let { -brand-short-name } automatically answer cookie pop-ups for you so you can get back to distraction-free browsing. { -brand-short-name } will reject all requests if possible, or accept all if not.
cfr-cookie-banner-accept-button-variant-1 = Dismiss Pop-ups
.accesskey = D
cfr-cookie-banner-reject-button-variant-1 = No thanks
.accesskey = N
cfr-cookie-banner-handling-header-variant-2 = Cookie Banner Reduction
cfr-cookie-banner-handling-body-variant-2 = Allow { -brand-short-name } to decline a sites cookie consent request if possible or accept cookie access when not possible?
cfr-cookie-banner-accept-button-variant-2 = Allow
.accesskey = A
cfr-cookie-banner-reject-button-variant-2 = Not now
.accesskey = N
## Firefox Accounts Message
cfr-doorhanger-bookmark-fxa-header = Sync your bookmarks everywhere.

View file

@ -38,7 +38,7 @@ etp-card-title-always = Enhanced Tracking Protection: Always On
etp-card-title-custom-not-blocking = Enhanced Tracking Protection: OFF
etp-card-content-description = { -brand-short-name } automatically stops companies from secretly following you around the web.
protection-report-etp-card-content-custom-not-blocking = All protections are currently turned off. Choose which trackers to block by managing your { -brand-short-name } protections settings.
protection-report-manage-protections = Manage Settings
protection-report-manage-protections = Manage settings
# This string is used to label the X axis of a graph. Other days of the week are generated via Intl.DateTimeFormat,
# capitalization for this string should match the output for your locale.
@ -74,10 +74,10 @@ lockwise-title = Never forget a password again
passwords-title-logged-in = Manage your passwords
passwords-header-content = { -brand-product-name } securely stores your passwords in your browser.
lockwise-header-content-logged-in = Securely store and sync your passwords to all your devices.
protection-report-passwords-save-passwords-button = Save Passwords
.title = Save Passwords
protection-report-passwords-manage-passwords-button = Manage Passwords
.title = Manage Passwords
protection-report-passwords-save-passwords-button = Save passwords
.title = Save passwords
protection-report-passwords-manage-passwords-button = Manage passwords
.title = Manage passwords
# Variables:
@ -103,7 +103,7 @@ monitor-title = Look out for data breaches
monitor-link = How it works
monitor-header-content-no-account = Check { -monitor-brand-name } to see if youve been part of a known data breach, and get alerts about new breaches.
monitor-header-content-signed-in = { -monitor-brand-name } warns you if your info has appeared in a known data breach.
monitor-sign-up-link = Sign Up for Breach Alerts
monitor-sign-up-link = Sign up for breach alerts
.title = Sign up for breach alerts on { -monitor-brand-name }
auto-scan = Automatically scanned today
@ -161,11 +161,11 @@ info-exposed-passwords-resolved =
monitor-no-breaches-title = Good news!
monitor-no-breaches-description = You have no known breaches. If that changes, we will let you know.
monitor-view-report-link = View Report
monitor-view-report-link = View report
.title = Resolve breaches on { -monitor-brand-short-name }
monitor-breaches-unresolved-title = Resolve your breaches
monitor-breaches-unresolved-description = After reviewing breach details and taking steps to protect your info, you can mark breaches as resolved.
monitor-manage-breaches-link = Manage Breaches
monitor-manage-breaches-link = Manage breaches
.title = Manage breaches on { -monitor-brand-short-name }
monitor-breaches-resolved-title = Nice! Youve resolved all known breaches.
monitor-breaches-resolved-description = If your email appears in any new breaches, we will let you know.
@ -186,7 +186,7 @@ monitor-partial-breaches-motivation-title-start = Great start!
monitor-partial-breaches-motivation-title-middle = Keep it up!
monitor-partial-breaches-motivation-title-end = Almost done! Keep it up.
monitor-partial-breaches-motivation-description = Resolve the rest of your breaches on { -monitor-brand-short-name }.
monitor-resolve-breaches-link = Resolve Breaches
monitor-resolve-breaches-link = Resolve breaches
.title = Resolve breaches on { -monitor-brand-short-name }
## The title attribute is used to display the type of protection.

View file

@ -501,7 +501,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "4730feccc2fce75b03516b1a5f56c4e07c89c766"
"revision": "b8dd5ae8b90e45c9af2de55409420a9143027af1"
},
"es-ES": {
"pin": false,
@ -537,7 +537,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "011b50c8b3fe52c49ae1d1e5df17a4fe1f5ae635"
"revision": "6b86e84a052f8ed46d970e2adf14754e1f4b816a"
},
"et": {
"pin": false,
@ -573,7 +573,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "69d16c0049c7802030f6e47cdb1bf5c5313489ce"
"revision": "a7a842112f33ec8b0982d80e56c7f5f42f5b0910"
},
"fa": {
"pin": false,
@ -951,7 +951,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "3ae00a3d5007c07bac2291331b532b4c49e1449e"
"revision": "a313723650bed22ecbb07be1cc082eb82dec629d"
},
"it": {
"pin": false,
@ -1137,7 +1137,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "e95469adac71b45a2c3e80959b05f76722ebc63c"
"revision": "6b4728134ac009a848996e3e1440e9e3a936a15c"
},
"lt": {
"pin": false,
@ -1371,7 +1371,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "9ccd7ab4899d32072d66add36ba16272c81bf9f6"
"revision": "dca9a96f5acfce3c20d46e70cfbc0668704e41f2"
},
"pa-IN": {
"pin": false,
@ -1497,7 +1497,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "cb42ef06d707058d5bcdb92808170833bda7083f"
"revision": "685f43b7534c582bdc9e6079b81d474f0f9a4726"
},
"sat": {
"pin": false,
@ -1641,7 +1641,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "b1709bf7d6a6dcec466b36abd6d304078a7f0fb7"
"revision": "3dd9a2ad4c4d11c002718d708196adbc951dde11"
},
"son": {
"pin": false,
@ -1713,7 +1713,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "76357c7cd07bb7346e4b2ffb057690987dad8dbf"
"revision": "c65f65dacfc43061c02d2a5a3b2d374369f5d880"
},
"szl": {
"pin": false,
@ -1803,7 +1803,7 @@
"win64-aarch64-devedition",
"win64-devedition"
],
"revision": "ff7d860a5456d852980152ea9ce70a3e34a24434"
"revision": "0f002ed676419fcf5b72cf02025825c9c97f9f98"
},
"tl": {
"pin": false,

View file

@ -30,10 +30,9 @@ export class FeatureCallout {
this.renderObserver = null;
this.savedActiveElement = null;
this.ready = false;
this.listenersRegistered = false;
this._positionListenersRegistered = false;
this.AWSetup = false;
this.page = page;
this.focusHandler = this._focusHandler.bind(this);
XPCOMUtils.defineLazyPreferenceGetter(
this,
@ -74,35 +73,30 @@ export class FeatureCallout {
// any other instances of the parent page. This does not apply when
// the Callout is shown in the browser chrome.
if (this.page !== "chrome") {
this.win.addEventListener(
"visibilitychange",
this._handlePrefChange.bind(this)
);
this.win.addEventListener("visibilitychange", this);
}
}
const positionCallout = this._positionCallout.bind(this);
_addPositionListeners() {
if (!this._positionListenersRegistered) {
this.win.addEventListener("resize", this);
const parentEl = this.doc.querySelector(
this.currentScreen?.parent_selector
);
parentEl?.addEventListener("toggle", this);
this._positionListenersRegistered = true;
}
}
this._addPositionListeners = () => {
if (!this.listenersRegistered) {
this.win.addEventListener("resize", positionCallout);
const parentEl = this.doc.querySelector(
this.currentScreen?.parent_selector
);
parentEl?.addEventListener("toggle", positionCallout);
this.listenersRegistered = true;
}
};
this._removePositionListeners = () => {
if (this.listenersRegistered) {
this.win.removeEventListener("resize", positionCallout);
const parentEl = this.doc.querySelector(
this.currentScreen?.parent_selector
);
parentEl?.removeEventListener("toggle", positionCallout);
this.listenersRegistered = false;
}
};
_removePositionListeners() {
if (this._positionListenersRegistered) {
this.win.removeEventListener("resize", this);
const parentEl = this.doc.querySelector(
this.currentScreen?.parent_selector
);
parentEl?.removeEventListener("toggle", this);
this._positionListenersRegistered = false;
}
}
async _handlePrefChange() {
@ -131,7 +125,7 @@ export class FeatureCallout {
// End the tour according to the tour progress pref or if the user disabled
// contextual feature recommendations.
if (prefVal.complete || !this.cfrFeaturesUserPref) {
this._endTour();
this.endTour();
this.currentScreen = null;
} else if (prefVal.screen !== this.currentScreen?.id) {
this.ready = false;
@ -147,6 +141,76 @@ export class FeatureCallout {
}, TRANSITION_MS);
}
}
handleEvent(event) {
switch (event.type) {
case "focus": {
let container = this.doc.getElementById(CONTAINER_ID);
if (!container) {
return;
}
// If focus has fired on the feature callout window itself, or on something
// contained in that window, ignore it, as we can't possibly place the focus
// on it after the callout is closd.
if (
event.target.id === CONTAINER_ID ||
(Node.isInstance(event.target) && container.contains(event.target))
) {
return;
}
// Save this so that if the next focus event is re-entering the popup,
// then we'll put the focus back here where the user left it once we exit
// the feature callout series.
this.savedActiveElement = this.doc.activeElement;
break;
}
case "keypress": {
if (event.key !== "Escape") {
return;
}
let container = this.doc.getElementById(CONTAINER_ID);
if (!container) {
return;
}
let focusedElement =
this.page === "chrome"
? Services.focus.focusedElement
: this.doc.activeElement;
// If the window has a focused element, let it handle the ESC key instead.
if (
!focusedElement ||
focusedElement === this.doc.body ||
focusedElement === this.browser ||
container.contains(focusedElement)
) {
this.win.AWSendEventTelemetry?.({
event: "DISMISS",
event_context: {
source: `KEY_${event.key}`,
page: this.page,
},
message_id: this.config?.id.toUpperCase(),
});
this._dismiss();
event.preventDefault();
}
break;
}
case "visibilitychange":
this._handlePrefChange();
break;
case "resize":
case "toggle":
this._positionCallout();
break;
default:
}
}
_addCalloutLinkElements() {
const addStylesheet = href => {
if (this.doc.querySelector(`link[href="${href}"]`)) {
@ -588,7 +652,7 @@ export class FeatureCallout {
);
this.win.AWSendToParent = (name, data) => receive(name)(data);
this.win.AWFinish = () => {
this._endTour();
this.endTour();
};
this.AWSetup = true;
}
@ -606,12 +670,14 @@ export class FeatureCallout {
windowFuncs.forEach(func => delete this.win[func]);
}
_endTour(skipFadeOut = false) {
// We don't want focus events that happen during teardown to effect
endTour(skipFadeOut = false) {
// We don't want focus events that happen during teardown to affect
// this.savedActiveElement
this.win.removeEventListener("focus", this.focusHandler, {
this.win.removeEventListener("focus", this, {
capture: true,
passive: true,
});
this.win.removeEventListener("keypress", this, { capture: true });
this.win.pageEventManager?.clear();
// We're deleting featureTourProgress here to ensure that the
@ -638,6 +704,15 @@ export class FeatureCallout {
);
}
_dismiss() {
let action = this.currentScreen?.content.dismiss_button?.action;
if (action?.type) {
this.win.AWSendToParent("SPECIAL_ACTION", action);
} else {
this.endTour();
}
}
async _addScriptsAndRender() {
const reactSrc = "resource://activity-stream/vendor/react.js";
const domSrc = "resource://activity-stream/vendor/react-dom.js";
@ -724,28 +799,6 @@ export class FeatureCallout {
}
}
_focusHandler(e) {
let container = this.doc.getElementById(CONTAINER_ID);
if (!container) {
return;
}
// If focus has fired on the feature callout window itself, or on something
// contained in that window, ignore it, as we can't possibly place the focus
// on it after the callout is closd.
if (
e.target.id === CONTAINER_ID ||
(Node.isInstance(e.target) && container.contains(e.target))
) {
return;
}
// Save this so that if the next focus event is re-entering the popup,
// then we'll put the focus back here where the user left it once we exit
// the feature callout series.
this.savedActiveElement = this.doc.activeElement;
}
/**
* For each member of the screen's page_event_listeners array, add a listener.
* @param {Array<PageEventListener>} listeners An array of listeners to set up
@ -811,7 +864,7 @@ export class FeatureCallout {
event_context: { source: `PAGE_EVENT:${source}`, page },
message_id,
});
this._endTour();
this._dismiss();
}
}
@ -867,11 +920,13 @@ export class FeatureCallout {
this._attachPageEventListeners(
this.currentScreen?.content?.page_event_listeners
);
this.win.addEventListener("keypress", this, { capture: true });
this._positionCallout();
let container = this.doc.getElementById(CONTAINER_ID);
container.focus();
this.win.addEventListener("focus", this.focusHandler, {
this.win.addEventListener("focus", this, {
capture: true, // get the event before retargeting
passive: true,
});
});
});

View file

@ -781,16 +781,12 @@ class GeolocationPermissionPrompt extends PermissionPromptForRequest {
name: this.getPrincipalName(),
};
if (this.principal.schemeIs("file")) {
options.checkbox = { show: false };
} else {
// Don't offer "always remember" action in PB mode
options.checkbox = {
show: !lazy.PrivateBrowsingUtils.isWindowPrivate(
this.browser.ownerGlobal
),
};
}
// Don't offer "always remember" action in PB mode
options.checkbox = {
show: !lazy.PrivateBrowsingUtils.isWindowPrivate(
this.browser.ownerGlobal
),
};
if (this.request.isRequestDelegatedToUnsafeThirdParty) {
// Second name should be the third party origin
@ -919,16 +915,12 @@ class XRPermissionPrompt extends PermissionPromptForRequest {
name: this.getPrincipalName(),
};
if (this.principal.schemeIs("file")) {
options.checkbox = { show: false };
} else {
// Don't offer "always remember" action in PB mode
options.checkbox = {
show: !lazy.PrivateBrowsingUtils.isWindowPrivate(
this.browser.ownerGlobal
),
};
}
// Don't offer "always remember" action in PB mode
options.checkbox = {
show: !lazy.PrivateBrowsingUtils.isWindowPrivate(
this.browser.ownerGlobal
),
};
if (options.checkbox.show) {
options.checkbox.label = lazy.gBrowserBundle.GetStringFromName(
@ -1243,16 +1235,12 @@ class MIDIPermissionPrompt extends SitePermsAddonInstallRequest {
name: this.getPrincipalName(),
};
if (this.principal.schemeIs("file")) {
options.checkbox = { show: false };
} else {
// Don't offer "always remember" action in PB mode
options.checkbox = {
show: !lazy.PrivateBrowsingUtils.isWindowPrivate(
this.browser.ownerGlobal
),
};
}
// Don't offer "always remember" action in PB mode
options.checkbox = {
show: !lazy.PrivateBrowsingUtils.isWindowPrivate(
this.browser.ownerGlobal
),
};
if (options.checkbox.show) {
options.checkbox.label = lazy.gBrowserBundle.GetStringFromName(

View file

@ -18,11 +18,21 @@ add_task(async function test_geo_permission_prompt() {
await testPrompt(PermissionUI.GeolocationPermissionPrompt);
});
// Tests that GeolocationPermissionPrompt works as expected with local files
add_task(async function test_geo_permission_prompt_local_file() {
await testPrompt(PermissionUI.GeolocationPermissionPrompt, true);
});
// Tests that XRPermissionPrompt works as expected
add_task(async function test_xr_permission_prompt() {
await testPrompt(PermissionUI.XRPermissionPrompt);
});
// Tests that XRPermissionPrompt works as expected with local files
add_task(async function test_xr_permission_prompt_local_file() {
await testPrompt(PermissionUI.XRPermissionPrompt, true);
});
// Tests that DesktopNotificationPermissionPrompt works as expected
add_task(async function test_desktop_notification_permission_prompt() {
Services.prefs.setBoolPref(
@ -57,6 +67,18 @@ add_task(async function test_midi_permission_prompt() {
await testPrompt(PermissionUI.MIDIPermissionPrompt);
});
// Tests that MidiPrompt works as expected with local files
add_task(async function test_midi_permission_prompt_local_file() {
if (Services.prefs.getBoolPref(SITEPERMS_ADDON_PROVIDER_PREF, false)) {
ok(
true,
"PermissionUI.MIDIPermissionPrompt uses SitePermsAddon install flow"
);
return;
}
await testPrompt(PermissionUI.MIDIPermissionPrompt, true);
});
// Tests that StoragePermissionPrompt works as expected
add_task(async function test_storage_access_permission_prompt() {
Services.prefs.setBoolPref("dom.storage_access.auto_grants", false);
@ -64,11 +86,11 @@ add_task(async function test_storage_access_permission_prompt() {
Services.prefs.clearUserPref("dom.storage_access.auto_grants");
});
async function testPrompt(Prompt) {
async function testPrompt(Prompt, useLocalFile = false) {
await BrowserTestUtils.withNewTab(
{
gBrowser,
url: "http://example.com",
url: useLocalFile ? `file://${PathUtils.tempDir}` : "http://example.com",
},
async function(browser) {
let mockRequest = makeMockPermissionRequest(browser);

View file

@ -227,45 +227,6 @@ moz-input-box > menupopup .context-menu-add-engine > .menu-iconic-left {
should be shared by all editBookmarkPanel.inc.xhtml consumers should be in
editBookmark.css. */
#editBMPanel_newFolderBox {
background-color: var(--arrowpanel-field-background);
color: inherit;
border: 1px solid var(--panel-separator-color);
border-radius: 0 0 2px 2px;
margin: 0;
padding: 0;
height: 24px;
}
#editBMPanel_newFolderButton {
appearance: none;
-moz-box-flex: 1;
-moz-context-properties: fill, fill-opacity;
fill: currentColor;
fill-opacity: 0.8;
border: none;
border-radius: 0;
padding: 0 9px;
margin: 0;
min-height: 24px;
height: 24px;
color: inherit;
list-style-image: url("chrome://global/skin/icons/plus.svg");
}
#editBMPanel_newFolderButton:hover {
background-color: var(--arrowpanel-dimmed);
}
#editBMPanel_newFolderButton:hover:active {
background-color: var(--arrowpanel-dimmed-further);
}
#editBMPanel_newFolderButton .button-text {
-moz-box-flex: 1; /* push the button icon to the start side */
text-align: start;
}
/**** folder tree and tag selector ****/
#editBMPanel_folderTree,

View file

@ -229,10 +229,13 @@ panel .text-link:-moz-lwtheme:not(:hover) {
* 2) buttons in the toolbar moving horizontally while the window opens,
* because the element is first shown at full width and then completely
* hidden.
* TODO(emilio): The comment above was never quite true (the message did take
* horizontal space, see bug 1812636). Figure out how much of this rule is
* really needed.
*/
#PersonalToolbar[collapsed=false] > #personal-toolbar-empty[nowidth] > #personal-toolbar-empty-description {
margin-inline: 0;
width: 0;
min-width: 0;
white-space: nowrap;
position: relative;
z-index: 1;

View file

@ -10,6 +10,20 @@
#editBMPanel_folderTree,
#editBMPanel_tagsSelector {
height: 12.5em;
border: 1px solid ThreeDShadow;
border-radius: 4px;
}
#editBMPanel_folderTree {
appearance: none;
overflow: hidden;
margin-block: 2px;
}
@media (-moz-platform: macos) {
#editBMPanel_folderTree {
margin: 6px 4px 0;
}
}
#editBMPanel_folderMenuList::part(icon) {
@ -35,16 +49,6 @@
fill: currentColor;
}
#editBMPanel_folderTree {
margin-block: 2px;
}
@media (-moz-platform: macos) {
#editBMPanel_folderTree {
margin: 6px 4px 0;
}
}
#editBMPanel_tagsSelector > richlistitem > image {
appearance: auto;
-moz-default-appearance: checkbox;

View file

@ -400,6 +400,17 @@
flex-grow: 1;
flex-shrink: 1;
min-width: 0;
overflow: hidden;
}
.urlbarView-dynamic-weather-summary[overflow],
.urlbarView-dynamic-weather-middleNoWrap[overflow] {
mask-image: linear-gradient(to left, transparent, black 2em);
}
.urlbarView-dynamic-weather-summary[overflow]:-moz-locale-dir(rtl),
.urlbarView-dynamic-weather-middleNoWrap[overflow]:-moz-locale-dir(rtl) {
mask-image: linear-gradient(to right, transparent, black 2em);
}
.urlbarView-dynamic-weather-top {
@ -412,42 +423,50 @@
align-items: center;
}
.urlbarView-results[wrap] > .urlbarView-row[dynamicType=weather] > .urlbarView-row-inner .urlbarView-dynamic-weather-top {
flex-wrap: wrap;
}
.urlbarView-results[wrap] > .urlbarView-row[dynamicType=weather] > .urlbarView-row-inner > .urlbarView-dynamic-weather-summary > .urlbarView-dynamic-weather-top > .urlbarView-dynamic-weather-topNoWrap > .urlbarView-dynamic-weather-titleSeparator {
display: none;
}
.urlbarView-dynamic-weather-middle {
font-size: 0.85em;
display: flex;
align-items: center;
flex-wrap: wrap;
}
.urlbarView-dynamic-weather-middleNoWrap {
display: inline-flex;
align-items: center;
overflow: hidden;
}
/* When middleNoWrap has overflowed, we want to hide the summaryTextSeparator.
We also want to keep the overflow state stable without it going back to
an underflow state. This is why we are using `visibility: hidden` so the
space is allocated for the summaryTextSeparator and highLow but they are
not visible on the page. Thus, keeping the middleNoWrap in an overflow
state while hiding the summaryTextSeparator.
*/
.urlbarView-dynamic-weather-middleNoWrap[overflow] > .urlbarView-dynamic-weather-summaryTextSeparator,
.urlbarView-dynamic-weather-middleNoWrap[overflow] > .urlbarView-dynamic-weather-highLow {
visibility: hidden;
}
/* The highLowWrap remains hidden when middleNoWrap is not overflowed. Once it
has overflowed, we display the highLowWrap element.
*/
.urlbarView-dynamic-weather-middleNoWrap:not([overflow]) + .urlbarView-dynamic-weather-highLowWrap {
display: none;
}
.urlbarView-dynamic-weather-summaryTextSeparator::before {
content: '\00B7';
margin: 0.25em;
}
.urlbarView-dynamic-weather-highLow {
/* The 100% width is needed so the highLow wraps at the same time as the URL
when the URL has overflowed.
TODO - In a follow-up patch I will fix it so the highLow will wrap when the
highLow has overflowed, it will wrap separte from the URL.*/
width: 100%;
}
.urlbarView-results[wrap] > .urlbarView-row[dynamicType=weather] > .urlbarView-row-inner .urlbarView-dynamic-weather-top,
.urlbarView-results[wrap] > .urlbarView-row[dynamicType=weather] > .urlbarView-row-inner .urlbarView-dynamic-weather-middle {
flex-wrap: wrap;
}
.urlbarView-results[wrap] > .urlbarView-row[dynamicType=weather] > .urlbarView-row-inner > .urlbarView-dynamic-weather-summary >
.urlbarView-dynamic-weather-top > .urlbarView-dynamic-weather-topNoWrap > .urlbarView-dynamic-weather-titleSeparator,
.urlbarView-results[wrap] > .urlbarView-row[dynamicType=weather] > .urlbarView-row-inner > .urlbarView-dynamic-weather-summary >
.urlbarView-dynamic-weather-middle > .urlbarView-dynamic-weather-middleNoWrap > .urlbarView-dynamic-weather-summaryTextSeparator {
display: none;
}
.urlbarView-dynamic-weather-bottom {
font-size: 0.85em;
margin-top: 0.40em;

View file

@ -50,5 +50,4 @@ Environment Variables
The following environment variables are used for cross-compile builds targeting OS X on Linux.
* CROSS_CCTOOLS_PATH: Path to the cctools directory where the cross compiler toolchain is located.
* CROSS_SYSROOT: Path to the OS X SDK directory for cross compile builds.

View file

@ -661,29 +661,13 @@ def main():
extra_cflags2 = []
extra_cxxflags2 = []
extra_asmflags = []
extra_ldflags = []
if is_cross_compile(target):
extra_flags = [
"-mlinker-version=137",
"-B",
"%s/bin" % os.getenv("CROSS_CCTOOLS_PATH"),
"-isysroot",
os.getenv("CROSS_SYSROOT"),
# technically the sysroot flag there should be enough to deduce this,
# but clang needs some help to figure this out.
"-I%s/usr/include" % os.getenv("CROSS_SYSROOT"),
"-iframework",
"%s/System/Library/Frameworks" % os.getenv("CROSS_SYSROOT"),
]
extra_cflags += extra_flags
extra_cxxflags += extra_flags
extra_cflags2 += extra_flags
extra_cxxflags2 += extra_flags
extra_asmflags += extra_flags
extra_ldflags = [
"-Wl,-syslibroot,%s" % os.getenv("CROSS_SYSROOT"),
"-Wl,-dead_strip",
]
# It's unfortunately required to specify the linker used here because
# the linker flags are used in LLVM's configure step before
# -DLLVM_ENABLE_LLD is actually processed.
extra_ldflags = [
"-fuse-ld=lld",
"-Wl,-dead_strip",
]
elif is_linux(target):
extra_cflags = []
extra_cxxflags = []

View file

@ -29,6 +29,8 @@ While we want to help users resolve build-related issues on their systems, we
are unable to help resolve build system issues on all possible operating
systems and versions.
.. _tier_1_hosts:
Tier-1 Hosts and Toolchains
^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -2,8 +2,6 @@ if test `uname -s` = Linux; then
. $topsrcdir/build/macosx/cross-mozconfig.common
fi
export MACOS_SDK_DIR=$MOZ_FETCHES_DIR/MacOSX13.0.sdk
if [ -n "$TASKCLUSTER_PGO_PROFILE_USE" -a -z "$USE_ARTIFACT" ]; then
# Work around https://github.com/llvm/llvm-project/issues/57734
export LDFLAGS=-Wl,-mllvm,--opaque-pointers

View file

@ -92,13 +92,21 @@ def bootstrap_toolchain_tasks(host):
log.warning(str(e))
log.debug(message)
return None
# We only want to use toolchains annotated with "local-toolchain". We also limit the
# amount of data to what we use, so that trace logs can be more useful.
tasks = {
k: {
def task_data(t):
result = {
"index": t.optimization["index-search"],
"artifact": t.attributes["toolchain-artifact"],
}
command = t.attributes.get("toolchain-command")
if command:
result["command"] = command
return result
# We only want to use toolchains annotated with "local-toolchain". We also limit the
# amount of data to what we use, so that trace logs can be more useful.
tasks = {
k: task_data(t)
for k, t in tasks.items()
if t.attributes.get("local-toolchain") and "index-search" in t.optimization
}
@ -154,10 +162,14 @@ def bootstrap_path(path, **kwargs):
task_index = task_index[0].split(".")[-1]
artifact = task["artifact"]
# `mach artifact toolchain` doesn't support authentication for
# private artifacts.
# private artifacts. Some toolchains may provide a command that can be
# used for local production of the artifact.
command = None
if not artifact.startswith("public/"):
log.debug("Cannot bootstrap %s: not a public artifact", label)
return False
command = task.get("command")
if not command:
log.debug("Cannot bootstrap %s: not a public artifact", label)
return False
index_file = os.path.join(toolchains_base_dir, "indices", path_parts[0])
try:
with open(index_file) as fh:
@ -173,22 +185,45 @@ def bootstrap_path(path, **kwargs):
# when e.g. building from a js standalone tarball, that doesn't contain the
# taskgraph code. In those cases, `mach artifact toolchain --from-build` would
# also fail.
try:
IndexSearch = import_module(
"gecko_taskgraph.optimize.strategies"
).IndexSearch
except Exception:
log.debug("Cannot bootstrap %s: missing taskgraph module", label)
return False
task_id = IndexSearch().should_replace_task(task, {}, None, task["index"])
task_id = None
if not command:
try:
IndexSearch = import_module(
"gecko_taskgraph.optimize.strategies"
).IndexSearch
except Exception:
log.debug("Cannot bootstrap %s: missing taskgraph module", label)
return False
task_id = IndexSearch().should_replace_task(
task, {}, None, task["index"]
)
if task_id:
# If we found the task in the index, use the `mach artifact toolchain`
# fast path.
flags = ["--from-task", f"{task_id}:{artifact}"]
command = [
"artifact",
"toolchain",
"--from-task",
f"{task_id}:{artifact}",
]
elif command:
# For private local toolchains, run the associated command.
command = (
[
"python",
os.path.join(
build_env.topsrcdir,
"taskcluster/scripts/misc",
command["script"],
),
]
+ command["arguments"]
+ [path_parts[0]]
)
else:
# Otherwise, use the slower path, which will print a better error than
# we would be able to.
flags = ["--from-build", label]
command = ["artifact", "toolchain", "--from-build", label]
log.info(
"%s bootstrapped toolchain in %s",
@ -201,10 +236,8 @@ def bootstrap_path(path, **kwargs):
sys.executable,
os.path.join(build_env.topsrcdir, "mach"),
"--log-no-times",
"artifact",
"toolchain",
]
+ flags,
+ command,
cwd=toolchains_base_dir,
check=True,
)

View file

@ -95,16 +95,23 @@ with only_when(host_is_osx | target_is_osx):
)
return Version(obj["Version"])
@depends("--with-macos-sdk", host)
def sdk_min_version():
return "13.0"
@depends(
"--with-macos-sdk",
host,
bootstrap_path(
"MacOSX{}.sdk".format(sdk_min_version()),
when=depends("--with-macos-sdk")(lambda x: not x),
),
)
@imports(_from="__builtin__", _import="Exception")
@imports(_from="os.path", _import="isdir")
@imports(_from="os", _import="listdir")
def macos_sdk(sdk, host):
# When we change the SDK we build with, please update the manual SDK
# installation docs:
# https://firefox-source-docs.mozilla.org/setup/macos_build.html#macos-sdk-is-unsupported
sdk_min_version = Version("11.3")
def macos_sdk(sdk, host, bootstrapped):
if bootstrapped:
sdk = [bootstrapped]
if sdk:
sdk = sdk[0]
try:
@ -144,13 +151,10 @@ with only_when(host_is_osx | target_is_osx):
"tools are selected during the Xcode/Developer Tools installation."
% sdk
)
sdk_installation_docs_url = "https://firefox-source-docs.mozilla.org/setup/macos_build.html#macos-sdk-is-unsupported"
if version < sdk_min_version:
if version < Version(sdk_min_version()):
die(
'SDK version "%s" is too old. Please upgrade to at least %s. Try '
"updating your system Xcode. If that's not sufficient, see the manual "
"SDK installation docs: %s"
% (version, sdk_min_version, sdk_installation_docs_url)
"updating your system Xcode." % (version, sdk_min_version())
)
return sdk

View file

@ -42,8 +42,7 @@
using namespace mozilla;
NS_IMPL_CLASSINFO(ContentPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
NS_PRINCIPAL_CID)
NS_IMPL_CLASSINFO(ContentPrincipal, nullptr, 0, NS_PRINCIPAL_CID)
NS_IMPL_QUERY_INTERFACE_CI(ContentPrincipal, nsIPrincipal)
NS_IMPL_CI_INTERFACE_GETTER(ContentPrincipal, nsIPrincipal)

View file

@ -14,8 +14,7 @@
using namespace mozilla;
NS_IMPL_CLASSINFO(ExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
NS_EXPANDEDPRINCIPAL_CID)
NS_IMPL_CLASSINFO(ExpandedPrincipal, nullptr, 0, NS_EXPANDEDPRINCIPAL_CID)
NS_IMPL_QUERY_INTERFACE_CI(ExpandedPrincipal, nsIPrincipal,
nsIExpandedPrincipal)
NS_IMPL_CI_INTERFACE_GETTER(ExpandedPrincipal, nsIPrincipal,

View file

@ -31,8 +31,7 @@
using namespace mozilla;
NS_IMPL_CLASSINFO(NullPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
NS_NULLPRINCIPAL_CID)
NS_IMPL_CLASSINFO(NullPrincipal, nullptr, 0, NS_NULLPRINCIPAL_CID)
NS_IMPL_QUERY_INTERFACE_CI(NullPrincipal, nsIPrincipal)
NS_IMPL_CI_INTERFACE_GETTER(NullPrincipal, nsIPrincipal)

View file

@ -17,8 +17,7 @@
using namespace mozilla;
NS_IMPL_CLASSINFO(SystemPrincipal, nullptr,
nsIClassInfo::SINGLETON | nsIClassInfo::MAIN_THREAD_ONLY,
NS_IMPL_CLASSINFO(SystemPrincipal, nullptr, nsIClassInfo::SINGLETON,
NS_SYSTEMPRINCIPAL_CID)
NS_IMPL_QUERY_INTERFACE_CI(SystemPrincipal, nsIPrincipal, nsISerializable)
NS_IMPL_CI_INTERFACE_GETTER(SystemPrincipal, nsIPrincipal, nsISerializable)

View file

@ -110,7 +110,7 @@ add_task(async function testSimpleSourcesWithManualClickExpand() {
info("Test the copy to clipboard context menu");
const mathMinTreeNode = findSourceNodeWithText(dbg, "math.min.js");
await triggerCopySourceContextMenu(dbg, mathMinTreeNode);
const clipboardData = SpecialPowers.getClipboardData("text/unicode");
const clipboardData = SpecialPowers.getClipboardData("text/plain");
is(
clipboardData,
EXAMPLE_URL + "math.min.js",

View file

@ -99,7 +99,7 @@ add_task(async function() {
// While the decimal one is the line where the line appear in CodeMirror.
// So while we set the breakpoint on the decimal line in CodeMirror gutter,
// internaly, the engine sets the breakpoint on the "virtual line".
const virtualBinaryLine = 0x118;
const virtualBinaryLine = 0x11a;
is(
"0x" + virtualBinaryLine.toString(16),
"0x" + generatedLine.toString(16),

View file

@ -48,6 +48,6 @@ add_task(async function() {
});
function checkClipboardData(expected) {
const actual = SpecialPowers.getClipboardData("text/unicode");
const actual = SpecialPowers.getClipboardData("text/plain");
return decodeURIComponent(actual).trim() === expected.trim();
}

View file

@ -62,6 +62,6 @@ add_task(async function() {
});
function checkClipboardData(expected) {
const actual = SpecialPowers.getClipboardData("text/unicode");
const actual = SpecialPowers.getClipboardData("text/plain");
return actual.trim() === expected.trim();
}

View file

@ -59,6 +59,6 @@ add_task(async function() {
});
function checkClipboardData(expected) {
const actual = SpecialPowers.getClipboardData("text/unicode");
const actual = SpecialPowers.getClipboardData("text/plain");
return actual.trim() === expected.trim();
}

View file

@ -237,7 +237,7 @@ async function copySomeTextAndCheckClipboard(view, positions, expectedPattern) {
}
function checkClipboard(expectedPattern) {
const actual = SpecialPowers.getClipboardData("text/unicode");
const actual = SpecialPowers.getClipboardData("text/plain");
const expectedRegExp = new RegExp(expectedPattern, "g");
return expectedRegExp.test(actual);
}
@ -249,7 +249,7 @@ function failClipboardCheck(expectedPattern) {
expectedPattern = expectedPattern.replace(/\\\(/g, "(");
expectedPattern = expectedPattern.replace(/\\\)/g, ")");
let actual = SpecialPowers.getClipboardData("text/unicode");
let actual = SpecialPowers.getClipboardData("text/plain");
// Trim the right hand side of our strings. This is because expectedPattern
// accounts for windows sometimes adding a newline to our copied data.

View file

@ -330,7 +330,7 @@ async function disableProperty(view, index) {
}
function checkClipboardData(expectedPattern) {
const actual = SpecialPowers.getClipboardData("text/unicode");
const actual = SpecialPowers.getClipboardData("text/plain");
const expectedRegExp = new RegExp(expectedPattern, "g");
return expectedRegExp.test(actual);
}
@ -342,7 +342,7 @@ function failedClipboard(expectedPattern) {
expectedPattern = expectedPattern.replace(/\\\(/g, "(");
expectedPattern = expectedPattern.replace(/\\\)/g, ")");
let actual = SpecialPowers.getClipboardData("text/unicode");
let actual = SpecialPowers.getClipboardData("text/plain");
// Trim the right hand side of our strings. This is because expectedPattern
// accounts for windows sometimes adding a newline to our copied data.

View file

@ -182,7 +182,7 @@ async function checkCopyEditorValue(view) {
}
function checkClipboardData(expectedPattern) {
const actual = SpecialPowers.getClipboardData("text/unicode");
const actual = SpecialPowers.getClipboardData("text/plain");
const expectedRegExp = new RegExp(expectedPattern, "g");
return expectedRegExp.test(actual);
}
@ -194,7 +194,7 @@ function failedClipboard(expectedPattern) {
expectedPattern = expectedPattern.replace(/\\\(/g, "(");
expectedPattern = expectedPattern.replace(/\\\)/g, ")");
let actual = SpecialPowers.getClipboardData("text/unicode");
let actual = SpecialPowers.getClipboardData("text/plain");
// Trim the right hand side of our strings. This is because expectedPattern
// accounts for windows sometimes adding a newline to our copied data.

View file

@ -43,11 +43,11 @@ add_task(async function() {
ok(true, "The eyedropper is now hidden");
info("Check that the clipboard still contains the copied color");
is(SpecialPowers.getClipboardData("text/unicode"), "#ff0000");
is(SpecialPowers.getClipboardData("text/plain"), "#ff0000");
info("Replace the clipboard content with another text");
SpecialPowers.clipboardCopyString("not-a-color");
is(SpecialPowers.getClipboardData("text/unicode"), "not-a-color");
is(SpecialPowers.getClipboardData("text/plain"), "not-a-color");
info("Click on the page again, check the clipboard was not updated");
await BrowserTestUtils.synthesizeMouseAtCenter(
@ -57,7 +57,7 @@ add_task(async function() {
);
// Wait 500ms because nothing is observable when the test is successful.
await wait(500);
is(SpecialPowers.getClipboardData("text/unicode"), "not-a-color");
is(SpecialPowers.getClipboardData("text/plain"), "not-a-color");
finalize();
});

View file

@ -155,7 +155,7 @@ async function testClearedRequests({ tab, monitor, toolbox }) {
connector
);
const jsonString = SpecialPowers.getClipboardData("text/unicode");
const jsonString = SpecialPowers.getClipboardData("text/plain");
const har = JSON.parse(jsonString);
is(har.log.entries.length, 2, "There must be two requests");
is(
@ -233,6 +233,6 @@ async function reloadAndCopyAllAsHar({
connector
);
const jsonString = SpecialPowers.getClipboardData("text/unicode");
const jsonString = SpecialPowers.getClipboardData("text/plain");
return JSON.parse(jsonString);
}

View file

@ -15,12 +15,12 @@ function copyString(string) {
}
/**
* Retrieve the current clipboard data matching the flavor "text/unicode".
* Retrieve the current clipboard data matching the flavor "text/plain".
*
* @return {String} Clipboard text content, null if no text clipboard data is available.
*/
function getText() {
const flavor = "text/unicode";
const flavor = "text/plain";
const xferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(
Ci.nsITransferable

View file

@ -20,7 +20,7 @@ Please obtain an API Token (Settings >> Conduit API Tokens)
Windows dependencies
--------------------
#. You need 64-bit version of Windows 7 or later.
#. You need a :ref:`supported version of Windows<tier_1_hosts>`.
#. Download and install `Visual Studio Community Edition. <https://visualstudio.microsoft.com/downloads/>`__
#. Finally download the `MozillaBuild Package. <https://ftp.mozilla.org/pub/mozilla/libraries/win32/MozillaBuildSetup-Latest.exe>`__ Installation directory should be:

View file

@ -3295,6 +3295,61 @@ The installer for Windows.
- Firefox::Installer
DevTools
~~~~~~~~
Mozilla Developer Tools
.. list-table::
:stub-columns: 1
:widths: 30 70
* - Owner(s)
-
| `Jan Honza Odvarko (Honza) <https://people.mozilla.org/s?query=Honza>`__
* - Peer(s)
-
| `Alexandre Poirot (ochameau) <https://people.mozilla.org/s?query=ochameau>`__
| `Julian Descottes (jdescottes) <https://people.mozilla.org/s?query=jdescottes>`__
| `Nicolas Chevobbe (nchevobbe) <https://people.mozilla.org/s?query=nchevobbe>`__
| `Hubert Boma Manilla (bomsy) <https://people.mozilla.org/s?query=bomsy>`__
| `Henrik Skupin (whimboo) <https://people.mozilla.org/s?query=whimboo>`__
* - Owner(s) Emeritus
- Patrick Brosset, Joe Walker, Dave Camp, Rob Campbell
* - Peer(s) Emeritus
- Mihai Șucan, Heather Arthur, Anton Kovalyov, Brandon Benvie, Eddy Bruel, James Long, Matteo Ferretti, Steve Fink (heapsnapshot code), Jaroslav Šnajdr, Tom Tromey, Paul Rouget, Victor Porof, Lin Clark, Jan Keromnes, Jordan Santell, Soledad Penadés, Mike Ratcliffe, Panagiotis Astithas, Tim Nguyen, Brian Grinstead, J. Ryan Stinnett, Jason Laster, David Walsh, Greg Tatum, Gabriel Luong, Brad Werth, Daisuke Akatsuka, Yulia Startsev, Logan Smyth, Julien Wajsberg, Razvan Caliman, Micah Tigley, Nick Fitzgerald, Jim Blandy, Belén Albeza
* - Includes
-
| `devtools/\*\*/\* <https://searchfox.org/mozilla-central/search?q=&path=devtools/\*\*/\*>`__
* - URL
- http://firefox-dev.tools/
* - Bugzilla Components
- DevTools
JavaScript usage, tools, and style
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Aspects of JavaScript use such as language feature usage, tooling such as lint configurations, formatting and naming style.
.. list-table::
:stub-columns: 1
:widths: 30 70
* - Owner(s)
-
| `Dave Townsend (mossop) <https://people.mozilla.org/s?query=mossop>`__
* - Peer(s)
-
| `Gijs <https://people.mozilla.org/s?query=Gijs>`__
| `Mark Banner (standard8) <https://people.mozilla.org/s?query=standard8>`__
| `Jan de Mooij (jandem) <https://people.mozilla.org/s?query=jandem>`__
* - Includes
-
| `.eslintrc-test-paths.js <https://searchfox.org/mozilla-central/search?q=&path=.eslintrc-test-paths.js>`__
| `\*\*/.eslintignore <https://searchfox.org/mozilla-central/search?q=&path=\*\*/.eslintignore>`__
| `\*\*/.eslintrc.js <https://searchfox.org/mozilla-central/search?q=&path=\*\*/.eslintrc.js>`__
| `tools/lint/eslint/\*\*/\* <https://searchfox.org/mozilla-central/search?q=&path=tools/lint/eslint/\*\*/\*>`__
Marionette
~~~~~~~~~~
Marionette is a remote protocol that lets out-of-process programs communicate with, instrument, and control Gecko-based browsers. Combined with geckodriver, this forms our WebDriver implementation.
@ -3380,6 +3435,62 @@ Aspects of Python use such as tooling, formatting and naming style
* - Bugzilla Components
- Developer Infrastructure :: Lint and Formatting
Remote Protocol
~~~~~~~~~~~~~~~
Low-level remote protocol exposing interfaces for inspecting state and controlling execution of web documents, instrumenting various subsystems in the browser, simulating user interaction for automation purposes, and for subscribing to updates from the aforementioned.
.. list-table::
:stub-columns: 1
:widths: 30 70
* - Owner(s)
-
| `Henrik Skupin (whimboo) <https://people.mozilla.org/s?query=whimboo>`__
* - Peer(s)
-
| `Julian Descottes (jdescottes) <https://people.mozilla.org/s?query=jdescottes>`__
* - Owner(s) Emeritus
- Andreas Tolfsen
* - Peer(s) Emeritus
- Maja Frydrychowicz, Alexandre Poirot, Yulia Startsev
* - Includes
-
| `remote/\*\*/\* <https://searchfox.org/mozilla-central/search?q=&path=remote/\*\*/\*>`__
* - URL
- https://firefox-source-docs.mozilla.org/remote/
* - Bugzilla Components
- Remote Protocol
Sync
~~~~
Firefox Sync client
.. list-table::
:stub-columns: 1
:widths: 30 70
* - Owner(s)
-
| `Mark Hammond (markh) <https://people.mozilla.org/s?query=markh>`__
* - Peer(s)
-
| `Lougenia Bailey (lougenia) <https://people.mozilla.org/s?query=lougenia>`__
| `Tarik Eshaq (teshaq) <https://people.mozilla.org/s?query=teshaq>`__
| `Ben Dean-Kawamura (bdk) <https://people.mozilla.org/s?query=bdk>`__
| `Sammy Khamis (skhamis) <https://people.mozilla.org/s?query=skhamis>`__
| `Lina Butler (lina) <https://people.mozilla.org/s?query=lina>`__
* - Owner(s) Emeritus
- Ryan Kelly
* - Includes
-
| `services/sync/\*\*/\* <https://searchfox.org/mozilla-central/search?q=&path=services/sync/\*\*/\*>`__
* - URL
- https://wiki.mozilla.org/Services/Process/Code_Review
* - Bugzilla Components
- Sync
firefox-ui
~~~~~~~~~~
Firefox UI test framework.
@ -3738,3 +3849,34 @@ Webextension APIs and integration.
-
| `browser/components/extensions/\*\*/\* <https://searchfox.org/mozilla-central/search?q=&path=browser/components/extensions/\*\*/\*>`__
| `toolkit/components/extensions/\*\*/\* <https://searchfox.org/mozilla-central/search?q=&path=toolkit/components/extensions/\*\*/\*>`__
URL Classifier
~~~~~~~~~~~~~~
Database and list-based classification of URL resources, such as Tracking Protection and SafeBrowsing.
.. list-table::
:stub-columns: 1
:widths: 30 70
* - Owner(s)
-
| `Dimi Lee (dlee) <https://people.mozilla.org/s?query=dlee>`__
| `Luke Crouch (groovecoder) <https://people.mozilla.org/s?query=groovecoder>`__
* - Peer(s)
-
| `Tim Huang (timhuang) <https://people.mozilla.org/s?query=timhuang>`__
| `Gian-Carlo Pascutto (gcp) <https://people.mozilla.org/s?query=gcp>`__
* - Owner(s) Emeritus
- François Marier
* - Peer(s) Emeritus
- Henry Chang, Ryan Tilder
* - Includes
-
| `toolkit/components/url-classifier/\*\*/\* <https://searchfox.org/mozilla-central/search?q=&path=toolkit/components/url-classifier/\*\*/\*>`__
| `netwerk/url-classifier/\*\*/\* <https://searchfox.org/mozilla-central/search?q=&path=netwerk/url-classifier/\*\*/\*>`__
* - Group
- dev-platform
* - URL
- https://github.com/mozilla-services/shavar https://wiki.mozilla.org/Phishing_Protection https://wiki.mozilla.org/Security/Tracking_protection https://wiki.mozilla.org/Security/Application_Reputation

View file

@ -74,10 +74,10 @@ You can test that Mercurial is installed by running:
.. code-block:: shell
# If you're using zsh
echo "export PATH=\"$(python3 -m site --user-base)/bin:$PATH\"" >> ~/.zshenv
echo 'export PATH="'"$(python3 -m site --user-base)"'/bin:$PATH"' >> ~/.zshenv
# If you're using bash
echo "export PATH=\"$(python3 -m site --user-base)/bin:$PATH\"" >> ~/.bashrc
echo 'export PATH="'"$(python3 -m site --user-base)"'/bin:$PATH"' >> ~/.bashrc
# If you're using a different shell, follow its documentation to see
# how to configure your PATH. Ensure that `$(python3 -m site --user-base)/bin`

View file

@ -49,7 +49,7 @@ both ``hg`` and ``moz-phab`` will be easily accessible:
.. code-block:: shell
echo "export PATH=\"$(python3 -m site --user-base)/bin:$PATH\"" >> ~/.zshenv
echo 'export PATH="'"$(python3 -m site --user-base)"'/bin:$PATH"' >> ~/.zshenv
python3 -m pip install --user mercurial==6.1.4
Now, restart your shell so that the ``PATH`` change took effect.
@ -120,41 +120,3 @@ say hello in the `Introduction channel
start working on <https://codetribute.mozilla.org/>`_.
See the :ref:`Firefox Contributors' Quick Reference` to learn how to test your changes,
send patches to Mozilla, update your source code locally, and more.
Troubleshooting
---------------
macOS SDK is unsupported
~~~~~~~~~~~~~~~~~~~~~~~~
.. only:: comment
If you are editing this section to bump the SDK and Xcode version, I'd recommend
following the steps to ensure that they're not obsolete. Apple doesn't guarantee
the structure of Xcode, so the SDK could be moved to a different location or
stored differently.
If the SDK included with your Xcode installation is not supported by Firefox,
you'll need to manually install one that is compatible.
We're currently using the 11 SDK on our build servers, so that's the one that you
should install:
1. Go to the `More Downloads for Apple Developers <https://developer.apple.com/download/more/>`_ page
and download Xcode 12.5.1.
2. Once downloaded, extract ``Xcode_12.5.1.xip``.
3. In your terminal, copy the SDK from the installer:
.. code-block:: shell
mkdir -p ~/.mozbuild/macos-sdk
# This assumes that Xcode is in your "Downloads" folder
cp -aH ~/Downloads/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk ~/.mozbuild/macos-sdk/
4. Finally, inform the Firefox build about this SDK by creating (or editing) a file called ``mozconfig`` file
in the Firefox source code directory. Add the following line:
.. code-block::
ac_add_options --with-macos-sdk=$HOME/.mozbuild/macos-sdk/MacOSX11.3.sdk
5. Now, you should be able to successfully run ``./mach build``.

View file

@ -13,6 +13,7 @@ At the time of writing (December, 2022), we currently have the following watersh
* 47.0.2, Windows only. We [added CPU instruction set information to the update URL](https://bugzilla.mozilla.org/show_bug.cgi?id=1271761) to later allow SSE1 to be deprecated.
* 56.0, Windows only. We added support for [sending information about the JAWS accessibility application to the update URL](https://bugzilla.mozilla.org/show_bug.cgi?id=1402376) to avoid updating people on crashy versions of it.
* 72.0.2, all platforms. This is a required version due to a [necessary two-step password database migration](https://bugzilla.mozilla.org/show_bug.cgi?id=1615382).
* 109.0.1, macOS only. This updates the channel-prefs.js file (normally excluded from updates) due to [signature issues](https://bugzilla.mozilla.org/show_bug.cgi?id=1804303).
[^1]: Here is a sample URL: https://aus5.mozilla.org/update/3/Firefox/85.0/20200518093924/WINNT_x86_64-msvc-x64/en-US/release/Windows_NT%2010.0.0.0.18363.1016%20(x64)/default/default/update.xml

View file

@ -2046,7 +2046,7 @@ CanonicalBrowsingContext::ChangeRemoteness(
// process, and then putting our previous document in the BFCache, try to stay
// in the same process to avoid creating new processes unnecessarily.
RefPtr<ContentParent> existingProcess = GetContentParent();
if (existingProcess && existingProcess->IsAlive() &&
if (existingProcess && !existingProcess->IsShuttingDown() &&
aOptions.mReplaceBrowsingContext &&
aOptions.mRemoteType == existingProcess->GetRemoteType()) {
change->mContentParent = existingProcess;

View file

@ -10,6 +10,8 @@
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/HTMLFormElement.h"
#include "mozilla/Encoding.h"
#include "nsGenericHTMLElement.h"
#include "nsQueryObject.h"
#include "MultipartBlobImpl.h"
@ -298,12 +300,37 @@ JSObject* FormData::WrapObject(JSContext* aCx,
return FormData_Binding::Wrap(aCx, this, aGivenProto);
}
// https://xhr.spec.whatwg.org/#dom-formdata
/* static */
already_AddRefed<FormData> FormData::Constructor(
const GlobalObject& aGlobal,
const Optional<NonNull<HTMLFormElement> >& aFormElement, ErrorResult& aRv) {
RefPtr<FormData> formData = new FormData(aGlobal.GetAsSupports());
const Optional<NonNull<HTMLFormElement> >& aFormElement,
nsGenericHTMLElement* aSubmitter, ErrorResult& aRv) {
RefPtr<FormData> formData;
// 1. If form is given, then:
if (aFormElement.WasPassed()) {
// 1.1. If submitter is non-null, then:
if (aSubmitter) {
nsCOMPtr<nsIFormControl> fc = do_QueryObject(aSubmitter);
// 1.1.1. If submitter is not a submit button, then throw a TypeError.
if (!fc || !fc->IsSubmitControl()) {
aRv.ThrowTypeError("The submitter is not a submit button.");
return nullptr;
}
// 1.1.2. If submitter's form owner is not this form element, then throw a
// "NotFoundError" DOMException.
if (fc->GetForm() != &aFormElement.Value()) {
aRv.ThrowNotFoundError("The submitter is not owned by this form.");
return nullptr;
}
}
// 1.2. Let list be the result of constructing the entry list for form and
// submitter.
formData =
new FormData(aGlobal.GetAsSupports(), UTF_8_ENCODING, aSubmitter);
aRv = aFormElement.Value().ConstructEntryList(formData);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
@ -312,6 +339,8 @@ already_AddRefed<FormData> FormData::Constructor(
// Step 9. Return a shallow clone of entry list.
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#constructing-form-data-set
formData = formData->Clone();
} else {
formData = new FormData(aGlobal.GetAsSupports());
}
return formData.forget();

View file

@ -12,6 +12,7 @@
#include "mozilla/dom/HTMLFormSubmission.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FormDataBinding.h"
#include "nsGenericHTMLElement.h"
#include "nsTArray.h"
#include "nsWrapperCache.h"
@ -69,7 +70,7 @@ class FormData final : public nsISupports,
static already_AddRefed<FormData> Constructor(
const GlobalObject& aGlobal,
const Optional<NonNull<HTMLFormElement> >& aFormElement,
ErrorResult& aRv);
nsGenericHTMLElement* aSubmitter, ErrorResult& aRv);
void Append(const nsAString& aName, const nsAString& aValue,
ErrorResult& aRv);

View file

@ -692,7 +692,7 @@ nsresult DragDataProducer::Produce(DataTransfer* aDataTransfer, bool* aCanDrag,
if (NS_SUCCEEDED(rv)) {
data->GetData(mInfoString);
}
rv = transferable->GetTransferData(kUnicodeMime, getter_AddRefs(supports));
rv = transferable->GetTransferData(kTextMime, getter_AddRefs(supports));
data = do_QueryInterface(supports);
NS_ENSURE_SUCCESS(rv, rv); // require plain text at a minimum
data->GetData(mTitleString);

View file

@ -7785,9 +7785,7 @@ void nsContentUtils::CallOnAllRemoteChildren(
bool nsContentUtils::IPCDataTransferItemHasKnownFlavor(
const IPCDataTransferItem& aItem) {
// Unknown types are converted to kCustomTypesMime.
// FIXME(bug 1776879) text/plain is converted to text/unicode still.
if (aItem.flavor().EqualsASCII(kCustomTypesMime) ||
aItem.flavor().EqualsASCII(kUnicodeMime)) {
if (aItem.flavor().EqualsASCII(kCustomTypesMime)) {
return true;
}

View file

@ -93,7 +93,7 @@ static nsresult EncodeForTextUnicode(nsIDocumentEncoder& aEncoder,
// html content with pre-wrap style : text/plain. Otherwise text/html. see
// nsHTMLCopyEncoder::SetSelection
nsAutoString mimeType;
mimeType.AssignLiteral(kUnicodeMime);
mimeType.AssignLiteral("text/unicode");
// Do the first and potentially trial encoding as preformatted and raw.
uint32_t flags = aAdditionalEncoderFlags |
@ -171,7 +171,7 @@ static nsresult EncodeAsTextHTMLWithContext(
}
struct EncodedDocumentWithContext {
// When determening `mSerializationForTextUnicode`, `text/unicode` is passed
// When determining `mSerializationForTextUnicode`, `text/unicode` is passed
// as mime type to the encoder. It uses this as a switch to decide whether to
// encode the document as `text/html` or `text/plain`. It is `true` iff
// `text/html` was used.
@ -274,14 +274,13 @@ static nsresult CreateTransferable(
if (!aEncodedDocumentWithContext.mSerializationForTextUnicode.IsEmpty()) {
// unicode text
// Add the unicode DataFlavor to the transferable
// Add the plain text DataFlavor to the transferable
// If we didn't have this, then nsDataObj::GetData matches
// text/unicode against the kURLMime flavour which is not desirable
// text/plain against the kURLMime flavour which is not desirable
// (eg. when pasting into Notepad)
rv =
AppendString(aTransferable,
aEncodedDocumentWithContext.mSerializationForTextUnicode,
kUnicodeMime);
rv = AppendString(
aTransferable,
aEncodedDocumentWithContext.mSerializationForTextUnicode, kTextMime);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -308,10 +307,9 @@ static nsresult CreateTransferable(
} else {
if (!aEncodedDocumentWithContext.mSerializationForTextUnicode.IsEmpty()) {
// Add the unicode DataFlavor to the transferable
rv =
AppendString(aTransferable,
aEncodedDocumentWithContext.mSerializationForTextUnicode,
kUnicodeMime);
rv = AppendString(
aTransferable,
aEncodedDocumentWithContext.mSerializationForTextUnicode, kTextMime);
NS_ENSURE_SUCCESS(rv, rv);
}
}
@ -475,7 +473,7 @@ nsresult nsCopySupport::ImageCopy(nsIImageLoadingContent* aImageElement,
NS_ENSURE_SUCCESS(rv, rv);
// append the string to the transferable
rv = AppendString(trans, NS_ConvertUTF8toUTF16(location), kUnicodeMime);
rv = AppendString(trans, NS_ConvertUTF8toUTF16(location), kTextMime);
NS_ENSURE_SUCCESS(rv, rv);
}

View file

@ -50,8 +50,8 @@ async function testCopyPaste(isXHTML) {
);
if (!suppressUnicodeCheck) {
ok(
clipboard.hasDataMatchingFlavors(["text/unicode"], 1),
"check text/unicode"
clipboard.hasDataMatchingFlavors(["text/plain"], 1),
"check text/plain"
);
}
if (!suppressHTMLCheck) {
@ -159,7 +159,7 @@ async function testCopyPaste(isXHTML) {
await copyChildrenToClipboard("draggable");
testSelectionToString("This is a draggable bit of text.");
testClipboardValue("text/unicode", "This is a draggable bit of text.");
testClipboardValue("text/plain", "This is a draggable bit of text.");
testHtmlClipboardValue(
"text/html",
'<div id="draggable" title="title to have a long HTML line">This is a <em>draggable</em> bit of text.</div>'
@ -168,7 +168,7 @@ async function testCopyPaste(isXHTML) {
await copyChildrenToClipboard("alist");
testSelectionToString(" bla\n\n foo\n bar\n\n");
testClipboardValue("text/unicode", " bla\n\n foo\n bar\n\n");
testClipboardValue("text/plain", " bla\n\n foo\n bar\n\n");
testHtmlClipboardValue(
"text/html",
'<div id="alist">\n bla\n <ul>\n <li>foo</li>\n \n <li>bar</li>\n </ul>\n </div>'
@ -177,7 +177,7 @@ async function testCopyPaste(isXHTML) {
await copyChildrenToClipboard("blist");
testSelectionToString(" mozilla\n\n foo\n bar\n\n");
testClipboardValue("text/unicode", " mozilla\n\n foo\n bar\n\n");
testClipboardValue("text/plain", " mozilla\n\n foo\n bar\n\n");
testHtmlClipboardValue(
"text/html",
'<div id="blist">\n mozilla\n <ol>\n <li>foo</li>\n \n <li>bar</li>\n </ol>\n </div>'
@ -187,7 +187,7 @@ async function testCopyPaste(isXHTML) {
await copyChildrenToClipboard("clist");
testSelectionToString(" mzla\n\n foo\n bazzinga!\n bar\n\n");
testClipboardValue(
"text/unicode",
"text/plain",
" mzla\n\n foo\n bazzinga!\n bar\n\n"
);
testHtmlClipboardValue(
@ -198,7 +198,7 @@ async function testCopyPaste(isXHTML) {
await copyChildrenToClipboard("div4");
testSelectionToString(" Tt t t ");
testClipboardValue("text/unicode", " Tt t t ");
testClipboardValue("text/plain", " Tt t t ");
if (isXHTML) {
testHtmlClipboardValue(
"text/html",
@ -219,7 +219,7 @@ async function testCopyPaste(isXHTML) {
await copyChildrenToClipboard("div5");
testSelectionToString(" T ");
testClipboardValue("text/unicode", " T ");
testClipboardValue("text/plain", " T ");
if (isXHTML) {
testHtmlClipboardValue(
"text/html",
@ -248,7 +248,7 @@ async function testCopyPaste(isXHTML) {
testSelectionToString("");
// START Disabled due to bug 564688
if (false) {
testClipboardValue("text/unicode", "");
testClipboardValue("text/plain", "");
testClipboardValue("text/html", "");
}
// END Disabled due to bug 564688
@ -264,7 +264,7 @@ async function testCopyPaste(isXHTML) {
testSelectionToString("");
// START Disabled due to bug 564688
if (false) {
testClipboardValue("text/unicode", "");
testClipboardValue("text/plain", "");
testClipboardValue("text/html", "");
}
// END Disabled due to bug 564688
@ -280,7 +280,7 @@ async function testCopyPaste(isXHTML) {
testSelectionToString("");
// START Disabled due to bug 564688
if (false) {
testClipboardValue("text/unicode", "");
testClipboardValue("text/plain", "");
testClipboardValue("text/html", "");
}
// END Disabled due to bug 564688
@ -294,7 +294,7 @@ async function testCopyPaste(isXHTML) {
suppressUnicodeCheckIfHidden
);
testSelectionToString("div9");
testClipboardValue("text/unicode", "div9");
testClipboardValue("text/plain", "div9");
testHtmlClipboardValue("text/html", "div9");
testInnerHTML("div9", "div9");
@ -462,20 +462,20 @@ async function testCopyPaste(isXHTML) {
await copyChildrenToClipboard("div13");
testSelectionToString("__");
testClipboardValue("text/unicode", "__");
testClipboardValue("text/plain", "__");
testHtmlClipboardValue("text/html", '<div id="div13">__</div>');
testPasteText("__");
// ============ converting cell boundaries to tabs in tables
await copyToClipboard($("tr1"));
testClipboardValue("text/unicode", "foo\tbar");
testClipboardValue("text/plain", "foo\tbar");
if (!isXHTML) {
// ============ spanning multiple rows
await copyRangeToClipboard($("tr2"), 0, $("tr3"), 0);
testClipboardValue("text/unicode", "1\t2\n3\t4\n");
testClipboardValue("text/plain", "1\t2\n3\t4\n");
testHtmlClipboardValue(
"text/html",
'<table><tbody><tr id="tr2"><tr id="tr2"><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr><tr id="tr3"></tr></tr></tbody></table>'
@ -487,7 +487,7 @@ async function testCopyPaste(isXHTML) {
addRange($("tr2"), 0, $("tr2"), 2);
addRange($("tr3"), 0, $("tr3"), 2);
await copySelectionToClipboard();
testClipboardValue("text/unicode", "1\t2\n5\t6");
testClipboardValue("text/plain", "1\t2\n5\t6");
testHtmlClipboardValue(
"text/html",
'<table><tbody><tr id="tr2"><td>1</td><td>2</td></tr><tr id="tr3"><td>5</td><td>6</td></tr></tbody></table>'
@ -502,7 +502,7 @@ async function testCopyPaste(isXHTML) {
$("div11").childNodes[1],
2
);
testClipboardValue("text/unicode", "Xdiv11");
testClipboardValue("text/plain", "Xdiv11");
testHtmlClipboardValue("text/html", "<div><p>X<span>div</span>11</p></div>");
await new Promise(resolve => {
@ -520,7 +520,7 @@ async function testCopyPaste(isXHTML) {
2
);
testClipboardValue("text/unicode", "Xdiv12");
testClipboardValue("text/plain", "Xdiv12");
testHtmlClipboardValue("text/html", "<div><p>X<span>div</span>12</p></div>");
await new Promise(resolve => {
setTimeout(resolve, 0);
@ -539,18 +539,18 @@ async function testCopyPaste(isXHTML) {
// Ruby annotation is included when selecting inside ruby.
await copyRangeToClipboard(ruby1, 0, ruby1, 6);
testClipboardValue("text/unicode", "aabb(AABB)");
testClipboardValue("text/plain", "aabb(AABB)");
// Ruby annotation is ignored when selecting across ruby.
await copyRangeToClipboard(ruby1Container, 0, ruby1Container, 3);
testClipboardValue("text/unicode", "XaabbY");
testClipboardValue("text/plain", "XaabbY");
// ... unless converter.html2txt.always_include_ruby is set
await SpecialPowers.pushPrefEnv({
set: [["converter.html2txt.always_include_ruby", true]],
});
await copyRangeToClipboard(ruby1Container, 0, ruby1Container, 3);
testClipboardValue("text/unicode", "Xaabb(AABB)Y");
testClipboardValue("text/plain", "Xaabb(AABB)Y");
await SpecialPowers.popPrefEnv();
}
}

View file

@ -59,8 +59,8 @@ function hasExpectedFlavors() {
var cb = Cc["@mozilla.org/widget/clipboard;1"].
getService(Ci.nsIClipboard);
ok(cb.hasDataMatchingFlavors(["text/unicode"], cb.kGlobalClipboard),
"The clipboard has text/unicode");
ok(cb.hasDataMatchingFlavors(["text/plain"], cb.kGlobalClipboard),
"The clipboard has text/plain");
ok(cb.hasDataMatchingFlavors(["text/html"], cb.kGlobalClipboard),
"The clipboard has text/html");

View file

@ -50,7 +50,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=816298
window.getSelection().selectAllChildren(document.getElementById(id));
documentViewer.copySelection();
is(clipboard.hasDataMatchingFlavors(["text/unicode"], 1), true);
is(clipboard.hasDataMatchingFlavors(["text/plain"], 1), true);
is(clipboard.hasDataMatchingFlavors(["text/html"], 1), true);
}
function getClipboardData(mime) {
@ -110,7 +110,7 @@ var clipboardHTML = [
'<p id=\"test5\">This<span style=\"user-select: all\"> text should</span> be copied.</p>',
];
// expected results for clipboard text/unicode
// expected results for clipboard text/plain
var clipboardUnicode = [
'This text should be copied.',
'This text should be copied.',
@ -145,7 +145,7 @@ for (var i = 0; i < originalStrings.length; i++) {
copyChildrenToClipboard(id);
is(window.getSelection().toString(), originalStrings[i], id + ' Selection.toString()');
testHtmlClipboardValue("text/html", clipboardHTML[i], id);
testClipboardValue("text/unicode", clipboardUnicode[i], id);
testClipboardValue("text/plain", clipboardUnicode[i], id);
testInnerHTML(id, innerHTMLStrings[i]);
testPasteText(textareaStrings[i], id + '.innerHTML');
}

View file

@ -80,7 +80,7 @@ async function clipboardTextForElementId(aDomId, aExpectedString) {
function setup() {
synthesizeKey("C", {accelKey: true});
},
"text/unicode");
"text/plain");
return copiedText;
}

View file

@ -57,15 +57,15 @@ function testCopyImage () {
//--------- Let's check the content of the clipboard now.
// Does the clipboard contain text/unicode data ?
ok(clipboard.hasDataMatchingFlavors(["text/unicode"], clipboard.kGlobalClipboard), "clipboard contains unicode text");
// Does the clipboard contain text/plain data ?
ok(clipboard.hasDataMatchingFlavors(["text/plain"], clipboard.kGlobalClipboard), "clipboard contains unicode text");
// Does the clipboard contain text/html data ?
ok(clipboard.hasDataMatchingFlavors(["text/html"], clipboard.kGlobalClipboard), "clipboard contains html text");
// Does the clipboard contain image data ?
ok(clipboard.hasDataMatchingFlavors(["image/png"], clipboard.kGlobalClipboard), "clipboard contains image");
// Is the text/uncodie data correct ?
testClipboardValue('text/unicode', 'about:logo');
// Is the text/plain data correct ?
testClipboardValue('text/plain', 'about:logo');
// Is the text/html data correct ?
var expected = '<img id="logo" src="about:logo">';
if (navigator.platform.includes("Win")) {

View file

@ -6,10 +6,10 @@ This test is different from test_copypaste.html in two ways:
1. The text/html clipboard flavor isn't tested, since nsCopySupport doesn't
produce it for XHTML.
2. The text/unicode flavor isn't tested when the selection is in hidden
2. The text/plain flavor isn't tested when the selection is in hidden
elements, since nsCopySupport doesn't produce text/plain for hidden
elements, and unlike HTML, neither does it produce text/_moz_htmlcontext
and text/_moz_htmlinfo, which the clipboard converts to text/unicode.
and text/_moz_htmlinfo, which the clipboard converts to text/plain.
-->
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>

View file

@ -82,7 +82,7 @@ waitUntilApzStable().then(async function() {
let element = doc.getElementById(id);
dragSelect(element, 0, 60);
await copySelectionToClipboard();
testClipboardValue("text/unicode", element.value.substr(0, 3));
testClipboardValue("text/plain", element.value.substr(0, 3));
}
}

View file

@ -91,7 +91,7 @@ function cutCopyAll(
aSetup,
aNext,
aNext,
"text/unicode",
"text/plain",
WATCH_TIMEOUT,
true
);

View file

@ -1702,6 +1702,11 @@ DOMInterfaces = {
'nativeType': 'mozilla::extensions::ExtensionPort',
},
'ExtensionProxy': {
'headerFile': 'mozilla/extensions/ExtensionProxy.h',
'nativeType': 'mozilla::extensions::ExtensionProxy',
},
'ExtensionRuntime': {
'headerFile': 'mozilla/extensions/ExtensionRuntime.h',
'nativeType': 'mozilla::extensions::ExtensionRuntime',
@ -1712,6 +1717,11 @@ DOMInterfaces = {
'nativeType': 'mozilla::extensions::ExtensionScripting',
},
'ExtensionSetting': {
'headerFile': 'mozilla/extensions/ExtensionSetting.h',
'nativeType': 'mozilla::extensions::ExtensionSetting',
},
'ExtensionTest': {
'headerFile': 'mozilla/extensions/ExtensionTest.h',
'nativeType': 'mozilla::extensions::ExtensionTest',

View file

@ -97,7 +97,7 @@ void Clipboard::ReadRequest::Answer() {
// Mandatory data types defined in
// https://w3c.github.io/clipboard-apis/#mandatory-data-types-x
AutoTArray<nsCString, 3>{nsDependentCString(kHTMLMime),
nsDependentCString(kUnicodeMime),
nsDependentCString(kTextMime),
nsDependentCString(kPNGImageMime)},
nsIClipboard::kGlobalClipboard)
->Then(
@ -123,10 +123,7 @@ void Clipboard::ReadRequest::Answer() {
RefPtr<ClipboardItem::ItemEntry> entry =
MakeRefPtr<ClipboardItem::ItemEntry>(
format.EqualsLiteral(kUnicodeMime)
? NS_ConvertUTF8toUTF16(kTextMime)
: NS_ConvertUTF8toUTF16(format),
format);
NS_ConvertUTF8toUTF16(format), format);
entry->LoadData(*global, *trans);
entries.AppendElement(std::move(entry));
}
@ -152,7 +149,7 @@ void Clipboard::ReadRequest::Answer() {
}
trans->Init(nullptr);
trans->AddDataFlavor(kUnicodeMime);
trans->AddDataFlavor(kTextMime);
clipboardService->AsyncGetData(trans, nsIClipboard::kGlobalClipboard)
->Then(
GetMainThreadSerialEventTarget(), __func__,
@ -160,7 +157,7 @@ void Clipboard::ReadRequest::Answer() {
[trans, p]() {
nsCOMPtr<nsISupports> data;
nsresult rv =
trans->GetTransferData(kUnicodeMime, getter_AddRefs(data));
trans->GetTransferData(kTextMime, getter_AddRefs(data));
nsAutoString str;
if (!NS_WARN_IF(NS_FAILED(rv))) {
@ -681,7 +678,7 @@ already_AddRefed<Promise> Clipboard::WriteText(const nsAString& aData,
nsTArray<RefPtr<ClipboardItem::ItemEntry>> items;
items.AppendElement(MakeRefPtr<ClipboardItem::ItemEntry>(
NS_LITERAL_STRING_FROM_CSTRING(kTextMime), nsLiteralCString(kUnicodeMime),
NS_LITERAL_STRING_FROM_CSTRING(kTextMime), nsLiteralCString(kTextMime),
std::move(data)));
nsTArray<OwningNonNull<ClipboardItem>> sequence;

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