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

View File

@ -119,6 +119,7 @@ class LinkHandlerChild extends ActorChild {
case "apple-touch-icon-precomposed": case "apple-touch-icon-precomposed":
case "fluid-icon": case "fluid-icon":
isRichIcon = true; isRichIcon = true;
// fall through
case "icon": case "icon":
if (iconAdded || link.hasAttribute("mask")) { if (iconAdded || link.hasAttribute("mask")) {
// Masked icons are not supported yet. // 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 = const PREF_SERVICES_SETTINGS_LAST_FETCHED =
"services.settings.last_update_seconds"; "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, { let formatter = new Services.intl.DateTimeFormat(undefined, {
dateStyle: "long", dateStyle: "long",

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@
#endif #endif
#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) // Enables some extra Extension System Logging (can reduce performance)
pref("extensions.logging.enabled", false); 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.remote", true);
pref("extensions.webextensions.background-delayed-startup", true); pref("extensions.webextensions.background-delayed-startup", true);
// Disable extensionStorage storage actor by default
pref("devtools.storage.extensionStorage.enabled", false);
// Dictionary download preference // Dictionary download preference
pref("browser.dictionaries.download.url", "data:text/plain,"); pref("browser.dictionaries.download.url", "data:text/plain,");
@ -199,17 +202,6 @@ pref("browser.warnOnQuit", true);
pref("browser.fullscreen.autohide", true); pref("browser.fullscreen.autohide", true);
pref("browser.overlink-delay", 80); 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 // Whether using `ctrl` when hitting return/enter in the URL bar
// (or clicking 'go') should prefix 'www.' and suffix // (or clicking 'go') should prefix 'www.' and suffix
// browser.fixup.alternate.suffix to the URL bar value prior to // 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.enabled", false);
pref("browser.urlbar.usepreloadedtopurls.expire_days", 14); pref("browser.urlbar.usepreloadedtopurls.expire_days", 14);
// Enable the new Address Bar code. pref("browser.urlbar.update1", false);
pref("browser.urlbar.quantumbar", true); pref("browser.urlbar.update1.expandTextOnFocus", false);
pref("browser.urlbar.openViewOnFocus", false);
pref("browser.altClickSave", false); pref("browser.altClickSave", false);
@ -325,10 +319,6 @@ pref("browser.search.hiddenOneOffs", "");
// Mirrors whether the search-container widget is in the navigation toolbar. // Mirrors whether the search-container widget is in the navigation toolbar.
pref("browser.search.widget.inNavBar", true); pref("browser.search.widget.inNavBar", true);
#ifndef RELEASE_OR_BETA
pref("browser.search.reset.enabled", true);
#endif
pref("browser.sessionhistory.max_entries", 50); pref("browser.sessionhistory.max_entries", 50);
// Built-in default permissions. // 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.enabled", true);
pref("services.sync.prefs.sync.browser.newtabpage.pinned", 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.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.homepage", true);
pref("services.sync.prefs.sync.browser.startup.page", true); pref("services.sync.prefs.sync.browser.startup.page", true);
pref("services.sync.prefs.sync.browser.tabs.loadInBackground", 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.enabled", false);
pref("services.sync.prefs.sync.privacy.fuzzyfox.clockgrainus", 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.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.resistFingerprinting", true);
pref("services.sync.prefs.sync.privacy.reduceTimerPrecision", true); pref("services.sync.prefs.sync.privacy.reduceTimerPrecision", true);
pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.microseconds", 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.visible", true);
pref("media.gmp-gmpopenh264.enabled", 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. // Set Firefox to block autoplay, asking for permission by default.
pref("media.autoplay.default", 1); // 0=Allowed, 1=Blocked, 5=All Blocked 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 // Enable blocking access to storage from tracking resources only in nightly
// and early beta. By default the value is 0: BEHAVIOR_ACCEPT // and early beta. By default the value is 0: BEHAVIOR_ACCEPT
pref("network.cookie.cookieBehavior", 4 /* BEHAVIOR_REJECT_TRACKER */); 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 #endif
pref("dom.storage_access.enabled", true); 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.showBlockedLabels", true);
pref("browser.contentblocking.control-center.ui.showAllowedLabels", false); 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. // Enables the new Protections Panel.
#ifdef NIGHTLY_BUILD #ifdef NIGHTLY_BUILD
pref("browser.protections_panel.enabled", true); pref("browser.protections_panel.enabled", true);
@ -1472,19 +1416,14 @@ pref("privacy.usercontext.about_newtab_segregation.enabled", true);
#ifdef NIGHTLY_BUILD #ifdef NIGHTLY_BUILD
pref("privacy.userContext.enabled", true); pref("privacy.userContext.enabled", true);
pref("privacy.userContext.ui.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 #else
pref("privacy.userContext.enabled", false); pref("privacy.userContext.enabled", false);
pref("privacy.userContext.ui.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 #endif
pref("privacy.userContext.extension", ""); 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 // Start the browser in e10s mode
pref("browser.tabs.remote.autostart", true); 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.emailMe", false);
pref("browser.tabs.crashReporting.email", ""); 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) #if defined(XP_WIN)
// Allows us to deprioritize the processes of background tabs at an OS level // Allows us to deprioritize the processes of background tabs at an OS level
pref("dom.ipc.processPriorityManager.enabled", true); pref("dom.ipc.processPriorityManager.enabled", true);
#endif #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: // Don't limit how many nodes we care about on desktop:
pref("reader.parse-node-limit", 0); 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.enabled", false);
pref("identity.fxaccounts.toolbar.accessed", 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 // Toolbox preferences
pref("devtools.toolbox.footer.height", 250); pref("devtools.toolbox.footer.height", 250);
pref("devtools.toolbox.sidebar.width", 500); 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-frames.enabled", true);
pref("devtools.command-button-splitconsole.enabled", true); pref("devtools.command-button-splitconsole.enabled", true);
pref("devtools.command-button-paintflashing.enabled", false); 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-responsive.enabled", true);
pref("devtools.command-button-screenshot.enabled", false); pref("devtools.command-button-screenshot.enabled", false);
pref("devtools.command-button-rulers.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); pref("devtools.netmonitor.features.webSockets", false);
#endif #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 // Enable the Storage Inspector
pref("devtools.storage.enabled", true); pref("devtools.storage.enabled", true);
@ -1879,9 +1774,6 @@ pref("devtools.styleeditor.transitions", true);
pref("devtools.screenshot.clipboard.enabled", false); pref("devtools.screenshot.clipboard.enabled", false);
pref("devtools.screenshot.audio.enabled", true); pref("devtools.screenshot.audio.enabled", true);
// Enable Scratchpad
pref("devtools.scratchpad.enabled", false);
// Make sure the DOM panel is hidden by default // Make sure the DOM panel is hidden by default
pref("devtools.dom.enabled", false); pref("devtools.dom.enabled", false);
@ -1932,13 +1824,6 @@ pref("devtools.webconsole.timestampMessages", false);
pref("devtools.webconsole.sidebarToggle", false); pref("devtools.webconsole.sidebarToggle", false);
#endif #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. // Saved editor mode state in the console.
pref("devtools.webconsole.input.editor", false); pref("devtools.webconsole.input.editor", false);
@ -2000,13 +1885,6 @@ pref("devtools.responsive.metaViewport.enabled", false);
// The user agent of the viewport. // The user agent of the viewport.
pref("devtools.responsive.userAgent", ""); 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. // Show the custom user agent input in Nightly builds.
#if defined(NIGHTLY_BUILD) #if defined(NIGHTLY_BUILD)
pref("devtools.responsive.showUserAgentInput", true); 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 * 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/. */ * 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. // if MOZ_UPDATER is defined.
/* import-globals-from aboutDialog.js */ /* 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 * 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/. */ * 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. // if MOZ_UPDATER is defined.
/* import-globals-from aboutDialog.js */ /* import-globals-from aboutDialog.js */

View File

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

View File

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

View File

@ -19,7 +19,7 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <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> <title>&loadError.label;</title>
<link rel="stylesheet" href="chrome://browser/skin/aboutNetError.css" type="text/css" media="all" /> <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 <!-- 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"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <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> <title data-l10n-id="restart-required-title"></title>
<link rel="stylesheet" type="text/css" media="all" <link rel="stylesheet" type="text/css" media="all"
href="chrome://browser/skin/aboutRestartRequired.css"/> href="chrome://browser/skin/aboutRestartRequired.css"/>

View File

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

View File

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

View File

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

View File

@ -343,6 +343,8 @@ var FullScreen = {
document.addEventListener("keypress", this._keyToggleCallback); document.addEventListener("keypress", this._keyToggleCallback);
document.addEventListener("popupshown", this._setPopupOpen); document.addEventListener("popupshown", this._setPopupOpen);
document.addEventListener("popuphidden", this._setPopupOpen); document.addEventListener("popuphidden", this._setPopupOpen);
gURLBar.controller.addQueryListener(this);
// In DOM fullscreen mode, we hide toolbars with CSS // In DOM fullscreen mode, we hide toolbars with CSS
if (!document.fullscreenElement) { if (!document.fullscreenElement) {
this.hideNavToolbox(true); this.hideNavToolbox(true);
@ -489,6 +491,7 @@ var FullScreen = {
document.removeEventListener("keypress", this._keyToggleCallback); document.removeEventListener("keypress", this._keyToggleCallback);
document.removeEventListener("popupshown", this._setPopupOpen); document.removeEventListener("popupshown", this._setPopupOpen);
document.removeEventListener("popuphidden", 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. // 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 // 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. // toggles chrome when moving mouse to the top, it doesn't go away again.
let target = aEvent.originalTarget;
if (target.localName == "tooltip") {
return;
}
if ( if (
aEvent.type == "popupshown" && aEvent.type == "popupshown" &&
!FullScreen._isChromeCollapsed && !FullScreen._isChromeCollapsed &&
aEvent.target.localName != "tooltip" && target.getAttribute("nopreventnavboxhide") != "true"
aEvent.target.localName != "window" &&
aEvent.target.getAttribute("nopreventnavboxhide") != "true"
) { ) {
FullScreen._isPopupOpen = true; FullScreen._isPopupOpen = true;
} else if ( } else if (aEvent.type == "popuphidden") {
aEvent.type == "popuphidden" &&
aEvent.target.localName != "tooltip" &&
aEvent.target.localName != "window"
) {
FullScreen._isPopupOpen = false; FullScreen._isPopupOpen = false;
// Try again to hide toolbar when we close the popup. // Try again to hide toolbar when we close the popup.
FullScreen.hideNavToolbox(true); 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() { get navToolboxHidden() {
return this._isChromeCollapsed; return this._isChromeCollapsed;
}, },
@ -644,10 +658,10 @@ var FullScreen = {
} }
}, 0); }, 0);
}); });
window.removeEventListener("keypress", retryHideNavToolbox); window.removeEventListener("keydown", retryHideNavToolbox);
window.removeEventListener("click", retryHideNavToolbox); window.removeEventListener("click", retryHideNavToolbox);
}; };
window.addEventListener("keypress", retryHideNavToolbox); window.addEventListener("keydown", retryHideNavToolbox);
window.addEventListener("click", retryHideNavToolbox); window.addEventListener("click", retryHideNavToolbox);
return; return;
} }

View File

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

View File

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

View File

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

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 #endif
</commandset> </commandset>
#include ../../components/places/content/placesCommands.inc.xul #include ../../components/places/content/placesCommands.inc.xhtml
<keyset id="mainKeyset"> <keyset id="mainKeyset">
<key id="key_newNavigator" <key id="key_newNavigator"

View File

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

View File

@ -35,6 +35,13 @@ var gIdentityHandler = {
*/ */
_isSecureInternalUI: false, _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 * nsITransportSecurityInfo metadata provided by gBrowser.securityUI the last
* time the identity UI was updated, or null if the connection is not secure. * 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 * RegExp used to decide if an about url should be shown as being part of
* the browser UI. * 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; 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 // 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 // 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 // document. In this case, don't upgrade the security state in the UI
@ -342,14 +361,6 @@ var gIdentityHandler = {
openPreferences("privacy-permissions"); openPreferences("privacy-permissions");
}, },
recordClick(object) {
Services.telemetry.recordEvent(
"security.ui.identitypopup",
"click",
object
);
},
/** /**
* Handler for mouseclicks on the "More Information" button in the * Handler for mouseclicks on the "More Information" button in the
* "identity-popup" panel. * "identity-popup" panel.
@ -372,12 +383,6 @@ var gIdentityHandler = {
}, },
disableMixedContentProtection() { 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 // Reload the page with the content unblocked
BrowserReloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT); BrowserReloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT);
PanelMultiView.hidePopup(this._identityPopup); PanelMultiView.hidePopup(this._identityPopup);
@ -458,6 +463,7 @@ var gIdentityHandler = {
// the documentation of the individual properties for details. // the documentation of the individual properties for details.
this.setURI(uri); this.setURI(uri);
this._secInfo = gBrowser.securityUI.secInfo; this._secInfo = gBrowser.securityUI.secInfo;
this._isSecureContext = gBrowser.securityUI.isSecureContext;
// Then, update the user interface with the available data. // Then, update the user interface with the available data.
this.refreshIdentityBlock(); this.refreshIdentityBlock();
@ -587,7 +593,7 @@ var gIdentityHandler = {
if (this._uriHasHost && this._isEV) { if (this._uriHasHost && this._isEV) {
return "verifiedIdentity"; return "verifiedIdentity";
} }
if (this._uriHasHost && this._isSecure) { if (this._uriHasHost && this._isSecureConnection) {
return "verifiedDomain"; return "verifiedDomain";
} }
return "unknownIdentity"; return "unknownIdentity";
@ -606,6 +612,20 @@ var gIdentityHandler = {
return !issuerCert.isBuiltInRoot; 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. * Updates the identity block user interface with the data from this object.
*/ */
@ -614,16 +634,28 @@ var gIdentityHandler = {
return; 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 icon_label = "";
let tooltip = ""; let tooltip = "";
let icon_country_label = ""; let icon_country_label = "";
let icon_labels_dir = "ltr"; let icon_labels_dir = "ltr";
if (this._isSecureInternalUI) { if (this._isSecureInternalUI) {
// This is a secure internal Firefox page.
this._identityBox.className = "chromeUI"; this._identityBox.className = "chromeUI";
let brandBundle = document.getElementById("bundle_brand"); let brandBundle = document.getElementById("bundle_brand");
icon_label = brandBundle.getString("brandShorterName"); icon_label = brandBundle.getString("brandShorterName");
} else if (this._uriHasHost && this._isEV) { } else if (this._uriHasHost && this._isEV) {
// This is a secure connection with EV.
this._identityBox.className = "verifiedIdentity"; this._identityBox.className = "verifiedIdentity";
if (this._isMixedActiveContentBlocked) { if (this._isMixedActiveContentBlocked) {
this._identityBox.classList.add("mixedActiveBlocked"); this._identityBox.classList.add("mixedActiveBlocked");
@ -654,13 +686,15 @@ var gIdentityHandler = {
: "ltr"; : "ltr";
} }
} else if (this._pageExtensionPolicy) { } else if (this._pageExtensionPolicy) {
// This is a WebExtension page.
this._identityBox.className = "extensionPage"; this._identityBox.className = "extensionPage";
let extensionName = this._pageExtensionPolicy.name; let extensionName = this._pageExtensionPolicy.name;
icon_label = gNavigatorBundle.getFormattedString( icon_label = gNavigatorBundle.getFormattedString(
"identity.extension.label", "identity.extension.label",
[extensionName] [extensionName]
); );
} else if (this._uriHasHost && this._isSecure) { } else if (this._uriHasHost && this._isSecureConnection) {
// This is a secure connection.
this._identityBox.className = "verifiedDomain"; this._identityBox.className = "verifiedDomain";
if (this._isMixedActiveContentBlocked) { if (this._isMixedActiveContentBlocked) {
this._identityBox.classList.add("mixedActiveBlocked"); this._identityBox.classList.add("mixedActiveBlocked");
@ -672,46 +706,45 @@ var gIdentityHandler = {
[this.getIdentityData().caOrg] [this.getIdentityData().caOrg]
); );
} }
} else if (!this._uriHasHost) { } else if (this._isBrokenConnection) {
// This is a secure connection, but something is wrong.
this._identityBox.className = "unknownIdentity"; 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 ( } else if (
gBrowser.selectedBrowser.documentURI && this._isSecureContext ||
(gBrowser.selectedBrowser.documentURI.scheme == "about" || (gBrowser.selectedBrowser.documentURI &&
gBrowser.selectedBrowser.documentURI.scheme == "chrome") (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"; this._identityBox.className = "unknownIdentity";
} else { } else {
if (this._isBroken) { // This is an insecure connection.
this._identityBox.className = "unknownIdentity"; let warnOnInsecure =
this._insecureConnectionIconEnabled ||
(this._insecureConnectionIconPBModeEnabled &&
PrivateBrowsingUtils.isWindowPrivate(window));
let className = warnOnInsecure ? "notSecure" : "unknownIdentity";
this._identityBox.className = className;
if (this._isMixedActiveContentLoaded) { let warnTextOnInsecure =
this._identityBox.classList.add("mixedActiveContent"); this._insecureConnectionTextEnabled ||
} else if (this._isMixedActiveContentBlocked) { (this._insecureConnectionTextPBModeEnabled &&
this._identityBox.classList.add( PrivateBrowsingUtils.isWindowPrivate(window));
"mixedDisplayContentLoadedActiveBlocked" if (warnTextOnInsecure) {
); icon_label = gNavigatorBundle.getString("identity.notSecure.label");
} else if (this._isMixedPassiveContentLoaded) { this._identityBox.classList.add("notSecureText");
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");
}
} }
if (this._hasInsecureLoginForms) { if (this._hasInsecureLoginForms) {
// Insecure login forms can only be present on "unknown identity" // Insecure login forms can only be present on "unknown identity"
@ -854,7 +887,7 @@ var gIdentityHandler = {
connection = "secure-ev"; connection = "secure-ev";
} else if (this._isCertUserOverridden) { } else if (this._isCertUserOverridden) {
connection = "secure-cert-user-overridden"; connection = "secure-cert-user-overridden";
} else if (this._isSecure) { } else if (this._isSecureConnection) {
connection = "secure"; connection = "secure";
customRoot = this._hasCustomRoot(); customRoot = this._hasCustomRoot();
} }
@ -882,7 +915,7 @@ var gIdentityHandler = {
// cipher. // cipher.
let ciphers = ""; let ciphers = "";
if ( if (
this._isBroken && this._isBrokenConnection &&
!this._isMixedActiveContentLoaded && !this._isMixedActiveContentLoaded &&
!this._isMixedPassiveContentLoaded !this._isMixedPassiveContentLoaded
) { ) {
@ -906,7 +939,7 @@ var gIdentityHandler = {
updateAttribute(element, "loginforms", loginforms); updateAttribute(element, "loginforms", loginforms);
updateAttribute(element, "ciphers", ciphers); updateAttribute(element, "ciphers", ciphers);
updateAttribute(element, "mixedcontent", mixedcontent); updateAttribute(element, "mixedcontent", mixedcontent);
updateAttribute(element, "isbroken", this._isBroken); updateAttribute(element, "isbroken", this._isBrokenConnection);
updateAttribute(element, "customroot", customRoot); updateAttribute(element, "customroot", customRoot);
} }
@ -917,7 +950,7 @@ var gIdentityHandler = {
let owner = ""; let owner = "";
// Fill in the CA name if we have a valid TLS certificate. // 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; verifier = this._identityIconLabels.tooltipText;
} }
@ -957,8 +990,6 @@ var gIdentityHandler = {
// Update per-site permissions section. // Update per-site permissions section.
this.updateSitePermissions(); this.updateSitePermissions();
ContentBlocking.toggleReportBreakageButton();
}, },
setURI(uri) { setURI(uri) {
@ -1034,6 +1065,40 @@ var gIdentityHandler = {
return; 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 // Make sure that the display:none style we set in xul is removed now that
// the popup is actually needed // the popup is actually needed
this._identityPopup.hidden = false; this._identityPopup.hidden = false;
@ -1058,12 +1123,6 @@ var gIdentityHandler = {
if (event.target == this._identityPopup) { if (event.target == this._identityPopup) {
window.addEventListener("focus", this, true); window.addEventListener("focus", this, true);
} }
Services.telemetry.recordEvent(
"security.ui.identitypopup",
"open",
"identity_popup"
);
}, },
onPopupHidden(event) { onPopupHidden(event) {
@ -1124,11 +1183,7 @@ var gIdentityHandler = {
let ctx = canvas.getContext("2d"); let ctx = canvas.getContext("2d");
ctx.font = `${14 * scale}px sans-serif`; ctx.font = `${14 * scale}px sans-serif`;
ctx.fillText(`${value}`, 20 * scale, 14 * scale); ctx.fillText(`${value}`, 20 * scale, 14 * scale);
let tabIcon = document.getAnonymousElementByAttribute( let tabIcon = gBrowser.selectedTab.iconImage;
gBrowser.selectedTab,
"anonid",
"tab-icon-image"
);
let image = new Image(); let image = new Image();
image.src = tabIcon.src; image.src = tabIcon.src;
ctx.drawImage(image, 0, 0, 16 * scale, 16 * scale); ctx.drawImage(image, 0, 0, 16 * scale, 16 * scale);
@ -1139,6 +1194,9 @@ var gIdentityHandler = {
dt.setData("text/plain", value); dt.setData("text/plain", value);
dt.setData("text/html", htmlString); dt.setData("text/html", htmlString);
dt.setDragImage(canvas, 16, 16); dt.setDragImage(canvas, 16, 16);
// Don't cover potential drop targets on the toolbars or in content.
gURLBar.view.close();
}, },
onLocationChange() { onLocationChange() {
@ -1249,7 +1307,10 @@ var gIdentityHandler = {
} else { } else {
img.classList.add(aPermission.id + "-icon"); 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"); img.classList.add("blocked-permission-icon");
} }

View File

@ -150,6 +150,8 @@ var gSync = {
return; return;
} }
MozXULElement.insertFTLIfNeeded("browser/sync.ftl");
this._generateNodeGetters(); this._generateNodeGetters();
// Label for the sync buttons. // Label for the sync buttons.
@ -158,11 +160,8 @@ var gSync = {
// setting this._initialized, so we don't attempt to remove observers. // setting this._initialized, so we don't attempt to remove observers.
return; 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), // 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). // (see bug 1384856).
// maybeUpdateUIState() also optimizes for this - if we should be in the // maybeUpdateUIState() also optimizes for this - if we should be in the
// "setup sync" state, that function assumes we are already in it and // "setup sync" state, that function assumes we are already in it and
@ -548,7 +547,7 @@ var gSync = {
}, },
updateSyncStatus(state) { updateSyncStatus(state) {
let syncNow = document.getElementById("PanelUI-remotetabs-syncnow"); let syncNow = document.querySelector(".syncNowBtn");
const syncingUI = syncNow.getAttribute("syncstatus") == "active"; const syncingUI = syncNow.getAttribute("syncstatus") == "active";
if (state.syncing != syncingUI) { if (state.syncing != syncingUI) {
// Do we need to update the UI? // Do we need to update the UI?
@ -1033,26 +1032,11 @@ var gSync = {
onActivityStart() { onActivityStart() {
clearTimeout(this._syncAnimationTimer); clearTimeout(this._syncAnimationTimer);
this._syncStartTime = Date.now(); this._syncStartTime = Date.now();
document.querySelectorAll(".syncNowBtn").forEach(el => {
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 => {
el.setAttribute("syncstatus", "active"); el.setAttribute("syncstatus", "active");
el.setAttribute("disabled", "true"); el.setAttribute("disabled", "true");
document.l10n.setAttributes(el, el.getAttribute("syncinglabel"));
}); });
remotetabsSyncNowEl.setAttribute("label", label);
fxaMenuSyncNowEl.setAttribute(
"label",
fxaMenuSyncNowEl.getAttribute("syncinglabel")
);
}, },
_onActivityStop() { _onActivityStop() {
@ -1060,16 +1044,10 @@ var gSync = {
return; return;
} }
let label = this.syncStrings.GetStringFromName("syncnow.label"); document.querySelectorAll(".syncNowBtn").forEach(el => {
let syncElements = [
document.getElementById("PanelUI-remotetabs-syncnow"),
document.getElementById("PanelUI-fxa-menu-syncnow-button"),
];
syncElements.forEach(el => {
el.removeAttribute("syncstatus"); el.removeAttribute("syncstatus");
el.removeAttribute("disabled"); el.removeAttribute("disabled");
el.setAttribute("label", label); document.l10n.setAttributes(el, "fxa-toolbar-sync-now");
}); });
Services.obs.notifyObservers(null, "test:browser-sync:activity-stop"); 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 // doSync forces a sync - it *does not* return a promise as it is called
// via the various UI components. // via the various UI components.
doSync() { doSync() {
@ -1191,14 +1217,13 @@ var gSync = {
tooltiptext = this.formatLastSyncDate(state.lastSync); tooltiptext = this.formatLastSyncDate(state.lastSync);
} }
if (this.appMenuLabel) { document.querySelectorAll(".syncNowBtn").forEach(el => {
let syncNow = document.getElementById("PanelUI-remotetabs-syncnow");
if (tooltiptext) { if (tooltiptext) {
syncNow.setAttribute("tooltiptext", tooltiptext); el.setAttribute("tooltiptext", tooltiptext);
} else { } else {
syncNow.removeAttribute("tooltiptext"); el.removeAttribute("tooltiptext");
} }
} });
}, },
get relativeTimeFormat() { get relativeTimeFormat() {

View File

@ -19,11 +19,17 @@
* these gets focus, it redirects focus to the appropriate button. This avoids * 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 * the need to continually manage the tabindex of toolbar buttons in response to
* toolbarchanges. * 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 = { ToolbarKeyboardNavigator = {
// Toolbars we want to be keyboard navigable. // Toolbars we want to be keyboard navigable.
kToolbars: [CustomizableUI.AREA_NAVBAR, CustomizableUI.AREA_BOOKMARKS], 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) { _isButton(aElem) {
return ( return (
@ -80,6 +86,16 @@ ToolbarKeyboardNavigator = {
return aRoot._toolbarKeyNavWalker; 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() { init() {
for (let id of this.kToolbars) { for (let id of this.kToolbars) {
let toolbar = document.getElementById(id); let toolbar = document.getElementById(id);
@ -87,16 +103,11 @@ ToolbarKeyboardNavigator = {
// We manage toolbar focus completely. This attribute ensures that CSS // We manage toolbar focus completely. This attribute ensures that CSS
// doesn't set -moz-user-focus: normal. // doesn't set -moz-user-focus: normal.
toolbar.setAttribute("keyNav", "true"); toolbar.setAttribute("keyNav", "true");
for (let stop of toolbar.getElementsByTagName("toolbartabstop")) { this._initTabStops(toolbar);
// 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);
}
toolbar.addEventListener("keydown", this); toolbar.addEventListener("keydown", this);
toolbar.addEventListener("keypress", this); toolbar.addEventListener("keypress", this);
} }
CustomizableUI.addListener(this);
}, },
uninit() { uninit() {
@ -109,6 +120,19 @@ ToolbarKeyboardNavigator = {
toolbar.removeEventListener("keypress", this); toolbar.removeEventListener("keypress", this);
toolbar.removeAttribute("keyNav"); 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) { _focusButton(aButton) {
@ -162,6 +186,42 @@ ToolbarKeyboardNavigator = {
walker.currentNode = aEvent.target; walker.currentNode = aEvent.target;
let button = walker.nextNode(); let button = walker.nextNode();
if (!button || !this._isButton(button)) { 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. // No navigable buttons for this tab stop. Skip it.
if (this._isFocusMovingBackward) { if (this._isFocusMovingBackward) {
document.commandDispatcher.rewindFocus(); document.commandDispatcher.rewindFocus();
@ -194,6 +254,20 @@ ToolbarKeyboardNavigator = {
_onKeyDown(aEvent) { _onKeyDown(aEvent) {
let focus = document.activeElement; 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 ( if (
aEvent.altKey || aEvent.altKey ||
aEvent.controlKey || aEvent.controlKey ||
@ -219,6 +293,83 @@ ToolbarKeyboardNavigator = {
aEvent.preventDefault(); 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) { _onKeyPress(aEvent) {
let focus = document.activeElement; let focus = document.activeElement;
if ( if (

View File

@ -2,10 +2,23 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * 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"); @namespace html url("http://www.w3.org/1999/xhtml");
:root,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow: -moz-hidden-unscrollable;
}
:root { :root {
text-rendering: optimizeLegibility;
min-height: 95px;
min-width: 95px;
/* variables */
--panelui-subview-transition-duration: 150ms; --panelui-subview-transition-duration: 150ms;
--lwt-additional-images: none; --lwt-additional-images: none;
--lwt-background-alignment: right top; --lwt-background-alignment: right top;
@ -16,6 +29,10 @@
--toolbar-color: var(--toolbar-non-lwt-textcolor); --toolbar-color: var(--toolbar-non-lwt-textcolor);
} }
:root:-moz-locale-dir(rtl) {
direction: rtl;
}
:root:-moz-lwtheme { :root:-moz-lwtheme {
--toolbar-bgcolor: rgba(255,255,255,.4); --toolbar-bgcolor: rgba(255,255,255,.4);
--toolbar-bgimage: none; --toolbar-bgimage: none;
@ -35,6 +52,26 @@
background-color: var(--lwt-accent-color-inactive, var(--lwt-accent-color)); 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 */ /* Set additional backgrounds alignment relative to toolbox */
#navigator-toolbox:-moz-lwtheme { #navigator-toolbox:-moz-lwtheme {
@ -43,29 +80,11 @@
background-repeat: var(--lwt-background-tiling); 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[compact=true] .search-setting-button,
.search-one-offs:not([compact=true]) .search-setting-button-compact { .search-one-offs:not([compact=true]) .search-setting-button-compact {
display: none; display: none;
} }
/* Prevent shrinking the page content to 0 height and width */
.browserStack {
min-height: 25px;
min-width: 25px;
}
%ifdef MENUBAR_CAN_AUTOHIDE %ifdef MENUBAR_CAN_AUTOHIDE
#toolbar-menubar[autohide="true"] { #toolbar-menubar[autohide="true"] {
overflow: hidden; overflow: hidden;
@ -80,7 +99,6 @@
%ifdef XP_MACOSX %ifdef XP_MACOSX
#toolbar-menubar { #toolbar-menubar {
-moz-binding: none;
visibility: collapse; visibility: collapse;
} }
%endif %endif
@ -119,7 +137,6 @@ panelview[mainview] > .panel-header {
.panel-viewcontainer.offscreen { .panel-viewcontainer.offscreen {
display: block; display: block;
position: absolute;
} }
.panel-viewstack { .panel-viewstack {
@ -127,10 +144,6 @@ panelview[mainview] > .panel-header {
transition: height var(--panelui-subview-transition-duration); 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") { @supports -moz-bool-pref("layout.css.emulate-moz-box-with-flex") {
#tabbrowser-tabs { #tabbrowser-tabs {
/* Without this, the tabs container width extends beyond the window width */ /* 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:not([overflow="true"]):not([hashiddentabs]) ~ #alltabs-button,
#tabbrowser-tabs[hasadjacentnewtabbutton]:not([overflow="true"]) ~ #new-tab-button, #tabbrowser-tabs[hasadjacentnewtabbutton]:not([overflow="true"]) ~ #new-tab-button,
#tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button, #tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > #tabs-newtab-button,
#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > .tabbrowser-arrowscrollbox > .tabs-newtab-button, #tabbrowser-tabs:not([hasadjacentnewtabbutton]) > .tabbrowser-arrowscrollbox > #tabs-newtab-button,
#TabsToolbar[customizing="true"] #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button { #TabsToolbar[customizing="true"] #tabs-newtab-button {
visibility: collapse; visibility: collapse;
} }
@ -155,10 +168,6 @@ panelview[mainview] > .panel-header {
visibility: hidden; /* temporary space to keep a tab's close button under the cursor */ 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]) { .tabbrowser-tab:not([pinned]) {
-moz-box-flex: 100; -moz-box-flex: 100;
max-width: 225px; max-width: 225px;
@ -208,13 +217,13 @@ panelview[mainview] > .panel-header {
} }
%endif %endif
#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] { #tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-arrowscrollbox > .tabbrowser-tab[pinned] {
position: fixed !important; position: fixed !important;
display: block; display: block;
} }
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[selected], #tabbrowser-tabs[movingtab] > .tabbrowser-arrowscrollbox > .tabbrowser-tab[selected],
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[multiselected] { #tabbrowser-tabs[movingtab] > .tabbrowser-arrowscrollbox > .tabbrowser-tab[multiselected] {
position: relative; position: relative;
z-index: 2; z-index: 2;
pointer-events: none; /* avoid blocking dragover events on scroll buttons */ pointer-events: none; /* avoid blocking dragover events on scroll buttons */
@ -248,8 +257,15 @@ panelview[mainview] > .panel-header {
pointer-events: auto; pointer-events: auto;
} }
toolbar[overflowable] > .customization-target { /* The address bar needs to be able to render outside of the toolbar, but as
overflow: hidden; * 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, toolbar:not([overflowing]) > .overflow-button,
@ -257,7 +273,7 @@ toolbar[customizing] > .overflow-button {
display: none; 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 { #nav-bar[customizing] > .overflow-button {
display: -moz-box; display: -moz-box;
} }
@ -534,20 +550,15 @@ toolbar:not(#TabsToolbar) > #personal-bookmarks {
} }
#urlbar, #urlbar,
.searchbar-textbox { #searchbar {
/* Setting a width and min-width to let the location & search bars maintain /* 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) */ a constant width in case they haven't be resized manually. (bug 965772) */
width: 1px; width: 1px;
min-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. */ /* 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; direction: ltr !important;
text-align: right !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 /* 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 to the input box direction if the user switches the text direction using
cmd_switchTextDirection (which applies a dir attribute to the <input>). */ 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; text-align: left !important;
} }
%ifdef ENABLE_MARIONETTE
/* /*
* Display visual cue that browser is under remote control by Marionette. * Display visual cue that browser is under remote control by Marionette.
* This is to help users visually distinguish a user agent session that * 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 { :root[remotecontrol] #urlbar #identity-box {
background: white; background: white;
} }
%endif
/* Show the url scheme in a static box when overflowing to the left */ /* Show the url scheme in a static box when overflowing to the left */
moz-input-box.urlbar-input-box { .urlbar-input-box {
position: relative; position: relative;
direction: ltr; direction: ltr;
} }
html|input.urlbar-scheme { #urlbar-scheme {
position: absolute; position: absolute;
height: 100%; height: 100%;
visibility: hidden; visibility: hidden;
@ -595,22 +607,22 @@ html|input.urlbar-scheme {
/* Visible if the urlbar is not focused and it overflows at the start. /* 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 */ 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; visibility: visible;
} }
/* Fade out URL on overflow /* Fade out URL on overflow
This mask may be overriden when a Contextual Feature Recommendation is shown, This mask may be overriden when a Contextual Feature Recommendation is shown,
see browser/themes/shared/urlbar-searchbar.inc.css for details */ 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); 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)); 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; mask-repeat: no-repeat;
} }
@ -621,10 +633,10 @@ html|input.urlbar-input {
} }
} }
#urlbar[actionoverride] > #urlbar-display-box, #urlbar[actionoverride] > #urlbar-input-container > #urlbar-label-box,
#urlbar:not([actiontype="switchtab"]):not([actiontype="extension"]) > #urlbar-display-box, #urlbar:not([actiontype="switchtab"]):not([actiontype="extension"]) > #urlbar-input-container > #urlbar-label-box,
#urlbar:not([actiontype="switchtab"]) > #urlbar-display-box > #switchtab, #urlbar:not([actiontype="switchtab"]) > #urlbar-input-container > #urlbar-label-box > #urlbar-label-switchtab,
#urlbar:not([actiontype="extension"]) > #urlbar-display-box > #extension { #urlbar:not([actiontype="extension"]) > #urlbar-input-container > #urlbar-label-box > #urlbar-label-extension {
display: none; display: none;
} }
@ -641,12 +653,18 @@ html|input.urlbar-input {
background-color: hsla(0,0%,80%,.5); /* match arrowpanel-dimmed-further */ background-color: hsla(0,0%,80%,.5); /* match arrowpanel-dimmed-further */
} }
#PopupAutoComplete[firstresultstyle="insecureWarning"] { /* Define the minimum width based on the style of result rows.
min-width: 200px; 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"] { #PopupAutoComplete > richlistbox > richlistitem[originaltype="insecureWarning"] {
-moz-binding: none;
height: auto; height: auto;
} }
@ -665,11 +683,11 @@ html|input.urlbar-input {
margin-inline-start: 0; 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), #identity-box.chromeUI ~ #page-action-buttons > .urlbar-page-action:not(#star-button-box),
.urlbar-history-dropmarker[usertyping], #urlbar[usertyping] > #urlbar-input-container > .urlbar-history-dropmarker,
.urlbar-go-button:not([usertyping]), #urlbar:not([usertyping]) > #urlbar-input-container > #urlbar-go-button,
.urlbar-go-button:not([parentfocused="true"]) { #urlbar:not([focused]) > #urlbar-input-container > #urlbar-go-button {
display: none; display: none;
} }
@ -677,66 +695,56 @@ html|input.urlbar-input {
-moz-user-focus: normal; -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 * 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 * plus the toolbarbutton-inner-padding. We're adding 4px to ensure things
* like rounding on hidpi don't accidentally result in the button going * like rounding on hidpi don't accidentally result in the button going
* into overflow. * into overflow.
*/ */
#urlbar-container { #urlbar-container {
min-width: calc(49ch + 24px + 2 * var(--toolbarbutton-inner-padding)); min-width: calc(350px + 24px + 2 * var(--toolbarbutton-inner-padding));
} }
#nav-bar[downloadsbuttonshown] #urlbar-container { #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 { #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 { @media (max-width: 770px) {
max-width: 60px;
}
}
@media (max-width: 600px) {
#urlbar-container { #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 { #nav-bar[downloadsbuttonshown] #urlbar-container {
min-width: 39ch; min-width: 280px;
}
:root[customizing] #urlbar-container {
min-width: 245px;
} }
#identity-icon-labels { #identity-icon-labels {
max-width: 50px; max-width: 50px;
} }
} }
@media (max-width: 500px) { @media (max-width: 550px) {
#urlbar-container { #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 { #nav-bar[downloadsbuttonshown] #urlbar-container {
min-width: 34ch; min-width: 225px;
} }
#identity-icon-labels { #identity-icon-labels {
max-width: 40px; max-width: 40px;
} }
} #urlbar-zoom-button {
@media (max-width: 400px) { display: none;
#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;
} }
} }
@ -748,7 +756,7 @@ html|input.urlbar-input {
margin-inline-end: 0.25em !important; 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], toolbarpaletteitem[place=toolbar][id^=wrapper-customizableui-special-spring],
toolbarspring { toolbarspring {
-moz-box-flex: 1; -moz-box-flex: 1;
@ -759,6 +767,14 @@ toolbarspring {
#nav-bar toolbarpaletteitem[id^=wrapper-customizableui-special-spring], #nav-bar toolbarpaletteitem[id^=wrapper-customizableui-special-spring],
#nav-bar toolbarspring { #nav-bar toolbarspring {
-moz-box-flex: 80; -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 { #widget-overflow-list > toolbarspring {
@ -786,10 +802,6 @@ toolbarspring {
.bookmark-item > .menu-iconic-left > .menu-iconic-icon { .bookmark-item > .menu-iconic-left > .menu-iconic-icon {
image-rendering: -moz-crisp-edges; 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 { 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 */ /* Hide extension toolbars that neglected to set the proper class */
window[chromehidden~="location"][chromehidden~="toolbar"] toolbar:not(.chromeclass-menubar), :root[chromehidden~="location"][chromehidden~="toolbar"] toolbar:not(.chromeclass-menubar) {
window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#print-preview-toolbar):not(.chromeclass-menubar) {
display: none; display: none;
} }
@ -831,7 +842,7 @@ window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#pri
background: black; background: black;
} }
html|*.pointerlockfswarning { .pointerlockfswarning {
position: fixed; position: fixed;
z-index: 2147483647 !important; z-index: 2147483647 !important;
visibility: visible; visibility: visible;
@ -845,32 +856,32 @@ html|*.pointerlockfswarning {
max-width: 95%; max-width: 95%;
pointer-events: none; pointer-events: none;
} }
html|*.pointerlockfswarning:not([hidden]) { .pointerlockfswarning:not([hidden]) {
display: flex; display: flex;
will-change: transform; will-change: transform;
} }
html|*.pointerlockfswarning[onscreen] { .pointerlockfswarning[onscreen] {
transform: translate(-50%, 50px); transform: translate(-50%, 50px);
} }
html|*.pointerlockfswarning[ontop] { .pointerlockfswarning[ontop] {
/* Use -10px to hide the border and border-radius on the top */ /* Use -10px to hide the border and border-radius on the top */
transform: translate(-50%, -10px); transform: translate(-50%, -10px);
} }
:root[OSXLionFullscreen] html|*.pointerlockfswarning[ontop] { :root[OSXLionFullscreen] .pointerlockfswarning[ontop] {
transform: translate(-50%, 80px); transform: translate(-50%, 80px);
} }
html|*.pointerlockfswarning-domain-text, .pointerlockfswarning-domain-text,
html|*.pointerlockfswarning-generic-text { .pointerlockfswarning-generic-text {
word-wrap: break-word; word-wrap: break-word;
/* We must specify a min-width, otherwise word-wrap:break-word doesn't work. Bug 630864. */ /* We must specify a min-width, otherwise word-wrap:break-word doesn't work. Bug 630864. */
min-width: 1px min-width: 1px
} }
html|*.pointerlockfswarning-domain-text:not([hidden]) + html|*.pointerlockfswarning-generic-text { .pointerlockfswarning-domain-text:not([hidden]) + .pointerlockfswarning-generic-text {
display: none; display: none;
} }
html|*#fullscreen-exit-button { #fullscreen-exit-button {
pointer-events: auto; pointer-events: auto;
} }
@ -893,7 +904,7 @@ html|*#fullscreen-exit-button {
/* should occupy space but not be visible */ /* should occupy space but not be visible */
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
-moz-stack-sizing: ignore; position: absolute;
} }
browser[tabmodalPromptShowing] { 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 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. */ 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]: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; display: none;
} }
@ -966,7 +977,7 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > .toolbarbut
display: -moz-box; 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; display: none;
} }
@ -985,7 +996,6 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > #downloads-
/* Give this menupopup an arrow panel styling */ /* Give this menupopup an arrow panel styling */
#BMB_bookmarksPopup { #BMB_bookmarksPopup {
appearance: none; appearance: none;
-moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-arrow");
background: transparent; background: transparent;
border: none; border: none;
/* The popup inherits -moz-image-region from the button, must reset it */ /* The popup inherits -moz-image-region from the button, must reset it */

View File

@ -35,6 +35,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
LightweightThemeConsumer: LightweightThemeConsumer:
"resource://gre/modules/LightweightThemeConsumer.jsm", "resource://gre/modules/LightweightThemeConsumer.jsm",
Log: "resource://gre/modules/Log.jsm", Log: "resource://gre/modules/Log.jsm",
LoginHelper: "resource://gre/modules/LoginHelper.jsm",
LoginManagerParent: "resource://gre/modules/LoginManagerParent.jsm", LoginManagerParent: "resource://gre/modules/LoginManagerParent.jsm",
MigrationUtils: "resource:///modules/MigrationUtils.jsm", MigrationUtils: "resource:///modules/MigrationUtils.jsm",
NetUtil: "resource://gre/modules/NetUtil.jsm", NetUtil: "resource://gre/modules/NetUtil.jsm",
@ -165,11 +166,6 @@ XPCOMUtils.defineLazyScriptGetter(
["gGestureSupport", "gHistorySwipeAnimation"], ["gGestureSupport", "gHistorySwipeAnimation"],
"chrome://browser/content/browser-gestureSupport.js" "chrome://browser/content/browser-gestureSupport.js"
); );
XPCOMUtils.defineLazyScriptGetter(
this,
"gSafeBrowsing",
"chrome://browser/content/browser-safebrowsing.js"
);
XPCOMUtils.defineLazyScriptGetter( XPCOMUtils.defineLazyScriptGetter(
this, this,
"gSync", "gSync",
@ -246,7 +242,9 @@ XPCOMUtils.defineLazyServiceGetters(this, {
"@mozilla.org/network/serialization-helper;1", "@mozilla.org/network/serialization-helper;1",
"nsISerializationHelper", "nsISerializationHelper",
], ],
#ifdef ENABLE_MARIONETTE
Marionette: ["@mozilla.org/remote/marionette;1", "nsIMarionette"], Marionette: ["@mozilla.org/remote/marionette;1", "nsIMarionette"],
#endif
WindowsUIUtils: ["@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils"], WindowsUIUtils: ["@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils"],
}); });
@ -286,58 +284,11 @@ XPCOMUtils.defineLazyGetter(this, "gNavToolbox", () => {
return document.getElementById("navigator-toolbox"); return document.getElementById("navigator-toolbox");
}); });
XPCOMUtils.defineLazyGetter(this, "gURLBar", () => gURLBarHandler.urlbar); XPCOMUtils.defineLazyGetter(this, "gURLBar", () => {
return new UrlbarInput({
/** textbox: document.getElementById("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, "ReferrerInfo", () => XPCOMUtils.defineLazyGetter(this, "ReferrerInfo", () =>
Components.Constructor( Components.Constructor(
@ -472,13 +423,6 @@ XPCOMUtils.defineLazyPreferenceGetter(
} }
); );
XPCOMUtils.defineLazyPreferenceGetter(
this,
"gHtmlAboutAddonsEnabled",
"extensions.htmlaboutaddons.enabled",
false
);
customElements.setElementCreationCallback("translation-notification", () => { customElements.setElementCreationCallback("translation-notification", () => {
Services.scriptloader.loadSubScript( Services.scriptloader.loadSubScript(
"chrome://browser/content/translation-notification.js", "chrome://browser/content/translation-notification.js",
@ -645,7 +589,7 @@ function UpdateBackForwardCommands(aWebNavigation) {
/** /**
* Click-and-Hold implementation for the Back and Forward buttons * 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() { function SetClickAndHoldHandlers() {
// Bug 414797: Clone the back/forward buttons' context menu into both buttons. // Bug 414797: Clone the back/forward buttons' context menu into both buttons.
@ -656,13 +600,13 @@ function SetClickAndHoldHandlers() {
let backButton = document.getElementById("back-button"); let backButton = document.getElementById("back-button");
backButton.setAttribute("type", "menu"); backButton.setAttribute("type", "menu");
backButton.appendChild(popup); backButton.prepend(popup);
gClickAndHoldListenersOnElement.add(backButton); gClickAndHoldListenersOnElement.add(backButton);
let forwardButton = document.getElementById("forward-button"); let forwardButton = document.getElementById("forward-button");
popup = popup.cloneNode(true); popup = popup.cloneNode(true);
forwardButton.setAttribute("type", "menu"); forwardButton.setAttribute("type", "menu");
forwardButton.appendChild(popup); forwardButton.prepend(popup);
gClickAndHoldListenersOnElement.add(forwardButton); gClickAndHoldListenersOnElement.add(forwardButton);
} }
@ -679,7 +623,7 @@ const gClickAndHoldListenersOnElement = {
} }
// Prevent the menupopup from opening immediately // Prevent the menupopup from opening immediately
aEvent.currentTarget.firstElementChild.hidden = true; aEvent.currentTarget.menupopup.hidden = true;
aEvent.currentTarget.addEventListener("mouseout", this); aEvent.currentTarget.addEventListener("mouseout", this);
aEvent.currentTarget.addEventListener("mouseup", this); aEvent.currentTarget.addEventListener("mouseup", this);
@ -1579,7 +1523,8 @@ var delayedStartupPromise = new Promise(resolve => {
var gBrowserInit = { var gBrowserInit = {
delayedStartupFinished: false, delayedStartupFinished: false,
idleTasksFinished: false, idleTasksFinishedPromise: null,
idleTaskPromiseResolve: null,
_tabToAdopt: undefined, _tabToAdopt: undefined,
@ -1613,10 +1558,6 @@ var gBrowserInit = {
}, },
onBeforeInitialXULLayout() { 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. // Set a sane starting width/height for all resolutions on new profiles.
if (Services.prefs.getBoolPref("privacy.resistFingerprinting")) { if (Services.prefs.getBoolPref("privacy.resistFingerprinting")) {
// When the fingerprinting resistance is enabled, making sure that we don't // 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. // This needs setting up before we create the first remote browser.
window.docShell.treeOwner window.docShell.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor) .QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow).XULBrowserWindow = window.XULBrowserWindow; .getInterface(Ci.nsIAppWindow).XULBrowserWindow = window.XULBrowserWindow;
window.browserDOMWindow = new nsBrowserAccess(); window.browserDOMWindow = new nsBrowserAccess();
gBrowser = window._gBrowser; gBrowser = window._gBrowser;
@ -1783,7 +1724,7 @@ var gBrowserInit = {
if (!window.toolbar.visible) { if (!window.toolbar.visible) {
// adjust browser UI for popups // adjust browser UI for popups
gURLBar.setAttribute("readonly", "true"); gURLBar.readOnly = true;
} }
// Misc. inits. // Misc. inits.
@ -1799,7 +1740,9 @@ var gBrowserInit = {
ToolbarKeyboardNavigator.init(); ToolbarKeyboardNavigator.init();
} }
#ifdef ENABLE_MARIONETTE
gRemoteControl.updateVisualCue(Marionette.running); gRemoteControl.updateVisualCue(Marionette.running);
#endif
// If we are given a tab to swap in, take care of it before first paint to // If we are given a tab to swap in, take care of it before first paint to
// avoid an about:blank flash. // avoid an about:blank flash.
@ -1883,7 +1826,9 @@ var gBrowserInit = {
this._handleURIToLoad(); this._handleURIToLoad();
Services.obs.addObserver(gIdentityHandler, "perm-changed"); Services.obs.addObserver(gIdentityHandler, "perm-changed");
#ifdef ENABLE_MARIONETTE
Services.obs.addObserver(gRemoteControl, "remote-active"); Services.obs.addObserver(gRemoteControl, "remote-active");
#endif
Services.obs.addObserver( Services.obs.addObserver(
gSessionHistoryObserver, gSessionHistoryObserver,
"browser:purge-session-history" "browser:purge-session-history"
@ -1927,8 +1872,7 @@ var gBrowserInit = {
let safeMode = document.getElementById("helpSafeMode"); let safeMode = document.getElementById("helpSafeMode");
if (Services.appinfo.inSafeMode) { if (Services.appinfo.inSafeMode) {
safeMode.label = safeMode.getAttribute("stoplabel"); document.l10n.setAttributes(safeMode, "menu-help-safe-mode-with-addons");
safeMode.accessKey = safeMode.getAttribute("stopaccesskey");
} }
// BiDi UI // BiDi UI
@ -1993,7 +1937,7 @@ var gBrowserInit = {
window.addEventListener("dragover", MousePosTracker); window.addEventListener("dragover", MousePosTracker);
gNavToolbox.addEventListener("customizationstarting", CustomizationHandler); gNavToolbox.addEventListener("customizationstarting", CustomizationHandler);
gNavToolbox.addEventListener("customizationending", CustomizationHandler); gNavToolbox.addEventListener("aftercustomization", CustomizationHandler);
SessionStore.promiseInitialized.then(() => { SessionStore.promiseInitialized.then(() => {
// Bail out if the window has been closed in the meantime. // 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 // timeouts) should execute in order. Note that this observer notification is
// not guaranteed to fire, since the window could close before we get here. // not guaranteed to fire, since the window could close before we get here.
scheduleIdleTask(() => { scheduleIdleTask(() => {
this.idleTasksFinished = true; this.idleTaskPromiseResolve();
Services.obs.notifyObservers( Services.obs.notifyObservers(
window, window,
"browser-idle-startup-tasks-finished" "browser-idle-startup-tasks-finished"
@ -2435,7 +2379,9 @@ var gBrowserInit = {
FullZoom.destroy(); FullZoom.destroy();
Services.obs.removeObserver(gIdentityHandler, "perm-changed"); Services.obs.removeObserver(gIdentityHandler, "perm-changed");
#ifdef ENABLE_MARIONETTE
Services.obs.removeObserver(gRemoteControl, "remote-active"); Services.obs.removeObserver(gRemoteControl, "remote-active");
#endif
Services.obs.removeObserver( Services.obs.removeObserver(
gSessionHistoryObserver, gSessionHistoryObserver,
"browser:purge-session-history" "browser:purge-session-history"
@ -2482,11 +2428,15 @@ var gBrowserInit = {
window.XULBrowserWindow = null; window.XULBrowserWindow = null;
window.docShell.treeOwner window.docShell.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor) .QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIXULWindow).XULBrowserWindow = null; .getInterface(Ci.nsIAppWindow).XULBrowserWindow = null;
window.browserDOMWindow = null; window.browserDOMWindow = null;
}, },
}; };
gBrowserInit.idleTasksFinishedPromise = new Promise(resolve => {
gBrowserInit.idleTaskPromiseResolve = resolve;
});
function HandleAppCommandEvent(evt) { function HandleAppCommandEvent(evt) {
switch (evt.command) { switch (evt.command) {
case "Back": 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() { function focusAndSelectUrlBar() {
// In customize mode, the url bar is disabled. If a new tab is opened or the // In customize mode, the url bar is disabled. If a new tab is opened or the
@ -2779,9 +2729,7 @@ function focusAndSelectUrlBar() {
function openLocation() { function openLocation() {
if (window.location.href == AppConstants.BROWSER_CHROME_URL) { if (window.location.href == AppConstants.BROWSER_CHROME_URL) {
focusAndSelectUrlBar(); focusAndSelectUrlBar();
if (gURLBar.openViewOnFocus && !gURLBar.view.isOpen) { gURLBar.view.autoOpen();
gURLBar.startQuery();
}
return; return;
} }
@ -3166,7 +3114,7 @@ function BrowserPageInfo(
// We didn't find a matching window, so open a new one. // We didn't find a matching window, so open a new one.
return openDialog( return openDialog(
"chrome://browser/content/pageinfo/pageInfo.xul", "chrome://browser/content/pageinfo/pageInfo.xhtml",
"", "",
"chrome,toolbar,dialog=no,resizable", "chrome,toolbar,dialog=no,resizable",
args args
@ -3371,10 +3319,7 @@ function SetPageProxyState(aState, updatePopupNotifications) {
} }
let oldPageProxyState = gURLBar.getAttribute("pageproxystate"); let oldPageProxyState = gURLBar.getAttribute("pageproxystate");
// The "browser_urlbar_stop_pending.js" test uses a MutationObserver to do gURLBar.setPageProxyState(aState);
// 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);
// the page proxy state is set to valid via OnLocationChange, which // the page proxy state is set to valid via OnLocationChange, which
// gets called when we switch tabs. // gets called when we switch tabs.
@ -3431,7 +3376,6 @@ var BrowserOnClick = {
init() { init() {
let mm = window.messageManager; let mm = window.messageManager;
mm.addMessageListener("Browser:CertExceptionError", this); mm.addMessageListener("Browser:CertExceptionError", this);
mm.addMessageListener("Browser:SiteBlockedError", this);
mm.addMessageListener("Browser:EnableOnlineMode", this); mm.addMessageListener("Browser:EnableOnlineMode", this);
mm.addMessageListener("Browser:ResetSSLPreferences", this); mm.addMessageListener("Browser:ResetSSLPreferences", this);
mm.addMessageListener("Browser:SSLErrorReportTelemetry", this); mm.addMessageListener("Browser:SSLErrorReportTelemetry", this);
@ -3443,7 +3387,6 @@ var BrowserOnClick = {
uninit() { uninit() {
let mm = window.messageManager; let mm = window.messageManager;
mm.removeMessageListener("Browser:CertExceptionError", this); mm.removeMessageListener("Browser:CertExceptionError", this);
mm.removeMessageListener("Browser:SiteBlockedError", this);
mm.removeMessageListener("Browser:EnableOnlineMode", this); mm.removeMessageListener("Browser:EnableOnlineMode", this);
mm.removeMessageListener("Browser:ResetSSLPreferences", this); mm.removeMessageListener("Browser:ResetSSLPreferences", this);
mm.removeMessageListener("Browser:SSLErrorReportTelemetry", this); mm.removeMessageListener("Browser:SSLErrorReportTelemetry", this);
@ -3464,15 +3407,6 @@ var BrowserOnClick = {
msg.data.frameId msg.data.frameId
); );
break; 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": case "Browser:EnableOnlineMode":
if (Services.io.offline) { if (Services.io.offline) {
// Reset network state and refresh the page. // Reset network state and refresh the page.
@ -3606,7 +3540,7 @@ var BrowserOnClick = {
cert = securityInfo.serverCert; cert = securityInfo.serverCert;
Services.ww.openWindow( Services.ww.openWindow(
window, window,
"chrome://pippki/content/certViewer.xul", "chrome://pippki/content/certViewer.xhtml",
"_blank", "_blank",
"centerscreen,chrome", "centerscreen,chrome",
cert 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) { ignoreWarningLink(reason, blockedInfo) {
let triggeringPrincipal = E10SUtils.deserializePrincipal( let triggeringPrincipal = E10SUtils.deserializePrincipal(
blockedInfo.triggeringPrincipal, blockedInfo.triggeringPrincipal,
@ -4638,14 +4530,13 @@ const BrowserSearch = {
_setURLBarPlaceholder(name) { _setURLBarPlaceholder(name) {
let placeholder; let placeholder;
if (name) { if (name) {
placeholder = gBrowserBundle.formatStringFromName( placeholder = gBrowserBundle.formatStringFromName("urlbar.placeholder", [
"urlbar.placeholder", name,
[name] ]);
);
} else { } else {
placeholder = gURLBar.getAttribute("defaultPlaceholder"); placeholder = gURLBar.getAttribute("defaultPlaceholder");
} }
gURLBar.setAttribute("placeholder", placeholder); gURLBar.placeholder = placeholder;
}, },
addEngine(browser, engine, uri) { addEngine(browser, engine, uri) {
@ -4751,10 +4642,7 @@ const BrowserSearch = {
} }
let focusUrlBarIfSearchFieldIsNotActive = function(aSearchBar) { let focusUrlBarIfSearchFieldIsNotActive = function(aSearchBar) {
if ( if (!aSearchBar || document.activeElement != aSearchBar.textbox) {
!aSearchBar ||
document.activeElement != aSearchBar.textbox.inputField
) {
// Limit the results to search suggestions, like the search bar. // Limit the results to search suggestions, like the search bar.
gURLBar.search(UrlbarTokenizer.RESTRICT.SEARCH); gURLBar.search(UrlbarTokenizer.RESTRICT.SEARCH);
} }
@ -4935,6 +4823,13 @@ const BrowserSearch = {
XPCOMUtils.defineConstant(this, "BrowserSearch", BrowserSearch); XPCOMUtils.defineConstant(this, "BrowserSearch", BrowserSearch);
function CreateContainerTabMenu(event) {
createUserContextMenu(event, {
useAccessKeys: false,
showDefaultTab: true,
});
}
function FillHistoryMenu(aParent) { function FillHistoryMenu(aParent) {
// Lazily add the hover listeners on first showing and never remove them // Lazily add the hover listeners on first showing and never remove them
if (!aParent.hasStatusListener) { if (!aParent.hasStatusListener) {
@ -5456,7 +5351,7 @@ var XULBrowserWindow = {
StatusPanel.update(); StatusPanel.update();
}, },
setOverLink(url, anchorElt) { setOverLink(url) {
if (url) { if (url) {
url = Services.textToSubURI.unEscapeURIForUI(url); url = Services.textToSubURI.unEscapeURIForUI(url);
@ -5688,7 +5583,7 @@ var XULBrowserWindow = {
var location = aLocationURI ? aLocationURI.spec : ""; var location = aLocationURI ? aLocationURI.spec : "";
this.hideOverLinkImmediately = true; this.hideOverLinkImmediately = true;
this.setOverLink("", null); this.setOverLink("");
this.hideOverLinkImmediately = false; this.hideOverLinkImmediately = false;
// We should probably not do this if the value has changed since the user // 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) { if (event.button == 0 && !this.stop.disabled) {
this._stopClicked = true; this._stopClicked = true;
} }
break;
case "animationend": { case "animationend": {
if ( if (
event.target.classList.contains("toolbarbutton-animatable-image") && event.target.classList.contains("toolbarbutton-animatable-image") &&
@ -6364,8 +6260,6 @@ var TabsProgressListener = {
gBrowser.getNotificationBox(aBrowser).removeTransientNotifications(); gBrowser.getNotificationBox(aBrowser).removeTransientNotifications();
FullZoom.onLocationChange(aLocationURI, false, aBrowser); FullZoom.onLocationChange(aLocationURI, false, aBrowser);
ContentBlocking.onLocationChange();
}, },
onLinkIconAvailable(browser, dataURI, iconURI) { onLinkIconAvailable(browser, dataURI, iconURI) {
@ -7044,6 +6938,7 @@ var gUIDensity = {
} }
gBrowser.tabContainer.uiDensityChanged(); gBrowser.tabContainer.uiDensityChanged();
gURLBar.updateLayoutBreakout();
}, },
}; };
@ -7972,8 +7867,7 @@ var CanvasPermissionPromptHelper = {
let browser; let browser;
if (aSubject instanceof Ci.nsIDOMWindow) { if (aSubject instanceof Ci.nsIDOMWindow) {
let contentWindow = aSubject.QueryInterface(Ci.nsIDOMWindow); browser = aSubject.docShell.chromeEventHandler;
browser = contentWindow.docShell.chromeEventHandler;
} else { } else {
browser = aSubject; browser = aSubject;
} }
@ -8419,7 +8313,6 @@ function BrowserOpenAddonsMgr(aView) {
if (aView) { if (aView) {
aSubject.loadView(aView); aSubject.loadView(aView);
} }
aSubject.QueryInterface(Ci.nsIDOMWindow);
aSubject.focus(); aSubject.focus();
resolve(aSubject); resolve(aSubject);
}, "EM-loaded"); }, "EM-loaded");
@ -8567,41 +8460,6 @@ function checkEmptyPageOrigin(
return contentPrincipal.isSystemPrincipal; 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 * Format a URL
* eg: * eg:
@ -8616,6 +8474,7 @@ function formatURL(aFormat, aIsPref) {
: Services.urlFormatter.formatURL(aFormat); : Services.urlFormatter.formatURL(aFormat);
} }
#ifdef ENABLE_MARIONETTE
/** /**
* Fired on the "marionette-remote-control" system notification, * Fired on the "marionette-remote-control" system notification,
* indicating if the browser session is under remote control. * indicating if the browser session is under remote control.
@ -8634,6 +8493,7 @@ const gRemoteControl = {
} }
}, },
}; };
#endif
const gAccessibilityServiceIndicator = { const gAccessibilityServiceIndicator = {
init() { init() {
@ -8723,10 +8583,6 @@ var gPrivateBrowsingUI = {
// Adjust the window's title // Adjust the window's title
let docElement = document.documentElement; let docElement = document.documentElement;
if (!PrivateBrowsingUtils.permanentPrivateBrowsing) { if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
docElement.setAttribute(
"title",
docElement.getAttribute("title_privatebrowsing")
);
docElement.setAttribute( docElement.setAttribute(
"titlemodifier", "titlemodifier",
docElement.getAttribute("titlemodifier_privatebrowsing") docElement.getAttribute("titlemodifier_privatebrowsing")
@ -9279,12 +9135,7 @@ var PanicButtonNotifier = {
popup.addEventListener("popuphidden", removeListeners); popup.addEventListener("popuphidden", removeListeners);
let widget = CustomizableUI.getWidget("panic-button").forWindow(window); let widget = CustomizableUI.getWidget("panic-button").forWindow(window);
let anchor = widget.anchor; let anchor = widget.anchor.icon;
anchor = document.getAnonymousElementByAttribute(
anchor,
"class",
"toolbarbutton-icon"
);
popup.openPopup(anchor, popup.getAttribute("position")); popup.openPopup(anchor, popup.getAttribute("position"));
} catch (ex) { } catch (ex) {
Cu.reportError(ex); Cu.reportError(ex);
@ -9440,7 +9291,6 @@ TabModalPromptBox.prototype = {
let prompt = prompts[prompts.length - 1]; let prompt = prompts[prompts.length - 1];
prompt.element.hidden = false; prompt.element.hidden = false;
// Because we were hidden before, this won't have been possible, so do it now: // Because we were hidden before, this won't have been possible, so do it now:
prompt.ensureXBLBindingAttached();
prompt.Dialog.setDefaultFocus(); prompt.Dialog.setDefaultFocus();
} else { } else {
browser.removeAttribute("tabmodalPromptShowing"); 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 * @param inputElement
* Search suggestions will be based on the text in this text box. * 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 * @param tableParent
* The suggestion table is appended as a child to this element. Since * 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 * 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 # 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/. # 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 # 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.xul # support MacOS specific features should be loaded directly from browser.xhtml
# rather than this file. # rather than this file.
# If you update this list, you may need to add a mapping within the following # 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/globalOverlay.js", this);
Services.scriptloader.loadSubScript("chrome://global/content/editMenuOverlay.js", this); Services.scriptloader.loadSubScript("chrome://global/content/editMenuOverlay.js", this);
Services.scriptloader.loadSubScript("chrome://browser/content/utilityOverlay.js", this); Services.scriptloader.loadSubScript("chrome://browser/content/utilityOverlay.js", this);
#ifdef XP_MACOSX if (AppConstants.platform == "macosx") {
Services.scriptloader.loadSubScript("chrome://global/content/macWindowMenu.js", this); Services.scriptloader.loadSubScript("chrome://global/content/macWindowMenu.js", this);
#endif }
</script> </script>

View File

@ -11,10 +11,11 @@
]> ]>
<window id="main-window" <window id="main-window"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> 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 --> <!-- Dock menu -->
<popupset> <popupset>

View File

@ -4,22 +4,29 @@
# This include file should only contain things that are needed to support MacOS # 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 # 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 # also needed in browser.xhtml, it should go in one of the various include files
# below that are shared with browser.xul. When including this file, # below that are shared with browser.xhtml. When including this file,
# browser-doctype.inc must also be included. # 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 # 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 #include global-scripts.inc
<script src="chrome://browser/content/nonbrowser-mac.js"></script> <script src="chrome://browser/content/nonbrowser-mac.js"></script>
# All sets except for popupsets (commands, keys, and stringbundles) # All sets except for popupsets (commands, keys, and stringbundles)
# *must* go into the browser-sets.inc file so that they can be shared with # *must* go into the browser-sets.inc file so that they can be shared with
# browser.xul # browser.xhtml
#include browser-sets.inc #include browser-sets.inc
# The entire main menubar is placed into browser-menubar.inc, so that it can be # 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 #include browser-menubar.inc

View File

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

View File

@ -6,7 +6,7 @@
<html> <html>
<head> <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"> <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://global/skin/in-content/common.css">
<link rel="stylesheet" type="text/css" href="chrome://browser/skin/newInstallPage.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 // If no windows are active (i.e. we're the hidden window), disable the close, minimize
// and zoom menu commands as well // 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 = [ var hiddenWindowDisabledItems = [
"cmd_close", "cmd_close",
"minimizeWindow", "minimizeWindow",
@ -123,7 +125,9 @@ function nonBrowserWindowDelayedStartup() {
function nonBrowserWindowShutdown() { function nonBrowserWindowShutdown() {
// If this is the hidden window being closed, release our reference to // If this is the hidden window being closed, release our reference to
// the dock menu element to prevent leaks on shutdown // 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( let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"].getService(
Ci.nsIMacDockSupport Ci.nsIMacDockSupport
); );

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -32,8 +32,9 @@ var gSanitizePromptDialog = {
init() { init() {
// This is used by selectByTimespan() to determine if the window has loaded. // This is used by selectByTimespan() to determine if the window has loaded.
this._inited = true; 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.l10n.setAttributes(OKButton, "sanitize-button-ok");
document.addEventListener("dialogaccept", function(e) { document.addEventListener("dialogaccept", function(e) {
@ -65,7 +66,7 @@ var gSanitizePromptDialog = {
} }
// Only apply the following if the dialog is opened outside of the Preferences. // 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. // 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. // Force the dialog to size again after the style attribute has been applied.
document.l10n.translateElements([document.documentElement]).then(() => { document.l10n.translateElements([document.documentElement]).then(() => {
@ -113,11 +114,10 @@ var gSanitizePromptDialog = {
// the 'accept' button to indicate things are happening and return false - // the 'accept' button to indicate things are happening and return false -
// once the async operation completes (either with or without errors) // once the async operation completes (either with or without errors)
// we close the window. // we close the window.
let docElt = document.documentElement; let acceptButton = this._dialog.getButton("accept");
let acceptButton = docElt.getButton("accept");
acceptButton.disabled = true; acceptButton.disabled = true;
document.l10n.setAttributes(acceptButton, "sanitize-button-clearing"); document.l10n.setAttributes(acceptButton, "sanitize-button-clearing");
docElt.getButton("cancel").disabled = true; this._dialog.getButton("cancel").disabled = true;
try { try {
let range = Sanitizer.getClearRange(this.selectedTimespan); let range = Sanitizer.getClearRange(this.selectedTimespan);
@ -174,7 +174,7 @@ var gSanitizePromptDialog = {
); );
try { try {
document.documentElement.getButton("accept").disabled = !found; this._dialog.getButton("accept").disabled = !found;
} catch (e) {} } catch (e) {}
// Update the warning prompt if needed // 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
.tab-close-button[pinned], .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:not([pendingicon]),
.tab-icon-pending[busy], .tab-icon-pending[busy],
.tab-icon-pending[pinned], .tab-icon-pending[pinned],
@ -54,15 +54,6 @@ tabpanels {
background-color: transparent; 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 */ /* Apply crisp rendering for favicons at exactly 2dppx resolution */
@media (resolution: 2dppx) { @media (resolution: 2dppx) {
.tab-icon-image { .tab-icon-image {

View File

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

View File

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

View File

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

View File

@ -43,7 +43,7 @@ add_task(async function init() {
// Below are test cases for XUL element // Below are test cases for XUL element
add_task(async function test_xul_text_link_label() { 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({ await BrowserTestUtils.openNewForegroundTab({
gBrowser, gBrowser,

View File

@ -85,11 +85,7 @@ add_task(async function test_toolbar_contextmenu_touch() {
// Test the urlbar input context menu. // Test the urlbar input context menu.
add_task(async function test_urlbar_contextmenu_touch() { add_task(async function test_urlbar_contextmenu_touch() {
let urlbar = document.getElementById("urlbar"); let urlbar = document.getElementById("urlbar");
let textBox = document.getAnonymousElementByAttribute( let textBox = urlbar.querySelector("moz-input-box");
urlbar,
"anonid",
"moz-input-box"
);
let menu = textBox.menupopup; let menu = textBox.menupopup;
await openAndCheckContextMenu(menu, textBox); 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, - 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/. --> - You can obtain one at http://mozilla.org/MPL/2.0/. -->
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"> 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"/> <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"); await waitForAttributeChange(tab, "label");
ok(tab.hasAttribute("busy"), "Should have seen the busy attribute"); ok(tab.hasAttribute("busy"), "Should have seen the busy attribute");
let label = document.getAnonymousElementByAttribute( let label = tab.textLabel;
tab,
"anonid",
"tab-label"
);
let bounds = label.getBoundingClientRect(); let bounds = label.getBoundingClientRect();
await waitForAttributeChange(tab, "busy"); await waitForAttributeChange(tab, "busy");
@ -84,11 +80,7 @@ add_task(async () => {
is(icon.iconURL, "http://example.com/favicon.ico"); is(icon.iconURL, "http://example.com/favicon.ico");
let tab = gBrowser.getTabForBrowser(browser); let tab = gBrowser.getTabForBrowser(browser);
let label = document.getAnonymousElementByAttribute( let label = tab.textLabel;
tab,
"anonid",
"tab-label"
);
let bounds = label.getBoundingClientRect(); let bounds = label.getBoundingClientRect();
await ContentTask.spawn(browser, null, () => { await ContentTask.spawn(browser, null, () => {

View File

@ -853,7 +853,7 @@ add_task(async function test_large_popup() {
BrowserTestUtils.removeTab(tab); 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() { add_task(async function test_large_popup_in_small_window() {
let newWin = await BrowserTestUtils.openNewBrowserWindow(); let newWin = await BrowserTestUtils.openNewBrowserWindow();
@ -862,10 +862,11 @@ add_task(async function test_large_popup_in_small_window() {
"resize", "resize",
false, false,
e => { 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; await resizePromise;
const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL); 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_bug479408_sample.html
browser_bug970746.xhtml browser_bug970746.xhtml
browser_star_hsts.sjs browser_star_hsts.sjs
browser_tab_dragdrop2_frame1.xul browser_tab_dragdrop2_frame1.xhtml
browser_tab_dragdrop_embed.html browser_tab_dragdrop_embed.html
browser_web_channel.html browser_web_channel.html
browser_web_channel_iframe.html browser_web_channel_iframe.html

View File

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

View File

@ -37,9 +37,7 @@ add_task(async function closeLastTabInWindow() {
let windowClosedPromise = BrowserTestUtils.domWindowClosed(newWin); let windowClosedPromise = BrowserTestUtils.domWindowClosed(newWin);
expectingDialog = true; expectingDialog = true;
// close tab: // close tab:
document firstTab.closeButton.click();
.getAnonymousElementByAttribute(firstTab, "anonid", "close-button")
.click();
await windowClosedPromise; await windowClosedPromise;
ok(!expectingDialog, "There should have been a dialog."); ok(!expectingDialog, "There should have been a dialog.");
ok(newWin.closed, "Window should be closed."); ok(newWin.closed, "Window should be closed.");
@ -73,17 +71,13 @@ add_task(async function closeWindoWithSingleTabTwice() {
let firstDialogShownPromise = new Promise((resolve, reject) => { let firstDialogShownPromise = new Promise((resolve, reject) => {
resolveDialogPromise = resolve; resolveDialogPromise = resolve;
}); });
document firstTab.closeButton.click();
.getAnonymousElementByAttribute(firstTab, "anonid", "close-button")
.click();
await firstDialogShownPromise; await firstDialogShownPromise;
info("Got initial dialog, now trying again"); info("Got initial dialog, now trying again");
expectingDialog = true; expectingDialog = true;
wantToClose = true; wantToClose = true;
resolveDialogPromise = null; resolveDialogPromise = null;
document firstTab.closeButton.click();
.getAnonymousElementByAttribute(firstTab, "anonid", "close-button")
.click();
await windowClosedPromise; await windowClosedPromise;
ok(!expectingDialog, "There should have been a dialog."); ok(!expectingDialog, "There should have been a dialog.");
ok(newWin.closed, "Window should be closed."); 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", "Write something here",
"The macOS services got the selected content text" "The macOS services got the selected content text"
); );
gURLBar.value = "test.mozilla.org"; gURLBar.value = "test.mozilla.org";
await gURLBar.focus(); await gURLBar.editor.selectAll();
await BrowserTestUtils.synthesizeKey(
"KEY_ArrowRight",
{ shiftKey: true, ctrlKey: true },
gBrowser.selectedBrowser
);
selectedText = DOMWindowUtils.GetSelectionAsPlaintext(); selectedText = DOMWindowUtils.GetSelectionAsPlaintext();
is( is(
selectedText, selectedText,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -526,7 +526,7 @@ function test_emitLatchedEvents(eventPrefix, initialDelta, cmd) {
} }
function test_addCommand(prefName, id) { 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("id", id);
cmd.setAttribute("oncommand", "this.callCount++;"); cmd.setAttribute("oncommand", "this.callCount++;");

View File

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

View File

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

View File

@ -200,9 +200,10 @@ async function drop(dragData, expectedURLs, ignoreFirstWindow = false) {
EventUtils EventUtils
); );
// Since synthesizeDrop triggers the srcElement, need to use another button. // Since synthesizeDrop triggers the srcElement, need to use another button
let dragSrcElement = document.getElementById("downloads-button"); // that should be visible.
ok(dragSrcElement, "Downloads button exists"); let dragSrcElement = document.getElementById("sidebar-button");
ok(dragSrcElement, "Sidebar button exists");
let newWindowButton = document.getElementById("new-window-button"); let newWindowButton = document.getElementById("new-window-button");
ok(newWindowButton, "New Window button exists"); 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() { function promiseNewWindow() {
return new Promise(resolve => { return new Promise(resolve => {
let observer = (subject, topic, data) => { let observer = (win, topic, data) => {
if (topic == "domwindowopened") { if (topic == "domwindowopened") {
Services.ww.unregisterNotification(observer); Services.ww.unregisterNotification(observer);
let win = subject.QueryInterface(Ci.nsIDOMWindow);
win.addEventListener( win.addEventListener(
"load", "load",
function() { function() {

View File

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

View File

@ -1,7 +1,7 @@
"use strict"; "use strict";
const ROOT = getRootDirectory(gTestPath); 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. // 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 // 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") && if (waitSteps > 0 && navigator.platform.includes("Linux") &&
panel.screenY == 210) { panel.screenY == 210) {
waitSteps--; waitSteps--;
/* eslint-disable mozilla/no-arbitrary-setTimeout */
setTimeout(popupShown, 10, event); setTimeout(popupShown, 10, event);
return; return;
} }
@ -90,7 +91,7 @@ function createPanel(attrs)
button.width = 120; button.width = 120;
button.height = 40; button.height = 40;
button.setAttribute("style", "appearance: none; border: 0; margin: 0;"); 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); return document.documentElement.appendChild(panel);
} }

View File

@ -676,6 +676,11 @@ function compareFocusResults() {
? browser1.contentWindow ? browser1.contentWindow
: browser2.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; var focusedElement = fm.focusedElement;
is( is(
@ -698,13 +703,7 @@ function compareFocusResults() {
is(matchWindow.document.hasFocus(), true, currentTestName + " hasFocus"); is(matchWindow.document.hasFocus(), true, currentTestName + " hasFocus");
var expectedActive = _expectedElement; var expectedActive = _expectedElement;
if (!expectedActive) { if (!expectedActive) {
// Documents that have a XUL document element currently have a different expectedActive = getId(matchWindow.document.body);
// 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);
} }
is( is(
getId(matchWindow.document.activeElement), getId(matchWindow.document.activeElement),

View File

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

View File

@ -3,21 +3,20 @@ function test() {
BrowserTestUtils.addTab(gBrowser); BrowserTestUtils.addTab(gBrowser);
BrowserTestUtils.addTab(gBrowser); BrowserTestUtils.addTab(gBrowser);
var tabs = gBrowser.tabs;
var owner; 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(); BrowserOpenTab();
is(gBrowser.selectedTab, tabs[4], "newly opened tab is selected"); is(gBrowser.selectedTab, gBrowser.tabs[4], "newly opened tab is selected");
gBrowser.removeCurrentTab(); gBrowser.removeCurrentTab();
is(gBrowser.selectedTab, owner, "owner is selected"); is(gBrowser.selectedTab, owner, "owner is selected");
owner = gBrowser.selectedTab; owner = gBrowser.selectedTab;
BrowserOpenTab(); BrowserOpenTab();
gBrowser.selectedTab = tabs[1]; gBrowser.selectedTab = gBrowser.tabs[1];
gBrowser.selectedTab = tabs[4]; gBrowser.selectedTab = gBrowser.tabs[4];
gBrowser.removeCurrentTab(); gBrowser.removeCurrentTab();
isnot( isnot(
gBrowser.selectedTab, gBrowser.selectedTab,
@ -32,10 +31,10 @@ function test() {
is( is(
gBrowser.selectedTab, gBrowser.selectedTab,
owner, 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(); gBrowser.removeCurrentTab();
} }
} }

View File

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

View File

@ -1,6 +1,8 @@
[DEFAULT] [DEFAULT]
support-files = head.js support-files = head.js
[browser_popup_keyNav.js]
support-files = focusableContent.html
[browser_toolbarButtonKeyPress.js] [browser_toolbarButtonKeyPress.js]
[browser_toolbarKeyNav.js] [browser_toolbarKeyNav.js]
support-files = !/browser/base/content/test/permissions/permissions.html 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"); 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) { function startFromUrlBar(aWindow = window) {
aWindow.gURLBar.focus(); aWindow.gURLBar.focus();
is( 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.focus();
aElem.removeAttribute("tabindex"); 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