mirror of
https://github.com/Feodor2/Mypal68.git
synced 2025-06-18 06:45:44 -04:00
68.14.8 - browser
This commit is contained in:
parent
b05a35282e
commit
2c58d3cb35
@ -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),
|
||||
});
|
||||
}
|
||||
}
|
@ -20,7 +20,6 @@ XPCOMUtils.defineLazyGlobalGetters(this, ["URL"]);
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
BrowserUtils: "resource://gre/modules/BrowserUtils.jsm",
|
||||
findAllCssSelectors: "resource://gre/modules/css-selector.js",
|
||||
SpellCheckHelper: "resource://gre/modules/InlineSpellChecker.jsm",
|
||||
LoginManagerContent: "resource://gre/modules/LoginManagerContent.jsm",
|
||||
WebNavigationFrames: "resource://gre/modules/WebNavigationFrames.jsm",
|
||||
@ -575,7 +574,6 @@ class ContextMenuChild extends ActorChild {
|
||||
let selectionInfo = BrowserUtils.getSelectionDetails(this.content);
|
||||
let loadContext = this.docShell.QueryInterface(Ci.nsILoadContext);
|
||||
let userContextId = loadContext.originAttributes.userContextId;
|
||||
let popupNodeSelectors = findAllCssSelectors(aEvent.composedTarget);
|
||||
|
||||
this._setContext(aEvent);
|
||||
let context = this.context;
|
||||
@ -652,7 +650,6 @@ class ContextMenuChild extends ActorChild {
|
||||
customMenuItems,
|
||||
contentDisposition,
|
||||
frameOuterWindowID,
|
||||
popupNodeSelectors,
|
||||
disableSetDesktopBg,
|
||||
parentAllowsMixedContent,
|
||||
};
|
||||
|
@ -119,6 +119,7 @@ class LinkHandlerChild extends ActorChild {
|
||||
case "apple-touch-icon-precomposed":
|
||||
case "fluid-icon":
|
||||
isRichIcon = true;
|
||||
// fall through
|
||||
case "icon":
|
||||
if (iconAdded || link.hasAttribute("mask")) {
|
||||
// Masked icons are not supported yet.
|
||||
|
@ -81,7 +81,11 @@ const PREF_SERVICES_SETTINGS_CLOCK_SKEW_SECONDS =
|
||||
const PREF_SERVICES_SETTINGS_LAST_FETCHED =
|
||||
"services.settings.last_update_seconds";
|
||||
|
||||
const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.", "security.ssl3."];
|
||||
const PREF_SSL_IMPACT_ROOTS = [
|
||||
"security.tls.version.",
|
||||
"security.ssl3.",
|
||||
"security.tls13.",
|
||||
];
|
||||
|
||||
let formatter = new Services.intl.DateTimeFormat(undefined, {
|
||||
dateStyle: "long",
|
||||
|
@ -104,7 +104,7 @@ class PageStyleChild extends ActorChild {
|
||||
}
|
||||
|
||||
// Skip any stylesheets that don't match the screen media type.
|
||||
if (currentStyleSheet.media.length > 0) {
|
||||
if (currentStyleSheet.media.length) {
|
||||
let mediaQueryList = currentStyleSheet.media.mediaText;
|
||||
if (!content.matchMedia(mediaQueryList).matches) {
|
||||
continue;
|
||||
|
@ -158,7 +158,6 @@ class PluginChild extends ActorChild {
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(
|
||||
Ci.nsIPluginHost
|
||||
);
|
||||
pluginElement.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
|
||||
let tagMimetype;
|
||||
let pluginName = gNavigatorBundle.GetStringFromName(
|
||||
@ -577,8 +576,8 @@ class PluginChild extends ActorChild {
|
||||
"openPluginUpdatePage",
|
||||
pluginTag
|
||||
);
|
||||
/* FALLTHRU */
|
||||
|
||||
/* FALLTHRU */
|
||||
case "PluginVulnerableNoUpdate":
|
||||
case "PluginClickToPlay":
|
||||
this._handleClickToPlayEvent(plugin);
|
||||
@ -763,14 +762,13 @@ class PluginChild extends ActorChild {
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(
|
||||
Ci.nsIPluginHost
|
||||
);
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
// guard against giving pluginHost.getPermissionStringForType a type
|
||||
// not associated with any known plugin
|
||||
if (!this.isKnownPlugin(objLoadingContent)) {
|
||||
if (!this.isKnownPlugin(plugin)) {
|
||||
return;
|
||||
}
|
||||
let permissionString = pluginHost.getPermissionStringForType(
|
||||
objLoadingContent.actualType
|
||||
plugin.actualType
|
||||
);
|
||||
let principal = doc.defaultView.top.document.nodePrincipal;
|
||||
let pluginPermission = Services.perms.testPermissionFromPrincipal(
|
||||
@ -797,8 +795,7 @@ class PluginChild extends ActorChild {
|
||||
}
|
||||
|
||||
onOverlayClick(event) {
|
||||
let document = event.target.ownerDocument;
|
||||
let plugin = document.getBindingParent(event.target);
|
||||
let plugin = event.target.containingShadowRoot.host;
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
// Have to check that the target is not the link to update the plugin
|
||||
if (
|
||||
@ -826,8 +823,7 @@ class PluginChild extends ActorChild {
|
||||
if (overlay) {
|
||||
overlay.removeEventListener("click", this, true);
|
||||
}
|
||||
let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (this.canActivatePlugin(objLoadingContent)) {
|
||||
if (this.canActivatePlugin(plugin)) {
|
||||
this._handleClickToPlayEvent(plugin);
|
||||
}
|
||||
}
|
||||
@ -847,7 +843,6 @@ class PluginChild extends ActorChild {
|
||||
|
||||
let pluginFound = false;
|
||||
for (let plugin of plugins) {
|
||||
plugin.QueryInterface(Ci.nsIObjectLoadingContent);
|
||||
if (!this.isKnownPlugin(plugin)) {
|
||||
continue;
|
||||
}
|
||||
@ -1110,8 +1105,6 @@ class PluginChild extends ActorChild {
|
||||
}
|
||||
|
||||
setCrashedNPAPIPluginState({ plugin, state, message }) {
|
||||
// Force a layout flush so the binding is attached.
|
||||
plugin.clientTop;
|
||||
let overlay = this.getPluginUI(plugin, "main");
|
||||
let statusDiv = this.getPluginUI(plugin, "submitStatus");
|
||||
let optInCB = this.getPluginUI(plugin, "submitURLOptIn");
|
||||
|
@ -22,7 +22,6 @@ with Files("WebRTCChild.jsm"):
|
||||
|
||||
FINAL_TARGET_FILES.actors += [
|
||||
'AboutReaderChild.jsm',
|
||||
'BlockedSiteChild.jsm',
|
||||
'BrowserTabChild.jsm',
|
||||
'ClickHandlerChild.jsm',
|
||||
'ContentSearchChild.jsm',
|
||||
|
@ -14,7 +14,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul");
|
||||
pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindowMac.xhtml");
|
||||
|
||||
// Enables some extra Extension System Logging (can reduce performance)
|
||||
pref("extensions.logging.enabled", false);
|
||||
@ -51,6 +51,9 @@ pref("extensions.webextensions.default-content-security-policy", "script-src 'se
|
||||
pref("extensions.webextensions.remote", true);
|
||||
pref("extensions.webextensions.background-delayed-startup", true);
|
||||
|
||||
// Disable extensionStorage storage actor by default
|
||||
pref("devtools.storage.extensionStorage.enabled", false);
|
||||
|
||||
// Dictionary download preference
|
||||
pref("browser.dictionaries.download.url", "data:text/plain,");
|
||||
|
||||
@ -199,17 +202,6 @@ pref("browser.warnOnQuit", true);
|
||||
pref("browser.fullscreen.autohide", true);
|
||||
pref("browser.overlink-delay", 80);
|
||||
|
||||
#ifdef UNIX_BUT_NOT_MAC
|
||||
pref("browser.urlbar.clickSelectsAll", false);
|
||||
#else
|
||||
pref("browser.urlbar.clickSelectsAll", true);
|
||||
#endif
|
||||
#ifdef UNIX_BUT_NOT_MAC
|
||||
pref("browser.urlbar.doubleClickSelectsAll", true);
|
||||
#else
|
||||
pref("browser.urlbar.doubleClickSelectsAll", false);
|
||||
#endif
|
||||
|
||||
// Whether using `ctrl` when hitting return/enter in the URL bar
|
||||
// (or clicking 'go') should prefix 'www.' and suffix
|
||||
// browser.fixup.alternate.suffix to the URL bar value prior to
|
||||
@ -272,8 +264,10 @@ pref("browser.urlbar.openintab", false);
|
||||
pref("browser.urlbar.usepreloadedtopurls.enabled", false);
|
||||
pref("browser.urlbar.usepreloadedtopurls.expire_days", 14);
|
||||
|
||||
// Enable the new Address Bar code.
|
||||
pref("browser.urlbar.quantumbar", true);
|
||||
pref("browser.urlbar.update1", false);
|
||||
pref("browser.urlbar.update1.expandTextOnFocus", false);
|
||||
|
||||
pref("browser.urlbar.openViewOnFocus", false);
|
||||
|
||||
pref("browser.altClickSave", false);
|
||||
|
||||
@ -325,10 +319,6 @@ pref("browser.search.hiddenOneOffs", "");
|
||||
// Mirrors whether the search-container widget is in the navigation toolbar.
|
||||
pref("browser.search.widget.inNavBar", true);
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
pref("browser.search.reset.enabled", true);
|
||||
#endif
|
||||
|
||||
pref("browser.sessionhistory.max_entries", 50);
|
||||
|
||||
// Built-in default permissions.
|
||||
@ -1095,7 +1085,6 @@ pref("services.sync.prefs.sync.browser.newtabpage.activity-stream.section.highli
|
||||
pref("services.sync.prefs.sync.browser.newtabpage.enabled", true);
|
||||
pref("services.sync.prefs.sync.browser.newtabpage.pinned", true);
|
||||
pref("services.sync.prefs.sync.browser.offline-apps.notify", true);
|
||||
pref("services.sync.prefs.sync.browser.sessionstore.restore_on_demand", true);
|
||||
pref("services.sync.prefs.sync.browser.startup.homepage", true);
|
||||
pref("services.sync.prefs.sync.browser.startup.page", true);
|
||||
pref("services.sync.prefs.sync.browser.tabs.loadInBackground", true);
|
||||
@ -1135,12 +1124,6 @@ pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true);
|
||||
pref("services.sync.prefs.sync.privacy.fuzzyfox.enabled", false);
|
||||
pref("services.sync.prefs.sync.privacy.fuzzyfox.clockgrainus", false);
|
||||
pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true);
|
||||
pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true);
|
||||
pref("services.sync.prefs.sync.privacy.trackingprotection.cryptomining.enabled", true);
|
||||
pref("services.sync.prefs.sync.privacy.trackingprotection.cryptomining.annotate.enabled", true);
|
||||
pref("services.sync.prefs.sync.privacy.trackingprotection.fingerprinting.enabled", true);
|
||||
pref("services.sync.prefs.sync.privacy.trackingprotection.fingerprinting.annotate.enabled", true);
|
||||
pref("services.sync.prefs.sync.privacy.trackingprotection.pbmode.enabled", true);
|
||||
pref("services.sync.prefs.sync.privacy.resistFingerprinting", true);
|
||||
pref("services.sync.prefs.sync.privacy.reduceTimerPrecision", true);
|
||||
pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.microseconds", true);
|
||||
@ -1352,8 +1335,6 @@ pref("media.gmp.trial-create.enabled", true);
|
||||
pref("media.gmp-gmpopenh264.visible", true);
|
||||
pref("media.gmp-gmpopenh264.enabled", true);
|
||||
|
||||
// Switch block autoplay logic to v2, and enable UI.
|
||||
pref("media.autoplay.enabled.user-gestures-needed", true);
|
||||
// Set Firefox to block autoplay, asking for permission by default.
|
||||
pref("media.autoplay.default", 1); // 0=Allowed, 1=Blocked, 5=All Blocked
|
||||
|
||||
@ -1414,10 +1395,6 @@ pref("media.gmp-provider.enabled", true);
|
||||
// Enable blocking access to storage from tracking resources only in nightly
|
||||
// and early beta. By default the value is 0: BEHAVIOR_ACCEPT
|
||||
pref("network.cookie.cookieBehavior", 4 /* BEHAVIOR_REJECT_TRACKER */);
|
||||
// Enable fingerprinting blocking by default only in nightly and early beta.
|
||||
pref("privacy.trackingprotection.fingerprinting.enabled", true);
|
||||
// Enable cryptomining blocking by default only in nightly and early beta.
|
||||
pref("privacy.trackingprotection.cryptomining.enabled", true);
|
||||
#endif
|
||||
|
||||
pref("dom.storage_access.enabled", true);
|
||||
@ -1428,39 +1405,6 @@ pref("browser.contentblocking.trackingprotection.control-center.ui.enabled", tru
|
||||
pref("browser.contentblocking.control-center.ui.showBlockedLabels", true);
|
||||
pref("browser.contentblocking.control-center.ui.showAllowedLabels", false);
|
||||
|
||||
pref("browser.contentblocking.cryptomining.preferences.ui.enabled", true);
|
||||
pref("browser.contentblocking.fingerprinting.preferences.ui.enabled", true);
|
||||
|
||||
// Possible values for browser.contentblocking.features.strict pref:
|
||||
// Tracking Protection:
|
||||
// "tp": tracking protection enabled
|
||||
// "-tp": tracking protection disabled
|
||||
// Tracking Protection in private windows:
|
||||
// "tpPrivate": tracking protection in private windows enabled
|
||||
// "-tpPrivate": tracking protection in private windows disabled
|
||||
// Fingerprinting:
|
||||
// "fp": fingerprinting blocking enabled
|
||||
// "-fp": fingerprinting blocking disabled
|
||||
// Cryptomining:
|
||||
// "cm": cryptomining blocking enabled
|
||||
// "-cm": cryptomining blocking disabled
|
||||
// Cookie behavior:
|
||||
// "cookieBehavior0": cookie behaviour BEHAVIOR_ACCEPT
|
||||
// "cookieBehavior1": cookie behaviour BEHAVIOR_REJECT_FOREIGN
|
||||
// "cookieBehavior2": cookie behaviour BEHAVIOR_REJECT
|
||||
// "cookieBehavior3": cookie behaviour BEHAVIOR_LIMIT_FOREIGN
|
||||
// "cookieBehavior4": cookie behaviour BEHAVIOR_REJECT_TRACKER
|
||||
// "cookieBehavior5": cookie behaviour BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN
|
||||
// One value from each section must be included in the browser.contentblocking.features.strict pref.
|
||||
pref("browser.contentblocking.features.strict", "tp,tpPrivate,cookieBehavior4,cm,fp");
|
||||
|
||||
// Enable the Report Breakage UI on Nightly and Beta but not on Release yet.
|
||||
pref("browser.contentblocking.reportBreakage.enabled", false);
|
||||
// Show report breakage for tracking cookies in all channels.
|
||||
pref("browser.contentblocking.rejecttrackers.reportBreakage.enabled", true);
|
||||
|
||||
pref("browser.contentblocking.reportBreakage.url", "data:text/plain,");
|
||||
|
||||
// Enables the new Protections Panel.
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("browser.protections_panel.enabled", true);
|
||||
@ -1472,19 +1416,14 @@ pref("privacy.usercontext.about_newtab_segregation.enabled", true);
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("privacy.userContext.enabled", true);
|
||||
pref("privacy.userContext.ui.enabled", true);
|
||||
|
||||
// 0 disables long press, 1 when clicked, the menu is shown, 2 the menu is
|
||||
// shown after X milliseconds.
|
||||
pref("privacy.userContext.longPressBehavior", 2);
|
||||
#else
|
||||
pref("privacy.userContext.enabled", false);
|
||||
pref("privacy.userContext.ui.enabled", false);
|
||||
|
||||
// 0 disables long press, 1 when clicked, the menu is shown, 2 the menu is
|
||||
// shown after X milliseconds.
|
||||
pref("privacy.userContext.longPressBehavior", 0);
|
||||
#endif
|
||||
pref("privacy.userContext.extension", "");
|
||||
// allows user to open container menu on a left click instead of a new
|
||||
// tab in the default container
|
||||
pref("privacy.userContext.newTabContainerOnLeftClick.enabled", false);
|
||||
|
||||
// Start the browser in e10s mode
|
||||
pref("browser.tabs.remote.autostart", true);
|
||||
@ -1508,30 +1447,11 @@ pref("browser.tabs.crashReporting.requestEmail", false);
|
||||
pref("browser.tabs.crashReporting.emailMe", false);
|
||||
pref("browser.tabs.crashReporting.email", "");
|
||||
|
||||
// How often to check for CPOW timeouts. CPOWs are only timed out by
|
||||
// the hang monitor.
|
||||
pref("dom.ipc.cpow.timeout", 500);
|
||||
|
||||
// Causes access on unsafe CPOWs from browser code to throw by default.
|
||||
pref("dom.ipc.cpows.forbid-unsafe-from-browser", true);
|
||||
|
||||
// Enable e10s hang monitoring (slow script checking and plugin hang
|
||||
// detection).
|
||||
pref("dom.ipc.processHangMonitor", false);
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// Allows us to deprioritize the processes of background tabs at an OS level
|
||||
pref("dom.ipc.processPriorityManager.enabled", true);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
// Don't report hangs in DEBUG builds. They're too slow and often a
|
||||
// debugger is attached.
|
||||
pref("dom.ipc.reportProcessHangs", false);
|
||||
#else
|
||||
pref("dom.ipc.reportProcessHangs", true);
|
||||
#endif
|
||||
|
||||
// Don't limit how many nodes we care about on desktop:
|
||||
pref("reader.parse-node-limit", 0);
|
||||
|
||||
@ -1646,13 +1566,6 @@ pref("browser.toolbars.keyboard_navigation", true);
|
||||
pref("identity.fxaccounts.toolbar.enabled", false);
|
||||
pref("identity.fxaccounts.toolbar.accessed", false);
|
||||
|
||||
// Check bundled JAR and XPI files for corruption.
|
||||
#ifdef RELEASE_OR_BETA
|
||||
pref("corroborator.enabled", false);
|
||||
#else
|
||||
pref("corroborator.enabled", true);
|
||||
#endif
|
||||
|
||||
// Toolbox preferences
|
||||
pref("devtools.toolbox.footer.height", 250);
|
||||
pref("devtools.toolbox.sidebar.width", 500);
|
||||
@ -1670,7 +1583,6 @@ pref("devtools.command-button-pick.enabled", true);
|
||||
pref("devtools.command-button-frames.enabled", true);
|
||||
pref("devtools.command-button-splitconsole.enabled", true);
|
||||
pref("devtools.command-button-paintflashing.enabled", false);
|
||||
pref("devtools.command-button-scratchpad.enabled", false);
|
||||
pref("devtools.command-button-responsive.enabled", true);
|
||||
pref("devtools.command-button-screenshot.enabled", false);
|
||||
pref("devtools.command-button-rulers.enabled", false);
|
||||
@ -1847,23 +1759,6 @@ pref("devtools.netmonitor.har.enableAutoExportToFile", false);
|
||||
pref("devtools.netmonitor.features.webSockets", false);
|
||||
#endif
|
||||
|
||||
// Scratchpad settings
|
||||
// - recentFileMax: The maximum number of recently-opened files
|
||||
// stored. Setting this preference to 0 will not
|
||||
// clear any recent files, but rather hide the
|
||||
// 'Open Recent'-menu.
|
||||
// - lineNumbers: Whether to show line numbers or not.
|
||||
// - wrapText: Whether to wrap text or not.
|
||||
// - showTrailingSpace: Whether to highlight trailing space or not.
|
||||
// - editorFontSize: Editor font size configuration.
|
||||
// - enableAutocompletion: Whether to enable JavaScript autocompletion.
|
||||
pref("devtools.scratchpad.recentFilesMax", 10);
|
||||
pref("devtools.scratchpad.lineNumbers", true);
|
||||
pref("devtools.scratchpad.wrapText", false);
|
||||
pref("devtools.scratchpad.showTrailingSpace", false);
|
||||
pref("devtools.scratchpad.editorFontSize", 12);
|
||||
pref("devtools.scratchpad.enableAutocompletion", true);
|
||||
|
||||
// Enable the Storage Inspector
|
||||
pref("devtools.storage.enabled", true);
|
||||
|
||||
@ -1879,9 +1774,6 @@ pref("devtools.styleeditor.transitions", true);
|
||||
pref("devtools.screenshot.clipboard.enabled", false);
|
||||
pref("devtools.screenshot.audio.enabled", true);
|
||||
|
||||
// Enable Scratchpad
|
||||
pref("devtools.scratchpad.enabled", false);
|
||||
|
||||
// Make sure the DOM panel is hidden by default
|
||||
pref("devtools.dom.enabled", false);
|
||||
|
||||
@ -1932,13 +1824,6 @@ pref("devtools.webconsole.timestampMessages", false);
|
||||
pref("devtools.webconsole.sidebarToggle", false);
|
||||
#endif
|
||||
|
||||
// Enable editor mode in the console in Nightly builds.
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
pref("devtools.webconsole.features.editor", true);
|
||||
#else
|
||||
pref("devtools.webconsole.features.editor", false);
|
||||
#endif
|
||||
|
||||
// Saved editor mode state in the console.
|
||||
pref("devtools.webconsole.input.editor", false);
|
||||
|
||||
@ -2000,13 +1885,6 @@ pref("devtools.responsive.metaViewport.enabled", false);
|
||||
// The user agent of the viewport.
|
||||
pref("devtools.responsive.userAgent", "");
|
||||
|
||||
// Whether to show the settings onboarding tooltip only in release or beta
|
||||
// builds.
|
||||
#if defined(RELEASE_OR_BETA)
|
||||
pref("devtools.responsive.show-setting-tooltip", true);
|
||||
#else
|
||||
pref("devtools.responsive.show-setting-tooltip", false);
|
||||
#endif
|
||||
// Show the custom user agent input in Nightly builds.
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
pref("devtools.responsive.showUserAgentInput", true);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Note: this file is included in aboutDialog.xul and preferences/advanced.xul
|
||||
// Note: this file is included in aboutDialog.xhtml and preferences/advanced.xhtml
|
||||
// if MOZ_UPDATER is defined.
|
||||
|
||||
/* import-globals-from aboutDialog.js */
|
||||
|
@ -2,7 +2,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Note: this file is included in aboutDialog.xul and preferences/advanced.xul
|
||||
// Note: this file is included in aboutDialog.xhtml and preferences/advanced.xhtml
|
||||
// if MOZ_UPDATER is defined.
|
||||
|
||||
/* import-globals-from aboutDialog.js */
|
||||
|
@ -31,7 +31,7 @@
|
||||
aria-describedby="version distribution distributionId communityDesc trademark"
|
||||
>
|
||||
#ifdef XP_MACOSX
|
||||
#include macWindow.inc.xul
|
||||
#include macWindow.inc.xhtml
|
||||
#endif
|
||||
|
||||
<linkset>
|
@ -6,6 +6,7 @@
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" />
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://global/skin/in-content/info-pages.css"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" />
|
||||
<title>&loadError.label;</title>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/aboutNetError.css" type="text/css" media="all" />
|
||||
<!-- If the location of the favicon is changed here, the FAVICON_ERRORPAGE_URL symbol in
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" />
|
||||
<title data-l10n-id="restart-required-title"></title>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/skin/aboutRestartRequired.css"/>
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" />
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://global/skin/in-content/info-pages.css"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
|
@ -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();
|
@ -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
@ -4,36 +4,29 @@
|
||||
|
||||
<menugroup id="context-navigation">
|
||||
<menuitem id="context-back"
|
||||
data-l10n-id="main-context-menu-back"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&backButton.tooltip;"
|
||||
aria-label="&backCmd.label;"
|
||||
command="Browser:BackOrBackDuplicate"
|
||||
accesskey="&backCmd.accesskey;"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-forward"
|
||||
data-l10n-id="main-context-menu-forward"
|
||||
class="menuitem-iconic"
|
||||
tooltiptext="&forwardButton.tooltip;"
|
||||
aria-label="&forwardCmd.label;"
|
||||
command="Browser:ForwardOrForwardDuplicate"
|
||||
accesskey="&forwardCmd.accesskey;"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-reload"
|
||||
class="menuitem-iconic"
|
||||
tooltip="dynamic-shortcut-tooltip"
|
||||
aria-label="&reloadCmd.label;"
|
||||
data-l10n-id="main-context-menu-reload"
|
||||
command="Browser:ReloadOrDuplicate"
|
||||
accesskey="&reloadCmd.accesskey;"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-stop"
|
||||
class="menuitem-iconic"
|
||||
tooltip="dynamic-shortcut-tooltip"
|
||||
aria-label="&stopCmd.label;"
|
||||
accesskey="&stopCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-stop"
|
||||
command="Browser:Stop"/>
|
||||
<menuitem id="context-bookmarkpage"
|
||||
class="menuitem-iconic"
|
||||
aria-label="&bookmarkPageCmd2.label;"
|
||||
accesskey="&bookmarkPageCmd2.accesskey;"
|
||||
data-l10n-id="main-context-menu-bookmark-page"
|
||||
oncommand="gContextMenu.bookmarkThisPage();"/>
|
||||
</menugroup>
|
||||
<menuseparator id="context-sep-navigation"/>
|
||||
@ -51,264 +44,211 @@
|
||||
oncommand="InlineSpellCheckerUI.undoAddToDictionary();" />
|
||||
<menuseparator id="spell-suggestions-separator"/>
|
||||
<menuitem id="context-openlinkincurrent"
|
||||
label="&openLinkCmdInCurrent.label;"
|
||||
accesskey="&openLinkCmdInCurrent.accesskey;"
|
||||
data-l10n-id="main-context-menu-open-link"
|
||||
oncommand="gContextMenu.openLinkInCurrent();"/>
|
||||
# label and data-usercontextid are dynamically set.
|
||||
<menuitem id="context-openlinkincontainertab"
|
||||
accesskey="&openLinkCmdInTab.accesskey;"
|
||||
oncommand="gContextMenu.openLinkInTab(event);"/>
|
||||
<menuitem id="context-openlinkintab"
|
||||
label="&openLinkCmdInTab.label;"
|
||||
accesskey="&openLinkCmdInTab.accesskey;"
|
||||
data-l10n-id="main-context-menu-open-link-new-tab"
|
||||
data-usercontextid="0"
|
||||
oncommand="gContextMenu.openLinkInTab(event);"/>
|
||||
|
||||
<menu id="context-openlinkinusercontext-menu"
|
||||
label="&openLinkCmdInContainerTab.label;"
|
||||
accesskey="&openLinkCmdInContainerTab.accesskey;"
|
||||
data-l10n-id="main-context-menu-open-link-container-tab"
|
||||
hidden="true">
|
||||
<menupopup oncommand="gContextMenu.openLinkInTab(event);"
|
||||
onpopupshowing="return gContextMenu.createContainerMenu(event);" />
|
||||
</menu>
|
||||
|
||||
<menuitem id="context-openlink"
|
||||
label="&openLinkCmd.label;"
|
||||
accesskey="&openLinkCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-open-link-new-window"
|
||||
oncommand="gContextMenu.openLink();"/>
|
||||
<menuitem id="context-openlinkprivate"
|
||||
label="&openLinkInPrivateWindowCmd.label;"
|
||||
accesskey="&openLinkInPrivateWindowCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-open-link-new-private-window"
|
||||
oncommand="gContextMenu.openLinkInPrivateWindow();"/>
|
||||
<menuseparator id="context-sep-open"/>
|
||||
<menuitem id="context-bookmarklink"
|
||||
label="&bookmarkThisLinkCmd.label;"
|
||||
accesskey="&bookmarkThisLinkCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-bookmark-this-link"
|
||||
oncommand="gContextMenu.bookmarkLink();"/>
|
||||
<menuitem id="context-savelink"
|
||||
label="&saveLinkCmd.label;"
|
||||
accesskey="&saveLinkCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-save-link"
|
||||
oncommand="gContextMenu.saveLink();"/>
|
||||
<menuitem id="context-copyemail"
|
||||
label="©EmailCmd.label;"
|
||||
accesskey="©EmailCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-copy-email"
|
||||
oncommand="gContextMenu.copyEmail();"/>
|
||||
<menuitem id="context-copylink"
|
||||
label="©LinkCmd.label;"
|
||||
accesskey="©LinkCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-copy-link"
|
||||
oncommand="gContextMenu.copyLink();"/>
|
||||
<menuseparator id="context-sep-copylink"/>
|
||||
<menuitem id="context-media-play"
|
||||
label="&mediaPlay.label;"
|
||||
accesskey="&mediaPlay.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-play"
|
||||
oncommand="gContextMenu.mediaCommand('play');"/>
|
||||
<menuitem id="context-media-pause"
|
||||
label="&mediaPause.label;"
|
||||
accesskey="&mediaPause.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-pause"
|
||||
oncommand="gContextMenu.mediaCommand('pause');"/>
|
||||
<menuitem id="context-media-mute"
|
||||
label="&mediaMute.label;"
|
||||
accesskey="&mediaMute.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-mute"
|
||||
oncommand="gContextMenu.mediaCommand('mute');"/>
|
||||
<menuitem id="context-media-unmute"
|
||||
label="&mediaUnmute.label;"
|
||||
accesskey="&mediaUnmute.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-unmute"
|
||||
oncommand="gContextMenu.mediaCommand('unmute');"/>
|
||||
<menu id="context-media-playbackrate" label="&mediaPlaybackRate2.label;" accesskey="&mediaPlaybackRate2.accesskey;">
|
||||
<menu id="context-media-playbackrate" data-l10n-id="main-context-menu-media-play-speed">
|
||||
<menupopup>
|
||||
<menuitem id="context-media-playbackrate-050x"
|
||||
label="&mediaPlaybackRate050x2.label;"
|
||||
accesskey="&mediaPlaybackRate050x2.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-play-speed-slow"
|
||||
type="radio"
|
||||
name="playbackrate"
|
||||
oncommand="gContextMenu.mediaCommand('playbackRate', 0.5);"/>
|
||||
<menuitem id="context-media-playbackrate-100x"
|
||||
label="&mediaPlaybackRate100x2.label;"
|
||||
accesskey="&mediaPlaybackRate100x2.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-play-speed-normal"
|
||||
type="radio"
|
||||
name="playbackrate"
|
||||
checked="true"
|
||||
oncommand="gContextMenu.mediaCommand('playbackRate', 1.0);"/>
|
||||
<menuitem id="context-media-playbackrate-125x"
|
||||
label="&mediaPlaybackRate125x2.label;"
|
||||
accesskey="&mediaPlaybackRate125x2.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-play-speed-fast"
|
||||
type="radio"
|
||||
name="playbackrate"
|
||||
oncommand="gContextMenu.mediaCommand('playbackRate', 1.25);"/>
|
||||
<menuitem id="context-media-playbackrate-150x"
|
||||
label="&mediaPlaybackRate150x2.label;"
|
||||
accesskey="&mediaPlaybackRate150x2.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-play-speed-faster"
|
||||
type="radio"
|
||||
name="playbackrate"
|
||||
oncommand="gContextMenu.mediaCommand('playbackRate', 1.5);"/>
|
||||
<menuitem id="context-media-playbackrate-200x"
|
||||
label="&mediaPlaybackRate200x2.label;"
|
||||
accesskey="&mediaPlaybackRate200x2.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-play-speed-fastest"
|
||||
type="radio"
|
||||
name="playbackrate"
|
||||
oncommand="gContextMenu.mediaCommand('playbackRate', 2.0);"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuitem id="context-media-loop"
|
||||
label="&mediaLoop.label;"
|
||||
accesskey="&mediaLoop.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-loop"
|
||||
type="checkbox"
|
||||
oncommand="gContextMenu.mediaCommand('loop');"/>
|
||||
<menuitem id="context-media-showcontrols"
|
||||
label="&mediaShowControls.label;"
|
||||
accesskey="&mediaShowControls.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-show-controls"
|
||||
oncommand="gContextMenu.mediaCommand('showcontrols');"/>
|
||||
<menuitem id="context-media-hidecontrols"
|
||||
label="&mediaHideControls.label;"
|
||||
accesskey="&mediaHideControls.accesskey;"
|
||||
data-l10n-id="main-context-menu-media-hide-controls"
|
||||
oncommand="gContextMenu.mediaCommand('hidecontrols');"/>
|
||||
<menuitem id="context-video-fullscreen"
|
||||
accesskey="&videoFullScreen.accesskey;"
|
||||
label="&videoFullScreen.label;"
|
||||
data-l10n-id="main-context-menu-media-video-fullscreen"
|
||||
oncommand="gContextMenu.mediaCommand('fullscreen');"/>
|
||||
<menuitem id="context-leave-dom-fullscreen"
|
||||
accesskey="&leaveDOMFullScreen.accesskey;"
|
||||
label="&leaveDOMFullScreen.label;"
|
||||
data-l10n-id="main-context-menu-media-video-leave-fullscreen"
|
||||
oncommand="gContextMenu.leaveDOMFullScreen();"/>
|
||||
<menuitem id="context-video-pictureinpicture"
|
||||
accesskey="&pictureInPicture.accesskey;"
|
||||
label="&pictureInPicture.label;"
|
||||
data-l10n-id="main-context-menu-media-pip"
|
||||
type="checkbox"
|
||||
oncommand="gContextMenu.mediaCommand('pictureinpicture');"/>
|
||||
<menuseparator id="context-media-sep-commands"/>
|
||||
<menuitem id="context-reloadimage"
|
||||
label="&reloadImageCmd.label;"
|
||||
accesskey="&reloadImageCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-image-reload"
|
||||
oncommand="gContextMenu.reloadImage();"/>
|
||||
<menuitem id="context-viewimage"
|
||||
label="&viewImageCmd.label;"
|
||||
accesskey="&viewImageCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-image-view"
|
||||
oncommand="gContextMenu.viewMedia(event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-viewvideo"
|
||||
label="&viewVideoCmd.label;"
|
||||
accesskey="&viewVideoCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-video-view"
|
||||
oncommand="gContextMenu.viewMedia(event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
#ifdef CONTEXT_COPY_IMAGE_CONTENTS
|
||||
<menuitem id="context-copyimage-contents"
|
||||
label="©ImageContentsCmd.label;"
|
||||
accesskey="©ImageContentsCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-image-copy"
|
||||
oncommand="goDoCommand('cmd_copyImage');"/>
|
||||
#endif
|
||||
<menuitem id="context-copyimage"
|
||||
label="©ImageCmd.label;"
|
||||
accesskey="©ImageCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-image-copy-location"
|
||||
oncommand="gContextMenu.copyMediaLocation();"/>
|
||||
<menuitem id="context-copyvideourl"
|
||||
label="©VideoURLCmd.label;"
|
||||
accesskey="©VideoURLCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-video-copy-location"
|
||||
oncommand="gContextMenu.copyMediaLocation();"/>
|
||||
<menuitem id="context-copyaudiourl"
|
||||
label="©AudioURLCmd.label;"
|
||||
accesskey="©AudioURLCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-audio-copy-location"
|
||||
oncommand="gContextMenu.copyMediaLocation();"/>
|
||||
<menuseparator id="context-sep-copyimage"/>
|
||||
<menuitem id="context-saveimage"
|
||||
label="&saveImageCmd.label;"
|
||||
accesskey="&saveImageCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-image-save-as"
|
||||
oncommand="gContextMenu.saveMedia();"/>
|
||||
<menuitem id="context-sendimage"
|
||||
label="&emailImageCmd.label;"
|
||||
accesskey="&emailImageCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-image-email"
|
||||
oncommand="gContextMenu.sendMedia();"/>
|
||||
<menuitem id="context-setDesktopBackground"
|
||||
label="&setDesktopBackgroundCmd.label;"
|
||||
accesskey="&setDesktopBackgroundCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-image-set-as-background"
|
||||
oncommand="gContextMenu.setDesktopBackground();"/>
|
||||
<menuitem id="context-viewimageinfo"
|
||||
label="&viewImageInfoCmd.label;"
|
||||
accesskey="&viewImageInfoCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-image-info"
|
||||
oncommand="gContextMenu.viewImageInfo();"/>
|
||||
<menuitem id="context-viewimagedesc"
|
||||
label="&viewImageDescCmd.label;"
|
||||
accesskey="&viewImageDescCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-image-desc"
|
||||
oncommand="gContextMenu.viewImageDesc(event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-savevideo"
|
||||
label="&saveVideoCmd.label;"
|
||||
accesskey="&saveVideoCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-video-save-as"
|
||||
oncommand="gContextMenu.saveMedia();"/>
|
||||
<menuitem id="context-saveaudio"
|
||||
label="&saveAudioCmd.label;"
|
||||
accesskey="&saveAudioCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-audio-save-as"
|
||||
oncommand="gContextMenu.saveMedia();"/>
|
||||
<menuitem id="context-video-saveimage"
|
||||
accesskey="&videoSaveImage.accesskey;"
|
||||
label="&videoSaveImage.label;"
|
||||
data-l10n-id="main-context-menu-video-image-save-as"
|
||||
oncommand="gContextMenu.saveVideoFrameAsImage();"/>
|
||||
<menuitem id="context-sendvideo"
|
||||
label="&emailVideoCmd.label;"
|
||||
accesskey="&emailVideoCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-video-email"
|
||||
oncommand="gContextMenu.sendMedia();"/>
|
||||
<menuitem id="context-sendaudio"
|
||||
label="&emailAudioCmd.label;"
|
||||
accesskey="&emailAudioCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-audio-email"
|
||||
oncommand="gContextMenu.sendMedia();"/>
|
||||
<menuitem id="context-ctp-play"
|
||||
label="&playPluginCmd.label;"
|
||||
accesskey="&playPluginCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-plugin-play"
|
||||
oncommand="gContextMenu.playPlugin();"/>
|
||||
<menuitem id="context-ctp-hide"
|
||||
label="&hidePluginCmd.label;"
|
||||
accesskey="&hidePluginCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-plugin-hide"
|
||||
oncommand="gContextMenu.hidePlugin();"/>
|
||||
<menuseparator id="context-sep-ctp"/>
|
||||
<menuitem id="context-savepage"
|
||||
label="&savePageCmd.label;"
|
||||
accesskey="&savePageCmd.accesskey2;"
|
||||
data-l10n-id="main-context-menu-page-save"
|
||||
oncommand="gContextMenu.savePageAs();"/>
|
||||
<menuseparator id="context-sep-sendpagetodevice" class="sync-ui-item"
|
||||
hidden="true"/>
|
||||
<menu id="context-sendpagetodevice"
|
||||
class="sync-ui-item"
|
||||
label="&sendPageToDevice.label;"
|
||||
accesskey="&sendPageToDevice.accesskey;"
|
||||
data-l10n-id="main-context-menu-send-to-device"
|
||||
hidden="true">
|
||||
<menupopup id="context-sendpagetodevice-popup"
|
||||
onpopupshowing="(() => { gSync.populateSendTabToDevicesMenu(event.target, gBrowser.currentURI.spec, gBrowser.contentTitle); })()"/>
|
||||
</menu>
|
||||
<menuseparator id="context-sep-viewbgimage"/>
|
||||
<menuitem id="context-viewbgimage"
|
||||
label="&viewBGImageCmd.label;"
|
||||
accesskey="&viewBGImageCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-view-background-image"
|
||||
oncommand="gContextMenu.viewBGImage(event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="context-undo"
|
||||
label="&undoCmd.label;"
|
||||
accesskey="&undoCmd.accesskey;"
|
||||
data-l10n-id="text-action-undo"
|
||||
command="cmd_undo"/>
|
||||
<menuseparator id="context-sep-undo"/>
|
||||
<menuitem id="context-cut"
|
||||
label="&cutCmd.label;"
|
||||
accesskey="&cutCmd.accesskey;"
|
||||
data-l10n-id="text-action-cut"
|
||||
command="cmd_cut"/>
|
||||
<menuitem id="context-copy"
|
||||
label="©Cmd.label;"
|
||||
accesskey="©Cmd.accesskey;"
|
||||
data-l10n-id="text-action-copy"
|
||||
command="cmd_copy"/>
|
||||
<menuitem id="context-paste"
|
||||
label="&pasteCmd.label;"
|
||||
accesskey="&pasteCmd.accesskey;"
|
||||
data-l10n-id="text-action-paste"
|
||||
command="cmd_paste"/>
|
||||
<menuitem id="context-delete"
|
||||
label="&deleteCmd.label;"
|
||||
accesskey="&deleteCmd.accesskey;"
|
||||
data-l10n-id="text-action-delete"
|
||||
command="cmd_delete"/>
|
||||
<menuseparator id="context-sep-paste"/>
|
||||
<menuitem id="context-selectall"
|
||||
label="&selectAllCmd.label;"
|
||||
accesskey="&selectAllCmd.accesskey;"
|
||||
data-l10n-id="text-action-select-all"
|
||||
command="cmd_selectAll"/>
|
||||
<menuseparator id="context-sep-selectall"/>
|
||||
<menuitem id="context-keywordfield"
|
||||
label="&keywordfield.label;"
|
||||
accesskey="&keywordfield.accesskey;"
|
||||
data-l10n-id="main-context-menu-keyword"
|
||||
oncommand="AddKeywordForSearchField();"/>
|
||||
<menuitem id="context-searchselect"
|
||||
oncommand="BrowserSearch.loadSearchFromContext(this.searchTerms, this.principal, this.csp);"/>
|
||||
@ -316,69 +256,56 @@
|
||||
hidden="true"/>
|
||||
<menu id="context-sendlinktodevice"
|
||||
class="sync-ui-item"
|
||||
label="&sendLinkToDevice.label;"
|
||||
accesskey="&sendLinkToDevice.accesskey;"
|
||||
data-l10n-id="main-context-menu-link-send-to-device"
|
||||
hidden="true">
|
||||
<menupopup id="context-sendlinktodevice-popup"
|
||||
onpopupshowing="gSync.populateSendTabToDevicesMenu(event.target, gContextMenu.linkURL, gContextMenu.linkTextStr);"/>
|
||||
</menu>
|
||||
<menuseparator id="frame-sep"/>
|
||||
<menu id="frame" label="&thisFrameMenu.label;" accesskey="&thisFrameMenu.accesskey;">
|
||||
<menu id="frame" data-l10n-id="main-context-menu-frame">
|
||||
<menupopup>
|
||||
<menuitem id="context-showonlythisframe"
|
||||
label="&showOnlyThisFrameCmd.label;"
|
||||
accesskey="&showOnlyThisFrameCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-frame-show-this"
|
||||
oncommand="gContextMenu.showOnlyThisFrame();"/>
|
||||
<menuitem id="context-openframeintab"
|
||||
label="&openFrameCmdInTab.label;"
|
||||
accesskey="&openFrameCmdInTab.accesskey;"
|
||||
data-l10n-id="main-context-menu-frame-open-tab"
|
||||
oncommand="gContextMenu.openFrameInTab();"/>
|
||||
<menuitem id="context-openframe"
|
||||
label="&openFrameCmd.label;"
|
||||
accesskey="&openFrameCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-frame-open-window"
|
||||
oncommand="gContextMenu.openFrame();"/>
|
||||
<menuseparator id="open-frame-sep"/>
|
||||
<menuitem id="context-reloadframe"
|
||||
label="&reloadFrameCmd.label;"
|
||||
accesskey="&reloadFrameCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-frame-reload"
|
||||
oncommand="gContextMenu.reloadFrame(event);"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="context-bookmarkframe"
|
||||
label="&bookmarkThisFrameCmd.label;"
|
||||
accesskey="&bookmarkThisFrameCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-frame-bookmark"
|
||||
oncommand="gContextMenu.addBookmarkForFrame();"/>
|
||||
<menuitem id="context-saveframe"
|
||||
label="&saveFrameCmd.label;"
|
||||
accesskey="&saveFrameCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-frame-save-as"
|
||||
oncommand="gContextMenu.saveFrame();"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="context-printframe"
|
||||
label="&printFrameCmd.label;"
|
||||
accesskey="&printFrameCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-frame-print"
|
||||
oncommand="gContextMenu.printFrame();"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="context-viewframesource"
|
||||
label="&viewFrameSourceCmd.label;"
|
||||
accesskey="&viewFrameSourceCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-frame-view-source"
|
||||
oncommand="gContextMenu.viewFrameSource();"/>
|
||||
<menuitem id="context-viewframeinfo"
|
||||
label="&viewFrameInfoCmd.label;"
|
||||
accesskey="&viewFrameInfoCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-frame-view-info"
|
||||
oncommand="gContextMenu.viewFrameInfo();"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuitem id="context-viewpartialsource-selection"
|
||||
label="&viewPartialSourceForSelectionCmd.label;"
|
||||
accesskey="&viewPartialSourceCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-view-selection-source"
|
||||
oncommand="gContextMenu.viewPartialSource();"/>
|
||||
<menuseparator id="context-sep-viewsource"/>
|
||||
<menuitem id="context-viewsource"
|
||||
label="&viewPageSourceCmd.label;"
|
||||
accesskey="&viewPageSourceCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-view-page-source"
|
||||
oncommand="BrowserViewSource(gContextMenu.browser);"/>
|
||||
<menuitem id="context-viewinfo"
|
||||
label="&viewPageInfoCmd.label;"
|
||||
accesskey="&viewPageInfoCmd.accesskey;"
|
||||
data-l10n-id="main-context-menu-view-page-info"
|
||||
oncommand="gContextMenu.viewInfo();"/>
|
||||
<menuseparator id="spell-separator"/>
|
||||
<menuitem id="spell-check-enabled"
|
||||
@ -403,12 +330,10 @@
|
||||
</menu>
|
||||
<menuseparator hidden="true" id="context-sep-bidi"/>
|
||||
<menuitem hidden="true" id="context-bidi-text-direction-toggle"
|
||||
label="&bidiSwitchTextDirectionItem.label;"
|
||||
accesskey="&bidiSwitchTextDirectionItem.accesskey;"
|
||||
data-l10n-id="main-context-menu-bidi-switch-text"
|
||||
command="cmd_switchTextDirection"/>
|
||||
<menuitem hidden="true" id="context-bidi-page-direction-toggle"
|
||||
label="&bidiSwitchPageDirectionItem.label;"
|
||||
accesskey="&bidiSwitchPageDirectionItem.accesskey;"
|
||||
data-l10n-id="main-context-menu-bidi-switch-page"
|
||||
oncommand="gContextMenu.switchPageDirection();"/>
|
||||
<menuseparator id="fill-login-separator" hidden="true"/>
|
||||
<menu id="fill-login"
|
||||
@ -441,10 +366,9 @@
|
||||
<menuseparator id="inspect-separator" hidden="true"/>
|
||||
<menuitem id="context-inspect"
|
||||
hidden="true"
|
||||
label="&inspectContextMenu.label;"
|
||||
accesskey="&inspectContextMenu.accesskey;"
|
||||
data-l10n-id="main-context-menu-inspect-element"
|
||||
oncommand="gContextMenu.inspectNode();"/>
|
||||
<menuitem id="context-inspect-a11y"
|
||||
hidden="true"
|
||||
label="&inspectA11YContextMenu.label;"
|
||||
data-l10n-id="main-context-menu-inspect-a11y-properties"
|
||||
oncommand="gContextMenu.inspectA11Y();"/>
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
/**
|
||||
* Customization handler prepares this browser window for entering and exiting
|
||||
* customization mode by handling customizationstarting and customizationending
|
||||
* customization mode by handling customizationstarting and aftercustomization
|
||||
* events.
|
||||
*/
|
||||
var CustomizationHandler = {
|
||||
@ -16,8 +16,8 @@ var CustomizationHandler = {
|
||||
case "customizationstarting":
|
||||
this._customizationStarting();
|
||||
break;
|
||||
case "customizationending":
|
||||
this._customizationEnding(aEvent.detail);
|
||||
case "aftercustomization":
|
||||
this._afterCustomization();
|
||||
break;
|
||||
}
|
||||
},
|
||||
@ -39,22 +39,16 @@ var CustomizationHandler = {
|
||||
UpdateUrlbarSearchSplitterState();
|
||||
|
||||
PlacesToolbarHelper.customizeStart();
|
||||
|
||||
gURLBarHandler.customizeStart();
|
||||
},
|
||||
|
||||
_customizationEnding(aDetails) {
|
||||
_afterCustomization() {
|
||||
// Update global UI elements that may have been added or removed
|
||||
if (aDetails.changed && AppConstants.platform != "macosx") {
|
||||
if (AppConstants.platform != "macosx") {
|
||||
updateEditUIVisibility();
|
||||
}
|
||||
|
||||
PlacesToolbarHelper.customizeDone();
|
||||
|
||||
UpdateUrlbarSearchSplitterState();
|
||||
|
||||
// Update the urlbar
|
||||
URLBarSetURI();
|
||||
XULBrowserWindow.asyncUpdateUI();
|
||||
|
||||
// Re-enable parts of the UI we disabled during the dialog
|
||||
@ -67,7 +61,9 @@ var CustomizationHandler = {
|
||||
|
||||
gBrowser.selectedBrowser.focus();
|
||||
|
||||
gURLBarHandler.customizeEnd();
|
||||
// Update the urlbar
|
||||
URLBarSetURI();
|
||||
UpdateUrlbarSearchSplitterState();
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -14,7 +14,5 @@
|
||||
%placesDTD;
|
||||
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
|
||||
%syncBrandDTD;
|
||||
<!ENTITY % reportphishDTD SYSTEM "chrome://browser/locale/safebrowsing/report-phishing.dtd">
|
||||
%reportphishDTD;
|
||||
<!ENTITY % editBookmarkOverlayDTD SYSTEM "chrome://browser/locale/places/editBookmarkOverlay.dtd">
|
||||
%editBookmarkOverlayDTD;
|
||||
|
@ -343,6 +343,8 @@ var FullScreen = {
|
||||
document.addEventListener("keypress", this._keyToggleCallback);
|
||||
document.addEventListener("popupshown", this._setPopupOpen);
|
||||
document.addEventListener("popuphidden", this._setPopupOpen);
|
||||
gURLBar.controller.addQueryListener(this);
|
||||
|
||||
// In DOM fullscreen mode, we hide toolbars with CSS
|
||||
if (!document.fullscreenElement) {
|
||||
this.hideNavToolbox(true);
|
||||
@ -489,6 +491,7 @@ var FullScreen = {
|
||||
document.removeEventListener("keypress", this._keyToggleCallback);
|
||||
document.removeEventListener("popupshown", this._setPopupOpen);
|
||||
document.removeEventListener("popuphidden", this._setPopupOpen);
|
||||
gURLBar.controller.removeQueryListener(this);
|
||||
}
|
||||
},
|
||||
|
||||
@ -540,25 +543,36 @@ var FullScreen = {
|
||||
// Otherwise, they would not affect chrome and the user would expect the chrome to go away.
|
||||
// e.g. we wouldn't want the autoscroll icon firing this event, so when the user
|
||||
// toggles chrome when moving mouse to the top, it doesn't go away again.
|
||||
let target = aEvent.originalTarget;
|
||||
if (target.localName == "tooltip") {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
aEvent.type == "popupshown" &&
|
||||
!FullScreen._isChromeCollapsed &&
|
||||
aEvent.target.localName != "tooltip" &&
|
||||
aEvent.target.localName != "window" &&
|
||||
aEvent.target.getAttribute("nopreventnavboxhide") != "true"
|
||||
target.getAttribute("nopreventnavboxhide") != "true"
|
||||
) {
|
||||
FullScreen._isPopupOpen = true;
|
||||
} else if (
|
||||
aEvent.type == "popuphidden" &&
|
||||
aEvent.target.localName != "tooltip" &&
|
||||
aEvent.target.localName != "window"
|
||||
) {
|
||||
} else if (aEvent.type == "popuphidden") {
|
||||
FullScreen._isPopupOpen = false;
|
||||
// Try again to hide toolbar when we close the popup.
|
||||
FullScreen.hideNavToolbox(true);
|
||||
}
|
||||
},
|
||||
|
||||
// UrlbarController listener method
|
||||
onViewOpen() {
|
||||
if (!this._isChromeCollapsed) {
|
||||
this._isPopupOpen = true;
|
||||
}
|
||||
},
|
||||
|
||||
// UrlbarController listener method
|
||||
onViewClose() {
|
||||
this._isPopupOpen = false;
|
||||
this.hideNavToolbox(true);
|
||||
},
|
||||
|
||||
get navToolboxHidden() {
|
||||
return this._isChromeCollapsed;
|
||||
},
|
||||
@ -644,10 +658,10 @@ var FullScreen = {
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
window.removeEventListener("keypress", retryHideNavToolbox);
|
||||
window.removeEventListener("keydown", retryHideNavToolbox);
|
||||
window.removeEventListener("click", retryHideNavToolbox);
|
||||
};
|
||||
window.addEventListener("keypress", retryHideNavToolbox);
|
||||
window.addEventListener("keydown", retryHideNavToolbox);
|
||||
window.addEventListener("click", retryHideNavToolbox);
|
||||
return;
|
||||
}
|
||||
|
@ -7,94 +7,65 @@
|
||||
!('@mozilla.org/widget/nativemenuservice;1' in Cc))
|
||||
this.setAttribute('openedwithkey',
|
||||
event.target.parentNode.openedWithKey);">
|
||||
<menu id="file-menu" label="&fileMenu.label;"
|
||||
accesskey="&fileMenu.accesskey;">
|
||||
<menu id="file-menu" data-l10n-id="menu-file">
|
||||
<menupopup id="menu_FilePopup"
|
||||
onpopupshowing="updateFileMenuUserContextUIVisibility('menu_newUserContext');
|
||||
updateFileMenuImportUIVisibility('cmd_importFromAnotherBrowser');">
|
||||
<menuitem id="menu_newNavigatorTab"
|
||||
label="&tabCmd.label;"
|
||||
command="cmd_newNavigatorTab"
|
||||
key="key_newNavigatorTab"
|
||||
accesskey="&tabCmd.accesskey;"/>
|
||||
key="key_newNavigatorTab" data-l10n-id="menu-file-new-tab"/>
|
||||
<menu id="menu_newUserContext"
|
||||
label="&newUserContext.label;"
|
||||
accesskey="&newUserContext.accesskey;"
|
||||
hidden="true">
|
||||
hidden="true" data-l10n-id="menu-file-new-container-tab">
|
||||
<menupopup onpopupshowing="return createUserContextMenu(event);" />
|
||||
</menu>
|
||||
<menuitem id="menu_newNavigator"
|
||||
label="&newNavigatorCmd.label;"
|
||||
accesskey="&newNavigatorCmd.accesskey;"
|
||||
key="key_newNavigator"
|
||||
command="cmd_newNavigator"/>
|
||||
command="cmd_newNavigator" data-l10n-id="menu-file-new-window"/>
|
||||
<menuitem id="menu_newPrivateWindow"
|
||||
label="&newPrivateWindow.label;"
|
||||
accesskey="&newPrivateWindow.accesskey;"
|
||||
command="Tools:PrivateBrowsing"
|
||||
key="key_privatebrowsing"/>
|
||||
key="key_privatebrowsing" data-l10n-id="menu-file-new-private-window"/>
|
||||
<menuitem id="menu_openLocation"
|
||||
hidden="true"
|
||||
label="&openLocationCmd.label;"
|
||||
command="Browser:OpenLocation"
|
||||
key="focusURLBar"/>
|
||||
key="focusURLBar" data-l10n-id="menu-file-open-location"/>
|
||||
<menuitem id="menu_openFile"
|
||||
label="&openFileCmd.label;"
|
||||
command="Browser:OpenFile"
|
||||
key="openFileKb"
|
||||
accesskey="&openFileCmd.accesskey;"/>
|
||||
key="openFileKb" data-l10n-id="menu-file-open-file"/>
|
||||
<menuitem id="menu_close"
|
||||
class="show-only-for-keyboard"
|
||||
label="&closeCmd.label;"
|
||||
key="key_close"
|
||||
accesskey="&closeCmd.accesskey;"
|
||||
command="cmd_close"/>
|
||||
command="cmd_close" data-l10n-id="menu-file-close"/>
|
||||
<menuitem id="menu_closeWindow"
|
||||
class="show-only-for-keyboard"
|
||||
hidden="true"
|
||||
command="cmd_closeWindow"
|
||||
key="key_closeWindow"
|
||||
label="&closeWindow.label;"
|
||||
accesskey="&closeWindow.accesskey;"/>
|
||||
key="key_closeWindow" data-l10n-id="menu-file-close-window"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_savePage"
|
||||
label="&savePageCmd.label;"
|
||||
accesskey="&savePageCmd.accesskey;"
|
||||
key="key_savePage"
|
||||
command="Browser:SavePage"/>
|
||||
command="Browser:SavePage" data-l10n-id="menu-file-save-page"/>
|
||||
<menuitem id="menu_sendLink"
|
||||
label="&emailPageCmd.label;"
|
||||
accesskey="&emailPageCmd.accesskey;"
|
||||
command="Browser:SendLink"/>
|
||||
command="Browser:SendLink" data-l10n-id="menu-file-email-link"/>
|
||||
<menuseparator/>
|
||||
#if !defined(MOZ_WIDGET_GTK)
|
||||
<menuitem id="menu_printSetup"
|
||||
label="&printSetupCmd.label;"
|
||||
accesskey="&printSetupCmd.accesskey;"
|
||||
command="cmd_pageSetup"/>
|
||||
command="cmd_pageSetup" data-l10n-id="menu-file-print-setup"/>
|
||||
#endif
|
||||
#ifndef XP_MACOSX
|
||||
<menuitem id="menu_printPreview"
|
||||
label="&printPreviewCmd.label;"
|
||||
accesskey="&printPreviewCmd.accesskey;"
|
||||
command="cmd_printPreview"/>
|
||||
command="cmd_printPreview" data-l10n-id="menu-file-print-preview"/>
|
||||
#endif
|
||||
<menuitem id="menu_print"
|
||||
label="&printCmd.label;"
|
||||
accesskey="&printCmd.accesskey;"
|
||||
key="printKb"
|
||||
command="cmd_print"/>
|
||||
command="cmd_print" data-l10n-id="menu-file-print"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_importFromAnotherBrowser"
|
||||
label="&importFromAnotherBrowserCmd.label;"
|
||||
accesskey="&importFromAnotherBrowserCmd.accesskey;"
|
||||
command="cmd_importFromAnotherBrowser"/>
|
||||
command="cmd_importFromAnotherBrowser" data-l10n-id="menu-file-import-from-another-browser"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="goOfflineMenuitem"
|
||||
label="&goOfflineCmd.label;"
|
||||
accesskey="&goOfflineCmd.accesskey;"
|
||||
type="checkbox"
|
||||
command="cmd_toggleOfflineStatus"/>
|
||||
command="cmd_toggleOfflineStatus" data-l10n-id="menu-file-go-offline"/>
|
||||
<!-- We need to leave those strings in DTD until bug 1568133 is fixed. -->
|
||||
<menuitem id="menu_FileQuitItem"
|
||||
#ifdef XP_WIN
|
||||
label="&quitApplicationCmdWin2.label;"
|
||||
@ -110,194 +81,139 @@
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="edit-menu" label="&editMenu.label;"
|
||||
accesskey="&editMenu.accesskey;">
|
||||
<menu id="edit-menu" data-l10n-id="menu-edit">
|
||||
<menupopup id="menu_EditPopup"
|
||||
onpopupshowing="updateEditUIVisibility()"
|
||||
onpopuphidden="updateEditUIVisibility()">
|
||||
<menuitem id="menu_undo"
|
||||
label="&undoCmd.label;"
|
||||
key="key_undo"
|
||||
accesskey="&undoCmd.accesskey;"
|
||||
command="cmd_undo"/>
|
||||
command="cmd_undo" data-l10n-id="text-action-undo"/>
|
||||
<menuitem id="menu_redo"
|
||||
label="&redoCmd.label;"
|
||||
key="key_redo"
|
||||
accesskey="&redoCmd.accesskey;"
|
||||
command="cmd_redo"/>
|
||||
command="cmd_redo" data-l10n-id="text-action-redo"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_cut"
|
||||
label="&cutCmd.label;"
|
||||
key="key_cut"
|
||||
accesskey="&cutCmd.accesskey;"
|
||||
command="cmd_cut"/>
|
||||
command="cmd_cut" data-l10n-id="text-action-cut"/>
|
||||
<menuitem id="menu_copy"
|
||||
label="©Cmd.label;"
|
||||
key="key_copy"
|
||||
accesskey="©Cmd.accesskey;"
|
||||
command="cmd_copy"/>
|
||||
command="cmd_copy" data-l10n-id="text-action-copy"/>
|
||||
<menuitem id="menu_paste"
|
||||
label="&pasteCmd.label;"
|
||||
key="key_paste"
|
||||
accesskey="&pasteCmd.accesskey;"
|
||||
command="cmd_paste"/>
|
||||
command="cmd_paste" data-l10n-id="text-action-paste"/>
|
||||
<menuitem id="menu_delete"
|
||||
label="&deleteCmd.label;"
|
||||
key="key_delete"
|
||||
accesskey="&deleteCmd.accesskey;"
|
||||
command="cmd_delete"/>
|
||||
command="cmd_delete" data-l10n-id="text-action-delete"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_selectAll"
|
||||
label="&selectAllCmd.label;"
|
||||
key="key_selectAll"
|
||||
accesskey="&selectAllCmd.accesskey;"
|
||||
command="cmd_selectAll"/>
|
||||
command="cmd_selectAll" data-l10n-id="text-action-select-all"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_find"
|
||||
label="&findOnCmd.label;"
|
||||
accesskey="&findOnCmd.accesskey;"
|
||||
key="key_find"
|
||||
command="cmd_find"/>
|
||||
command="cmd_find" data-l10n-id="menu-edit-find-on"/>
|
||||
<menuitem id="menu_findAgain"
|
||||
class="show-only-for-keyboard"
|
||||
label="&findAgainCmd.label;"
|
||||
accesskey="&findAgainCmd.accesskey;"
|
||||
key="key_findAgain"
|
||||
command="cmd_findAgain"/>
|
||||
command="cmd_findAgain" data-l10n-id="menu-edit-find-again"/>
|
||||
<menuseparator hidden="true" id="textfieldDirection-separator"/>
|
||||
<menuitem id="textfieldDirection-swap"
|
||||
command="cmd_switchTextDirection"
|
||||
key="key_switchTextDirection"
|
||||
label="&bidiSwitchTextDirectionItem.label;"
|
||||
accesskey="&bidiSwitchTextDirectionItem.accesskey;"
|
||||
hidden="true"/>
|
||||
hidden="true" data-l10n-id="menu-edit-bidi-switch-text-direction"/>
|
||||
#ifdef XP_UNIX
|
||||
#ifndef XP_MACOSX
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_preferences"
|
||||
label="&preferencesCmdUnix.label;"
|
||||
accesskey="&preferencesCmdUnix.accesskey;"
|
||||
oncommand="openPreferences(undefined);"/>
|
||||
oncommand="openPreferences(undefined);" data-l10n-id="menu-preferences"/>
|
||||
#endif
|
||||
#endif
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="view-menu" label="&viewMenu.label;"
|
||||
accesskey="&viewMenu.accesskey;">
|
||||
<menu id="view-menu" data-l10n-id="menu-view">
|
||||
<menupopup id="menu_viewPopup"
|
||||
onpopupshowing="updateCharacterEncodingMenuState();">
|
||||
<menu id="viewToolbarsMenu"
|
||||
label="&viewToolbarsMenu.label;"
|
||||
accesskey="&viewToolbarsMenu.accesskey;">
|
||||
<menu id="viewToolbarsMenu" data-l10n-id="menu-view-toolbars-menu">
|
||||
<menupopup onpopupshowing="onViewToolbarsPopupShowing(event);">
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_customizeToolbars"
|
||||
label="&viewCustomizeToolbar.label;"
|
||||
accesskey="&viewCustomizeToolbar.accesskey;"
|
||||
command="cmd_CustomizeToolbars"/>
|
||||
command="cmd_CustomizeToolbars" data-l10n-id="menu-view-customize-toolbar"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menu id="viewSidebarMenuMenu"
|
||||
label="&viewSidebarMenu.label;"
|
||||
accesskey="&viewSidebarMenu.accesskey;">
|
||||
<menu id="viewSidebarMenuMenu" data-l10n-id="menu-view-sidebar">
|
||||
<menupopup id="viewSidebarMenu">
|
||||
<menuitem id="menu_bookmarksSidebar"
|
||||
type="checkbox"
|
||||
key="viewBookmarksSidebarKb"
|
||||
oncommand="SidebarUI.toggle('viewBookmarksSidebar');"
|
||||
label="&bookmarksButton.label;"/>
|
||||
oncommand="SidebarUI.toggle('viewBookmarksSidebar');" data-l10n-id="menu-view-bookmarks"/>
|
||||
<menuitem id="menu_historySidebar"
|
||||
type="checkbox"
|
||||
key="key_gotoHistory"
|
||||
oncommand="SidebarUI.toggle('viewHistorySidebar');"
|
||||
label="&historyButton.label;"/>
|
||||
oncommand="SidebarUI.toggle('viewHistorySidebar');" data-l10n-id="menu-view-history-button"/>
|
||||
<menuitem id="menu_tabsSidebar"
|
||||
type="checkbox"
|
||||
class="sync-ui-item"
|
||||
oncommand="SidebarUI.toggle('viewTabsSidebar');"
|
||||
label="&syncedTabs.sidebar.label;"/>
|
||||
oncommand="SidebarUI.toggle('viewTabsSidebar');" data-l10n-id="menu-view-synced-tabs-sidebar"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
<menu id="viewFullZoomMenu" label="&fullZoom.label;"
|
||||
accesskey="&fullZoom.accesskey;"
|
||||
onpopupshowing="FullZoom.updateMenu();">
|
||||
<menu id="viewFullZoomMenu"
|
||||
onpopupshowing="FullZoom.updateMenu();" data-l10n-id="menu-view-full-zoom">
|
||||
<menupopup>
|
||||
<menuitem id="menu_zoomEnlarge"
|
||||
key="key_fullZoomEnlarge"
|
||||
label="&fullZoomEnlargeCmd.label;"
|
||||
accesskey="&fullZoomEnlargeCmd.accesskey;"
|
||||
command="cmd_fullZoomEnlarge"/>
|
||||
command="cmd_fullZoomEnlarge" data-l10n-id="menu-view-full-zoom-enlarge"/>
|
||||
<menuitem id="menu_zoomReduce"
|
||||
key="key_fullZoomReduce"
|
||||
label="&fullZoomReduceCmd.label;"
|
||||
accesskey="&fullZoomReduceCmd.accesskey;"
|
||||
command="cmd_fullZoomReduce"/>
|
||||
command="cmd_fullZoomReduce" data-l10n-id="menu-view-full-zoom-reduce"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_zoomReset"
|
||||
key="key_fullZoomReset"
|
||||
label="&fullZoomResetCmd.label;"
|
||||
accesskey="&fullZoomResetCmd.accesskey;"
|
||||
command="cmd_fullZoomReset"/>
|
||||
command="cmd_fullZoomReset" data-l10n-id="menu-view-full-zoom-reset"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="toggle_zoom"
|
||||
label="&fullZoomToggleCmd.label;"
|
||||
accesskey="&fullZoomToggleCmd.accesskey;"
|
||||
type="checkbox"
|
||||
command="cmd_fullZoomToggle"
|
||||
checked="false"/>
|
||||
checked="false" data-l10n-id="menu-view-full-zoom-toggle"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menu id="pageStyleMenu" label="&pageStyleMenu.label;"
|
||||
accesskey="&pageStyleMenu.accesskey;">
|
||||
<menu id="pageStyleMenu" data-l10n-id="menu-view-page-style-menu">
|
||||
<menupopup onpopupshowing="gPageStyleMenu.fillPopup(this);">
|
||||
<menuitem id="menu_pageStyleNoStyle"
|
||||
label="&pageStyleNoStyle.label;"
|
||||
accesskey="&pageStyleNoStyle.accesskey;"
|
||||
oncommand="gPageStyleMenu.disableStyle();"
|
||||
type="radio"/>
|
||||
type="radio" data-l10n-id="menu-view-page-style-no-style"/>
|
||||
<menuitem id="menu_pageStylePersistentOnly"
|
||||
label="&pageStylePersistentOnly.label;"
|
||||
accesskey="&pageStylePersistentOnly.accesskey;"
|
||||
oncommand="gPageStyleMenu.switchStyleSheet('');"
|
||||
type="radio"
|
||||
checked="true"/>
|
||||
checked="true" data-l10n-id="menu-view-page-basic-style"/>
|
||||
<menuseparator/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menu id="charsetMenu"
|
||||
label="&charsetMenu2.label;"
|
||||
accesskey="&charsetMenu2.accesskey;"
|
||||
oncommand="BrowserSetForcedCharacterSet(event.target.getAttribute('charset'));"
|
||||
onpopupshowing="CharsetMenu.build(event.target); UpdateCurrentCharset(this);">
|
||||
onpopupshowing="CharsetMenu.build(event.target); UpdateCurrentCharset(this);" data-l10n-id="menu-view-charset">
|
||||
<menupopup>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
#ifdef XP_MACOSX
|
||||
<menuitem id="enterFullScreenItem"
|
||||
accesskey="&enterFullScreenCmd.accesskey;"
|
||||
label="&enterFullScreenCmd.label;"
|
||||
key="key_fullScreen">
|
||||
key="key_fullScreen" data-l10n-id="menu-view-enter-full-screen">
|
||||
<observes element="View:FullScreen" attribute="oncommand"/>
|
||||
<observes element="View:FullScreen" attribute="disabled"/>
|
||||
</menuitem>
|
||||
<menuitem id="exitFullScreenItem"
|
||||
accesskey="&exitFullScreenCmd.accesskey;"
|
||||
label="&exitFullScreenCmd.label;"
|
||||
key="key_fullScreen"
|
||||
hidden="true">
|
||||
hidden="true" data-l10n-id="menu-view-exit-full-screen">
|
||||
<observes element="View:FullScreen" attribute="oncommand"/>
|
||||
<observes element="View:FullScreen" attribute="disabled"/>
|
||||
</menuitem>
|
||||
#else
|
||||
<menuitem id="fullScreenItem"
|
||||
accesskey="&fullScreenCmd.accesskey;"
|
||||
label="&fullScreenCmd.label;"
|
||||
key="key_fullScreen"
|
||||
type="checkbox"
|
||||
observes="View:FullScreen"/>
|
||||
observes="View:FullScreen" data-l10n-id="menu-view-full-screen"/>
|
||||
#endif
|
||||
<menuitem id="menu_readerModeItem"
|
||||
observes="View:ReaderView"
|
||||
@ -305,27 +221,20 @@
|
||||
hidden="true"/>
|
||||
<menuitem id="menu_showAllTabs"
|
||||
hidden="true"
|
||||
accesskey="&showAllTabsCmd.accesskey;"
|
||||
label="&showAllTabsCmd.label;"
|
||||
command="Browser:ShowAllTabs"
|
||||
key="key_showAllTabs"/>
|
||||
key="key_showAllTabs" data-l10n-id="menu-view-show-all-tabs"/>
|
||||
<menuseparator hidden="true" id="documentDirection-separator"/>
|
||||
<menuitem id="documentDirection-swap"
|
||||
hidden="true"
|
||||
label="&bidiSwitchPageDirectionItem.label;"
|
||||
accesskey="&bidiSwitchPageDirectionItem.accesskey;"
|
||||
oncommand="gBrowser.selectedBrowser
|
||||
.messageManager
|
||||
.sendAsyncMessage('SwitchDocumentDirection');"/>
|
||||
oncommand="gBrowser.selectedBrowser.sendMessageToActor('SwitchDocumentDirection', {}, 'SwitchDocumentDirection');" data-l10n-id="menu-view-bidi-switch-page-direction"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="history-menu"
|
||||
label="&historyMenu.label;"
|
||||
accesskey="&historyMenu.accesskey;">
|
||||
<menu id="history-menu" data-l10n-id="menu-history">
|
||||
<menupopup id="goPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
oncommand="this.parentNode._placesView._onCommand(event);"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
@ -334,42 +243,37 @@
|
||||
tooltip="bhTooltip"
|
||||
popupsinherittooltip="true">
|
||||
<menuitem id="menu_showAllHistory"
|
||||
label="&showAllHistoryCmd2.label;"
|
||||
#ifndef XP_MACOSX
|
||||
key="showAllHistoryKb"
|
||||
#endif
|
||||
command="Browser:ShowAllHistory"/>
|
||||
command="Browser:ShowAllHistory" data-l10n-id="menu-history-show-all-history"/>
|
||||
<menuitem id="sanitizeItem"
|
||||
label="&clearRecentHistory.label;"
|
||||
key="key_sanitize"
|
||||
command="Tools:Sanitize"/>
|
||||
command="Tools:Sanitize" data-l10n-id="menu-history-clear-recent-history"/>
|
||||
<menuseparator id="sanitizeSeparator"/>
|
||||
<menuitem id="sync-tabs-menuitem"
|
||||
label="&syncTabsMenu3.label;"
|
||||
oncommand="gSync.openSyncedTabsPanel();"
|
||||
hidden="true"/>
|
||||
hidden="true" data-l10n-id="menu-history-synced-tabs"/>
|
||||
<menuitem id="historyRestoreLastSession"
|
||||
label="&historyRestoreLastSession.label;"
|
||||
command="Browser:RestoreLastSession"/>
|
||||
command="Browser:RestoreLastSession" data-l10n-id="menu-history-restore-last-session"/>
|
||||
<menuitem id="hiddenTabsMenu"
|
||||
label="&hiddenTabs.label;"
|
||||
oncommand="gTabsPanel.showHiddenTabsPanel();"
|
||||
hidden="true"/>
|
||||
hidden="true" data-l10n-id="menu-history-hidden-tabs"/>
|
||||
<menu id="historyUndoMenu"
|
||||
label="&historyUndoMenu.label;"
|
||||
disabled="true">
|
||||
disabled="true" data-l10n-id="menu-history-undo-menu">
|
||||
<menupopup id="historyUndoPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
onpopupshowing="document.getElementById('history-menu')._placesView.populateUndoSubmenu();"/>
|
||||
</menu>
|
||||
<menu id="historyUndoWindowMenu"
|
||||
label="&historyUndoWindowMenu.label;"
|
||||
disabled="true">
|
||||
disabled="true" data-l10n-id="menu-history-undo-window-menu">
|
||||
<menupopup id="historyUndoWindowPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
onpopupshowing="document.getElementById('history-menu')._placesView.populateUndoWindowSubmenu();"/>
|
||||
</menu>
|
||||
@ -379,14 +283,13 @@
|
||||
</menu>
|
||||
|
||||
<menu id="bookmarksMenu"
|
||||
label="&bookmarksMenu.label;"
|
||||
accesskey="&bookmarksMenu.accesskey;"
|
||||
ondragenter="PlacesMenuDNDHandler.onDragEnter(event);"
|
||||
ondragover="PlacesMenuDNDHandler.onDragOver(event);"
|
||||
ondrop="PlacesMenuDNDHandler.onDrop(event);">
|
||||
ondrop="PlacesMenuDNDHandler.onDrop(event);" data-l10n-id="menu-bookmarks-menu">
|
||||
<menupopup id="bookmarksMenuPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
context="placesContext"
|
||||
openInTabs="children"
|
||||
@ -398,26 +301,24 @@
|
||||
new PlacesMenu(event, `place:parent=${PlacesUtils.bookmarks.menuGuid}`);"
|
||||
tooltip="bhTooltip" popupsinherittooltip="true">
|
||||
<menuitem id="bookmarksShowAll"
|
||||
label="&showAllBookmarks2.label;"
|
||||
command="Browser:ShowAllBookmarks"
|
||||
key="manBookmarkKb"/>
|
||||
key="manBookmarkKb" data-l10n-id="menu-bookmarks-show-all"/>
|
||||
<menuseparator id="organizeBookmarksSeparator"/>
|
||||
<menuitem id="menu_bookmarkThisPage"
|
||||
command="Browser:AddBookmarkAs"
|
||||
key="addBookmarkAsKb"/>
|
||||
<menuitem id="menu_bookmarkAllTabs"
|
||||
label="&addCurPagesCmd.label;"
|
||||
class="show-only-for-keyboard"
|
||||
command="Browser:BookmarkAllTabs"
|
||||
key="bookmarkAllTabsKb"/>
|
||||
key="bookmarkAllTabsKb" data-l10n-id="menu-bookmarks-all-tabs"/>
|
||||
<menuseparator id="bookmarksToolbarSeparator"/>
|
||||
<menu id="bookmarksToolbarFolderMenu"
|
||||
class="menu-iconic bookmark-item"
|
||||
label="&personalbarCmd.label;"
|
||||
container="true">
|
||||
container="true" data-l10n-id="menu-bookmarks-toolbar">
|
||||
<menupopup id="bookmarksToolbarFolderPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
@ -425,11 +326,11 @@
|
||||
</menu>
|
||||
<menu id="menu_unsortedBookmarks"
|
||||
class="menu-iconic bookmark-item"
|
||||
label="&otherBookmarksCmd.label;"
|
||||
container="true">
|
||||
container="true" data-l10n-id="menu-bookmarks-other">
|
||||
<menupopup id="otherBookmarksFolderPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
@ -437,12 +338,12 @@
|
||||
</menu>
|
||||
<menu id="menu_mobileBookmarks"
|
||||
class="menu-iconic bookmark-item"
|
||||
label="&mobileBookmarksCmd.label;"
|
||||
hidden="true"
|
||||
container="true">
|
||||
container="true" data-l10n-id="menu-bookmarks-mobile">
|
||||
<menupopup id="mobileBookmarksFolderPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
@ -453,81 +354,59 @@
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="tools-menu"
|
||||
label="&toolsMenu.label;"
|
||||
accesskey="&toolsMenu.accesskey;">
|
||||
<menu id="tools-menu" data-l10n-id="menu-tools">
|
||||
<menupopup id="menu_ToolsPopup">
|
||||
<menuitem id="menu_openDownloads"
|
||||
label="&downloads.label;"
|
||||
accesskey="&downloads.accesskey;"
|
||||
key="key_openDownloads"
|
||||
command="Tools:Downloads"/>
|
||||
command="Tools:Downloads" data-l10n-id="menu-tools-downloads"/>
|
||||
<menuitem id="menu_openAddons"
|
||||
label="&addons.label;"
|
||||
accesskey="&addons.accesskey;"
|
||||
key="key_openAddons"
|
||||
command="Tools:Addons"/>
|
||||
command="Tools:Addons" data-l10n-id="menu-tools-addons"/>
|
||||
|
||||
<!-- only one of sync-setup, sync-unverifieditem, sync-syncnowitem or sync-reauthitem will be showing at once -->
|
||||
<menuitem id="sync-setup"
|
||||
class="sync-ui-item"
|
||||
label="&syncSignIn.label;"
|
||||
accesskey="&syncSignIn.accesskey;"
|
||||
hidden="true"
|
||||
oncommand="gSync.openPrefs('menubar')"/>
|
||||
oncommand="gSync.openPrefs('menubar')" data-l10n-id="menu-tools-sync-sign-in"/>
|
||||
<menuitem id="sync-unverifieditem"
|
||||
class="sync-ui-item"
|
||||
label="&syncSignIn.label;"
|
||||
accesskey="&syncSignIn.accesskey;"
|
||||
hidden="true"
|
||||
oncommand="gSync.openPrefs('menubar')"/>
|
||||
oncommand="gSync.openPrefs('menubar')" data-l10n-id="menu-tools-sync-sign-in"/>
|
||||
<menuitem id="sync-syncnowitem"
|
||||
class="sync-ui-item"
|
||||
label="&syncSyncNowItem.label;"
|
||||
accesskey="&syncSyncNowItem.accesskey;"
|
||||
hidden="true"
|
||||
oncommand="gSync.doSync(event);"/>
|
||||
oncommand="gSync.doSync(event);" data-l10n-id="menu-tools-sync-now"/>
|
||||
<menuitem id="sync-reauthitem"
|
||||
class="sync-ui-item"
|
||||
label="&syncReAuthItem.label;"
|
||||
accesskey="&syncReAuthItem.accesskey;"
|
||||
hidden="true"
|
||||
oncommand="gSync.openSignInAgainPage('menubar');"/>
|
||||
oncommand="gSync.openSignInAgainPage('menubar');" data-l10n-id="menu-tools-sync-re-auth"/>
|
||||
<menuseparator id="devToolsSeparator"/>
|
||||
<menu id="webDeveloperMenu"
|
||||
label="&webDeveloperMenu.label;"
|
||||
accesskey="&webDeveloperMenu.accesskey;">
|
||||
<menu id="webDeveloperMenu" data-l10n-id="menu-tools-web-developer">
|
||||
<menupopup id="menuWebDeveloperPopup">
|
||||
<menuitem id="menu_pageSource"
|
||||
label="&pageSourceCmd.label;"
|
||||
key="key_viewSource"
|
||||
command="View:PageSource"
|
||||
accesskey="&pageSourceCmd.accesskey;"/>
|
||||
command="View:PageSource" data-l10n-id="menu-tools-page-source"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuitem id="menu_pageInfo"
|
||||
accesskey="&pageInfoCmd.accesskey;"
|
||||
label="&pageInfoCmd.label;"
|
||||
#ifndef XP_WIN
|
||||
key="key_viewInfo"
|
||||
#endif
|
||||
command="View:PageInfo"/>
|
||||
command="View:PageInfo" data-l10n-id="menu-tools-page-info"/>
|
||||
#ifndef XP_UNIX
|
||||
<menuseparator id="prefSep"/>
|
||||
<menuitem id="menu_preferences"
|
||||
label="&preferencesCmd2.label;"
|
||||
accesskey="&preferencesCmd2.accesskey;"
|
||||
oncommand="openPreferences(undefined);"/>
|
||||
oncommand="openPreferences(undefined);" data-l10n-id="menu-preferences"/>
|
||||
#endif
|
||||
#ifdef MOZ_DEBUG
|
||||
<menuitem id="menu_layout_debugger"
|
||||
label="&ldbCmd.label;"
|
||||
accesskey="&ldbCmd.accesskey;"
|
||||
data-l10n-id="menu-tools-layout-debugger"
|
||||
oncommand="toOpenWindowByType('mozapp:layoutdebug',
|
||||
'chrome://layoutdebug/content/');"/>
|
||||
'chrome://layoutdebug/content/layoutdebug.xhtml');"/>
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
<!-- nsMenuBarX hides these and uses them to build the Application menu. -->
|
||||
<!-- We need to leave those strings in DTD until bug 1568133 is fixed. -->
|
||||
<menuitem id="menu_preferences" label="&preferencesCmdMac.label;" key="key_preferencesCmdMac" oncommand="openPreferences(undefined);"/>
|
||||
<menuitem id="menu_mac_services" label="&servicesMenuMac.label;"/>
|
||||
<menuitem id="menu_mac_hide_app" label="&hideThisAppCmdMac2.label;" key="key_hideThisAppCmdMac"/>
|
||||
@ -538,35 +417,29 @@
|
||||
</menu>
|
||||
#ifdef XP_MACOSX
|
||||
<menu id="windowMenu"
|
||||
label="&windowMenu.label;"
|
||||
onpopupshowing="macWindowMenuDidShow();"
|
||||
onpopuphidden="macWindowMenuDidHide();"
|
||||
>
|
||||
data-l10n-id="menu-window-menu">
|
||||
<menupopup id="windowPopup">
|
||||
<menuitem command="minimizeWindow" key="key_minimizeWindow"/>
|
||||
<menuitem command="zoomWindow"/>
|
||||
<!-- decomment when "BringAllToFront" is implemented
|
||||
<menuseparator/>
|
||||
<menuitem label="&bringAllToFront.label;" disabled="true"/> -->
|
||||
<menuitem disabled="true" data-l10n-id="menu-window-bring-all-to-front"/> -->
|
||||
<menuseparator id="sep-window-list"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
#endif
|
||||
<menu id="helpMenu"
|
||||
#ifdef XP_WIN
|
||||
label="&helpMenuWin.label;"
|
||||
accesskey="&helpMenuWin.accesskey;"
|
||||
#else
|
||||
label="&helpMenu.label;"
|
||||
accesskey="&helpMenu.accesskey;"
|
||||
#endif
|
||||
>
|
||||
data-l10n-id="menu-help">
|
||||
<menupopup id="menu_HelpPopup" onpopupshowing="buildHelpMenu();">
|
||||
<menuitem id="menu_openHelp"
|
||||
oncommand="openHelpLink('')"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
label="&productHelp2.label;"
|
||||
accesskey="&productHelp2.accesskey;"
|
||||
data-l10n-id="menu-help-product"
|
||||
#ifdef XP_MACOSX
|
||||
key="key_openHelpMac"/>
|
||||
#else
|
||||
@ -574,37 +447,15 @@
|
||||
#endif
|
||||
<menuitem id="menu_keyboardShortcuts"
|
||||
oncommand="openHelpLink('')"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
label="&helpKeyboardShortcuts.label;"
|
||||
accesskey="&helpKeyboardShortcuts.accesskey;"/>
|
||||
onclick="checkForMiddleClick(this, event);" data-l10n-id="menu-help-keyboard-shortcuts"/>
|
||||
<menuitem id="troubleShooting"
|
||||
accesskey="&helpTroubleshootingInfo.accesskey;"
|
||||
label="&helpTroubleshootingInfo.label;"
|
||||
oncommand="openTroubleshootingPage()"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
onclick="checkForMiddleClick(this, event);" data-l10n-id="menu-help-troubleshooting-info"/>
|
||||
<menuitem id="feedbackPage"
|
||||
accesskey="&helpFeedbackPage.accesskey;"
|
||||
label="&helpFeedbackPage.label;"
|
||||
oncommand="openFeedbackPage()"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
onclick="checkForMiddleClick(this, event);" data-l10n-id="menu-help-feedback-page"/>
|
||||
<menuitem id="helpSafeMode"
|
||||
accesskey="&helpSafeMode.accesskey;"
|
||||
label="&helpSafeMode.label;"
|
||||
stopaccesskey="&helpSafeMode.stop.accesskey;"
|
||||
stoplabel="&helpSafeMode.stop.label;"
|
||||
oncommand="safeModeRestart();"/>
|
||||
<menuitem id="menu_HelpPopup_reportPhishingtoolmenu"
|
||||
label="&reportDeceptiveSiteMenu.title;"
|
||||
accesskey="&reportDeceptiveSiteMenu.accesskey;"
|
||||
disabled="true"
|
||||
oncommand="openUILink(gSafeBrowsing.getReportURL('Phish'), event, {triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})});"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
hidden="true"/>
|
||||
<menuitem id="menu_HelpPopup_reportPhishingErrortoolmenu"
|
||||
disabled="true"
|
||||
oncommand="ReportFalseDeceptiveSite();"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
hidden="true"/>
|
||||
oncommand="safeModeRestart();" data-l10n-id="menu-help-safe-mode-without-addons"/>
|
||||
<menuseparator id="helpPolicySeparator"
|
||||
hidden="true"/>
|
||||
<menuitem id="helpPolicySupport"
|
||||
@ -612,6 +463,7 @@
|
||||
oncommand="openUILinkIn(Services.policies.getSupportMenu().URL.href, 'tab', {triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({})});"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuseparator id="aboutSeparator"/>
|
||||
<!-- We need to leave those strings in DTD until bug 1568133 is fixed. -->
|
||||
<menuitem id="aboutName"
|
||||
accesskey="&aboutProduct2.accesskey;"
|
||||
label="&aboutProduct2.label;"
|
||||
|
@ -244,6 +244,9 @@ var BrowserPageActions = {
|
||||
"subviewbutton-iconic",
|
||||
"pageAction-panel-button"
|
||||
);
|
||||
if (action.isBadged) {
|
||||
buttonNode.setAttribute("badged", "true");
|
||||
}
|
||||
buttonNode.setAttribute("actionid", action.id);
|
||||
buttonNode.addEventListener("command", event => {
|
||||
this.doCommandForAction(action, event, buttonNode);
|
||||
@ -318,14 +321,13 @@ var BrowserPageActions = {
|
||||
_makeActivatedActionPanelForAction(action) {
|
||||
let panelNode = document.createXULElement("panel");
|
||||
panelNode.id = this._activatedActionPanelID;
|
||||
panelNode.classList.add("cui-widget-panel");
|
||||
panelNode.classList.add("cui-widget-panel", "panel-no-padding");
|
||||
panelNode.setAttribute("actionID", action.id);
|
||||
panelNode.setAttribute("role", "group");
|
||||
panelNode.setAttribute("type", "arrow");
|
||||
panelNode.setAttribute("flip", "slide");
|
||||
panelNode.setAttribute("noautofocus", "true");
|
||||
panelNode.setAttribute("tabspecific", "true");
|
||||
panelNode.setAttribute("photon", "true");
|
||||
|
||||
let panelViewNode = null;
|
||||
let iframeNode = null;
|
||||
@ -1192,7 +1194,6 @@ BrowserPageActions.addSearchEngine = {
|
||||
this._updateTitleAndIcon();
|
||||
this.action.setWantsSubview(this.engines.length > 1, window);
|
||||
let button = BrowserPageActions.panelButtonNodeForActionID(this.action.id);
|
||||
button.classList.add("badged-button");
|
||||
button.setAttribute("image", this.engines[0].icon);
|
||||
button.setAttribute("uri", this.engines[0].uri);
|
||||
button.setAttribute("crop", "center");
|
||||
|
@ -152,8 +152,7 @@ var StarUI = {
|
||||
break;
|
||||
}
|
||||
this._isComposing = true;
|
||||
// Explicit fall-through, during composition, panel shouldn't be
|
||||
// hidden automatically.
|
||||
// Explicit fall-through, during composition, panel shouldn't be hidden automatically.
|
||||
case "input":
|
||||
// Might have edited some text without keyboard events nor composition
|
||||
// events. Fall-through to cancel auto close in such case.
|
||||
@ -581,7 +580,7 @@ var PlacesCommandHook = {
|
||||
if (!organizer || organizer.closed) {
|
||||
// No currently open places window, so open one with the specified mode.
|
||||
openDialog(
|
||||
"chrome://browser/content/places/places.xul",
|
||||
"chrome://browser/content/places/places.xhtml",
|
||||
"",
|
||||
"chrome,toolbar=yes,dialog=no,resizable",
|
||||
item
|
||||
@ -949,7 +948,7 @@ var PlacesMenuDNDHandler = {
|
||||
}
|
||||
|
||||
PlacesControllerDragHelper.currentDropTarget = event.target;
|
||||
let popup = event.target.lastChild;
|
||||
let popup = event.target.menupopup;
|
||||
if (
|
||||
this._loadTimer ||
|
||||
popup.state === "showing" ||
|
||||
@ -991,7 +990,7 @@ var PlacesMenuDNDHandler = {
|
||||
}
|
||||
|
||||
PlacesControllerDragHelper.currentDropTarget = null;
|
||||
let popup = event.target.lastChild;
|
||||
let popup = event.target.menupopup;
|
||||
|
||||
if (this._loadTimer) {
|
||||
this._loadTimer.cancel();
|
||||
@ -1031,8 +1030,8 @@ var PlacesMenuDNDHandler = {
|
||||
node.getAttribute("type") == "menu");
|
||||
let isStatic =
|
||||
!("_placesNode" in node) &&
|
||||
node.lastChild &&
|
||||
node.lastChild.hasAttribute("placespopup") &&
|
||||
node.menupopup &&
|
||||
node.menupopup.hasAttribute("placespopup") &&
|
||||
!node.parentNode.hasAttribute("placespopup");
|
||||
return isMenu && isStatic;
|
||||
},
|
||||
@ -1234,12 +1233,9 @@ var LibraryUI = {
|
||||
|
||||
let animatableBox = document.getElementById("library-animatable-box");
|
||||
let navBar = document.getElementById("nav-bar");
|
||||
let libraryIcon = document.getAnonymousElementByAttribute(
|
||||
libraryButton,
|
||||
"class",
|
||||
"toolbarbutton-icon"
|
||||
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(
|
||||
libraryButton.icon
|
||||
);
|
||||
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryIcon);
|
||||
let libraryBounds = window.windowUtils.getBoundsWithoutFlushing(
|
||||
libraryButton
|
||||
);
|
||||
@ -1312,12 +1308,9 @@ var LibraryUI = {
|
||||
}
|
||||
|
||||
let animatableBox = document.getElementById("library-animatable-box");
|
||||
let libraryIcon = document.getAnonymousElementByAttribute(
|
||||
libraryButton,
|
||||
"class",
|
||||
"toolbarbutton-icon"
|
||||
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(
|
||||
libraryButton.icon
|
||||
);
|
||||
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryIcon);
|
||||
|
||||
// Resizing the window will only have the ability to change the X offset of the
|
||||
// library button.
|
||||
@ -1581,7 +1574,7 @@ var BookmarkingUI = {
|
||||
if (this._hasBookmarksObserver) {
|
||||
PlacesUtils.bookmarks.removeObserver(this);
|
||||
PlacesUtils.observers.removeListener(
|
||||
["bookmark-added"],
|
||||
["bookmark-added", "bookmark-removed"],
|
||||
this.handlePlacesEvents
|
||||
);
|
||||
}
|
||||
@ -1632,7 +1625,7 @@ var BookmarkingUI = {
|
||||
PlacesUtils.bookmarks.addObserver(this);
|
||||
this.handlePlacesEvents = this.handlePlacesEvents.bind(this);
|
||||
PlacesUtils.observers.addListener(
|
||||
["bookmark-added"],
|
||||
["bookmark-added", "bookmark-removed"],
|
||||
this.handlePlacesEvents
|
||||
);
|
||||
this._hasBookmarksObserver = true;
|
||||
@ -1925,28 +1918,30 @@ var BookmarkingUI = {
|
||||
},
|
||||
|
||||
handlePlacesEvents(aEvents) {
|
||||
// Only need to update the UI if it wasn't marked as starred before:
|
||||
if (this._itemGuids.size == 0) {
|
||||
for (let { url, guid } of aEvents) {
|
||||
if (url && url == this._uri.spec) {
|
||||
// If a new bookmark has been added to the tracked uri, register it.
|
||||
if (!this._itemGuids.has(guid)) {
|
||||
this._itemGuids.add(guid);
|
||||
this._updateStar();
|
||||
for (let ev of aEvents) {
|
||||
switch (ev.type) {
|
||||
case "bookmark-added":
|
||||
// Only need to update the UI if it wasn't marked as starred before:
|
||||
if (this._itemGuids.size == 0) {
|
||||
if (ev.url && ev.url == this._uri.spec) {
|
||||
// If a new bookmark has been added to the tracked uri, register it.
|
||||
if (!this._itemGuids.has(ev.guid)) {
|
||||
this._itemGuids.add(ev.guid);
|
||||
this._updateStar();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// nsINavBookmarkObserver
|
||||
onItemRemoved(aItemId, aParentId, aIndex, aItemType, aURI, aGuid) {
|
||||
// If one of the tracked bookmarks has been removed, unregister it.
|
||||
if (this._itemGuids.has(aGuid)) {
|
||||
this._itemGuids.delete(aGuid);
|
||||
// Only need to update the UI if the page is no longer starred
|
||||
if (this._itemGuids.size == 0) {
|
||||
this._updateStar();
|
||||
break;
|
||||
case "bookmark-removed":
|
||||
// If one of the tracked bookmarks has been removed, unregister it.
|
||||
if (this._itemGuids.has(ev.guid)) {
|
||||
this._itemGuids.delete(ev.guid);
|
||||
// Only need to update the UI if the page is no longer starred
|
||||
if (this._itemGuids.size == 0) {
|
||||
this._updateStar();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -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);
|
||||
},
|
||||
};
|
@ -108,7 +108,7 @@
|
||||
#endif
|
||||
</commandset>
|
||||
|
||||
#include ../../components/places/content/placesCommands.inc.xul
|
||||
#include ../../components/places/content/placesCommands.inc.xhtml
|
||||
|
||||
<keyset id="mainKeyset">
|
||||
<key id="key_newNavigator"
|
||||
|
@ -17,7 +17,7 @@ var SidebarUI = {
|
||||
title: document
|
||||
.getElementById("sidebar-switcher-bookmarks")
|
||||
.getAttribute("label"),
|
||||
url: "chrome://browser/content/places/bookmarksSidebar.xul",
|
||||
url: "chrome://browser/content/places/bookmarksSidebar.xhtml",
|
||||
menuId: "menu_bookmarksSidebar",
|
||||
buttonId: "sidebar-switcher-bookmarks",
|
||||
},
|
||||
@ -28,7 +28,7 @@ var SidebarUI = {
|
||||
title: document
|
||||
.getElementById("sidebar-switcher-history")
|
||||
.getAttribute("label"),
|
||||
url: "chrome://browser/content/places/historySidebar.xul",
|
||||
url: "chrome://browser/content/places/historySidebar.xhtml",
|
||||
menuId: "menu_historySidebar",
|
||||
buttonId: "sidebar-switcher-history",
|
||||
triggerButtonId: "appMenuViewHistorySidebar",
|
||||
@ -226,7 +226,7 @@ var SidebarUI = {
|
||||
// First reset all ordinals to match DOM ordering.
|
||||
let browser = document.getElementById("browser");
|
||||
[...browser.children].forEach((node, i) => {
|
||||
node.ordinal = i + 1;
|
||||
node.style.MozBoxOrdinalGroup = i + 1;
|
||||
});
|
||||
|
||||
if (!this._positionStart) {
|
||||
@ -234,9 +234,9 @@ var SidebarUI = {
|
||||
// Want to display as: | appcontent | splitter | sidebar-box |
|
||||
// So we just swap box and appcontent ordering
|
||||
let appcontent = document.getElementById("appcontent");
|
||||
let boxOrdinal = this._box.ordinal;
|
||||
this._box.ordinal = appcontent.ordinal;
|
||||
appcontent.ordinal = boxOrdinal;
|
||||
let boxOrdinal = this._box.style.MozBoxOrdinalGroup;
|
||||
this._box.style.MozBoxOrdinalGroup = appcontent.style.MozBoxOrdinalGroup;
|
||||
appcontent.style.MozBoxOrdinalGroup = boxOrdinal;
|
||||
// Indicate we've switched ordering to the box
|
||||
this._box.setAttribute("positionend", true);
|
||||
} else {
|
||||
|
@ -35,6 +35,13 @@ var gIdentityHandler = {
|
||||
*/
|
||||
_isSecureInternalUI: false,
|
||||
|
||||
/**
|
||||
* Whether the content window is considered a "secure context". This
|
||||
* includes "potentially trustworthy" origins such as file:// URLs or localhost.
|
||||
* https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
|
||||
*/
|
||||
_isSecureContext: false,
|
||||
|
||||
/**
|
||||
* nsITransportSecurityInfo metadata provided by gBrowser.securityUI the last
|
||||
* time the identity UI was updated, or null if the connection is not secure.
|
||||
@ -50,13 +57,25 @@ var gIdentityHandler = {
|
||||
* RegExp used to decide if an about url should be shown as being part of
|
||||
* the browser UI.
|
||||
*/
|
||||
_secureInternalUIWhitelist: /^(?:accounts|addons|cache|config|crashes|customizing|downloads|healthreport|license|permissions|preferences|rights|sessionrestore|support)(?:[?#]|$)/i,
|
||||
_secureInternalUIWhitelist: /^(?:accounts|addons|cache|config|crashes|customizing|downloads|license|permissions|preferences|rights|sessionrestore|support)(?:[?#]|$)/i,
|
||||
|
||||
get _isBroken() {
|
||||
/**
|
||||
* Whether the established HTTPS connection is considered "broken".
|
||||
* This could have several reasons, such as mixed content or weak
|
||||
* cryptography. If this is true, _isSecureConnection is false.
|
||||
*/
|
||||
get _isBrokenConnection() {
|
||||
return this._state & Ci.nsIWebProgressListener.STATE_IS_BROKEN;
|
||||
},
|
||||
|
||||
get _isSecure() {
|
||||
/**
|
||||
* Whether the connection to the current site was done via secure
|
||||
* transport. Note that this attribute is not true in all cases that
|
||||
* the site was accessed via HTTPS, i.e. _isSecureConnection will
|
||||
* be false when _isBrokenConnection is true, even though the page
|
||||
* was loaded over HTTPS.
|
||||
*/
|
||||
get _isSecureConnection() {
|
||||
// If a <browser> is included within a chrome document, then this._state
|
||||
// will refer to the security state for the <browser> and not the top level
|
||||
// document. In this case, don't upgrade the security state in the UI
|
||||
@ -342,14 +361,6 @@ var gIdentityHandler = {
|
||||
openPreferences("privacy-permissions");
|
||||
},
|
||||
|
||||
recordClick(object) {
|
||||
Services.telemetry.recordEvent(
|
||||
"security.ui.identitypopup",
|
||||
"click",
|
||||
object
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for mouseclicks on the "More Information" button in the
|
||||
* "identity-popup" panel.
|
||||
@ -372,12 +383,6 @@ var gIdentityHandler = {
|
||||
},
|
||||
|
||||
disableMixedContentProtection() {
|
||||
// Use telemetry to measure how often unblocking happens
|
||||
const kMIXED_CONTENT_UNBLOCK_EVENT = 2;
|
||||
let histogram = Services.telemetry.getHistogramById(
|
||||
"MIXED_CONTENT_UNBLOCK_COUNTER"
|
||||
);
|
||||
histogram.add(kMIXED_CONTENT_UNBLOCK_EVENT);
|
||||
// Reload the page with the content unblocked
|
||||
BrowserReloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT);
|
||||
PanelMultiView.hidePopup(this._identityPopup);
|
||||
@ -458,6 +463,7 @@ var gIdentityHandler = {
|
||||
// the documentation of the individual properties for details.
|
||||
this.setURI(uri);
|
||||
this._secInfo = gBrowser.securityUI.secInfo;
|
||||
this._isSecureContext = gBrowser.securityUI.isSecureContext;
|
||||
|
||||
// Then, update the user interface with the available data.
|
||||
this.refreshIdentityBlock();
|
||||
@ -587,7 +593,7 @@ var gIdentityHandler = {
|
||||
if (this._uriHasHost && this._isEV) {
|
||||
return "verifiedIdentity";
|
||||
}
|
||||
if (this._uriHasHost && this._isSecure) {
|
||||
if (this._uriHasHost && this._isSecureConnection) {
|
||||
return "verifiedDomain";
|
||||
}
|
||||
return "unknownIdentity";
|
||||
@ -606,6 +612,20 @@ var gIdentityHandler = {
|
||||
return !issuerCert.isBuiltInRoot;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether the current URI results in an "invalid"
|
||||
* URL bar state, which effectively means hidden security
|
||||
* indicators.
|
||||
*/
|
||||
_hasInvalidPageProxyState() {
|
||||
return (
|
||||
!this._uriHasHost &&
|
||||
this._uri &&
|
||||
isBlankPageURL(this._uri.spec) &&
|
||||
!this._uri.schemeIs("moz-extension")
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the identity block user interface with the data from this object.
|
||||
*/
|
||||
@ -614,16 +634,28 @@ var gIdentityHandler = {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this condition is true, the URL bar will have an "invalid"
|
||||
// pageproxystate, which will hide the security indicators. Thus, we can
|
||||
// safely avoid updating the security UI.
|
||||
//
|
||||
// This will also filter out intermediate about:blank loads to avoid
|
||||
// flickering the identity block and doing unnecessary work.
|
||||
if (this._hasInvalidPageProxyState()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let icon_label = "";
|
||||
let tooltip = "";
|
||||
let icon_country_label = "";
|
||||
let icon_labels_dir = "ltr";
|
||||
|
||||
if (this._isSecureInternalUI) {
|
||||
// This is a secure internal Firefox page.
|
||||
this._identityBox.className = "chromeUI";
|
||||
let brandBundle = document.getElementById("bundle_brand");
|
||||
icon_label = brandBundle.getString("brandShorterName");
|
||||
} else if (this._uriHasHost && this._isEV) {
|
||||
// This is a secure connection with EV.
|
||||
this._identityBox.className = "verifiedIdentity";
|
||||
if (this._isMixedActiveContentBlocked) {
|
||||
this._identityBox.classList.add("mixedActiveBlocked");
|
||||
@ -654,13 +686,15 @@ var gIdentityHandler = {
|
||||
: "ltr";
|
||||
}
|
||||
} else if (this._pageExtensionPolicy) {
|
||||
// This is a WebExtension page.
|
||||
this._identityBox.className = "extensionPage";
|
||||
let extensionName = this._pageExtensionPolicy.name;
|
||||
icon_label = gNavigatorBundle.getFormattedString(
|
||||
"identity.extension.label",
|
||||
[extensionName]
|
||||
);
|
||||
} else if (this._uriHasHost && this._isSecure) {
|
||||
} else if (this._uriHasHost && this._isSecureConnection) {
|
||||
// This is a secure connection.
|
||||
this._identityBox.className = "verifiedDomain";
|
||||
if (this._isMixedActiveContentBlocked) {
|
||||
this._identityBox.classList.add("mixedActiveBlocked");
|
||||
@ -672,46 +706,45 @@ var gIdentityHandler = {
|
||||
[this.getIdentityData().caOrg]
|
||||
);
|
||||
}
|
||||
} else if (!this._uriHasHost) {
|
||||
} else if (this._isBrokenConnection) {
|
||||
// This is a secure connection, but something is wrong.
|
||||
this._identityBox.className = "unknownIdentity";
|
||||
|
||||
if (this._isMixedActiveContentLoaded) {
|
||||
this._identityBox.classList.add("mixedActiveContent");
|
||||
} else if (this._isMixedActiveContentBlocked) {
|
||||
this._identityBox.classList.add(
|
||||
"mixedDisplayContentLoadedActiveBlocked"
|
||||
);
|
||||
} else if (this._isMixedPassiveContentLoaded) {
|
||||
this._identityBox.classList.add("mixedDisplayContent");
|
||||
} else {
|
||||
this._identityBox.classList.add("weakCipher");
|
||||
}
|
||||
} else if (
|
||||
gBrowser.selectedBrowser.documentURI &&
|
||||
(gBrowser.selectedBrowser.documentURI.scheme == "about" ||
|
||||
gBrowser.selectedBrowser.documentURI.scheme == "chrome")
|
||||
this._isSecureContext ||
|
||||
(gBrowser.selectedBrowser.documentURI &&
|
||||
(gBrowser.selectedBrowser.documentURI.scheme == "about" ||
|
||||
gBrowser.selectedBrowser.documentURI.scheme == "chrome"))
|
||||
) {
|
||||
// For net errors we should not show notSecure as it's likely confusing
|
||||
// This is a local resource (and shouldn't be marked insecure).
|
||||
this._identityBox.className = "unknownIdentity";
|
||||
} else {
|
||||
if (this._isBroken) {
|
||||
this._identityBox.className = "unknownIdentity";
|
||||
// This is an insecure connection.
|
||||
let warnOnInsecure =
|
||||
this._insecureConnectionIconEnabled ||
|
||||
(this._insecureConnectionIconPBModeEnabled &&
|
||||
PrivateBrowsingUtils.isWindowPrivate(window));
|
||||
let className = warnOnInsecure ? "notSecure" : "unknownIdentity";
|
||||
this._identityBox.className = className;
|
||||
|
||||
if (this._isMixedActiveContentLoaded) {
|
||||
this._identityBox.classList.add("mixedActiveContent");
|
||||
} else if (this._isMixedActiveContentBlocked) {
|
||||
this._identityBox.classList.add(
|
||||
"mixedDisplayContentLoadedActiveBlocked"
|
||||
);
|
||||
} else if (this._isMixedPassiveContentLoaded) {
|
||||
this._identityBox.classList.add("mixedDisplayContent");
|
||||
} else {
|
||||
this._identityBox.classList.add("weakCipher");
|
||||
}
|
||||
} else {
|
||||
let warnOnInsecure =
|
||||
this._insecureConnectionIconEnabled ||
|
||||
(this._insecureConnectionIconPBModeEnabled &&
|
||||
PrivateBrowsingUtils.isWindowPrivate(window));
|
||||
let className = warnOnInsecure ? "notSecure" : "unknownIdentity";
|
||||
this._identityBox.className = className;
|
||||
|
||||
let warnTextOnInsecure =
|
||||
this._insecureConnectionTextEnabled ||
|
||||
(this._insecureConnectionTextPBModeEnabled &&
|
||||
PrivateBrowsingUtils.isWindowPrivate(window));
|
||||
if (warnTextOnInsecure) {
|
||||
icon_label = gNavigatorBundle.getString("identity.notSecure.label");
|
||||
this._identityBox.classList.add("notSecureText");
|
||||
}
|
||||
let warnTextOnInsecure =
|
||||
this._insecureConnectionTextEnabled ||
|
||||
(this._insecureConnectionTextPBModeEnabled &&
|
||||
PrivateBrowsingUtils.isWindowPrivate(window));
|
||||
if (warnTextOnInsecure) {
|
||||
icon_label = gNavigatorBundle.getString("identity.notSecure.label");
|
||||
this._identityBox.classList.add("notSecureText");
|
||||
}
|
||||
if (this._hasInsecureLoginForms) {
|
||||
// Insecure login forms can only be present on "unknown identity"
|
||||
@ -854,7 +887,7 @@ var gIdentityHandler = {
|
||||
connection = "secure-ev";
|
||||
} else if (this._isCertUserOverridden) {
|
||||
connection = "secure-cert-user-overridden";
|
||||
} else if (this._isSecure) {
|
||||
} else if (this._isSecureConnection) {
|
||||
connection = "secure";
|
||||
customRoot = this._hasCustomRoot();
|
||||
}
|
||||
@ -882,7 +915,7 @@ var gIdentityHandler = {
|
||||
// cipher.
|
||||
let ciphers = "";
|
||||
if (
|
||||
this._isBroken &&
|
||||
this._isBrokenConnection &&
|
||||
!this._isMixedActiveContentLoaded &&
|
||||
!this._isMixedPassiveContentLoaded
|
||||
) {
|
||||
@ -906,7 +939,7 @@ var gIdentityHandler = {
|
||||
updateAttribute(element, "loginforms", loginforms);
|
||||
updateAttribute(element, "ciphers", ciphers);
|
||||
updateAttribute(element, "mixedcontent", mixedcontent);
|
||||
updateAttribute(element, "isbroken", this._isBroken);
|
||||
updateAttribute(element, "isbroken", this._isBrokenConnection);
|
||||
updateAttribute(element, "customroot", customRoot);
|
||||
}
|
||||
|
||||
@ -917,7 +950,7 @@ var gIdentityHandler = {
|
||||
let owner = "";
|
||||
|
||||
// Fill in the CA name if we have a valid TLS certificate.
|
||||
if (this._isSecure || this._isCertUserOverridden) {
|
||||
if (this._isSecureConnection || this._isCertUserOverridden) {
|
||||
verifier = this._identityIconLabels.tooltipText;
|
||||
}
|
||||
|
||||
@ -957,8 +990,6 @@ var gIdentityHandler = {
|
||||
|
||||
// Update per-site permissions section.
|
||||
this.updateSitePermissions();
|
||||
|
||||
ContentBlocking.toggleReportBreakageButton();
|
||||
},
|
||||
|
||||
setURI(uri) {
|
||||
@ -1034,6 +1065,40 @@ var gIdentityHandler = {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we are in DOM full-screen, exit it before showing the identity popup
|
||||
if (document.fullscreen) {
|
||||
// Open the identity popup after DOM full-screen exit
|
||||
// We need to wait for the exit event and after that wait for the fullscreen exit transition to complete
|
||||
// If we call _openPopup before the full-screen transition ends it can get cancelled
|
||||
// Only waiting for painted is not sufficient because we could still be in the full-screen enter transition.
|
||||
let exitedEventReceived = false;
|
||||
window.messageManager.addMessageListener(
|
||||
"DOMFullscreen:Painted",
|
||||
function listener() {
|
||||
if (!exitedEventReceived) {
|
||||
return;
|
||||
}
|
||||
window.messageManager.removeMessageListener(
|
||||
"DOMFullscreen:Painted",
|
||||
listener
|
||||
);
|
||||
gIdentityHandler._openPopup(event);
|
||||
}
|
||||
);
|
||||
window.addEventListener(
|
||||
"MozDOMFullscreen:Exited",
|
||||
() => {
|
||||
exitedEventReceived = true;
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
document.exitFullscreen();
|
||||
return;
|
||||
}
|
||||
this._openPopup(event);
|
||||
},
|
||||
|
||||
_openPopup(event) {
|
||||
// Make sure that the display:none style we set in xul is removed now that
|
||||
// the popup is actually needed
|
||||
this._identityPopup.hidden = false;
|
||||
@ -1058,12 +1123,6 @@ var gIdentityHandler = {
|
||||
if (event.target == this._identityPopup) {
|
||||
window.addEventListener("focus", this, true);
|
||||
}
|
||||
|
||||
Services.telemetry.recordEvent(
|
||||
"security.ui.identitypopup",
|
||||
"open",
|
||||
"identity_popup"
|
||||
);
|
||||
},
|
||||
|
||||
onPopupHidden(event) {
|
||||
@ -1124,11 +1183,7 @@ var gIdentityHandler = {
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.font = `${14 * scale}px sans-serif`;
|
||||
ctx.fillText(`${value}`, 20 * scale, 14 * scale);
|
||||
let tabIcon = document.getAnonymousElementByAttribute(
|
||||
gBrowser.selectedTab,
|
||||
"anonid",
|
||||
"tab-icon-image"
|
||||
);
|
||||
let tabIcon = gBrowser.selectedTab.iconImage;
|
||||
let image = new Image();
|
||||
image.src = tabIcon.src;
|
||||
ctx.drawImage(image, 0, 0, 16 * scale, 16 * scale);
|
||||
@ -1139,6 +1194,9 @@ var gIdentityHandler = {
|
||||
dt.setData("text/plain", value);
|
||||
dt.setData("text/html", htmlString);
|
||||
dt.setDragImage(canvas, 16, 16);
|
||||
|
||||
// Don't cover potential drop targets on the toolbars or in content.
|
||||
gURLBar.view.close();
|
||||
},
|
||||
|
||||
onLocationChange() {
|
||||
@ -1249,7 +1307,10 @@ var gIdentityHandler = {
|
||||
} else {
|
||||
img.classList.add(aPermission.id + "-icon");
|
||||
}
|
||||
if (aPermission.state == SitePermissions.BLOCK) {
|
||||
if (
|
||||
aPermission.state == SitePermissions.BLOCK ||
|
||||
aPermission.state == SitePermissions.AUTOPLAY_BLOCKED_ALL
|
||||
) {
|
||||
img.classList.add("blocked-permission-icon");
|
||||
}
|
||||
|
||||
|
@ -150,6 +150,8 @@ var gSync = {
|
||||
return;
|
||||
}
|
||||
|
||||
MozXULElement.insertFTLIfNeeded("browser/sync.ftl");
|
||||
|
||||
this._generateNodeGetters();
|
||||
|
||||
// Label for the sync buttons.
|
||||
@ -158,11 +160,8 @@ var gSync = {
|
||||
// setting this._initialized, so we don't attempt to remove observers.
|
||||
return;
|
||||
}
|
||||
let syncNow = document.getElementById("PanelUI-remotetabs-syncnow");
|
||||
let label = this.syncStrings.GetStringFromName("syncnow.label");
|
||||
syncNow.setAttribute("label", label);
|
||||
// We start with every menuitem hidden (except for the "setup sync" state),
|
||||
// so that we don't need to init the sync UI on windows like pageInfo.xul
|
||||
// so that we don't need to init the sync UI on windows like pageInfo.xhtml
|
||||
// (see bug 1384856).
|
||||
// maybeUpdateUIState() also optimizes for this - if we should be in the
|
||||
// "setup sync" state, that function assumes we are already in it and
|
||||
@ -548,7 +547,7 @@ var gSync = {
|
||||
},
|
||||
|
||||
updateSyncStatus(state) {
|
||||
let syncNow = document.getElementById("PanelUI-remotetabs-syncnow");
|
||||
let syncNow = document.querySelector(".syncNowBtn");
|
||||
const syncingUI = syncNow.getAttribute("syncstatus") == "active";
|
||||
if (state.syncing != syncingUI) {
|
||||
// Do we need to update the UI?
|
||||
@ -1033,26 +1032,11 @@ var gSync = {
|
||||
onActivityStart() {
|
||||
clearTimeout(this._syncAnimationTimer);
|
||||
this._syncStartTime = Date.now();
|
||||
|
||||
let label = this.syncStrings.GetStringFromName("syncingtabs.label");
|
||||
let remotetabsSyncNowEl = document.getElementById(
|
||||
"PanelUI-remotetabs-syncnow"
|
||||
);
|
||||
let fxaMenuSyncNowEl = document.getElementById(
|
||||
"PanelUI-fxa-menu-syncnow-button"
|
||||
);
|
||||
let syncElements = [remotetabsSyncNowEl, fxaMenuSyncNowEl];
|
||||
|
||||
syncElements.forEach(el => {
|
||||
document.querySelectorAll(".syncNowBtn").forEach(el => {
|
||||
el.setAttribute("syncstatus", "active");
|
||||
el.setAttribute("disabled", "true");
|
||||
document.l10n.setAttributes(el, el.getAttribute("syncinglabel"));
|
||||
});
|
||||
|
||||
remotetabsSyncNowEl.setAttribute("label", label);
|
||||
fxaMenuSyncNowEl.setAttribute(
|
||||
"label",
|
||||
fxaMenuSyncNowEl.getAttribute("syncinglabel")
|
||||
);
|
||||
},
|
||||
|
||||
_onActivityStop() {
|
||||
@ -1060,16 +1044,10 @@ var gSync = {
|
||||
return;
|
||||
}
|
||||
|
||||
let label = this.syncStrings.GetStringFromName("syncnow.label");
|
||||
let syncElements = [
|
||||
document.getElementById("PanelUI-remotetabs-syncnow"),
|
||||
document.getElementById("PanelUI-fxa-menu-syncnow-button"),
|
||||
];
|
||||
|
||||
syncElements.forEach(el => {
|
||||
document.querySelectorAll(".syncNowBtn").forEach(el => {
|
||||
el.removeAttribute("syncstatus");
|
||||
el.removeAttribute("disabled");
|
||||
el.setAttribute("label", label);
|
||||
document.l10n.setAttributes(el, "fxa-toolbar-sync-now");
|
||||
});
|
||||
|
||||
Services.obs.notifyObservers(null, "test:browser-sync:activity-stop");
|
||||
@ -1091,6 +1069,54 @@ var gSync = {
|
||||
}
|
||||
},
|
||||
|
||||
// Disconnect from sync, and optionally disconnect from the FxA account.
|
||||
// Returns true if the disconnection happened (ie, if the user didn't decline
|
||||
// when asked to confirm)
|
||||
async disconnect({ confirm = true, disconnectAccount = true } = {}) {
|
||||
if (confirm && !(await this._confirmDisconnect(disconnectAccount))) {
|
||||
return false;
|
||||
}
|
||||
await Weave.Service.promiseInitialized;
|
||||
await Weave.Service.startOver();
|
||||
if (disconnectAccount) {
|
||||
await fxAccounts.signOut();
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Prompts the user whether or not they want to proceed with
|
||||
* disconnecting from their Firefox Account or Sync.
|
||||
* @param {Boolean} disconnectAccount True if we are disconnecting both Sync and FxA.
|
||||
* @returns {Boolean} True if the user confirmed.
|
||||
*/
|
||||
async _confirmDisconnect(disconnectAccount) {
|
||||
const l10nPrefix = `${
|
||||
disconnectAccount ? "fxa" : "sync"
|
||||
}-disconnect-dialog`;
|
||||
const [title, body, button] = await document.l10n.formatValues([
|
||||
{ id: `${l10nPrefix}-title` },
|
||||
{ id: `${l10nPrefix}-body` },
|
||||
{ id: "sync-disconnect-dialog-button" },
|
||||
]);
|
||||
// buttonPressed will be 0 for disconnect, 1 for cancel.
|
||||
const flags =
|
||||
Services.prompt.BUTTON_TITLE_IS_STRING * Services.prompt.BUTTON_POS_0 +
|
||||
Services.prompt.BUTTON_TITLE_CANCEL * Services.prompt.BUTTON_POS_1;
|
||||
const buttonPressed = Services.prompt.confirmEx(
|
||||
window,
|
||||
title,
|
||||
body,
|
||||
flags,
|
||||
button,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{}
|
||||
);
|
||||
return buttonPressed == 0;
|
||||
},
|
||||
|
||||
// doSync forces a sync - it *does not* return a promise as it is called
|
||||
// via the various UI components.
|
||||
doSync() {
|
||||
@ -1191,14 +1217,13 @@ var gSync = {
|
||||
tooltiptext = this.formatLastSyncDate(state.lastSync);
|
||||
}
|
||||
|
||||
if (this.appMenuLabel) {
|
||||
let syncNow = document.getElementById("PanelUI-remotetabs-syncnow");
|
||||
document.querySelectorAll(".syncNowBtn").forEach(el => {
|
||||
if (tooltiptext) {
|
||||
syncNow.setAttribute("tooltiptext", tooltiptext);
|
||||
el.setAttribute("tooltiptext", tooltiptext);
|
||||
} else {
|
||||
syncNow.removeAttribute("tooltiptext");
|
||||
el.removeAttribute("tooltiptext");
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
get relativeTimeFormat() {
|
||||
|
@ -19,11 +19,17 @@
|
||||
* these gets focus, it redirects focus to the appropriate button. This avoids
|
||||
* the need to continually manage the tabindex of toolbar buttons in response to
|
||||
* toolbarchanges.
|
||||
* In addition to linear navigation with tab and arrows, users can also type
|
||||
* the first (or first few) characters of a button's name to jump directly to
|
||||
* that button.
|
||||
*/
|
||||
|
||||
ToolbarKeyboardNavigator = {
|
||||
// Toolbars we want to be keyboard navigable.
|
||||
kToolbars: [CustomizableUI.AREA_NAVBAR, CustomizableUI.AREA_BOOKMARKS],
|
||||
// Delay (in ms) after which to clear any search text typed by the user if
|
||||
// the user hasn't typed anything further.
|
||||
kSearchClearTimeout: 1000,
|
||||
|
||||
_isButton(aElem) {
|
||||
return (
|
||||
@ -80,6 +86,16 @@ ToolbarKeyboardNavigator = {
|
||||
return aRoot._toolbarKeyNavWalker;
|
||||
},
|
||||
|
||||
_initTabStops(aRoot) {
|
||||
for (let stop of aRoot.getElementsByTagName("toolbartabstop")) {
|
||||
// These are invisible, but because they need to be in the tab order,
|
||||
// they can't get display: none or similar. They must therefore be
|
||||
// explicitly hidden for accessibility.
|
||||
stop.setAttribute("aria-hidden", "true");
|
||||
stop.addEventListener("focus", this);
|
||||
}
|
||||
},
|
||||
|
||||
init() {
|
||||
for (let id of this.kToolbars) {
|
||||
let toolbar = document.getElementById(id);
|
||||
@ -87,16 +103,11 @@ ToolbarKeyboardNavigator = {
|
||||
// We manage toolbar focus completely. This attribute ensures that CSS
|
||||
// doesn't set -moz-user-focus: normal.
|
||||
toolbar.setAttribute("keyNav", "true");
|
||||
for (let stop of toolbar.getElementsByTagName("toolbartabstop")) {
|
||||
// These are invisible, but because they need to be in the tab order,
|
||||
// they can't get display: none or similar. They must therefore be
|
||||
// explicitly hidden for accessibility.
|
||||
stop.setAttribute("aria-hidden", "true");
|
||||
stop.addEventListener("focus", this);
|
||||
}
|
||||
this._initTabStops(toolbar);
|
||||
toolbar.addEventListener("keydown", this);
|
||||
toolbar.addEventListener("keypress", this);
|
||||
}
|
||||
CustomizableUI.addListener(this);
|
||||
},
|
||||
|
||||
uninit() {
|
||||
@ -109,6 +120,19 @@ ToolbarKeyboardNavigator = {
|
||||
toolbar.removeEventListener("keypress", this);
|
||||
toolbar.removeAttribute("keyNav");
|
||||
}
|
||||
CustomizableUI.removeListener(this);
|
||||
},
|
||||
|
||||
// CustomizableUI event handler
|
||||
onWidgetAdded(aWidgetId, aArea, aPosition) {
|
||||
if (!this.kToolbars.includes(aArea)) {
|
||||
return;
|
||||
}
|
||||
let widget = document.getElementById(aWidgetId);
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
this._initTabStops(widget);
|
||||
},
|
||||
|
||||
_focusButton(aButton) {
|
||||
@ -162,6 +186,42 @@ ToolbarKeyboardNavigator = {
|
||||
walker.currentNode = aEvent.target;
|
||||
let button = walker.nextNode();
|
||||
if (!button || !this._isButton(button)) {
|
||||
// If we think we're moving backward, and focus came from outside the
|
||||
// toolbox, we might actually have wrapped around. This currently only
|
||||
// happens in popup windows (because in normal windows, focus first
|
||||
// goes to the tabstrip, where we don't have tabstops). In this case,
|
||||
// the event target was the first tabstop. If we can't find a button,
|
||||
// e.g. because we're in a popup where most buttons are hidden, we
|
||||
// should ensure focus keeps moving forward:
|
||||
if (
|
||||
oldFocus &&
|
||||
this._isFocusMovingBackward &&
|
||||
!gNavToolbox.contains(oldFocus)
|
||||
) {
|
||||
let allStops = Array.from(
|
||||
gNavToolbox.querySelectorAll("toolbartabstop")
|
||||
);
|
||||
// Find the previous toolbartabstop:
|
||||
let earlierVisibleStopIndex = allStops.indexOf(aEvent.target) - 1;
|
||||
// Then work out if any of the earlier ones are in a visible
|
||||
// toolbar:
|
||||
while (earlierVisibleStopIndex >= 0) {
|
||||
let stopToolbar = allStops[earlierVisibleStopIndex].closest(
|
||||
"toolbar"
|
||||
);
|
||||
if (
|
||||
window.windowUtils.getBoundsWithoutFlushing(stopToolbar).height > 0
|
||||
) {
|
||||
break;
|
||||
}
|
||||
earlierVisibleStopIndex--;
|
||||
}
|
||||
// If we couldn't find any earlier visible stops, we're not moving
|
||||
// backwards, we're moving forwards and wrapped around:
|
||||
if (earlierVisibleStopIndex == -1) {
|
||||
this._isFocusMovingBackward = false;
|
||||
}
|
||||
}
|
||||
// No navigable buttons for this tab stop. Skip it.
|
||||
if (this._isFocusMovingBackward) {
|
||||
document.commandDispatcher.rewindFocus();
|
||||
@ -194,6 +254,20 @@ ToolbarKeyboardNavigator = {
|
||||
|
||||
_onKeyDown(aEvent) {
|
||||
let focus = document.activeElement;
|
||||
if (
|
||||
aEvent.key != " " &&
|
||||
aEvent.key.length == 1 &&
|
||||
this._isButton(focus) &&
|
||||
// Don't handle characters if the user is focused in a panel anchored
|
||||
// to the toolbar.
|
||||
!focus.closest("panel")
|
||||
) {
|
||||
this._onSearchChar(aEvent.currentTarget, aEvent.key);
|
||||
return;
|
||||
}
|
||||
// Anything that doesn't trigger search should clear the search.
|
||||
this._clearSearch();
|
||||
|
||||
if (
|
||||
aEvent.altKey ||
|
||||
aEvent.controlKey ||
|
||||
@ -219,6 +293,83 @@ ToolbarKeyboardNavigator = {
|
||||
aEvent.preventDefault();
|
||||
},
|
||||
|
||||
_clearSearch() {
|
||||
this._searchText = "";
|
||||
if (this._clearSearchTimeout) {
|
||||
clearTimeout(this._clearSearchTimeout);
|
||||
this._clearSearchTimeout = null;
|
||||
}
|
||||
},
|
||||
|
||||
_onSearchChar(aToolbar, aChar) {
|
||||
if (this._clearSearchTimeout) {
|
||||
// The user just typed a character, so reset the timer.
|
||||
clearTimeout(this._clearSearchTimeout);
|
||||
}
|
||||
// Convert to lower case so we can do case insensitive searches.
|
||||
let char = aChar.toLowerCase();
|
||||
// If the user has only typed a single character and they type the same
|
||||
// character again, they want to move to the next item starting with that
|
||||
// same character. Effectively, it's as if there was no existing search.
|
||||
// In that case, we just leave this._searchText alone.
|
||||
if (!this._searchText) {
|
||||
this._searchText = char;
|
||||
} else if (this._searchText != char) {
|
||||
this._searchText += char;
|
||||
}
|
||||
// Clear the search if the user doesn't type anything more within the timeout.
|
||||
this._clearSearchTimeout = setTimeout(
|
||||
this._clearSearch.bind(this),
|
||||
this.kSearchClearTimeout
|
||||
);
|
||||
|
||||
let oldFocus = document.activeElement;
|
||||
let walker = this._getWalker(aToolbar);
|
||||
// Search forward after the current control.
|
||||
walker.currentNode = oldFocus;
|
||||
for (
|
||||
let newFocus = walker.nextNode();
|
||||
newFocus;
|
||||
newFocus = walker.nextNode()
|
||||
) {
|
||||
if (this._doesSearchMatch(newFocus)) {
|
||||
this._focusButton(newFocus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// No match, so search from the start until the current control.
|
||||
walker.currentNode = walker.root;
|
||||
for (
|
||||
let newFocus = walker.firstChild();
|
||||
newFocus && newFocus != oldFocus;
|
||||
newFocus = walker.nextNode()
|
||||
) {
|
||||
if (this._doesSearchMatch(newFocus)) {
|
||||
this._focusButton(newFocus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_doesSearchMatch(aElem) {
|
||||
if (!this._isButton(aElem)) {
|
||||
return false;
|
||||
}
|
||||
for (let attrib of ["aria-label", "label", "tooltiptext"]) {
|
||||
let label = aElem.getAttribute(attrib);
|
||||
if (!label) {
|
||||
continue;
|
||||
}
|
||||
// Convert to lower case so we do a case insensitive comparison.
|
||||
// (this._searchText is already lower case.)
|
||||
label = label.toLowerCase();
|
||||
if (label.startsWith(this._searchText)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_onKeyPress(aEvent) {
|
||||
let focus = document.activeElement;
|
||||
if (
|
||||
|
@ -2,10 +2,23 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
|
||||
:root,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
:root {
|
||||
text-rendering: optimizeLegibility;
|
||||
min-height: 95px;
|
||||
min-width: 95px;
|
||||
|
||||
/* variables */
|
||||
--panelui-subview-transition-duration: 150ms;
|
||||
--lwt-additional-images: none;
|
||||
--lwt-background-alignment: right top;
|
||||
@ -16,6 +29,10 @@
|
||||
--toolbar-color: var(--toolbar-non-lwt-textcolor);
|
||||
}
|
||||
|
||||
:root:-moz-locale-dir(rtl) {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
:root:-moz-lwtheme {
|
||||
--toolbar-bgcolor: rgba(255,255,255,.4);
|
||||
--toolbar-bgimage: none;
|
||||
@ -35,6 +52,26 @@
|
||||
background-color: var(--lwt-accent-color-inactive, var(--lwt-accent-color));
|
||||
}
|
||||
|
||||
:root:not([chromehidden~="toolbar"]) {
|
||||
min-width: 450px;
|
||||
}
|
||||
|
||||
:root[customizing] {
|
||||
min-width: -moz-fit-content;
|
||||
}
|
||||
|
||||
/* Prevent shrinking the page content to 0 height and width */
|
||||
.browserStack {
|
||||
min-height: 25px;
|
||||
min-width: 25px;
|
||||
}
|
||||
|
||||
body {
|
||||
display: -moz-box;
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
/* Set additional backgrounds alignment relative to toolbox */
|
||||
|
||||
#navigator-toolbox:-moz-lwtheme {
|
||||
@ -43,29 +80,11 @@
|
||||
background-repeat: var(--lwt-background-tiling);
|
||||
}
|
||||
|
||||
:root:not([chromehidden~="toolbar"]) {
|
||||
%ifdef XP_MACOSX
|
||||
min-width: 335px;
|
||||
%else
|
||||
min-width: 300px;
|
||||
%endif
|
||||
}
|
||||
|
||||
:root[customize-entered] {
|
||||
min-width: -moz-fit-content;
|
||||
}
|
||||
|
||||
.search-one-offs[compact=true] .search-setting-button,
|
||||
.search-one-offs:not([compact=true]) .search-setting-button-compact {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Prevent shrinking the page content to 0 height and width */
|
||||
.browserStack {
|
||||
min-height: 25px;
|
||||
min-width: 25px;
|
||||
}
|
||||
|
||||
%ifdef MENUBAR_CAN_AUTOHIDE
|
||||
#toolbar-menubar[autohide="true"] {
|
||||
overflow: hidden;
|
||||
@ -80,7 +99,6 @@
|
||||
|
||||
%ifdef XP_MACOSX
|
||||
#toolbar-menubar {
|
||||
-moz-binding: none;
|
||||
visibility: collapse;
|
||||
}
|
||||
%endif
|
||||
@ -119,7 +137,6 @@ panelview[mainview] > .panel-header {
|
||||
|
||||
.panel-viewcontainer.offscreen {
|
||||
display: block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.panel-viewstack {
|
||||
@ -127,10 +144,6 @@ panelview[mainview] > .panel-header {
|
||||
transition: height var(--panelui-subview-transition-duration);
|
||||
}
|
||||
|
||||
#tabbrowser-tabs {
|
||||
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabs");
|
||||
}
|
||||
|
||||
@supports -moz-bool-pref("layout.css.emulate-moz-box-with-flex") {
|
||||
#tabbrowser-tabs {
|
||||
/* Without this, the tabs container width extends beyond the window width */
|
||||
@ -145,9 +158,9 @@ panelview[mainview] > .panel-header {
|
||||
|
||||
#tabbrowser-tabs:not([overflow="true"]):not([hashiddentabs]) ~ #alltabs-button,
|
||||
#tabbrowser-tabs[hasadjacentnewtabbutton]:not([overflow="true"]) ~ #new-tab-button,
|
||||
#tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
|
||||
#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
|
||||
#TabsToolbar[customizing="true"] #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button {
|
||||
#tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > #tabs-newtab-button,
|
||||
#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > .tabbrowser-arrowscrollbox > #tabs-newtab-button,
|
||||
#TabsToolbar[customizing="true"] #tabs-newtab-button {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
@ -155,10 +168,6 @@ panelview[mainview] > .panel-header {
|
||||
visibility: hidden; /* temporary space to keep a tab's close button under the cursor */
|
||||
}
|
||||
|
||||
.tabbrowser-tab {
|
||||
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tab");
|
||||
}
|
||||
|
||||
.tabbrowser-tab:not([pinned]) {
|
||||
-moz-box-flex: 100;
|
||||
max-width: 225px;
|
||||
@ -208,13 +217,13 @@ panelview[mainview] > .panel-header {
|
||||
}
|
||||
%endif
|
||||
|
||||
#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
|
||||
#tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-arrowscrollbox > .tabbrowser-tab[pinned] {
|
||||
position: fixed !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[selected],
|
||||
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[multiselected] {
|
||||
#tabbrowser-tabs[movingtab] > .tabbrowser-arrowscrollbox > .tabbrowser-tab[selected],
|
||||
#tabbrowser-tabs[movingtab] > .tabbrowser-arrowscrollbox > .tabbrowser-tab[multiselected] {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
pointer-events: none; /* avoid blocking dragover events on scroll buttons */
|
||||
@ -248,8 +257,15 @@ panelview[mainview] > .panel-header {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
toolbar[overflowable] > .customization-target {
|
||||
overflow: hidden;
|
||||
/* The address bar needs to be able to render outside of the toolbar, but as
|
||||
* long as it's within the toolbar's bounds we can clip the toolbar so that the
|
||||
* rendering pipeline doesn't reserve an enormous texture for it. */
|
||||
#nav-bar:not([urlbar-exceeds-toolbar-bounds]),
|
||||
/* When customizing, overflowable toolbars move automatically moved items back
|
||||
* from the overflow menu, but we still don't want to render them outside of
|
||||
* the customization target. */
|
||||
toolbar[overflowable][customizing] > .customization-target {
|
||||
overflow: clip;
|
||||
}
|
||||
|
||||
toolbar:not([overflowing]) > .overflow-button,
|
||||
@ -257,7 +273,7 @@ toolbar[customizing] > .overflow-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
window:not([chromehidden~="toolbar"]) #nav-bar[nonemptyoverflow] > .overflow-button,
|
||||
:root:not([chromehidden~="toolbar"]) #nav-bar[nonemptyoverflow] > .overflow-button,
|
||||
#nav-bar[customizing] > .overflow-button {
|
||||
display: -moz-box;
|
||||
}
|
||||
@ -534,20 +550,15 @@ toolbar:not(#TabsToolbar) > #personal-bookmarks {
|
||||
}
|
||||
|
||||
#urlbar,
|
||||
.searchbar-textbox {
|
||||
#searchbar {
|
||||
/* Setting a width and min-width to let the location & search bars maintain
|
||||
a constant width in case they haven't be resized manually. (bug 965772) */
|
||||
width: 1px;
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
|
||||
#urlbar[quantumbar="true"] {
|
||||
-moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
|
||||
}
|
||||
|
||||
/* Display URLs left-to-right but right aligned in RTL mode. */
|
||||
html|input.urlbar-input:-moz-locale-dir(rtl) {
|
||||
#urlbar-input:-moz-locale-dir(rtl) {
|
||||
direction: ltr !important;
|
||||
text-align: right !important;
|
||||
}
|
||||
@ -555,10 +566,11 @@ html|input.urlbar-input:-moz-locale-dir(rtl) {
|
||||
/* Make sure that the location bar's alignment in RTL mode changes according
|
||||
to the input box direction if the user switches the text direction using
|
||||
cmd_switchTextDirection (which applies a dir attribute to the <input>). */
|
||||
html|input.urlbar-input[dir=ltr]:-moz-locale-dir(rtl) {
|
||||
#urlbar-input[dir=ltr]:-moz-locale-dir(rtl) {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
%ifdef ENABLE_MARIONETTE
|
||||
/*
|
||||
* Display visual cue that browser is under remote control by Marionette.
|
||||
* This is to help users visually distinguish a user agent session that
|
||||
@ -579,13 +591,13 @@ html|input.urlbar-input[dir=ltr]:-moz-locale-dir(rtl) {
|
||||
:root[remotecontrol] #urlbar #identity-box {
|
||||
background: white;
|
||||
}
|
||||
|
||||
%endif
|
||||
/* Show the url scheme in a static box when overflowing to the left */
|
||||
moz-input-box.urlbar-input-box {
|
||||
.urlbar-input-box {
|
||||
position: relative;
|
||||
direction: ltr;
|
||||
}
|
||||
html|input.urlbar-scheme {
|
||||
#urlbar-scheme {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
visibility: hidden;
|
||||
@ -595,22 +607,22 @@ html|input.urlbar-scheme {
|
||||
|
||||
/* Visible if the urlbar is not focused and it overflows at the start.
|
||||
Uses the required-valid trick to check if it contains a value */
|
||||
html|input.urlbar-scheme[textoverflow="start"]:not([focused]):valid {
|
||||
#urlbar[textoverflow="start"]:not([focused]) > #urlbar-input-container > .urlbar-input-box > #urlbar-scheme:valid {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* Fade out URL on overflow
|
||||
This mask may be overriden when a Contextual Feature Recommendation is shown,
|
||||
see browser/themes/shared/urlbar-searchbar.inc.css for details */
|
||||
html|input.urlbar-input[textoverflow="end"]:not([focused]) {
|
||||
#urlbar[textoverflow="end"]:not([focused]) > #urlbar-input-container > .urlbar-input-box > #urlbar-input {
|
||||
mask-image: linear-gradient(to left, transparent, black 3ch);
|
||||
}
|
||||
|
||||
html|input.urlbar-input[textoverflow="start"]:not([focused]) {
|
||||
#urlbar[textoverflow="start"]:not([focused]) > #urlbar-input-container > .urlbar-input-box > #urlbar-input {
|
||||
mask-image: linear-gradient(to right, transparent var(--urlbar-scheme-size), black calc(var(--urlbar-scheme-size) + 3ch));
|
||||
}
|
||||
|
||||
html|input.urlbar-input {
|
||||
#urlbar-input {
|
||||
mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@ -621,10 +633,10 @@ html|input.urlbar-input {
|
||||
}
|
||||
}
|
||||
|
||||
#urlbar[actionoverride] > #urlbar-display-box,
|
||||
#urlbar:not([actiontype="switchtab"]):not([actiontype="extension"]) > #urlbar-display-box,
|
||||
#urlbar:not([actiontype="switchtab"]) > #urlbar-display-box > #switchtab,
|
||||
#urlbar:not([actiontype="extension"]) > #urlbar-display-box > #extension {
|
||||
#urlbar[actionoverride] > #urlbar-input-container > #urlbar-label-box,
|
||||
#urlbar:not([actiontype="switchtab"]):not([actiontype="extension"]) > #urlbar-input-container > #urlbar-label-box,
|
||||
#urlbar:not([actiontype="switchtab"]) > #urlbar-input-container > #urlbar-label-box > #urlbar-label-switchtab,
|
||||
#urlbar:not([actiontype="extension"]) > #urlbar-input-container > #urlbar-label-box > #urlbar-label-extension {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -641,12 +653,18 @@ html|input.urlbar-input {
|
||||
background-color: hsla(0,0%,80%,.5); /* match arrowpanel-dimmed-further */
|
||||
}
|
||||
|
||||
#PopupAutoComplete[firstresultstyle="insecureWarning"] {
|
||||
min-width: 200px;
|
||||
/* Define the minimum width based on the style of result rows.
|
||||
The order of the min-width rules below must be in increasing order. */
|
||||
#PopupAutoComplete[resultstyles~="loginsFooter"],
|
||||
#PopupAutoComplete[resultstyles~="insecureWarning"] {
|
||||
min-width: 17em;
|
||||
}
|
||||
|
||||
#PopupAutoComplete[resultstyles~="generatedPassword"] {
|
||||
min-width: 21em;
|
||||
}
|
||||
|
||||
#PopupAutoComplete > richlistbox > richlistitem[originaltype="insecureWarning"] {
|
||||
-moz-binding: none;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@ -665,11 +683,11 @@ html|input.urlbar-input {
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
#urlbar[pageproxystate=invalid] > #page-action-buttons > .urlbar-page-action,
|
||||
#urlbar-input-container[pageproxystate=invalid] > #page-action-buttons > .urlbar-page-action,
|
||||
#identity-box.chromeUI ~ #page-action-buttons > .urlbar-page-action:not(#star-button-box),
|
||||
.urlbar-history-dropmarker[usertyping],
|
||||
.urlbar-go-button:not([usertyping]),
|
||||
.urlbar-go-button:not([parentfocused="true"]) {
|
||||
#urlbar[usertyping] > #urlbar-input-container > .urlbar-history-dropmarker,
|
||||
#urlbar:not([usertyping]) > #urlbar-input-container > #urlbar-go-button,
|
||||
#urlbar:not([focused]) > #urlbar-input-container > #urlbar-go-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -677,66 +695,56 @@ html|input.urlbar-input {
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
||||
/* We leave 49ch plus whatever space the download button will need when it
|
||||
/* We leave 350px plus whatever space the download button will need when it
|
||||
* appears. Normally this should be 16px for the icon, plus 2 * 2px padding
|
||||
* plus the toolbarbutton-inner-padding. We're adding 4px to ensure things
|
||||
* like rounding on hidpi don't accidentally result in the button going
|
||||
* into overflow.
|
||||
*/
|
||||
#urlbar-container {
|
||||
min-width: calc(49ch + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
#urlbar-container {
|
||||
min-width: calc(350px + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
}
|
||||
|
||||
#nav-bar[downloadsbuttonshown] #urlbar-container {
|
||||
min-width: 49ch;
|
||||
min-width: 350px;
|
||||
}
|
||||
|
||||
/* Customize mode is difficult to use at moderate window width if the Urlbar
|
||||
remains 350px wide. */
|
||||
:root[customizing] #urlbar-container {
|
||||
min-width: 280px;
|
||||
}
|
||||
|
||||
#identity-icon-labels {
|
||||
max-width: 17em;
|
||||
max-width: 10em;
|
||||
}
|
||||
@media (max-width: 700px) {
|
||||
#urlbar-container {
|
||||
min-width: calc(44ch + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
}
|
||||
#nav-bar[downloadsbuttonshown] #urlbar-container {
|
||||
min-width: 44ch;
|
||||
}
|
||||
|
||||
#identity-icon-labels {
|
||||
max-width: 60px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
@media (max-width: 770px) {
|
||||
#urlbar-container {
|
||||
min-width: calc(39ch + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
min-width: calc(280px + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
}
|
||||
#nav-bar[downloadsbuttonshown] #urlbar-container {
|
||||
min-width: 39ch;
|
||||
min-width: 280px;
|
||||
}
|
||||
:root[customizing] #urlbar-container {
|
||||
min-width: 245px;
|
||||
}
|
||||
#identity-icon-labels {
|
||||
max-width: 50px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 500px) {
|
||||
@media (max-width: 550px) {
|
||||
#urlbar-container {
|
||||
min-width: calc(34ch + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
min-width: calc(225px + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
}
|
||||
#nav-bar[downloadsbuttonshown] #urlbar-container {
|
||||
min-width: 34ch;
|
||||
min-width: 225px;
|
||||
}
|
||||
#identity-icon-labels {
|
||||
max-width: 40px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 400px) {
|
||||
#urlbar-container {
|
||||
min-width: calc(27ch + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
}
|
||||
#nav-bar[downloadsbuttonshown] #urlbar-container {
|
||||
min-width: 27ch;
|
||||
}
|
||||
#identity-icon-labels {
|
||||
max-width: 30px;
|
||||
#urlbar-zoom-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -748,7 +756,7 @@ html|input.urlbar-input {
|
||||
margin-inline-end: 0.25em !important;
|
||||
}
|
||||
|
||||
/* Flexible spacer sizing (matching url bar) */
|
||||
/* Flexible spacer sizing (gets overridden in the navbar) */
|
||||
toolbarpaletteitem[place=toolbar][id^=wrapper-customizableui-special-spring],
|
||||
toolbarspring {
|
||||
-moz-box-flex: 1;
|
||||
@ -759,6 +767,14 @@ toolbarspring {
|
||||
#nav-bar toolbarpaletteitem[id^=wrapper-customizableui-special-spring],
|
||||
#nav-bar toolbarspring {
|
||||
-moz-box-flex: 80;
|
||||
/* We shrink the flexible spacers, but not to nothing so they can be
|
||||
* manipulated in customize mode; the next rule shrinks them further
|
||||
* outside customize mode. */
|
||||
min-width: 10px;
|
||||
}
|
||||
|
||||
#nav-bar:not([customizing]) toolbarspring {
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
#widget-overflow-list > toolbarspring {
|
||||
@ -786,10 +802,6 @@ toolbarspring {
|
||||
.bookmark-item > .menu-iconic-left > .menu-iconic-icon {
|
||||
image-rendering: -moz-crisp-edges;
|
||||
}
|
||||
/* Synced Tabs sidebar */
|
||||
html|*.tabs-container html|*.item-tabs-list html|*.item-icon-container {
|
||||
image-rendering: -moz-crisp-edges;
|
||||
}
|
||||
}
|
||||
|
||||
menupopup[emptyplacesresult="true"] > .hide-if-empty-places-result {
|
||||
@ -797,8 +809,7 @@ menupopup[emptyplacesresult="true"] > .hide-if-empty-places-result {
|
||||
}
|
||||
|
||||
/* Hide extension toolbars that neglected to set the proper class */
|
||||
window[chromehidden~="location"][chromehidden~="toolbar"] toolbar:not(.chromeclass-menubar),
|
||||
window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#print-preview-toolbar):not(.chromeclass-menubar) {
|
||||
:root[chromehidden~="location"][chromehidden~="toolbar"] toolbar:not(.chromeclass-menubar) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -831,7 +842,7 @@ window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#pri
|
||||
background: black;
|
||||
}
|
||||
|
||||
html|*.pointerlockfswarning {
|
||||
.pointerlockfswarning {
|
||||
position: fixed;
|
||||
z-index: 2147483647 !important;
|
||||
visibility: visible;
|
||||
@ -845,32 +856,32 @@ html|*.pointerlockfswarning {
|
||||
max-width: 95%;
|
||||
pointer-events: none;
|
||||
}
|
||||
html|*.pointerlockfswarning:not([hidden]) {
|
||||
.pointerlockfswarning:not([hidden]) {
|
||||
display: flex;
|
||||
will-change: transform;
|
||||
}
|
||||
html|*.pointerlockfswarning[onscreen] {
|
||||
.pointerlockfswarning[onscreen] {
|
||||
transform: translate(-50%, 50px);
|
||||
}
|
||||
html|*.pointerlockfswarning[ontop] {
|
||||
.pointerlockfswarning[ontop] {
|
||||
/* Use -10px to hide the border and border-radius on the top */
|
||||
transform: translate(-50%, -10px);
|
||||
}
|
||||
:root[OSXLionFullscreen] html|*.pointerlockfswarning[ontop] {
|
||||
:root[OSXLionFullscreen] .pointerlockfswarning[ontop] {
|
||||
transform: translate(-50%, 80px);
|
||||
}
|
||||
|
||||
html|*.pointerlockfswarning-domain-text,
|
||||
html|*.pointerlockfswarning-generic-text {
|
||||
.pointerlockfswarning-domain-text,
|
||||
.pointerlockfswarning-generic-text {
|
||||
word-wrap: break-word;
|
||||
/* We must specify a min-width, otherwise word-wrap:break-word doesn't work. Bug 630864. */
|
||||
min-width: 1px
|
||||
}
|
||||
html|*.pointerlockfswarning-domain-text:not([hidden]) + html|*.pointerlockfswarning-generic-text {
|
||||
.pointerlockfswarning-domain-text:not([hidden]) + .pointerlockfswarning-generic-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html|*#fullscreen-exit-button {
|
||||
#fullscreen-exit-button {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
@ -893,7 +904,7 @@ html|*#fullscreen-exit-button {
|
||||
/* should occupy space but not be visible */
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
-moz-stack-sizing: ignore;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
browser[tabmodalPromptShowing] {
|
||||
@ -958,7 +969,7 @@ browser[tabmodalPromptShowing] {
|
||||
and just show the icon. This is a hack to side-step very weird layout bugs that
|
||||
seem to be caused by the indicator stack interacting with the menu panel. */
|
||||
#downloads-button[indicator]:not([cui-areatype="menu-panel"]) > .toolbarbutton-badge-stack > image.toolbarbutton-icon,
|
||||
#downloads-button[indicator][cui-areatype="menu-panel"] > #downloads-indicator-anchor {
|
||||
#downloads-button[indicator][cui-areatype="menu-panel"] > .toolbarbutton-badge-stack > #downloads-indicator-anchor {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -966,7 +977,7 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > .toolbarbut
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > #downloads-indicator-anchor {
|
||||
toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > .toolbarbutton-badge-stack > #downloads-indicator-anchor {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -985,7 +996,6 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > #downloads-
|
||||
/* Give this menupopup an arrow panel styling */
|
||||
#BMB_bookmarksPopup {
|
||||
appearance: none;
|
||||
-moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-arrow");
|
||||
background: transparent;
|
||||
border: none;
|
||||
/* The popup inherits -moz-image-region from the button, must reset it */
|
||||
|
@ -35,6 +35,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
LightweightThemeConsumer:
|
||||
"resource://gre/modules/LightweightThemeConsumer.jsm",
|
||||
Log: "resource://gre/modules/Log.jsm",
|
||||
LoginHelper: "resource://gre/modules/LoginHelper.jsm",
|
||||
LoginManagerParent: "resource://gre/modules/LoginManagerParent.jsm",
|
||||
MigrationUtils: "resource:///modules/MigrationUtils.jsm",
|
||||
NetUtil: "resource://gre/modules/NetUtil.jsm",
|
||||
@ -165,11 +166,6 @@ XPCOMUtils.defineLazyScriptGetter(
|
||||
["gGestureSupport", "gHistorySwipeAnimation"],
|
||||
"chrome://browser/content/browser-gestureSupport.js"
|
||||
);
|
||||
XPCOMUtils.defineLazyScriptGetter(
|
||||
this,
|
||||
"gSafeBrowsing",
|
||||
"chrome://browser/content/browser-safebrowsing.js"
|
||||
);
|
||||
XPCOMUtils.defineLazyScriptGetter(
|
||||
this,
|
||||
"gSync",
|
||||
@ -246,7 +242,9 @@ XPCOMUtils.defineLazyServiceGetters(this, {
|
||||
"@mozilla.org/network/serialization-helper;1",
|
||||
"nsISerializationHelper",
|
||||
],
|
||||
#ifdef ENABLE_MARIONETTE
|
||||
Marionette: ["@mozilla.org/remote/marionette;1", "nsIMarionette"],
|
||||
#endif
|
||||
WindowsUIUtils: ["@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils"],
|
||||
});
|
||||
|
||||
@ -286,58 +284,11 @@ XPCOMUtils.defineLazyGetter(this, "gNavToolbox", () => {
|
||||
return document.getElementById("navigator-toolbox");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gURLBar", () => gURLBarHandler.urlbar);
|
||||
|
||||
/**
|
||||
* Tracks the urlbar object, allowing to reinitiate it when necessary, e.g. on
|
||||
* customization.
|
||||
*/
|
||||
var gURLBarHandler = {
|
||||
/**
|
||||
* The urlbar binding or object.
|
||||
*/
|
||||
get urlbar() {
|
||||
if (!this._urlbar) {
|
||||
let textbox = document.getElementById("urlbar");
|
||||
this._urlbar = new UrlbarInput({ textbox });
|
||||
if (this._lastValue) {
|
||||
this._urlbar.value = this._lastValue;
|
||||
delete this._lastValue;
|
||||
}
|
||||
gBrowser.tabContainer.addEventListener("TabSelect", this._urlbar);
|
||||
}
|
||||
return this._urlbar;
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoked by CustomizationHandler when a customization starts.
|
||||
*/
|
||||
customizeStart() {
|
||||
if (this._urlbar) {
|
||||
this._urlbar.removeCopyCutController();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoked by CustomizationHandler when a customization ends.
|
||||
*/
|
||||
customizeEnd() {
|
||||
this._reset();
|
||||
},
|
||||
|
||||
/**
|
||||
* Used to reset the gURLBar value.
|
||||
*/
|
||||
_reset() {
|
||||
if (this._urlbar) {
|
||||
gBrowser.tabContainer.removeEventListener("TabSelect", this._urlbar);
|
||||
this._lastValue = this._urlbar.value;
|
||||
this._urlbar.uninit();
|
||||
delete this._urlbar;
|
||||
gURLBar = this.urlbar;
|
||||
}
|
||||
},
|
||||
};
|
||||
XPCOMUtils.defineLazyGetter(this, "gURLBar", () => {
|
||||
return new UrlbarInput({
|
||||
textbox: document.getElementById("urlbar"),
|
||||
});
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ReferrerInfo", () =>
|
||||
Components.Constructor(
|
||||
@ -472,13 +423,6 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
}
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"gHtmlAboutAddonsEnabled",
|
||||
"extensions.htmlaboutaddons.enabled",
|
||||
false
|
||||
);
|
||||
|
||||
customElements.setElementCreationCallback("translation-notification", () => {
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://browser/content/translation-notification.js",
|
||||
@ -645,7 +589,7 @@ function UpdateBackForwardCommands(aWebNavigation) {
|
||||
|
||||
/**
|
||||
* Click-and-Hold implementation for the Back and Forward buttons
|
||||
* XXXmano: should this live in toolbarbutton.xml?
|
||||
* XXXmano: should this live in toolbarbutton.js?
|
||||
*/
|
||||
function SetClickAndHoldHandlers() {
|
||||
// Bug 414797: Clone the back/forward buttons' context menu into both buttons.
|
||||
@ -656,13 +600,13 @@ function SetClickAndHoldHandlers() {
|
||||
|
||||
let backButton = document.getElementById("back-button");
|
||||
backButton.setAttribute("type", "menu");
|
||||
backButton.appendChild(popup);
|
||||
backButton.prepend(popup);
|
||||
gClickAndHoldListenersOnElement.add(backButton);
|
||||
|
||||
let forwardButton = document.getElementById("forward-button");
|
||||
popup = popup.cloneNode(true);
|
||||
forwardButton.setAttribute("type", "menu");
|
||||
forwardButton.appendChild(popup);
|
||||
forwardButton.prepend(popup);
|
||||
gClickAndHoldListenersOnElement.add(forwardButton);
|
||||
}
|
||||
|
||||
@ -679,7 +623,7 @@ const gClickAndHoldListenersOnElement = {
|
||||
}
|
||||
|
||||
// Prevent the menupopup from opening immediately
|
||||
aEvent.currentTarget.firstElementChild.hidden = true;
|
||||
aEvent.currentTarget.menupopup.hidden = true;
|
||||
|
||||
aEvent.currentTarget.addEventListener("mouseout", this);
|
||||
aEvent.currentTarget.addEventListener("mouseup", this);
|
||||
@ -1579,7 +1523,8 @@ var delayedStartupPromise = new Promise(resolve => {
|
||||
|
||||
var gBrowserInit = {
|
||||
delayedStartupFinished: false,
|
||||
idleTasksFinished: false,
|
||||
idleTasksFinishedPromise: null,
|
||||
idleTaskPromiseResolve: null,
|
||||
|
||||
_tabToAdopt: undefined,
|
||||
|
||||
@ -1613,10 +1558,6 @@ var gBrowserInit = {
|
||||
},
|
||||
|
||||
onBeforeInitialXULLayout() {
|
||||
// Turn on QuantumBar. This can be removed once the quantumbar attribute is gone.
|
||||
let urlbar = document.getElementById("urlbar");
|
||||
urlbar.setAttribute("quantumbar", true);
|
||||
|
||||
// Set a sane starting width/height for all resolutions on new profiles.
|
||||
if (Services.prefs.getBoolPref("privacy.resistFingerprinting")) {
|
||||
// When the fingerprinting resistance is enabled, making sure that we don't
|
||||
@ -1685,7 +1626,7 @@ var gBrowserInit = {
|
||||
// This needs setting up before we create the first remote browser.
|
||||
window.docShell.treeOwner
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIXULWindow).XULBrowserWindow = window.XULBrowserWindow;
|
||||
.getInterface(Ci.nsIAppWindow).XULBrowserWindow = window.XULBrowserWindow;
|
||||
window.browserDOMWindow = new nsBrowserAccess();
|
||||
|
||||
gBrowser = window._gBrowser;
|
||||
@ -1783,7 +1724,7 @@ var gBrowserInit = {
|
||||
|
||||
if (!window.toolbar.visible) {
|
||||
// adjust browser UI for popups
|
||||
gURLBar.setAttribute("readonly", "true");
|
||||
gURLBar.readOnly = true;
|
||||
}
|
||||
|
||||
// Misc. inits.
|
||||
@ -1799,7 +1740,9 @@ var gBrowserInit = {
|
||||
ToolbarKeyboardNavigator.init();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MARIONETTE
|
||||
gRemoteControl.updateVisualCue(Marionette.running);
|
||||
#endif
|
||||
|
||||
// If we are given a tab to swap in, take care of it before first paint to
|
||||
// avoid an about:blank flash.
|
||||
@ -1883,7 +1826,9 @@ var gBrowserInit = {
|
||||
this._handleURIToLoad();
|
||||
|
||||
Services.obs.addObserver(gIdentityHandler, "perm-changed");
|
||||
#ifdef ENABLE_MARIONETTE
|
||||
Services.obs.addObserver(gRemoteControl, "remote-active");
|
||||
#endif
|
||||
Services.obs.addObserver(
|
||||
gSessionHistoryObserver,
|
||||
"browser:purge-session-history"
|
||||
@ -1927,8 +1872,7 @@ var gBrowserInit = {
|
||||
|
||||
let safeMode = document.getElementById("helpSafeMode");
|
||||
if (Services.appinfo.inSafeMode) {
|
||||
safeMode.label = safeMode.getAttribute("stoplabel");
|
||||
safeMode.accessKey = safeMode.getAttribute("stopaccesskey");
|
||||
document.l10n.setAttributes(safeMode, "menu-help-safe-mode-with-addons");
|
||||
}
|
||||
|
||||
// BiDi UI
|
||||
@ -1993,7 +1937,7 @@ var gBrowserInit = {
|
||||
window.addEventListener("dragover", MousePosTracker);
|
||||
|
||||
gNavToolbox.addEventListener("customizationstarting", CustomizationHandler);
|
||||
gNavToolbox.addEventListener("customizationending", CustomizationHandler);
|
||||
gNavToolbox.addEventListener("aftercustomization", CustomizationHandler);
|
||||
|
||||
SessionStore.promiseInitialized.then(() => {
|
||||
// Bail out if the window has been closed in the meantime.
|
||||
@ -2288,7 +2232,7 @@ var gBrowserInit = {
|
||||
// timeouts) should execute in order. Note that this observer notification is
|
||||
// not guaranteed to fire, since the window could close before we get here.
|
||||
scheduleIdleTask(() => {
|
||||
this.idleTasksFinished = true;
|
||||
this.idleTaskPromiseResolve();
|
||||
Services.obs.notifyObservers(
|
||||
window,
|
||||
"browser-idle-startup-tasks-finished"
|
||||
@ -2435,7 +2379,9 @@ var gBrowserInit = {
|
||||
FullZoom.destroy();
|
||||
|
||||
Services.obs.removeObserver(gIdentityHandler, "perm-changed");
|
||||
#ifdef ENABLE_MARIONETTE
|
||||
Services.obs.removeObserver(gRemoteControl, "remote-active");
|
||||
#endif
|
||||
Services.obs.removeObserver(
|
||||
gSessionHistoryObserver,
|
||||
"browser:purge-session-history"
|
||||
@ -2482,11 +2428,15 @@ var gBrowserInit = {
|
||||
window.XULBrowserWindow = null;
|
||||
window.docShell.treeOwner
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIXULWindow).XULBrowserWindow = null;
|
||||
.getInterface(Ci.nsIAppWindow).XULBrowserWindow = null;
|
||||
window.browserDOMWindow = null;
|
||||
},
|
||||
};
|
||||
|
||||
gBrowserInit.idleTasksFinishedPromise = new Promise(resolve => {
|
||||
gBrowserInit.idleTaskPromiseResolve = resolve;
|
||||
});
|
||||
|
||||
function HandleAppCommandEvent(evt) {
|
||||
switch (evt.command) {
|
||||
case "Back":
|
||||
@ -2754,7 +2704,7 @@ function loadOneOrMoreURIs(aURIString, aTriggeringPrincipal, aCsp) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses the location bar input field and selects its contents.
|
||||
* Focuses and expands the location bar input field and selects its contents.
|
||||
*/
|
||||
function focusAndSelectUrlBar() {
|
||||
// In customize mode, the url bar is disabled. If a new tab is opened or the
|
||||
@ -2779,9 +2729,7 @@ function focusAndSelectUrlBar() {
|
||||
function openLocation() {
|
||||
if (window.location.href == AppConstants.BROWSER_CHROME_URL) {
|
||||
focusAndSelectUrlBar();
|
||||
if (gURLBar.openViewOnFocus && !gURLBar.view.isOpen) {
|
||||
gURLBar.startQuery();
|
||||
}
|
||||
gURLBar.view.autoOpen();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3166,7 +3114,7 @@ function BrowserPageInfo(
|
||||
|
||||
// We didn't find a matching window, so open a new one.
|
||||
return openDialog(
|
||||
"chrome://browser/content/pageinfo/pageInfo.xul",
|
||||
"chrome://browser/content/pageinfo/pageInfo.xhtml",
|
||||
"",
|
||||
"chrome,toolbar,dialog=no,resizable",
|
||||
args
|
||||
@ -3371,10 +3319,7 @@ function SetPageProxyState(aState, updatePopupNotifications) {
|
||||
}
|
||||
|
||||
let oldPageProxyState = gURLBar.getAttribute("pageproxystate");
|
||||
// The "browser_urlbar_stop_pending.js" test uses a MutationObserver to do
|
||||
// some verifications at this point, and it breaks if we don't write the
|
||||
// attribute, even if it hasn't changed (bug 1338115).
|
||||
gURLBar.setAttribute("pageproxystate", aState);
|
||||
gURLBar.setPageProxyState(aState);
|
||||
|
||||
// the page proxy state is set to valid via OnLocationChange, which
|
||||
// gets called when we switch tabs.
|
||||
@ -3431,7 +3376,6 @@ var BrowserOnClick = {
|
||||
init() {
|
||||
let mm = window.messageManager;
|
||||
mm.addMessageListener("Browser:CertExceptionError", this);
|
||||
mm.addMessageListener("Browser:SiteBlockedError", this);
|
||||
mm.addMessageListener("Browser:EnableOnlineMode", this);
|
||||
mm.addMessageListener("Browser:ResetSSLPreferences", this);
|
||||
mm.addMessageListener("Browser:SSLErrorReportTelemetry", this);
|
||||
@ -3443,7 +3387,6 @@ var BrowserOnClick = {
|
||||
uninit() {
|
||||
let mm = window.messageManager;
|
||||
mm.removeMessageListener("Browser:CertExceptionError", this);
|
||||
mm.removeMessageListener("Browser:SiteBlockedError", this);
|
||||
mm.removeMessageListener("Browser:EnableOnlineMode", this);
|
||||
mm.removeMessageListener("Browser:ResetSSLPreferences", this);
|
||||
mm.removeMessageListener("Browser:SSLErrorReportTelemetry", this);
|
||||
@ -3464,15 +3407,6 @@ var BrowserOnClick = {
|
||||
msg.data.frameId
|
||||
);
|
||||
break;
|
||||
case "Browser:SiteBlockedError":
|
||||
this.onAboutBlocked(
|
||||
msg.data.elementId,
|
||||
msg.data.reason,
|
||||
msg.data.isTopFrame,
|
||||
msg.data.location,
|
||||
msg.data.blockedInfo
|
||||
);
|
||||
break;
|
||||
case "Browser:EnableOnlineMode":
|
||||
if (Services.io.offline) {
|
||||
// Reset network state and refresh the page.
|
||||
@ -3606,7 +3540,7 @@ var BrowserOnClick = {
|
||||
cert = securityInfo.serverCert;
|
||||
Services.ww.openWindow(
|
||||
window,
|
||||
"chrome://pippki/content/certViewer.xul",
|
||||
"chrome://pippki/content/certViewer.xhtml",
|
||||
"_blank",
|
||||
"centerscreen,chrome",
|
||||
cert
|
||||
@ -3682,48 +3616,6 @@ var BrowserOnClick = {
|
||||
}
|
||||
},
|
||||
|
||||
onAboutBlocked(elementId, reason, isTopFrame, location, blockedInfo) {
|
||||
// Depending on what page we are displaying here (malware/phishing/unwanted)
|
||||
// use the right strings and links for each.
|
||||
let bucketName = "";
|
||||
let sendTelemetry = false;
|
||||
if (reason === "malware") {
|
||||
sendTelemetry = true;
|
||||
bucketName = "WARNING_MALWARE_PAGE_";
|
||||
} else if (reason === "phishing") {
|
||||
sendTelemetry = true;
|
||||
bucketName = "WARNING_PHISHING_PAGE_";
|
||||
} else if (reason === "unwanted") {
|
||||
sendTelemetry = true;
|
||||
bucketName = "WARNING_UNWANTED_PAGE_";
|
||||
} else if (reason === "harmful") {
|
||||
sendTelemetry = true;
|
||||
bucketName = "WARNING_HARMFUL_PAGE_";
|
||||
}
|
||||
let secHistogram = Services.telemetry.getHistogramById(
|
||||
"URLCLASSIFIER_UI_EVENTS"
|
||||
);
|
||||
let nsISecTel = Ci.IUrlClassifierUITelemetry;
|
||||
bucketName += isTopFrame ? "TOP_" : "FRAME_";
|
||||
|
||||
switch (elementId) {
|
||||
case "goBackButton":
|
||||
if (sendTelemetry) {
|
||||
secHistogram.add(nsISecTel[bucketName + "GET_ME_OUT_OF_HERE"]);
|
||||
}
|
||||
getMeOutOfHere();
|
||||
break;
|
||||
case "ignore_warning_link":
|
||||
if (Services.prefs.getBoolPref("browser.safebrowsing.allowOverride")) {
|
||||
if (sendTelemetry) {
|
||||
secHistogram.add(nsISecTel[bucketName + "IGNORE_WARNING"]);
|
||||
}
|
||||
this.ignoreWarningLink(reason, blockedInfo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
ignoreWarningLink(reason, blockedInfo) {
|
||||
let triggeringPrincipal = E10SUtils.deserializePrincipal(
|
||||
blockedInfo.triggeringPrincipal,
|
||||
@ -4638,14 +4530,13 @@ const BrowserSearch = {
|
||||
_setURLBarPlaceholder(name) {
|
||||
let placeholder;
|
||||
if (name) {
|
||||
placeholder = gBrowserBundle.formatStringFromName(
|
||||
"urlbar.placeholder",
|
||||
[name]
|
||||
);
|
||||
placeholder = gBrowserBundle.formatStringFromName("urlbar.placeholder", [
|
||||
name,
|
||||
]);
|
||||
} else {
|
||||
placeholder = gURLBar.getAttribute("defaultPlaceholder");
|
||||
}
|
||||
gURLBar.setAttribute("placeholder", placeholder);
|
||||
gURLBar.placeholder = placeholder;
|
||||
},
|
||||
|
||||
addEngine(browser, engine, uri) {
|
||||
@ -4751,10 +4642,7 @@ const BrowserSearch = {
|
||||
}
|
||||
|
||||
let focusUrlBarIfSearchFieldIsNotActive = function(aSearchBar) {
|
||||
if (
|
||||
!aSearchBar ||
|
||||
document.activeElement != aSearchBar.textbox.inputField
|
||||
) {
|
||||
if (!aSearchBar || document.activeElement != aSearchBar.textbox) {
|
||||
// Limit the results to search suggestions, like the search bar.
|
||||
gURLBar.search(UrlbarTokenizer.RESTRICT.SEARCH);
|
||||
}
|
||||
@ -4935,6 +4823,13 @@ const BrowserSearch = {
|
||||
|
||||
XPCOMUtils.defineConstant(this, "BrowserSearch", BrowserSearch);
|
||||
|
||||
function CreateContainerTabMenu(event) {
|
||||
createUserContextMenu(event, {
|
||||
useAccessKeys: false,
|
||||
showDefaultTab: true,
|
||||
});
|
||||
}
|
||||
|
||||
function FillHistoryMenu(aParent) {
|
||||
// Lazily add the hover listeners on first showing and never remove them
|
||||
if (!aParent.hasStatusListener) {
|
||||
@ -5456,7 +5351,7 @@ var XULBrowserWindow = {
|
||||
StatusPanel.update();
|
||||
},
|
||||
|
||||
setOverLink(url, anchorElt) {
|
||||
setOverLink(url) {
|
||||
if (url) {
|
||||
url = Services.textToSubURI.unEscapeURIForUI(url);
|
||||
|
||||
@ -5688,7 +5583,7 @@ var XULBrowserWindow = {
|
||||
var location = aLocationURI ? aLocationURI.spec : "";
|
||||
|
||||
this.hideOverLinkImmediately = true;
|
||||
this.setOverLink("", null);
|
||||
this.setOverLink("");
|
||||
this.hideOverLinkImmediately = false;
|
||||
|
||||
// We should probably not do this if the value has changed since the user
|
||||
@ -6081,6 +5976,7 @@ var CombinedStopReload = {
|
||||
if (event.button == 0 && !this.stop.disabled) {
|
||||
this._stopClicked = true;
|
||||
}
|
||||
break;
|
||||
case "animationend": {
|
||||
if (
|
||||
event.target.classList.contains("toolbarbutton-animatable-image") &&
|
||||
@ -6364,8 +6260,6 @@ var TabsProgressListener = {
|
||||
gBrowser.getNotificationBox(aBrowser).removeTransientNotifications();
|
||||
|
||||
FullZoom.onLocationChange(aLocationURI, false, aBrowser);
|
||||
|
||||
ContentBlocking.onLocationChange();
|
||||
},
|
||||
|
||||
onLinkIconAvailable(browser, dataURI, iconURI) {
|
||||
@ -7044,6 +6938,7 @@ var gUIDensity = {
|
||||
}
|
||||
|
||||
gBrowser.tabContainer.uiDensityChanged();
|
||||
gURLBar.updateLayoutBreakout();
|
||||
},
|
||||
};
|
||||
|
||||
@ -7972,8 +7867,7 @@ var CanvasPermissionPromptHelper = {
|
||||
|
||||
let browser;
|
||||
if (aSubject instanceof Ci.nsIDOMWindow) {
|
||||
let contentWindow = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
browser = contentWindow.docShell.chromeEventHandler;
|
||||
browser = aSubject.docShell.chromeEventHandler;
|
||||
} else {
|
||||
browser = aSubject;
|
||||
}
|
||||
@ -8419,7 +8313,6 @@ function BrowserOpenAddonsMgr(aView) {
|
||||
if (aView) {
|
||||
aSubject.loadView(aView);
|
||||
}
|
||||
aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
aSubject.focus();
|
||||
resolve(aSubject);
|
||||
}, "EM-loaded");
|
||||
@ -8567,41 +8460,6 @@ function checkEmptyPageOrigin(
|
||||
return contentPrincipal.isSystemPrincipal;
|
||||
}
|
||||
|
||||
function ReportFalseDeceptiveSite() {
|
||||
let docURI = gBrowser.selectedBrowser.documentURI;
|
||||
let isPhishingPage =
|
||||
docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
|
||||
|
||||
if (isPhishingPage) {
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
let onMessage = message => {
|
||||
mm.removeMessageListener("DeceptiveBlockedDetails:Result", onMessage);
|
||||
let reportUrl = gSafeBrowsing.getReportURL(
|
||||
"PhishMistake",
|
||||
message.data.blockedInfo
|
||||
);
|
||||
if (reportUrl) {
|
||||
openTrustedLinkIn(reportUrl, "tab");
|
||||
} else {
|
||||
let bundle = Services.strings.createBundle(
|
||||
"chrome://browser/locale/safebrowsing/safebrowsing.properties"
|
||||
);
|
||||
Services.prompt.alert(
|
||||
window,
|
||||
bundle.GetStringFromName("errorReportFalseDeceptiveTitle"),
|
||||
bundle.formatStringFromName(
|
||||
"errorReportFalseDeceptiveMessage",
|
||||
[message.data.blockedInfo.provider]
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
mm.addMessageListener("DeceptiveBlockedDetails:Result", onMessage);
|
||||
|
||||
mm.sendAsyncMessage("DeceptiveBlockedDetails");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a URL
|
||||
* eg:
|
||||
@ -8616,6 +8474,7 @@ function formatURL(aFormat, aIsPref) {
|
||||
: Services.urlFormatter.formatURL(aFormat);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MARIONETTE
|
||||
/**
|
||||
* Fired on the "marionette-remote-control" system notification,
|
||||
* indicating if the browser session is under remote control.
|
||||
@ -8634,6 +8493,7 @@ const gRemoteControl = {
|
||||
}
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
const gAccessibilityServiceIndicator = {
|
||||
init() {
|
||||
@ -8723,10 +8583,6 @@ var gPrivateBrowsingUI = {
|
||||
// Adjust the window's title
|
||||
let docElement = document.documentElement;
|
||||
if (!PrivateBrowsingUtils.permanentPrivateBrowsing) {
|
||||
docElement.setAttribute(
|
||||
"title",
|
||||
docElement.getAttribute("title_privatebrowsing")
|
||||
);
|
||||
docElement.setAttribute(
|
||||
"titlemodifier",
|
||||
docElement.getAttribute("titlemodifier_privatebrowsing")
|
||||
@ -9279,12 +9135,7 @@ var PanicButtonNotifier = {
|
||||
popup.addEventListener("popuphidden", removeListeners);
|
||||
|
||||
let widget = CustomizableUI.getWidget("panic-button").forWindow(window);
|
||||
let anchor = widget.anchor;
|
||||
anchor = document.getAnonymousElementByAttribute(
|
||||
anchor,
|
||||
"class",
|
||||
"toolbarbutton-icon"
|
||||
);
|
||||
let anchor = widget.anchor.icon;
|
||||
popup.openPopup(anchor, popup.getAttribute("position"));
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
@ -9440,7 +9291,6 @@ TabModalPromptBox.prototype = {
|
||||
let prompt = prompts[prompts.length - 1];
|
||||
prompt.element.hidden = false;
|
||||
// Because we were hidden before, this won't have been possible, so do it now:
|
||||
prompt.ensureXBLBindingAttached();
|
||||
prompt.Dialog.setDefaultFocus();
|
||||
} else {
|
||||
browser.removeAttribute("tabmodalPromptShowing");
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,7 @@ this.ContentSearchUIController = (function() {
|
||||
*
|
||||
* @param inputElement
|
||||
* Search suggestions will be based on the text in this text box.
|
||||
* Assumed to be an html:input. xul:textbox is untested but might work.
|
||||
* Assumed to be an html:input.
|
||||
* @param tableParent
|
||||
* The suggestion table is appended as a child to this element. Since
|
||||
* the table is absolutely positioned and its top and left values are set
|
||||
|
@ -2,8 +2,8 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# JS files which are needed by browser.xul but no other top level windows to
|
||||
# support MacOS specific features should be loaded directly from browser.xul
|
||||
# JS files which are needed by browser.xhtml but no other top level windows to
|
||||
# support MacOS specific features should be loaded directly from browser.xhtml
|
||||
# rather than this file.
|
||||
|
||||
# If you update this list, you may need to add a mapping within the following
|
||||
@ -18,8 +18,8 @@ Services.scriptloader.loadSubScript("chrome://browser/content/browser-places.js"
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/globalOverlay.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/editMenuOverlay.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/utilityOverlay.js", this);
|
||||
#ifdef XP_MACOSX
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/macWindowMenu.js", this);
|
||||
#endif
|
||||
if (AppConstants.platform == "macosx") {
|
||||
Services.scriptloader.loadSubScript("chrome://global/content/macWindowMenu.js", this);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
@ -11,10 +11,11 @@
|
||||
]>
|
||||
|
||||
<window id="main-window"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
data-l10n-sync="true">
|
||||
|
||||
#include macWindow.inc.xul
|
||||
#include macWindow.inc.xhtml
|
||||
|
||||
<!-- Dock menu -->
|
||||
<popupset>
|
@ -4,22 +4,29 @@
|
||||
|
||||
# This include file should only contain things that are needed to support MacOS
|
||||
# specific features that are needed for all top level windows. If the feature is
|
||||
# also needed in browser.xul, it should go in one of the various include files
|
||||
# below that are shared with browser.xul. When including this file,
|
||||
# also needed in browser.xhtml, it should go in one of the various include files
|
||||
# below that are shared with browser.xhtml. When including this file,
|
||||
# browser-doctype.inc must also be included.
|
||||
|
||||
# All JS files which are needed by browser.xul and other top level windows to
|
||||
<linkset>
|
||||
<html:link rel="localization" href="branding/brand.ftl"/>
|
||||
<html:link rel="localization" href="browser/branding/sync-brand.ftl"/>
|
||||
<html:link rel="localization" href="toolkit/global/textActions.ftl"/>
|
||||
<html:link rel="localization" href="browser/menubar.ftl"/>
|
||||
</linkset>
|
||||
|
||||
# All JS files which are needed by browser.xhtml and other top level windows to
|
||||
# support MacOS specific features *must* go into the global-scripts.inc file so
|
||||
# that they can be shared with browser.xul.
|
||||
# that they can be shared with browser.xhtml.
|
||||
#include global-scripts.inc
|
||||
|
||||
<script src="chrome://browser/content/nonbrowser-mac.js"></script>
|
||||
|
||||
# All sets except for popupsets (commands, keys, and stringbundles)
|
||||
# *must* go into the browser-sets.inc file so that they can be shared with
|
||||
# browser.xul
|
||||
# browser.xhtml
|
||||
#include browser-sets.inc
|
||||
|
||||
# The entire main menubar is placed into browser-menubar.inc, so that it can be
|
||||
# shared with browser.xul.
|
||||
# shared with browser.xhtml.
|
||||
#include browser-menubar.inc
|
@ -95,9 +95,6 @@ with Files("test/tabs/**"):
|
||||
with Files("test/touch/**"):
|
||||
BUG_COMPONENT = ("Firefox", "General")
|
||||
|
||||
with Files("test/trackingUI/**"):
|
||||
BUG_COMPONENT = ("Firefox", "Protections UI")
|
||||
|
||||
with Files("test/webextensions/**"):
|
||||
BUG_COMPONENT = ("WebExtensions", "Untriaged")
|
||||
|
||||
@ -110,9 +107,6 @@ with Files("aboutNetError.xhtml"):
|
||||
with Files("test/caps/**"):
|
||||
BUG_COMPONENT = ("Firefox", "Security")
|
||||
|
||||
with Files("blockedSite.xhtml"):
|
||||
BUG_COMPONENT = ("Toolkit", "Safe Browsing")
|
||||
|
||||
with Files("browser-addons.js"):
|
||||
BUG_COMPONENT = ("Toolkit", "Add-ons Manager")
|
||||
|
||||
@ -140,19 +134,16 @@ with Files("browser-places.js"):
|
||||
with Files("browser-plugins.js"):
|
||||
BUG_COMPONENT = ("Core", "Plug-ins")
|
||||
|
||||
with Files("browser-safebrowsing.js"):
|
||||
BUG_COMPONENT = ("Toolkit", "Safe Browsing")
|
||||
|
||||
with Files("browser-sync.js"):
|
||||
BUG_COMPONENT = ("Firefox", "Sync")
|
||||
|
||||
with Files("contentSearch*"):
|
||||
BUG_COMPONENT = ("Firefox", "Search")
|
||||
|
||||
with Files("hiddenWindow.xul"):
|
||||
with Files("hiddenWindowMac.xhtml"):
|
||||
BUG_COMPONENT = ("Firefox", "Site Permissions")
|
||||
|
||||
with Files("macWindow.inc.xul"):
|
||||
with Files("macWindow.inc.xhtml"):
|
||||
BUG_COMPONENT = ("Firefox", "Shell Integration")
|
||||
|
||||
with Files("tabbrowser*"):
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Security-Policy" content="connect-src https:; default-src chrome:">
|
||||
<meta http-equiv="Content-Security-Policy" content="connect-src https:; default-src chrome:; object-src 'none'">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<link rel="stylesheet" type="text/css" href="chrome://global/skin/in-content/common.css">
|
||||
<link rel="stylesheet" type="text/css" href="chrome://browser/skin/newInstallPage.css">
|
||||
|
@ -65,7 +65,9 @@ function nonBrowserWindowStartup() {
|
||||
|
||||
// If no windows are active (i.e. we're the hidden window), disable the close, minimize
|
||||
// and zoom menu commands as well
|
||||
if (window.location.href == "chrome://browser/content/hiddenWindow.xul") {
|
||||
if (
|
||||
window.location.href == "chrome://browser/content/hiddenWindowMac.xhtml"
|
||||
) {
|
||||
var hiddenWindowDisabledItems = [
|
||||
"cmd_close",
|
||||
"minimizeWindow",
|
||||
@ -123,7 +125,9 @@ function nonBrowserWindowDelayedStartup() {
|
||||
function nonBrowserWindowShutdown() {
|
||||
// If this is the hidden window being closed, release our reference to
|
||||
// the dock menu element to prevent leaks on shutdown
|
||||
if (window.location.href == "chrome://browser/content/hiddenWindow.xul") {
|
||||
if (
|
||||
window.location.href == "chrome://browser/content/hiddenWindowMac.xhtml"
|
||||
) {
|
||||
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"].getService(
|
||||
Ci.nsIMacDockSupport
|
||||
);
|
||||
|
@ -2,16 +2,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
LoginHelper: "resource://gre/modules/LoginHelper.jsm",
|
||||
LoginManagerContextMenu: "resource://gre/modules/LoginManagerContextMenu.jsm",
|
||||
DevToolsShim: "chrome://devtools-startup/content/DevToolsShim.jsm",
|
||||
});
|
||||
|
||||
var gContextMenuContentData = null;
|
||||
|
||||
function setContextMenuContentData(data) {
|
||||
gContextMenuContentData = data;
|
||||
nsContextMenu.contentData = data;
|
||||
}
|
||||
|
||||
function openContextMenu(aMessage) {
|
||||
@ -41,10 +33,9 @@ function openContextMenu(aMessage) {
|
||||
}
|
||||
}
|
||||
|
||||
gContextMenuContentData = {
|
||||
nsContextMenu.contentData = {
|
||||
context: data.context,
|
||||
isRemote: data.isRemote,
|
||||
popupNodeSelectors: data.popupNodeSelectors,
|
||||
browser,
|
||||
editFlags: data.editFlags,
|
||||
spellInfo,
|
||||
@ -68,7 +59,7 @@ function openContextMenu(aMessage) {
|
||||
};
|
||||
|
||||
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
|
||||
let context = gContextMenuContentData.context;
|
||||
let context = nsContextMenu.contentData.context;
|
||||
|
||||
// We don't have access to the original event here, as that happened in
|
||||
// another process. Therefore we synthesize a new MouseEvent to propagate the
|
||||
@ -96,14 +87,8 @@ function openContextMenu(aMessage) {
|
||||
popup.openPopupAtScreen(newEvent.screenX, newEvent.screenY, true, newEvent);
|
||||
}
|
||||
|
||||
function nsContextMenu(aXulMenu, aIsShift) {
|
||||
this.shouldDisplay = true;
|
||||
this.initMenu(aXulMenu, aIsShift);
|
||||
}
|
||||
|
||||
// Prototype for nsContextMenu "class."
|
||||
nsContextMenu.prototype = {
|
||||
initMenu: function CM_initMenu(aXulMenu, aIsShift) {
|
||||
class nsContextMenu {
|
||||
constructor(aXulMenu, aIsShift) {
|
||||
// Get contextual info.
|
||||
this.setContext();
|
||||
|
||||
@ -116,7 +101,7 @@ nsContextMenu.prototype = {
|
||||
if (!aIsShift) {
|
||||
if (this.isRemote) {
|
||||
this.hasPageMenu = PageMenuParent.addToPopup(
|
||||
gContextMenuContentData.customMenuItems,
|
||||
this.contentData.customMenuItems,
|
||||
this.browser,
|
||||
aXulMenu
|
||||
);
|
||||
@ -149,9 +134,7 @@ nsContextMenu.prototype = {
|
||||
onSpellcheckable: this.onSpellcheckable,
|
||||
onPassword: this.onPassword,
|
||||
srcUrl: this.mediaURL,
|
||||
frameUrl: gContextMenuContentData
|
||||
? gContextMenuContentData.docLocation
|
||||
: undefined,
|
||||
frameUrl: this.contentData ? this.contentData.docLocation : undefined,
|
||||
pageUrl: this.browser ? this.browser.currentURI.spec : undefined,
|
||||
linkText: this.linkTextStr,
|
||||
linkUrl: this.linkURL,
|
||||
@ -160,8 +143,8 @@ nsContextMenu.prototype = {
|
||||
: undefined,
|
||||
frameId: this.frameOuterWindowID,
|
||||
webExtBrowserType: this.webExtBrowserType,
|
||||
webExtContextData: gContextMenuContentData
|
||||
? gContextMenuContentData.webExtContextData
|
||||
webExtContextData: this.contentData
|
||||
? this.contentData.webExtContextData
|
||||
: undefined,
|
||||
};
|
||||
subject.wrappedJSObject = subject;
|
||||
@ -191,16 +174,17 @@ nsContextMenu.prototype = {
|
||||
|
||||
// Initialize (disable/remove) menu items.
|
||||
this.initItems();
|
||||
},
|
||||
}
|
||||
|
||||
setContext() {
|
||||
let context = Object.create(null);
|
||||
this.isRemote = false;
|
||||
|
||||
if (gContextMenuContentData) {
|
||||
context = gContextMenuContentData.context;
|
||||
gContextMenuContentData.context = null;
|
||||
this.isRemote = gContextMenuContentData.isRemote;
|
||||
if (nsContextMenu.contentData) {
|
||||
this.contentData = nsContextMenu.contentData;
|
||||
context = this.contentData.context;
|
||||
nsContextMenu.contentData = null;
|
||||
this.isRemote = this.contentData.isRemote;
|
||||
}
|
||||
|
||||
this.shouldDisplay = context.shouldDisplay;
|
||||
@ -265,15 +249,9 @@ nsContextMenu.prototype = {
|
||||
|
||||
this.csp = E10SUtils.deserializeCSP(context.csp);
|
||||
|
||||
// Remember the CSS selectors corresponding to clicked node. gContextMenuContentData
|
||||
// can be null if the menu was triggered by tests in which case use an empty array.
|
||||
this.targetSelectors = gContextMenuContentData
|
||||
? gContextMenuContentData.popupNodeSelectors
|
||||
: [];
|
||||
|
||||
if (this.isRemote) {
|
||||
this.browser = gContextMenuContentData.browser;
|
||||
this.selectionInfo = gContextMenuContentData.selectionInfo;
|
||||
this.browser = this.contentData.browser;
|
||||
this.selectionInfo = this.contentData.selectionInfo;
|
||||
} else {
|
||||
this.browser = this.ownerDoc.defaultView.docShell.chromeEventHandler;
|
||||
this.selectionInfo = BrowserUtils.getSelectionDetails(window);
|
||||
@ -294,7 +272,7 @@ nsContextMenu.prototype = {
|
||||
|
||||
if (context.shouldInitInlineSpellCheckerUINoChildren) {
|
||||
if (this.isRemote) {
|
||||
InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo);
|
||||
InlineSpellCheckerUI.initFromRemote(this.contentData.spellInfo);
|
||||
} else {
|
||||
InlineSpellCheckerUI.init(this.target.editor);
|
||||
InlineSpellCheckerUI.initFromEvent(
|
||||
@ -306,7 +284,7 @@ nsContextMenu.prototype = {
|
||||
|
||||
if (context.shouldInitInlineSpellCheckerUIWithChildren) {
|
||||
if (this.isRemote) {
|
||||
InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo);
|
||||
InlineSpellCheckerUI.initFromRemote(this.contentData.spellInfo);
|
||||
} else {
|
||||
var targetWin = this.ownerDoc.defaultView;
|
||||
var { editingSession } = targetWin.docShell;
|
||||
@ -322,30 +300,30 @@ nsContextMenu.prototype = {
|
||||
this.showItem("spell-check-enabled", canSpell);
|
||||
this.showItem("spell-separator", canSpell);
|
||||
}
|
||||
}, // setContext
|
||||
} // setContext
|
||||
|
||||
hiding: function CM_hiding() {
|
||||
hiding() {
|
||||
if (this.browser && this.browser.messageManager) {
|
||||
this.browser.messageManager.sendAsyncMessage("ContextMenu:Hiding");
|
||||
}
|
||||
|
||||
gContextMenuContentData = null;
|
||||
this.contentData = null;
|
||||
InlineSpellCheckerUI.clearSuggestionsFromMenu();
|
||||
InlineSpellCheckerUI.clearDictionaryListFromMenu();
|
||||
InlineSpellCheckerUI.uninit();
|
||||
if (
|
||||
Cu.isModuleLoaded("resource://gre/modules/LoginManagerContextMenu.jsm")
|
||||
) {
|
||||
LoginManagerContextMenu.clearLoginsFromMenu(document);
|
||||
nsContextMenu.LoginManagerContextMenu.clearLoginsFromMenu(document);
|
||||
}
|
||||
|
||||
// This handler self-deletes, only run it if it is still there:
|
||||
if (this._onPopupHiding) {
|
||||
this._onPopupHiding();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
initItems: function CM_initItems() {
|
||||
initItems() {
|
||||
this.initPageMenuSeparator();
|
||||
this.initOpenItems();
|
||||
this.initNavigationItems();
|
||||
@ -359,13 +337,13 @@ nsContextMenu.prototype = {
|
||||
this.initClickToPlayItems();
|
||||
this.initPasswordManagerItems();
|
||||
this.initSyncItems();
|
||||
},
|
||||
}
|
||||
|
||||
initPageMenuSeparator: function CM_initPageMenuSeparator() {
|
||||
initPageMenuSeparator() {
|
||||
this.showItem("page-menu-separator", this.hasPageMenu);
|
||||
},
|
||||
}
|
||||
|
||||
initOpenItems: function CM_initOpenItems() {
|
||||
initOpenItems() {
|
||||
var isMailtoInternal = false;
|
||||
if (this.onMailtoLink) {
|
||||
var mailtoHandler = Cc[
|
||||
@ -396,17 +374,14 @@ nsContextMenu.prototype = {
|
||||
}
|
||||
|
||||
var inContainer = false;
|
||||
if (gContextMenuContentData.userContextId) {
|
||||
if (this.contentData.userContextId) {
|
||||
inContainer = true;
|
||||
var item = document.getElementById("context-openlinkincontainertab");
|
||||
|
||||
item.setAttribute(
|
||||
"data-usercontextid",
|
||||
gContextMenuContentData.userContextId
|
||||
);
|
||||
item.setAttribute("data-usercontextid", this.contentData.userContextId);
|
||||
|
||||
var label = ContextualIdentityService.getUserContextLabel(
|
||||
gContextMenuContentData.userContextId
|
||||
this.contentData.userContextId
|
||||
);
|
||||
item.setAttribute(
|
||||
"label",
|
||||
@ -436,9 +411,9 @@ nsContextMenu.prototype = {
|
||||
);
|
||||
this.showItem("context-openlinkincurrent", this.onPlainTextLink);
|
||||
this.showItem("context-sep-open", shouldShow);
|
||||
},
|
||||
}
|
||||
|
||||
initNavigationItems: function CM_initNavigationItems() {
|
||||
initNavigationItems() {
|
||||
var shouldShow =
|
||||
!(
|
||||
this.isContentSelected ||
|
||||
@ -462,9 +437,9 @@ nsContextMenu.prototype = {
|
||||
|
||||
this.showItem("context-reload", stopReloadItem == "reload");
|
||||
this.showItem("context-stop", stopReloadItem == "stop");
|
||||
},
|
||||
}
|
||||
|
||||
initLeaveDOMFullScreenItems: function CM_initLeaveFullScreenItem() {
|
||||
initLeaveDOMFullScreenItems() {
|
||||
// only show the option if the user is in DOM fullscreen
|
||||
var shouldShow = this.target.ownerDocument.fullscreen;
|
||||
this.showItem("context-leave-dom-fullscreen", shouldShow);
|
||||
@ -473,9 +448,9 @@ nsContextMenu.prototype = {
|
||||
if (shouldShow) {
|
||||
this.showItem("context-media-sep-commands", true);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
initSaveItems: function CM_initSaveItems() {
|
||||
initSaveItems() {
|
||||
var shouldShow = !(
|
||||
this.onTextInput ||
|
||||
this.onLink ||
|
||||
@ -515,9 +490,9 @@ nsContextMenu.prototype = {
|
||||
"disabled",
|
||||
!this.mediaURL || mediaIsBlob
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
initViewItems: function CM_initViewItems() {
|
||||
initViewItems() {
|
||||
// View source is always OK, unless in directory listing.
|
||||
this.showItem(
|
||||
"context-viewpartialsource-selection",
|
||||
@ -586,8 +561,9 @@ nsContextMenu.prototype = {
|
||||
);
|
||||
|
||||
if (haveSetDesktopBackground && this.onLoadedImage) {
|
||||
document.getElementById("context-setDesktopBackground").disabled =
|
||||
gContextMenuContentData.disableSetDesktopBackground;
|
||||
document.getElementById(
|
||||
"context-setDesktopBackground"
|
||||
).disabled = this.contentData.disableSetDesktopBackground;
|
||||
}
|
||||
|
||||
// Reload image depends on an image that's not fully loaded
|
||||
@ -634,9 +610,9 @@ nsContextMenu.prototype = {
|
||||
"context-viewimagedesc",
|
||||
this.onImage && this.imageDescURL !== ""
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
initMiscItems: function CM_initMiscItems() {
|
||||
initMiscItems() {
|
||||
// Use "Bookmark This Link" if on a link.
|
||||
let bookmarkPage = document.getElementById("context-bookmarkpage");
|
||||
this.showItem(
|
||||
@ -707,7 +683,7 @@ nsContextMenu.prototype = {
|
||||
"context-bidi-page-direction-toggle",
|
||||
!this.onTextInput && top.gBidiUI
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
initSpellingItems() {
|
||||
var canSpell =
|
||||
@ -762,7 +738,7 @@ nsContextMenu.prototype = {
|
||||
} else {
|
||||
this.showItem("spell-add-dictionaries-main", false);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
initClipboardItems() {
|
||||
// Copy depends on whether there is selected text.
|
||||
@ -823,7 +799,7 @@ nsContextMenu.prototype = {
|
||||
"context-sep-copyimage",
|
||||
this.onImage || this.onVideo || this.onAudio
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
initMediaPlayerItems() {
|
||||
var onMedia = this.onVideo || this.onAudio;
|
||||
@ -932,18 +908,17 @@ nsContextMenu.prototype = {
|
||||
}
|
||||
}
|
||||
this.showItem("context-media-sep-commands", onMedia);
|
||||
},
|
||||
}
|
||||
|
||||
initClickToPlayItems() {
|
||||
this.showItem("context-ctp-play", this.onCTPPlugin);
|
||||
this.showItem("context-ctp-hide", this.onCTPPlugin);
|
||||
this.showItem("context-sep-ctp", this.onCTPPlugin);
|
||||
},
|
||||
}
|
||||
|
||||
initPasswordManagerItems() {
|
||||
let loginFillInfo =
|
||||
gContextMenuContentData && gContextMenuContentData.loginFillInfo;
|
||||
let documentURI = gContextMenuContentData.documentURIObject;
|
||||
let loginFillInfo = this.contentData && this.contentData.loginFillInfo;
|
||||
let documentURI = this.contentData.documentURIObject;
|
||||
|
||||
// If we could not find a password field we
|
||||
// don't want to show the form fill option.
|
||||
@ -987,7 +962,7 @@ nsContextMenu.prototype = {
|
||||
}
|
||||
|
||||
let formOrigin = LoginHelper.getLoginOrigin(documentURI.spec);
|
||||
let fragment = LoginManagerContextMenu.addLoginsToMenu(
|
||||
let fragment = nsContextMenu.LoginManagerContextMenu.addLoginsToMenu(
|
||||
this.targetIdentifier,
|
||||
this.browser,
|
||||
formOrigin
|
||||
@ -1015,40 +990,48 @@ nsContextMenu.prototype = {
|
||||
let popup = document.getElementById("fill-login-popup");
|
||||
let insertBeforeElement = document.getElementById("fill-login-no-logins");
|
||||
popup.insertBefore(fragment, insertBeforeElement);
|
||||
},
|
||||
}
|
||||
|
||||
initSyncItems() {
|
||||
gSync.updateContentContextMenu(this);
|
||||
},
|
||||
}
|
||||
|
||||
openPasswordManager() {
|
||||
LoginHelper.openPasswordManager(window, {
|
||||
filterString: gContextMenuContentData.documentURIObject.host,
|
||||
filterString: this.contentData.documentURIObject.host,
|
||||
entryPoint: "contextmenu",
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
fillGeneratedPassword() {
|
||||
LoginManagerContextMenu.fillGeneratedPassword(this.targetIdentifier,
|
||||
gContextMenuContentData.documentURIObject,
|
||||
this.browser);
|
||||
},
|
||||
nsContextMenu.LoginManagerContextMenu.fillGeneratedPassword(
|
||||
this.targetIdentifier,
|
||||
this.contentData.documentURIObject,
|
||||
this.browser
|
||||
);
|
||||
}
|
||||
|
||||
inspectNode() {
|
||||
return DevToolsShim.inspectNode(gBrowser.selectedTab, this.targetSelectors);
|
||||
},
|
||||
return nsContextMenu.DevToolsShim.inspectNode(
|
||||
gBrowser.selectedTab,
|
||||
this.targetIdentifier
|
||||
);
|
||||
}
|
||||
|
||||
inspectA11Y() {
|
||||
return DevToolsShim.inspectA11Y(gBrowser.selectedTab, this.targetSelectors);
|
||||
},
|
||||
return nsContextMenu.DevToolsShim.inspectA11Y(
|
||||
gBrowser.selectedTab,
|
||||
this.targetIdentifier
|
||||
);
|
||||
}
|
||||
|
||||
_openLinkInParameters(extra) {
|
||||
let params = {
|
||||
charset: gContextMenuContentData.charSet,
|
||||
charset: this.contentData.charSet,
|
||||
originPrincipal: this.principal,
|
||||
triggeringPrincipal: this.principal,
|
||||
csp: this.csp,
|
||||
frameOuterWindowID: gContextMenuContentData.frameOuterWindowID,
|
||||
frameOuterWindowID: this.contentData.frameOuterWindowID,
|
||||
};
|
||||
for (let p in extra) {
|
||||
params[p] = extra[p];
|
||||
@ -1061,13 +1044,13 @@ nsContextMenu.prototype = {
|
||||
}
|
||||
|
||||
let referrerInfo = this.onLink
|
||||
? gContextMenuContentData.linkReferrerInfo
|
||||
: gContextMenuContentData.referrerInfo;
|
||||
? this.contentData.linkReferrerInfo
|
||||
: this.contentData.referrerInfo;
|
||||
// If we want to change userContextId, we must be sure that we don't
|
||||
// propagate the referrer.
|
||||
if (
|
||||
("userContextId" in params &&
|
||||
params.userContextId != gContextMenuContentData.userContextId) ||
|
||||
params.userContextId != this.contentData.userContextId) ||
|
||||
this.onPlainTextLink
|
||||
) {
|
||||
referrerInfo = new ReferrerInfo(
|
||||
@ -1079,12 +1062,12 @@ nsContextMenu.prototype = {
|
||||
|
||||
params.referrerInfo = referrerInfo;
|
||||
return params;
|
||||
},
|
||||
}
|
||||
|
||||
// Open linked-to URL in a new window.
|
||||
openLink() {
|
||||
openLinkIn(this.linkURL, "window", this._openLinkInParameters());
|
||||
},
|
||||
}
|
||||
|
||||
// Open linked-to URL in a new private window.
|
||||
openLinkInPrivateWindow() {
|
||||
@ -1093,18 +1076,18 @@ nsContextMenu.prototype = {
|
||||
"window",
|
||||
this._openLinkInParameters({ private: true })
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
// Open linked-to URL in a new tab.
|
||||
openLinkInTab(event) {
|
||||
let referrerURI = gContextMenuContentData.documentURIObject;
|
||||
let referrerURI = this.contentData.documentURIObject;
|
||||
|
||||
// if its parent allows mixed content and the referring URI passes
|
||||
// a same origin check with the target URI, we can preserve the users
|
||||
// decision of disabling MCB on a page for it's child tabs.
|
||||
let persistAllowMixedContentInChildTab = false;
|
||||
|
||||
if (gContextMenuContentData.parentAllowsMixedContent) {
|
||||
if (this.contentData.parentAllowsMixedContent) {
|
||||
const sm = Services.scriptSecurityManager;
|
||||
try {
|
||||
let targetURI = this.linkURI;
|
||||
@ -1121,22 +1104,22 @@ nsContextMenu.prototype = {
|
||||
};
|
||||
|
||||
openLinkIn(this.linkURL, "tab", this._openLinkInParameters(params));
|
||||
},
|
||||
}
|
||||
|
||||
// open URL in current tab
|
||||
openLinkInCurrent() {
|
||||
openLinkIn(this.linkURL, "current", this._openLinkInParameters());
|
||||
},
|
||||
}
|
||||
|
||||
// Open frame in a new tab.
|
||||
openFrameInTab() {
|
||||
openLinkIn(gContextMenuContentData.docLocation, "tab", {
|
||||
charset: gContextMenuContentData.charSet,
|
||||
openLinkIn(this.contentData.docLocation, "tab", {
|
||||
charset: this.contentData.charSet,
|
||||
triggeringPrincipal: this.browser.contentPrincipal,
|
||||
csp: this.browser.csp,
|
||||
referrerInfo: gContextMenuContentData.frameReferrerInfo,
|
||||
referrerInfo: this.contentData.frameReferrerInfo,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
// Reload clicked-in frame.
|
||||
reloadFrame(aEvent) {
|
||||
@ -1146,30 +1129,30 @@ nsContextMenu.prototype = {
|
||||
null,
|
||||
{ target: this.target, forceReload }
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
// Open clicked-in frame in its own window.
|
||||
openFrame() {
|
||||
openLinkIn(gContextMenuContentData.docLocation, "window", {
|
||||
charset: gContextMenuContentData.charSet,
|
||||
openLinkIn(this.contentData.docLocation, "window", {
|
||||
charset: this.contentData.charSet,
|
||||
triggeringPrincipal: this.browser.contentPrincipal,
|
||||
csp: this.browser.csp,
|
||||
referrerInfo: gContextMenuContentData.frameReferrerInfo,
|
||||
referrerInfo: this.contentData.frameReferrerInfo,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
// Open clicked-in frame in the same window.
|
||||
showOnlyThisFrame() {
|
||||
urlSecurityCheck(
|
||||
gContextMenuContentData.docLocation,
|
||||
this.contentData.docLocation,
|
||||
this.browser.contentPrincipal,
|
||||
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT
|
||||
);
|
||||
openWebLinkIn(gContextMenuContentData.docLocation, "current", {
|
||||
referrerInfo: gContextMenuContentData.frameReferrerInfo,
|
||||
openWebLinkIn(this.contentData.docLocation, "current", {
|
||||
referrerInfo: this.contentData.frameReferrerInfo,
|
||||
triggeringPrincipal: this.browser.contentPrincipal,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
// View Partial Source
|
||||
viewPartialSource() {
|
||||
@ -1202,36 +1185,36 @@ nsContextMenu.prototype = {
|
||||
};
|
||||
|
||||
top.gViewSourceUtils.viewPartialSourceInBrowser(browser, openSelectionFn);
|
||||
},
|
||||
}
|
||||
|
||||
// Open new "view source" window with the frame's URL.
|
||||
viewFrameSource() {
|
||||
BrowserViewSourceOfDocument({
|
||||
browser: this.browser,
|
||||
URL: gContextMenuContentData.docLocation,
|
||||
URL: this.contentData.docLocation,
|
||||
outerWindowID: this.frameOuterWindowID,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
viewInfo() {
|
||||
BrowserPageInfo(
|
||||
gContextMenuContentData.docLocation,
|
||||
this.contentData.docLocation,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
this.browser
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
viewImageInfo() {
|
||||
BrowserPageInfo(
|
||||
gContextMenuContentData.docLocation,
|
||||
this.contentData.docLocation,
|
||||
"mediaTab",
|
||||
this.imageInfo,
|
||||
null,
|
||||
this.browser
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
viewImageDesc(e) {
|
||||
urlSecurityCheck(
|
||||
@ -1240,21 +1223,21 @@ nsContextMenu.prototype = {
|
||||
Ci.nsIScriptSecurityManager.DISALLOW_SCRIPT
|
||||
);
|
||||
openUILink(this.imageDescURL, e, {
|
||||
referrerInfo: gContextMenuContentData.referrerInfo,
|
||||
referrerInfo: this.contentData.referrerInfo,
|
||||
triggeringPrincipal: this.principal,
|
||||
csp: this.csp,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
viewFrameInfo() {
|
||||
BrowserPageInfo(
|
||||
gContextMenuContentData.docLocation,
|
||||
this.contentData.docLocation,
|
||||
null,
|
||||
null,
|
||||
this.frameOuterWindowID,
|
||||
this.browser
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
reloadImage() {
|
||||
urlSecurityCheck(
|
||||
@ -1268,7 +1251,7 @@ nsContextMenu.prototype = {
|
||||
null,
|
||||
{ target: this.target }
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
_canvasToBlobURL(target) {
|
||||
let mm = this.browser.messageManager;
|
||||
@ -1284,11 +1267,11 @@ nsContextMenu.prototype = {
|
||||
};
|
||||
mm.addMessageListener("ContextMenu:Canvas:ToBlobURL:Result", onMessage);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
// Change current window to the URL of the image, video, or audio.
|
||||
viewMedia(e) {
|
||||
let referrerInfo = gContextMenuContentData.referrerInfo;
|
||||
let referrerInfo = this.contentData.referrerInfo;
|
||||
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
|
||||
if (this.onCanvas) {
|
||||
this._canvasToBlobURL(this.target).then(function(blobURL) {
|
||||
@ -1310,7 +1293,7 @@ nsContextMenu.prototype = {
|
||||
csp: this.csp,
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
saveVideoFrameAsImage() {
|
||||
let mm = this.browser.messageManager;
|
||||
@ -1339,7 +1322,7 @@ nsContextMenu.prototype = {
|
||||
);
|
||||
|
||||
// Cache this because we fetch the data async
|
||||
let referrerInfo = gContextMenuContentData.referrerInfo;
|
||||
let referrerInfo = this.contentData.referrerInfo;
|
||||
|
||||
let onMessage = message => {
|
||||
mm.removeMessageListener(
|
||||
@ -1369,11 +1352,11 @@ nsContextMenu.prototype = {
|
||||
"ContextMenu:SaveVideoFrameAsImage:Result",
|
||||
onMessage
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
leaveDOMFullScreen() {
|
||||
document.exitFullscreen();
|
||||
},
|
||||
}
|
||||
|
||||
// Change current window to the URL of the background image.
|
||||
viewBGImage(e) {
|
||||
@ -1384,11 +1367,11 @@ nsContextMenu.prototype = {
|
||||
);
|
||||
|
||||
openUILink(this.bgImageURL, e, {
|
||||
referrerInfo: gContextMenuContentData.referrerInfo,
|
||||
referrerInfo: this.contentData.referrerInfo,
|
||||
triggeringPrincipal: this.principal,
|
||||
csp: this.csp,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
setDesktopBackground() {
|
||||
let mm = this.browser.messageManager;
|
||||
@ -1419,7 +1402,7 @@ nsContextMenu.prototype = {
|
||||
|
||||
// Confirm since it's annoying if you hit this accidentally.
|
||||
const kDesktopBackgroundURL =
|
||||
"chrome://browser/content/setDesktopBackground.xul";
|
||||
"chrome://browser/content/setDesktopBackground.xhtml";
|
||||
|
||||
if (AppConstants.platform == "macosx") {
|
||||
// On Mac, the Set Desktop Background window is not modal.
|
||||
@ -1455,12 +1438,12 @@ nsContextMenu.prototype = {
|
||||
"ContextMenu:SetAsDesktopBackground:Result",
|
||||
onMessage
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
// Save URL of clicked-on frame.
|
||||
saveFrame() {
|
||||
saveBrowser(this.browser, false, this.frameOuterWindowID);
|
||||
},
|
||||
}
|
||||
|
||||
// Helper function to wait for appropriate MIME-type headers and
|
||||
// then prompt the user with a file picker
|
||||
@ -1639,13 +1622,13 @@ nsContextMenu.prototype = {
|
||||
|
||||
// kick off the channel with our proxy object as the listener
|
||||
channel.asyncOpen(new saveAsListener(this.principal));
|
||||
},
|
||||
}
|
||||
|
||||
// Save URL of clicked-on link.
|
||||
saveLink() {
|
||||
let referrerInfo = this.onLink
|
||||
? gContextMenuContentData.linkReferrerInfo
|
||||
: gContextMenuContentData.referrerInfo;
|
||||
? this.contentData.linkReferrerInfo
|
||||
: this.contentData.referrerInfo;
|
||||
|
||||
let isContentWindowPrivate = this.isRemote
|
||||
? this.ownerDoc.isPrivate
|
||||
@ -1661,14 +1644,14 @@ nsContextMenu.prototype = {
|
||||
this.linkDownload,
|
||||
isContentWindowPrivate
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
// Backwards-compatibility wrapper
|
||||
saveImage() {
|
||||
if (this.onCanvas || this.onImage) {
|
||||
this.saveMedia();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Save URL of the clicked upon image, video, or audio.
|
||||
saveMedia() {
|
||||
@ -1676,7 +1659,7 @@ nsContextMenu.prototype = {
|
||||
let isContentWindowPrivate = this.isRemote
|
||||
? this.ownerDoc.isPrivate
|
||||
: undefined;
|
||||
let referrerInfo = gContextMenuContentData.referrerInfo;
|
||||
let referrerInfo = this.contentData.referrerInfo;
|
||||
let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser);
|
||||
if (this.onCanvas) {
|
||||
// Bypass cache, since it's a data: URL.
|
||||
@ -1704,8 +1687,8 @@ nsContextMenu.prototype = {
|
||||
this.mediaURL,
|
||||
null, // document
|
||||
null, // file name; we'll take it from the URL
|
||||
gContextMenuContentData.contentDisposition,
|
||||
gContextMenuContentData.contentType,
|
||||
this.contentData.contentDisposition,
|
||||
this.contentData.contentType,
|
||||
false, // do not bypass the cache
|
||||
"SaveImageTitle",
|
||||
null, // chosen data
|
||||
@ -1730,26 +1713,26 @@ nsContextMenu.prototype = {
|
||||
isContentWindowPrivate
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Backwards-compatibility wrapper
|
||||
sendImage() {
|
||||
if (this.onCanvas || this.onImage) {
|
||||
this.sendMedia();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
sendMedia() {
|
||||
MailIntegration.sendMessage(this.mediaURL, "");
|
||||
},
|
||||
}
|
||||
|
||||
playPlugin() {
|
||||
gPluginHandler.contextMenuCommand(this.browser, this.target, "play");
|
||||
},
|
||||
}
|
||||
|
||||
hidePlugin() {
|
||||
gPluginHandler.contextMenuCommand(this.browser, this.target, "hide");
|
||||
},
|
||||
}
|
||||
|
||||
// Generate email address and put it on clipboard.
|
||||
copyEmail() {
|
||||
@ -1775,7 +1758,7 @@ nsContextMenu.prototype = {
|
||||
Ci.nsIClipboardHelper
|
||||
);
|
||||
clipboard.copyString(addresses);
|
||||
},
|
||||
}
|
||||
|
||||
copyLink() {
|
||||
// If we're in a view source tab, remove the view-source: prefix
|
||||
@ -1784,7 +1767,7 @@ nsContextMenu.prototype = {
|
||||
Ci.nsIClipboardHelper
|
||||
);
|
||||
clipboard.copyString(linkURL);
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
@ -1806,7 +1789,7 @@ nsContextMenu.prototype = {
|
||||
if (item) {
|
||||
item.hidden = !aShow;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Set given attribute of specified context-menu item. If the
|
||||
// value is null, then it removes the attribute (which works
|
||||
@ -1822,7 +1805,7 @@ nsContextMenu.prototype = {
|
||||
elem.setAttribute(aAttr, aVal);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Temporary workaround for DOM api not yet implemented by XUL nodes.
|
||||
cloneNode(aItem) {
|
||||
@ -1838,7 +1821,7 @@ nsContextMenu.prototype = {
|
||||
|
||||
// Voila!
|
||||
return node;
|
||||
},
|
||||
}
|
||||
|
||||
getLinkURI() {
|
||||
try {
|
||||
@ -1848,12 +1831,12 @@ nsContextMenu.prototype = {
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
}
|
||||
|
||||
// Kept for addon compat
|
||||
linkText() {
|
||||
return this.linkTextStr;
|
||||
},
|
||||
}
|
||||
|
||||
// Determines whether or not the separator with the specified ID should be
|
||||
// shown or not by determining if there are any non-hidden items between it
|
||||
@ -1870,7 +1853,7 @@ nsContextMenu.prototype = {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
addDictionaries() {
|
||||
var uri = formatURL("browser.dictionaries.download.url", true);
|
||||
@ -1896,21 +1879,21 @@ nsContextMenu.prototype = {
|
||||
var where = newWindowPref == 3 ? "tab" : "window";
|
||||
|
||||
openTrustedLinkIn(uri, where);
|
||||
},
|
||||
}
|
||||
|
||||
bookmarkThisPage: function CM_bookmarkThisPage() {
|
||||
bookmarkThisPage() {
|
||||
window.top.PlacesCommandHook.bookmarkPage().catch(Cu.reportError);
|
||||
},
|
||||
}
|
||||
|
||||
bookmarkLink: function CM_bookmarkLink() {
|
||||
bookmarkLink() {
|
||||
window.top.PlacesCommandHook.bookmarkLink(
|
||||
this.linkURL,
|
||||
this.linkTextStr
|
||||
).catch(Cu.reportError);
|
||||
},
|
||||
}
|
||||
|
||||
addBookmarkForFrame: function CM_addBookmarkForFrame() {
|
||||
let uri = gContextMenuContentData.documentURIObject;
|
||||
addBookmarkForFrame() {
|
||||
let uri = this.contentData.documentURIObject;
|
||||
let mm = this.browser.messageManager;
|
||||
|
||||
let onMessage = message => {
|
||||
@ -1926,21 +1909,21 @@ nsContextMenu.prototype = {
|
||||
mm.sendAsyncMessage("ContextMenu:BookmarkFrame", null, {
|
||||
target: this.target,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
savePageAs: function CM_savePageAs() {
|
||||
savePageAs() {
|
||||
saveBrowser(this.browser);
|
||||
},
|
||||
}
|
||||
|
||||
printFrame: function CM_printFrame() {
|
||||
printFrame() {
|
||||
PrintUtils.printWindow(this.frameOuterWindowID, this.browser);
|
||||
},
|
||||
}
|
||||
|
||||
switchPageDirection: function CM_switchPageDirection() {
|
||||
switchPageDirection() {
|
||||
this.browser.messageManager.sendAsyncMessage("SwitchDocumentDirection");
|
||||
},
|
||||
}
|
||||
|
||||
mediaCommand: function CM_mediaCommand(command, data) {
|
||||
mediaCommand(command, data) {
|
||||
let mm = this.browser.messageManager;
|
||||
let win = this.browser.ownerGlobal;
|
||||
let windowUtils = win.windowUtils;
|
||||
@ -1949,14 +1932,14 @@ nsContextMenu.prototype = {
|
||||
{ command, data, handlingUserInput: windowUtils.isHandlingUserInput },
|
||||
{ element: this.target }
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
copyMediaLocation() {
|
||||
var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
|
||||
Ci.nsIClipboardHelper
|
||||
);
|
||||
clipboard.copyString(this.mediaURL);
|
||||
},
|
||||
}
|
||||
|
||||
drmLearnMore(aEvent) {
|
||||
let drmInfoURL =
|
||||
@ -1969,14 +1952,14 @@ nsContextMenu.prototype = {
|
||||
dest = "tab";
|
||||
}
|
||||
openTrustedLinkIn(drmInfoURL, dest);
|
||||
},
|
||||
}
|
||||
|
||||
get imageURL() {
|
||||
if (this.onImage) {
|
||||
return this.mediaURL;
|
||||
}
|
||||
return "";
|
||||
},
|
||||
}
|
||||
|
||||
// Formats the 'Search <engine> for "<selection or link text>"' context menu.
|
||||
formatSearchContextItem() {
|
||||
@ -2012,13 +1995,18 @@ nsContextMenu.prototype = {
|
||||
menuItem.accessKey = gNavigatorBundle.getString(
|
||||
"contextMenuSearch.accesskey"
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
createContainerMenu(aEvent) {
|
||||
let createMenuOptions = {
|
||||
isContextMenu: true,
|
||||
excludeUserContextId: gContextMenuContentData.userContextId,
|
||||
excludeUserContextId: this.contentData.userContextId,
|
||||
};
|
||||
return createUserContextMenu(aEvent, createMenuOptions);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(nsContextMenu, {
|
||||
LoginManagerContextMenu: "resource://gre/modules/LoginManagerContextMenu.jsm",
|
||||
DevToolsShim: "chrome://devtools-startup/content/DevToolsShim.jsm",
|
||||
});
|
||||
|
@ -29,7 +29,7 @@
|
||||
<html:link rel="localization" href="browser/pageInfo.ftl"/>
|
||||
</linkset>
|
||||
#ifdef XP_MACOSX
|
||||
#include ../macWindow.inc.xul
|
||||
#include ../macWindow.inc.xhtml
|
||||
#else
|
||||
<script src="chrome://global/content/globalOverlay.js"/>
|
||||
<script src="chrome://global/content/editMenuOverlay.js"/>
|
||||
@ -266,7 +266,7 @@
|
||||
id="selectallbutton"
|
||||
oncommand="doSelectAllMedia();"/>
|
||||
<button data-l10n-id="media-save-as"
|
||||
icon="save" id="imagesaveasbutton"
|
||||
id="imagesaveasbutton"
|
||||
oncommand="saveMedia();"/>
|
||||
</hbox>
|
||||
<vbox id="imagecontainerbox" flex="1" pack="center">
|
||||
@ -281,7 +281,7 @@
|
||||
<hbox id="mediaSaveBox" collapsed="true">
|
||||
<spacer id="mediaSaveBoxSpacer" flex="1"/>
|
||||
<button data-l10n-id="media-save-image-as"
|
||||
icon="save" id="mediasaveasbutton"
|
||||
id="mediasaveasbutton"
|
||||
oncommand="saveMedia();"/>
|
||||
</hbox>
|
||||
<hbox pack="end">
|
||||
@ -341,6 +341,7 @@
|
||||
<input id="security-identity-verifier-value" readonly="readonly"
|
||||
data-l10n-attrs="value"/>
|
||||
<xul:button id="security-view-cert" data-l10n-id="security-view"
|
||||
collapsed="true"
|
||||
oncommand="security.viewCert();"/>
|
||||
</div>
|
||||
</td>
|
@ -23,26 +23,29 @@ ChromeUtils.defineModuleGetter(
|
||||
);
|
||||
|
||||
var security = {
|
||||
init(uri, windowInfo) {
|
||||
async init(uri, windowInfo) {
|
||||
this.uri = uri;
|
||||
this.windowInfo = windowInfo;
|
||||
this.securityInfo = await this._getSecurityInfo();
|
||||
},
|
||||
|
||||
// Display the server certificate (static)
|
||||
viewCert() {
|
||||
var cert = security._cert;
|
||||
viewCertHelper(window, cert);
|
||||
Services.ww.openWindow(
|
||||
window,
|
||||
"chrome://pippki/content/certViewer.xhtml",
|
||||
"_blank",
|
||||
"centerscreen,chrome",
|
||||
this.securityInfo.cert
|
||||
);
|
||||
},
|
||||
|
||||
_getSecurityInfo() {
|
||||
async _getSecurityInfo() {
|
||||
// We don't have separate info for a frame, return null until further notice
|
||||
// (see bug 138479)
|
||||
if (!this.windowInfo.isTopWindow) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var hostName = this.windowInfo.hostName;
|
||||
|
||||
var ui = security._getSecurityUI();
|
||||
if (!ui) {
|
||||
return null;
|
||||
@ -53,16 +56,18 @@ var security = {
|
||||
ui.state &
|
||||
(Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
|
||||
Ci.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT);
|
||||
var isInsecure = ui.state & Ci.nsIWebProgressListener.STATE_IS_INSECURE;
|
||||
var isEV = ui.state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL;
|
||||
var secInfo = ui.secInfo;
|
||||
|
||||
if (!isInsecure && secInfo) {
|
||||
var cert = secInfo.serverCert;
|
||||
var issuerName = cert.issuerOrganization || cert.issuerName;
|
||||
let secInfo = await window.opener.gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.getSecurityInfo();
|
||||
if (secInfo) {
|
||||
secInfo.QueryInterface(Ci.nsITransportSecurityInfo);
|
||||
let cert = secInfo.serverCert;
|
||||
let issuerName = null;
|
||||
if (cert) {
|
||||
issuerName = cert.issuerOrganization || cert.issuerName;
|
||||
}
|
||||
|
||||
var retval = {
|
||||
hostName,
|
||||
cAName: issuerName,
|
||||
encryptionAlgorithm: undefined,
|
||||
encryptionStrength: undefined,
|
||||
@ -71,6 +76,7 @@ var security = {
|
||||
isMixed,
|
||||
isEV,
|
||||
cert,
|
||||
certChain: secInfo.succeededCertChain || secInfo.failedCertChain,
|
||||
certificateTransparency: undefined,
|
||||
};
|
||||
|
||||
@ -121,7 +127,6 @@ var security = {
|
||||
return retval;
|
||||
}
|
||||
return {
|
||||
hostName,
|
||||
cAName: "",
|
||||
encryptionAlgorithm: "",
|
||||
encryptionStrength: 0,
|
||||
@ -205,18 +210,16 @@ var security = {
|
||||
*/
|
||||
viewPasswords() {
|
||||
LoginHelper.openPasswordManager(window, {
|
||||
filterString: this._getSecurityInfo().hostName,
|
||||
filterString: this.windowInfo.hostName,
|
||||
entryPoint: "pageinfo",
|
||||
});
|
||||
},
|
||||
|
||||
_cert: null,
|
||||
};
|
||||
|
||||
function securityOnLoad(uri, windowInfo) {
|
||||
security.init(uri, windowInfo);
|
||||
async function securityOnLoad(uri, windowInfo) {
|
||||
await security.init(uri, windowInfo);
|
||||
|
||||
var info = security._getSecurityInfo();
|
||||
let info = security.securityInfo;
|
||||
if (
|
||||
!info ||
|
||||
(uri.scheme === "about" && !uri.spec.startsWith("about:certerror"))
|
||||
@ -227,7 +230,7 @@ function securityOnLoad(uri, windowInfo) {
|
||||
document.getElementById("securityTab").hidden = false;
|
||||
|
||||
/* Set Identity section text */
|
||||
setText("security-identity-domain-value", info.hostName);
|
||||
setText("security-identity-domain-value", windowInfo.hostName);
|
||||
|
||||
var validity;
|
||||
if (info.cert && !info.isBroken) {
|
||||
@ -275,7 +278,6 @@ function securityOnLoad(uri, windowInfo) {
|
||||
/* Manage the View Cert button*/
|
||||
var viewCert = document.getElementById("security-view-cert");
|
||||
if (info.cert) {
|
||||
security._cert = info.cert;
|
||||
viewCert.collapsed = false;
|
||||
} else {
|
||||
viewCert.collapsed = true;
|
||||
@ -305,7 +307,7 @@ function securityOnLoad(uri, windowInfo) {
|
||||
document.l10n.setAttributes(
|
||||
document.getElementById("security-privacy-history-value"),
|
||||
"security-visits-number",
|
||||
{ visits: previousVisitCount(info.hostName) }
|
||||
{ visits: previousVisitCount(windowInfo.hostName) }
|
||||
);
|
||||
|
||||
/* Set the Technical Detail section messages */
|
||||
@ -334,12 +336,11 @@ function securityOnLoad(uri, windowInfo) {
|
||||
);
|
||||
msg1 = pkiBundle.getString("pageInfo_Privacy_Encrypted1");
|
||||
msg2 = pkiBundle.getString("pageInfo_Privacy_Encrypted2");
|
||||
security._cert = info.cert;
|
||||
} else {
|
||||
hdr = pkiBundle.getString("pageInfo_NoEncryption");
|
||||
if (info.hostName != null) {
|
||||
if (windowInfo.hostName != null) {
|
||||
msg1 = pkiBundle.getFormattedString("pageInfo_Privacy_None1", [
|
||||
info.hostName,
|
||||
windowInfo.hostName,
|
||||
]);
|
||||
} else {
|
||||
msg1 = pkiBundle.getString("pageInfo_Privacy_None4");
|
||||
@ -375,20 +376,6 @@ function setText(id, value) {
|
||||
}
|
||||
}
|
||||
|
||||
function viewCertHelper(parent, cert) {
|
||||
if (!cert) {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.ww.openWindow(
|
||||
parent,
|
||||
"chrome://pippki/content/certViewer.xul",
|
||||
"_blank",
|
||||
"centerscreen,chrome",
|
||||
cert
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true iff realm (proto://host:port) (extracted from uri) has
|
||||
* saved passwords
|
||||
|
@ -54,8 +54,8 @@
|
||||
|
||||
<popupnotification id="password-notification" hidden="true">
|
||||
<popupnotificationcontent orient="vertical">
|
||||
<textbox id="password-notification-username"/>
|
||||
<textbox id="password-notification-password" type="password" show-content=""/>
|
||||
<html:input id="password-notification-username"/>
|
||||
<html:input id="password-notification-password" type="password"/>
|
||||
<checkbox id="password-notification-visibilityToggle" hidden="true"/>
|
||||
</popupnotificationcontent>
|
||||
</popupnotification>
|
||||
|
@ -30,7 +30,7 @@ function showResetDialog() {
|
||||
reset: false,
|
||||
};
|
||||
window.openDialog(
|
||||
"chrome://global/content/resetProfile.xul",
|
||||
"chrome://global/content/resetProfile.xhtml",
|
||||
null,
|
||||
"chrome,modal,centerscreen,titlebar,dialog=yes",
|
||||
retVals
|
||||
@ -68,6 +68,7 @@ function onExtra1() {
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
const dialog = document.getElementById("safeModeDialog");
|
||||
if (appStartup.automaticSafeModeNecessary) {
|
||||
document.getElementById("autoSafeMode").hidden = false;
|
||||
document.getElementById("safeMode").hidden = true;
|
||||
@ -75,11 +76,11 @@ function onLoad() {
|
||||
document.getElementById("resetProfile").hidden = false;
|
||||
} else {
|
||||
// Hide the reset button is it's not supported.
|
||||
document.documentElement.getButton("extra1").hidden = true;
|
||||
dialog.getButton("extra1").hidden = true;
|
||||
}
|
||||
} else if (!ResetProfile.resetSupported()) {
|
||||
// Hide the reset button and text if it's not supported.
|
||||
document.documentElement.getButton("extra1").hidden = true;
|
||||
dialog.getButton("extra1").hidden = true;
|
||||
document.getElementById("resetProfileInstead").hidden = true;
|
||||
}
|
||||
document.addEventListener("dialogaccept", onDefaultButton);
|
||||
|
@ -7,15 +7,15 @@
|
||||
<?xml-stylesheet href="chrome://global/skin/"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/safeMode.css"?>
|
||||
|
||||
<dialog id="safeModeDialog"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
<window xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
data-l10n-id="safe-mode-window"
|
||||
data-l10n-attrs="title,style"
|
||||
onload="onLoad()">
|
||||
<dialog id="safeModeDialog"
|
||||
buttons="accept,extra1"
|
||||
buttonidaccept="start-safe-mode"
|
||||
buttonidextra1="refresh-profile"
|
||||
onload="onLoad()">
|
||||
buttonidextra1="refresh-profile">
|
||||
|
||||
<linkset>
|
||||
<html:link rel="localization" href="branding/brand.ftl"/>
|
||||
@ -43,3 +43,4 @@
|
||||
|
||||
<separator class="thin"/>
|
||||
</dialog>
|
||||
</window>
|
@ -11,17 +11,17 @@
|
||||
|
||||
<?xml-stylesheet href="chrome://browser/content/sanitizeDialog.css"?>
|
||||
|
||||
<!DOCTYPE dialog>
|
||||
<!DOCTYPE window>
|
||||
|
||||
<dialog id="SanitizeDialog" type="child"
|
||||
<window id="SanitizeDialog"
|
||||
type="child"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
buttons="accept,cancel"
|
||||
persist="lastSelected screenX screenY"
|
||||
role="dialog"
|
||||
data-l10n-id="dialog-title"
|
||||
data-l10n-attrs="style"
|
||||
onload="gSanitizePromptDialog.init();">
|
||||
<dialog buttons="accept,cancel">
|
||||
|
||||
<linkset>
|
||||
<html:link rel="localization" href="browser/sanitize.ftl"/>
|
||||
@ -100,3 +100,4 @@
|
||||
</hbox>
|
||||
</groupbox>
|
||||
</dialog>
|
||||
</window>
|
@ -32,8 +32,9 @@ var gSanitizePromptDialog = {
|
||||
init() {
|
||||
// This is used by selectByTimespan() to determine if the window has loaded.
|
||||
this._inited = true;
|
||||
this._dialog = document.querySelector("dialog");
|
||||
|
||||
let OKButton = document.documentElement.getButton("accept");
|
||||
let OKButton = this._dialog.getButton("accept");
|
||||
document.l10n.setAttributes(OKButton, "sanitize-button-ok");
|
||||
|
||||
document.addEventListener("dialogaccept", function(e) {
|
||||
@ -65,7 +66,7 @@ var gSanitizePromptDialog = {
|
||||
}
|
||||
|
||||
// Only apply the following if the dialog is opened outside of the Preferences.
|
||||
if (!("gSubDialog" in window.opener)) {
|
||||
if (!window.opener || !("gSubDialog" in window.opener)) {
|
||||
// The style attribute on the dialog may get set after the dialog has been sized.
|
||||
// Force the dialog to size again after the style attribute has been applied.
|
||||
document.l10n.translateElements([document.documentElement]).then(() => {
|
||||
@ -113,11 +114,10 @@ var gSanitizePromptDialog = {
|
||||
// the 'accept' button to indicate things are happening and return false -
|
||||
// once the async operation completes (either with or without errors)
|
||||
// we close the window.
|
||||
let docElt = document.documentElement;
|
||||
let acceptButton = docElt.getButton("accept");
|
||||
let acceptButton = this._dialog.getButton("accept");
|
||||
acceptButton.disabled = true;
|
||||
document.l10n.setAttributes(acceptButton, "sanitize-button-clearing");
|
||||
docElt.getButton("cancel").disabled = true;
|
||||
this._dialog.getButton("cancel").disabled = true;
|
||||
|
||||
try {
|
||||
let range = Sanitizer.getClearRange(this.selectedTimespan);
|
||||
@ -174,7 +174,7 @@ var gSanitizePromptDialog = {
|
||||
);
|
||||
|
||||
try {
|
||||
document.documentElement.getButton("accept").disabled = !found;
|
||||
this._dialog.getButton("accept").disabled = !found;
|
||||
} catch (e) {}
|
||||
|
||||
// Update the warning prompt if needed
|
||||
|
649
browser/base/content/tabbrowser-tab.js
Normal file
649
browser/base/content/tabbrowser-tab.js
Normal 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",
|
||||
});
|
||||
}
|
2029
browser/base/content/tabbrowser-tabs.js
Normal file
2029
browser/base/content/tabbrowser-tabs.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.tab-close-button[pinned],
|
||||
#tabbrowser-tabs[closebuttons="activetab"] > .tabbrowser-tab > .tab-stack > .tab-content > .tab-close-button:not([selected="true"]),
|
||||
#tabbrowser-tabs[closebuttons="activetab"] > .tabbrowser-arrowscrollbox > .tabbrowser-tab > .tab-stack > .tab-content > .tab-close-button:not([selected="true"]),
|
||||
.tab-icon-pending:not([pendingicon]),
|
||||
.tab-icon-pending[busy],
|
||||
.tab-icon-pending[pinned],
|
||||
@ -54,15 +54,6 @@ tabpanels {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.tab-drop-indicator-box {
|
||||
-moz-box-align: end;
|
||||
}
|
||||
|
||||
.tab-drop-indicator {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Apply crisp rendering for favicons at exactly 2dppx resolution */
|
||||
@media (resolution: 2dppx) {
|
||||
.tab-icon-image {
|
||||
|
@ -39,6 +39,7 @@
|
||||
window.addEventListener("occlusionstatechange", this);
|
||||
window.addEventListener("framefocusrequested", this);
|
||||
|
||||
this.tabContainer.init();
|
||||
this._setupInitialBrowserAndTab();
|
||||
|
||||
if (Services.prefs.getBoolPref("browser.display.use_system_colors")) {
|
||||
@ -83,6 +84,7 @@
|
||||
);
|
||||
|
||||
this._setupEventListeners();
|
||||
this._initialized = true;
|
||||
},
|
||||
|
||||
ownerGlobal: window,
|
||||
@ -93,6 +95,8 @@
|
||||
|
||||
_visibleTabs: null,
|
||||
|
||||
_tabs: null,
|
||||
|
||||
_lastRelatedTabMap: new WeakMap(),
|
||||
|
||||
mProgressListeners: [],
|
||||
@ -253,8 +257,10 @@
|
||||
},
|
||||
|
||||
get tabs() {
|
||||
delete this.tabs;
|
||||
return (this.tabs = this.tabContainer.children);
|
||||
if (!this._tabs) {
|
||||
this._tabs = this.tabContainer.allTabs;
|
||||
}
|
||||
return this._tabs;
|
||||
},
|
||||
|
||||
get tabbox() {
|
||||
@ -267,25 +273,16 @@
|
||||
return (this.tabpanels = document.getElementById("tabbrowser-tabpanels"));
|
||||
},
|
||||
|
||||
get addEventListener() {
|
||||
delete this.addEventListener;
|
||||
return (this.addEventListener = this.tabpanels.addEventListener.bind(
|
||||
this.tabpanels
|
||||
));
|
||||
addEventListener(...args) {
|
||||
this.tabpanels.addEventListener(...args);
|
||||
},
|
||||
|
||||
get removeEventListener() {
|
||||
delete this.removeEventListener;
|
||||
return (this.removeEventListener = this.tabpanels.removeEventListener.bind(
|
||||
this.tabpanels
|
||||
));
|
||||
removeEventListener(...args) {
|
||||
this.tabpanels.removeEventListener(...args);
|
||||
},
|
||||
|
||||
get dispatchEvent() {
|
||||
delete this.dispatchEvent;
|
||||
return (this.dispatchEvent = this.tabpanels.dispatchEvent.bind(
|
||||
this.tabpanels
|
||||
));
|
||||
dispatchEvent(...args) {
|
||||
return this.tabpanels.dispatchEvent(...args);
|
||||
},
|
||||
|
||||
get visibleTabs() {
|
||||
@ -307,19 +304,6 @@
|
||||
return i;
|
||||
},
|
||||
|
||||
get popupAnchor() {
|
||||
if (this.selectedTab._popupAnchor) {
|
||||
return this.selectedTab._popupAnchor;
|
||||
}
|
||||
let stack = this.selectedBrowser.parentNode;
|
||||
// Create an anchor for the popup
|
||||
let popupAnchor = document.createXULElement("hbox");
|
||||
popupAnchor.className = "popup-anchor";
|
||||
popupAnchor.hidden = true;
|
||||
stack.appendChild(popupAnchor);
|
||||
return (this.selectedTab._popupAnchor = popupAnchor);
|
||||
},
|
||||
|
||||
set selectedTab(val) {
|
||||
if (gNavToolbox.collapsed && !this._allowTabChange) {
|
||||
return this.tabbox.selectedTab;
|
||||
@ -572,6 +556,11 @@
|
||||
return this.selectedBrowser.userTypedValue;
|
||||
},
|
||||
|
||||
_invalidateCachedTabs() {
|
||||
this._tabs = null;
|
||||
this._visibleTabs = null;
|
||||
},
|
||||
|
||||
_setFindbarData() {
|
||||
// Ensure we know what the find bar key is in the content process:
|
||||
let { sharedData } = Services.ppmm;
|
||||
@ -723,19 +712,15 @@
|
||||
|
||||
syncThrobberAnimations(aTab) {
|
||||
aTab.ownerGlobal.promiseDocumentFlushed(() => {
|
||||
if (!aTab.parentNode) {
|
||||
if (!aTab.container) {
|
||||
return;
|
||||
}
|
||||
|
||||
const animations = Array.from(
|
||||
aTab.parentNode.getElementsByTagName("tab")
|
||||
aTab.container.getElementsByTagName("tab")
|
||||
)
|
||||
.map(tab => {
|
||||
const throbber = document.getAnonymousElementByAttribute(
|
||||
tab,
|
||||
"anonid",
|
||||
"tab-throbber"
|
||||
);
|
||||
const throbber = tab.throbber;
|
||||
return throbber ? throbber.getAnimations({ subtree: true }) : [];
|
||||
})
|
||||
.reduce((a, b) => a.concat(b))
|
||||
@ -989,7 +974,7 @@
|
||||
|
||||
var modifier = docElement.getAttribute("titlemodifier");
|
||||
if (docTitle) {
|
||||
newTitle += docElement.getAttribute("titlepreface");
|
||||
newTitle += docElement.getAttribute("titlepreface") || "";
|
||||
newTitle += docTitle;
|
||||
if (modifier) {
|
||||
newTitle += sep;
|
||||
@ -1002,14 +987,25 @@
|
||||
// XXX https://bugzilla.mozilla.org/show_bug.cgi?id=22183#c239
|
||||
try {
|
||||
if (docElement.getAttribute("chromehidden").includes("location")) {
|
||||
var uri = Services.io.createExposableURI(aBrowser.currentURI);
|
||||
if (uri.scheme == "about") {
|
||||
newTitle = uri.spec + sep + newTitle;
|
||||
const uri = Services.io.createExposableURI(aBrowser.currentURI);
|
||||
if (uri.scheme === "about") {
|
||||
newTitle = `${uri.spec}${sep}${newTitle}`;
|
||||
} else if (uri.scheme === "moz-extension") {
|
||||
const ext = WebExtensionPolicy.getByHostname(uri.host);
|
||||
if (ext && ext.name) {
|
||||
const prefix = document.querySelector("#urlbar-label-extension")
|
||||
.value;
|
||||
newTitle = `${prefix} (${ext.name})${sep}${newTitle}`;
|
||||
} else {
|
||||
newTitle = `${uri.prePath}${sep}${newTitle}`;
|
||||
}
|
||||
} else {
|
||||
newTitle = uri.prePath + sep + newTitle;
|
||||
newTitle = `${uri.prePath}${sep}${newTitle}`;
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch (e) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
return newTitle;
|
||||
},
|
||||
@ -1245,6 +1241,7 @@
|
||||
if (!gMultiProcessBrowser) {
|
||||
this._adjustFocusBeforeTabSwitch(oldTab, newTab);
|
||||
this._adjustFocusAfterTabSwitch(newTab);
|
||||
gURLBar.afterTabSwitchFocusChange();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1338,9 +1335,6 @@
|
||||
// In full screen mode, only bother making the location bar visible
|
||||
// if the tab is a blank one.
|
||||
if (newBrowser._urlbarFocused && gURLBar) {
|
||||
// Explicitly close the popup if the URL bar retains focus
|
||||
gURLBar.view.close();
|
||||
|
||||
// If the user happened to type into the URL bar for this browser
|
||||
// by the time we got here, focusing will cause the text to be
|
||||
// selected which could cause them to overwrite what they've
|
||||
@ -1367,10 +1361,7 @@
|
||||
|
||||
// Don't focus the content area if something has been focused after the
|
||||
// tab switch was initiated.
|
||||
if (
|
||||
gMultiProcessBrowser &&
|
||||
document.activeElement != document.documentElement
|
||||
) {
|
||||
if (gMultiProcessBrowser && document.activeElement != document.body) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2574,8 +2565,7 @@
|
||||
(openerBrowser && this.getTabForBrowser(openerBrowser)) ||
|
||||
(relatedToCurrent && this.selectedTab);
|
||||
|
||||
var t = document.createXULElement("tab");
|
||||
|
||||
var t = document.createXULElement("tab", { is: "tabbrowser-tab" });
|
||||
t.openerTab = openerTab;
|
||||
|
||||
aURI = aURI || "about:blank";
|
||||
@ -2648,9 +2638,6 @@
|
||||
);
|
||||
}
|
||||
|
||||
// invalidate cache
|
||||
this._visibleTabs = null;
|
||||
|
||||
let usingPreloadedContent = false;
|
||||
let b;
|
||||
|
||||
@ -2702,9 +2689,11 @@
|
||||
index = Math.min(index, this.tabs.length);
|
||||
}
|
||||
|
||||
// Use .item() instead of [] because we need .item() to return null in
|
||||
// order to append the tab at the end in case index == tabs.length.
|
||||
let tabAfter = this.tabs.item(index);
|
||||
let tabAfter = this.tabs[index] || null;
|
||||
this._invalidateCachedTabs();
|
||||
// Prevent a flash of unstyled content by setting up the tab content
|
||||
// and inherited attributes before appending it (see Bug 1592054):
|
||||
t.initialize();
|
||||
this.tabContainer.insertBefore(t, tabAfter);
|
||||
if (tabAfter) {
|
||||
this._updateTabsAfterInsert();
|
||||
@ -3192,7 +3181,7 @@
|
||||
setTimeout(
|
||||
function(tab, tabbrowser) {
|
||||
if (
|
||||
tab.parentNode &&
|
||||
tab.container &&
|
||||
window.getComputedStyle(tab).maxWidth == "0.1px"
|
||||
) {
|
||||
console.assert(
|
||||
@ -3335,7 +3324,7 @@
|
||||
|
||||
aTab.closing = true;
|
||||
this._removingTabs.push(aTab);
|
||||
this._visibleTabs = null; // invalidate cache
|
||||
this._invalidateCachedTabs();
|
||||
|
||||
// Invalidate hovered tab state tracking for this closing tab.
|
||||
if (this.tabContainer._hoveredTab == aTab) {
|
||||
@ -3474,6 +3463,7 @@
|
||||
|
||||
// Remove the tab ...
|
||||
aTab.remove();
|
||||
this._invalidateCachedTabs();
|
||||
|
||||
// Update hashiddentabs if this tab was hidden.
|
||||
if (aTab.hidden) {
|
||||
@ -3588,17 +3578,16 @@
|
||||
}
|
||||
|
||||
// Try to find a remaining tab that comes after the given tab
|
||||
let tab = aTab;
|
||||
do {
|
||||
tab = tab.nextElementSibling;
|
||||
} while (tab && !remainingTabs.includes(tab));
|
||||
let tab = this.tabContainer.findNextTab(aTab, {
|
||||
direction: 1,
|
||||
filter: _tab => remainingTabs.includes(_tab),
|
||||
});
|
||||
|
||||
if (!tab) {
|
||||
tab = aTab;
|
||||
|
||||
do {
|
||||
tab = tab.previousElementSibling;
|
||||
} while (tab && !remainingTabs.includes(tab));
|
||||
tab = this.tabContainer.findNextTab(aTab, {
|
||||
direction: -1,
|
||||
filter: _tab => remainingTabs.includes(_tab),
|
||||
});
|
||||
}
|
||||
|
||||
return tab;
|
||||
@ -3972,7 +3961,7 @@
|
||||
showTab(aTab) {
|
||||
if (aTab.hidden) {
|
||||
aTab.removeAttribute("hidden");
|
||||
this._visibleTabs = null; // invalidate cache
|
||||
this._invalidateCachedTabs();
|
||||
|
||||
this.tabContainer._updateCloseButtons();
|
||||
this.tabContainer._updateHiddenTabsStatus();
|
||||
@ -3995,7 +3984,7 @@
|
||||
!aTab._sharingState
|
||||
) {
|
||||
aTab.setAttribute("hidden", "true");
|
||||
this._visibleTabs = null; // invalidate cache
|
||||
this._invalidateCachedTabs();
|
||||
|
||||
this.tabContainer._updateCloseButtons();
|
||||
this.tabContainer._updateHiddenTabsStatus();
|
||||
@ -4179,12 +4168,9 @@
|
||||
|
||||
aIndex = aIndex < aTab._tPos ? aIndex : aIndex + 1;
|
||||
|
||||
// invalidate cache
|
||||
this._visibleTabs = null;
|
||||
|
||||
// use .item() instead of [] because dragging to the end of the strip goes out of
|
||||
// bounds: .item() returns null (so it acts like appendChild), but [] throws
|
||||
this.tabContainer.insertBefore(aTab, this.tabs.item(aIndex));
|
||||
let neighbor = this.tabs[aIndex] || null;
|
||||
this._invalidateCachedTabs();
|
||||
this.tabContainer.insertBefore(aTab, neighbor);
|
||||
this._updateTabsAfterInsert();
|
||||
|
||||
if (wasFocused) {
|
||||
@ -4205,10 +4191,10 @@
|
||||
},
|
||||
|
||||
moveTabForward() {
|
||||
let nextTab = this.selectedTab.nextElementSibling;
|
||||
while (nextTab && nextTab.hidden) {
|
||||
nextTab = nextTab.nextElementSibling;
|
||||
}
|
||||
let nextTab = this.tabContainer.findNextTab(this.selectedTab, {
|
||||
direction: 1,
|
||||
filter: tab => !tab.hidden,
|
||||
});
|
||||
|
||||
if (nextTab) {
|
||||
this.moveTabTo(this.selectedTab, nextTab._tPos);
|
||||
@ -4253,7 +4239,7 @@
|
||||
let newTab = this.addWebTab("about:blank", params);
|
||||
let newBrowser = this.getBrowserForTab(newTab);
|
||||
|
||||
aTab.parentNode._finishAnimateTabMove();
|
||||
aTab.container._finishAnimateTabMove();
|
||||
|
||||
if (!createLazyBrowser) {
|
||||
// Stop the about:blank load.
|
||||
@ -4276,10 +4262,10 @@
|
||||
},
|
||||
|
||||
moveTabBackward() {
|
||||
let previousTab = this.selectedTab.previousElementSibling;
|
||||
while (previousTab && previousTab.hidden) {
|
||||
previousTab = previousTab.previousElementSibling;
|
||||
}
|
||||
let previousTab = this.tabContainer.findNextTab(this.selectedTab, {
|
||||
direction: -1,
|
||||
filter: tab => !tab.hidden,
|
||||
});
|
||||
|
||||
if (previousTab) {
|
||||
this.moveTabTo(this.selectedTab, previousTab._tPos);
|
||||
@ -4355,7 +4341,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const tabs = this._visibleTabs;
|
||||
const tabs = this.visibleTabs;
|
||||
const indexOfTab1 = tabs.indexOf(aTab1);
|
||||
const indexOfTab2 = tabs.indexOf(aTab2);
|
||||
|
||||
@ -4704,10 +4690,46 @@
|
||||
}
|
||||
},
|
||||
|
||||
getTabTooltip(tab, includeLabel = true) {
|
||||
let label = "";
|
||||
if (includeLabel) {
|
||||
label = tab._fullLabel || tab.getAttribute("label");
|
||||
}
|
||||
if (AppConstants.NIGHTLY_BUILD) {
|
||||
if (
|
||||
tab.linkedBrowser &&
|
||||
tab.linkedBrowser.isRemoteBrowser &&
|
||||
tab.linkedBrowser.frameLoader
|
||||
) {
|
||||
label +=
|
||||
" (pid " + tab.linkedBrowser.frameLoader.remoteTab.osPid + ")";
|
||||
|
||||
if (
|
||||
window.docShell.QueryInterface(Ci.nsILoadContext)
|
||||
.useRemoteSubframes
|
||||
) {
|
||||
label += " [F]";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tab.userContextId) {
|
||||
label = gTabBrowserBundle.formatStringFromName(
|
||||
"tabs.containers.tooltip",
|
||||
[
|
||||
label,
|
||||
ContextualIdentityService.getUserContextLabel(tab.userContextId),
|
||||
]
|
||||
);
|
||||
}
|
||||
return label;
|
||||
},
|
||||
|
||||
createTooltip(event) {
|
||||
event.stopPropagation();
|
||||
var tab = document.tooltipNode;
|
||||
if (!tab || tab.localName != "tab") {
|
||||
let tab = document.tooltipNode
|
||||
? document.tooltipNode.closest("tab")
|
||||
: null;
|
||||
if (!tab) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
@ -4766,33 +4788,7 @@
|
||||
).replace("#1", affectedTabsLength);
|
||||
}
|
||||
} else {
|
||||
label = tab._fullLabel || tab.getAttribute("label");
|
||||
if (AppConstants.NIGHTLY_BUILD) {
|
||||
if (
|
||||
tab.linkedBrowser &&
|
||||
tab.linkedBrowser.isRemoteBrowser &&
|
||||
tab.linkedBrowser.frameLoader
|
||||
) {
|
||||
label +=
|
||||
" (pid " + tab.linkedBrowser.frameLoader.remoteTab.osPid + ")";
|
||||
|
||||
if (
|
||||
window.docShell.QueryInterface(Ci.nsILoadContext)
|
||||
.useRemoteSubframes
|
||||
) {
|
||||
label += " [F]";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tab.userContextId) {
|
||||
label = gTabBrowserBundle.formatStringFromName(
|
||||
"tabs.containers.tooltip",
|
||||
[
|
||||
label,
|
||||
ContextualIdentityService.getUserContextLabel(tab.userContextId),
|
||||
]
|
||||
);
|
||||
}
|
||||
label = this.getTabTooltip(tab);
|
||||
}
|
||||
|
||||
event.target.setAttribute("label", label);
|
||||
@ -5000,6 +4996,7 @@
|
||||
},
|
||||
|
||||
destroy() {
|
||||
this.tabContainer.destroy();
|
||||
Services.obs.removeObserver(this, "contextual-identity-updated");
|
||||
|
||||
for (let tab of this.tabs) {
|
||||
@ -5188,6 +5185,25 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (!browser.docShell) {
|
||||
return;
|
||||
}
|
||||
// Ensure `docShell.document` (an nsIWebNavigation idl prop) is there:
|
||||
browser.docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
if (event.target != browser.docShell.document) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore empty title changes on internal pages. This prevents the title
|
||||
// from changing while Fluent is populating the (initially-empty) title
|
||||
// element.
|
||||
if (
|
||||
!browser.contentTitle &&
|
||||
browser.contentPrincipal.isSystemPrincipal
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
var titleChanged = this.setTabTitle(tab);
|
||||
if (titleChanged && !tab.selected && !tab.hasAttribute("busy")) {
|
||||
tab.setAttribute("titlechanged", "true");
|
||||
@ -5806,45 +5822,50 @@
|
||||
gBrowser._tabAttrModified(this.mTab, ["busy"]);
|
||||
}
|
||||
|
||||
// If the browser was playing audio, we should remove the playing state.
|
||||
if (this.mTab.hasAttribute("soundplaying") && !isSameDocument) {
|
||||
clearTimeout(this.mTab._soundPlayingAttrRemovalTimer);
|
||||
this.mTab._soundPlayingAttrRemovalTimer = 0;
|
||||
this.mTab.removeAttribute("soundplaying");
|
||||
gBrowser._tabAttrModified(this.mTab, ["soundplaying"]);
|
||||
}
|
||||
|
||||
// If the browser was previously muted, we should restore the muted state.
|
||||
if (this.mTab.hasAttribute("muted")) {
|
||||
this.mTab.linkedBrowser.mute();
|
||||
}
|
||||
|
||||
if (gBrowser.isFindBarInitialized(this.mTab)) {
|
||||
let findBar = gBrowser.getCachedFindBar(this.mTab);
|
||||
|
||||
// Close the Find toolbar if we're in old-style TAF mode
|
||||
if (findBar.findMode != findBar.FIND_NORMAL) {
|
||||
findBar.close();
|
||||
if (!isSameDocument) {
|
||||
// If the browser was playing audio, we should remove the playing state.
|
||||
if (this.mTab.hasAttribute("soundplaying")) {
|
||||
clearTimeout(this.mTab._soundPlayingAttrRemovalTimer);
|
||||
this.mTab._soundPlayingAttrRemovalTimer = 0;
|
||||
this.mTab.removeAttribute("soundplaying");
|
||||
gBrowser._tabAttrModified(this.mTab, ["soundplaying"]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isReload) {
|
||||
gBrowser.setTabTitle(this.mTab);
|
||||
}
|
||||
// If the browser was previously muted, we should restore the muted state.
|
||||
if (this.mTab.hasAttribute("muted")) {
|
||||
this.mTab.linkedBrowser.mute();
|
||||
}
|
||||
|
||||
// Don't clear the favicon if this tab is in the pending
|
||||
// state, as SessionStore will have set the icon for us even
|
||||
// though we're pointed at an about:blank. Also don't clear it
|
||||
// if onLocationChange was triggered by a pushState or a
|
||||
// replaceState (bug 550565) or a hash change (bug 408415).
|
||||
if (
|
||||
!this.mTab.hasAttribute("pending") &&
|
||||
aWebProgress.isLoadingDocument &&
|
||||
!isSameDocument
|
||||
) {
|
||||
// Removing the tab's image here causes flickering, wait until the load
|
||||
// is complete.
|
||||
this.mBrowser.mIconURL = null;
|
||||
if (gBrowser.isFindBarInitialized(this.mTab)) {
|
||||
let findBar = gBrowser.getCachedFindBar(this.mTab);
|
||||
|
||||
// Close the Find toolbar if we're in old-style TAF mode
|
||||
if (findBar.findMode != findBar.FIND_NORMAL) {
|
||||
findBar.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we're not updating for same-document loads, despite
|
||||
// the `title` argument to `history.pushState/replaceState`. For
|
||||
// context, see https://bugzilla.mozilla.org/show_bug.cgi?id=585653
|
||||
// and https://github.com/whatwg/html/issues/2174
|
||||
if (!isReload) {
|
||||
gBrowser.setTabTitle(this.mTab);
|
||||
}
|
||||
|
||||
// Don't clear the favicon if this tab is in the pending
|
||||
// state, as SessionStore will have set the icon for us even
|
||||
// though we're pointed at an about:blank. Also don't clear it
|
||||
// if onLocationChange was triggered by a pushState or a
|
||||
// replaceState (bug 550565) or a hash change (bug 408415).
|
||||
if (
|
||||
!this.mTab.hasAttribute("pending") &&
|
||||
aWebProgress.isLoadingDocument
|
||||
) {
|
||||
// Removing the tab's image here causes flickering, wait until the
|
||||
// load is complete.
|
||||
this.mBrowser.mIconURL = null;
|
||||
}
|
||||
}
|
||||
|
||||
let userContextId = this.mBrowser.getAttribute("usercontextid") || 0;
|
||||
@ -6124,10 +6145,9 @@ var TabContextMenu = {
|
||||
});
|
||||
},
|
||||
updateContextMenu(aPopupMenu) {
|
||||
this.contextTab =
|
||||
aPopupMenu.triggerNode.localName == "tab"
|
||||
? aPopupMenu.triggerNode
|
||||
: gBrowser.selectedTab;
|
||||
let tab = aPopupMenu.triggerNode && aPopupMenu.triggerNode.closest("tab");
|
||||
this.contextTab = tab || gBrowser.selectedTab;
|
||||
|
||||
let disabled = gBrowser.tabs.length == 1;
|
||||
let multiselectionContext = this.contextTab.multiselected;
|
||||
|
||||
@ -6200,10 +6220,12 @@ var TabContextMenu = {
|
||||
let lastVisibleTab = visibleTabs[visibleTabs.length - 1];
|
||||
let tabsToMove = contextTabIsSelected ? selectedTabs : [this.contextTab];
|
||||
let lastTabToMove = tabsToMove[tabsToMove.length - 1];
|
||||
let isLastPinnedTab =
|
||||
lastTabToMove.pinned &&
|
||||
(!lastTabToMove.nextElementSibling ||
|
||||
!lastTabToMove.nextElementSibling.pinned);
|
||||
|
||||
let isLastPinnedTab = false;
|
||||
if (lastTabToMove.pinned) {
|
||||
let sibling = gBrowser.tabContainer.findNextTab(lastTabToMove);
|
||||
isLastPinnedTab = !sibling || !sibling.pinned;
|
||||
}
|
||||
contextMoveTabToEnd.disabled =
|
||||
(lastTabToMove == lastVisibleTab || isLastPinnedTab) &&
|
||||
allSelectedTabsAdjacent;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,7 +26,7 @@ add_task(async function() {
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter("#brandLogo", {}, browser);
|
||||
|
||||
let doc = window.document;
|
||||
let searchInput = BrowserSearch.searchBar.textbox.inputField;
|
||||
let searchInput = BrowserSearch.searchBar.textbox;
|
||||
isnot(
|
||||
searchInput,
|
||||
doc.activeElement,
|
||||
|
@ -1,4 +1,4 @@
|
||||
[DEFAULT]
|
||||
|
||||
[test_aboutCrashed.xul]
|
||||
[test_aboutRestartRequired.xul]
|
||||
[test_aboutCrashed.xhtml]
|
||||
[test_aboutRestartRequired.xhtml]
|
||||
|
@ -4,7 +4,7 @@ support-files =
|
||||
test_contextmenu_links.html
|
||||
subtst_contextmenu.html
|
||||
subtst_contextmenu_input.html
|
||||
subtst_contextmenu_xul.xul
|
||||
subtst_contextmenu_xul.xhtml
|
||||
ctxmenu-image.png
|
||||
../general/head.js
|
||||
../general/video.ogg
|
||||
|
@ -43,7 +43,7 @@ add_task(async function init() {
|
||||
|
||||
// Below are test cases for XUL element
|
||||
add_task(async function test_xul_text_link_label() {
|
||||
let url = chrome_base + "subtst_contextmenu_xul.xul";
|
||||
let url = chrome_base + "subtst_contextmenu_xul.xhtml";
|
||||
|
||||
await BrowserTestUtils.openNewForegroundTab({
|
||||
gBrowser,
|
||||
|
@ -85,11 +85,7 @@ add_task(async function test_toolbar_contextmenu_touch() {
|
||||
// Test the urlbar input context menu.
|
||||
add_task(async function test_urlbar_contextmenu_touch() {
|
||||
let urlbar = document.getElementById("urlbar");
|
||||
let textBox = document.getAnonymousElementByAttribute(
|
||||
urlbar,
|
||||
"anonid",
|
||||
"moz-input-box"
|
||||
);
|
||||
let textBox = urlbar.querySelector("moz-input-box");
|
||||
let menu = textBox.menupopup;
|
||||
await openAndCheckContextMenu(menu, textBox);
|
||||
});
|
||||
|
@ -3,7 +3,7 @@
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
<label id="test-xul-text-link-label" is="text-link" value="XUL text-link label" href="https://www.mozilla.com"/>
|
||||
</page>
|
||||
</window>
|
@ -44,11 +44,7 @@ add_task(async () => {
|
||||
|
||||
await waitForAttributeChange(tab, "label");
|
||||
ok(tab.hasAttribute("busy"), "Should have seen the busy attribute");
|
||||
let label = document.getAnonymousElementByAttribute(
|
||||
tab,
|
||||
"anonid",
|
||||
"tab-label"
|
||||
);
|
||||
let label = tab.textLabel;
|
||||
let bounds = label.getBoundingClientRect();
|
||||
|
||||
await waitForAttributeChange(tab, "busy");
|
||||
@ -84,11 +80,7 @@ add_task(async () => {
|
||||
is(icon.iconURL, "http://example.com/favicon.ico");
|
||||
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
let label = document.getAnonymousElementByAttribute(
|
||||
tab,
|
||||
"anonid",
|
||||
"tab-label"
|
||||
);
|
||||
let label = tab.textLabel;
|
||||
let bounds = label.getBoundingClientRect();
|
||||
|
||||
await ContentTask.spawn(browser, null, () => {
|
||||
|
@ -853,7 +853,7 @@ add_task(async function test_large_popup() {
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
// This test checks the same as the previous test but in a new smaller window.
|
||||
// This test checks the same as the previous test but in a new, vertically smaller window.
|
||||
add_task(async function test_large_popup_in_small_window() {
|
||||
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
@ -862,10 +862,11 @@ add_task(async function test_large_popup_in_small_window() {
|
||||
"resize",
|
||||
false,
|
||||
e => {
|
||||
return newWin.innerHeight <= 400 && newWin.innerWidth <= 400;
|
||||
info(`Got resize event (innerHeight: ${newWin.innerHeight})`);
|
||||
return newWin.innerHeight <= 400;
|
||||
}
|
||||
);
|
||||
newWin.resizeTo(400, 400);
|
||||
newWin.resizeTo(600, 400);
|
||||
await resizePromise;
|
||||
|
||||
const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
|
||||
|
4
browser/base/content/test/fullscreen/browser.ini
Normal file
4
browser/base/content/test/fullscreen/browser.ini
Normal file
@ -0,0 +1,4 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
head.js
|
||||
[browser_bug1557041.js]
|
48
browser/base/content/test/fullscreen/browser_bug1557041.js
Normal file
48
browser/base/content/test/fullscreen/browser_bug1557041.js
Normal 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");
|
||||
});
|
||||
});
|
@ -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");
|
||||
});
|
||||
});
|
31
browser/base/content/test/fullscreen/head.js
Normal file
31
browser/base/content/test/fullscreen/head.js
Normal 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;
|
||||
}
|
@ -14,7 +14,7 @@ support-files =
|
||||
browser_bug479408_sample.html
|
||||
browser_bug970746.xhtml
|
||||
browser_star_hsts.sjs
|
||||
browser_tab_dragdrop2_frame1.xul
|
||||
browser_tab_dragdrop2_frame1.xhtml
|
||||
browser_tab_dragdrop_embed.html
|
||||
browser_web_channel.html
|
||||
browser_web_channel_iframe.html
|
||||
|
@ -27,7 +27,7 @@ add_task(async function() {
|
||||
let contextMenuPromise = BrowserTestUtils.waitForEvent(
|
||||
contextMenu,
|
||||
"popupshown"
|
||||
).then(() => gContextMenuContentData.target);
|
||||
);
|
||||
|
||||
await ContentTask.spawn(
|
||||
tab.linkedBrowser,
|
||||
|
@ -37,9 +37,7 @@ add_task(async function closeLastTabInWindow() {
|
||||
let windowClosedPromise = BrowserTestUtils.domWindowClosed(newWin);
|
||||
expectingDialog = true;
|
||||
// close tab:
|
||||
document
|
||||
.getAnonymousElementByAttribute(firstTab, "anonid", "close-button")
|
||||
.click();
|
||||
firstTab.closeButton.click();
|
||||
await windowClosedPromise;
|
||||
ok(!expectingDialog, "There should have been a dialog.");
|
||||
ok(newWin.closed, "Window should be closed.");
|
||||
@ -73,17 +71,13 @@ add_task(async function closeWindoWithSingleTabTwice() {
|
||||
let firstDialogShownPromise = new Promise((resolve, reject) => {
|
||||
resolveDialogPromise = resolve;
|
||||
});
|
||||
document
|
||||
.getAnonymousElementByAttribute(firstTab, "anonid", "close-button")
|
||||
.click();
|
||||
firstTab.closeButton.click();
|
||||
await firstDialogShownPromise;
|
||||
info("Got initial dialog, now trying again");
|
||||
expectingDialog = true;
|
||||
wantToClose = true;
|
||||
resolveDialogPromise = null;
|
||||
document
|
||||
.getAnonymousElementByAttribute(firstTab, "anonid", "close-button")
|
||||
.click();
|
||||
firstTab.closeButton.click();
|
||||
await windowClosedPromise;
|
||||
ok(!expectingDialog, "There should have been a dialog.");
|
||||
ok(newWin.closed, "Window should be closed.");
|
||||
|
@ -34,14 +34,8 @@ add_task(async function test_content_and_chrome_selection() {
|
||||
"Write something here",
|
||||
"The macOS services got the selected content text"
|
||||
);
|
||||
|
||||
gURLBar.value = "test.mozilla.org";
|
||||
await gURLBar.focus();
|
||||
await BrowserTestUtils.synthesizeKey(
|
||||
"KEY_ArrowRight",
|
||||
{ shiftKey: true, ctrlKey: true },
|
||||
gBrowser.selectedBrowser
|
||||
);
|
||||
await gURLBar.editor.selectAll();
|
||||
selectedText = DOMWindowUtils.GetSelectionAsPlaintext();
|
||||
is(
|
||||
selectedText,
|
||||
|
@ -6,7 +6,7 @@ add_task(async function() {
|
||||
);
|
||||
await SimpleTest.promiseFocus(win);
|
||||
|
||||
let tab = win.gBrowser.tabContainer.firstElementChild;
|
||||
let tab = win.gBrowser.tabs[0];
|
||||
await promiseTabLoadEvent(
|
||||
tab,
|
||||
getRootDirectory(gTestPath) + "test_bug462673.html"
|
||||
@ -36,7 +36,7 @@ add_task(async function() {
|
||||
);
|
||||
await SimpleTest.promiseFocus(win);
|
||||
|
||||
let tab = win.gBrowser.tabContainer.firstElementChild;
|
||||
let tab = win.gBrowser.tabs[0];
|
||||
await promiseTabLoadEvent(
|
||||
tab,
|
||||
getRootDirectory(gTestPath) + "test_bug462673.html"
|
||||
@ -47,7 +47,7 @@ add_task(async function() {
|
||||
win.gBrowser.removeTab(tab);
|
||||
ok(!win.closed, "Window stays open");
|
||||
if (!win.closed) {
|
||||
is(win.gBrowser.tabContainer.childElementCount, 1, "Window has one tab");
|
||||
is(win.gBrowser.tabs.length, 1, "Window has one tab");
|
||||
is(win.gBrowser.browsers.length, 1, "Window has one browser");
|
||||
is(win.gBrowser.selectedTab, newTab, "Remaining tab is selected");
|
||||
is(
|
||||
|
@ -55,8 +55,9 @@ add_task(async function test_remove_bookmark_with_tag_via_edit_bookmark() {
|
||||
);
|
||||
|
||||
let removeNotification = PlacesTestUtils.waitForNotification(
|
||||
"onItemRemoved",
|
||||
(id, parentId, index, type, itemUrl) => testURL == unescape(itemUrl.spec)
|
||||
"bookmark-removed",
|
||||
events => events.some(event => unescape(event.url) == testURL),
|
||||
"places"
|
||||
);
|
||||
|
||||
let removeButton = document.getElementById("editBookmarkPanelRemoveButton");
|
||||
|
@ -10,7 +10,7 @@ function waitForNewWindow() {
|
||||
|
||||
is(
|
||||
domwindow.document.location.href,
|
||||
"chrome://mozapps/content/downloads/unknownContentType.xul",
|
||||
"chrome://mozapps/content/downloads/unknownContentType.xhtml",
|
||||
"Download page appeared"
|
||||
);
|
||||
resolve(domwindow);
|
||||
|
@ -2,15 +2,15 @@
|
||||
// event.clipboardData.
|
||||
|
||||
add_task(async function() {
|
||||
var textbox = document.createElement("textbox");
|
||||
document.documentElement.appendChild(textbox);
|
||||
var input = document.createElement("input");
|
||||
document.documentElement.appendChild(input);
|
||||
|
||||
textbox.focus();
|
||||
textbox.value = "Text";
|
||||
textbox.select();
|
||||
input.focus();
|
||||
input.value = "Text";
|
||||
input.select();
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
textbox.addEventListener(
|
||||
input.addEventListener(
|
||||
"copy",
|
||||
function(event) {
|
||||
event.clipboardData.setData("text/plain", "Alternate");
|
||||
@ -42,10 +42,10 @@ add_task(async function() {
|
||||
});
|
||||
is(output, "Passed", "Paste file");
|
||||
|
||||
textbox.focus();
|
||||
input.focus();
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
textbox.addEventListener(
|
||||
input.addEventListener(
|
||||
"paste",
|
||||
function(event) {
|
||||
let dt = event.clipboardData;
|
||||
@ -74,7 +74,7 @@ add_task(async function() {
|
||||
EventUtils.synthesizeKey("v", { accelKey: true });
|
||||
});
|
||||
|
||||
document.documentElement.removeChild(textbox);
|
||||
input.remove();
|
||||
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
@ -114,12 +114,12 @@ add_task(async function() {
|
||||
"Ctrl+Tab*2 -> Ctrl+W -> Ctrl+Shift+Tab*2 keeps the selected tab"
|
||||
);
|
||||
}
|
||||
gBrowser.removeTab(gBrowser.tabContainer.lastElementChild);
|
||||
gBrowser.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
|
||||
checkTabs(2);
|
||||
|
||||
await ctrlTabTest([1], 1, 0);
|
||||
|
||||
gBrowser.removeTab(gBrowser.tabContainer.lastElementChild);
|
||||
gBrowser.removeTab(gBrowser.tabs[gBrowser.tabs.length - 1]);
|
||||
checkTabs(1);
|
||||
|
||||
{
|
||||
|
@ -67,14 +67,10 @@ add_task(async function() {
|
||||
doCompletion();
|
||||
});
|
||||
// Click again:
|
||||
document
|
||||
.getAnonymousElementByAttribute(testTab, "anonid", "close-button")
|
||||
.click();
|
||||
testTab.closeButton.click();
|
||||
});
|
||||
// Click once:
|
||||
document
|
||||
.getAnonymousElementByAttribute(testTab, "anonid", "close-button")
|
||||
.click();
|
||||
testTab.closeButton.click();
|
||||
});
|
||||
await TestUtils.waitForCondition(() => !testTab.parentNode);
|
||||
ok(!testTab.parentNode, "Tab should be closed completely");
|
||||
|
@ -1,4 +1,4 @@
|
||||
function test() {
|
||||
async function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let EventUtils = {};
|
||||
@ -21,13 +21,15 @@ function test() {
|
||||
];
|
||||
// set the valid attribute so dropping is allowed
|
||||
var oldstate = gURLBar.getAttribute("pageproxystate");
|
||||
gURLBar.setAttribute("pageproxystate", "valid");
|
||||
var dt = EventUtils.synthesizeDragStart(
|
||||
document.getElementById("identity-box"),
|
||||
gURLBar.setPageProxyState("valid");
|
||||
let result = await EventUtils.synthesizePlainDragAndCancel(
|
||||
{
|
||||
srcElement: document.getElementById("identity-box"),
|
||||
},
|
||||
expected
|
||||
);
|
||||
is(dt, null, "drag on proxy icon");
|
||||
gURLBar.setAttribute("pageproxystate", oldstate);
|
||||
ok(result === true, "dragging dataTransfer should be expected");
|
||||
gURLBar.setPageProxyState(oldstate);
|
||||
// Now, the identity information panel is opened by the proxy icon click.
|
||||
// We need to close it for next tests.
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, window);
|
||||
|
@ -526,7 +526,7 @@ function test_emitLatchedEvents(eventPrefix, initialDelta, cmd) {
|
||||
}
|
||||
|
||||
function test_addCommand(prefName, id) {
|
||||
let cmd = test_commandset.appendChild(document.createElement("command"));
|
||||
let cmd = test_commandset.appendChild(document.createXULElement("command"));
|
||||
cmd.setAttribute("id", id);
|
||||
cmd.setAttribute("oncommand", "this.callCount++;");
|
||||
|
||||
|
@ -12,9 +12,10 @@ add_task(async function() {
|
||||
EventUtils
|
||||
);
|
||||
|
||||
// Since synthesizeDrop triggers the srcElement, need to use another button.
|
||||
let dragSrcElement = document.getElementById("downloads-button");
|
||||
ok(dragSrcElement, "Downloads button exists");
|
||||
// Since synthesizeDrop triggers the srcElement, need to use another button
|
||||
// that should be visible.
|
||||
let dragSrcElement = document.getElementById("sidebar-button");
|
||||
ok(dragSrcElement, "Sidebar button exists");
|
||||
let homeButton = document.getElementById("home-button");
|
||||
ok(homeButton, "home button present");
|
||||
|
||||
@ -53,7 +54,7 @@ add_task(async function() {
|
||||
Services.prefs.addObserver(HOMEPAGE_PREF, observer);
|
||||
});
|
||||
|
||||
setHomepageDialog.document.documentElement.acceptDialog();
|
||||
setHomepageDialog.document.getElementById("commonDialog").acceptDialog();
|
||||
|
||||
await setHomepagePromise;
|
||||
}
|
||||
|
@ -213,9 +213,10 @@ async function drop(dragData, expectedURLs) {
|
||||
EventUtils
|
||||
);
|
||||
|
||||
// Since synthesizeDrop triggers the srcElement, need to use another button.
|
||||
let dragSrcElement = document.getElementById("downloads-button");
|
||||
ok(dragSrcElement, "Downloads button exists");
|
||||
// Since synthesizeDrop triggers the srcElement, need to use another button
|
||||
// that should be visible.
|
||||
let dragSrcElement = document.getElementById("sidebar-button");
|
||||
ok(dragSrcElement, "Sidebar button exists");
|
||||
let newTabButton = document.getElementById("new-tab-button");
|
||||
ok(newTabButton, "New Tab button exists");
|
||||
|
||||
|
@ -200,9 +200,10 @@ async function drop(dragData, expectedURLs, ignoreFirstWindow = false) {
|
||||
EventUtils
|
||||
);
|
||||
|
||||
// Since synthesizeDrop triggers the srcElement, need to use another button.
|
||||
let dragSrcElement = document.getElementById("downloads-button");
|
||||
ok(dragSrcElement, "Downloads button exists");
|
||||
// Since synthesizeDrop triggers the srcElement, need to use another button
|
||||
// that should be visible.
|
||||
let dragSrcElement = document.getElementById("sidebar-button");
|
||||
ok(dragSrcElement, "Sidebar button exists");
|
||||
let newWindowButton = document.getElementById("new-window-button");
|
||||
ok(newWindowButton, "New Window button exists");
|
||||
|
||||
|
@ -19,10 +19,9 @@ const PAGE = `data:text/html,<a id="target" href="%23" onclick="window.open('htt
|
||||
*/
|
||||
function promiseNewWindow() {
|
||||
return new Promise(resolve => {
|
||||
let observer = (subject, topic, data) => {
|
||||
let observer = (win, topic, data) => {
|
||||
if (topic == "domwindowopened") {
|
||||
Services.ww.unregisterNotification(observer);
|
||||
let win = subject.QueryInterface(Ci.nsIDOMWindow);
|
||||
win.addEventListener(
|
||||
"load",
|
||||
function() {
|
||||
|
@ -6,7 +6,7 @@ MockFilePicker.init(window);
|
||||
|
||||
const SAVE_PER_SITE_PREF = "browser.download.lastDir.savePerSite";
|
||||
const ALWAYS_DOWNLOAD_DIR_PREF = "browser.download.useDownloadDir";
|
||||
const UCT_URI = "chrome://mozapps/content/downloads/unknownContentType.xul";
|
||||
const UCT_URI = "chrome://mozapps/content/downloads/unknownContentType.xhtml";
|
||||
|
||||
/* import-globals-from ../../../../../toolkit/content/tests/browser/common/mockTransfer.js */
|
||||
Services.scriptloader.loadSubScript(
|
||||
@ -76,7 +76,9 @@ function triggerSave(aWindow, aCallback) {
|
||||
function continueDownloading() {
|
||||
for (let win of Services.wm.getEnumerator("")) {
|
||||
if (win.location && win.location.href == UCT_URI) {
|
||||
win.document.documentElement._fireButtonEvent("accept");
|
||||
win.document
|
||||
.getElementById("unknownContentType")
|
||||
._fireButtonEvent("accept");
|
||||
win.close();
|
||||
return;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const ROOT = getRootDirectory(gTestPath);
|
||||
const URI = ROOT + "browser_tab_dragdrop2_frame1.xul";
|
||||
const URI = ROOT + "browser_tab_dragdrop2_frame1.xhtml";
|
||||
|
||||
// Load the test page (which runs some child popup tests) in a new window.
|
||||
// After the tests were run, tear off the tab into a new window and run popup
|
||||
|
@ -68,6 +68,7 @@ function popupShown(event)
|
||||
if (waitSteps > 0 && navigator.platform.includes("Linux") &&
|
||||
panel.screenY == 210) {
|
||||
waitSteps--;
|
||||
/* eslint-disable mozilla/no-arbitrary-setTimeout */
|
||||
setTimeout(popupShown, 10, event);
|
||||
return;
|
||||
}
|
||||
@ -90,7 +91,7 @@ function createPanel(attrs)
|
||||
button.width = 120;
|
||||
button.height = 40;
|
||||
button.setAttribute("style", "appearance: none; border: 0; margin: 0;");
|
||||
panel.setAttribute("style", "-moz-appearance: none; border: 0; margin: 0;");
|
||||
panel.setAttribute("style", "appearance: none; border: 0; margin: 0;");
|
||||
return document.documentElement.appendChild(panel);
|
||||
}
|
||||
|
@ -676,6 +676,11 @@ function compareFocusResults() {
|
||||
? browser1.contentWindow
|
||||
: browser2.contentWindow;
|
||||
}
|
||||
if (_expectedWindow == "main-window") {
|
||||
// The browser window's body doesn't have an id set usually - set one now
|
||||
// so it can be used for id comparisons below.
|
||||
matchWindow.document.body.id = "main-window-body";
|
||||
}
|
||||
|
||||
var focusedElement = fm.focusedElement;
|
||||
is(
|
||||
@ -698,13 +703,7 @@ function compareFocusResults() {
|
||||
is(matchWindow.document.hasFocus(), true, currentTestName + " hasFocus");
|
||||
var expectedActive = _expectedElement;
|
||||
if (!expectedActive) {
|
||||
// Documents that have a XUL document element currently have a different
|
||||
// active element behavior than regular HTML documents. This test will
|
||||
// need to be updated when bug 1492582 is fixed.
|
||||
expectedActive =
|
||||
matchWindow.document.documentElement instanceof XULElement
|
||||
? "main-window"
|
||||
: getId(matchWindow.document.body);
|
||||
expectedActive = getId(matchWindow.document.body);
|
||||
}
|
||||
is(
|
||||
getId(matchWindow.document.activeElement),
|
||||
|
@ -51,11 +51,7 @@ add_task(async function() {
|
||||
info("Waiting for the load in that tab to finish");
|
||||
await secondTabLoadedPromise;
|
||||
|
||||
let closeBtn = document.getAnonymousElementByAttribute(
|
||||
secondTab,
|
||||
"anonid",
|
||||
"close-button"
|
||||
);
|
||||
let closeBtn = secondTab.closeButton;
|
||||
info("closing second tab (which will self-close in beforeunload)");
|
||||
closeBtn.click();
|
||||
ok(
|
||||
|
@ -3,21 +3,20 @@ function test() {
|
||||
BrowserTestUtils.addTab(gBrowser);
|
||||
BrowserTestUtils.addTab(gBrowser);
|
||||
|
||||
var tabs = gBrowser.tabs;
|
||||
var owner;
|
||||
|
||||
is(tabs.length, 4, "4 tabs are open");
|
||||
is(gBrowser.tabs.length, 4, "4 tabs are open");
|
||||
|
||||
owner = gBrowser.selectedTab = tabs[2];
|
||||
owner = gBrowser.selectedTab = gBrowser.tabs[2];
|
||||
BrowserOpenTab();
|
||||
is(gBrowser.selectedTab, tabs[4], "newly opened tab is selected");
|
||||
is(gBrowser.selectedTab, gBrowser.tabs[4], "newly opened tab is selected");
|
||||
gBrowser.removeCurrentTab();
|
||||
is(gBrowser.selectedTab, owner, "owner is selected");
|
||||
|
||||
owner = gBrowser.selectedTab;
|
||||
BrowserOpenTab();
|
||||
gBrowser.selectedTab = tabs[1];
|
||||
gBrowser.selectedTab = tabs[4];
|
||||
gBrowser.selectedTab = gBrowser.tabs[1];
|
||||
gBrowser.selectedTab = gBrowser.tabs[4];
|
||||
gBrowser.removeCurrentTab();
|
||||
isnot(
|
||||
gBrowser.selectedTab,
|
||||
@ -32,10 +31,10 @@ function test() {
|
||||
is(
|
||||
gBrowser.selectedTab,
|
||||
owner,
|
||||
"owner relatitionship persists when tab is moved"
|
||||
"owner relationship persists when tab is moved"
|
||||
);
|
||||
|
||||
while (tabs.length > 1) {
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ add_task(async function() {
|
||||
let win = await waitForNewWindow();
|
||||
is(
|
||||
win.location,
|
||||
"chrome://mozapps/content/downloads/unknownContentType.xul",
|
||||
"chrome://mozapps/content/downloads/unknownContentType.xhtml",
|
||||
"Should have seen the unknown content dialog."
|
||||
);
|
||||
is(gBrowser.contentTitle, "Test Page", "Should still have the right title.");
|
||||
|
@ -1,6 +1,8 @@
|
||||
[DEFAULT]
|
||||
support-files = head.js
|
||||
|
||||
[browser_popup_keyNav.js]
|
||||
support-files = focusableContent.html
|
||||
[browser_toolbarButtonKeyPress.js]
|
||||
[browser_toolbarKeyNav.js]
|
||||
support-files = !/browser/base/content/test/permissions/permissions.html
|
||||
|
49
browser/base/content/test/keyboard/browser_popup_keyNav.js
Normal file
49
browser/base/content/test/keyboard/browser_popup_keyNav.js
Normal 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);
|
||||
});
|
||||
});
|
@ -19,44 +19,6 @@ function resetToolbarWithoutDevEditionButtons() {
|
||||
CustomizableUI.removeWidgetFromArea("developer-button");
|
||||
}
|
||||
|
||||
async function expectFocusAfterKey(
|
||||
aKey,
|
||||
aFocus,
|
||||
aAncestorOk = false,
|
||||
aWindow = window
|
||||
) {
|
||||
let res = aKey.match(/^(Shift\+)?(?:(.)|(.+))$/);
|
||||
let shift = Boolean(res[1]);
|
||||
let key;
|
||||
if (res[2]) {
|
||||
key = res[2]; // Character.
|
||||
} else {
|
||||
key = "KEY_" + res[3]; // Tab, ArrowRight, etc.
|
||||
}
|
||||
let expected;
|
||||
let friendlyExpected;
|
||||
if (typeof aFocus == "string") {
|
||||
expected = aWindow.document.getElementById(aFocus);
|
||||
friendlyExpected = aFocus;
|
||||
} else {
|
||||
expected = aFocus;
|
||||
if (aFocus == aWindow.gURLBar.inputField) {
|
||||
friendlyExpected = "URL bar input";
|
||||
} else if (aFocus == aWindow.gBrowser.selectedBrowser) {
|
||||
friendlyExpected = "Web document";
|
||||
}
|
||||
}
|
||||
info("Listening on item " + (expected.id || expected.className));
|
||||
let focused = BrowserTestUtils.waitForEvent(expected, "focus", aAncestorOk);
|
||||
EventUtils.synthesizeKey(key, { shiftKey: shift }, aWindow);
|
||||
let receivedEvent = await focused;
|
||||
info(
|
||||
"Got focus on item: " +
|
||||
(receivedEvent.target.id || receivedEvent.target.className)
|
||||
);
|
||||
ok(true, friendlyExpected + " focused after " + aKey + " pressed");
|
||||
}
|
||||
|
||||
function startFromUrlBar(aWindow = window) {
|
||||
aWindow.gURLBar.focus();
|
||||
is(
|
||||
@ -373,3 +335,65 @@ add_task(async function testPanelCloseRestoresFocus() {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Test navigation by typed characters.
|
||||
add_task(async function testCharacterNavigation() {
|
||||
await BrowserTestUtils.withNewTab("https://example.com", async function() {
|
||||
await waitUntilReloadEnabled();
|
||||
startFromUrlBar();
|
||||
await expectFocusAfterKey("Tab", "pageActionButton");
|
||||
await expectFocusAfterKey("h", "home-button");
|
||||
// There's no button starting with "hs", so pressing s should do nothing.
|
||||
EventUtils.synthesizeKey("s");
|
||||
is(
|
||||
document.activeElement.id,
|
||||
"home-button",
|
||||
"home-button still focused after s pressed"
|
||||
);
|
||||
// Escape should reset the search.
|
||||
EventUtils.synthesizeKey("KEY_Escape");
|
||||
// Now that the search is reset, pressing s should focus Save to Pocket.
|
||||
await expectFocusAfterKey("s", "pocket-button");
|
||||
// Pressing i makes the search "si", so it should focus Sidebars.
|
||||
await expectFocusAfterKey("i", "sidebar-button");
|
||||
// Reset the search.
|
||||
EventUtils.synthesizeKey("KEY_Escape");
|
||||
await expectFocusAfterKey("s", "pocket-button");
|
||||
// Pressing s again should find the next button starting with s: Sidebars.
|
||||
await expectFocusAfterKey("s", "sidebar-button");
|
||||
});
|
||||
});
|
||||
|
||||
// Test that toolbar character navigation doesn't trigger in PanelMultiView for
|
||||
// a panel anchored to the toolbar.
|
||||
// We do this by opening the Library menu and ensuring that pressing s
|
||||
// does nothing.
|
||||
// This test should be removed if PanelMultiView implements character
|
||||
// navigation.
|
||||
add_task(async function testCharacterInPanelMultiView() {
|
||||
let button = document.getElementById("library-button");
|
||||
forceFocus(button);
|
||||
let view = document.getElementById("appMenu-libraryView");
|
||||
let focused = BrowserTestUtils.waitForEvent(view, "focus", true);
|
||||
EventUtils.synthesizeKey(" ");
|
||||
let focusEvt = await focused;
|
||||
ok(true, "Focus inside Library menu after toolbar button pressed");
|
||||
EventUtils.synthesizeKey("s");
|
||||
is(document.activeElement, focusEvt.target, "s inside panel does nothing");
|
||||
let hidden = BrowserTestUtils.waitForEvent(document, "popuphidden", true);
|
||||
view.closest("panel").hidePopup();
|
||||
await hidden;
|
||||
});
|
||||
|
||||
// Test tab stops after the search bar is added.
|
||||
add_task(async function testTabStopsAfterSearchBarAdded() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.search.widget.inNavBar", 1]],
|
||||
});
|
||||
await withNewBlankTab(async function() {
|
||||
startFromUrlBar();
|
||||
await expectFocusAfterKey("Tab", "searchbar", true);
|
||||
await expectFocusAfterKey("Tab", "library-button");
|
||||
});
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
1
browser/base/content/test/keyboard/focusableContent.html
Normal file
1
browser/base/content/test/keyboard/focusableContent.html
Normal file
@ -0,0 +1 @@
|
||||
<button>Just a button here to have something focusable.</button>
|
@ -15,3 +15,41 @@ function forceFocus(aElem) {
|
||||
aElem.focus();
|
||||
aElem.removeAttribute("tabindex");
|
||||
}
|
||||
|
||||
async function expectFocusAfterKey(
|
||||
aKey,
|
||||
aFocus,
|
||||
aAncestorOk = false,
|
||||
aWindow = window
|
||||
) {
|
||||
let res = aKey.match(/^(Shift\+)?(?:(.)|(.+))$/);
|
||||
let shift = Boolean(res[1]);
|
||||
let key;
|
||||
if (res[2]) {
|
||||
key = res[2]; // Character.
|
||||
} else {
|
||||
key = "KEY_" + res[3]; // Tab, ArrowRight, etc.
|
||||
}
|
||||
let expected;
|
||||
let friendlyExpected;
|
||||
if (typeof aFocus == "string") {
|
||||
expected = aWindow.document.getElementById(aFocus);
|
||||
friendlyExpected = aFocus;
|
||||
} else {
|
||||
expected = aFocus;
|
||||
if (aFocus == aWindow.gURLBar.inputField) {
|
||||
friendlyExpected = "URL bar input";
|
||||
} else if (aFocus == aWindow.gBrowser.selectedBrowser) {
|
||||
friendlyExpected = "Web document";
|
||||
}
|
||||
}
|
||||
info("Listening on item " + (expected.id || expected.className));
|
||||
let focused = BrowserTestUtils.waitForEvent(expected, "focus", aAncestorOk);
|
||||
EventUtils.synthesizeKey(key, { shiftKey: shift }, aWindow);
|
||||
let receivedEvent = await focused;
|
||||
info(
|
||||
"Got focus on item: " +
|
||||
(receivedEvent.target.id || receivedEvent.target.className)
|
||||
);
|
||||
ok(true, friendlyExpected + " focused after " + aKey + " pressed");
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user