/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- * 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/. */
/* eslint-env mozilla/browser-window */
"use strict";
var kSkipCacheFlags =
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY |
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
var BrowserCommands = {
back(aEvent) { const where = BrowserUtils.whereToOpenLink(aEvent, false, true);
for (const tab of gBrowser.selectedTabs) { const browser = tab.linkedBrowser; const url = browser.currentURI; const urlSpec = url.spec; // We need to cache the content principal here because the browser will be // reconstructed when the remoteness changes and the content prinicpal will // be cleared after reconstruction. const principal = tab.linkedBrowser.contentPrincipal; if (gBrowser.updateBrowserRemotenessByURL(browser, urlSpec)) { // If the remoteness has changed, the new browser doesn't have any // information of what was loaded before, so we need to load the previous // URL again. if (tab.linkedPanel) {
loadBrowserURI(browser, url, principal);
} else { // Shift to fully loaded browser and make // sure load handler is instantiated.
tab.addEventListener( "SSTabRestoring",
() => loadBrowserURI(browser, url, principal),
{ once: true }
);
gBrowser._insertBrowser(tab);
}
} else {
unchangedRemoteness.push(tab);
}
}
if (!unchangedRemoteness.length) { return;
}
// Reset temporary permissions on the remaining tabs to reload. // This is done here because we only want to reset // permissions on user reload. for (const tab of unchangedRemoteness) {
SitePermissions.clearTemporaryBlockPermissions(tab.linkedBrowser); // Also reset DOS mitigations for the basic auth prompt on reload. delete tab.linkedBrowser.authPromptAbuseCounter;
}
gIdentityHandler.hidePopup();
gPermissionPanel.hidePopup();
if (document.hasValidTransientUserGestureActivation) {
reloadFlags |= Ci.nsIWebNavigation.LOAD_FLAGS_USER_ACTIVATION;
}
for (const tab of unchangedRemoteness) {
reloadBrowser(tab, reloadFlags);
}
function reloadBrowser(tab) { if (tab.linkedPanel) { const { browsingContext } = tab.linkedBrowser; const { sessionHistory } = browsingContext; if (sessionHistory) {
sessionHistory.reload(reloadFlags);
} else {
browsingContext.reload(reloadFlags);
}
} else { // Shift to fully loaded browser and make // sure load handler is instantiated.
tab.addEventListener( "SSTabRestoring",
() => tab.linkedBrowser.browsingContext.reload(reloadFlags),
{
once: true,
}
);
gBrowser._insertBrowser(tab);
}
}
home(aEvent) { if (aEvent?.button == 2) { // right-click: do nothing return;
}
const homePage = HomePage.get(window);
let where = BrowserUtils.whereToOpenLink(aEvent, false, true);
// Don't load the home page in pinned or hidden tabs (e.g. Firefox View). if (
where == "current" &&
(gBrowser?.selectedTab.pinned || gBrowser?.selectedTab.hidden)
) {
where = "tab";
}
// openTrustedLinkIn in utilityOverlay.js doesn't handle loading multiple pages
let notifyObservers; switch (where) { case"current": // If we're going to load an initial page in the current tab as the // home page, we set initialPageLoadedFromURLBar so that the URL // bar is cleared properly (even during a remoteness flip). if (isInitialPage(homePage)) {
gBrowser.selectedBrowser.initialPageLoadedFromUserAction = homePage;
}
loadOneOrMoreURIs(
homePage,
Services.scriptSecurityManager.getSystemPrincipal(), null
); if (isBlankPageURL(homePage)) {
gURLBar.select();
} else {
gBrowser.selectedBrowser.focus();
}
notifyObservers = true;
aEvent?.preventDefault(); break; case"tabshifted": case"tab": { const urls = homePage.split("|"); const loadInBackground = Services.prefs.getBoolPref( "browser.tabs.loadBookmarksInBackground", false
); // The homepage observer event should only be triggered when the homepage opens // in the foreground. This is mostly to support the homepage changed by extension // doorhanger which doesn't currently support background pages. This may change in // bug 1438396.
notifyObservers = !loadInBackground;
gBrowser.loadTabs(urls, {
inBackground: loadInBackground,
triggeringPrincipal:
Services.scriptSecurityManager.getSystemPrincipal(),
csp: null,
}); if (!loadInBackground) { if (isBlankPageURL(homePage)) {
gURLBar.select();
} else {
gBrowser.selectedBrowser.focus();
}
}
aEvent?.preventDefault(); break;
} case"window": // OpenBrowserWindow will trigger the observer event, so no need to do so here.
notifyObservers = false;
OpenBrowserWindow();
aEvent?.preventDefault(); break;
}
if (notifyObservers) { // A notification for when a user has triggered their homepage. This is used // to display a doorhanger explaining that an extension has modified the // homepage, if necessary. Observers are only notified if the homepage // becomes the active page.
Services.obs.notifyObservers(null, "browser-open-homepage-start");
}
},
if (event) {
where = BrowserUtils.whereToOpenLink(event, false, true);
switch (where) { case"tab": case"tabshifted": // When accel-click or middle-click are used, open the new tab as // related to the current tab.
relatedToCurrent = true; break; case"current":
where = "tab"; break;
}
}
// A notification intended to be useful for modular peformance tracking // starting as close as is reasonably possible to the time when the user // expressed the intent to open a new tab. Since there are a lot of // entry points, this won't catch every single tab created, but most // initiated by the user should go through here. // // Note 1: This notification gets notified with a promise that resolves // with the linked browser when the tab gets created // Note 2: This is also used to notify a user that an extension has changed // the New Tab page.
Services.obs.notifyObservers(
{
wrappedJSObject: new Promise(resolve => {
let options = {
relatedToCurrent,
resolveOnNewTabCreated: resolve,
}; if (!werePassedURL && searchClipboard) {
let clipboard = readFromClipboard();
clipboard =
UrlbarUtils.stripUnsafeProtocolOnPaste(clipboard).trim(); if (clipboard) {
url = clipboard;
options.allowThirdPartyFixup = true;
}
}
openTrustedLinkIn(url, where, options);
}),
}, "browser-open-newtab-start"
);
},
closeTabOrWindow(event) { // If we're not a browser window, just close the window. if (window.location.href != AppConstants.BROWSER_CHROME_URL) {
closeWindow(true); return;
}
// In a multi-select context, close all selected tabs if (gBrowser.multiSelectedTabsCount) {
gBrowser.removeMultiSelectedTabs(); return;
}
// Keyboard shortcuts that would close a tab that is pinned select the first // unpinned tab instead. if (
event &&
(event.ctrlKey || event.metaKey || event.altKey) &&
gBrowser.selectedTab.pinned
) { if (gBrowser.visibleTabs.length > gBrowser.pinnedTabCount) {
gBrowser.tabContainer.selectedIndex = gBrowser.pinnedTabCount;
} return;
}
// If the current tab is the last one, this will close the window.
gBrowser.removeCurrentTab({ animate: true });
},
tryToCloseWindow(event) { if (WindowIsClosing(event)) {
window.close();
} // WindowIsClosing does all the necessary checks
},
/** * Open the View Source dialog. * * @param args * An object with the following properties: * * URL (required): * A string URL for the page we'd like to view the source of. * browser (optional): * The browser containing the document that we would like to view the * source of. This is required if outerWindowID is passed. * outerWindowID (optional): * The outerWindowID of the content window containing the document that * we want to view the source of. You only need to provide this if you * want to attempt to retrieve the document source from the network * cache. * lineNumber (optional): * The line number to focus on once the source is loaded.
*/
async viewSourceOfDocument(args) { // Check if external view source is enabled. If so, try it. If it fails, // fallback to internal view source. if (Services.prefs.getBoolPref("view_source.editor.external")) { try {
await top.gViewSourceUtils.openInExternalEditor(args); return;
} catch (data) {}
}
let tabBrowser = gBrowser;
let preferredRemoteType;
let initialBrowsingContextGroupId; if (args.browser) {
preferredRemoteType = args.browser.remoteType;
initialBrowsingContextGroupId = args.browser.browsingContext.group.id;
} else { if (!tabBrowser) { thrownew Error( "viewSourceOfDocument should be passed the " + "subject browser if called from a window without " + "gBrowser defined."
);
} // Some internal URLs (such as specific chrome: and about: URLs that are // not yet remote ready) cannot be loaded in a remote browser. View // source in tab expects the new view source browser's remoteness to match // that of the original URL, so disable remoteness if necessary for this // URL. const oa = E10SUtils.predictOriginAttributes({ window });
preferredRemoteType = E10SUtils.getRemoteTypeForURI(
args.URL,
gMultiProcessBrowser,
gFissionBrowser,
E10SUtils.DEFAULT_REMOTE_TYPE, null,
oa
);
}
// In the case of popups, we need to find a non-popup browser window. if (!tabBrowser || !window.toolbar.visible) { // This returns only non-popup browser windows by default. const browserWindow = BrowserWindowTracker.getTopWindow();
tabBrowser = browserWindow.gBrowser;
}
// `viewSourceInBrowser` will load the source content from the page // descriptor for the tab (when possible) or fallback to the network if // that fails. Either way, the view source module will manage the tab's // location, so use "about:blank" here to avoid unnecessary redundant // requests. const tab = tabBrowser.addTab("about:blank", {
relatedToCurrent: true,
inBackground: inNewWindow,
skipAnimation: inNewWindow,
preferredRemoteType,
initialBrowsingContextGroupId,
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
skipLoad: true,
});
args.viewSourceBrowser = tabBrowser.getBrowserForTab(tab);
top.gViewSourceUtils.viewSourceInBrowser(args);
if (inNewWindow) {
tabBrowser.hideTab(tab);
tabBrowser.replaceTabWithWindow(tab);
}
},
/** * Opens the View Source dialog for the source loaded in the root * top-level document of the browser. This is really just a * convenience wrapper around viewSourceOfDocument. * * @param browser * The browser that we want to load the source of.
*/
viewSource(browser) { this.viewSourceOfDocument({
browser,
outerWindowID: browser.outerWindowID,
URL: browser.currentURI.spec,
});
},
/** * @param documentURL URL of the document to view, or null for this window's document * @param initialTab name of the initial tab to display, or null for the first tab * @param imageElement image to load in the Media Tab of the Page Info window; can be null/omitted * @param browsingContext the browsingContext of the frame that we want to view information about; can be null/omitted * @param browser the browser containing the document we're interested in inspecting; can be null/omitted
*/
pageInfo(documentURL, initialTab, imageElement, browsingContext, browser) { const args = { initialTab, imageElement, browsingContext, browser };
// Check for windows matching the url for (const currentWindow of Services.wm.getEnumerator( "Browser:page-info"
)) { if (currentWindow.closed) { continue;
} if (
currentWindow.document.documentElement.getAttribute("relatedUrl") ==
documentURL &&
PrivateBrowsingUtils.isWindowPrivate(currentWindow) == isPrivate
) {
currentWindow.focus();
currentWindow.resetPageInfo(args); return currentWindow;
}
}
// We didn't find a matching window, so open a new one.
let options = "chrome,toolbar,dialog=no,resizable";
// Ensure the window groups correctly in the Windows taskbar if (isPrivate) {
options += ",private";
} return openDialog( "chrome://browser/content/pageinfo/pageInfo.xhtml", "",
options,
args
);
},
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.