68.14.8 - browser

This commit is contained in:
Fedor 2025-04-19 19:10:44 +03:00
parent b05a35282e
commit 2c58d3cb35
678 changed files with 16040 additions and 22500 deletions

View File

@ -1,211 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
var EXPORTED_SYMBOLS = ["BlockedSiteChild"];
const { ActorChild } = ChromeUtils.import(
"resource://gre/modules/ActorChild.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"E10SUtils",
"resource://gre/modules/E10SUtils.jsm"
);
ChromeUtils.defineModuleGetter(
this,
"SafeBrowsing",
"resource://gre/modules/SafeBrowsing.jsm"
);
function getSiteBlockedErrorDetails(docShell) {
let blockedInfo = {};
if (docShell.failedChannel) {
let classifiedChannel = docShell.failedChannel.QueryInterface(
Ci.nsIClassifiedChannel
);
if (classifiedChannel) {
let httpChannel = docShell.failedChannel.QueryInterface(
Ci.nsIHttpChannel
);
let reportUri = httpChannel.URI;
// Remove the query to avoid leaking sensitive data
if (reportUri instanceof Ci.nsIURL) {
reportUri = reportUri
.mutate()
.setQuery("")
.finalize();
}
let triggeringPrincipal = docShell.failedChannel.loadInfo
? E10SUtils.serializePrincipal(
docShell.failedChannel.loadInfo.triggeringPrincipal
)
: null;
blockedInfo = {
list: classifiedChannel.matchedList,
triggeringPrincipal,
provider: classifiedChannel.matchedProvider,
uri: reportUri.asciiSpec,
};
}
}
return blockedInfo;
}
class BlockedSiteChild extends ActorChild {
receiveMessage(msg) {
if (msg.name == "DeceptiveBlockedDetails") {
this.mm.sendAsyncMessage("DeceptiveBlockedDetails:Result", {
blockedInfo: getSiteBlockedErrorDetails(this.mm.docShell),
});
}
}
handleEvent(event) {
if (event.type == "AboutBlockedLoaded") {
this.onAboutBlockedLoaded(event);
} else if (event.type == "click" && event.button == 0) {
this.onClick(event);
}
}
onAboutBlockedLoaded(aEvent) {
let global = this.mm;
let content = aEvent.target.ownerGlobal;
let blockedInfo = getSiteBlockedErrorDetails(global.docShell);
let provider = blockedInfo.provider || "";
let doc = content.document;
/**
* Set error description link in error details.
* For example, the "reported as a deceptive site" link for
* blocked phishing pages.
*/
let desc = Services.prefs.getCharPref(
"browser.safebrowsing.provider." + provider + ".reportURL",
""
);
if (desc) {
doc
.getElementById("error_desc_link")
.setAttribute("href", desc + encodeURIComponent(aEvent.detail.url));
}
// Set other links in error details.
switch (aEvent.detail.err) {
case "malware":
doc
.getElementById("report_detection")
.setAttribute(
"href",
SafeBrowsing.getReportURL("MalwareMistake", blockedInfo) ||
"https://www.stopbadware.org/firefox"
);
doc
.getElementById("learn_more_link")
.setAttribute("href", "https://www.stopbadware.org/firefox");
break;
case "unwanted":
doc
.getElementById("learn_more_link")
.setAttribute(
"href",
"https://www.google.com/about/unwanted-software-policy.html"
);
break;
case "phishing":
doc
.getElementById("report_detection")
.setAttribute(
"href",
SafeBrowsing.getReportURL("PhishMistake", blockedInfo) ||
"https://safebrowsing.google.com/safebrowsing/report_error/?tpl=mozilla"
);
doc
.getElementById("learn_more_link")
.setAttribute("href", "https://www.antiphishing.org//");
break;
}
// Set the firefox support url.
doc
.getElementById("firefox_support")
.setAttribute(
"href",
Services.urlFormatter.formatURLPref("app.support.baseURL") +
"phishing-malware"
);
// Show safe browsing details on load if the pref is set to true.
let showDetails = Services.prefs.getBoolPref(
"browser.xul.error_pages.show_safe_browsing_details_on_load"
);
if (showDetails) {
let details = content.document.getElementById(
"errorDescriptionContainer"
);
details.removeAttribute("hidden");
}
// Set safe browsing advisory link.
let advisoryUrl = Services.prefs.getCharPref(
"browser.safebrowsing.provider." + provider + ".advisoryURL",
""
);
let advisoryDesc = content.document.getElementById("advisoryDescText");
if (!advisoryUrl) {
advisoryDesc.remove();
return;
}
let advisoryLinkText = Services.prefs.getCharPref(
"browser.safebrowsing.provider." + provider + ".advisoryName",
""
);
if (!advisoryLinkText) {
advisoryDesc.remove();
return;
}
content.document.l10n.setAttributes(
advisoryDesc,
"safeb-palm-advisory-desc",
{ advisoryname: advisoryLinkText }
);
content.document
.getElementById("advisory_provider")
.setAttribute("href", advisoryUrl);
}
onClick(event) {
let ownerDoc = event.target.ownerDocument;
if (!ownerDoc) {
return;
}
var reason = "phishing";
if (/e=malwareBlocked/.test(ownerDoc.documentURI)) {
reason = "malware";
} else if (/e=unwantedBlocked/.test(ownerDoc.documentURI)) {
reason = "unwanted";
} else if (/e=harmfulBlocked/.test(ownerDoc.documentURI)) {
reason = "harmful";
}
this.mm.sendAsyncMessage("Browser:SiteBlockedError", {
location: ownerDoc.location.href,
reason,
elementId: event.target.getAttribute("id"),
isTopFrame: ownerDoc.defaultView.parent === ownerDoc.defaultView,
blockedInfo: getSiteBlockedErrorDetails(ownerDoc.defaultView.docShell),
});
}
}

View File

@ -20,7 +20,6 @@ XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]);
XPCOMUtils.defineLazyModuleGetters(this, {
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
BrowserUtils: "resource://gre/modules/BrowserUtils.jsm",
findAllCssSelectors: "resource://gre/modules/css-selector.js",
SpellCheckHelper: "resource://gre/modules/InlineSpellChecker.jsm",
LoginManagerContent: "resource://gre/modules/LoginManagerContent.jsm",
WebNavigationFrames: "resource://gre/modules/WebNavigationFrames.jsm",
@ -575,7 +574,6 @@ class ContextMenuChild extends ActorChild {
let selectionInfo = BrowserUtils.getSelectionDetails(this.content);
let loadContext = this.docShell.QueryInterface(Ci.nsILoadContext);
let userContextId = loadContext.originAttributes.userContextId;
let popupNodeSelectors = findAllCssSelectors(aEvent.composedTarget);
this._setContext(aEvent);
let context = this.context;
@ -652,7 +650,6 @@ class ContextMenuChild extends ActorChild {
customMenuItems,
contentDisposition,
frameOuterWindowID,
popupNodeSelectors,
disableSetDesktopBg,
parentAllowsMixedContent,
};

View File

@ -119,6 +119,7 @@ class LinkHandlerChild extends ActorChild {
case "apple-touch-icon-precomposed":
case "fluid-icon":
isRichIcon = true;
// fall through
case "icon":
if (iconAdded || link.hasAttribute("mask")) {
// Masked icons are not supported yet.

View File

@ -81,7 +81,11 @@ const PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS =
const PREF_SERVICES_SETTINGS_LAST_FETCHED =
"services.settings.last_update_seconds";
const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.", "security.ssl3."];
const PREF_SSL_IMPACT_ROOTS = [
"security.tls.version.",
"security.ssl3.",
"security.tls13.",
];
let formatter = new Services.intl.DateTimeFormat(undefined, {
dateStyle: "long",

View File

@ -104,7 +104,7 @@ class PageStyleChild extends ActorChild {
}
// Skip any stylesheets that don't match the screen media type.
if (currentStyleSheet.media.length > 0) {
if (currentStyleSheet.media.length) {
let mediaQueryList = currentStyleSheet.media.mediaText;
if (!content.matchMedia(mediaQueryList).matches) {
continue;

View File

@ -158,7 +158,6 @@ class PluginChild extends ActorChild {
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(
Ci.nsIPluginHost
);
pluginElement.QueryInterface(Ci.nsIObjectLoadingContent);
let tagMimetype;
let pluginName = gNavigatorBundle.GetStringFromName(
@ -577,8 +576,8 @@ class PluginChild extends ActorChild {
"openPluginUpdatePage",
pluginTag
);
/* FALLTHRU */
/* FALLTHRU */
case "PluginVulnerableNoUpdate":
case "PluginClickToPlay":
this._handleClickToPlayEvent(plugin);
@ -763,14 +762,13 @@ class PluginChild extends ActorChild {
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(
Ci.nsIPluginHost
);
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
// guard against giving pluginHost.getPermissionStringForType a type
// not associated with any known plugin
if (!this.isKnownPlugin(objLoadingContent)) {
if (!this.isKnownPlugin(plugin)) {
return;
}
let permissionString = pluginHost.getPermissionStringForType(
objLoadingContent.actualType
plugin.actualType
);
let principal = doc.defaultView.top.document.nodePrincipal;
let pluginPermission = Services.perms.testPermissionFromPrincipal(
@ -797,8 +795,7 @@ class PluginChild extends ActorChild {
}
onOverlayClick(event) {
let document = event.target.ownerDocument;
let plugin = document.getBindingParent(event.target);
let plugin = event.target.containingShadowRoot.host;
let overlay = this.getPluginUI(plugin, "main");
// Have to check that the target is not the link to update the plugin
if (
@ -826,8 +823,7 @@ class PluginChild extends ActorChild {
if (overlay) {
overlay.removeEventListener("click", this, true);
}
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
if (this.canActivatePlugin(objLoadingContent)) {
if (this.canActivatePlugin(plugin)) {
this._handleClickToPlayEvent(plugin);
}
}
@ -847,7 +843,6 @@ class PluginChild extends ActorChild {
let pluginFound = false;
for (let plugin of plugins) {
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
if (!this.isKnownPlugin(plugin)) {
continue;
}
@ -1110,8 +1105,6 @@ class PluginChild extends ActorChild {
}
setCrashedNPAPIPluginState({ plugin, state, message }) {
// Force a layout flush so the binding is attached.
plugin.clientTop;
let overlay = this.getPluginUI(plugin, "main");
let statusDiv = this.getPluginUI(plugin, "submitStatus");
let optInCB = this.getPluginUI(plugin, "submitURLOptIn");

View File

@ -22,7 +22,6 @@ with Files("WebRTCChild.jsm"):
FINAL_TARGET_FILES.actors += [
'AboutReaderChild.jsm',
'BlockedSiteChild.jsm',
'BrowserTabChild.jsm',
'ClickHandlerChild.jsm',
'ContentSearchChild.jsm',

View File

@ -14,7 +14,7 @@
#endif
#endif
pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul");
pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindowMac.xhtml");
// Enables some extra Extension System Logging (can reduce performance)
pref("extensions.logging.enabled", false);
@ -51,6 +51,9 @@ pref("extensions.webextensions.default-content-security-policy", "script-src 'se
pref("extensions.webextensions.remote", true);
pref("extensions.webextensions.background-delayed-startup", true);
// Disable extensionStorage storage actor by default
pref("devtools.storage.extensionStorage.enabled", false);
// Dictionary download preference
pref("browser.dictionaries.download.url", "data:text/plain,");
@ -199,17 +202,6 @@ pref("browser.warnOnQuit", true);
pref("browser.fullscreen.autohide", true);
pref("browser.overlink-delay", 80);
#ifdef UNIX_BUT_NOT_MAC
pref("browser.urlbar.clickSelectsAll", false);
#else
pref("browser.urlbar.clickSelectsAll", true);
#endif
#ifdef UNIX_BUT_NOT_MAC
pref("browser.urlbar.doubleClickSelectsAll", true);
#else
pref("browser.urlbar.doubleClickSelectsAll", false);
#endif
// Whether using `ctrl` when hitting return/enter in the URL bar
// (or clicking 'go') should prefix 'www.' and suffix
// browser.fixup.alternate.suffix to the URL bar value prior to
@ -272,8 +264,10 @@ pref("browser.urlbar.openintab", false);
pref("browser.urlbar.usepreloadedtopurls.enabled", false);
pref("browser.urlbar.usepreloadedtopurls.expire_days", 14);
// Enable the new Address Bar code.
pref("browser.urlbar.quantumbar", true);
pref("browser.urlbar.update1", false);
pref("browser.urlbar.update1.expandTextOnFocus", false);
pref("browser.urlbar.openViewOnFocus", false);
pref("browser.altClickSave", false);
@ -325,10 +319,6 @@ pref("browser.search.hiddenOneOffs", "");
// Mirrors whether the search-container widget is in the navigation toolbar.
pref("browser.search.widget.inNavBar", true);
#ifndef RELEASE_OR_BETA
pref("browser.search.reset.enabled", true);
#endif
pref("browser.sessionhistory.max_entries", 50);
// Built-in default permissions.
@ -1095,7 +1085,6 @@ pref("services.sync.prefs.sync.browser.newtabpage.activity-stream.section.highli
pref("services.sync.prefs.sync.browser.newtabpage.enabled", true);
pref("services.sync.prefs.sync.browser.newtabpage.pinned", true);
pref("services.sync.prefs.sync.browser.offline-apps.notify", true);
pref("services.sync.prefs.sync.browser.sessionstore.restore_on_demand", true);
pref("services.sync.prefs.sync.browser.startup.homepage", true);
pref("services.sync.prefs.sync.browser.startup.page", true);
pref("services.sync.prefs.sync.browser.tabs.loadInBackground", true);
@ -1135,12 +1124,6 @@ pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true);
pref("services.sync.prefs.sync.privacy.fuzzyfox.enabled", false);
pref("services.sync.prefs.sync.privacy.fuzzyfox.clockgrainus", false);
pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true);
pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true);
pref("services.sync.prefs.sync.privacy.trackingprotection.cryptomining.enabled", true);
pref("services.sync.prefs.sync.privacy.trackingprotection.cryptomining.annotate.enabled", true);
pref("services.sync.prefs.sync.privacy.trackingprotection.fingerprinting.enabled", true);
pref("services.sync.prefs.sync.privacy.trackingprotection.fingerprinting.annotate.enabled", true);
pref("services.sync.prefs.sync.privacy.trackingprotection.pbmode.enabled", true);
pref("services.sync.prefs.sync.privacy.resistFingerprinting", true);
pref("services.sync.prefs.sync.privacy.reduceTimerPrecision", true);
pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.microseconds", true);
@ -1352,8 +1335,6 @@ pref("media.gmp.trial-create.enabled", true);
pref("media.gmp-gmpopenh264.visible", true);
pref("media.gmp-gmpopenh264.enabled", true);
// Switch block autoplay logic to v2, and enable UI.
pref("media.autoplay.enabled.user-gestures-needed", true);
// Set Firefox to block autoplay, asking for permission by default.
pref("media.autoplay.default", 1); // 0=Allowed, 1=Blocked, 5=All Blocked
@ -1414,10 +1395,6 @@ pref("media.gmp-provider.enabled", true);
// Enable blocking access to storage from tracking resources only in nightly
// and early beta. By default the value is 0: BEHAVIOR_ACCEPT
pref("network.cookie.cookieBehavior", 4 /* BEHAVIOR_REJECT_TRACKER */);
// Enable fingerprinting blocking by default only in nightly and early beta.
pref("privacy.trackingprotection.fingerprinting.enabled", true);
// Enable cryptomining blocking by default only in nightly and early beta.
pref("privacy.trackingprotection.cryptomining.enabled", true);
#endif
pref("dom.storage_access.enabled", true);
@ -1428,39 +1405,6 @@ pref("browser.contentblocking.trackingprotection.control-center.ui.enabled", tru
pref("browser.contentblocking.control-center.ui.showBlockedLabels", true);
pref("browser.contentblocking.control-center.ui.showAllowedLabels", false);
pref("browser.contentblocking.cryptomining.preferences.ui.enabled", true);
pref("browser.contentblocking.fingerprinting.preferences.ui.enabled", true);
// Possible values for browser.contentblocking.features.strict pref:
// Tracking Protection:
// "tp": tracking protection enabled
// "-tp": tracking protection disabled
// Tracking Protection in private windows:
// "tpPrivate": tracking protection in private windows enabled
// "-tpPrivate": tracking protection in private windows disabled
// Fingerprinting:
// "fp": fingerprinting blocking enabled
// "-fp": fingerprinting blocking disabled
// Cryptomining:
// "cm": cryptomining blocking enabled
// "-cm": cryptomining blocking disabled
// Cookie behavior:
// "cookieBehavior0": cookie behaviour BEHAVIOR_ACCEPT
// "cookieBehavior1": cookie behaviour BEHAVIOR_REJECT_FOREIGN
// "cookieBehavior2": cookie behaviour BEHAVIOR_REJECT
// "cookieBehavior3": cookie behaviour BEHAVIOR_LIMIT_FOREIGN
// "cookieBehavior4": cookie behaviour BEHAVIOR_REJECT_TRACKER
// "cookieBehavior5": cookie behaviour BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN
// One value from each section must be included in the browser.contentblocking.features.strict pref.
pref("browser.contentblocking.features.strict", "tp,tpPrivate,cookieBehavior4,cm,fp");
// Enable the Report Breakage UI on Nightly and Beta but not on Release yet.
pref("browser.contentblocking.reportBreakage.enabled", false);
// Show report breakage for tracking cookies in all channels.
pref("browser.contentblocking.rejecttrackers.reportBreakage.enabled", true);
pref("browser.contentblocking.reportBreakage.url", "data:text/plain,");
// Enables the new Protections Panel.
#ifdef NIGHTLY_BUILD
pref("browser.protections_panel.enabled", true);
@ -1472,19 +1416,14 @@ pref("privacy.usercontext.about_newtab_segregation.enabled", true);
#ifdef NIGHTLY_BUILD
pref("privacy.userContext.enabled", true);
pref("privacy.userContext.ui.enabled", true);
// 0 disables long press, 1 when clicked, the menu is shown, 2 the menu is
// shown after X milliseconds.
pref("privacy.userContext.longPressBehavior", 2);
#else
pref("privacy.userContext.enabled", false);
pref("privacy.userContext.ui.enabled", false);
// 0 disables long press, 1 when clicked, the menu is shown, 2 the menu is
// shown after X milliseconds.
pref("privacy.userContext.longPressBehavior", 0);
#endif
pref("privacy.userContext.extension", "");
// allows user to open container menu on a left click instead of a new
// tab in the default container
pref("privacy.userContext.newTabContainerOnLeftClick.enabled", false);
// Start the browser in e10s mode
pref("browser.tabs.remote.autostart", true);
@ -1508,30 +1447,11 @@ pref("browser.tabs.crashReporting.requestEmail", false);
pref("browser.tabs.crashReporting.emailMe", false);
pref("browser.tabs.crashReporting.email", "");
// How often to check for CPOW timeouts. CPOWs are only timed out by
// the hang monitor.
pref("dom.ipc.cpow.timeout", 500);
// Causes access on unsafe CPOWs from browser code to throw by default.
pref("dom.ipc.cpows.forbid-unsafe-from-browser", true);
// Enable e10s hang monitoring (slow script checking and plugin hang
// detection).
pref("dom.ipc.processHangMonitor", false);
#if defined(XP_WIN)
// Allows us to deprioritize the processes of background tabs at an OS level
pref("dom.ipc.processPriorityManager.enabled", true);
#endif
#ifdef DEBUG
// Don't report hangs in DEBUG builds. They're too slow and often a
// debugger is attached.
pref("dom.ipc.reportProcessHangs", false);
#else
pref("dom.ipc.reportProcessHangs", true);
#endif
// Don't limit how many nodes we care about on desktop:
pref("reader.parse-node-limit", 0);
@ -1646,13 +1566,6 @@ pref("browser.toolbars.keyboard_navigation", true);
pref("identity.fxaccounts.toolbar.enabled", false);
pref("identity.fxaccounts.toolbar.accessed", false);
// Check bundled JAR and XPI files for corruption.
#ifdef RELEASE_OR_BETA
pref("corroborator.enabled", false);
#else
pref("corroborator.enabled", true);
#endif
// Toolbox preferences
pref("devtools.toolbox.footer.height", 250);
pref("devtools.toolbox.sidebar.width", 500);
@ -1670,7 +1583,6 @@ pref("devtools.command-button-pick.enabled", true);
pref("devtools.command-button-frames.enabled", true);
pref("devtools.command-button-splitconsole.enabled", true);
pref("devtools.command-button-paintflashing.enabled", false);
pref("devtools.command-button-scratchpad.enabled", false);
pref("devtools.command-button-responsive.enabled", true);
pref("devtools.command-button-screenshot.enabled", false);
pref("devtools.command-button-rulers.enabled", false);
@ -1847,23 +1759,6 @@ pref("devtools.netmonitor.har.enableAutoExportToFile", false);
pref("devtools.netmonitor.features.webSockets", false);
#endif
// Scratchpad settings
// - recentFileMax: The maximum number of recently-opened files
// stored. Setting this preference to 0 will not
// clear any recent files, but rather hide the
// 'Open Recent'-menu.
// - lineNumbers: Whether to show line numbers or not.
// - wrapText: Whether to wrap text or not.
// - showTrailingSpace: Whether to highlight trailing space or not.
// - editorFontSize: Editor font size configuration.
// - enableAutocompletion: Whether to enable JavaScript autocompletion.
pref("devtools.scratchpad.recentFilesMax", 10);
pref("devtools.scratchpad.lineNumbers", true);
pref("devtools.scratchpad.wrapText", false);
pref("devtools.scratchpad.showTrailingSpace", false);
pref("devtools.scratchpad.editorFontSize", 12);
pref("devtools.scratchpad.enableAutocompletion", true);
// Enable the Storage Inspector
pref("devtools.storage.enabled", true);
@ -1879,9 +1774,6 @@ pref("devtools.styleeditor.transitions", true);
pref("devtools.screenshot.clipboard.enabled", false);
pref("devtools.screenshot.audio.enabled", true);
// Enable Scratchpad
pref("devtools.scratchpad.enabled", false);
// Make sure the DOM panel is hidden by default
pref("devtools.dom.enabled", false);
@ -1932,13 +1824,6 @@ pref("devtools.webconsole.timestampMessages", false);
pref("devtools.webconsole.sidebarToggle", false);
#endif
// Enable editor mode in the console in Nightly builds.
#if defined(NIGHTLY_BUILD)
pref("devtools.webconsole.features.editor", true);
#else
pref("devtools.webconsole.features.editor", false);
#endif
// Saved editor mode state in the console.
pref("devtools.webconsole.input.editor", false);
@ -2000,13 +1885,6 @@ pref("devtools.responsive.metaViewport.enabled", false);
// The user agent of the viewport.
pref("devtools.responsive.userAgent", "");
// Whether to show the settings onboarding tooltip only in release or beta
// builds.
#if defined(RELEASE_OR_BETA)
pref("devtools.responsive.show-setting-tooltip", true);
#else
pref("devtools.responsive.show-setting-tooltip", false);
#endif
// Show the custom user agent input in Nightly builds.
#if defined(NIGHTLY_BUILD)
pref("devtools.responsive.showUserAgentInput", true);

View File

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Note: this file is included in aboutDialog.xul and preferences/advanced.xul
// Note: this file is included in aboutDialog.xhtml and preferences/advanced.xhtml
// if MOZ_UPDATER is defined.
/* import-globals-from aboutDialog.js */

View File

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Note: this file is included in aboutDialog.xul and preferences/advanced.xul
// Note: this file is included in aboutDialog.xhtml and preferences/advanced.xhtml
// if MOZ_UPDATER is defined.
/* import-globals-from aboutDialog.js */

View File

@ -31,7 +31,7 @@
aria-describedby="version distribution distributionId communityDesc trademark"
>
#ifdef XP_MACOSX
#include macWindow.inc.xul
#include macWindow.inc.xhtml
#endif
<linkset>

View File

@ -6,6 +6,7 @@
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" />
<link rel="stylesheet" type="text/css" media="all"
href="chrome://global/skin/in-content/info-pages.css"/>
<link rel="stylesheet" type="text/css" media="all"

View File

@ -19,7 +19,7 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Security-Policy" content="default-src chrome:" />
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" />
<title>&loadError.label;</title>
<link rel="stylesheet" href="chrome://browser/skin/aboutNetError.css" type="text/css" media="all" />
<!-- If the location of the favicon is changed here, the FAVICON_ERRORPAGE_URL symbol in

View File

@ -6,7 +6,7 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Security-Policy" content="default-src chrome:" />
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" />
<title data-l10n-id="restart-required-title"></title>
<link rel="stylesheet" type="text/css" media="all"
href="chrome://browser/skin/aboutRestartRequired.css"/>

View File

@ -8,7 +8,7 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Security-Policy" content="default-src chrome:" />
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" />
<link rel="stylesheet" type="text/css" media="all"
href="chrome://global/skin/in-content/info-pages.css"/>
<link rel="stylesheet" type="text/css" media="all"

View File

@ -1,152 +0,0 @@
// Error url MUST be formatted like this:
// about:blocked?e=error_code&u=url(&o=1)?
// (o=1 when user overrides are allowed)
// Note that this file uses document.documentURI to get
// the URL (with the format from above). This is because
// document.location.href gets the current URI off the docshell,
// which is the URL displayed in the location bar, i.e.
// the URI that the user attempted to load.
function getErrorCode() {
var url = document.documentURI;
var error = url.search(/e\=/);
var duffUrl = url.search(/\&u\=/);
return decodeURIComponent(url.slice(error + 2, duffUrl));
}
function getURL() {
var url = document.documentURI;
var match = url.match(/&u=([^&]+)&/);
// match == null if not found; if so, return an empty string
// instead of what would turn out to be portions of the URI
if (!match) {
return "";
}
url = decodeURIComponent(match[1]);
// If this is a view-source page, then get then real URI of the page
if (url.startsWith("view-source:")) {
url = url.slice(12);
}
return url;
}
/**
* Check whether this warning page is overridable or not, in which case
* the "ignore the risk" suggestion in the error description
* should not be shown.
*/
function getOverride() {
var url = document.documentURI;
var match = url.match(/&o=1&/);
return !!match;
}
/**
* Attempt to get the hostname via document.location. Fail back
* to getURL so that we always return something meaningful.
*/
function getHostString() {
try {
return document.location.hostname;
} catch (e) {
return getURL();
}
}
function onClickSeeDetails() {
let details = document.getElementById("errorDescriptionContainer");
if (details.hidden) {
details.removeAttribute("hidden");
} else {
details.setAttribute("hidden", "true");
}
}
function initPage() {
var error = "";
switch (getErrorCode()) {
case "malwareBlocked":
error = "malware";
break;
case "deceptiveBlocked":
error = "phishing";
break;
case "unwantedBlocked":
error = "unwanted";
break;
case "harmfulBlocked":
error = "harmful";
break;
default:
return;
}
// Set page contents depending on type of blocked page
// Prepare the title and short description text
let titleText = document.getElementById("errorTitleText");
document.l10n.setAttributes(
titleText,
"safeb-blocked-" + error + "-page-title"
);
let shortDesc = document.getElementById("errorShortDescText");
document.l10n.setAttributes(
shortDesc,
"safeb-blocked-" + error + "-page-short-desc"
);
// Prepare the inner description, ensuring any redundant inner elements are removed.
let innerDesc = document.getElementById("errorInnerDescription");
let innerDescL10nID = "safeb-blocked-" + error + "-page-error-desc-";
if (!getOverride()) {
innerDescL10nID += "no-override";
document.getElementById("ignore_warning_link").remove();
} else {
innerDescL10nID += "override";
}
if (error == "unwanted" || error == "harmful") {
document.getElementById("report_detection").remove();
}
document.l10n.setAttributes(innerDesc, innerDescL10nID, {
sitename: getHostString(),
});
// Add the learn more content:
let learnMore = document.getElementById("learn_more");
document.l10n.setAttributes(
learnMore,
"safeb-blocked-" + error + "-page-learn-more"
);
// Set sitename to bold by adding class
let errorSitename = document.getElementById("error_desc_sitename");
errorSitename.setAttribute("class", "sitename");
let titleEl = document.createElement("title");
document.l10n.setAttributes(
titleEl,
"safeb-blocked-" + error + "-page-title"
);
document.head.appendChild(titleEl);
// Inform the test harness that we're done loading the page.
var event = new CustomEvent("AboutBlockedLoaded", {
bubbles: true,
detail: {
url: this.getURL(),
err: error,
},
});
document.dispatchEvent(event);
}
let seeDetailsButton = document.getElementById("seeDetailsButton");
seeDetailsButton.addEventListener("click", onClickSeeDetails);
// Note: It is important to run the script this way, instead of using
// an onload handler. This is because error pages are loaded as
// LOAD_BACKGROUND, which means that onload handlers will not be executed.
initPage();

View File

@ -1,62 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Security-Policy" content="default-src chrome:" />
<link rel="stylesheet" href="chrome://browser/skin/blockedSite.css" type="text/css" media="all" />
<link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/blocklist_favicon.png"/>
<link rel="localization" href="branding/brand.ftl"/>
<link rel="localization" href="browser/safebrowsing/blockedSite.ftl"/>
</head>
<body>
<div id="errorPageContainer" class="container">
<!-- Error Title -->
<div id="errorTitle" class="title">
<h1 class="title-text" id="errorTitleText"></h1>
</div>
<div id="errorLongContent">
<!-- Short Description -->
<div id="errorShortDesc">
<p id="errorShortDescText"></p>
</div>
<!-- Advisory -->
<div id="advisoryDesc">
<p id="advisoryDescText">
<a id="advisory_provider" data-l10n-name="advisory_provider"></a>
</p>
</div>
<!-- Action buttons -->
<div id="buttons" class="button-container">
<!-- Commands handled in browser.js -->
<button id="goBackButton" data-l10n-id="safeb-palm-accept-label"></button>
<button id="seeDetailsButton" data-l10n-id="safeb-palm-see-details-label"></button>
</div>
</div>
<div id="errorDescriptionContainer" hidden="true">
<!-- Error Descriptions Handled in blockedSite.js -->
<div class="error-description" id="errorLongDesc">
<p id="errorInnerDescription">
<span id="error_desc_sitename" data-l10n-name="sitename"></span>
<a id="error_desc_link" data-l10n-name="error_desc_link"></a>
<a id="report_detection" data-l10n-name="report_detection"></a>
<a id="ignore_warning_link" data-l10n-name="ignore_warning_link"></a>
</p>
<p id="learn_more">
<a id="learn_more_link" data-l10n-name="learn_more_link"></a>
<a id="firefox_support" data-l10n-name="firefox_support"></a>
</p>
</div>
</div>
</div>
</body>
<script src="chrome://browser/content/blockedSite.js"/>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -4,36 +4,29 @@
<menugroup id="context-navigation">
<menuitem id="context-back"
data-l10n-id="main-context-menu-back"
class="menuitem-iconic"
tooltiptext="&backButton.tooltip;"
aria-label="&backCmd.label;"
command="Browser:BackOrBackDuplicate"
accesskey="&backCmd.accesskey;"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="context-forward"
data-l10n-id="main-context-menu-forward"
class="menuitem-iconic"
tooltiptext="&forwardButton.tooltip;"
aria-label="&forwardCmd.label;"
command="Browser:ForwardOrForwardDuplicate"
accesskey="&forwardCmd.accesskey;"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="context-reload"
class="menuitem-iconic"
tooltip="dynamic-shortcut-tooltip"
aria-label="&reloadCmd.label;"
data-l10n-id="main-context-menu-reload"
command="Browser:ReloadOrDuplicate"
accesskey="&reloadCmd.accesskey;"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="context-stop"
class="menuitem-iconic"
tooltip="dynamic-shortcut-tooltip"
aria-label="&stopCmd.label;"
accesskey="&stopCmd.accesskey;"
data-l10n-id="main-context-menu-stop"
command="Browser:Stop"/>
<menuitem id="context-bookmarkpage"
class="menuitem-iconic"
aria-label="&bookmarkPageCmd2.label;"
accesskey="&bookmarkPageCmd2.accesskey;"
data-l10n-id="main-context-menu-bookmark-page"
oncommand="gContextMenu.bookmarkThisPage();"/>
</menugroup>
<menuseparator id="context-sep-navigation"/>
@ -51,264 +44,211 @@
oncommand="InlineSpellCheckerUI.undoAddToDictionary();" />
<menuseparator id="spell-suggestions-separator"/>
<menuitem id="context-openlinkincurrent"
label="&openLinkCmdInCurrent.label;"
accesskey="&openLinkCmdInCurrent.accesskey;"
data-l10n-id="main-context-menu-open-link"
oncommand="gContextMenu.openLinkInCurrent();"/>
# label and data-usercontextid are dynamically set.
<menuitem id="context-openlinkincontainertab"
accesskey="&openLinkCmdInTab.accesskey;"
oncommand="gContextMenu.openLinkInTab(event);"/>
<menuitem id="context-openlinkintab"
label="&openLinkCmdInTab.label;"
accesskey="&openLinkCmdInTab.accesskey;"
data-l10n-id="main-context-menu-open-link-new-tab"
data-usercontextid="0"
oncommand="gContextMenu.openLinkInTab(event);"/>
<menu id="context-openlinkinusercontext-menu"
label="&openLinkCmdInContainerTab.label;"
accesskey="&openLinkCmdInContainerTab.accesskey;"
data-l10n-id="main-context-menu-open-link-container-tab"
hidden="true">
<menupopup oncommand="gContextMenu.openLinkInTab(event);"
onpopupshowing="return gContextMenu.createContainerMenu(event);" />
</menu>
<menuitem id="context-openlink"
label="&openLinkCmd.label;"
accesskey="&openLinkCmd.accesskey;"
data-l10n-id="main-context-menu-open-link-new-window"
oncommand="gContextMenu.openLink();"/>
<menuitem id="context-openlinkprivate"
label="&openLinkInPrivateWindowCmd.label;"
accesskey="&openLinkInPrivateWindowCmd.accesskey;"
data-l10n-id="main-context-menu-open-link-new-private-window"
oncommand="gContextMenu.openLinkInPrivateWindow();"/>
<menuseparator id="context-sep-open"/>
<menuitem id="context-bookmarklink"
label="&bookmarkThisLinkCmd.label;"
accesskey="&bookmarkThisLinkCmd.accesskey;"
data-l10n-id="main-context-menu-bookmark-this-link"
oncommand="gContextMenu.bookmarkLink();"/>
<menuitem id="context-savelink"
label="&saveLinkCmd.label;"
accesskey="&saveLinkCmd.accesskey;"
data-l10n-id="main-context-menu-save-link"
oncommand="gContextMenu.saveLink();"/>
<menuitem id="context-copyemail"
label="&copyEmailCmd.label;"
accesskey="&copyEmailCmd.accesskey;"
data-l10n-id="main-context-menu-copy-email"
oncommand="gContextMenu.copyEmail();"/>
<menuitem id="context-copylink"
label="&copyLinkCmd.label;"
accesskey="&copyLinkCmd.accesskey;"
data-l10n-id="main-context-menu-copy-link"
oncommand="gContextMenu.copyLink();"/>
<menuseparator id="context-sep-copylink"/>
<menuitem id="context-media-play"
label="&mediaPlay.label;"
accesskey="&mediaPlay.accesskey;"
data-l10n-id="main-context-menu-media-play"
oncommand="gContextMenu.mediaCommand('play');"/>
<menuitem id="context-media-pause"
label="&mediaPause.label;"
accesskey="&mediaPause.accesskey;"
data-l10n-id="main-context-menu-media-pause"
oncommand="gContextMenu.mediaCommand('pause');"/>
<menuitem id="context-media-mute"
label="&mediaMute.label;"
accesskey="&mediaMute.accesskey;"
data-l10n-id="main-context-menu-media-mute"
oncommand="gContextMenu.mediaCommand('mute');"/>
<menuitem id="context-media-unmute"
label="&mediaUnmute.label;"
accesskey="&mediaUnmute.accesskey;"
data-l10n-id="main-context-menu-media-unmute"
oncommand="gContextMenu.mediaCommand('unmute');"/>
<menu id="context-media-playbackrate" label="&mediaPlaybackRate2.label;" accesskey="&mediaPlaybackRate2.accesskey;">
<menu id="context-media-playbackrate" data-l10n-id="main-context-menu-media-play-speed">
<menupopup>
<menuitem id="context-media-playbackrate-050x"
label="&mediaPlaybackRate050x2.label;"
accesskey="&mediaPlaybackRate050x2.accesskey;"
data-l10n-id="main-context-menu-media-play-speed-slow"
type="radio"
name="playbackrate"
oncommand="gContextMenu.mediaCommand('playbackRate', 0.5);"/>
<menuitem id="context-media-playbackrate-100x"
label="&mediaPlaybackRate100x2.label;"
accesskey="&mediaPlaybackRate100x2.accesskey;"
data-l10n-id="main-context-menu-media-play-speed-normal"
type="radio"
name="playbackrate"
checked="true"
oncommand="gContextMenu.mediaCommand('playbackRate', 1.0);"/>
<menuitem id="context-media-playbackrate-125x"
label="&mediaPlaybackRate125x2.label;"
accesskey="&mediaPlaybackRate125x2.accesskey;"
data-l10n-id="main-context-menu-media-play-speed-fast"
type="radio"
name="playbackrate"
oncommand="gContextMenu.mediaCommand('playbackRate', 1.25);"/>
<menuitem id="context-media-playbackrate-150x"
label="&mediaPlaybackRate150x2.label;"
accesskey="&mediaPlaybackRate150x2.accesskey;"
data-l10n-id="main-context-menu-media-play-speed-faster"
type="radio"
name="playbackrate"
oncommand="gContextMenu.mediaCommand('playbackRate', 1.5);"/>
<menuitem id="context-media-playbackrate-200x"
label="&mediaPlaybackRate200x2.label;"
accesskey="&mediaPlaybackRate200x2.accesskey;"
data-l10n-id="main-context-menu-media-play-speed-fastest"
type="radio"
name="playbackrate"
oncommand="gContextMenu.mediaCommand('playbackRate', 2.0);"/>
</menupopup>
</menu>
<menuitem id="context-media-loop"
label="&mediaLoop.label;"
accesskey="&mediaLoop.accesskey;"
data-l10n-id="main-context-menu-media-loop"
type="checkbox"
oncommand="gContextMenu.mediaCommand('loop');"/>
<menuitem id="context-media-showcontrols"
label="&mediaShowControls.label;"
accesskey="&mediaShowControls.accesskey;"
data-l10n-id="main-context-menu-media-show-controls"
oncommand="gContextMenu.mediaCommand('showcontrols');"/>
<menuitem id="context-media-hidecontrols"
label="&mediaHideControls.label;"
accesskey="&mediaHideControls.accesskey;"
data-l10n-id="main-context-menu-media-hide-controls"
oncommand="gContextMenu.mediaCommand('hidecontrols');"/>
<menuitem id="context-video-fullscreen"
accesskey="&videoFullScreen.accesskey;"
label="&videoFullScreen.label;"
data-l10n-id="main-context-menu-media-video-fullscreen"
oncommand="gContextMenu.mediaCommand('fullscreen');"/>
<menuitem id="context-leave-dom-fullscreen"
accesskey="&leaveDOMFullScreen.accesskey;"
label="&leaveDOMFullScreen.label;"
data-l10n-id="main-context-menu-media-video-leave-fullscreen"
oncommand="gContextMenu.leaveDOMFullScreen();"/>
<menuitem id="context-video-pictureinpicture"
accesskey="&pictureInPicture.accesskey;"
label="&pictureInPicture.label;"
data-l10n-id="main-context-menu-media-pip"
type="checkbox"
oncommand="gContextMenu.mediaCommand('pictureinpicture');"/>
<menuseparator id="context-media-sep-commands"/>
<menuitem id="context-reloadimage"
label="&reloadImageCmd.label;"
accesskey="&reloadImageCmd.accesskey;"
data-l10n-id="main-context-menu-image-reload"
oncommand="gContextMenu.reloadImage();"/>
<menuitem id="context-viewimage"
label="&viewImageCmd.label;"
accesskey="&viewImageCmd.accesskey;"
data-l10n-id="main-context-menu-image-view"
oncommand="gContextMenu.viewMedia(event);"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="context-viewvideo"
label="&viewVideoCmd.label;"
accesskey="&viewVideoCmd.accesskey;"
data-l10n-id="main-context-menu-video-view"
oncommand="gContextMenu.viewMedia(event);"
onclick="checkForMiddleClick(this, event);"/>
#ifdef CONTEXT_COPY_IMAGE_CONTENTS
<menuitem id="context-copyimage-contents"
label="&copyImageContentsCmd.label;"
accesskey="&copyImageContentsCmd.accesskey;"
data-l10n-id="main-context-menu-image-copy"
oncommand="goDoCommand('cmd_copyImage');"/>
#endif
<menuitem id="context-copyimage"
label="&copyImageCmd.label;"
accesskey="&copyImageCmd.accesskey;"
data-l10n-id="main-context-menu-image-copy-location"
oncommand="gContextMenu.copyMediaLocation();"/>
<menuitem id="context-copyvideourl"
label="&copyVideoURLCmd.label;"
accesskey="&copyVideoURLCmd.accesskey;"
data-l10n-id="main-context-menu-video-copy-location"
oncommand="gContextMenu.copyMediaLocation();"/>
<menuitem id="context-copyaudiourl"
label="&copyAudioURLCmd.label;"
accesskey="&copyAudioURLCmd.accesskey;"
data-l10n-id="main-context-menu-audio-copy-location"
oncommand="gContextMenu.copyMediaLocation();"/>
<menuseparator id="context-sep-copyimage"/>
<menuitem id="context-saveimage"
label="&saveImageCmd.label;"
accesskey="&saveImageCmd.accesskey;"
data-l10n-id="main-context-menu-image-save-as"
oncommand="gContextMenu.saveMedia();"/>
<menuitem id="context-sendimage"
label="&emailImageCmd.label;"
accesskey="&emailImageCmd.accesskey;"
data-l10n-id="main-context-menu-image-email"
oncommand="gContextMenu.sendMedia();"/>
<menuitem id="context-setDesktopBackground"
label="&setDesktopBackgroundCmd.label;"
accesskey="&setDesktopBackgroundCmd.accesskey;"
data-l10n-id="main-context-menu-image-set-as-background"
oncommand="gContextMenu.setDesktopBackground();"/>
<menuitem id="context-viewimageinfo"
label="&viewImageInfoCmd.label;"
accesskey="&viewImageInfoCmd.accesskey;"
data-l10n-id="main-context-menu-image-info"
oncommand="gContextMenu.viewImageInfo();"/>
<menuitem id="context-viewimagedesc"
label="&viewImageDescCmd.label;"
accesskey="&viewImageDescCmd.accesskey;"
data-l10n-id="main-context-menu-image-desc"
oncommand="gContextMenu.viewImageDesc(event);"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="context-savevideo"
label="&saveVideoCmd.label;"
accesskey="&saveVideoCmd.accesskey;"
data-l10n-id="main-context-menu-video-save-as"
oncommand="gContextMenu.saveMedia();"/>
<menuitem id="context-saveaudio"
label="&saveAudioCmd.label;"
accesskey="&saveAudioCmd.accesskey;"
data-l10n-id="main-context-menu-audio-save-as"
oncommand="gContextMenu.saveMedia();"/>
<menuitem id="context-video-saveimage"
accesskey="&videoSaveImage.accesskey;"
label="&videoSaveImage.label;"
data-l10n-id="main-context-menu-video-image-save-as"
oncommand="gContextMenu.saveVideoFrameAsImage();"/>
<menuitem id="context-sendvideo"
label="&emailVideoCmd.label;"
accesskey="&emailVideoCmd.accesskey;"
data-l10n-id="main-context-menu-video-email"
oncommand="gContextMenu.sendMedia();"/>
<menuitem id="context-sendaudio"
label="&emailAudioCmd.label;"
accesskey="&emailAudioCmd.accesskey;"
data-l10n-id="main-context-menu-audio-email"
oncommand="gContextMenu.sendMedia();"/>
<menuitem id="context-ctp-play"
label="&playPluginCmd.label;"
accesskey="&playPluginCmd.accesskey;"
data-l10n-id="main-context-menu-plugin-play"
oncommand="gContextMenu.playPlugin();"/>
<menuitem id="context-ctp-hide"
label="&hidePluginCmd.label;"
accesskey="&hidePluginCmd.accesskey;"
data-l10n-id="main-context-menu-plugin-hide"
oncommand="gContextMenu.hidePlugin();"/>
<menuseparator id="context-sep-ctp"/>
<menuitem id="context-savepage"
label="&savePageCmd.label;"
accesskey="&savePageCmd.accesskey2;"
data-l10n-id="main-context-menu-page-save"
oncommand="gContextMenu.savePageAs();"/>
<menuseparator id="context-sep-sendpagetodevice" class="sync-ui-item"
hidden="true"/>
<menu id="context-sendpagetodevice"
class="sync-ui-item"
label="&sendPageToDevice.label;"
accesskey="&sendPageToDevice.accesskey;"
data-l10n-id="main-context-menu-send-to-device"
hidden="true">
<menupopup id="context-sendpagetodevice-popup"
onpopupshowing="(() => { gSync.populateSendTabToDevicesMenu(event.target, gBrowser.currentURI.spec, gBrowser.contentTitle); })()"/>
</menu>
<menuseparator id="context-sep-viewbgimage"/>
<menuitem id="context-viewbgimage"
label="&viewBGImageCmd.label;"
accesskey="&viewBGImageCmd.accesskey;"
data-l10n-id="main-context-menu-view-background-image"
oncommand="gContextMenu.viewBGImage(event);"
onclick="checkForMiddleClick(this, event);"/>
<menuitem id="context-undo"
label="&undoCmd.label;"
accesskey="&undoCmd.accesskey;"
data-l10n-id="text-action-undo"
command="cmd_undo"/>
<menuseparator id="context-sep-undo"/>
<menuitem id="context-cut"
label="&cutCmd.label;"
accesskey="&cutCmd.accesskey;"
data-l10n-id="text-action-cut"
command="cmd_cut"/>
<menuitem id="context-copy"
label="&copyCmd.label;"
accesskey="&copyCmd.accesskey;"
data-l10n-id="text-action-copy"
command="cmd_copy"/>
<menuitem id="context-paste"
label="&pasteCmd.label;"
accesskey="&pasteCmd.accesskey;"
data-l10n-id="text-action-paste"
command="cmd_paste"/>
<menuitem id="context-delete"
label="&deleteCmd.label;"
accesskey="&deleteCmd.accesskey;"
data-l10n-id="text-action-delete"
command="cmd_delete"/>
<menuseparator id="context-sep-paste"/>
<menuitem id="context-selectall"
label="&selectAllCmd.label;"
accesskey="&selectAllCmd.accesskey;"
data-l10n-id="text-action-select-all"
command="cmd_selectAll"/>
<menuseparator id="context-sep-selectall"/>
<menuitem id="context-keywordfield"
label="&keywordfield.label;"
accesskey="&keywordfield.accesskey;"
data-l10n-id="main-context-menu-keyword"
oncommand="AddKeywordForSearchField();"/>
<menuitem id="context-searchselect"
oncommand="BrowserSearch.loadSearchFromContext(this.searchTerms, this.principal, this.csp);"/>
@ -316,69 +256,56 @@
hidden="true"/>
<menu id="context-sendlinktodevice"
class="sync-ui-item"
label="&sendLinkToDevice.label;"
accesskey="&sendLinkToDevice.accesskey;"
data-l10n-id="main-context-menu-link-send-to-device"
hidden="true">
<menupopup id="context-sendlinktodevice-popup"
onpopupshowing="gSync.populateSendTabToDevicesMenu(event.target, gContextMenu.linkURL, gContextMenu.linkTextStr);"/>
</menu>
<menuseparator id="frame-sep"/>
<menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;">
<menu id="frame" data-l10n-id="main-context-menu-frame">
<menupopup>
<menuitem id="context-showonlythisframe"
label="&showOnlyThisFrameCmd.label;"
accesskey="&showOnlyThisFrameCmd.accesskey;"
data-l10n-id="main-context-menu-frame-show-this"
oncommand="gContextMenu.showOnlyThisFrame();"/>
<menuitem id="context-openframeintab"
label="&openFrameCmdInTab.label;"
accesskey="&openFrameCmdInTab.accesskey;"
data-l10n-id="main-context-menu-frame-open-tab"
oncommand="gContextMenu.openFrameInTab();"/>
<menuitem id="context-openframe"
label="&openFrameCmd.label;"
accesskey="&openFrameCmd.accesskey;"
data-l10n-id="main-context-menu-frame-open-window"
oncommand="gContextMenu.openFrame();"/>
<menuseparator id="open-frame-sep"/>
<menuitem id="context-reloadframe"
label="&reloadFrameCmd.label;"
accesskey="&reloadFrameCmd.accesskey;"
data-l10n-id="main-context-menu-frame-reload"
oncommand="gContextMenu.reloadFrame(event);"/>
<menuseparator/>
<menuitem id="context-bookmarkframe"
label="&bookmarkThisFrameCmd.label;"
accesskey="&bookmarkThisFrameCmd.accesskey;"
data-l10n-id="main-context-menu-frame-bookmark"
oncommand="gContextMenu.addBookmarkForFrame();"/>
<menuitem id="context-saveframe"
label="&saveFrameCmd.label;"
accesskey="&saveFrameCmd.accesskey;"
data-l10n-id="main-context-menu-frame-save-as"
oncommand="gContextMenu.saveFrame();"/>
<menuseparator/>
<menuitem id="context-printframe"
label="&printFrameCmd.label;"
accesskey="&printFrameCmd.accesskey;"
data-l10n-id="main-context-menu-frame-print"
oncommand="gContextMenu.printFrame();"/>
<menuseparator/>
<menuitem id="context-viewframesource"
label="&viewFrameSourceCmd.label;"
accesskey="&viewFrameSourceCmd.accesskey;"
data-l10n-id="main-context-menu-frame-view-source"
oncommand="gContextMenu.viewFrameSource();"/>
<menuitem id="context-viewframeinfo"
label="&viewFrameInfoCmd.label;"
accesskey="&viewFrameInfoCmd.accesskey;"
data-l10n-id="main-context-menu-frame-view-info"
oncommand="gContextMenu.viewFrameInfo();"/>
</menupopup>
</menu>
<menuitem id="context-viewpartialsource-selection"
label="&viewPartialSourceForSelectionCmd.label;"
accesskey="&viewPartialSourceCmd.accesskey;"
data-l10n-id="main-context-menu-view-selection-source"
oncommand="gContextMenu.viewPartialSource();"/>
<menuseparator id="context-sep-viewsource"/>
<menuitem id="context-viewsource"
label="&viewPageSourceCmd.label;"
accesskey="&viewPageSourceCmd.accesskey;"
data-l10n-id="main-context-menu-view-page-source"
oncommand="BrowserViewSource(gContextMenu.browser);"/>
<menuitem id="context-viewinfo"
label="&viewPageInfoCmd.label;"
accesskey="&viewPageInfoCmd.accesskey;"
data-l10n-id="main-context-menu-view-page-info"
oncommand="gContextMenu.viewInfo();"/>
<menuseparator id="spell-separator"/>
<menuitem id="spell-check-enabled"
@ -403,12 +330,10 @@
</menu>
<menuseparator hidden="true" id="context-sep-bidi"/>
<menuitem hidden="true" id="context-bidi-text-direction-toggle"
label="&bidiSwitchTextDirectionItem.label;"
accesskey="&bidiSwitchTextDirectionItem.accesskey;"
data-l10n-id="main-context-menu-bidi-switch-text"
command="cmd_switchTextDirection"/>
<menuitem hidden="true" id="context-bidi-page-direction-toggle"
label="&bidiSwitchPageDirectionItem.label;"
accesskey="&bidiSwitchPageDirectionItem.accesskey;"
data-l10n-id="main-context-menu-bidi-switch-page"
oncommand="gContextMenu.switchPageDirection();"/>
<menuseparator id="fill-login-separator" hidden="true"/>
<menu id="fill-login"
@ -441,10 +366,9 @@
<menuseparator id="inspect-separator" hidden="true"/>
<menuitem id="context-inspect"
hidden="true"
label="&inspectContextMenu.label;"
accesskey="&inspectContextMenu.accesskey;"
data-l10n-id="main-context-menu-inspect-element"
oncommand="gContextMenu.inspectNode();"/>
<menuitem id="context-inspect-a11y"
hidden="true"
label="&inspectA11YContextMenu.label;"
data-l10n-id="main-context-menu-inspect-a11y-properties"
oncommand="gContextMenu.inspectA11Y();"/>

View File

@ -7,7 +7,7 @@
/**
* Customization handler prepares this browser window for entering and exiting
* customization mode by handling customizationstarting and customizationending
* customization mode by handling customizationstarting and aftercustomization
* events.
*/
var CustomizationHandler = {
@ -16,8 +16,8 @@ var CustomizationHandler = {
case "customizationstarting":
this._customizationStarting();
break;
case "customizationending":
this._customizationEnding(aEvent.detail);
case "aftercustomization":
this._afterCustomization();
break;
}
},
@ -39,22 +39,16 @@ var CustomizationHandler = {
UpdateUrlbarSearchSplitterState();
PlacesToolbarHelper.customizeStart();
gURLBarHandler.customizeStart();
},
_customizationEnding(aDetails) {
_afterCustomization() {
// Update global UI elements that may have been added or removed
if (aDetails.changed && AppConstants.platform != "macosx") {
if (AppConstants.platform != "macosx") {
updateEditUIVisibility();
}
PlacesToolbarHelper.customizeDone();
UpdateUrlbarSearchSplitterState();
// Update the urlbar
URLBarSetURI();
XULBrowserWindow.asyncUpdateUI();
// Re-enable parts of the UI we disabled during the dialog
@ -67,7 +61,9 @@ var CustomizationHandler = {
gBrowser.selectedBrowser.focus();
gURLBarHandler.customizeEnd();
// Update the urlbar
URLBarSetURI();
UpdateUrlbarSearchSplitterState();
},
};

View File

@ -14,7 +14,5 @@
%placesDTD;
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
%syncBrandDTD;
<!ENTITY % reportphishDTD SYSTEM "chrome://browser/locale/safebrowsing/report-phishing.dtd">
%reportphishDTD;
<!ENTITY % editBookmarkOverlayDTD SYSTEM "chrome://browser/locale/places/editBookmarkOverlay.dtd">
%editBookmarkOverlayDTD;

View File

@ -343,6 +343,8 @@ var FullScreen = {
document.addEventListener("keypress", this._keyToggleCallback);
document.addEventListener("popupshown", this._setPopupOpen);
document.addEventListener("popuphidden", this._setPopupOpen);
gURLBar.controller.addQueryListener(this);
// In DOM fullscreen mode, we hide toolbars with CSS
if (!document.fullscreenElement) {
this.hideNavToolbox(true);
@ -489,6 +491,7 @@ var FullScreen = {
document.removeEventListener("keypress", this._keyToggleCallback);
document.removeEventListener("popupshown", this._setPopupOpen);
document.removeEventListener("popuphidden", this._setPopupOpen);
gURLBar.controller.removeQueryListener(this);
}
},
@ -540,25 +543,36 @@ var FullScreen = {
// Otherwise, they would not affect chrome and the user would expect the chrome to go away.
// e.g. we wouldn't want the autoscroll icon firing this event, so when the user
// toggles chrome when moving mouse to the top, it doesn't go away again.
let target = aEvent.originalTarget;
if (target.localName == "tooltip") {
return;
}
if (
aEvent.type == "popupshown" &&
!FullScreen._isChromeCollapsed &&
aEvent.target.localName != "tooltip" &&
aEvent.target.localName != "window" &&
aEvent.target.getAttribute("nopreventnavboxhide") != "true"
target.getAttribute("nopreventnavboxhide") != "true"
) {
FullScreen._isPopupOpen = true;
} else if (
aEvent.type == "popuphidden" &&
aEvent.target.localName != "tooltip" &&
aEvent.target.localName != "window"
) {
} else if (aEvent.type == "popuphidden") {
FullScreen._isPopupOpen = false;
// Try again to hide toolbar when we close the popup.
FullScreen.hideNavToolbox(true);
}
},
// UrlbarController listener method
onViewOpen() {
if (!this._isChromeCollapsed) {
this._isPopupOpen = true;
}
},
// UrlbarController listener method
onViewClose() {
this._isPopupOpen = false;
this.hideNavToolbox(true);
},
get navToolboxHidden() {
return this._isChromeCollapsed;
},
@ -644,10 +658,10 @@ var FullScreen = {
}
}, 0);
});
window.removeEventListener("keypress", retryHideNavToolbox);
window.removeEventListener("keydown", retryHideNavToolbox);
window.removeEventListener("click", retryHideNavToolbox);
};
window.addEventListener("keypress", retryHideNavToolbox);
window.addEventListener("keydown", retryHideNavToolbox);
window.addEventListener("click", retryHideNavToolbox);
return;
}

View File

@ -7,94 +7,65 @@
!('@mozilla.org/widget/nativemenuservice;1' in Cc))
this.setAttribute('openedwithkey',
event.target.parentNode.openedWithKey);">
<menu id="file-menu" label="&fileMenu.label;"
accesskey="&fileMenu.accesskey;">
<menu id="file-menu" data-l10n-id="menu-file">
<menupopup id="menu_FilePopup"
onpopupshowing="updateFileMenuUserContextUIVisibility('menu_newUserContext');
updateFileMenuImportUIVisibility('cmd_importFromAnotherBrowser');">
<menuitem id="menu_newNavigatorTab"
label="&tabCmd.label;"
command="cmd_newNavigatorTab"
key="key_newNavigatorTab"
accesskey="&tabCmd.accesskey;"/>
key="key_newNavigatorTab" data-l10n-id="menu-file-new-tab"/>
<menu id="menu_newUserContext"
label="&newUserContext.label;"
accesskey="&newUserContext.accesskey;"
hidden="true">
hidden="true" data-l10n-id="menu-file-new-container-tab">
<menupopup onpopupshowing="return createUserContextMenu(event);" />
</menu>
<menuitem id="menu_newNavigator"
label="&newNavigatorCmd.label;"
accesskey="&newNavigatorCmd.accesskey;"
key="key_newNavigator"
command="cmd_newNavigator"/>
command="cmd_newNavigator" data-l10n-id="menu-file-new-window"/>
<menuitem id="menu_newPrivateWindow"
label="&newPrivateWindow.label;"
accesskey="&newPrivateWindow.accesskey;"
command="Tools:PrivateBrowsing"
key="key_privatebrowsing"/>
key="key_privatebrowsing" data-l10n-id="menu-file-new-private-window"/>
<menuitem id="menu_openLocation"
hidden="true"
label="&openLocationCmd.label;"
command="Browser:OpenLocation"
key="focusURLBar"/>
key="focusURLBar" data-l10n-id="menu-file-open-location"/>
<menuitem id="menu_openFile"
label="&openFileCmd.label;"
command="Browser:OpenFile"
key="openFileKb"
accesskey="&openFileCmd.accesskey;"/>
key="openFileKb" data-l10n-id="menu-file-open-file"/>
<menuitem id="menu_close"
class="show-only-for-keyboard"
label="&closeCmd.label;"
key="key_close"
accesskey="&closeCmd.accesskey;"
command="cmd_close"/>
command="cmd_close" data-l10n-id="menu-file-close"/>
<menuitem id="menu_closeWindow"
class="show-only-for-keyboard"
hidden="true"
command="cmd_closeWindow"
key="key_closeWindow"
label="&closeWindow.label;"
accesskey="&closeWindow.accesskey;"/>
key="key_closeWindow" data-l10n-id="menu-file-close-window"/>
<menuseparator/>
<menuitem id="menu_savePage"
label="&savePageCmd.label;"
accesskey="&savePageCmd.accesskey;"
key="key_savePage"
command="Browser:SavePage"/>
command="Browser:SavePage" data-l10n-id="menu-file-save-page"/>
<menuitem id="menu_sendLink"
label="&emailPageCmd.label;"
accesskey="&emailPageCmd.accesskey;"
command="Browser:SendLink"/>
command="Browser:SendLink" data-l10n-id="menu-file-email-link"/>
<menuseparator/>
#if !defined(MOZ_WIDGET_GTK)
<menuitem id="menu_printSetup"
label="&printSetupCmd.label;"
accesskey="&printSetupCmd.accesskey;"
command="cmd_pageSetup"/>
command="cmd_pageSetup" data-l10n-id="menu-file-print-setup"/>
#endif
#ifndef XP_MACOSX
<menuitem id="menu_printPreview"
label="&printPreviewCmd.label;"
accesskey="&printPreviewCmd.accesskey;"
command="cmd_printPreview"/>
command="cmd_printPreview" data-l10n-id="menu-file-print-preview"/>
#endif
<menuitem id="menu_print"
label="&printCmd.label;"
accesskey="&printCmd.accesskey;"
key="printKb"
command="cmd_print"/>
command="cmd_print" data-l10n-id="menu-file-print"/>
<menuseparator/>
<menuitem id="menu_importFromAnotherBrowser"
label="&importFromAnotherBrowserCmd.label;"
accesskey="&importFromAnotherBrowserCmd.accesskey;"
command="cmd_importFromAnotherBrowser"/>
command="cmd_importFromAnotherBrowser" data-l10n-id="menu-file-import-from-another-browser"/>
<menuseparator/>
<menuitem id="goOfflineMenuitem"
label="&goOfflineCmd.label;"
accesskey="&goOfflineCmd.accesskey;"
type="checkbox"
command="cmd_toggleOfflineStatus"/>
command="cmd_toggleOfflineStatus" data-l10n-id="menu-file-go-offline"/>
<!-- We need to leave those strings in DTD until bug 1568133 is fixed. -->
<menuitem id="menu_FileQuitItem"
#ifdef XP_WIN
label="&quitApplicationCmdWin2.label;"
@ -110,194 +81,139 @@
</menupopup>
</menu>
<menu id="edit-menu" label="&editMenu.label;"
accesskey="&editMenu.accesskey;">
<menu id="edit-menu" data-l10n-id="menu-edit">
<menupopup id="menu_EditPopup"
onpopupshowing="updateEditUIVisibility()"
onpopuphidden="updateEditUIVisibility()">
<menuitem id="menu_undo"
label="&undoCmd.label;"
key="key_undo"
accesskey="&undoCmd.accesskey;"
command="cmd_undo"/>
command="cmd_undo" data-l10n-id="text-action-undo"/>
<menuitem id="menu_redo"
label="&redoCmd.label;"
key="key_redo"
accesskey="&redoCmd.accesskey;"
command="cmd_redo"/>
command="cmd_redo" data-l10n-id="text-action-redo"/>
<menuseparator/>
<menuitem id="menu_cut"
label="&cutCmd.label;"
key="key_cut"
accesskey="&cutCmd.accesskey;"
command="cmd_cut"/>
command="cmd_cut" data-l10n-id="text-action-cut"/>
<menuitem id="menu_copy"
label="&copyCmd.label;"
key="key_copy"
accesskey="&copyCmd.accesskey;"
command="cmd_copy"/>
command="cmd_copy" data-l10n-id="text-action-copy"/>
<menuitem id="menu_paste"
label="&pasteCmd.label;"
key="key_paste"
accesskey="&pasteCmd.accesskey;"
command="cmd_paste"/>
command="cmd_paste" data-l10n-id="text-action-paste"/>
<menuitem id="menu_delete"
label="&deleteCmd.label;"
key="key_delete"
accesskey="&deleteCmd.accesskey;"
command="cmd_delete"/>
command="cmd_delete" data-l10n-id="text-action-delete"/>
<menuseparator/>
<menuitem id="menu_selectAll"
label="&selectAllCmd.label;"
key="key_selectAll"
accesskey="&selectAllCmd.accesskey;"
command="cmd_selectAll"/>
command="cmd_selectAll" data-l10n-id="text-action-select-all"/>
<menuseparator/>
<menuitem id="menu_find"
label="&findOnCmd.label;"
accesskey="&findOnCmd.accesskey;"
key="key_find"
command="cmd_find"/>
command="cmd_find" data-l10n-id="menu-edit-find-on"/>
<menuitem id="menu_findAgain"
class="show-only-for-keyboard"
label="&findAgainCmd.label;"
accesskey="&findAgainCmd.accesskey;"
key="key_findAgain"
command="cmd_findAgain"/>
command="cmd_findAgain" data-l10n-id="menu-edit-find-again"/>
<menuseparator hidden="true" id="textfieldDirection-separator"/>
<menuitem id="textfieldDirection-swap"
command="cmd_switchTextDirection"
key="key_switchTextDirection"
label="&bidiSwitchTextDirectionItem.label;"
accesskey="&bidiSwitchTextDirectionItem.accesskey;"
hidden="true"/>
hidden="true" data-l10n-id="menu-edit-bidi-switch-text-direction"/>
#ifdef XP_UNIX
#ifndef XP_MACOSX
<menuseparator/>
<menuitem id="menu_preferences"
label="&preferencesCmdUnix.label;"
accesskey="&preferencesCmdUnix.accesskey;"
oncommand="openPreferences(undefined);"/>
oncommand="openPreferences(undefined);" data-l10n-id="menu-preferences"/>
#endif
#endif
</menupopup>
</menu>
<menu id="view-menu" label="&viewMenu.label;"
accesskey="&viewMenu.accesskey;">
<menu id="view-menu" data-l10n-id="menu-view">
<menupopup id="menu_viewPopup"
onpopupshowing="updateCharacterEncodingMenuState();">
<menu id="viewToolbarsMenu"
label="&viewToolbarsMenu.label;"
accesskey="&viewToolbarsMenu.accesskey;">
<menu id="viewToolbarsMenu" data-l10n-id="menu-view-toolbars-menu">
<menupopup onpopupshowing="onViewToolbarsPopupShowing(event);">
<menuseparator/>
<menuitem id="menu_customizeToolbars"
label="&viewCustomizeToolbar.label;"
accesskey="&viewCustomizeToolbar.accesskey;"
command="cmd_CustomizeToolbars"/>
command="cmd_CustomizeToolbars" data-l10n-id="menu-view-customize-toolbar"/>
</menupopup>
</menu>
<menu id="viewSidebarMenuMenu"
label="&viewSidebarMenu.label;"
accesskey="&viewSidebarMenu.accesskey;">
<menu id="viewSidebarMenuMenu" data-l10n-id="menu-view-sidebar">
<menupopup id="viewSidebarMenu">
<menuitem id="menu_bookmarksSidebar"
type="checkbox"
key="viewBookmarksSidebarKb"
oncommand="SidebarUI.toggle('viewBookmarksSidebar');"
label="&bookmarksButton.label;"/>
oncommand="SidebarUI.toggle('viewBookmarksSidebar');" data-l10n-id="menu-view-bookmarks"/>
<menuitem id="menu_historySidebar"
type="checkbox"
key="key_gotoHistory"
oncommand="SidebarUI.toggle('viewHistorySidebar');"
label="&historyButton.label;"/>
oncommand="SidebarUI.toggle('viewHistorySidebar');" data-l10n-id="menu-view-history-button"/>
<menuitem id="menu_tabsSidebar"
type="checkbox"
class="sync-ui-item"
oncommand="SidebarUI.toggle('viewTabsSidebar');"
label="&syncedTabs.sidebar.label;"/>
oncommand="SidebarUI.toggle('viewTabsSidebar');" data-l10n-id="menu-view-synced-tabs-sidebar"/>
</menupopup>
</menu>
<menuseparator/>
<menu id="viewFullZoomMenu" label="&fullZoom.label;"
accesskey="&fullZoom.accesskey;"
onpopupshowing="FullZoom.updateMenu();">
<menu id="viewFullZoomMenu"
onpopupshowing="FullZoom.updateMenu();" data-l10n-id="menu-view-full-zoom">
<menupopup>
<menuitem id="menu_zoomEnlarge"
key="key_fullZoomEnlarge"
label="&fullZoomEnlargeCmd.label;"
accesskey="&fullZoomEnlargeCmd.accesskey;"
command="cmd_fullZoomEnlarge"/>
command="cmd_fullZoomEnlarge" data-l10n-id="menu-view-full-zoom-enlarge"/>
<menuitem id="menu_zoomReduce"
key="key_fullZoomReduce"
label="&fullZoomReduceCmd.label;"
accesskey="&fullZoomReduceCmd.accesskey;"
command="cmd_fullZoomReduce"/>
command="cmd_fullZoomReduce" data-l10n-id="menu-view-full-zoom-reduce"/>
<menuseparator/>
<menuitem id="menu_zoomReset"
key="key_fullZoomReset"
label="&fullZoomResetCmd.label;"
accesskey="&fullZoomResetCmd.accesskey;"
command="cmd_fullZoomReset"/>
command="cmd_fullZoomReset" data-l10n-id="menu-view-full-zoom-reset"/>
<menuseparator/>
<menuitem id="toggle_zoom"
label="&fullZoomToggleCmd.label;"
accesskey="&fullZoomToggleCmd.accesskey;"
type="checkbox"
command="cmd_fullZoomToggle"
checked="false"/>
checked="false" data-l10n-id="menu-view-full-zoom-toggle"/>
</menupopup>
</menu>
<menu id="pageStyleMenu" label="&pageStyleMenu.label;"
accesskey="&pageStyleMenu.accesskey;">
<menu id="pageStyleMenu" data-l10n-id="menu-view-page-style-menu">
<menupopup onpopupshowing="gPageStyleMenu.fillPopup(this);">
<menuitem id="menu_pageStyleNoStyle"
label="&pageStyleNoStyle.label;"
accesskey="&pageStyleNoStyle.accesskey;"
oncommand="gPageStyleMenu.disableStyle();"
type="radio"/>
type="radio" data-l10n-id="menu-view-page-style-no-style"/>
<menuitem id="menu_pageStylePersistentOnly"
label="&pageStylePersistentOnly.label;"
accesskey="&pageStylePersistentOnly.accesskey;"
oncommand="gPageStyleMenu.switchStyleSheet('');"
type="radio"
checked="true"/>
checked="true" data-l10n-id="menu-view-page-basic-style"/>
<menuseparator/>
</menupopup>
</menu>
<menu id="charsetMenu"
label="&charsetMenu2.label;"
accesskey="&charsetMenu2.accesskey;"
oncommand="BrowserSetForcedCharacterSet(event.target.getAttribute('charset'));"
onpopupshowing="CharsetMenu.build(event.target); UpdateCurrentCharset(this);">
onpopupshowing="CharsetMenu.build(event.target); UpdateCurrentCharset(this);" data-l10n-id="menu-view-charset">
<menupopup>
</menupopup>
</menu>
<menuseparator/>
#ifdef XP_MACOSX
<menuitem id="enterFullScreenItem"
accesskey="&enterFullScreenCmd.accesskey;"
label="&enterFullScreenCmd.label;"
key="key_fullScreen">
key="key_fullScreen" data-l10n-id="menu-view-enter-full-screen">
<observes element="View:FullScreen" attribute="oncommand"/>
<observes element="View:FullScreen" attribute="disabled"/>
</menuitem>
<menuitem id="exitFullScreenItem"
accesskey="&exitFullScreenCmd.accesskey;"
label="&exitFullScreenCmd.label;"
key="key_fullScreen"
hidden="true">
hidden="true" data-l10n-id="menu-view-exit-full-screen">
<observes element="View:FullScreen" attribute="oncommand"/>
<observes element="View:FullScreen" attribute="disabled"/>
</menuitem>
#else
<menuitem id="fullScreenItem"
accesskey="&fullScreenCmd.accesskey;"
label="&fullScreenCmd.label;"
key="key_fullScreen"
type="checkbox"
observes="View:FullScreen"/>
observes="View:FullScreen" data-l10n-id="menu-view-full-screen"/>
#endif
<menuitem id="menu_readerModeItem"
observes="View:ReaderView"
@ -305,27 +221,20 @@
hidden="true"/>
<menuitem id="menu_showAllTabs"
hidden="true"
accesskey="&showAllTabsCmd.accesskey;"
label="&showAllTabsCmd.label;"
command="Browser:ShowAllTabs"
key="key_showAllTabs"/>
key="key_showAllTabs" data-l10n-id="menu-view-show-all-tabs"/>
<menuseparator hidden="true" id="documentDirection-separator"/>
<menuitem id="documentDirection-swap"
hidden="true"
label="&bidiSwitchPageDirectionItem.label;"
accesskey="&bidiSwitchPageDirectionItem.accesskey;"
oncommand="gBrowser.selectedBrowser
.messageManager
.sendAsyncMessage('SwitchDocumentDirection');"/>
oncommand="gBrowser.selectedBrowser.sendMessageToActor('SwitchDocumentDirection', {}, 'SwitchDocumentDirection');" data-l10n-id="menu-view-bidi-switch-page-direction"/>
</menupopup>
</menu>
<menu id="history-menu"
label="&historyMenu.label;"
accesskey="&historyMenu.accesskey;">
<menu id="history-menu" data-l10n-id="menu-history">
<menupopup id="goPopup"
#ifndef XP_MACOSX
placespopup="true"
is="places-popup"
#endif
oncommand="this.parentNode._placesView._onCommand(event);"
onclick="checkForMiddleClick(this, event);"
@ -334,42 +243,37 @@
tooltip="bhTooltip"
popupsinherittooltip="true">
<menuitem id="menu_showAllHistory"
label="&showAllHistoryCmd2.label;"
#ifndef XP_MACOSX
key="showAllHistoryKb"
#endif
command="Browser:ShowAllHistory"/>
command="Browser:ShowAllHistory" data-l10n-id="menu-history-show-all-history"/>
<menuitem id="sanitizeItem"
label="&clearRecentHistory.label;"
key="key_sanitize"
command="Tools:Sanitize"/>
command="Tools:Sanitize" data-l10n-id="menu-history-clear-recent-history"/>
<menuseparator id="sanitizeSeparator"/>
<menuitem id="sync-tabs-menuitem"
label="&syncTabsMenu3.label;"
oncommand="gSync.openSyncedTabsPanel();"
hidden="true"/>
hidden="true" data-l10n-id="menu-history-synced-tabs"/>
<menuitem id="historyRestoreLastSession"
label="&historyRestoreLastSession.label;"
command="Browser:RestoreLastSession"/>
command="Browser:RestoreLastSession" data-l10n-id="menu-history-restore-last-session"/>
<menuitem id="hiddenTabsMenu"
label="&hiddenTabs.label;"
oncommand="gTabsPanel.showHiddenTabsPanel();"
hidden="true"/>
hidden="true" data-l10n-id="menu-history-hidden-tabs"/>
<menu id="historyUndoMenu"
label="&historyUndoMenu.label;"
disabled="true">
disabled="true" data-l10n-id="menu-history-undo-menu">
<menupopup id="historyUndoPopup"
#ifndef XP_MACOSX
placespopup="true"
is="places-popup"
#endif
onpopupshowing="document.getElementById('history-menu')._placesView.populateUndoSubmenu();"/>
</menu>
<menu id="historyUndoWindowMenu"
label="&historyUndoWindowMenu.label;"
disabled="true">
disabled="true" data-l10n-id="menu-history-undo-window-menu">
<menupopup id="historyUndoWindowPopup"
#ifndef XP_MACOSX
placespopup="true"
is="places-popup"
#endif
onpopupshowing="document.getElementById('history-menu')._placesView.populateUndoWindowSubmenu();"/>
</menu>
@ -379,14 +283,13 @@
</menu>
<menu id="bookmarksMenu"
label="&bookmarksMenu.label;"
accesskey="&bookmarksMenu.accesskey;"
ondragenter="PlacesMenuDNDHandler.onDragEnter(event);"
ondragover="PlacesMenuDNDHandler.onDragOver(event);"
ondrop="PlacesMenuDNDHandler.onDrop(event);">
ondrop="PlacesMenuDNDHandler.onDrop(event);" data-l10n-id="menu-bookmarks-menu">
<menupopup id="bookmarksMenuPopup"
#ifndef XP_MACOSX
placespopup="true"
is="places-popup"
#endif
context="placesContext"
openInTabs="children"
@ -398,26 +301,24 @@
new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.menuGuid}`);"
tooltip="bhTooltip" popupsinherittooltip="true">
<menuitem id="bookmarksShowAll"
label="&showAllBookmarks2.label;"
command="Browser:ShowAllBookmarks"
key="manBookmarkKb"/>
key="manBookmarkKb" data-l10n-id="menu-bookmarks-show-all"/>
<menuseparator id="organizeBookmarksSeparator"/>
<menuitem id="menu_bookmarkThisPage"
command="Browser:AddBookmarkAs"
key="addBookmarkAsKb"/>
<menuitem id="menu_bookmarkAllTabs"
label="&addCurPagesCmd.label;"
class="show-only-for-keyboard"
command="Browser:BookmarkAllTabs"
key="bookmarkAllTabsKb"/>
key="bookmarkAllTabsKb" data-l10n-id="menu-bookmarks-all-tabs"/>
<menuseparator id="bookmarksToolbarSeparator"/>
<menu id="bookmarksToolbarFolderMenu"
class="menu-iconic bookmark-item"
label="&personalbarCmd.label;"
container="true">
container="true" data-l10n-id="menu-bookmarks-toolbar">
<menupopup id="bookmarksToolbarFolderPopup"
#ifndef XP_MACOSX
placespopup="true"
is="places-popup"
#endif
context="placesContext"
onpopupshowing="if (!this.parentNode._placesView)
@ -425,11 +326,11 @@
</menu>
<menu id="menu_unsortedBookmarks"
class="menu-iconic bookmark-item"
label="&otherBookmarksCmd.label;"
container="true">
container="true" data-l10n-id="menu-bookmarks-other">
<menupopup id="otherBookmarksFolderPopup"
#ifndef XP_MACOSX
placespopup="true"
is="places-popup"
#endif
context="placesContext"
onpopupshowing="if (!this.parentNode._placesView)
@ -437,12 +338,12 @@
</menu>
<menu id="menu_mobileBookmarks"
class="menu-iconic bookmark-item"
label="&mobileBookmarksCmd.label;"
hidden="true"
container="true">
container="true" data-l10n-id="menu-bookmarks-mobile">
<menupopup id="mobileBookmarksFolderPopup"
#ifndef XP_MACOSX
placespopup="true"
is="places-popup"
#endif
context="placesContext"
onpopupshowing="if (!this.parentNode._placesView)
@ -453,81 +354,59 @@
</menupopup>
</menu>
<menu id="tools-menu"
label="&toolsMenu.label;"
accesskey="&toolsMenu.accesskey;">
<menu id="tools-menu" data-l10n-id="menu-tools">
<menupopup id="menu_ToolsPopup">
<menuitem id="menu_openDownloads"
label="&downloads.label;"
accesskey="&downloads.accesskey;"
key="key_openDownloads"
command="Tools:Downloads"/>
command="Tools:Downloads" data-l10n-id="menu-tools-downloads"/>
<menuitem id="menu_openAddons"
label="&addons.label;"
accesskey="&addons.accesskey;"
key="key_openAddons"
command="Tools:Addons"/>
command="Tools:Addons" data-l10n-id="menu-tools-addons"/>
<!-- only one of sync-setup, sync-unverifieditem, sync-syncnowitem or sync-reauthitem will be showing at once -->
<menuitem id="sync-setup"
class="sync-ui-item"
label="&syncSignIn.label;"
accesskey="&syncSignIn.accesskey;"
hidden="true"
oncommand="gSync.openPrefs('menubar')"/>
oncommand="gSync.openPrefs('menubar')" data-l10n-id="menu-tools-sync-sign-in"/>
<menuitem id="sync-unverifieditem"
class="sync-ui-item"
label="&syncSignIn.label;"
accesskey="&syncSignIn.accesskey;"
hidden="true"
oncommand="gSync.openPrefs('menubar')"/>
oncommand="gSync.openPrefs('menubar')" data-l10n-id="menu-tools-sync-sign-in"/>
<menuitem id="sync-syncnowitem"
class="sync-ui-item"
label="&syncSyncNowItem.label;"
accesskey="&syncSyncNowItem.accesskey;"
hidden="true"
oncommand="gSync.doSync(event);"/>
oncommand="gSync.doSync(event);" data-l10n-id="menu-tools-sync-now"/>
<menuitem id="sync-reauthitem"
class="sync-ui-item"
label="&syncReAuthItem.label;"
accesskey="&syncReAuthItem.accesskey;"
hidden="true"
oncommand="gSync.openSignInAgainPage('menubar');"/>
oncommand="gSync.openSignInAgainPage('menubar');" data-l10n-id="menu-tools-sync-re-auth"/>
<menuseparator id="devToolsSeparator"/>
<menu id="webDeveloperMenu"
label="&webDeveloperMenu.label;"
accesskey="&webDeveloperMenu.accesskey;">
<menu id="webDeveloperMenu" data-l10n-id="menu-tools-web-developer">
<menupopup id="menuWebDeveloperPopup">
<menuitem id="menu_pageSource"
label="&pageSourceCmd.label;"
key="key_viewSource"
command="View:PageSource"
accesskey="&pageSourceCmd.accesskey;"/>
command="View:PageSource" data-l10n-id="menu-tools-page-source"/>
</menupopup>
</menu>
<menuitem id="menu_pageInfo"
accesskey="&pageInfoCmd.accesskey;"
label="&pageInfoCmd.label;"
#ifndef XP_WIN
key="key_viewInfo"
#endif
command="View:PageInfo"/>
command="View:PageInfo" data-l10n-id="menu-tools-page-info"/>
#ifndef XP_UNIX
<menuseparator id="prefSep"/>
<menuitem id="menu_preferences"
label="&preferencesCmd2.label;"
accesskey="&preferencesCmd2.accesskey;"
oncommand="openPreferences(undefined);"/>
oncommand="openPreferences(undefined);" data-l10n-id="menu-preferences"/>
#endif
#ifdef MOZ_DEBUG
<menuitem id="menu_layout_debugger"
label="&ldbCmd.label;"
accesskey="&ldbCmd.accesskey;"
data-l10n-id="menu-tools-layout-debugger"
oncommand="toOpenWindowByType('mozapp:layoutdebug',
'chrome://layoutdebug/content/');"/>
'chrome://layoutdebug/content/layoutdebug.xhtml');"/>
#endif
#ifdef XP_MACOSX
<!-- nsMenuBarX hides these and uses them to build the Application menu. -->
<!-- We need to leave those strings in DTD until bug 1568133 is fixed. -->
<menuitem id="menu_preferences" label="&preferencesCmdMac.label;" key="key_preferencesCmdMac" oncommand="openPreferences(undefined);"/>
<menuitem id="menu_mac_services" label="&servicesMenuMac.label;"/>
<menuitem id="menu_mac_hide_app" label="&hideThisAppCmdMac2.label;" key="key_hideThisAppCmdMac"/>
@ -538,35 +417,29 @@
</menu>
#ifdef XP_MACOSX
<menu id="windowMenu"
label="&windowMenu.label;"
onpopupshowing="macWindowMenuDidShow();"
onpopuphidden="macWindowMenuDidHide();"
>
data-l10n-id="menu-window-menu">
<menupopup id="windowPopup">
<menuitem command="minimizeWindow" key="key_minimizeWindow"/>
<menuitem command="zoomWindow"/>
<!-- decomment when "BringAllToFront" is implemented
<menuseparator/>
<menuitem label="&bringAllToFront.label;" disabled="true"/> -->
<menuitem disabled="true" data-l10n-id="menu-window-bring-all-to-front"/> -->
<menuseparator id="sep-window-list"/>
</menupopup>
</menu>
#endif
<menu id="helpMenu"
#ifdef XP_WIN
label="&helpMenuWin.label;"
accesskey="&helpMenuWin.accesskey;"
#else
label="&helpMenu.label;"
accesskey="&helpMenu.accesskey;"
#endif
>
data-l10n-id="menu-help">
<menupopup id="menu_HelpPopup" onpopupshowing="buildHelpMenu();">
<menuitem id="menu_openHelp"
oncommand="openHelpLink('')"
onclick="checkForMiddleClick(this, event);"
label="&productHelp2.label;"
accesskey="&productHelp2.accesskey;"
data-l10n-id="menu-help-product"
#ifdef XP_MACOSX
key="key_openHelpMac"/>
#else
@ -574,37 +447,15 @@
#endif
<menuitem id="menu_keyboardShortcuts"
oncommand="openHelpLink('')"
onclick="checkForMiddleClick(this, event);"
label="&helpKeyboardShortcuts.label;"
accesskey="&helpKeyboardShortcuts.accesskey;"/>
onclick="checkForMiddleClick(this, event);" data-l10n-id="menu-help-keyboard-shortcuts"/>
<menuitem id="troubleShooting"
accesskey="&helpTroubleshootingInfo.accesskey;"
label="&helpTroubleshootingInfo.label;"
oncommand="openTroubleshootingPage()"
onclick="checkForMiddleClick(this, event);"/>
onclick="checkForMiddleClick(this, event);" data-l10n-id="menu-help-troubleshooting-info"/>
<menuitem id="feedbackPage"
accesskey="&helpFeedbackPage.accesskey;"
label="&helpFeedbackPage.label;"
oncommand="openFeedbackPage()"
onclick="checkForMiddleClick(this, event);"/>
onclick="checkForMiddleClick(this, event);" data-l10n-id="menu-help-feedback-page"/>
<menuitem id="helpSafeMode"
accesskey="&helpSafeMode.accesskey;"
label="&helpSafeMode.label;"
stopaccesskey="&helpSafeMode.stop.accesskey;"
stoplabel="&helpSafeMode.stop.label;"
oncommand="safeModeRestart();"/>
<menuitem id="menu_HelpPopup_reportPhishingtoolmenu"
label="&reportDeceptiveSiteMenu.title;"
accesskey="&reportDeceptiveSiteMenu.accesskey;"
disabled="true"
oncommand="openUILink(gSafeBrowsing.getReportURL('Phish'), event, {triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})});"
onclick="checkForMiddleClick(this, event);"
hidden="true"/>
<menuitem id="menu_HelpPopup_reportPhishingErrortoolmenu"
disabled="true"
oncommand="ReportFalseDeceptiveSite();"
onclick="checkForMiddleClick(this, event);"
hidden="true"/>
oncommand="safeModeRestart();" data-l10n-id="menu-help-safe-mode-without-addons"/>
<menuseparator id="helpPolicySeparator"
hidden="true"/>
<menuitem id="helpPolicySupport"
@ -612,6 +463,7 @@
oncommand="openUILinkIn(Services.policies.getSupportMenu().URL.href, 'tab', {triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})});"
onclick="checkForMiddleClick(this, event);"/>
<menuseparator id="aboutSeparator"/>
<!-- We need to leave those strings in DTD until bug 1568133 is fixed. -->
<menuitem id="aboutName"
accesskey="&aboutProduct2.accesskey;"
label="&aboutProduct2.label;"

View File

@ -244,6 +244,9 @@ var BrowserPageActions = {
"subviewbutton-iconic",
"pageAction-panel-button"
);
if (action.isBadged) {
buttonNode.setAttribute("badged", "true");
}
buttonNode.setAttribute("actionid", action.id);
buttonNode.addEventListener("command", event => {
this.doCommandForAction(action, event, buttonNode);
@ -318,14 +321,13 @@ var BrowserPageActions = {
_makeActivatedActionPanelForAction(action) {
let panelNode = document.createXULElement("panel");
panelNode.id = this._activatedActionPanelID;
panelNode.classList.add("cui-widget-panel");
panelNode.classList.add("cui-widget-panel", "panel-no-padding");
panelNode.setAttribute("actionID", action.id);
panelNode.setAttribute("role", "group");
panelNode.setAttribute("type", "arrow");
panelNode.setAttribute("flip", "slide");
panelNode.setAttribute("noautofocus", "true");
panelNode.setAttribute("tabspecific", "true");
panelNode.setAttribute("photon", "true");
let panelViewNode = null;
let iframeNode = null;
@ -1192,7 +1194,6 @@ BrowserPageActions.addSearchEngine = {
this._updateTitleAndIcon();
this.action.setWantsSubview(this.engines.length > 1, window);
let button = BrowserPageActions.panelButtonNodeForActionID(this.action.id);
button.classList.add("badged-button");
button.setAttribute("image", this.engines[0].icon);
button.setAttribute("uri", this.engines[0].uri);
button.setAttribute("crop", "center");

View File

@ -152,8 +152,7 @@ var StarUI = {
break;
}
this._isComposing = true;
// Explicit fall-through, during composition, panel shouldn't be
// hidden automatically.
// Explicit fall-through, during composition, panel shouldn't be hidden automatically.
case "input":
// Might have edited some text without keyboard events nor composition
// events. Fall-through to cancel auto close in such case.
@ -581,7 +580,7 @@ var PlacesCommandHook = {
if (!organizer || organizer.closed) {
// No currently open places window, so open one with the specified mode.
openDialog(
"chrome://browser/content/places/places.xul",
"chrome://browser/content/places/places.xhtml",
"",
"chrome,toolbar=yes,dialog=no,resizable",
item
@ -949,7 +948,7 @@ var PlacesMenuDNDHandler = {
}
PlacesControllerDragHelper.currentDropTarget = event.target;
let popup = event.target.lastChild;
let popup = event.target.menupopup;
if (
this._loadTimer ||
popup.state === "showing" ||
@ -991,7 +990,7 @@ var PlacesMenuDNDHandler = {
}
PlacesControllerDragHelper.currentDropTarget = null;
let popup = event.target.lastChild;
let popup = event.target.menupopup;
if (this._loadTimer) {
this._loadTimer.cancel();
@ -1031,8 +1030,8 @@ var PlacesMenuDNDHandler = {
node.getAttribute("type") == "menu");
let isStatic =
!("_placesNode" in node) &&
node.lastChild &&
node.lastChild.hasAttribute("placespopup") &&
node.menupopup &&
node.menupopup.hasAttribute("placespopup") &&
!node.parentNode.hasAttribute("placespopup");
return isMenu && isStatic;
},
@ -1234,12 +1233,9 @@ var LibraryUI = {
let animatableBox = document.getElementById("library-animatable-box");
let navBar = document.getElementById("nav-bar");
let libraryIcon = document.getAnonymousElementByAttribute(
libraryButton,
"class",
"toolbarbutton-icon"
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(
libraryButton.icon
);
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryIcon);
let libraryBounds = window.windowUtils.getBoundsWithoutFlushing(
libraryButton
);
@ -1312,12 +1308,9 @@ var LibraryUI = {
}
let animatableBox = document.getElementById("library-animatable-box");
let libraryIcon = document.getAnonymousElementByAttribute(
libraryButton,
"class",
"toolbarbutton-icon"
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(
libraryButton.icon
);
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryIcon);
// Resizing the window will only have the ability to change the X offset of the
// library button.
@ -1581,7 +1574,7 @@ var BookmarkingUI = {
if (this._hasBookmarksObserver) {
PlacesUtils.bookmarks.removeObserver(this);
PlacesUtils.observers.removeListener(
["bookmark-added"],
["bookmark-added", "bookmark-removed"],
this.handlePlacesEvents
);
}
@ -1632,7 +1625,7 @@ var BookmarkingUI = {
PlacesUtils.bookmarks.addObserver(this);
this.handlePlacesEvents = this.handlePlacesEvents.bind(this);
PlacesUtils.observers.addListener(
["bookmark-added"],
["bookmark-added", "bookmark-removed"],
this.handlePlacesEvents
);
this._hasBookmarksObserver = true;
@ -1925,28 +1918,30 @@ var BookmarkingUI = {
},
handlePlacesEvents(aEvents) {
// Only need to update the UI if it wasn't marked as starred before:
if (this._itemGuids.size == 0) {
for (let { url, guid } of aEvents) {
if (url && url == this._uri.spec) {
// If a new bookmark has been added to the tracked uri, register it.
if (!this._itemGuids.has(guid)) {
this._itemGuids.add(guid);
this._updateStar();
for (let ev of aEvents) {
switch (ev.type) {
case "bookmark-added":
// Only need to update the UI if it wasn't marked as starred before:
if (this._itemGuids.size == 0) {
if (ev.url && ev.url == this._uri.spec) {
// If a new bookmark has been added to the tracked uri, register it.
if (!this._itemGuids.has(ev.guid)) {
this._itemGuids.add(ev.guid);
this._updateStar();
}
}
}
}
}
}
},
// nsINavBookmarkObserver
onItemRemoved(aItemId, aParentId, aIndex, aItemType, aURI, aGuid) {
// If one of the tracked bookmarks has been removed, unregister it.
if (this._itemGuids.has(aGuid)) {
this._itemGuids.delete(aGuid);
// Only need to update the UI if the page is no longer starred
if (this._itemGuids.size == 0) {
this._updateStar();
break;
case "bookmark-removed":
// If one of the tracked bookmarks has been removed, unregister it.
if (this._itemGuids.has(ev.guid)) {
this._itemGuids.delete(ev.guid);
// Only need to update the UI if the page is no longer starred
if (this._itemGuids.size == 0) {
this._updateStar();
}
}
break;
}
}
},

View File

@ -1,82 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This file is loaded into the browser window scope.
/* eslint-env mozilla/browser-window */
var gSafeBrowsing = {
setReportPhishingMenu() {
// In order to detect whether or not we're at the phishing warning
// page, we have to check the documentURI instead of the currentURI.
// This is because when the DocShell loads an error page, the
// currentURI stays at the original target, while the documentURI
// will point to the internal error page we loaded instead.
var docURI = gBrowser.selectedBrowser.documentURI;
var isPhishingPage =
docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
// Show/hide the appropriate menu item.
const reportMenu = document.getElementById(
"menu_HelpPopup_reportPhishingtoolmenu"
);
reportMenu.hidden = isPhishingPage;
const reportErrorMenu = document.getElementById(
"menu_HelpPopup_reportPhishingErrortoolmenu"
);
reportErrorMenu.hidden = !isPhishingPage;
if (isPhishingPage && !reportErrorMenu.hasAttribute("data-l10n-id")) {
MozXULElement.insertFTLIfNeeded("browser/safebrowsing/blockedSite.ftl");
document.l10n.setAttributes(reportErrorMenu, "safeb-palm-notdeceptive");
}
// Now look at the currentURI to learn which page we were trying
// to browse to.
const uri = gBrowser.currentURI;
const isReportablePage =
uri && (uri.schemeIs("http") || uri.schemeIs("https"));
const disabledByPolicy = !Services.policies.isAllowed("feedbackCommands");
if (disabledByPolicy || isPhishingPage || !isReportablePage) {
reportMenu.setAttribute("disabled", "true");
} else {
reportMenu.removeAttribute("disabled");
}
if (disabledByPolicy || !isPhishingPage || !isReportablePage) {
reportErrorMenu.setAttribute("disabled", "true");
} else {
reportErrorMenu.removeAttribute("disabled");
}
},
/**
* Used to report a phishing page or a false positive
*
* @param name
* String One of "PhishMistake", "MalwareMistake", or "Phish"
* @param info
* Information about the reasons for blocking the resource.
* In the case false positive, it may contain SafeBrowsing
* matching list and provider of the list
* @return String the report phishing URL.
*/
getReportURL(name, info) {
let reportInfo = info;
if (!reportInfo) {
let pageUri = gBrowser.currentURI;
// Remove the query to avoid including potentially sensitive data
if (pageUri instanceof Ci.nsIURL) {
pageUri = pageUri
.mutate()
.setQuery("")
.finalize();
}
reportInfo = { uri: pageUri.asciiSpec };
}
return SafeBrowsing.getReportURL(name, reportInfo);
},
};

View File

@ -108,7 +108,7 @@
#endif
</commandset>
#include ../../components/places/content/placesCommands.inc.xul
#include ../../components/places/content/placesCommands.inc.xhtml
<keyset id="mainKeyset">
<key id="key_newNavigator"

View File

@ -17,7 +17,7 @@ var SidebarUI = {
title: document
.getElementById("sidebar-switcher-bookmarks")
.getAttribute("label"),
url: "chrome://browser/content/places/bookmarksSidebar.xul",
url: "chrome://browser/content/places/bookmarksSidebar.xhtml",
menuId: "menu_bookmarksSidebar",
buttonId: "sidebar-switcher-bookmarks",
},
@ -28,7 +28,7 @@ var SidebarUI = {
title: document
.getElementById("sidebar-switcher-history")
.getAttribute("label"),
url: "chrome://browser/content/places/historySidebar.xul",
url: "chrome://browser/content/places/historySidebar.xhtml",
menuId: "menu_historySidebar",
buttonId: "sidebar-switcher-history",
triggerButtonId: "appMenuViewHistorySidebar",
@ -226,7 +226,7 @@ var SidebarUI = {
// First reset all ordinals to match DOM ordering.
let browser = document.getElementById("browser");
[...browser.children].forEach((node, i) => {
node.ordinal = i + 1;
node.style.MozBoxOrdinalGroup = i + 1;
});
if (!this._positionStart) {
@ -234,9 +234,9 @@ var SidebarUI = {
// Want to display as: | appcontent | splitter | sidebar-box |
// So we just swap box and appcontent ordering
let appcontent = document.getElementById("appcontent");
let boxOrdinal = this._box.ordinal;
this._box.ordinal = appcontent.ordinal;
appcontent.ordinal = boxOrdinal;
let boxOrdinal = this._box.style.MozBoxOrdinalGroup;
this._box.style.MozBoxOrdinalGroup = appcontent.style.MozBoxOrdinalGroup;
appcontent.style.MozBoxOrdinalGroup = boxOrdinal;
// Indicate we've switched ordering to the box
this._box.setAttribute("positionend", true);
} else {

View File

@ -35,6 +35,13 @@ var gIdentityHandler = {
*/
_isSecureInternalUI: false,
/**
* Whether the content window is considered a "secure context". This
* includes "potentially trustworthy" origins such as file:// URLs or localhost.
* https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
*/
_isSecureContext: false,
/**
* nsITransportSecurityInfo metadata provided by gBrowser.securityUI the last
* time the identity UI was updated, or null if the connection is not secure.
@ -50,13 +57,25 @@ var gIdentityHandler = {
* RegExp used to decide if an about url should be shown as being part of
* the browser UI.
*/
_secureInternalUIWhitelist: /^(?:accounts|addons|cache|config|crashes|customizing|downloads|healthreport|license|permissions|preferences|rights|sessionrestore|support)(?:[?#]|$)/i,
_secureInternalUIWhitelist: /^(?:accounts|addons|cache|config|crashes|customizing|downloads|license|permissions|preferences|rights|sessionrestore|support)(?:[?#]|$)/i,
get _isBroken() {
/**
* Whether the established HTTPS connection is considered "broken".
* This could have several reasons, such as mixed content or weak
* cryptography. If this is true, _isSecureConnection is false.
*/
get _isBrokenConnection() {
return this._state & Ci.nsIWebProgressListener.STATE_IS_BROKEN;
},
get _isSecure() {
/**
* Whether the connection to the current site was done via secure
* transport. Note that this attribute is not true in all cases that
* the site was accessed via HTTPS, i.e. _isSecureConnection will
* be false when _isBrokenConnection is true, even though the page
* was loaded over HTTPS.
*/
get _isSecureConnection() {
// If a <browser> is included within a chrome document, then this._state
// will refer to the security state for the <browser> and not the top level
// document. In this case, don't upgrade the security state in the UI
@ -342,14 +361,6 @@ var gIdentityHandler = {
openPreferences("privacy-permissions");
},
recordClick(object) {
Services.telemetry.recordEvent(
"security.ui.identitypopup",
"click",
object
);
},
/**
* Handler for mouseclicks on the "More Information" button in the
* "identity-popup" panel.
@ -372,12 +383,6 @@ var gIdentityHandler = {
},
disableMixedContentProtection() {
// Use telemetry to measure how often unblocking happens
const kMIXED_CONTENT_UNBLOCK_EVENT = 2;
let histogram = Services.telemetry.getHistogramById(
"MIXED_CONTENT_UNBLOCK_COUNTER"
);
histogram.add(kMIXED_CONTENT_UNBLOCK_EVENT);
// Reload the page with the content unblocked
BrowserReloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT);
PanelMultiView.hidePopup(this._identityPopup);
@ -458,6 +463,7 @@ var gIdentityHandler = {
// the documentation of the individual properties for details.
this.setURI(uri);
this._secInfo = gBrowser.securityUI.secInfo;
this._isSecureContext = gBrowser.securityUI.isSecureContext;
// Then, update the user interface with the available data.
this.refreshIdentityBlock();
@ -587,7 +593,7 @@ var gIdentityHandler = {
if (this._uriHasHost && this._isEV) {
return "verifiedIdentity";
}
if (this._uriHasHost && this._isSecure) {
if (this._uriHasHost && this._isSecureConnection) {
return "verifiedDomain";
}
return "unknownIdentity";
@ -606,6 +612,20 @@ var gIdentityHandler = {
return !issuerCert.isBuiltInRoot;
},
/**
* Returns whether the current URI results in an "invalid"
* URL bar state, which effectively means hidden security
* indicators.
*/
_hasInvalidPageProxyState() {
return (
!this._uriHasHost &&
this._uri &&
isBlankPageURL(this._uri.spec) &&
!this._uri.schemeIs("moz-extension")
);
},
/**
* Updates the identity block user interface with the data from this object.
*/
@ -614,16 +634,28 @@ var gIdentityHandler = {
return;
}
// If this condition is true, the URL bar will have an "invalid"
// pageproxystate, which will hide the security indicators. Thus, we can
// safely avoid updating the security UI.
//
// This will also filter out intermediate about:blank loads to avoid
// flickering the identity block and doing unnecessary work.
if (this._hasInvalidPageProxyState()) {
return;
}
let icon_label = "";
let tooltip = "";
let icon_country_label = "";
let icon_labels_dir = "ltr";
if (this._isSecureInternalUI) {
// This is a secure internal Firefox page.
this._identityBox.className = "chromeUI";
let brandBundle = document.getElementById("bundle_brand");
icon_label = brandBundle.getString("brandShorterName");
} else if (this._uriHasHost && this._isEV) {
// This is a secure connection with EV.
this._identityBox.className = "verifiedIdentity";
if (this._isMixedActiveContentBlocked) {
this._identityBox.classList.add("mixedActiveBlocked");
@ -654,13 +686,15 @@ var gIdentityHandler = {
: "ltr";
}
} else if (this._pageExtensionPolicy) {
// This is a WebExtension page.
this._identityBox.className = "extensionPage";
let extensionName = this._pageExtensionPolicy.name;
icon_label = gNavigatorBundle.getFormattedString(
"identity.extension.label",
[extensionName]
);
} else if (this._uriHasHost && this._isSecure) {
} else if (this._uriHasHost && this._isSecureConnection) {
// This is a secure connection.
this._identityBox.className = "verifiedDomain";
if (this._isMixedActiveContentBlocked) {
this._identityBox.classList.add("mixedActiveBlocked");
@ -672,46 +706,45 @@ var gIdentityHandler = {
[this.getIdentityData().caOrg]
);
}
} else if (!this._uriHasHost) {
} else if (this._isBrokenConnection) {
// This is a secure connection, but something is wrong.
this._identityBox.className = "unknownIdentity";
if (this._isMixedActiveContentLoaded) {
this._identityBox.classList.add("mixedActiveContent");
} else if (this._isMixedActiveContentBlocked) {
this._identityBox.classList.add(
"mixedDisplayContentLoadedActiveBlocked"
);
} else if (this._isMixedPassiveContentLoaded) {
this._identityBox.classList.add("mixedDisplayContent");
} else {
this._identityBox.classList.add("weakCipher");
}
} else if (
gBrowser.selectedBrowser.documentURI &&
(gBrowser.selectedBrowser.documentURI.scheme == "about" ||
gBrowser.selectedBrowser.documentURI.scheme == "chrome")
this._isSecureContext ||
(gBrowser.selectedBrowser.documentURI &&
(gBrowser.selectedBrowser.documentURI.scheme == "about" ||
gBrowser.selectedBrowser.documentURI.scheme == "chrome"))
) {
// For net errors we should not show notSecure as it's likely confusing
// This is a local resource (and shouldn't be marked insecure).
this._identityBox.className = "unknownIdentity";
} else {
if (this._isBroken) {
this._identityBox.className = "unknownIdentity";
// This is an insecure connection.
let warnOnInsecure =
this._insecureConnectionIconEnabled ||
(this._insecureConnectionIconPBModeEnabled &&
PrivateBrowsingUtils.isWindowPrivate(window));
let className = warnOnInsecure ? "notSecure" : "unknownIdentity";
this._identityBox.className = className;
if (this._isMixedActiveContentLoaded) {
this._identityBox.classList.add("mixedActiveContent");
} else if (this._isMixedActiveContentBlocked) {
this._identityBox.classList.add(
"mixedDisplayContentLoadedActiveBlocked"
);
} else if (this._isMixedPassiveContentLoaded) {
this._identityBox.classList.add("mixedDisplayContent");
} else {
this._identityBox.classList.add("weakCipher");
}
} else {
let warnOnInsecure =
this._insecureConnectionIconEnabled ||
(this._insecureConnectionIconPBModeEnabled &&
PrivateBrowsingUtils.isWindowPrivate(window));
let className = warnOnInsecure ? "notSecure" : "unknownIdentity";
this._identityBox.className = className;
let warnTextOnInsecure =
this._insecureConnectionTextEnabled ||
(this._insecureConnectionTextPBModeEnabled &&
PrivateBrowsingUtils.isWindowPrivate(window));
if (warnTextOnInsecure) {
icon_label = gNavigatorBundle.getString("identity.notSecure.label");
this._identityBox.classList.add("notSecureText");
}
let warnTextOnInsecure =
this._insecureConnectionTextEnabled ||
(this._insecureConnectionTextPBModeEnabled &&
PrivateBrowsingUtils.isWindowPrivate(window));
if (warnTextOnInsecure) {
icon_label = gNavigatorBundle.getString("identity.notSecure.label");
this._identityBox.classList.add("notSecureText");
}
if (this._hasInsecureLoginForms) {
// Insecure login forms can only be present on "unknown identity"
@ -854,7 +887,7 @@ var gIdentityHandler = {
connection = "secure-ev";
} else if (this._isCertUserOverridden) {
connection = "secure-cert-user-overridden";
} else if (this._isSecure) {
} else if (this._isSecureConnection) {
connection = "secure";
customRoot = this._hasCustomRoot();
}
@ -882,7 +915,7 @@ var gIdentityHandler = {
// cipher.
let ciphers = "";
if (
this._isBroken &&
this._isBrokenConnection &&
!this._isMixedActiveContentLoaded &&
!this._isMixedPassiveContentLoaded
) {
@ -906,7 +939,7 @@ var gIdentityHandler = {
updateAttribute(element, "loginforms", loginforms);
updateAttribute(element, "ciphers", ciphers);
updateAttribute(element, "mixedcontent", mixedcontent);
updateAttribute(element, "isbroken", this._isBroken);
updateAttribute(element, "isbroken", this._isBrokenConnection);
updateAttribute(element, "customroot", customRoot);
}
@ -917,7 +950,7 @@ var gIdentityHandler = {
let owner = "";
// Fill in the CA name if we have a valid TLS certificate.
if (this._isSecure || this._isCertUserOverridden) {
if (this._isSecureConnection || this._isCertUserOverridden) {
verifier = this._identityIconLabels.tooltipText;
}
@ -957,8 +990,6 @@ var gIdentityHandler = {
// Update per-site permissions section.
this.updateSitePermissions();
ContentBlocking.toggleReportBreakageButton();
},
setURI(uri) {
@ -1034,6 +1065,40 @@ var gIdentityHandler = {
return;
}
// If we are in DOM full-screen, exit it before showing the identity popup
if (document.fullscreen) {
// Open the identity popup after DOM full-screen exit
// We need to wait for the exit event and after that wait for the fullscreen exit transition to complete
// If we call _openPopup before the full-screen transition ends it can get cancelled
// Only waiting for painted is not sufficient because we could still be in the full-screen enter transition.
let exitedEventReceived = false;
window.messageManager.addMessageListener(
"DOMFullscreen:Painted",
function listener() {
if (!exitedEventReceived) {
return;
}
window.messageManager.removeMessageListener(
"DOMFullscreen:Painted",
listener
);
gIdentityHandler._openPopup(event);
}
);
window.addEventListener(
"MozDOMFullscreen:Exited",
() => {
exitedEventReceived = true;
},
{ once: true }
);
document.exitFullscreen();
return;
}
this._openPopup(event);
},
_openPopup(event) {
// Make sure that the display:none style we set in xul is removed now that
// the popup is actually needed
this._identityPopup.hidden = false;
@ -1058,12 +1123,6 @@ var gIdentityHandler = {
if (event.target == this._identityPopup) {
window.addEventListener("focus", this, true);
}
Services.telemetry.recordEvent(
"security.ui.identitypopup",
"open",
"identity_popup"
);
},
onPopupHidden(event) {
@ -1124,11 +1183,7 @@ var gIdentityHandler = {
let ctx = canvas.getContext("2d");
ctx.font = `${14 * scale}px sans-serif`;
ctx.fillText(`${value}`, 20 * scale, 14 * scale);
let tabIcon = document.getAnonymousElementByAttribute(
gBrowser.selectedTab,
"anonid",
"tab-icon-image"
);
let tabIcon = gBrowser.selectedTab.iconImage;
let image = new Image();
image.src = tabIcon.src;
ctx.drawImage(image, 0, 0, 16 * scale, 16 * scale);
@ -1139,6 +1194,9 @@ var gIdentityHandler = {
dt.setData("text/plain", value);
dt.setData("text/html", htmlString);
dt.setDragImage(canvas, 16, 16);
// Don't cover potential drop targets on the toolbars or in content.
gURLBar.view.close();
},
onLocationChange() {
@ -1249,7 +1307,10 @@ var gIdentityHandler = {
} else {
img.classList.add(aPermission.id + "-icon");
}
if (aPermission.state == SitePermissions.BLOCK) {
if (
aPermission.state == SitePermissions.BLOCK ||
aPermission.state == SitePermissions.AUTOPLAY_BLOCKED_ALL
) {
img.classList.add("blocked-permission-icon");
}

View File

@ -150,6 +150,8 @@ var gSync = {
return;
}
MozXULElement.insertFTLIfNeeded("browser/sync.ftl");
this._generateNodeGetters();
// Label for the sync buttons.
@ -158,11 +160,8 @@ var gSync = {
// setting this._initialized, so we don't attempt to remove observers.
return;
}
let syncNow = document.getElementById("PanelUI-remotetabs-syncnow");
let label = this.syncStrings.GetStringFromName("syncnow.label");
syncNow.setAttribute("label", label);
// We start with every menuitem hidden (except for the "setup sync" state),
// so that we don't need to init the sync UI on windows like pageInfo.xul
// so that we don't need to init the sync UI on windows like pageInfo.xhtml
// (see bug 1384856).
// maybeUpdateUIState() also optimizes for this - if we should be in the
// "setup sync" state, that function assumes we are already in it and
@ -548,7 +547,7 @@ var gSync = {
},
updateSyncStatus(state) {
let syncNow = document.getElementById("PanelUI-remotetabs-syncnow");
let syncNow = document.querySelector(".syncNowBtn");
const syncingUI = syncNow.getAttribute("syncstatus") == "active";
if (state.syncing != syncingUI) {
// Do we need to update the UI?
@ -1033,26 +1032,11 @@ var gSync = {
onActivityStart() {
clearTimeout(this._syncAnimationTimer);
this._syncStartTime = Date.now();
let label = this.syncStrings.GetStringFromName("syncingtabs.label");
let remotetabsSyncNowEl = document.getElementById(
"PanelUI-remotetabs-syncnow"
);
let fxaMenuSyncNowEl = document.getElementById(
"PanelUI-fxa-menu-syncnow-button"
);
let syncElements = [remotetabsSyncNowEl, fxaMenuSyncNowEl];
syncElements.forEach(el => {
document.querySelectorAll(".syncNowBtn").forEach(el => {
el.setAttribute("syncstatus", "active");
el.setAttribute("disabled", "true");
document.l10n.setAttributes(el, el.getAttribute("syncinglabel"));
});
remotetabsSyncNowEl.setAttribute("label", label);
fxaMenuSyncNowEl.setAttribute(
"label",
fxaMenuSyncNowEl.getAttribute("syncinglabel")
);
},
_onActivityStop() {
@ -1060,16 +1044,10 @@ var gSync = {
return;
}
let label = this.syncStrings.GetStringFromName("syncnow.label");
let syncElements = [
document.getElementById("PanelUI-remotetabs-syncnow"),
document.getElementById("PanelUI-fxa-menu-syncnow-button"),
];
syncElements.forEach(el => {
document.querySelectorAll(".syncNowBtn").forEach(el => {
el.removeAttribute("syncstatus");
el.removeAttribute("disabled");
el.setAttribute("label", label);
document.l10n.setAttributes(el, "fxa-toolbar-sync-now");
});
Services.obs.notifyObservers(null, "test:browser-sync:activity-stop");
@ -1091,6 +1069,54 @@ var gSync = {
}
},
// Disconnect from sync, and optionally disconnect from the FxA account.
// Returns true if the disconnection happened (ie, if the user didn't decline
// when asked to confirm)
async disconnect({ confirm = true, disconnectAccount = true } = {}) {
if (confirm && !(await this._confirmDisconnect(disconnectAccount))) {
return false;
}
await Weave.Service.promiseInitialized;
await Weave.Service.startOver();
if (disconnectAccount) {
await fxAccounts.signOut();
}
return true;
},
/**
* Prompts the user whether or not they want to proceed with
* disconnecting from their Firefox Account or Sync.
* @param {Boolean} disconnectAccount True if we are disconnecting both Sync and FxA.
* @returns {Boolean} True if the user confirmed.
*/
async _confirmDisconnect(disconnectAccount) {
const l10nPrefix = `${
disconnectAccount ? "fxa" : "sync"
}-disconnect-dialog`;
const [title, body, button] = await document.l10n.formatValues([
{ id: `${l10nPrefix}-title` },
{ id: `${l10nPrefix}-body` },
{ id: "sync-disconnect-dialog-button" },
]);
// buttonPressed will be 0 for disconnect, 1 for cancel.
const flags =
Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 +
Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1;
const buttonPressed = Services.prompt.confirmEx(
window,
title,
body,
flags,
button,
null,
null,
null,
{}
);
return buttonPressed == 0;
},
// doSync forces a sync - it *does not* return a promise as it is called
// via the various UI components.
doSync() {
@ -1191,14 +1217,13 @@ var gSync = {
tooltiptext = this.formatLastSyncDate(state.lastSync);
}
if (this.appMenuLabel) {
let syncNow = document.getElementById("PanelUI-remotetabs-syncnow");
document.querySelectorAll(".syncNowBtn").forEach(el => {
if (tooltiptext) {
syncNow.setAttribute("tooltiptext", tooltiptext);
el.setAttribute("tooltiptext", tooltiptext);
} else {
syncNow.removeAttribute("tooltiptext");
el.removeAttribute("tooltiptext");
}
}
});
},
get relativeTimeFormat() {

View File

@ -19,11 +19,17 @@
* these gets focus, it redirects focus to the appropriate button. This avoids
* the need to continually manage the tabindex of toolbar buttons in response to
* toolbarchanges.
* In addition to linear navigation with tab and arrows, users can also type
* the first (or first few) characters of a button's name to jump directly to
* that button.
*/
ToolbarKeyboardNavigator = {
// Toolbars we want to be keyboard navigable.
kToolbars: [CustomizableUI.AREA_NAVBAR, CustomizableUI.AREA_BOOKMARKS],
// Delay (in ms) after which to clear any search text typed by the user if
// the user hasn't typed anything further.
kSearchClearTimeout: 1000,
_isButton(aElem) {
return (
@ -80,6 +86,16 @@ ToolbarKeyboardNavigator = {
return aRoot._toolbarKeyNavWalker;
},
_initTabStops(aRoot) {
for (let stop of aRoot.getElementsByTagName("toolbartabstop")) {
// These are invisible, but because they need to be in the tab order,
// they can't get display: none or similar. They must therefore be
// explicitly hidden for accessibility.
stop.setAttribute("aria-hidden", "true");
stop.addEventListener("focus", this);
}
},
init() {
for (let id of this.kToolbars) {
let toolbar = document.getElementById(id);
@ -87,16 +103,11 @@ ToolbarKeyboardNavigator = {
// We manage toolbar focus completely. This attribute ensures that CSS
// doesn't set -moz-user-focus: normal.
toolbar.setAttribute("keyNav", "true");
for (let stop of toolbar.getElementsByTagName("toolbartabstop")) {
// These are invisible, but because they need to be in the tab order,
// they can't get display: none or similar. They must therefore be
// explicitly hidden for accessibility.
stop.setAttribute("aria-hidden", "true");
stop.addEventListener("focus", this);
}
this._initTabStops(toolbar);
toolbar.addEventListener("keydown", this);
toolbar.addEventListener("keypress", this);
}
CustomizableUI.addListener(this);
},
uninit() {
@ -109,6 +120,19 @@ ToolbarKeyboardNavigator = {
toolbar.removeEventListener("keypress", this);
toolbar.removeAttribute("keyNav");
}
CustomizableUI.removeListener(this);
},
// CustomizableUI event handler
onWidgetAdded(aWidgetId, aArea, aPosition) {
if (!this.kToolbars.includes(aArea)) {
return;
}
let widget = document.getElementById(aWidgetId);
if (!widget) {
return;
}
this._initTabStops(widget);
},
_focusButton(aButton) {
@ -162,6 +186,42 @@ ToolbarKeyboardNavigator = {
walker.currentNode = aEvent.target;
let button = walker.nextNode();
if (!button || !this._isButton(button)) {
// If we think we're moving backward, and focus came from outside the
// toolbox, we might actually have wrapped around. This currently only
// happens in popup windows (because in normal windows, focus first
// goes to the tabstrip, where we don't have tabstops). In this case,
// the event target was the first tabstop. If we can't find a button,
// e.g. because we're in a popup where most buttons are hidden, we
// should ensure focus keeps moving forward:
if (
oldFocus &&
this._isFocusMovingBackward &&
!gNavToolbox.contains(oldFocus)
) {
let allStops = Array.from(
gNavToolbox.querySelectorAll("toolbartabstop")
);
// Find the previous toolbartabstop:
let earlierVisibleStopIndex = allStops.indexOf(aEvent.target) - 1;
// Then work out if any of the earlier ones are in a visible
// toolbar:
while (earlierVisibleStopIndex >= 0) {
let stopToolbar = allStops[earlierVisibleStopIndex].closest(
"toolbar"
);
if (
window.windowUtils.getBoundsWithoutFlushing(stopToolbar).height > 0
) {
break;
}
earlierVisibleStopIndex--;
}
// If we couldn't find any earlier visible stops, we're not moving
// backwards, we're moving forwards and wrapped around:
if (earlierVisibleStopIndex == -1) {
this._isFocusMovingBackward = false;
}
}
// No navigable buttons for this tab stop. Skip it.
if (this._isFocusMovingBackward) {
document.commandDispatcher.rewindFocus();
@ -194,6 +254,20 @@ ToolbarKeyboardNavigator = {
_onKeyDown(aEvent) {
let focus = document.activeElement;
if (
aEvent.key != " " &&
aEvent.key.length == 1 &&
this._isButton(focus) &&
// Don't handle characters if the user is focused in a panel anchored
// to the toolbar.
!focus.closest("panel")
) {
this._onSearchChar(aEvent.currentTarget, aEvent.key);
return;
}
// Anything that doesn't trigger search should clear the search.
this._clearSearch();
if (
aEvent.altKey ||
aEvent.controlKey ||
@ -219,6 +293,83 @@ ToolbarKeyboardNavigator = {
aEvent.preventDefault();
},
_clearSearch() {
this._searchText = "";
if (this._clearSearchTimeout) {
clearTimeout(this._clearSearchTimeout);
this._clearSearchTimeout = null;
}
},
_onSearchChar(aToolbar, aChar) {
if (this._clearSearchTimeout) {
// The user just typed a character, so reset the timer.
clearTimeout(this._clearSearchTimeout);
}
// Convert to lower case so we can do case insensitive searches.
let char = aChar.toLowerCase();
// If the user has only typed a single character and they type the same
// character again, they want to move to the next item starting with that
// same character. Effectively, it's as if there was no existing search.
// In that case, we just leave this._searchText alone.
if (!this._searchText) {
this._searchText = char;
} else if (this._searchText != char) {
this._searchText += char;
}
// Clear the search if the user doesn't type anything more within the timeout.
this._clearSearchTimeout = setTimeout(
this._clearSearch.bind(this),
this.kSearchClearTimeout
);
let oldFocus = document.activeElement;
let walker = this._getWalker(aToolbar);
// Search forward after the current control.
walker.currentNode = oldFocus;
for (
let newFocus = walker.nextNode();
newFocus;
newFocus = walker.nextNode()
) {
if (this._doesSearchMatch(newFocus)) {
this._focusButton(newFocus);
return;
}
}
// No match, so search from the start until the current control.
walker.currentNode = walker.root;
for (
let newFocus = walker.firstChild();
newFocus && newFocus != oldFocus;
newFocus = walker.nextNode()
) {
if (this._doesSearchMatch(newFocus)) {
this._focusButton(newFocus);
return;
}
}
},
_doesSearchMatch(aElem) {
if (!this._isButton(aElem)) {
return false;
}
for (let attrib of ["aria-label", "label", "tooltiptext"]) {
let label = aElem.getAttribute(attrib);
if (!label) {
continue;
}
// Convert to lower case so we do a case insensitive comparison.
// (this._searchText is already lower case.)
label = label.toLowerCase();
if (label.startsWith(this._searchText)) {
return true;
}
}
return false;
},
_onKeyPress(aEvent) {
let focus = document.activeElement;
if (

View File

@ -2,10 +2,23 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
:root,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow: -moz-hidden-unscrollable;
}
:root {
text-rendering: optimizeLegibility;
min-height: 95px;
min-width: 95px;
/* variables */
--panelui-subview-transition-duration: 150ms;
--lwt-additional-images: none;
--lwt-background-alignment: right top;
@ -16,6 +29,10 @@
--toolbar-color: var(--toolbar-non-lwt-textcolor);
}
:root:-moz-locale-dir(rtl) {
direction: rtl;
}
:root:-moz-lwtheme {
--toolbar-bgcolor: rgba(255,255,255,.4);
--toolbar-bgimage: none;
@ -35,6 +52,26 @@
background-color: var(--lwt-accent-color-inactive, var(--lwt-accent-color));
}
:root:not([chromehidden~="toolbar"]) {
min-width: 450px;
}
:root[customizing] {
min-width: -moz-fit-content;
}
/* Prevent shrinking the page content to 0 height and width */
.browserStack {
min-height: 25px;
min-width: 25px;
}
body {
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-flex: 1;
}
/* Set additional backgrounds alignment relative to toolbox */
#navigator-toolbox:-moz-lwtheme {
@ -43,29 +80,11 @@
background-repeat: var(--lwt-background-tiling);
}
:root:not([chromehidden~="toolbar"]) {
%ifdef XP_MACOSX
min-width: 335px;
%else
min-width: 300px;
%endif
}
:root[customize-entered] {
min-width: -moz-fit-content;
}
.search-one-offs[compact=true] .search-setting-button,
.search-one-offs:not([compact=true]) .search-setting-button-compact {
display: none;
}
/* Prevent shrinking the page content to 0 height and width */
.browserStack {
min-height: 25px;
min-width: 25px;
}
%ifdef MENUBAR_CAN_AUTOHIDE
#toolbar-menubar[autohide="true"] {
overflow: hidden;
@ -80,7 +99,6 @@
%ifdef XP_MACOSX
#toolbar-menubar {
-moz-binding: none;
visibility: collapse;
}
%endif
@ -119,7 +137,6 @@ panelview[mainview] > .panel-header {
.panel-viewcontainer.offscreen {
display: block;
position: absolute;
}
.panel-viewstack {
@ -127,10 +144,6 @@ panelview[mainview] > .panel-header {
transition: height var(--panelui-subview-transition-duration);
}
#tabbrowser-tabs {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabs");
}
@supports -moz-bool-pref("layout.css.emulate-moz-box-with-flex") {
#tabbrowser-tabs {
/* Without this, the tabs container width extends beyond the window width */
@ -145,9 +158,9 @@ panelview[mainview] > .panel-header {
#tabbrowser-tabs:not([overflow="true"]):not([hashiddentabs]) ~ #alltabs-button,
#tabbrowser-tabs[hasadjacentnewtabbutton]:not([overflow="true"]) ~ #new-tab-button,
#tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
#TabsToolbar[customizing="true"] #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button {
#tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > #tabs-newtab-button,
#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > .tabbrowser-arrowscrollbox > #tabs-newtab-button,
#TabsToolbar[customizing="true"] #tabs-newtab-button {
visibility: collapse;
}
@ -155,10 +168,6 @@ panelview[mainview] > .panel-header {
visibility: hidden; /* temporary space to keep a tab's close button under the cursor */
}
.tabbrowser-tab {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tab");
}
.tabbrowser-tab:not([pinned]) {
-moz-box-flex: 100;
max-width: 225px;
@ -208,13 +217,13 @@ panelview[mainview] > .panel-header {
}
%endif
#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-arrowscrollbox > .tabbrowser-tab[pinned] {
position: fixed !important;
display: block;
}
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[selected],
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[multiselected] {
#tabbrowser-tabs[movingtab] > .tabbrowser-arrowscrollbox > .tabbrowser-tab[selected],
#tabbrowser-tabs[movingtab] > .tabbrowser-arrowscrollbox > .tabbrowser-tab[multiselected] {
position: relative;
z-index: 2;
pointer-events: none; /* avoid blocking dragover events on scroll buttons */
@ -248,8 +257,15 @@ panelview[mainview] > .panel-header {
pointer-events: auto;
}
toolbar[overflowable] > .customization-target {
overflow: hidden;
/* The address bar needs to be able to render outside of the toolbar, but as
* long as it's within the toolbar's bounds we can clip the toolbar so that the
* rendering pipeline doesn't reserve an enormous texture for it. */
#nav-bar:not([urlbar-exceeds-toolbar-bounds]),
/* When customizing, overflowable toolbars move automatically moved items back
* from the overflow menu, but we still don't want to render them outside of
* the customization target. */
toolbar[overflowable][customizing] > .customization-target {
overflow: clip;
}
toolbar:not([overflowing]) > .overflow-button,
@ -257,7 +273,7 @@ toolbar[customizing] > .overflow-button {
display: none;
}
window:not([chromehidden~="toolbar"]) #nav-bar[nonemptyoverflow] > .overflow-button,
:root:not([chromehidden~="toolbar"]) #nav-bar[nonemptyoverflow] > .overflow-button,
#nav-bar[customizing] > .overflow-button {
display: -moz-box;
}
@ -534,20 +550,15 @@ toolbar:not(#TabsToolbar) > #personal-bookmarks {
}
#urlbar,
.searchbar-textbox {
#searchbar {
/* Setting a width and min-width to let the location & search bars maintain
a constant width in case they haven't be resized manually. (bug 965772) */
width: 1px;
min-width: 1px;
}
#urlbar[quantumbar="true"] {
-moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
}
/* Display URLs left-to-right but right aligned in RTL mode. */
html|input.urlbar-input:-moz-locale-dir(rtl) {
#urlbar-input:-moz-locale-dir(rtl) {
direction: ltr !important;
text-align: right !important;
}
@ -555,10 +566,11 @@ html|input.urlbar-input:-moz-locale-dir(rtl) {
/* Make sure that the location bar's alignment in RTL mode changes according
to the input box direction if the user switches the text direction using
cmd_switchTextDirection (which applies a dir attribute to the <input>). */
html|input.urlbar-input[dir=ltr]:-moz-locale-dir(rtl) {
#urlbar-input[dir=ltr]:-moz-locale-dir(rtl) {
text-align: left !important;
}
%ifdef ENABLE_MARIONETTE
/*
* Display visual cue that browser is under remote control by Marionette.
* This is to help users visually distinguish a user agent session that
@ -579,13 +591,13 @@ html|input.urlbar-input[dir=ltr]:-moz-locale-dir(rtl) {
:root[remotecontrol] #urlbar #identity-box {
background: white;
}
%endif
/* Show the url scheme in a static box when overflowing to the left */
moz-input-box.urlbar-input-box {
.urlbar-input-box {
position: relative;
direction: ltr;
}
html|input.urlbar-scheme {
#urlbar-scheme {
position: absolute;
height: 100%;
visibility: hidden;
@ -595,22 +607,22 @@ html|input.urlbar-scheme {
/* Visible if the urlbar is not focused and it overflows at the start.
Uses the required-valid trick to check if it contains a value */
html|input.urlbar-scheme[textoverflow="start"]:not([focused]):valid {
#urlbar[textoverflow="start"]:not([focused]) > #urlbar-input-container > .urlbar-input-box > #urlbar-scheme:valid {
visibility: visible;
}
/* Fade out URL on overflow
This mask may be overriden when a Contextual Feature Recommendation is shown,
see browser/themes/shared/urlbar-searchbar.inc.css for details */
html|input.urlbar-input[textoverflow="end"]:not([focused]) {
#urlbar[textoverflow="end"]:not([focused]) > #urlbar-input-container > .urlbar-input-box > #urlbar-input {
mask-image: linear-gradient(to left, transparent, black 3ch);
}
html|input.urlbar-input[textoverflow="start"]:not([focused]) {
#urlbar[textoverflow="start"]:not([focused]) > #urlbar-input-container > .urlbar-input-box > #urlbar-input {
mask-image: linear-gradient(to right, transparent var(--urlbar-scheme-size), black calc(var(--urlbar-scheme-size) + 3ch));
}
html|input.urlbar-input {
#urlbar-input {
mask-repeat: no-repeat;
}
@ -621,10 +633,10 @@ html|input.urlbar-input {
}
}
#urlbar[actionoverride] > #urlbar-display-box,
#urlbar:not([actiontype="switchtab"]):not([actiontype="extension"]) > #urlbar-display-box,
#urlbar:not([actiontype="switchtab"]) > #urlbar-display-box > #switchtab,
#urlbar:not([actiontype="extension"]) > #urlbar-display-box > #extension {
#urlbar[actionoverride] > #urlbar-input-container > #urlbar-label-box,
#urlbar:not([actiontype="switchtab"]):not([actiontype="extension"]) > #urlbar-input-container > #urlbar-label-box,
#urlbar:not([actiontype="switchtab"]) > #urlbar-input-container > #urlbar-label-box > #urlbar-label-switchtab,
#urlbar:not([actiontype="extension"]) > #urlbar-input-container > #urlbar-label-box > #urlbar-label-extension {
display: none;
}
@ -641,12 +653,18 @@ html|input.urlbar-input {
background-color: hsla(0,0%,80%,.5); /* match arrowpanel-dimmed-further */
}
#PopupAutoComplete[firstresultstyle="insecureWarning"] {
min-width: 200px;
/* Define the minimum width based on the style of result rows.
The order of the min-width rules below must be in increasing order. */
#PopupAutoComplete[resultstyles~="loginsFooter"],
#PopupAutoComplete[resultstyles~="insecureWarning"] {
min-width: 17em;
}
#PopupAutoComplete[resultstyles~="generatedPassword"] {
min-width: 21em;
}
#PopupAutoComplete > richlistbox > richlistitem[originaltype="insecureWarning"] {
-moz-binding: none;
height: auto;
}
@ -665,11 +683,11 @@ html|input.urlbar-input {
margin-inline-start: 0;
}
#urlbar[pageproxystate=invalid] > #page-action-buttons > .urlbar-page-action,
#urlbar-input-container[pageproxystate=invalid] > #page-action-buttons > .urlbar-page-action,
#identity-box.chromeUI ~ #page-action-buttons > .urlbar-page-action:not(#star-button-box),
.urlbar-history-dropmarker[usertyping],
.urlbar-go-button:not([usertyping]),
.urlbar-go-button:not([parentfocused="true"]) {
#urlbar[usertyping] > #urlbar-input-container > .urlbar-history-dropmarker,
#urlbar:not([usertyping]) > #urlbar-input-container > #urlbar-go-button,
#urlbar:not([focused]) > #urlbar-input-container > #urlbar-go-button {
display: none;
}
@ -677,66 +695,56 @@ html|input.urlbar-input {
-moz-user-focus: normal;
}
/* We leave 49ch plus whatever space the download button will need when it
/* We leave 350px plus whatever space the download button will need when it
* appears. Normally this should be 16px for the icon, plus 2 * 2px padding
* plus the toolbarbutton-inner-padding. We're adding 4px to ensure things
* like rounding on hidpi don't accidentally result in the button going
* into overflow.
*/
#urlbar-container {
min-width: calc(49ch + 24px + 2 * var(--toolbarbutton-inner-padding));
#urlbar-container {
min-width: calc(350px + 24px + 2 * var(--toolbarbutton-inner-padding));
}
#nav-bar[downloadsbuttonshown] #urlbar-container {
min-width: 49ch;
min-width: 350px;
}
/* Customize mode is difficult to use at moderate window width if the Urlbar
remains 350px wide. */
:root[customizing] #urlbar-container {
min-width: 280px;
}
#identity-icon-labels {
max-width: 17em;
max-width: 10em;
}
@media (max-width: 700px) {
#urlbar-container {
min-width: calc(44ch + 24px + 2 * var(--toolbarbutton-inner-padding));
}
#nav-bar[downloadsbuttonshown] #urlbar-container {
min-width: 44ch;
}
#identity-icon-labels {
max-width: 60px;
}
}
@media (max-width: 600px) {
@media (max-width: 770px) {
#urlbar-container {
min-width: calc(39ch + 24px + 2 * var(--toolbarbutton-inner-padding));
min-width: calc(280px + 24px + 2 * var(--toolbarbutton-inner-padding));
}
#nav-bar[downloadsbuttonshown] #urlbar-container {
min-width: 39ch;
min-width: 280px;
}
:root[customizing] #urlbar-container {
min-width: 245px;
}
#identity-icon-labels {
max-width: 50px;
}
}
@media (max-width: 500px) {
@media (max-width: 550px) {
#urlbar-container {
min-width: calc(34ch + 24px + 2 * var(--toolbarbutton-inner-padding));
min-width: calc(225px + 24px + 2 * var(--toolbarbutton-inner-padding));
}
#nav-bar[downloadsbuttonshown] #urlbar-container {
min-width: 34ch;
min-width: 225px;
}
#identity-icon-labels {
max-width: 40px;
}
}
@media (max-width: 400px) {
#urlbar-container {
min-width: calc(27ch + 24px + 2 * var(--toolbarbutton-inner-padding));
}
#nav-bar[downloadsbuttonshown] #urlbar-container {
min-width: 27ch;
}
#identity-icon-labels {
max-width: 30px;
#urlbar-zoom-button {
display: none;
}
}
@ -748,7 +756,7 @@ html|input.urlbar-input {
margin-inline-end: 0.25em !important;
}
/* Flexible spacer sizing (matching url bar) */
/* Flexible spacer sizing (gets overridden in the navbar) */
toolbarpaletteitem[place=toolbar][id^=wrapper-customizableui-special-spring],
toolbarspring {
-moz-box-flex: 1;
@ -759,6 +767,14 @@ toolbarspring {
#nav-bar toolbarpaletteitem[id^=wrapper-customizableui-special-spring],
#nav-bar toolbarspring {
-moz-box-flex: 80;
/* We shrink the flexible spacers, but not to nothing so they can be
* manipulated in customize mode; the next rule shrinks them further
* outside customize mode. */
min-width: 10px;
}
#nav-bar:not([customizing]) toolbarspring {
min-width: 1px;
}
#widget-overflow-list > toolbarspring {
@ -786,10 +802,6 @@ toolbarspring {
.bookmark-item > .menu-iconic-left > .menu-iconic-icon {
image-rendering: -moz-crisp-edges;
}
/* Synced Tabs sidebar */
html|*.tabs-container html|*.item-tabs-list html|*.item-icon-container {
image-rendering: -moz-crisp-edges;
}
}
menupopup[emptyplacesresult="true"] > .hide-if-empty-places-result {
@ -797,8 +809,7 @@ menupopup[emptyplacesresult="true"] > .hide-if-empty-places-result {
}
/* Hide extension toolbars that neglected to set the proper class */
window[chromehidden~="location"][chromehidden~="toolbar"] toolbar:not(.chromeclass-menubar),
window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#print-preview-toolbar):not(.chromeclass-menubar) {
:root[chromehidden~="location"][chromehidden~="toolbar"] toolbar:not(.chromeclass-menubar) {
display: none;
}
@ -831,7 +842,7 @@ window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#pri
background: black;
}
html|*.pointerlockfswarning {
.pointerlockfswarning {
position: fixed;
z-index: 2147483647 !important;
visibility: visible;
@ -845,32 +856,32 @@ html|*.pointerlockfswarning {
max-width: 95%;
pointer-events: none;
}
html|*.pointerlockfswarning:not([hidden]) {
.pointerlockfswarning:not([hidden]) {
display: flex;
will-change: transform;
}
html|*.pointerlockfswarning[onscreen] {
.pointerlockfswarning[onscreen] {
transform: translate(-50%, 50px);
}
html|*.pointerlockfswarning[ontop] {
.pointerlockfswarning[ontop] {
/* Use -10px to hide the border and border-radius on the top */
transform: translate(-50%, -10px);
}
:root[OSXLionFullscreen] html|*.pointerlockfswarning[ontop] {
:root[OSXLionFullscreen] .pointerlockfswarning[ontop] {
transform: translate(-50%, 80px);
}
html|*.pointerlockfswarning-domain-text,
html|*.pointerlockfswarning-generic-text {
.pointerlockfswarning-domain-text,
.pointerlockfswarning-generic-text {
word-wrap: break-word;
/* We must specify a min-width, otherwise word-wrap:break-word doesn't work. Bug 630864. */
min-width: 1px
}
html|*.pointerlockfswarning-domain-text:not([hidden]) + html|*.pointerlockfswarning-generic-text {
.pointerlockfswarning-domain-text:not([hidden]) + .pointerlockfswarning-generic-text {
display: none;
}
html|*#fullscreen-exit-button {
#fullscreen-exit-button {
pointer-events: auto;
}
@ -893,7 +904,7 @@ html|*#fullscreen-exit-button {
/* should occupy space but not be visible */
opacity: 0;
pointer-events: none;
-moz-stack-sizing: ignore;
position: absolute;
}
browser[tabmodalPromptShowing] {
@ -958,7 +969,7 @@ browser[tabmodalPromptShowing] {
and just show the icon. This is a hack to side-step very weird layout bugs that
seem to be caused by the indicator stack interacting with the menu panel. */
#downloads-button[indicator]:not([cui-areatype="menu-panel"]) > .toolbarbutton-badge-stack > image.toolbarbutton-icon,
#downloads-button[indicator][cui-areatype="menu-panel"] > #downloads-indicator-anchor {
#downloads-button[indicator][cui-areatype="menu-panel"] > .toolbarbutton-badge-stack > #downloads-indicator-anchor {
display: none;
}
@ -966,7 +977,7 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > .toolbarbut
display: -moz-box;
}
toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > #downloads-indicator-anchor {
toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > .toolbarbutton-badge-stack > #downloads-indicator-anchor {
display: none;
}
@ -985,7 +996,6 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > #downloads-
/* Give this menupopup an arrow panel styling */
#BMB_bookmarksPopup {
appearance: none;
-moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-arrow");
background: transparent;
border: none;
/* The popup inherits -moz-image-region from the button, must reset it */

View File

@ -35,6 +35,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
LightweightThemeConsumer:
"resource://gre/modules/LightweightThemeConsumer.jsm",
Log: "resource://gre/modules/Log.jsm",
LoginHelper: "resource://gre/modules/LoginHelper.jsm",
LoginManagerParent: "resource://gre/modules/LoginManagerParent.jsm",
MigrationUtils: "resource:///modules/MigrationUtils.jsm",
NetUtil: "resource://gre/modules/NetUtil.jsm",
@ -165,11 +166,6 @@ XPCOMUtils.defineLazyScriptGetter(
["gGestureSupport", "gHistorySwipeAnimation"],
"chrome://browser/content/browser-gestureSupport.js"
);
XPCOMUtils.defineLazyScriptGetter(
this,
"gSafeBrowsing",
"chrome://browser/content/browser-safebrowsing.js"
);
XPCOMUtils.defineLazyScriptGetter(
this,
"gSync",
@ -246,7 +242,9 @@ XPCOMUtils.defineLazyServiceGetters(this, {
"@mozilla.org/network/serialization-helper;1",
"nsISerializationHelper",
],
#ifdef ENABLE_MARIONETTE
Marionette: ["@mozilla.org/remote/marionette;1", "nsIMarionette"],
#endif
WindowsUIUtils: ["@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils"],
});
@ -286,58 +284,11 @@ XPCOMUtils.defineLazyGetter(this, "gNavToolbox", () => {
return document.getElementById("navigator-toolbox");
});
XPCOMUtils.defineLazyGetter(this, "gURLBar", () => gURLBarHandler.urlbar);
/**
* Tracks the urlbar object, allowing to reinitiate it when necessary, e.g. on
* customization.
*/
var gURLBarHandler = {
/**
* The urlbar binding or object.
*/
get urlbar() {
if (!this._urlbar) {
let textbox = document.getElementById("urlbar");
this._urlbar = new UrlbarInput({ textbox });
if (this._lastValue) {
this._urlbar.value = this._lastValue;
delete this._lastValue;
}
gBrowser.tabContainer.addEventListener("TabSelect", this._urlbar);
}
return this._urlbar;
},
/**
* Invoked by CustomizationHandler when a customization starts.
*/
customizeStart() {
if (this._urlbar) {
this._urlbar.removeCopyCutController();
}
},
/**
* Invoked by CustomizationHandler when a customization ends.
*/
customizeEnd() {
this._reset();
},
/**
* Used to reset the gURLBar value.
*/
_reset() {
if (this._urlbar) {
gBrowser.tabContainer.removeEventListener("TabSelect", this._urlbar);
this._lastValue = this._urlbar.value;
this._urlbar.uninit();
delete this._urlbar;
gURLBar = this.urlbar;
}
},
};
XPCOMUtils.defineLazyGetter(this, "gURLBar", () => {
return new UrlbarInput({
textbox: document.getElementById("urlbar"),
});
});
XPCOMUtils.defineLazyGetter(this, "ReferrerInfo", () =>
Components.Constructor(
@ -472,13 +423,6 @@ XPCOMUtils.defineLazyPreferenceGetter(
}
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"gHtmlAboutAddonsEnabled",
"extensions.htmlaboutaddons.enabled",
false
);
customElements.setElementCreationCallback("translation-notification", () => {
Services.scriptloader.loadSubScript(
"chrome://browser/content/translation-notification.js",
@ -645,7 +589,7 @@ function UpdateBackForwardCommands(aWebNavigation) {
/**
* Click-and-Hold implementation for the Back and Forward buttons
* XXXmano: should this live in toolbarbutton.xml?
* XXXmano: should this live in toolbarbutton.js?
*/
function SetClickAndHoldHandlers() {
// Bug 414797: Clone the back/forward buttons' context menu into both buttons.
@ -656,13 +600,13 @@ function SetClickAndHoldHandlers() {
let backButton = document.getElementById("back-button");
backButton.setAttribute("type", "menu");
backButton.appendChild(popup);
backButton.prepend(popup);
gClickAndHoldListenersOnElement.add(backButton);
let forwardButton = document.getElementById("forward-button");
popup = popup.cloneNode(true);
forwardButton.setAttribute("type", "menu");
forwardButton.appendChild(popup);
forwardButton.prepend(popup);
gClickAndHoldListenersOnElement.add(forwardButton);
}
@ -679,7 +623,7 @@ const gClickAndHoldListenersOnElement = {
}
// Prevent the menupopup from opening immediately
aEvent.currentTarget.firstElementChild.hidden = true;
aEvent.currentTarget.menupopup.hidden = true;
aEvent.currentTarget.addEventListener("mouseout", this);
aEvent.currentTarget.addEventListener("mouseup", this);
@ -1579,7 +1523,8 @@ var delayedStartupPromise = new Promise(resolve => {
var gBrowserInit = {
delayedStartupFinished: false,
idleTasksFinished: false,
idleTasksFinishedPromise: null,
idleTaskPromiseResolve: null,
_tabToAdopt: undefined,
@ -1613,10 +1558,6 @@ var gBrowserInit = {
},
onBeforeInitialXULLayout() {
// Turn on QuantumBar. This can be removed once the quantumbar attribute is gone.
let urlbar = document.getElementById("urlbar");
urlbar.setAttribute("quantumbar", true);
// Set a sane starting width/height for all resolutions on new profiles.
if (Services.prefs.getBoolPref("privacy.resistFingerprinting")) {
// When the fingerprinting resistance is enabled, making sure that we don't
@ -1685,7 +1626,7 @@ var gBrowserInit = {
// This needs setting up before we create the first remote browser.
window.docShell.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow).XULBrowserWindow = window.XULBrowserWindow;
.getInterface(Ci.nsIAppWindow).XULBrowserWindow = window.XULBrowserWindow;
window.browserDOMWindow = new nsBrowserAccess();
gBrowser = window._gBrowser;
@ -1783,7 +1724,7 @@ var gBrowserInit = {
if (!window.toolbar.visible) {
// adjust browser UI for popups
gURLBar.setAttribute("readonly", "true");
gURLBar.readOnly = true;
}
// Misc. inits.
@ -1799,7 +1740,9 @@ var gBrowserInit = {
ToolbarKeyboardNavigator.init();
}
#ifdef ENABLE_MARIONETTE
gRemoteControl.updateVisualCue(Marionette.running);
#endif
// If we are given a tab to swap in, take care of it before first paint to
// avoid an about:blank flash.
@ -1883,7 +1826,9 @@ var gBrowserInit = {
this._handleURIToLoad();
Services.obs.addObserver(gIdentityHandler, "perm-changed");
#ifdef ENABLE_MARIONETTE
Services.obs.addObserver(gRemoteControl, "remote-active");
#endif
Services.obs.addObserver(
gSessionHistoryObserver,
"browser:purge-session-history"
@ -1927,8 +1872,7 @@ var gBrowserInit = {
let safeMode = document.getElementById("helpSafeMode");
if (Services.appinfo.inSafeMode) {
safeMode.label = safeMode.getAttribute("stoplabel");
safeMode.accessKey = safeMode.getAttribute("stopaccesskey");
document.l10n.setAttributes(safeMode, "menu-help-safe-mode-with-addons");
}
// BiDi UI
@ -1993,7 +1937,7 @@ var gBrowserInit = {
window.addEventListener("dragover", MousePosTracker);
gNavToolbox.addEventListener("customizationstarting", CustomizationHandler);
gNavToolbox.addEventListener("customizationending", CustomizationHandler);
gNavToolbox.addEventListener("aftercustomization", CustomizationHandler);
SessionStore.promiseInitialized.then(() => {
// Bail out if the window has been closed in the meantime.
@ -2288,7 +2232,7 @@ var gBrowserInit = {
// timeouts) should execute in order. Note that this observer notification is
// not guaranteed to fire, since the window could close before we get here.
scheduleIdleTask(() => {
this.idleTasksFinished = true;
this.idleTaskPromiseResolve();
Services.obs.notifyObservers(
window,
"browser-idle-startup-tasks-finished"
@ -2435,7 +2379,9 @@ var gBrowserInit = {
FullZoom.destroy();
Services.obs.removeObserver(gIdentityHandler, "perm-changed");
#ifdef ENABLE_MARIONETTE
Services.obs.removeObserver(gRemoteControl, "remote-active");
#endif
Services.obs.removeObserver(
gSessionHistoryObserver,
"browser:purge-session-history"
@ -2482,11 +2428,15 @@ var gBrowserInit = {
window.XULBrowserWindow = null;
window.docShell.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow).XULBrowserWindow = null;
.getInterface(Ci.nsIAppWindow).XULBrowserWindow = null;
window.browserDOMWindow = null;
},
};
gBrowserInit.idleTasksFinishedPromise = new Promise(resolve => {
gBrowserInit.idleTaskPromiseResolve = resolve;
});
function HandleAppCommandEvent(evt) {
switch (evt.command) {
case "Back":
@ -2754,7 +2704,7 @@ function loadOneOrMoreURIs(aURIString, aTriggeringPrincipal, aCsp) {
}
/**
* Focuses the location bar input field and selects its contents.
* Focuses and expands the location bar input field and selects its contents.
*/
function focusAndSelectUrlBar() {
// In customize mode, the url bar is disabled. If a new tab is opened or the
@ -2779,9 +2729,7 @@ function focusAndSelectUrlBar() {
function openLocation() {
if (window.location.href == AppConstants.BROWSER_CHROME_URL) {
focusAndSelectUrlBar();
if (gURLBar.openViewOnFocus && !gURLBar.view.isOpen) {
gURLBar.startQuery();
}
gURLBar.view.autoOpen();
return;
}
@ -3166,7 +3114,7 @@ function BrowserPageInfo(
// We didn't find a matching window, so open a new one.
return openDialog(
"chrome://browser/content/pageinfo/pageInfo.xul",
"chrome://browser/content/pageinfo/pageInfo.xhtml",
"",
"chrome,toolbar,dialog=no,resizable",
args
@ -3371,10 +3319,7 @@ function SetPageProxyState(aState, updatePopupNotifications) {
}
let oldPageProxyState = gURLBar.getAttribute("pageproxystate");
// The "browser_urlbar_stop_pending.js" test uses a MutationObserver to do
// some verifications at this point, and it breaks if we don't write the
// attribute, even if it hasn't changed (bug 1338115).
gURLBar.setAttribute("pageproxystate", aState);
gURLBar.setPageProxyState(aState);
// the page proxy state is set to valid via OnLocationChange, which
// gets called when we switch tabs.
@ -3431,7 +3376,6 @@ var BrowserOnClick = {
init() {
let mm = window.messageManager;
mm.addMessageListener("Browser:CertExceptionError", this);
mm.addMessageListener("Browser:SiteBlockedError", this);
mm.addMessageListener("Browser:EnableOnlineMode", this);
mm.addMessageListener("Browser:ResetSSLPreferences", this);
mm.addMessageListener("Browser:SSLErrorReportTelemetry", this);
@ -3443,7 +3387,6 @@ var BrowserOnClick = {
uninit() {
let mm = window.messageManager;
mm.removeMessageListener("Browser:CertExceptionError", this);
mm.removeMessageListener("Browser:SiteBlockedError", this);
mm.removeMessageListener("Browser:EnableOnlineMode", this);
mm.removeMessageListener("Browser:ResetSSLPreferences", this);
mm.removeMessageListener("Browser:SSLErrorReportTelemetry", this);
@ -3464,15 +3407,6 @@ var BrowserOnClick = {
msg.data.frameId
);
break;
case "Browser:SiteBlockedError":
this.onAboutBlocked(
msg.data.elementId,
msg.data.reason,
msg.data.isTopFrame,
msg.data.location,
msg.data.blockedInfo
);
break;
case "Browser:EnableOnlineMode":
if (Services.io.offline) {
// Reset network state and refresh the page.
@ -3606,7 +3540,7 @@ var BrowserOnClick = {
cert = securityInfo.serverCert;
Services.ww.openWindow(
window,
"chrome://pippki/content/certViewer.xul",
"chrome://pippki/content/certViewer.xhtml",
"_blank",
"centerscreen,chrome",
cert
@ -3682,48 +3616,6 @@ var BrowserOnClick = {
}
},
onAboutBlocked(elementId, reason, isTopFrame, location, blockedInfo) {
// Depending on what page we are displaying here (malware/phishing/unwanted)
// use the right strings and links for each.
let bucketName = "";
let sendTelemetry = false;
if (reason === "malware") {
sendTelemetry = true;
bucketName = "WARNING_MALWARE_PAGE_";
} else if (reason === "phishing") {
sendTelemetry = true;
bucketName = "WARNING_PHISHING_PAGE_";
} else if (reason === "unwanted") {
sendTelemetry = true;
bucketName = "WARNING_UNWANTED_PAGE_";
} else if (reason === "harmful") {
sendTelemetry = true;
bucketName = "WARNING_HARMFUL_PAGE_";
}
let secHistogram = Services.telemetry.getHistogramById(
"URLCLASSIFIER_UI_EVENTS"
);
let nsISecTel = Ci.IUrlClassifierUITelemetry;
bucketName += isTopFrame ? "TOP_" : "FRAME_";
switch (elementId) {
case "goBackButton":
if (sendTelemetry) {
secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
}
getMeOutOfHere();
break;
case "ignore_warning_link":
if (Services.prefs.getBoolPref("browser.safebrowsing.allowOverride")) {
if (sendTelemetry) {
secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]);
}
this.ignoreWarningLink(reason, blockedInfo);
}
break;
}
},
ignoreWarningLink(reason, blockedInfo) {
let triggeringPrincipal = E10SUtils.deserializePrincipal(
blockedInfo.triggeringPrincipal,
@ -4638,14 +4530,13 @@ const BrowserSearch = {
_setURLBarPlaceholder(name) {
let placeholder;
if (name) {
placeholder = gBrowserBundle.formatStringFromName(
"urlbar.placeholder",
[name]
);
placeholder = gBrowserBundle.formatStringFromName("urlbar.placeholder", [
name,
]);
} else {
placeholder = gURLBar.getAttribute("defaultPlaceholder");
}
gURLBar.setAttribute("placeholder", placeholder);
gURLBar.placeholder = placeholder;
},
addEngine(browser, engine, uri) {
@ -4751,10 +4642,7 @@ const BrowserSearch = {
}
let focusUrlBarIfSearchFieldIsNotActive = function(aSearchBar) {
if (
!aSearchBar ||
document.activeElement != aSearchBar.textbox.inputField
) {
if (!aSearchBar || document.activeElement != aSearchBar.textbox) {
// Limit the results to search suggestions, like the search bar.
gURLBar.search(UrlbarTokenizer.RESTRICT.SEARCH);
}
@ -4935,6 +4823,13 @@ const BrowserSearch = {
XPCOMUtils.defineConstant(this, "BrowserSearch", BrowserSearch);
function CreateContainerTabMenu(event) {
createUserContextMenu(event, {
useAccessKeys: false,
showDefaultTab: true,
});
}
function FillHistoryMenu(aParent) {
// Lazily add the hover listeners on first showing and never remove them
if (!aParent.hasStatusListener) {
@ -5456,7 +5351,7 @@ var XULBrowserWindow = {
StatusPanel.update();
},
setOverLink(url, anchorElt) {
setOverLink(url) {
if (url) {
url = Services.textToSubURI.unEscapeURIForUI(url);
@ -5688,7 +5583,7 @@ var XULBrowserWindow = {
var location = aLocationURI ? aLocationURI.spec : "";
this.hideOverLinkImmediately = true;
this.setOverLink("", null);
this.setOverLink("");
this.hideOverLinkImmediately = false;
// We should probably not do this if the value has changed since the user
@ -6081,6 +5976,7 @@ var CombinedStopReload = {
if (event.button == 0 && !this.stop.disabled) {
this._stopClicked = true;
}
break;
case "animationend": {
if (
event.target.classList.contains("toolbarbutton-animatable-image") &&
@ -6364,8 +6260,6 @@ var TabsProgressListener = {
gBrowser.getNotificationBox(aBrowser).removeTransientNotifications();
FullZoom.onLocationChange(aLocationURI, false, aBrowser);
ContentBlocking.onLocationChange();
},
onLinkIconAvailable(browser, dataURI, iconURI) {
@ -7044,6 +6938,7 @@ var gUIDensity = {
}
gBrowser.tabContainer.uiDensityChanged();
gURLBar.updateLayoutBreakout();
},
};
@ -7972,8 +7867,7 @@ var CanvasPermissionPromptHelper = {
let browser;
if (aSubject instanceof Ci.nsIDOMWindow) {
let contentWindow = aSubject.QueryInterface(Ci.nsIDOMWindow);
browser = contentWindow.docShell.chromeEventHandler;
browser = aSubject.docShell.chromeEventHandler;
} else {
browser = aSubject;
}
@ -8419,7 +8313,6 @@ function BrowserOpenAddonsMgr(aView) {
if (aView) {
aSubject.loadView(aView);
}
aSubject.QueryInterface(Ci.nsIDOMWindow);
aSubject.focus();
resolve(aSubject);
}, "EM-loaded");
@ -8567,41 +8460,6 @@ function checkEmptyPageOrigin(
return contentPrincipal.isSystemPrincipal;
}
function ReportFalseDeceptiveSite() {
let docURI = gBrowser.selectedBrowser.documentURI;
let isPhishingPage =
docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
if (isPhishingPage) {
let mm = gBrowser.selectedBrowser.messageManager;
let onMessage = message => {
mm.removeMessageListener("DeceptiveBlockedDetails:Result", onMessage);
let reportUrl = gSafeBrowsing.getReportURL(
"PhishMistake",
message.data.blockedInfo
);
if (reportUrl) {
openTrustedLinkIn(reportUrl, "tab");
} else {
let bundle = Services.strings.createBundle(
"chrome://browser/locale/safebrowsing/safebrowsing.properties"
);
Services.prompt.alert(
window,
bundle.GetStringFromName("errorReportFalseDeceptiveTitle"),
bundle.formatStringFromName(
"errorReportFalseDeceptiveMessage",
[message.data.blockedInfo.provider]
)
);
}
};
mm.addMessageListener("DeceptiveBlockedDetails:Result", onMessage);
mm.sendAsyncMessage("DeceptiveBlockedDetails");
}
}
/**
* Format a URL
* eg:
@ -8616,6 +8474,7 @@ function formatURL(aFormat, aIsPref) {
: Services.urlFormatter.formatURL(aFormat);
}
#ifdef ENABLE_MARIONETTE
/**
* Fired on the "marionette-remote-control" system notification,
* indicating if the browser session is under remote control.
@ -8634,6 +8493,7 @@ const gRemoteControl = {
}
},
};
#endif
const gAccessibilityServiceIndicator = {
init() {
@ -8723,10 +8583,6 @@ var gPrivateBrowsingUI = {
// Adjust the window's title
let docElement = document.documentElement;
if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
docElement.setAttribute(
"title",
docElement.getAttribute("title_privatebrowsing")
);
docElement.setAttribute(
"titlemodifier",
docElement.getAttribute("titlemodifier_privatebrowsing")
@ -9279,12 +9135,7 @@ var PanicButtonNotifier = {
popup.addEventListener("popuphidden", removeListeners);
let widget = CustomizableUI.getWidget("panic-button").forWindow(window);
let anchor = widget.anchor;
anchor = document.getAnonymousElementByAttribute(
anchor,
"class",
"toolbarbutton-icon"
);
let anchor = widget.anchor.icon;
popup.openPopup(anchor, popup.getAttribute("position"));
} catch (ex) {
Cu.reportError(ex);
@ -9440,7 +9291,6 @@ TabModalPromptBox.prototype = {
let prompt = prompts[prompts.length - 1];
prompt.element.hidden = false;
// Because we were hidden before, this won't have been possible, so do it now:
prompt.ensureXBLBindingAttached();
prompt.Dialog.setDefaultFocus();
} else {
browser.removeAttribute("tabmodalPromptShowing");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@ this.ContentSearchUIController = (function() {
*
* @param inputElement
* Search suggestions will be based on the text in this text box.
* Assumed to be an html:input. xul:textbox is untested but might work.
* Assumed to be an html:input.
* @param tableParent
* The suggestion table is appended as a child to this element. Since
* the table is absolutely positioned and its top and left values are set

View File

@ -2,8 +2,8 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# JS files which are needed by browser.xul but no other top level windows to
# support MacOS specific features should be loaded directly from browser.xul
# JS files which are needed by browser.xhtml but no other top level windows to
# support MacOS specific features should be loaded directly from browser.xhtml
# rather than this file.
# If you update this list, you may need to add a mapping within the following
@ -18,8 +18,8 @@ Services.scriptloader.loadSubScript("chrome://browser/content/browser-places.js"
Services.scriptloader.loadSubScript("chrome://global/content/globalOverlay.js", this);
Services.scriptloader.loadSubScript("chrome://global/content/editMenuOverlay.js", this);
Services.scriptloader.loadSubScript("chrome://browser/content/utilityOverlay.js", this);
#ifdef XP_MACOSX
Services.scriptloader.loadSubScript("chrome://global/content/macWindowMenu.js", this);
#endif
if (AppConstants.platform == "macosx") {
Services.scriptloader.loadSubScript("chrome://global/content/macWindowMenu.js", this);
}
</script>

View File

@ -11,10 +11,11 @@
]>
<window id="main-window"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
data-l10n-sync="true">
#include macWindow.inc.xul
#include macWindow.inc.xhtml
<!-- Dock menu -->
<popupset>

View File

@ -4,22 +4,29 @@
# This include file should only contain things that are needed to support MacOS
# specific features that are needed for all top level windows. If the feature is
# also needed in browser.xul, it should go in one of the various include files
# below that are shared with browser.xul. When including this file,
# also needed in browser.xhtml, it should go in one of the various include files
# below that are shared with browser.xhtml. When including this file,
# browser-doctype.inc must also be included.
# All JS files which are needed by browser.xul and other top level windows to
<linkset>
<html:link rel="localization" href="branding/brand.ftl"/>
<html:link rel="localization" href="browser/branding/sync-brand.ftl"/>
<html:link rel="localization" href="toolkit/global/textActions.ftl"/>
<html:link rel="localization" href="browser/menubar.ftl"/>
</linkset>
# All JS files which are needed by browser.xhtml and other top level windows to
# support MacOS specific features *must* go into the global-scripts.inc file so
# that they can be shared with browser.xul.
# that they can be shared with browser.xhtml.
#include global-scripts.inc
<script src="chrome://browser/content/nonbrowser-mac.js"></script>
# All sets except for popupsets (commands, keys, and stringbundles)
# *must* go into the browser-sets.inc file so that they can be shared with
# browser.xul
# browser.xhtml
#include browser-sets.inc
# The entire main menubar is placed into browser-menubar.inc, so that it can be
# shared with browser.xul.
# shared with browser.xhtml.
#include browser-menubar.inc

View File

@ -95,9 +95,6 @@ with Files("test/tabs/**"):
with Files("test/touch/**"):
BUG_COMPONENT = ("Firefox", "General")
with Files("test/trackingUI/**"):
BUG_COMPONENT = ("Firefox", "Protections UI")
with Files("test/webextensions/**"):
BUG_COMPONENT = ("WebExtensions", "Untriaged")
@ -110,9 +107,6 @@ with Files("aboutNetError.xhtml"):
with Files("test/caps/**"):
BUG_COMPONENT = ("Firefox", "Security")
with Files("blockedSite.xhtml"):
BUG_COMPONENT = ("Toolkit", "Safe Browsing")
with Files("browser-addons.js"):
BUG_COMPONENT = ("Toolkit", "Add-ons Manager")
@ -140,19 +134,16 @@ with Files("browser-places.js"):
with Files("browser-plugins.js"):
BUG_COMPONENT = ("Core", "Plug-ins")
with Files("browser-safebrowsing.js"):
BUG_COMPONENT = ("Toolkit", "Safe Browsing")
with Files("browser-sync.js"):
BUG_COMPONENT = ("Firefox", "Sync")
with Files("contentSearch*"):
BUG_COMPONENT = ("Firefox", "Search")
with Files("hiddenWindow.xul"):
with Files("hiddenWindowMac.xhtml"):
BUG_COMPONENT = ("Firefox", "Site Permissions")
with Files("macWindow.inc.xul"):
with Files("macWindow.inc.xhtml"):
BUG_COMPONENT = ("Firefox", "Shell Integration")
with Files("tabbrowser*"):

View File

@ -6,7 +6,7 @@
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="connect-src https:; default-src chrome:">
<meta http-equiv="Content-Security-Policy" content="connect-src https:; default-src chrome:; object-src 'none'">
<meta name="referrer" content="no-referrer">
<link rel="stylesheet" type="text/css" href="chrome://global/skin/in-content/common.css">
<link rel="stylesheet" type="text/css" href="chrome://browser/skin/newInstallPage.css">

View File

@ -65,7 +65,9 @@ function nonBrowserWindowStartup() {
// If no windows are active (i.e. we're the hidden window), disable the close, minimize
// and zoom menu commands as well
if (window.location.href == "chrome://browser/content/hiddenWindow.xul") {
if (
window.location.href == "chrome://browser/content/hiddenWindowMac.xhtml"
) {
var hiddenWindowDisabledItems = [
"cmd_close",
"minimizeWindow",
@ -123,7 +125,9 @@ function nonBrowserWindowDelayedStartup() {
function nonBrowserWindowShutdown() {
// If this is the hidden window being closed, release our reference to
// the dock menu element to prevent leaks on shutdown
if (window.location.href == "chrome://browser/content/hiddenWindow.xul") {
if (
window.location.href == "chrome://browser/content/hiddenWindowMac.xhtml"
) {
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"].getService(
Ci.nsIMacDockSupport
);

View File

@ -2,16 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
XPCOMUtils.defineLazyModuleGetters(this, {
LoginHelper: "resource://gre/modules/LoginHelper.jsm",
LoginManagerContextMenu: "resource://gre/modules/LoginManagerContextMenu.jsm",
DevToolsShim: "chrome://devtools-startup/content/DevToolsShim.jsm",
});
var gContextMenuContentData = null;
function setContextMenuContentData(data) {
gContextMenuContentData = data;
nsContextMenu.contentData = data;
}
function openContextMenu(aMessage) {
@ -41,10 +33,9 @@ function openContextMenu(aMessage) {
}
}
gContextMenuContentData = {
nsContextMenu.contentData = {
context: data.context,
isRemote: data.isRemote,
popupNodeSelectors: data.popupNodeSelectors,
browser,
editFlags: data.editFlags,
spellInfo,
@ -68,7 +59,7 @@ function openContextMenu(aMessage) {
};
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
let context = gContextMenuContentData.context;
let context = nsContextMenu.contentData.context;
// We don't have access to the original event here, as that happened in
// another process. Therefore we synthesize a new MouseEvent to propagate the
@ -96,14 +87,8 @@ function openContextMenu(aMessage) {
popup.openPopupAtScreen(newEvent.screenX, newEvent.screenY, true, newEvent);
}
function nsContextMenu(aXulMenu, aIsShift) {
this.shouldDisplay = true;
this.initMenu(aXulMenu, aIsShift);
}
// Prototype for nsContextMenu "class."
nsContextMenu.prototype = {
initMenu: function CM_initMenu(aXulMenu, aIsShift) {
class nsContextMenu {
constructor(aXulMenu, aIsShift) {
// Get contextual info.
this.setContext();
@ -116,7 +101,7 @@ nsContextMenu.prototype = {
if (!aIsShift) {
if (this.isRemote) {
this.hasPageMenu = PageMenuParent.addToPopup(
gContextMenuContentData.customMenuItems,
this.contentData.customMenuItems,
this.browser,
aXulMenu
);
@ -149,9 +134,7 @@ nsContextMenu.prototype = {
onSpellcheckable: this.onSpellcheckable,
onPassword: this.onPassword,
srcUrl: this.mediaURL,
frameUrl: gContextMenuContentData
? gContextMenuContentData.docLocation
: undefined,
frameUrl: this.contentData ? this.contentData.docLocation : undefined,
pageUrl: this.browser ? this.browser.currentURI.spec : undefined,
linkText: this.linkTextStr,
linkUrl: this.linkURL,
@ -160,8 +143,8 @@ nsContextMenu.prototype = {
: undefined,
frameId: this.frameOuterWindowID,
webExtBrowserType: this.webExtBrowserType,
webExtContextData: gContextMenuContentData
? gContextMenuContentData.webExtContextData
webExtContextData: this.contentData
? this.contentData.webExtContextData
: undefined,
};
subject.wrappedJSObject = subject;
@ -191,16 +174,17 @@ nsContextMenu.prototype = {
// Initialize (disable/remove) menu items.
this.initItems();
},
}
setContext() {
let context = Object.create(null);
this.isRemote = false;
if (gContextMenuContentData) {
context = gContextMenuContentData.context;
gContextMenuContentData.context = null;
this.isRemote = gContextMenuContentData.isRemote;
if (nsContextMenu.contentData) {
this.contentData = nsContextMenu.contentData;
context = this.contentData.context;
nsContextMenu.contentData = null;
this.isRemote = this.contentData.isRemote;
}
this.shouldDisplay = context.shouldDisplay;
@ -265,15 +249,9 @@ nsContextMenu.prototype = {
this.csp = E10SUtils.deserializeCSP(context.csp);
// Remember the CSS selectors corresponding to clicked node. gContextMenuContentData
// can be null if the menu was triggered by tests in which case use an empty array.
this.targetSelectors = gContextMenuContentData
? gContextMenuContentData.popupNodeSelectors
: [];
if (this.isRemote) {
this.browser = gContextMenuContentData.browser;
this.selectionInfo = gContextMenuContentData.selectionInfo;
this.browser = this.contentData.browser;
this.selectionInfo = this.contentData.selectionInfo;
} else {
this.browser = this.ownerDoc.defaultView.docShell.chromeEventHandler;
this.selectionInfo = BrowserUtils.getSelectionDetails(window);
@ -294,7 +272,7 @@ nsContextMenu.prototype = {
if (context.shouldInitInlineSpellCheckerUINoChildren) {
if (this.isRemote) {
InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo);
InlineSpellCheckerUI.initFromRemote(this.contentData.spellInfo);
} else {
InlineSpellCheckerUI.init(this.target.editor);
InlineSpellCheckerUI.initFromEvent(
@ -306,7 +284,7 @@ nsContextMenu.prototype = {
if (context.shouldInitInlineSpellCheckerUIWithChildren) {
if (this.isRemote) {
InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo);
InlineSpellCheckerUI.initFromRemote(this.contentData.spellInfo);
} else {
var targetWin = this.ownerDoc.defaultView;
var { editingSession } = targetWin.docShell;
@ -322,30 +300,30 @@ nsContextMenu.prototype = {
this.showItem("spell-check-enabled", canSpell);
this.showItem("spell-separator", canSpell);
}
}, // setContext
} // setContext
hiding: function CM_hiding() {
hiding() {
if (this.browser && this.browser.messageManager) {
this.browser.messageManager.sendAsyncMessage("ContextMenu:Hiding");
}
gContextMenuContentData = null;
this.contentData = null;
InlineSpellCheckerUI.clearSuggestionsFromMenu();
InlineSpellCheckerUI.clearDictionaryListFromMenu();
InlineSpellCheckerUI.uninit();
if (
Cu.isModuleLoaded("resource://gre/modules/LoginManagerContextMenu.jsm")
) {
LoginManagerContextMenu.clearLoginsFromMenu(document);
nsContextMenu.LoginManagerContextMenu.clearLoginsFromMenu(document);
}
// This handler self-deletes, only run it if it is still there:
if (this._onPopupHiding) {
this._onPopupHiding();
}
},
}
initItems: function CM_initItems() {
initItems() {
this.initPageMenuSeparator();
this.initOpenItems();
this.initNavigationItems();
@ -359,13 +337,13 @@ nsContextMenu.prototype = {
this.initClickToPlayItems();
this.initPasswordManagerItems();
this.initSyncItems();
},
}
initPageMenuSeparator: function CM_initPageMenuSeparator() {
initPageMenuSeparator() {
this.showItem("page-menu-separator", this.hasPageMenu);
},
}
initOpenItems: function CM_initOpenItems() {
initOpenItems() {
var isMailtoInternal = false;
if (this.onMailtoLink) {
var mailtoHandler = Cc[
@ -396,17 +374,14 @@ nsContextMenu.prototype = {
}
var inContainer = false;
if (gContextMenuContentData.userContextId) {
if (this.contentData.userContextId) {
inContainer = true;
var item = document.getElementById("context-openlinkincontainertab");
item.setAttribute(
"data-usercontextid",
gContextMenuContentData.userContextId
);
item.setAttribute("data-usercontextid", this.contentData.userContextId);
var label = ContextualIdentityService.getUserContextLabel(
gContextMenuContentData.userContextId
this.contentData.userContextId
);
item.setAttribute(
"label",
@ -436,9 +411,9 @@ nsContextMenu.prototype = {
);
this.showItem("context-openlinkincurrent", this.onPlainTextLink);
this.showItem("context-sep-open", shouldShow);
},
}
initNavigationItems: function CM_initNavigationItems() {
initNavigationItems() {
var shouldShow =
!(
this.isContentSelected ||
@ -462,9 +437,9 @@ nsContextMenu.prototype = {
this.showItem("context-reload", stopReloadItem == "reload");
this.showItem("context-stop", stopReloadItem == "stop");
},
}
initLeaveDOMFullScreenItems: function CM_initLeaveFullScreenItem() {
initLeaveDOMFullScreenItems() {
// only show the option if the user is in DOM fullscreen
var shouldShow = this.target.ownerDocument.fullscreen;
this.showItem("context-leave-dom-fullscreen", shouldShow);
@ -473,9 +448,9 @@ nsContextMenu.prototype = {
if (shouldShow) {
this.showItem("context-media-sep-commands", true);
}
},
}
initSaveItems: function CM_initSaveItems() {
initSaveItems() {
var shouldShow = !(
this.onTextInput ||
this.onLink ||
@ -515,9 +490,9 @@ nsContextMenu.prototype = {
"disabled",
!this.mediaURL || mediaIsBlob
);
},
}
initViewItems: function CM_initViewItems() {
initViewItems() {
// View source is always OK, unless in directory listing.
this.showItem(
"context-viewpartialsource-selection",
@ -586,8 +561,9 @@ nsContextMenu.prototype = {
);
if (haveSetDesktopBackground && this.onLoadedImage) {
document.getElementById("context-setDesktopBackground").disabled =
gContextMenuContentData.disableSetDesktopBackground;
document.getElementById(
"context-setDesktopBackground"
).disabled = this.contentData.disableSetDesktopBackground;
}
// Reload image depends on an image that's not fully loaded
@ -634,9 +610,9 @@ nsContextMenu.prototype = {
"context-viewimagedesc",
this.onImage && this.imageDescURL !== ""
);
},
}
initMiscItems: function CM_initMiscItems() {
initMiscItems() {
// Use "Bookmark This Link" if on a link.
let bookmarkPage = document.getElementById("context-bookmarkpage");
this.showItem(
@ -707,7 +683,7 @@ nsContextMenu.prototype = {
"context-bidi-page-direction-toggle",
!this.onTextInput && top.gBidiUI
);
},
}
initSpellingItems() {
var canSpell =
@ -762,7 +738,7 @@ nsContextMenu.prototype = {
} else {
this.showItem("spell-add-dictionaries-main", false);
}
},
}
initClipboardItems() {
// Copy depends on whether there is selected text.
@ -823,7 +799,7 @@ nsContextMenu.prototype = {
"context-sep-copyimage",
this.onImage || this.onVideo || this.onAudio
);
},
}
initMediaPlayerItems() {
var onMedia = this.onVideo || this.onAudio;
@ -932,18 +908,17 @@ nsContextMenu.prototype = {
}
}
this.showItem("context-media-sep-commands", onMedia);
},
}
initClickToPlayItems() {
this.showItem("context-ctp-play", this.onCTPPlugin);
this.showItem("context-ctp-hide", this.onCTPPlugin);
this.showItem("context-sep-ctp", this.onCTPPlugin);
},
}
initPasswordManagerItems() {
let loginFillInfo =
gContextMenuContentData && gContextMenuContentData.loginFillInfo;
let documentURI = gContextMenuContentData.documentURIObject;
let loginFillInfo = this.contentData && this.contentData.loginFillInfo;
let documentURI = this.contentData.documentURIObject;
// If we could not find a password field we
// don't want to show the form fill option.
@ -987,7 +962,7 @@ nsContextMenu.prototype = {
}
let formOrigin = LoginHelper.getLoginOrigin(documentURI.spec);
let fragment = LoginManagerContextMenu.addLoginsToMenu(
let fragment = nsContextMenu.LoginManagerContextMenu.addLoginsToMenu(
this.targetIdentifier,
this.browser,
formOrigin
@ -1015,40 +990,48 @@ nsContextMenu.prototype = {
let popup = document.getElementById("fill-login-popup");
let insertBeforeElement = document.getElementById("fill-login-no-logins");
popup.insertBefore(fragment, insertBeforeElement);
},
}
initSyncItems() {
gSync.updateContentContextMenu(this);
},
}
openPasswordManager() {
LoginHelper.openPasswordManager(window, {
filterString: gContextMenuContentData.documentURIObject.host,
filterString: this.contentData.documentURIObject.host,
entryPoint: "contextmenu",
});
},
}
fillGeneratedPassword() {
LoginManagerContextMenu.fillGeneratedPassword(this.targetIdentifier,
gContextMenuContentData.documentURIObject,
this.browser);
},
nsContextMenu.LoginManagerContextMenu.fillGeneratedPassword(
this.targetIdentifier,
this.contentData.documentURIObject,
this.browser
);
}
inspectNode() {
return DevToolsShim.inspectNode(gBrowser.selectedTab, this.targetSelectors);
},
return nsContextMenu.DevToolsShim.inspectNode(
gBrowser.selectedTab,
this.targetIdentifier
);
}
inspectA11Y() {
return DevToolsShim.inspectA11Y(gBrowser.selectedTab, this.targetSelectors);
},
return nsContextMenu.DevToolsShim.inspectA11Y(
gBrowser.selectedTab,
this.targetIdentifier
);
}
_openLinkInParameters(extra) {
let params = {
charset: gContextMenuContentData.charSet,
charset: this.contentData.charSet,
originPrincipal: this.principal,
triggeringPrincipal: this.principal,
csp: this.csp,
frameOuterWindowID: gContextMenuContentData.frameOuterWindowID,
frameOuterWindowID: this.contentData.frameOuterWindowID,
};
for (let p in extra) {
params[p] = extra[p];
@ -1061,13 +1044,13 @@ nsContextMenu.prototype = {
}
let referrerInfo = this.onLink
? gContextMenuContentData.linkReferrerInfo
: gContextMenuContentData.referrerInfo;
? this.contentData.linkReferrerInfo
: this.contentData.referrerInfo;
// If we want to change userContextId, we must be sure that we don't
// propagate the referrer.
if (
("userContextId" in params &&
params.userContextId != gContextMenuContentData.userContextId) ||
params.userContextId != this.contentData.userContextId) ||
this.onPlainTextLink
) {
referrerInfo = new ReferrerInfo(
@ -1079,12 +1062,12 @@ nsContextMenu.prototype = {
params.referrerInfo = referrerInfo;
return params;
},
}
// Open linked-to URL in a new window.
openLink() {
openLinkIn(this.linkURL, "window", this._openLinkInParameters());
},
}
// Open linked-to URL in a new private window.
openLinkInPrivateWindow() {
@ -1093,18 +1076,18 @@ nsContextMenu.prototype = {
"window",
this._openLinkInParameters({ private: true })
);
},
}
// Open linked-to URL in a new tab.
openLinkInTab(event) {
let referrerURI = gContextMenuContentData.documentURIObject;
let referrerURI = this.contentData.documentURIObject;
// if its parent allows mixed content and the referring URI passes
// a same origin check with the target URI, we can preserve the users
// decision of disabling MCB on a page for it's child tabs.
let persistAllowMixedContentInChildTab = false;
if (gContextMenuContentData.parentAllowsMixedContent) {
if (this.contentData.parentAllowsMixedContent) {
const sm = Services.scriptSecurityManager;
try {
let targetURI = this.linkURI;
@ -1121,22 +1104,22 @@ nsContextMenu.prototype = {
};
openLinkIn(this.linkURL, "tab", this._openLinkInParameters(params));
},
}
// open URL in current tab
openLinkInCurrent() {
openLinkIn(this.linkURL, "current", this._openLinkInParameters());
},
}
// Open frame in a new tab.
openFrameInTab() {
openLinkIn(gContextMenuContentData.docLocation, "tab", {
charset: gContextMenuContentData.charSet,
openLinkIn(this.contentData.docLocation, "tab", {
charset: this.contentData.charSet,
triggeringPrincipal: this.browser.contentPrincipal,
csp: this.browser.csp,
referrerInfo: gContextMenuContentData.frameReferrerInfo,
referrerInfo: this.contentData.frameReferrerInfo,
});
},
}
// Reload clicked-in frame.
reloadFrame(aEvent) {
@ -1146,30 +1129,30 @@ nsContextMenu.prototype = {
null,
{ target: this.target, forceReload }
);
},
}
// Open clicked-in frame in its own window.
openFrame() {
openLinkIn(gContextMenuContentData.docLocation, "window", {
charset: gContextMenuContentData.charSet,
openLinkIn(this.contentData.docLocation, "window", {
charset: this.contentData.charSet,
triggeringPrincipal: this.browser.contentPrincipal,
csp: this.browser.csp,
referrerInfo: gContextMenuContentData.frameReferrerInfo,
referrerInfo: this.contentData.frameReferrerInfo,
});
},
}
// Open clicked-in frame in the same window.
showOnlyThisFrame() {
urlSecurityCheck(
gContextMenuContentData.docLocation,
this.contentData.docLocation,
this.browser.contentPrincipal,
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT
);
openWebLinkIn(gContextMenuContentData.docLocation, "current", {
referrerInfo: gContextMenuContentData.frameReferrerInfo,
openWebLinkIn(this.contentData.docLocation, "current", {
referrerInfo: this.contentData.frameReferrerInfo,
triggeringPrincipal: this.browser.contentPrincipal,
});
},
}
// View Partial Source
viewPartialSource() {
@ -1202,36 +1185,36 @@ nsContextMenu.prototype = {
};
top.gViewSourceUtils.viewPartialSourceInBrowser(browser, openSelectionFn);
},
}
// Open new "view source" window with the frame's URL.
viewFrameSource() {
BrowserViewSourceOfDocument({
browser: this.browser,
URL: gContextMenuContentData.docLocation,
URL: this.contentData.docLocation,
outerWindowID: this.frameOuterWindowID,
});
},
}
viewInfo() {
BrowserPageInfo(
gContextMenuContentData.docLocation,
this.contentData.docLocation,
null,
null,
null,
this.browser
);
},
}
viewImageInfo() {
BrowserPageInfo(
gContextMenuContentData.docLocation,
this.contentData.docLocation,
"mediaTab",
this.imageInfo,
null,
this.browser
);
},
}
viewImageDesc(e) {
urlSecurityCheck(
@ -1240,21 +1223,21 @@ nsContextMenu.prototype = {
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT
);
openUILink(this.imageDescURL, e, {
referrerInfo: gContextMenuContentData.referrerInfo,
referrerInfo: this.contentData.referrerInfo,
triggeringPrincipal: this.principal,
csp: this.csp,
});
},
}
viewFrameInfo() {
BrowserPageInfo(
gContextMenuContentData.docLocation,
this.contentData.docLocation,
null,
null,
this.frameOuterWindowID,
this.browser
);
},
}
reloadImage() {
urlSecurityCheck(
@ -1268,7 +1251,7 @@ nsContextMenu.prototype = {
null,
{ target: this.target }
);
},
}
_canvasToBlobURL(target) {
let mm = this.browser.messageManager;
@ -1284,11 +1267,11 @@ nsContextMenu.prototype = {
};
mm.addMessageListener("ContextMenu:Canvas:ToBlobURL:Result", onMessage);
});
},
}
// Change current window to the URL of the image, video, or audio.
viewMedia(e) {
let referrerInfo = gContextMenuContentData.referrerInfo;
let referrerInfo = this.contentData.referrerInfo;
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
if (this.onCanvas) {
this._canvasToBlobURL(this.target).then(function(blobURL) {
@ -1310,7 +1293,7 @@ nsContextMenu.prototype = {
csp: this.csp,
});
}
},
}
saveVideoFrameAsImage() {
let mm = this.browser.messageManager;
@ -1339,7 +1322,7 @@ nsContextMenu.prototype = {
);
// Cache this because we fetch the data async
let referrerInfo = gContextMenuContentData.referrerInfo;
let referrerInfo = this.contentData.referrerInfo;
let onMessage = message => {
mm.removeMessageListener(
@ -1369,11 +1352,11 @@ nsContextMenu.prototype = {
"ContextMenu:SaveVideoFrameAsImage:Result",
onMessage
);
},
}
leaveDOMFullScreen() {
document.exitFullscreen();
},
}
// Change current window to the URL of the background image.
viewBGImage(e) {
@ -1384,11 +1367,11 @@ nsContextMenu.prototype = {
);
openUILink(this.bgImageURL, e, {
referrerInfo: gContextMenuContentData.referrerInfo,
referrerInfo: this.contentData.referrerInfo,
triggeringPrincipal: this.principal,
csp: this.csp,
});
},
}
setDesktopBackground() {
let mm = this.browser.messageManager;
@ -1419,7 +1402,7 @@ nsContextMenu.prototype = {
// Confirm since it's annoying if you hit this accidentally.
const kDesktopBackgroundURL =
"chrome://browser/content/setDesktopBackground.xul";
"chrome://browser/content/setDesktopBackground.xhtml";
if (AppConstants.platform == "macosx") {
// On Mac, the Set Desktop Background window is not modal.
@ -1455,12 +1438,12 @@ nsContextMenu.prototype = {
"ContextMenu:SetAsDesktopBackground:Result",
onMessage
);
},
}
// Save URL of clicked-on frame.
saveFrame() {
saveBrowser(this.browser, false, this.frameOuterWindowID);
},
}
// Helper function to wait for appropriate MIME-type headers and
// then prompt the user with a file picker
@ -1639,13 +1622,13 @@ nsContextMenu.prototype = {
// kick off the channel with our proxy object as the listener
channel.asyncOpen(new saveAsListener(this.principal));
},
}
// Save URL of clicked-on link.
saveLink() {
let referrerInfo = this.onLink
? gContextMenuContentData.linkReferrerInfo
: gContextMenuContentData.referrerInfo;
? this.contentData.linkReferrerInfo
: this.contentData.referrerInfo;
let isContentWindowPrivate = this.isRemote
? this.ownerDoc.isPrivate
@ -1661,14 +1644,14 @@ nsContextMenu.prototype = {
this.linkDownload,
isContentWindowPrivate
);
},
}
// Backwards-compatibility wrapper
saveImage() {
if (this.onCanvas || this.onImage) {
this.saveMedia();
}
},
}
// Save URL of the clicked upon image, video, or audio.
saveMedia() {
@ -1676,7 +1659,7 @@ nsContextMenu.prototype = {
let isContentWindowPrivate = this.isRemote
? this.ownerDoc.isPrivate
: undefined;
let referrerInfo = gContextMenuContentData.referrerInfo;
let referrerInfo = this.contentData.referrerInfo;
let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser);
if (this.onCanvas) {
// Bypass cache, since it's a data: URL.
@ -1704,8 +1687,8 @@ nsContextMenu.prototype = {
this.mediaURL,
null, // document
null, // file name; we'll take it from the URL
gContextMenuContentData.contentDisposition,
gContextMenuContentData.contentType,
this.contentData.contentDisposition,
this.contentData.contentType,
false, // do not bypass the cache
"SaveImageTitle",
null, // chosen data
@ -1730,26 +1713,26 @@ nsContextMenu.prototype = {
isContentWindowPrivate
);
}
},
}
// Backwards-compatibility wrapper
sendImage() {
if (this.onCanvas || this.onImage) {
this.sendMedia();
}
},
}
sendMedia() {
MailIntegration.sendMessage(this.mediaURL, "");
},
}
playPlugin() {
gPluginHandler.contextMenuCommand(this.browser, this.target, "play");
},
}
hidePlugin() {
gPluginHandler.contextMenuCommand(this.browser, this.target, "hide");
},
}
// Generate email address and put it on clipboard.
copyEmail() {
@ -1775,7 +1758,7 @@ nsContextMenu.prototype = {
Ci.nsIClipboardHelper
);
clipboard.copyString(addresses);
},
}
copyLink() {
// If we're in a view source tab, remove the view-source: prefix
@ -1784,7 +1767,7 @@ nsContextMenu.prototype = {
Ci.nsIClipboardHelper
);
clipboard.copyString(linkURL);
},
}
/**
* Utilities
@ -1806,7 +1789,7 @@ nsContextMenu.prototype = {
if (item) {
item.hidden = !aShow;
}
},
}
// Set given attribute of specified context-menu item. If the
// value is null, then it removes the attribute (which works
@ -1822,7 +1805,7 @@ nsContextMenu.prototype = {
elem.setAttribute(aAttr, aVal);
}
}
},
}
// Temporary workaround for DOM api not yet implemented by XUL nodes.
cloneNode(aItem) {
@ -1838,7 +1821,7 @@ nsContextMenu.prototype = {
// Voila!
return node;
},
}
getLinkURI() {
try {
@ -1848,12 +1831,12 @@ nsContextMenu.prototype = {
}
return null;
},
}
// Kept for addon compat
linkText() {
return this.linkTextStr;
},
}
// Determines whether or not the separator with the specified ID should be
// shown or not by determining if there are any non-hidden items between it
@ -1870,7 +1853,7 @@ nsContextMenu.prototype = {
}
}
return false;
},
}
addDictionaries() {
var uri = formatURL("browser.dictionaries.download.url", true);
@ -1896,21 +1879,21 @@ nsContextMenu.prototype = {
var where = newWindowPref == 3 ? "tab" : "window";
openTrustedLinkIn(uri, where);
},
}
bookmarkThisPage: function CM_bookmarkThisPage() {
bookmarkThisPage() {
window.top.PlacesCommandHook.bookmarkPage().catch(Cu.reportError);
},
}
bookmarkLink: function CM_bookmarkLink() {
bookmarkLink() {
window.top.PlacesCommandHook.bookmarkLink(
this.linkURL,
this.linkTextStr
).catch(Cu.reportError);
},
}
addBookmarkForFrame: function CM_addBookmarkForFrame() {
let uri = gContextMenuContentData.documentURIObject;
addBookmarkForFrame() {
let uri = this.contentData.documentURIObject;
let mm = this.browser.messageManager;
let onMessage = message => {
@ -1926,21 +1909,21 @@ nsContextMenu.prototype = {
mm.sendAsyncMessage("ContextMenu:BookmarkFrame", null, {
target: this.target,
});
},
}
savePageAs: function CM_savePageAs() {
savePageAs() {
saveBrowser(this.browser);
},
}
printFrame: function CM_printFrame() {
printFrame() {
PrintUtils.printWindow(this.frameOuterWindowID, this.browser);
},
}
switchPageDirection: function CM_switchPageDirection() {
switchPageDirection() {
this.browser.messageManager.sendAsyncMessage("SwitchDocumentDirection");
},
}
mediaCommand: function CM_mediaCommand(command, data) {
mediaCommand(command, data) {
let mm = this.browser.messageManager;
let win = this.browser.ownerGlobal;
let windowUtils = win.windowUtils;
@ -1949,14 +1932,14 @@ nsContextMenu.prototype = {
{ command, data, handlingUserInput: windowUtils.isHandlingUserInput },
{ element: this.target }
);
},
}
copyMediaLocation() {
var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
Ci.nsIClipboardHelper
);
clipboard.copyString(this.mediaURL);
},
}
drmLearnMore(aEvent) {
let drmInfoURL =
@ -1969,14 +1952,14 @@ nsContextMenu.prototype = {
dest = "tab";
}
openTrustedLinkIn(drmInfoURL, dest);
},
}
get imageURL() {
if (this.onImage) {
return this.mediaURL;
}
return "";
},
}
// Formats the 'Search <engine> for "<selection or link text>"' context menu.
formatSearchContextItem() {
@ -2012,13 +1995,18 @@ nsContextMenu.prototype = {
menuItem.accessKey = gNavigatorBundle.getString(
"contextMenuSearch.accesskey"
);
},
}
createContainerMenu(aEvent) {
let createMenuOptions = {
isContextMenu: true,
excludeUserContextId: gContextMenuContentData.userContextId,
excludeUserContextId: this.contentData.userContextId,
};
return createUserContextMenu(aEvent, createMenuOptions);
},
};
}
}
XPCOMUtils.defineLazyModuleGetters(nsContextMenu, {
LoginManagerContextMenu: "resource://gre/modules/LoginManagerContextMenu.jsm",
DevToolsShim: "chrome://devtools-startup/content/DevToolsShim.jsm",
});

View File

@ -29,7 +29,7 @@
<html:link rel="localization" href="browser/pageInfo.ftl"/>
</linkset>
#ifdef XP_MACOSX
#include ../macWindow.inc.xul
#include ../macWindow.inc.xhtml
#else
<script src="chrome://global/content/globalOverlay.js"/>
<script src="chrome://global/content/editMenuOverlay.js"/>
@ -266,7 +266,7 @@
id="selectallbutton"
oncommand="doSelectAllMedia();"/>
<button data-l10n-id="media-save-as"
icon="save" id="imagesaveasbutton"
id="imagesaveasbutton"
oncommand="saveMedia();"/>
</hbox>
<vbox id="imagecontainerbox" flex="1" pack="center">
@ -281,7 +281,7 @@
<hbox id="mediaSaveBox" collapsed="true">
<spacer id="mediaSaveBoxSpacer" flex="1"/>
<button data-l10n-id="media-save-image-as"
icon="save" id="mediasaveasbutton"
id="mediasaveasbutton"
oncommand="saveMedia();"/>
</hbox>
<hbox pack="end">
@ -341,6 +341,7 @@
<input id="security-identity-verifier-value" readonly="readonly"
data-l10n-attrs="value"/>
<xul:button id="security-view-cert" data-l10n-id="security-view"
collapsed="true"
oncommand="security.viewCert();"/>
</div>
</td>

View File

@ -23,26 +23,29 @@ ChromeUtils.defineModuleGetter(
);
var security = {
init(uri, windowInfo) {
async init(uri, windowInfo) {
this.uri = uri;
this.windowInfo = windowInfo;
this.securityInfo = await this._getSecurityInfo();
},
// Display the server certificate (static)
viewCert() {
var cert = security._cert;
viewCertHelper(window, cert);
Services.ww.openWindow(
window,
"chrome://pippki/content/certViewer.xhtml",
"_blank",
"centerscreen,chrome",
this.securityInfo.cert
);
},
_getSecurityInfo() {
async _getSecurityInfo() {
// We don't have separate info for a frame, return null until further notice
// (see bug 138479)
if (!this.windowInfo.isTopWindow) {
return null;
}
var hostName = this.windowInfo.hostName;
var ui = security._getSecurityUI();
if (!ui) {
return null;
@ -53,16 +56,18 @@ var security = {
ui.state &
(Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
var isInsecure = ui.state & Ci.nsIWebProgressListener.STATE_IS_INSECURE;
var isEV = ui.state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL;
var secInfo = ui.secInfo;
if (!isInsecure && secInfo) {
var cert = secInfo.serverCert;
var issuerName = cert.issuerOrganization || cert.issuerName;
let secInfo = await window.opener.gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.getSecurityInfo();
if (secInfo) {
secInfo.QueryInterface(Ci.nsITransportSecurityInfo);
let cert = secInfo.serverCert;
let issuerName = null;
if (cert) {
issuerName = cert.issuerOrganization || cert.issuerName;
}
var retval = {
hostName,
cAName: issuerName,
encryptionAlgorithm: undefined,
encryptionStrength: undefined,
@ -71,6 +76,7 @@ var security = {
isMixed,
isEV,
cert,
certChain: secInfo.succeededCertChain || secInfo.failedCertChain,
certificateTransparency: undefined,
};
@ -121,7 +127,6 @@ var security = {
return retval;
}
return {
hostName,
cAName: "",
encryptionAlgorithm: "",
encryptionStrength: 0,
@ -205,18 +210,16 @@ var security = {
*/
viewPasswords() {
LoginHelper.openPasswordManager(window, {
filterString: this._getSecurityInfo().hostName,
filterString: this.windowInfo.hostName,
entryPoint: "pageinfo",
});
},
_cert: null,
};
function securityOnLoad(uri, windowInfo) {
security.init(uri, windowInfo);
async function securityOnLoad(uri, windowInfo) {
await security.init(uri, windowInfo);
var info = security._getSecurityInfo();
let info = security.securityInfo;
if (
!info ||
(uri.scheme === "about" && !uri.spec.startsWith("about:certerror"))
@ -227,7 +230,7 @@ function securityOnLoad(uri, windowInfo) {
document.getElementById("securityTab").hidden = false;
/* Set Identity section text */
setText("security-identity-domain-value", info.hostName);
setText("security-identity-domain-value", windowInfo.hostName);
var validity;
if (info.cert && !info.isBroken) {
@ -275,7 +278,6 @@ function securityOnLoad(uri, windowInfo) {
/* Manage the View Cert button*/
var viewCert = document.getElementById("security-view-cert");
if (info.cert) {
security._cert = info.cert;
viewCert.collapsed = false;
} else {
viewCert.collapsed = true;
@ -305,7 +307,7 @@ function securityOnLoad(uri, windowInfo) {
document.l10n.setAttributes(
document.getElementById("security-privacy-history-value"),
"security-visits-number",
{ visits: previousVisitCount(info.hostName) }
{ visits: previousVisitCount(windowInfo.hostName) }
);
/* Set the Technical Detail section messages */
@ -334,12 +336,11 @@ function securityOnLoad(uri, windowInfo) {
);
msg1 = pkiBundle.getString("pageInfo_Privacy_Encrypted1");
msg2 = pkiBundle.getString("pageInfo_Privacy_Encrypted2");
security._cert = info.cert;
} else {
hdr = pkiBundle.getString("pageInfo_NoEncryption");
if (info.hostName != null) {
if (windowInfo.hostName != null) {
msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [
info.hostName,
windowInfo.hostName,
]);
} else {
msg1 = pkiBundle.getString("pageInfo_Privacy_None4");
@ -375,20 +376,6 @@ function setText(id, value) {
}
}
function viewCertHelper(parent, cert) {
if (!cert) {
return;
}
Services.ww.openWindow(
parent,
"chrome://pippki/content/certViewer.xul",
"_blank",
"centerscreen,chrome",
cert
);
}
/**
* Return true iff realm (proto://host:port) (extracted from uri) has
* saved passwords

View File

@ -54,8 +54,8 @@
<popupnotification id="password-notification" hidden="true">
<popupnotificationcontent orient="vertical">
<textbox id="password-notification-username"/>
<textbox id="password-notification-password" type="password" show-content=""/>
<html:input id="password-notification-username"/>
<html:input id="password-notification-password" type="password"/>
<checkbox id="password-notification-visibilityToggle" hidden="true"/>
</popupnotificationcontent>
</popupnotification>

View File

@ -30,7 +30,7 @@ function showResetDialog() {
reset: false,
};
window.openDialog(
"chrome://global/content/resetProfile.xul",
"chrome://global/content/resetProfile.xhtml",
null,
"chrome,modal,centerscreen,titlebar,dialog=yes",
retVals
@ -68,6 +68,7 @@ function onExtra1() {
}
function onLoad() {
const dialog = document.getElementById("safeModeDialog");
if (appStartup.automaticSafeModeNecessary) {
document.getElementById("autoSafeMode").hidden = false;
document.getElementById("safeMode").hidden = true;
@ -75,11 +76,11 @@ function onLoad() {
document.getElementById("resetProfile").hidden = false;
} else {
// Hide the reset button is it's not supported.
document.documentElement.getButton("extra1").hidden = true;
dialog.getButton("extra1").hidden = true;
}
} else if (!ResetProfile.resetSupported()) {
// Hide the reset button and text if it's not supported.
document.documentElement.getButton("extra1").hidden = true;
dialog.getButton("extra1").hidden = true;
document.getElementById("resetProfileInstead").hidden = true;
}
document.addEventListener("dialogaccept", onDefaultButton);

View File

@ -7,15 +7,15 @@
<?xml-stylesheet href="chrome://global/skin/"?>
<?xml-stylesheet href="chrome://browser/content/safeMode.css"?>
<dialog id="safeModeDialog"
xmlns:html="http://www.w3.org/1999/xhtml"
<window xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
data-l10n-id="safe-mode-window"
data-l10n-attrs="title,style"
onload="onLoad()">
<dialog id="safeModeDialog"
buttons="accept,extra1"
buttonidaccept="start-safe-mode"
buttonidextra1="refresh-profile"
onload="onLoad()">
buttonidextra1="refresh-profile">
<linkset>
<html:link rel="localization" href="branding/brand.ftl"/>
@ -43,3 +43,4 @@
<separator class="thin"/>
</dialog>
</window>

View File

@ -11,17 +11,17 @@
<?xml-stylesheet href="chrome://browser/content/sanitizeDialog.css"?>
<!DOCTYPE dialog>
<!DOCTYPE window>
<dialog id="SanitizeDialog" type="child"
<window id="SanitizeDialog"
type="child"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
buttons="accept,cancel"
persist="lastSelected screenX screenY"
role="dialog"
data-l10n-id="dialog-title"
data-l10n-attrs="style"
onload="gSanitizePromptDialog.init();">
<dialog buttons="accept,cancel">
<linkset>
<html:link rel="localization" href="browser/sanitize.ftl"/>
@ -100,3 +100,4 @@
</hbox>
</groupbox>
</dialog>
</window>

View File

@ -32,8 +32,9 @@ var gSanitizePromptDialog = {
init() {
// This is used by selectByTimespan() to determine if the window has loaded.
this._inited = true;
this._dialog = document.querySelector("dialog");
let OKButton = document.documentElement.getButton("accept");
let OKButton = this._dialog.getButton("accept");
document.l10n.setAttributes(OKButton, "sanitize-button-ok");
document.addEventListener("dialogaccept", function(e) {
@ -65,7 +66,7 @@ var gSanitizePromptDialog = {
}
// Only apply the following if the dialog is opened outside of the Preferences.
if (!("gSubDialog" in window.opener)) {
if (!window.opener || !("gSubDialog" in window.opener)) {
// The style attribute on the dialog may get set after the dialog has been sized.
// Force the dialog to size again after the style attribute has been applied.
document.l10n.translateElements([document.documentElement]).then(() => {
@ -113,11 +114,10 @@ var gSanitizePromptDialog = {
// the 'accept' button to indicate things are happening and return false -
// once the async operation completes (either with or without errors)
// we close the window.
let docElt = document.documentElement;
let acceptButton = docElt.getButton("accept");
let acceptButton = this._dialog.getButton("accept");
acceptButton.disabled = true;
document.l10n.setAttributes(acceptButton, "sanitize-button-clearing");
docElt.getButton("cancel").disabled = true;
this._dialog.getButton("cancel").disabled = true;
try {
let range = Sanitizer.getClearRange(this.selectedTimespan);
@ -174,7 +174,7 @@ var gSanitizePromptDialog = {
);
try {
document.documentElement.getButton("accept").disabled = !found;
this._dialog.getButton("accept").disabled = !found;
} catch (e) {}
// Update the warning prompt if needed

View File

@ -0,0 +1,649 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// This is loaded into chrome windows with the subscript loader. Wrap in
// a block to prevent accidentally leaking globals onto `window`.
{
class MozTabbrowserTab extends MozElements.MozTab {
constructor() {
super();
this.addEventListener("mouseover", this);
this.addEventListener("mouseout", this);
this.addEventListener("dragstart", this, true);
this.addEventListener("dragstart", this);
this.addEventListener("mousedown", this);
this.addEventListener("mouseup", this);
this.addEventListener("click", this);
this.addEventListener("dblclick", this, true);
this.addEventListener("animationend", this);
this.addEventListener("focus", this);
this.addEventListener("AriaFocus", this);
this._selectedOnFirstMouseDown = false;
/**
* Describes how the tab ended up in this mute state. May be any of:
*
* - undefined: The tabs mute state has never changed.
* - null: The mute state was last changed through the UI.
* - Any string: The ID was changed through an extension API. The string
* must be the ID of the extension which changed it.
*/
this.muteReason = undefined;
this.mOverCloseButton = false;
this.mCorrespondingMenuitem = null;
this.closing = false;
}
static get inheritedAttributes() {
return {
".tab-background": "selected=visuallyselected,fadein,multiselected",
".tab-line":
"selected=visuallyselected,multiselected,before-multiselected",
".tab-loading-burst": "pinned,bursting,notselectedsinceload",
".tab-content":
"pinned,selected=visuallyselected,titlechanged,attention",
".tab-throbber":
"fadein,pinned,busy,progress,selected=visuallyselected",
".tab-icon-pending":
"fadein,pinned,busy,progress,selected=visuallyselected,pendingicon",
".tab-icon-image":
"src=image,triggeringprincipal=iconloadingprincipal,requestcontextid,fadein,pinned,selected=visuallyselected,busy,crashed,sharing",
".tab-sharing-icon-overlay": "sharing,selected=visuallyselected,pinned",
".tab-icon-overlay":
"crashed,busy,soundplaying,soundplaying-scheduledremoval,pinned,muted,blocked,selected=visuallyselected,activemedia-blocked",
".tab-label-container":
"pinned,selected=visuallyselected,labeldirection",
".tab-label":
"text=label,accesskey,fadein,pinned,selected=visuallyselected,attention",
".tab-icon-sound":
"soundplaying,soundplaying-scheduledremoval,pinned,muted,blocked,selected=visuallyselected,activemedia-blocked,pictureinpicture",
".tab-close-button": "fadein,pinned,selected=visuallyselected",
};
}
get fragment() {
if (!this.constructor.hasOwnProperty("_fragment")) {
this.constructor._fragment = MozXULElement.parseXULToFragment(`
<stack class="tab-stack" flex="1">
<vbox class="tab-background">
<hbox class="tab-line"/>
<spacer flex="1" class="tab-background-inner"/>
<hbox class="tab-bottom-line"/>
</vbox>
<hbox class="tab-loading-burst"/>
<hbox class="tab-content" align="center">
<hbox class="tab-throbber" layer="true"/>
<hbox class="tab-icon-pending"/>
<image class="tab-icon-image" validate="never" role="presentation"/>
<image class="tab-sharing-icon-overlay" role="presentation"/>
<image class="tab-icon-overlay" role="presentation"/>
<hbox class="tab-label-container"
onoverflow="this.setAttribute('textoverflow', 'true');"
onunderflow="this.removeAttribute('textoverflow');"
flex="1">
<label class="tab-text tab-label" role="presentation"/>
</hbox>
<image class="tab-icon-sound" role="presentation"/>
<image class="tab-close-button close-icon" role="presentation"/>
</hbox>
</stack>
`);
}
return document.importNode(this.constructor._fragment, true);
}
connectedCallback() {
this.initialize();
}
initialize() {
if (this._initialized) {
return;
}
this.textContent = "";
this.appendChild(this.fragment);
this.initializeAttributeInheritance();
this.setAttribute("context", "tabContextMenu");
this._initialized = true;
if (!("_lastAccessed" in this)) {
this.updateLastAccessed();
}
}
get container() {
return gBrowser.tabContainer;
}
set _visuallySelected(val) {
if (val == (this.getAttribute("visuallyselected") == "true")) {
return val;
}
if (val) {
this.setAttribute("visuallyselected", "true");
} else {
this.removeAttribute("visuallyselected");
}
gBrowser._tabAttrModified(this, ["visuallyselected"]);
return val;
}
set _selected(val) {
// in e10s we want to only pseudo-select a tab before its rendering is done, so that
// the rest of the system knows that the tab is selected, but we don't want to update its
// visual status to selected until after we receive confirmation that its content has painted.
if (val) {
this.setAttribute("selected", "true");
} else {
this.removeAttribute("selected");
}
// If we're non-e10s we should update the visual selection as well at the same time,
// *or* if we're e10s and the visually selected tab isn't changing, in which case the
// tab switcher code won't run and update anything else (like the before- and after-
// selected attributes).
if (
!gMultiProcessBrowser ||
(val && this.hasAttribute("visuallyselected"))
) {
this._visuallySelected = val;
}
return val;
}
get pinned() {
return this.getAttribute("pinned") == "true";
}
get hidden() {
return this.getAttribute("hidden") == "true";
}
get muted() {
return this.getAttribute("muted") == "true";
}
get multiselected() {
return this.getAttribute("multiselected") == "true";
}
get beforeMultiselected() {
return this.getAttribute("before-multiselected") == "true";
}
get userContextId() {
return this.hasAttribute("usercontextid")
? parseInt(this.getAttribute("usercontextid"))
: 0;
}
get soundPlaying() {
return this.getAttribute("soundplaying") == "true";
}
get pictureinpicture() {
return this.getAttribute("pictureinpicture") == "true";
}
get activeMediaBlocked() {
return this.getAttribute("activemedia-blocked") == "true";
}
get isEmpty() {
// Determines if a tab is "empty", usually used in the context of determining
// if it's ok to close the tab.
if (this.hasAttribute("busy")) {
return false;
}
if (this.hasAttribute("customizemode")) {
return false;
}
let browser = this.linkedBrowser;
if (!isBlankPageURL(browser.currentURI.spec)) {
return false;
}
if (!checkEmptyPageOrigin(browser)) {
return false;
}
if (browser.canGoForward || browser.canGoBack) {
return false;
}
return true;
}
get lastAccessed() {
return this._lastAccessed == Infinity ? Date.now() : this._lastAccessed;
}
get _overPlayingIcon() {
let iconVisible =
this.hasAttribute("soundplaying") ||
this.hasAttribute("muted") ||
this.hasAttribute("activemedia-blocked");
let soundPlayingIcon = this.soundPlayingIcon;
let overlayIcon = this.overlayIcon;
return (
(soundPlayingIcon && soundPlayingIcon.matches(":hover")) ||
(overlayIcon && overlayIcon.matches(":hover") && iconVisible)
);
}
get soundPlayingIcon() {
return this.querySelector(".tab-icon-sound");
}
get overlayIcon() {
return this.querySelector(".tab-icon-overlay");
}
get throbber() {
return this.querySelector(".tab-throbber");
}
get iconImage() {
return this.querySelector(".tab-icon-image");
}
get sharingIcon() {
return this.querySelector(".tab-sharing-icon-overlay");
}
get textLabel() {
return this.querySelector(".tab-label");
}
get closeButton() {
return this.querySelector(".tab-close-button");
}
updateLastAccessed(aDate) {
this._lastAccessed = this.selected ? Infinity : aDate || Date.now();
}
on_mouseover(event) {
if (event.target.classList.contains("tab-close-button")) {
this.mOverCloseButton = true;
}
this._mouseenter();
}
on_mouseout(event) {
if (event.target.classList.contains("tab-close-button")) {
this.mOverCloseButton = false;
}
this._mouseleave();
}
on_dragstart(event) {
if (event.eventPhase == Event.CAPTURING_PHASE) {
this.style.MozUserFocus = "";
} else if (this.mOverCloseButton) {
event.stopPropagation();
}
}
on_mousedown(event) {
let eventMaySelectTab = true;
let tabContainer = this.container;
if (
tabContainer._closeTabByDblclick &&
event.button == 0 &&
event.detail == 1
) {
this._selectedOnFirstMouseDown = this.selected;
}
if (this.selected) {
this.style.MozUserFocus = "ignore";
} else if (
event.target.classList.contains("tab-close-button") ||
event.target.classList.contains("tab-icon-sound") ||
event.target.classList.contains("tab-icon-overlay")
) {
eventMaySelectTab = false;
}
if (event.button == 1) {
gBrowser.warmupTab(gBrowser._findTabToBlurTo(this));
}
if (event.button == 0 && tabContainer._multiselectEnabled) {
let shiftKey = event.shiftKey;
let accelKey = event.getModifierState("Accel");
if (shiftKey) {
eventMaySelectTab = false;
const lastSelectedTab = gBrowser.lastMultiSelectedTab;
if (!accelKey) {
gBrowser.selectedTab = lastSelectedTab;
// Make sure selection is cleared when tab-switch doesn't happen.
gBrowser.clearMultiSelectedTabs(false);
}
gBrowser.addRangeToMultiSelectedTabs(lastSelectedTab, this);
} else if (accelKey) {
// Ctrl (Cmd for mac) key is pressed
eventMaySelectTab = false;
if (this.multiselected) {
gBrowser.removeFromMultiSelectedTabs(this, true);
} else if (this != gBrowser.selectedTab) {
gBrowser.addToMultiSelectedTabs(this, false);
gBrowser.lastMultiSelectedTab = this;
}
} else if (!this.selected && this.multiselected) {
gBrowser.lockClearMultiSelectionOnce();
}
}
if (eventMaySelectTab) {
super.on_mousedown(event);
}
}
on_mouseup(event) {
// Make sure that clear-selection is released.
// Otherwise selection using Shift key may be broken.
gBrowser.unlockClearMultiSelection();
this.style.MozUserFocus = "";
}
on_click(event) {
if (event.button != 0) {
return;
}
if (event.getModifierState("Accel") || event.shiftKey) {
return;
}
if (
gBrowser.multiSelectedTabsCount > 0 &&
!event.target.classList.contains("tab-close-button") &&
!event.target.classList.contains("tab-icon-sound") &&
!event.target.classList.contains("tab-icon-overlay")
) {
// Tabs were previously multi-selected and user clicks on a tab
// without holding Ctrl/Cmd Key
// Force positional attributes to update when the
// target (of the click) is the "active" tab.
let updatePositionalAttr = gBrowser.selectedTab == this;
gBrowser.clearMultiSelectedTabs(updatePositionalAttr);
}
if (
event.target.classList.contains("tab-icon-sound") ||
(event.target.classList.contains("tab-icon-overlay") &&
(event.target.hasAttribute("soundplaying") ||
event.target.hasAttribute("muted") ||
event.target.hasAttribute("activemedia-blocked")))
) {
if (this.multiselected) {
gBrowser.toggleMuteAudioOnMultiSelectedTabs(this);
} else {
this.toggleMuteAudio();
}
return;
}
if (event.target.classList.contains("tab-close-button")) {
if (this.multiselected) {
gBrowser.removeMultiSelectedTabs();
} else {
gBrowser.removeTab(this, {
animate: true,
byMouse: event.mozInputSource == MouseEvent.MOZ_SOURCE_MOUSE,
});
}
// This enables double-click protection for the tab container
// (see tabbrowser-tabs 'click' handler).
gBrowser.tabContainer._blockDblClick = true;
}
}
on_dblclick(event) {
if (event.button != 0) {
return;
}
// for the one-close-button case
if (event.target.classList.contains("tab-close-button")) {
event.stopPropagation();
}
let tabContainer = this.container;
if (
tabContainer._closeTabByDblclick &&
this._selectedOnFirstMouseDown &&
this.selected &&
!(
event.target.classList.contains("tab-icon-sound") ||
event.target.classList.contains("tab-icon-overlay")
)
) {
gBrowser.removeTab(this, {
animate: true,
byMouse: event.mozInputSource == MouseEvent.MOZ_SOURCE_MOUSE,
});
}
}
on_animationend(event) {
if (event.target.classList.contains("tab-loading-burst")) {
this.removeAttribute("bursting");
}
}
_mouseenter() {
if (this.hidden || this.closing) {
return;
}
let tabContainer = this.container;
let visibleTabs = tabContainer._getVisibleTabs();
let tabIndex = visibleTabs.indexOf(this);
if (this.selected) {
tabContainer._handleTabSelect();
}
if (tabIndex == 0) {
tabContainer._beforeHoveredTab = null;
} else {
let candidate = visibleTabs[tabIndex - 1];
let separatedByScrollButton =
tabContainer.getAttribute("overflow") == "true" &&
candidate.pinned &&
!this.pinned;
if (!candidate.selected && !separatedByScrollButton) {
tabContainer._beforeHoveredTab = candidate;
candidate.setAttribute("beforehovered", "true");
}
}
if (tabIndex == visibleTabs.length - 1) {
tabContainer._afterHoveredTab = null;
} else {
let candidate = visibleTabs[tabIndex + 1];
if (!candidate.selected) {
tabContainer._afterHoveredTab = candidate;
candidate.setAttribute("afterhovered", "true");
}
}
tabContainer._hoveredTab = this;
if (this.linkedPanel && !this.selected) {
this.linkedBrowser.unselectedTabHover(true);
this.startUnselectedTabHoverTimer();
}
// Prepare connection to host beforehand.
SessionStore.speculativeConnectOnTabHover(this);
let tabToWarm = this;
if (this.mOverCloseButton) {
tabToWarm = gBrowser._findTabToBlurTo(this);
}
gBrowser.warmupTab(tabToWarm);
}
_mouseleave() {
let tabContainer = this.container;
if (tabContainer._beforeHoveredTab) {
tabContainer._beforeHoveredTab.removeAttribute("beforehovered");
tabContainer._beforeHoveredTab = null;
}
if (tabContainer._afterHoveredTab) {
tabContainer._afterHoveredTab.removeAttribute("afterhovered");
tabContainer._afterHoveredTab = null;
}
tabContainer._hoveredTab = null;
if (this.linkedPanel && !this.selected) {
this.linkedBrowser.unselectedTabHover(false);
this.cancelUnselectedTabHoverTimer();
}
}
startUnselectedTabHoverTimer() {
// Only record data when we need to.
if (!this.linkedBrowser.shouldHandleUnselectedTabHover) {
return;
}
if (
!TelemetryStopwatch.running("HOVER_UNTIL_UNSELECTED_TAB_OPENED", this)
) {
TelemetryStopwatch.start("HOVER_UNTIL_UNSELECTED_TAB_OPENED", this);
}
if (this._hoverTabTimer) {
clearTimeout(this._hoverTabTimer);
this._hoverTabTimer = null;
}
}
cancelUnselectedTabHoverTimer() {
// Since we're listening "mouseout" event, instead of "mouseleave".
// Every time the cursor is moving from the tab to its child node (icon),
// it would dispatch "mouseout"(for tab) first and then dispatch
// "mouseover" (for icon, eg: close button, speaker icon) soon.
// It causes we would cancel present TelemetryStopwatch immediately
// when cursor is moving on the icon, and then start a new one.
// In order to avoid this situation, we could delay cancellation and
// remove it if we get "mouseover" within very short period.
this._hoverTabTimer = setTimeout(() => {
if (
TelemetryStopwatch.running("HOVER_UNTIL_UNSELECTED_TAB_OPENED", this)
) {
TelemetryStopwatch.cancel("HOVER_UNTIL_UNSELECTED_TAB_OPENED", this);
}
}, 100);
}
finishUnselectedTabHoverTimer() {
// Stop timer when the tab is opened.
if (
TelemetryStopwatch.running("HOVER_UNTIL_UNSELECTED_TAB_OPENED", this)
) {
TelemetryStopwatch.finish("HOVER_UNTIL_UNSELECTED_TAB_OPENED", this);
}
}
toggleMuteAudio(aMuteReason) {
let browser = this.linkedBrowser;
let modifiedAttrs = [];
let hist = Services.telemetry.getHistogramById(
"TAB_AUDIO_INDICATOR_USED"
);
if (this.hasAttribute("activemedia-blocked")) {
this.removeAttribute("activemedia-blocked");
modifiedAttrs.push("activemedia-blocked");
browser.resumeMedia();
hist.add(3 /* unblockByClickingIcon */);
} else {
if (browser.audioMuted) {
if (this.linkedPanel) {
// "Lazy Browser" should not invoke its unmute method
browser.unmute();
}
this.removeAttribute("muted");
hist.add(1 /* unmute */);
} else {
if (this.linkedPanel) {
// "Lazy Browser" should not invoke its mute method
browser.mute();
}
this.setAttribute("muted", "true");
hist.add(0 /* mute */);
}
this.muteReason = aMuteReason || null;
modifiedAttrs.push("muted");
}
gBrowser._tabAttrModified(this, modifiedAttrs);
}
setUserContextId(aUserContextId) {
if (aUserContextId) {
if (this.linkedBrowser) {
this.linkedBrowser.setAttribute("usercontextid", aUserContextId);
}
this.setAttribute("usercontextid", aUserContextId);
} else {
if (this.linkedBrowser) {
this.linkedBrowser.removeAttribute("usercontextid");
}
this.removeAttribute("usercontextid");
}
ContextualIdentityService.setTabStyle(this);
}
updateA11yDescription() {
let prevDescTab = gBrowser.tabContainer.querySelector(
"tab[aria-describedby]"
);
if (prevDescTab) {
// We can only have a description for the focused tab.
prevDescTab.removeAttribute("aria-describedby");
}
let desc = document.getElementById("tabbrowser-tab-a11y-desc");
desc.textContent = gBrowser.getTabTooltip(this, false);
this.setAttribute("aria-describedby", "tabbrowser-tab-a11y-desc");
}
on_focus(event) {
this.updateA11yDescription();
}
on_AriaFocus(event) {
this.updateA11yDescription();
}
}
customElements.define("tabbrowser-tab", MozTabbrowserTab, {
extends: "tab",
});
}

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
.tab-close-button[pinned],
#tabbrowser-tabs[closebuttons="activetab"] > .tabbrowser-tab > .tab-stack > .tab-content > .tab-close-button:not([selected="true"]),
#tabbrowser-tabs[closebuttons="activetab"] > .tabbrowser-arrowscrollbox > .tabbrowser-tab > .tab-stack > .tab-content > .tab-close-button:not([selected="true"]),
.tab-icon-pending:not([pendingicon]),
.tab-icon-pending[busy],
.tab-icon-pending[pinned],
@ -54,15 +54,6 @@ tabpanels {
background-color: transparent;
}
.tab-drop-indicator-box {
-moz-box-align: end;
}
.tab-drop-indicator {
position: relative;
z-index: 2;
}
/* Apply crisp rendering for favicons at exactly 2dppx resolution */
@media (resolution: 2dppx) {
.tab-icon-image {

View File

@ -39,6 +39,7 @@
window.addEventListener("occlusionstatechange", this);
window.addEventListener("framefocusrequested", this);
this.tabContainer.init();
this._setupInitialBrowserAndTab();
if (Services.prefs.getBoolPref("browser.display.use_system_colors")) {
@ -83,6 +84,7 @@
);
this._setupEventListeners();
this._initialized = true;
},
ownerGlobal: window,
@ -93,6 +95,8 @@
_visibleTabs: null,
_tabs: null,
_lastRelatedTabMap: new WeakMap(),
mProgressListeners: [],
@ -253,8 +257,10 @@
},
get tabs() {
delete this.tabs;
return (this.tabs = this.tabContainer.children);
if (!this._tabs) {
this._tabs = this.tabContainer.allTabs;
}
return this._tabs;
},
get tabbox() {
@ -267,25 +273,16 @@
return (this.tabpanels = document.getElementById("tabbrowser-tabpanels"));
},
get addEventListener() {
delete this.addEventListener;
return (this.addEventListener = this.tabpanels.addEventListener.bind(
this.tabpanels
));
addEventListener(...args) {
this.tabpanels.addEventListener(...args);
},
get removeEventListener() {
delete this.removeEventListener;
return (this.removeEventListener = this.tabpanels.removeEventListener.bind(
this.tabpanels
));
removeEventListener(...args) {
this.tabpanels.removeEventListener(...args);
},
get dispatchEvent() {
delete this.dispatchEvent;
return (this.dispatchEvent = this.tabpanels.dispatchEvent.bind(
this.tabpanels
));
dispatchEvent(...args) {
return this.tabpanels.dispatchEvent(...args);
},
get visibleTabs() {
@ -307,19 +304,6 @@
return i;
},
get popupAnchor() {
if (this.selectedTab._popupAnchor) {
return this.selectedTab._popupAnchor;
}
let stack = this.selectedBrowser.parentNode;
// Create an anchor for the popup
let popupAnchor = document.createXULElement("hbox");
popupAnchor.className = "popup-anchor";
popupAnchor.hidden = true;
stack.appendChild(popupAnchor);
return (this.selectedTab._popupAnchor = popupAnchor);
},
set selectedTab(val) {
if (gNavToolbox.collapsed && !this._allowTabChange) {
return this.tabbox.selectedTab;
@ -572,6 +556,11 @@
return this.selectedBrowser.userTypedValue;
},
_invalidateCachedTabs() {
this._tabs = null;
this._visibleTabs = null;
},
_setFindbarData() {
// Ensure we know what the find bar key is in the content process:
let { sharedData } = Services.ppmm;
@ -723,19 +712,15 @@
syncThrobberAnimations(aTab) {
aTab.ownerGlobal.promiseDocumentFlushed(() => {
if (!aTab.parentNode) {
if (!aTab.container) {
return;
}
const animations = Array.from(
aTab.parentNode.getElementsByTagName("tab")
aTab.container.getElementsByTagName("tab")
)
.map(tab => {
const throbber = document.getAnonymousElementByAttribute(
tab,
"anonid",
"tab-throbber"
);
const throbber = tab.throbber;
return throbber ? throbber.getAnimations({ subtree: true }) : [];
})
.reduce((a, b) => a.concat(b))
@ -989,7 +974,7 @@
var modifier = docElement.getAttribute("titlemodifier");
if (docTitle) {
newTitle += docElement.getAttribute("titlepreface");
newTitle += docElement.getAttribute("titlepreface") || "";
newTitle += docTitle;
if (modifier) {
newTitle += sep;
@ -1002,14 +987,25 @@
// XXX https://bugzilla.mozilla.org/show_bug.cgi?id=22183#c239
try {
if (docElement.getAttribute("chromehidden").includes("location")) {
var uri = Services.io.createExposableURI(aBrowser.currentURI);
if (uri.scheme == "about") {
newTitle = uri.spec + sep + newTitle;
const uri = Services.io.createExposableURI(aBrowser.currentURI);
if (uri.scheme === "about") {
newTitle = `${uri.spec}${sep}${newTitle}`;
} else if (uri.scheme === "moz-extension") {
const ext = WebExtensionPolicy.getByHostname(uri.host);
if (ext && ext.name) {
const prefix = document.querySelector("#urlbar-label-extension")
.value;
newTitle = `${prefix} (${ext.name})${sep}${newTitle}`;
} else {
newTitle = `${uri.prePath}${sep}${newTitle}`;
}
} else {
newTitle = uri.prePath + sep + newTitle;
newTitle = `${uri.prePath}${sep}${newTitle}`;
}
}
} catch (e) {}
} catch (e) {
// ignored
}
return newTitle;
},
@ -1245,6 +1241,7 @@
if (!gMultiProcessBrowser) {
this._adjustFocusBeforeTabSwitch(oldTab, newTab);
this._adjustFocusAfterTabSwitch(newTab);
gURLBar.afterTabSwitchFocusChange();
}
}
@ -1338,9 +1335,6 @@
// In full screen mode, only bother making the location bar visible
// if the tab is a blank one.
if (newBrowser._urlbarFocused && gURLBar) {
// Explicitly close the popup if the URL bar retains focus
gURLBar.view.close();
// If the user happened to type into the URL bar for this browser
// by the time we got here, focusing will cause the text to be
// selected which could cause them to overwrite what they've
@ -1367,10 +1361,7 @@
// Don't focus the content area if something has been focused after the
// tab switch was initiated.
if (
gMultiProcessBrowser &&
document.activeElement != document.documentElement
) {
if (gMultiProcessBrowser && document.activeElement != document.body) {
return;
}
@ -2574,8 +2565,7 @@
(openerBrowser && this.getTabForBrowser(openerBrowser)) ||
(relatedToCurrent && this.selectedTab);
var t = document.createXULElement("tab");
var t = document.createXULElement("tab", { is: "tabbrowser-tab" });
t.openerTab = openerTab;
aURI = aURI || "about:blank";
@ -2648,9 +2638,6 @@
);
}
// invalidate cache
this._visibleTabs = null;
let usingPreloadedContent = false;
let b;
@ -2702,9 +2689,11 @@
index = Math.min(index, this.tabs.length);
}
// Use .item() instead of [] because we need .item() to return null in
// order to append the tab at the end in case index == tabs.length.
let tabAfter = this.tabs.item(index);
let tabAfter = this.tabs[index] || null;
this._invalidateCachedTabs();
// Prevent a flash of unstyled content by setting up the tab content
// and inherited attributes before appending it (see Bug 1592054):
t.initialize();
this.tabContainer.insertBefore(t, tabAfter);
if (tabAfter) {
this._updateTabsAfterInsert();
@ -3192,7 +3181,7 @@
setTimeout(
function(tab, tabbrowser) {
if (
tab.parentNode &&
tab.container &&
window.getComputedStyle(tab).maxWidth == "0.1px"
) {
console.assert(
@ -3335,7 +3324,7 @@
aTab.closing = true;
this._removingTabs.push(aTab);
this._visibleTabs = null; // invalidate cache
this._invalidateCachedTabs();
// Invalidate hovered tab state tracking for this closing tab.
if (this.tabContainer._hoveredTab == aTab) {
@ -3474,6 +3463,7 @@
// Remove the tab ...
aTab.remove();
this._invalidateCachedTabs();
// Update hashiddentabs if this tab was hidden.
if (aTab.hidden) {
@ -3588,17 +3578,16 @@
}
// Try to find a remaining tab that comes after the given tab
let tab = aTab;
do {
tab = tab.nextElementSibling;
} while (tab && !remainingTabs.includes(tab));
let tab = this.tabContainer.findNextTab(aTab, {
direction: 1,
filter: _tab => remainingTabs.includes(_tab),
});
if (!tab) {
tab = aTab;
do {
tab = tab.previousElementSibling;
} while (tab && !remainingTabs.includes(tab));
tab = this.tabContainer.findNextTab(aTab, {
direction: -1,
filter: _tab => remainingTabs.includes(_tab),
});
}
return tab;
@ -3972,7 +3961,7 @@
showTab(aTab) {
if (aTab.hidden) {
aTab.removeAttribute("hidden");
this._visibleTabs = null; // invalidate cache
this._invalidateCachedTabs();
this.tabContainer._updateCloseButtons();
this.tabContainer._updateHiddenTabsStatus();
@ -3995,7 +3984,7 @@
!aTab._sharingState
) {
aTab.setAttribute("hidden", "true");
this._visibleTabs = null; // invalidate cache
this._invalidateCachedTabs();
this.tabContainer._updateCloseButtons();
this.tabContainer._updateHiddenTabsStatus();
@ -4179,12 +4168,9 @@
aIndex = aIndex < aTab._tPos ? aIndex : aIndex + 1;
// invalidate cache
this._visibleTabs = null;
// use .item() instead of [] because dragging to the end of the strip goes out of
// bounds: .item() returns null (so it acts like appendChild), but [] throws
this.tabContainer.insertBefore(aTab, this.tabs.item(aIndex));
let neighbor = this.tabs[aIndex] || null;
this._invalidateCachedTabs();
this.tabContainer.insertBefore(aTab, neighbor);
this._updateTabsAfterInsert();
if (wasFocused) {
@ -4205,10 +4191,10 @@
},
moveTabForward() {
let nextTab = this.selectedTab.nextElementSibling;
while (nextTab && nextTab.hidden) {
nextTab = nextTab.nextElementSibling;
}
let nextTab = this.tabContainer.findNextTab(this.selectedTab, {
direction: 1,
filter: tab => !tab.hidden,
});
if (nextTab) {
this.moveTabTo(this.selectedTab, nextTab._tPos);
@ -4253,7 +4239,7 @@
let newTab = this.addWebTab("about:blank", params);
let newBrowser = this.getBrowserForTab(newTab);
aTab.parentNode._finishAnimateTabMove();
aTab.container._finishAnimateTabMove();
if (!createLazyBrowser) {
// Stop the about:blank load.
@ -4276,10 +4262,10 @@
},
moveTabBackward() {
let previousTab = this.selectedTab.previousElementSibling;
while (previousTab && previousTab.hidden) {
previousTab = previousTab.previousElementSibling;
}
let previousTab = this.tabContainer.findNextTab(this.selectedTab, {
direction: -1,
filter: tab => !tab.hidden,
});
if (previousTab) {
this.moveTabTo(this.selectedTab, previousTab._tPos);
@ -4355,7 +4341,7 @@
return;
}
const tabs = this._visibleTabs;
const tabs = this.visibleTabs;
const indexOfTab1 = tabs.indexOf(aTab1);
const indexOfTab2 = tabs.indexOf(aTab2);
@ -4704,10 +4690,46 @@
}
},
getTabTooltip(tab, includeLabel = true) {
let label = "";
if (includeLabel) {
label = tab._fullLabel || tab.getAttribute("label");
}
if (AppConstants.NIGHTLY_BUILD) {
if (
tab.linkedBrowser &&
tab.linkedBrowser.isRemoteBrowser &&
tab.linkedBrowser.frameLoader
) {
label +=
" (pid " + tab.linkedBrowser.frameLoader.remoteTab.osPid + ")";
if (
window.docShell.QueryInterface(Ci.nsILoadContext)
.useRemoteSubframes
) {
label += " [F]";
}
}
}
if (tab.userContextId) {
label = gTabBrowserBundle.formatStringFromName(
"tabs.containers.tooltip",
[
label,
ContextualIdentityService.getUserContextLabel(tab.userContextId),
]
);
}
return label;
},
createTooltip(event) {
event.stopPropagation();
var tab = document.tooltipNode;
if (!tab || tab.localName != "tab") {
let tab = document.tooltipNode
? document.tooltipNode.closest("tab")
: null;
if (!tab) {
event.preventDefault();
return;
}
@ -4766,33 +4788,7 @@
).replace("#1", affectedTabsLength);
}
} else {
label = tab._fullLabel || tab.getAttribute("label");
if (AppConstants.NIGHTLY_BUILD) {
if (
tab.linkedBrowser &&
tab.linkedBrowser.isRemoteBrowser &&
tab.linkedBrowser.frameLoader
) {
label +=
" (pid " + tab.linkedBrowser.frameLoader.remoteTab.osPid + ")";
if (
window.docShell.QueryInterface(Ci.nsILoadContext)
.useRemoteSubframes
) {
label += " [F]";
}
}
}
if (tab.userContextId) {
label = gTabBrowserBundle.formatStringFromName(
"tabs.containers.tooltip",
[
label,
ContextualIdentityService.getUserContextLabel(tab.userContextId),
]
);
}
label = this.getTabTooltip(tab);
}
event.target.setAttribute("label", label);
@ -5000,6 +4996,7 @@
},
destroy() {
this.tabContainer.destroy();
Services.obs.removeObserver(this, "contextual-identity-updated");
for (let tab of this.tabs) {
@ -5188,6 +5185,25 @@
return;
}
if (!browser.docShell) {
return;
}
// Ensure `docShell.document` (an nsIWebNavigation idl prop) is there:
browser.docShell.QueryInterface(Ci.nsIWebNavigation);
if (event.target != browser.docShell.document) {
return;
}
// Ignore empty title changes on internal pages. This prevents the title
// from changing while Fluent is populating the (initially-empty) title
// element.
if (
!browser.contentTitle &&
browser.contentPrincipal.isSystemPrincipal
) {
return;
}
var titleChanged = this.setTabTitle(tab);
if (titleChanged && !tab.selected && !tab.hasAttribute("busy")) {
tab.setAttribute("titlechanged", "true");
@ -5806,45 +5822,50 @@
gBrowser._tabAttrModified(this.mTab, ["busy"]);
}
// If the browser was playing audio, we should remove the playing state.
if (this.mTab.hasAttribute("soundplaying") && !isSameDocument) {
clearTimeout(this.mTab._soundPlayingAttrRemovalTimer);
this.mTab._soundPlayingAttrRemovalTimer = 0;
this.mTab.removeAttribute("soundplaying");
gBrowser._tabAttrModified(this.mTab, ["soundplaying"]);
}
// If the browser was previously muted, we should restore the muted state.
if (this.mTab.hasAttribute("muted")) {
this.mTab.linkedBrowser.mute();
}
if (gBrowser.isFindBarInitialized(this.mTab)) {
let findBar = gBrowser.getCachedFindBar(this.mTab);
// Close the Find toolbar if we're in old-style TAF mode
if (findBar.findMode != findBar.FIND_NORMAL) {
findBar.close();
if (!isSameDocument) {
// If the browser was playing audio, we should remove the playing state.
if (this.mTab.hasAttribute("soundplaying")) {
clearTimeout(this.mTab._soundPlayingAttrRemovalTimer);
this.mTab._soundPlayingAttrRemovalTimer = 0;
this.mTab.removeAttribute("soundplaying");
gBrowser._tabAttrModified(this.mTab, ["soundplaying"]);
}
}
if (!isReload) {
gBrowser.setTabTitle(this.mTab);
}
// If the browser was previously muted, we should restore the muted state.
if (this.mTab.hasAttribute("muted")) {
this.mTab.linkedBrowser.mute();
}
// Don't clear the favicon if this tab is in the pending
// state, as SessionStore will have set the icon for us even
// though we're pointed at an about:blank. Also don't clear it
// if onLocationChange was triggered by a pushState or a
// replaceState (bug 550565) or a hash change (bug 408415).
if (
!this.mTab.hasAttribute("pending") &&
aWebProgress.isLoadingDocument &&
!isSameDocument
) {
// Removing the tab's image here causes flickering, wait until the load
// is complete.
this.mBrowser.mIconURL = null;
if (gBrowser.isFindBarInitialized(this.mTab)) {
let findBar = gBrowser.getCachedFindBar(this.mTab);
// Close the Find toolbar if we're in old-style TAF mode
if (findBar.findMode != findBar.FIND_NORMAL) {
findBar.close();
}
}
// Note that we're not updating for same-document loads, despite
// the `title` argument to `history.pushState/replaceState`. For
// context, see https://bugzilla.mozilla.org/show_bug.cgi?id=585653
// and https://github.com/whatwg/html/issues/2174
if (!isReload) {
gBrowser.setTabTitle(this.mTab);
}
// Don't clear the favicon if this tab is in the pending
// state, as SessionStore will have set the icon for us even
// though we're pointed at an about:blank. Also don't clear it
// if onLocationChange was triggered by a pushState or a
// replaceState (bug 550565) or a hash change (bug 408415).
if (
!this.mTab.hasAttribute("pending") &&
aWebProgress.isLoadingDocument
) {
// Removing the tab's image here causes flickering, wait until the
// load is complete.
this.mBrowser.mIconURL = null;
}
}
let userContextId = this.mBrowser.getAttribute("usercontextid") || 0;
@ -6124,10 +6145,9 @@ var TabContextMenu = {
});
},
updateContextMenu(aPopupMenu) {
this.contextTab =
aPopupMenu.triggerNode.localName == "tab"
? aPopupMenu.triggerNode
: gBrowser.selectedTab;
let tab = aPopupMenu.triggerNode && aPopupMenu.triggerNode.closest("tab");
this.contextTab = tab || gBrowser.selectedTab;
let disabled = gBrowser.tabs.length == 1;
let multiselectionContext = this.contextTab.multiselected;
@ -6200,10 +6220,12 @@ var TabContextMenu = {
let lastVisibleTab = visibleTabs[visibleTabs.length - 1];
let tabsToMove = contextTabIsSelected ? selectedTabs : [this.contextTab];
let lastTabToMove = tabsToMove[tabsToMove.length - 1];
let isLastPinnedTab =
lastTabToMove.pinned &&
(!lastTabToMove.nextElementSibling ||
!lastTabToMove.nextElementSibling.pinned);
let isLastPinnedTab = false;
if (lastTabToMove.pinned) {
let sibling = gBrowser.tabContainer.findNextTab(lastTabToMove);
isLastPinnedTab = !sibling || !sibling.pinned;
}
contextMoveTabToEnd.disabled =
(lastTabToMove == lastVisibleTab || isLastPinnedTab) &&
allSelectedTabsAdjacent;

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@ add_task(async function() {
await BrowserTestUtils.synthesizeMouseAtCenter("#brandLogo", {}, browser);
let doc = window.document;
let searchInput = BrowserSearch.searchBar.textbox.inputField;
let searchInput = BrowserSearch.searchBar.textbox;
isnot(
searchInput,
doc.activeElement,

View File

@ -1,4 +1,4 @@
[DEFAULT]
[test_aboutCrashed.xul]
[test_aboutRestartRequired.xul]
[test_aboutCrashed.xhtml]
[test_aboutRestartRequired.xhtml]

View File

@ -4,7 +4,7 @@ support-files =
test_contextmenu_links.html
subtst_contextmenu.html
subtst_contextmenu_input.html
subtst_contextmenu_xul.xul
subtst_contextmenu_xul.xhtml
ctxmenu-image.png
../general/head.js
../general/video.ogg

View File

@ -43,7 +43,7 @@ add_task(async function init() {
// Below are test cases for XUL element
add_task(async function test_xul_text_link_label() {
let url = chrome_base + "subtst_contextmenu_xul.xul";
let url = chrome_base + "subtst_contextmenu_xul.xhtml";
await BrowserTestUtils.openNewForegroundTab({
gBrowser,

View File

@ -85,11 +85,7 @@ add_task(async function test_toolbar_contextmenu_touch() {
// Test the urlbar input context menu.
add_task(async function test_urlbar_contextmenu_touch() {
let urlbar = document.getElementById("urlbar");
let textBox = document.getAnonymousElementByAttribute(
urlbar,
"anonid",
"moz-input-box"
);
let textBox = urlbar.querySelector("moz-input-box");
let menu = textBox.menupopup;
await openAndCheckContextMenu(menu, textBox);
});

View File

@ -3,7 +3,7 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml">
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml">
<label id="test-xul-text-link-label" is="text-link" value="XUL text-link label" href="https://www.mozilla.com"/>
</page>
</window>

View File

@ -44,11 +44,7 @@ add_task(async () => {
await waitForAttributeChange(tab, "label");
ok(tab.hasAttribute("busy"), "Should have seen the busy attribute");
let label = document.getAnonymousElementByAttribute(
tab,
"anonid",
"tab-label"
);
let label = tab.textLabel;
let bounds = label.getBoundingClientRect();
await waitForAttributeChange(tab, "busy");
@ -84,11 +80,7 @@ add_task(async () => {
is(icon.iconURL, "http://example.com/favicon.ico");
let tab = gBrowser.getTabForBrowser(browser);
let label = document.getAnonymousElementByAttribute(
tab,
"anonid",
"tab-label"
);
let label = tab.textLabel;
let bounds = label.getBoundingClientRect();
await ContentTask.spawn(browser, null, () => {

View File

@ -853,7 +853,7 @@ add_task(async function test_large_popup() {
BrowserTestUtils.removeTab(tab);
});
// This test checks the same as the previous test but in a new smaller window.
// This test checks the same as the previous test but in a new, vertically smaller window.
add_task(async function test_large_popup_in_small_window() {
let newWin = await BrowserTestUtils.openNewBrowserWindow();
@ -862,10 +862,11 @@ add_task(async function test_large_popup_in_small_window() {
"resize",
false,
e => {
return newWin.innerHeight <= 400 && newWin.innerWidth <= 400;
info(`Got resize event (innerHeight: ${newWin.innerHeight})`);
return newWin.innerHeight <= 400;
}
);
newWin.resizeTo(400, 400);
newWin.resizeTo(600, 400);
await resizePromise;
const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);

View File

@ -0,0 +1,4 @@
[DEFAULT]
support-files =
head.js
[browser_bug1557041.js]

View File

@ -0,0 +1,48 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { BrowserTestUtils } = ChromeUtils.import(
"resource://testing-common/BrowserTestUtils.jsm"
);
// This test tends to trigger a race in the fullscreen time telemetry,
// where the fullscreen enter and fullscreen exit events (which use the
// same histogram ID) overlap. That causes TelemetryStopwatch to log an
// error.
SimpleTest.ignoreAllUncaughtExceptions(true);
add_task(async function test_identityPopupCausesFSExit() {
let url = "https://example.com/";
await BrowserTestUtils.withNewTab("about:blank", async browser => {
let loaded = BrowserTestUtils.browserLoaded(browser, false, url);
BrowserTestUtils.loadURI(browser, url);
await loaded;
let identityBox = document.getElementById("identity-box");
let identityPopup = document.getElementById("identity-popup");
info("Entering DOM fullscreen");
await changeFullscreen(browser, true);
let popupShown = BrowserTestUtils.waitForEvent(
identityPopup,
"popupshown",
true
);
let fsExit = waitForFullScreenState(browser, false);
identityBox.click();
info("Waiting for fullscreen exit and identity popup to show");
await Promise.all([fsExit, popupShown]);
ok(
identityPopup.hasAttribute("panelopen"),
"Identity popup should be open"
);
ok(!window.fullScreen, "Should not be in full-screen");
});
});

View File

@ -0,0 +1,50 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// This test makes sure that when the user presses enter in the urlbar in full
// screen, the toolbars are hidden. This should not be run on macOS because we
// don't hide the toolbars there.
"use strict";
XPCOMUtils.defineLazyModuleGetters(this, {
UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.jsm",
});
add_task(async function test() {
await BrowserTestUtils.withNewTab("about:blank", async () => {
// Do the View:FullScreen command and wait for the transition.
let onFullscreen = BrowserTestUtils.waitForEvent(window, "fullscreen");
document.getElementById("View:FullScreen").doCommand();
await onFullscreen;
// Do the Browser:OpenLocation command to show the nav toolbox and focus
// the urlbar.
let onToolboxShown = TestUtils.topicObserved(
"fullscreen-nav-toolbox",
(subject, data) => data == "shown"
);
document.getElementById("Browser:OpenLocation").doCommand();
info("Waiting for the nav toolbox to be shown");
await onToolboxShown;
// Enter a URL.
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "http://example.com/",
waitForFocus: SimpleTest.waitForFocus,
fireInputEvent: true,
});
// Press enter and wait for the nav toolbox to be hidden.
let onToolboxHidden = TestUtils.topicObserved(
"fullscreen-nav-toolbox",
(subject, data) => data == "hidden"
);
EventUtils.synthesizeKey("KEY_Enter");
info("Waiting for the nav toolbox to be hidden");
await onToolboxHidden;
Assert.ok(true, "Nav toolbox hidden");
});
});

View File

@ -0,0 +1,31 @@
const { ContentTaskUtils } = ChromeUtils.import(
"resource://testing-common/ContentTaskUtils.jsm"
);
const { ContentTask } = ChromeUtils.import(
"resource://testing-common/ContentTask.jsm"
);
function waitForFullScreenState(browser, state) {
let eventName = state
? "MozDOMFullscreen:Entered"
: "MozDOMFullscreen:Exited";
return BrowserTestUtils.waitForEvent(browser.ownerGlobal, eventName);
}
/**
* Spawns content task in browser to enter / leave fullscreen
* @param browser - Browser to use for JS fullscreen requests
* @param {Boolean} fullscreenState - true to enter fullscreen, false to leave
* @returns {Promise} - Resolves once fullscreen change is applied
*/
function changeFullscreen(browser, fullScreenState) {
let fullScreenChange = waitForFullScreenState(browser, fullScreenState);
ContentTask.spawn(browser, fullScreenState, state => {
if (state) {
content.document.body.requestFullscreen();
} else {
content.document.exitFullscreen();
}
});
return fullScreenChange;
}

View File

@ -14,7 +14,7 @@ support-files =
browser_bug479408_sample.html
browser_bug970746.xhtml
browser_star_hsts.sjs
browser_tab_dragdrop2_frame1.xul
browser_tab_dragdrop2_frame1.xhtml
browser_tab_dragdrop_embed.html
browser_web_channel.html
browser_web_channel_iframe.html

View File

@ -27,7 +27,7 @@ add_task(async function() {
let contextMenuPromise = BrowserTestUtils.waitForEvent(
contextMenu,
"popupshown"
).then(() => gContextMenuContentData.target);
);
await ContentTask.spawn(
tab.linkedBrowser,

View File

@ -37,9 +37,7 @@ add_task(async function closeLastTabInWindow() {
let windowClosedPromise = BrowserTestUtils.domWindowClosed(newWin);
expectingDialog = true;
// close tab:
document
.getAnonymousElementByAttribute(firstTab, "anonid", "close-button")
.click();
firstTab.closeButton.click();
await windowClosedPromise;
ok(!expectingDialog, "There should have been a dialog.");
ok(newWin.closed, "Window should be closed.");
@ -73,17 +71,13 @@ add_task(async function closeWindoWithSingleTabTwice() {
let firstDialogShownPromise = new Promise((resolve, reject) => {
resolveDialogPromise = resolve;
});
document
.getAnonymousElementByAttribute(firstTab, "anonid", "close-button")
.click();
firstTab.closeButton.click();
await firstDialogShownPromise;
info("Got initial dialog, now trying again");
expectingDialog = true;
wantToClose = true;
resolveDialogPromise = null;
document
.getAnonymousElementByAttribute(firstTab, "anonid", "close-button")
.click();
firstTab.closeButton.click();
await windowClosedPromise;
ok(!expectingDialog, "There should have been a dialog.");
ok(newWin.closed, "Window should be closed.");

View File

@ -34,14 +34,8 @@ add_task(async function test_content_and_chrome_selection() {
"Write something here",
"The macOS services got the selected content text"
);
gURLBar.value = "test.mozilla.org";
await gURLBar.focus();
await BrowserTestUtils.synthesizeKey(
"KEY_ArrowRight",
{ shiftKey: true, ctrlKey: true },
gBrowser.selectedBrowser
);
await gURLBar.editor.selectAll();
selectedText = DOMWindowUtils.GetSelectionAsPlaintext();
is(
selectedText,

View File

@ -6,7 +6,7 @@ add_task(async function() {
);
await SimpleTest.promiseFocus(win);
let tab = win.gBrowser.tabContainer.firstElementChild;
let tab = win.gBrowser.tabs[0];
await promiseTabLoadEvent(
tab,
getRootDirectory(gTestPath) + "test_bug462673.html"
@ -36,7 +36,7 @@ add_task(async function() {
);
await SimpleTest.promiseFocus(win);
let tab = win.gBrowser.tabContainer.firstElementChild;
let tab = win.gBrowser.tabs[0];
await promiseTabLoadEvent(
tab,
getRootDirectory(gTestPath) + "test_bug462673.html"
@ -47,7 +47,7 @@ add_task(async function() {
win.gBrowser.removeTab(tab);
ok(!win.closed, "Window stays open");
if (!win.closed) {
is(win.gBrowser.tabContainer.childElementCount, 1, "Window has one tab");
is(win.gBrowser.tabs.length, 1, "Window has one tab");
is(win.gBrowser.browsers.length, 1, "Window has one browser");
is(win.gBrowser.selectedTab, newTab, "Remaining tab is selected");
is(

View File

@ -55,8 +55,9 @@ add_task(async function test_remove_bookmark_with_tag_via_edit_bookmark() {
);
let removeNotification = PlacesTestUtils.waitForNotification(
"onItemRemoved",
(id, parentId, index, type, itemUrl) => testURL == unescape(itemUrl.spec)
"bookmark-removed",
events => events.some(event => unescape(event.url) == testURL),
"places"
);
let removeButton = document.getElementById("editBookmarkPanelRemoveButton");

View File

@ -10,7 +10,7 @@ function waitForNewWindow() {
is(
domwindow.document.location.href,
"chrome://mozapps/content/downloads/unknownContentType.xul",
"chrome://mozapps/content/downloads/unknownContentType.xhtml",
"Download page appeared"
);
resolve(domwindow);

View File

@ -2,15 +2,15 @@
// event.clipboardData.
add_task(async function() {
var textbox = document.createElement("textbox");
document.documentElement.appendChild(textbox);
var input = document.createElement("input");
document.documentElement.appendChild(input);
textbox.focus();
textbox.value = "Text";
textbox.select();
input.focus();
input.value = "Text";
input.select();
await new Promise((resolve, reject) => {
textbox.addEventListener(
input.addEventListener(
"copy",
function(event) {
event.clipboardData.setData("text/plain", "Alternate");
@ -42,10 +42,10 @@ add_task(async function() {
});
is(output, "Passed", "Paste file");
textbox.focus();
input.focus();
await new Promise((resolve, reject) => {
textbox.addEventListener(
input.addEventListener(
"paste",
function(event) {
let dt = event.clipboardData;
@ -74,7 +74,7 @@ add_task(async function() {
EventUtils.synthesizeKey("v", { accelKey: true });
});
document.documentElement.removeChild(textbox);
input.remove();
BrowserTestUtils.removeTab(tab);
});

View File

@ -114,12 +114,12 @@ add_task(async function() {
"Ctrl+Tab*2 -> Ctrl+W -> Ctrl+Shift+Tab*2 keeps the selected tab"
);
}
gBrowser.removeTab(gBrowser.tabContainer.lastElementChild);
gBrowser.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
checkTabs(2);
await ctrlTabTest([1], 1, 0);
gBrowser.removeTab(gBrowser.tabContainer.lastElementChild);
gBrowser.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
checkTabs(1);
{

View File

@ -67,14 +67,10 @@ add_task(async function() {
doCompletion();
});
// Click again:
document
.getAnonymousElementByAttribute(testTab, "anonid", "close-button")
.click();
testTab.closeButton.click();
});
// Click once:
document
.getAnonymousElementByAttribute(testTab, "anonid", "close-button")
.click();
testTab.closeButton.click();
});
await TestUtils.waitForCondition(() => !testTab.parentNode);
ok(!testTab.parentNode, "Tab should be closed completely");

View File

@ -1,4 +1,4 @@
function test() {
async function test() {
waitForExplicitFinish();
let EventUtils = {};
@ -21,13 +21,15 @@ function test() {
];
// set the valid attribute so dropping is allowed
var oldstate = gURLBar.getAttribute("pageproxystate");
gURLBar.setAttribute("pageproxystate", "valid");
var dt = EventUtils.synthesizeDragStart(
document.getElementById("identity-box"),
gURLBar.setPageProxyState("valid");
let result = await EventUtils.synthesizePlainDragAndCancel(
{
srcElement: document.getElementById("identity-box"),
},
expected
);
is(dt, null, "drag on proxy icon");
gURLBar.setAttribute("pageproxystate", oldstate);
ok(result === true, "dragging dataTransfer should be expected");
gURLBar.setPageProxyState(oldstate);
// Now, the identity information panel is opened by the proxy icon click.
// We need to close it for next tests.
EventUtils.synthesizeKey("VK_ESCAPE", {}, window);

View File

@ -526,7 +526,7 @@ function test_emitLatchedEvents(eventPrefix, initialDelta, cmd) {
}
function test_addCommand(prefName, id) {
let cmd = test_commandset.appendChild(document.createElement("command"));
let cmd = test_commandset.appendChild(document.createXULElement("command"));
cmd.setAttribute("id", id);
cmd.setAttribute("oncommand", "this.callCount++;");

View File

@ -12,9 +12,10 @@ add_task(async function() {
EventUtils
);
// Since synthesizeDrop triggers the srcElement, need to use another button.
let dragSrcElement = document.getElementById("downloads-button");
ok(dragSrcElement, "Downloads button exists");
// Since synthesizeDrop triggers the srcElement, need to use another button
// that should be visible.
let dragSrcElement = document.getElementById("sidebar-button");
ok(dragSrcElement, "Sidebar button exists");
let homeButton = document.getElementById("home-button");
ok(homeButton, "home button present");
@ -53,7 +54,7 @@ add_task(async function() {
Services.prefs.addObserver(HOMEPAGE_PREF, observer);
});
setHomepageDialog.document.documentElement.acceptDialog();
setHomepageDialog.document.getElementById("commonDialog").acceptDialog();
await setHomepagePromise;
}

View File

@ -213,9 +213,10 @@ async function drop(dragData, expectedURLs) {
EventUtils
);
// Since synthesizeDrop triggers the srcElement, need to use another button.
let dragSrcElement = document.getElementById("downloads-button");
ok(dragSrcElement, "Downloads button exists");
// Since synthesizeDrop triggers the srcElement, need to use another button
// that should be visible.
let dragSrcElement = document.getElementById("sidebar-button");
ok(dragSrcElement, "Sidebar button exists");
let newTabButton = document.getElementById("new-tab-button");
ok(newTabButton, "New Tab button exists");

View File

@ -200,9 +200,10 @@ async function drop(dragData, expectedURLs, ignoreFirstWindow = false) {
EventUtils
);
// Since synthesizeDrop triggers the srcElement, need to use another button.
let dragSrcElement = document.getElementById("downloads-button");
ok(dragSrcElement, "Downloads button exists");
// Since synthesizeDrop triggers the srcElement, need to use another button
// that should be visible.
let dragSrcElement = document.getElementById("sidebar-button");
ok(dragSrcElement, "Sidebar button exists");
let newWindowButton = document.getElementById("new-window-button");
ok(newWindowButton, "New Window button exists");

View File

@ -19,10 +19,9 @@ const PAGE = `data:text/html,<a id="target" href="%23" onclick="window.open('htt
*/
function promiseNewWindow() {
return new Promise(resolve => {
let observer = (subject, topic, data) => {
let observer = (win, topic, data) => {
if (topic == "domwindowopened") {
Services.ww.unregisterNotification(observer);
let win = subject.QueryInterface(Ci.nsIDOMWindow);
win.addEventListener(
"load",
function() {

View File

@ -6,7 +6,7 @@ MockFilePicker.init(window);
const SAVE_PER_SITE_PREF = "browser.download.lastDir.savePerSite";
const ALWAYS_DOWNLOAD_DIR_PREF = "browser.download.useDownloadDir";
const UCT_URI = "chrome://mozapps/content/downloads/unknownContentType.xul";
const UCT_URI = "chrome://mozapps/content/downloads/unknownContentType.xhtml";
/* import-globals-from ../../../../../toolkit/content/tests/browser/common/mockTransfer.js */
Services.scriptloader.loadSubScript(
@ -76,7 +76,9 @@ function triggerSave(aWindow, aCallback) {
function continueDownloading() {
for (let win of Services.wm.getEnumerator("")) {
if (win.location && win.location.href == UCT_URI) {
win.document.documentElement._fireButtonEvent("accept");
win.document
.getElementById("unknownContentType")
._fireButtonEvent("accept");
win.close();
return;
}

View File

@ -1,7 +1,7 @@
"use strict";
const ROOT = getRootDirectory(gTestPath);
const URI = ROOT + "browser_tab_dragdrop2_frame1.xul";
const URI = ROOT + "browser_tab_dragdrop2_frame1.xhtml";
// Load the test page (which runs some child popup tests) in a new window.
// After the tests were run, tear off the tab into a new window and run popup

View File

@ -68,6 +68,7 @@ function popupShown(event)
if (waitSteps > 0 && navigator.platform.includes("Linux") &&
panel.screenY == 210) {
waitSteps--;
/* eslint-disable mozilla/no-arbitrary-setTimeout */
setTimeout(popupShown, 10, event);
return;
}
@ -90,7 +91,7 @@ function createPanel(attrs)
button.width = 120;
button.height = 40;
button.setAttribute("style", "appearance: none; border: 0; margin: 0;");
panel.setAttribute("style", "-moz-appearance: none; border: 0; margin: 0;");
panel.setAttribute("style", "appearance: none; border: 0; margin: 0;");
return document.documentElement.appendChild(panel);
}

View File

@ -676,6 +676,11 @@ function compareFocusResults() {
? browser1.contentWindow
: browser2.contentWindow;
}
if (_expectedWindow == "main-window") {
// The browser window's body doesn't have an id set usually - set one now
// so it can be used for id comparisons below.
matchWindow.document.body.id = "main-window-body";
}
var focusedElement = fm.focusedElement;
is(
@ -698,13 +703,7 @@ function compareFocusResults() {
is(matchWindow.document.hasFocus(), true, currentTestName + " hasFocus");
var expectedActive = _expectedElement;
if (!expectedActive) {
// Documents that have a XUL document element currently have a different
// active element behavior than regular HTML documents. This test will
// need to be updated when bug 1492582 is fixed.
expectedActive =
matchWindow.document.documentElement instanceof XULElement
? "main-window"
: getId(matchWindow.document.body);
expectedActive = getId(matchWindow.document.body);
}
is(
getId(matchWindow.document.activeElement),

View File

@ -51,11 +51,7 @@ add_task(async function() {
info("Waiting for the load in that tab to finish");
await secondTabLoadedPromise;
let closeBtn = document.getAnonymousElementByAttribute(
secondTab,
"anonid",
"close-button"
);
let closeBtn = secondTab.closeButton;
info("closing second tab (which will self-close in beforeunload)");
closeBtn.click();
ok(

View File

@ -3,21 +3,20 @@ function test() {
BrowserTestUtils.addTab(gBrowser);
BrowserTestUtils.addTab(gBrowser);
var tabs = gBrowser.tabs;
var owner;
is(tabs.length, 4, "4 tabs are open");
is(gBrowser.tabs.length, 4, "4 tabs are open");
owner = gBrowser.selectedTab = tabs[2];
owner = gBrowser.selectedTab = gBrowser.tabs[2];
BrowserOpenTab();
is(gBrowser.selectedTab, tabs[4], "newly opened tab is selected");
is(gBrowser.selectedTab, gBrowser.tabs[4], "newly opened tab is selected");
gBrowser.removeCurrentTab();
is(gBrowser.selectedTab, owner, "owner is selected");
owner = gBrowser.selectedTab;
BrowserOpenTab();
gBrowser.selectedTab = tabs[1];
gBrowser.selectedTab = tabs[4];
gBrowser.selectedTab = gBrowser.tabs[1];
gBrowser.selectedTab = gBrowser.tabs[4];
gBrowser.removeCurrentTab();
isnot(
gBrowser.selectedTab,
@ -32,10 +31,10 @@ function test() {
is(
gBrowser.selectedTab,
owner,
"owner relatitionship persists when tab is moved"
"owner relationship persists when tab is moved"
);
while (tabs.length > 1) {
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
}

View File

@ -27,7 +27,7 @@ add_task(async function() {
let win = await waitForNewWindow();
is(
win.location,
"chrome://mozapps/content/downloads/unknownContentType.xul",
"chrome://mozapps/content/downloads/unknownContentType.xhtml",
"Should have seen the unknown content dialog."
);
is(gBrowser.contentTitle, "Test Page", "Should still have the right title.");

View File

@ -1,6 +1,8 @@
[DEFAULT]
support-files = head.js
[browser_popup_keyNav.js]
support-files = focusableContent.html
[browser_toolbarButtonKeyPress.js]
[browser_toolbarKeyNav.js]
support-files = !/browser/base/content/test/permissions/permissions.html

View File

@ -0,0 +1,49 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_PATH = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"http://example.com"
);
/**
* Keyboard navigation has some edgecases in popups because
* there is no tabstrip or menubar. Check that tabbing forward
* and backward to/from the content document works:
*/
add_task(async function test_popup_keynav() {
await SpecialPowers.pushPrefEnv({
set: [
["browser.toolbars.keyboard_navigation", true],
["accessibility.tabfocus", 7],
],
});
const kURL = TEST_PATH + "focusableContent.html";
await BrowserTestUtils.withNewTab(kURL, async browser => {
let windowPromise = BrowserTestUtils.waitForNewWindow({
url: kURL,
});
SpecialPowers.spawn(browser, [], () => {
content.window.open(
content.location.href,
"_blank",
"height=500,width=500,menubar=no,toolbar=no,status=1,resizable=1"
);
});
let win = await windowPromise;
let hamburgerButton = win.document.getElementById("PanelUI-menu-button");
forceFocus(hamburgerButton);
await expectFocusAfterKey("Tab", win.gBrowser.selectedBrowser, false, win);
// Focus the button inside the webpage.
EventUtils.synthesizeKey("KEY_Tab", {}, win);
// Focus the first item in the URL bar
let firstButton = win.document
.getElementById("urlbar-container")
.querySelector("toolbarbutton,[role=button]");
await expectFocusAfterKey("Tab", firstButton, false, win);
await BrowserTestUtils.closeWindow(win);
});
});

View File

@ -19,44 +19,6 @@ function resetToolbarWithoutDevEditionButtons() {
CustomizableUI.removeWidgetFromArea("developer-button");
}
async function expectFocusAfterKey(
aKey,
aFocus,
aAncestorOk = false,
aWindow = window
) {
let res = aKey.match(/^(Shift\+)?(?:(.)|(.+))$/);
let shift = Boolean(res[1]);
let key;
if (res[2]) {
key = res[2]; // Character.
} else {
key = "KEY_" + res[3]; // Tab, ArrowRight, etc.
}
let expected;
let friendlyExpected;
if (typeof aFocus == "string") {
expected = aWindow.document.getElementById(aFocus);
friendlyExpected = aFocus;
} else {
expected = aFocus;
if (aFocus == aWindow.gURLBar.inputField) {
friendlyExpected = "URL bar input";
} else if (aFocus == aWindow.gBrowser.selectedBrowser) {
friendlyExpected = "Web document";
}
}
info("Listening on item " + (expected.id || expected.className));
let focused = BrowserTestUtils.waitForEvent(expected, "focus", aAncestorOk);
EventUtils.synthesizeKey(key, { shiftKey: shift }, aWindow);
let receivedEvent = await focused;
info(
"Got focus on item: " +
(receivedEvent.target.id || receivedEvent.target.className)
);
ok(true, friendlyExpected + " focused after " + aKey + " pressed");
}
function startFromUrlBar(aWindow = window) {
aWindow.gURLBar.focus();
is(
@ -373,3 +335,65 @@ add_task(async function testPanelCloseRestoresFocus() {
);
});
});
// Test navigation by typed characters.
add_task(async function testCharacterNavigation() {
await BrowserTestUtils.withNewTab("https://example.com", async function() {
await waitUntilReloadEnabled();
startFromUrlBar();
await expectFocusAfterKey("Tab", "pageActionButton");
await expectFocusAfterKey("h", "home-button");
// There's no button starting with "hs", so pressing s should do nothing.
EventUtils.synthesizeKey("s");
is(
document.activeElement.id,
"home-button",
"home-button still focused after s pressed"
);
// Escape should reset the search.
EventUtils.synthesizeKey("KEY_Escape");
// Now that the search is reset, pressing s should focus Save to Pocket.
await expectFocusAfterKey("s", "pocket-button");
// Pressing i makes the search "si", so it should focus Sidebars.
await expectFocusAfterKey("i", "sidebar-button");
// Reset the search.
EventUtils.synthesizeKey("KEY_Escape");
await expectFocusAfterKey("s", "pocket-button");
// Pressing s again should find the next button starting with s: Sidebars.
await expectFocusAfterKey("s", "sidebar-button");
});
});
// Test that toolbar character navigation doesn't trigger in PanelMultiView for
// a panel anchored to the toolbar.
// We do this by opening the Library menu and ensuring that pressing s
// does nothing.
// This test should be removed if PanelMultiView implements character
// navigation.
add_task(async function testCharacterInPanelMultiView() {
let button = document.getElementById("library-button");
forceFocus(button);
let view = document.getElementById("appMenu-libraryView");
let focused = BrowserTestUtils.waitForEvent(view, "focus", true);
EventUtils.synthesizeKey(" ");
let focusEvt = await focused;
ok(true, "Focus inside Library menu after toolbar button pressed");
EventUtils.synthesizeKey("s");
is(document.activeElement, focusEvt.target, "s inside panel does nothing");
let hidden = BrowserTestUtils.waitForEvent(document, "popuphidden", true);
view.closest("panel").hidePopup();
await hidden;
});
// Test tab stops after the search bar is added.
add_task(async function testTabStopsAfterSearchBarAdded() {
await SpecialPowers.pushPrefEnv({
set: [["browser.search.widget.inNavBar", 1]],
});
await withNewBlankTab(async function() {
startFromUrlBar();
await expectFocusAfterKey("Tab", "searchbar", true);
await expectFocusAfterKey("Tab", "library-button");
});
await SpecialPowers.popPrefEnv();
});

View File

@ -0,0 +1 @@
<button>Just a button here to have something focusable.</button>

View File

@ -15,3 +15,41 @@ function forceFocus(aElem) {
aElem.focus();
aElem.removeAttribute("tabindex");
}
async function expectFocusAfterKey(
aKey,
aFocus,
aAncestorOk = false,
aWindow = window
) {
let res = aKey.match(/^(Shift\+)?(?:(.)|(.+))$/);
let shift = Boolean(res[1]);
let key;
if (res[2]) {
key = res[2]; // Character.
} else {
key = "KEY_" + res[3]; // Tab, ArrowRight, etc.
}
let expected;
let friendlyExpected;
if (typeof aFocus == "string") {
expected = aWindow.document.getElementById(aFocus);
friendlyExpected = aFocus;
} else {
expected = aFocus;
if (aFocus == aWindow.gURLBar.inputField) {
friendlyExpected = "URL bar input";
} else if (aFocus == aWindow.gBrowser.selectedBrowser) {
friendlyExpected = "Web document";
}
}
info("Listening on item " + (expected.id || expected.className));
let focused = BrowserTestUtils.waitForEvent(expected, "focus", aAncestorOk);
EventUtils.synthesizeKey(key, { shiftKey: shift }, aWindow);
let receivedEvent = await focused;
info(
"Got focus on item: " +
(receivedEvent.target.id || receivedEvent.target.className)
);
ok(true, friendlyExpected + " focused after " + aKey + " pressed");
}

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