Update On Thu Feb 2 19:59:58 CET 2023
This commit is contained in:
parent
e7c7490f12
commit
8a51308b35
1885 changed files with 39478 additions and 13405 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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()}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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`,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
]);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
);
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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``
|
||||
|
|
|
@ -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 ?? "";
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
|
|
|
@ -83,7 +83,7 @@ function checkPrimarySelection(expectedVal = "") {
|
|||
)
|
||||
) {
|
||||
let primaryAsText = SpecialPowers.getClipboardData(
|
||||
"text/unicode",
|
||||
"text/plain",
|
||||
SpecialPowers.Ci.nsIClipboard.kSelectionClipboard
|
||||
);
|
||||
Assert.equal(primaryAsText, expectedVal);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
ac_add_options --disable-release
|
||||
export MACOS_SDK_DIR=$MOZ_FETCHES_DIR/MacOSX13.0.sdk
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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 site’s 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.
|
||||
|
|
|
@ -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 you’ve 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! You’ve 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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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``.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ async function clipboardTextForElementId(aDomId, aExpectedString) {
|
|||
function setup() {
|
||||
synthesizeKey("C", {accelKey: true});
|
||||
},
|
||||
"text/unicode");
|
||||
"text/plain");
|
||||
return copiedText;
|
||||
}
|
||||
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ function cutCopyAll(
|
|||
aSetup,
|
||||
aNext,
|
||||
aNext,
|
||||
"text/unicode",
|
||||
"text/plain",
|
||||
WATCH_TIMEOUT,
|
||||
true
|
||||
);
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue