/* -*- 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/. */
let _resolveDelayedStartup; var delayedStartupPromise = new Promise(resolve => {
_resolveDelayedStartup = resolve;
});
var gBrowserInit = {
delayedStartupFinished: false,
domContentLoaded: false,
_setupFirstContentWindowPaintPromise() {
let lastTransactionId = window.windowUtils.lastTransactionId;
let layerTreeListener = () => { if (this.getTabToAdopt()) { // Need to wait until we finish adopting the tab, or we might end // up focusing the initial browser and then losing focus when it // gets swapped out for the tab to adopt. return;
}
removeEventListener("MozLayerTreeReady", layerTreeListener);
let listener = e => { if (e.transactionId > lastTransactionId) {
window.removeEventListener("MozAfterPaint", listener); this._firstContentWindowPaintDeferred.resolve();
}
};
addEventListener("MozAfterPaint", listener);
};
addEventListener("MozLayerTreeReady", layerTreeListener);
},
getTabToAdopt() { if (this._tabToAdopt !== undefined) { returnthis._tabToAdopt;
}
if (window.arguments && window.XULElement.isInstance(window.arguments[0])) { this._tabToAdopt = window.arguments[0];
// Clear the reference of the tab being adopted from the arguments.
window.arguments[0] = null;
} else { // There was no tab to adopt in the arguments, set _tabToAdopt to null // to avoid checking it again. this._tabToAdopt = null;
}
returnthis._tabToAdopt;
},
_clearTabToAdopt() { this._tabToAdopt = null;
},
// Used to check if the new window is still adopting an existing tab as its first tab // (e.g. from the WebExtensions internals).
isAdoptingTab() { return !!this.getTabToAdopt();
},
// Set a sane starting width/height for all resolutions on new profiles. if (ChromeUtils.shouldResistFingerprinting("RoundWindowSize", null)) { // When the fingerprinting resistance is enabled, making sure that we don't // have a maximum window to interfere with generating rounded window dimensions.
document.documentElement.setAttribute("sizemode", "normal");
} elseif (!document.documentElement.hasAttribute("width")) { const TARGET_WIDTH = 1280; const TARGET_HEIGHT = 1040;
let width = Math.min(screen.availWidth * 0.9, TARGET_WIDTH);
let height = Math.min(screen.availHeight * 0.9, TARGET_HEIGHT);
if (width < TARGET_WIDTH && height < TARGET_HEIGHT) {
document.documentElement.setAttribute("sizemode", "maximized");
}
} if (AppConstants.MENUBAR_CAN_AUTOHIDE) { const toolbarMenubar = document.getElementById("toolbar-menubar"); // set a default value if (!toolbarMenubar.hasAttribute("autohide")) {
toolbarMenubar.setAttribute("autohide", true);
}
document.l10n.setAttributes(
toolbarMenubar, "toolbar-context-menu-menu-bar-cmd"
);
toolbarMenubar.setAttribute("data-l10n-attrs", "toolbarname");
}
// Run menubar initialization first, to avoid CustomTitlebar code picking // up mutations from it and causing a reflow.
AutoHideMenubar.init(); // Update the customtitlebar attribute so the window can be sized // correctly.
window.TabBarVisibility.update();
CustomTitlebar.init();
// Call this after we set attributes that might change toolbars' computed // text color.
ToolbarIconColor.init();
},
onDOMContentLoaded() { // This needs setting up before we create the first remote browser.
window.docShell.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIAppWindow).XULBrowserWindow = window.XULBrowserWindow;
window.browserDOMWindow = new nsBrowserAccess();
gBrowser = new window.Tabbrowser();
gBrowser.init();
let isVerticalTabs = Services.prefs.getBoolPref( "sidebar.verticalTabs", false
);
let nonRemovables;
// We don't want these normally non-removable elements to get put back into the // tabstrip if we're initializing with vertical tabs. // We should refrain from excluding popups here to make sure CUI doesn't // get into a blank saved state. if (isVerticalTabs) {
nonRemovables = [gBrowser.tabContainer]; for (let elem of nonRemovables) {
elem.setAttribute("removable", "true"); // tell CUI to ignore this element when it builds the toolbar areas
elem.setAttribute("skipintoolbarset", "true");
}
} for (let area of CustomizableUI.areas) {
let type = CustomizableUI.getAreaType(area); if (type == CustomizableUI.TYPE_TOOLBAR) {
let node = document.getElementById(area);
CustomizableUI.registerToolbarNode(node);
}
} if (isVerticalTabs) { // Show the vertical tabs toolbar
setToolbarVisibility(
document.getElementById(CustomizableUI.AREA_VERTICAL_TABSTRIP), true, false, false
);
let tabstripToolbar = document.getElementById(
CustomizableUI.AREA_TABSTRIP
);
let wasCollapsed = tabstripToolbar.collapsed;
TabBarVisibility.update(); if (tabstripToolbar.collapsed !== wasCollapsed) {
let eventParams = {
detail: {
visible: !tabstripToolbar.collapsed,
},
bubbles: true,
};
let event = new CustomEvent("toolbarvisibilitychange", eventParams);
tabstripToolbar.dispatchEvent(event);
}
for (let elem of nonRemovables) {
elem.setAttribute("removable", "false");
elem.removeAttribute("skipintoolbarset");
}
}
BrowserSearch.initPlaceHolder();
// Hack to ensure that the various initial pages favicon is loaded // instantaneously, to avoid flickering and improve perceived performance. this._callWithURIToLoad(uriToLoad => {
let url; try {
url = Services.io.newURI(uriToLoad);
} catch (e) { return;
}
let nonQuery = url.prePath + url.filePath; if (nonQuery in gPageIcons) {
gBrowser.setIcon(gBrowser.selectedTab, gPageIcons[nonQuery]);
}
});
updateFxaToolbarMenu(gFxaToolbarEnabled, true);
updatePrintCommands(gPrintEnabled);
gUnifiedExtensions.init();
// Setting the focus will cause a style flush, it's preferable to call anything // that will modify the DOM from within this function before this call. this._setInitialFocus();
// These routines add message listeners. They must run before // loading the frame script to ensure that we don't miss any // message sent between when the frame script is loaded and when // the listener is registered.
CaptivePortalWatcher.init();
ZoomUI.init(window);
if (!gMultiProcessBrowser) { // There is a Content:Click message manually sent from content.
gBrowser.tabpanels.addEventListener("click", contentAreaClick, {
capture: true,
mozSystemGroup: true,
});
}
// hook up UI through progress listener
gBrowser.addProgressListener(window.XULBrowserWindow);
gBrowser.addTabsProgressListener(window.TabsProgressListener);
SidebarController.init();
// We do this in onload because we want to ensure the button's state // doesn't flicker as the window is being shown.
DownloadsButton.init();
// Certain kinds of automigration rely on this notification to complete // their tasks BEFORE the browser window is shown. SessionStore uses it to // restore tabs into windows AFTER important parts like gMultiProcessBrowser // have been initialized.
Services.obs.notifyObservers(window, "browser-window-before-show");
if (!window.toolbar.visible) { // adjust browser UI for popups
gURLBar.readOnly = true;
}
// Update UI if browser is under remote control.
gRemoteControl.updateVisualCue();
// If we are given a tab to swap in, take care of it before first paint to // avoid an about:blank flash.
let tabToAdopt = this.getTabToAdopt(); if (tabToAdopt) {
let evt = new CustomEvent("before-initial-tab-adopted", {
bubbles: true,
});
gBrowser.tabpanels.dispatchEvent(evt);
// Stop the about:blank load
gBrowser.stop();
// Remove the speculative focus from the urlbar to let the url be formatted.
gURLBar.removeAttribute("focused");
// Clear the reference to the tab once its adoption has been completed. this._clearTabToAdopt();
}; if (tabToAdopt.linkedBrowser.isRemoteBrowser) { // For remote browsers, wait for the paint event, otherwise the tabs // are not yet ready and focus gets confused because the browser swaps // out while tabs are switching.
addEventListener("MozAfterPaint", swapBrowsers, { once: true });
} else {
swapBrowsers();
}
}
// Wait until chrome is painted before executing code not critical to making the window visible this._boundDelayedStartup = this._delayedStartup.bind(this);
window.addEventListener("MozAfterPaint", this._boundDelayedStartup);
if (!PrivateBrowsingUtils.enabled) {
document.getElementById("Tools:PrivateBrowsing").hidden = true; // Setting disabled doesn't disable the shortcut, so we just remove // the keybinding.
document.getElementById("key_privatebrowsing").remove();
}
if (BrowserUIUtils.quitShortcutDisabled) {
document.getElementById("key_quitApplication").remove();
document.getElementById("menu_FileQuitItem").removeAttribute("key");
// Initialize the full zoom setting. // We do this before the session restore service gets initialized so we can // apply full zoom settings to tabs restored by the session restore service.
FullZoom.init();
PanelUI.init(shouldSuppressPopupNotifications);
// Setup click-and-hold gestures access to the session history // menus if global click-and-hold isn't turned on if (!Services.prefs.getBoolPref("ui.click_hold_context_menus", false)) {
SetClickAndHoldHandlers();
}
function initBackForwardButtonTooltip(tooltipId, l10nId, shortcutId) {
let shortcut = document.getElementById(shortcutId);
shortcut = ShortcutUtils.prettifyShortcut(shortcut);
let tooltip = document.getElementById(tooltipId);
document.l10n.setAttributes(tooltip, l10nId, { shortcut });
}
// The object handling the downloads indicator is initialized here in the // delayed startup function, but the actual indicator element is not loaded // unless there are downloads to be displayed.
DownloadsButton.initializeIndicator();
if (AppConstants.platform != "macosx") {
updateEditUIVisibility();
let placesContext = document.getElementById("placesContext");
placesContext.addEventListener("popupshowing", updateEditUIVisibility);
placesContext.addEventListener("popuphiding", updateEditUIVisibility);
}
FullScreen.init();
MenuTouchModeObserver.init();
if (AppConstants.MOZ_DATA_REPORTING) {
gDataNotificationInfoBar.init();
}
if (!AppConstants.MOZILLA_OFFICIAL) {
DevelopmentHelpers.init();
}
gExtensionsNotifications.init();
let wasMinimized = window.windowState == window.STATE_MINIMIZED;
window.addEventListener("sizemodechange", () => {
let isMinimized = window.windowState == window.STATE_MINIMIZED; if (wasMinimized != isMinimized) {
wasMinimized = isMinimized;
UpdatePopupNotificationsVisibility();
}
});
SessionStore.promiseInitialized.then(() => { // Bail out if the window has been closed in the meantime. if (window.closed) { return;
}
// Enable the Restore Last Session command if needed
RestoreLastSessionObserver.init();
SidebarController.startDelayedLoad();
PanicButtonNotifier.init();
});
if (BrowserHandler.kiosk) { // We don't modify popup windows for kiosk mode if (!gURLBar.readOnly) {
window.fullScreen = true;
}
}
if (Services.policies.status === Services.policies.ACTIVE) { if (!Services.policies.isAllowed("hideShowMenuBar")) {
document
.getElementById("toolbar-menubar")
.removeAttribute("toolbarname");
} if (!Services.policies.isAllowed("filepickers")) {
let savePageCommand = document.getElementById("Browser:SavePage");
let openFileCommand = document.getElementById("Browser:OpenFile");
this.delayedStartupFinished = true;
_resolveDelayedStartup();
Services.obs.notifyObservers(window, "browser-delayed-startup-finished");
TelemetryTimestamps.add("delayedStartupFinished"); // We've announced that delayed startup has finished. Do not add code past this point.
},
/** * Resolved on the first MozLayerTreeReady and next MozAfterPaint in the * parent process.
*/
get firstContentWindowPaintPromise() { returnthis._firstContentWindowPaintDeferred.promise;
},
_setInitialFocus() {
let initiallyFocusedElement = document.commandDispatcher.focusedElement;
// To prevent startup flicker, the urlbar has the 'focused' attribute set // by default. If we are not sure the urlbar will be focused in this // window, we need to remove the attribute before first paint. // TODO (bug 1629956): The urlbar having the 'focused' attribute by default // isn't a useful optimization anymore since UrlbarInput needs layout // information to focus the urlbar properly.
let shouldRemoveFocusedAttribute = true;
// If the initial browser is remote, in order to optimize for first paint, // we'll defer switching focus to that browser until it has painted. // Otherwise use a regular promise to guarantee that mutationobserver // microtasks that could affect focusability have run.
let promise = gBrowser.selectedBrowser.isRemoteBrowser
? this.firstContentWindowPaintPromise
: Promise.resolve();
promise.then(() => { // If focus didn't move while we were waiting, we're okay to move to // the browser. if (
document.commandDispatcher.focusedElement == initiallyFocusedElement
) {
gBrowser.selectedBrowser.focus();
}
});
});
// Delay removing the attribute using requestAnimationFrame to avoid // invalidating styles multiple times in a row if uriToLoadPromise // resolves before first paint. if (shouldRemoveFocusedAttribute) {
window.requestAnimationFrame(() => { if (shouldRemoveFocusedAttribute) {
gURLBar.removeAttribute("focused");
}
});
}
},
_handleURIToLoad() { this._callWithURIToLoad(uriToLoad => { if (!uriToLoad) { // We don't check whether window.arguments[5] (userContextId) is set // because tabbrowser.js takes care of that for the initial tab. return;
}
// We don't check if uriToLoad is a XULElement because this case has // already been handled before first paint, and the argument cleared. if (Array.isArray(uriToLoad)) { // This function throws for certain malformed URIs, so use exception handling // so that we don't disrupt startup try {
gBrowser.loadTabs(uriToLoad, {
inBackground: false,
replace: true, // See below for the semantics of window.arguments. Only the minimum is supported.
userContextId: window.arguments[5],
triggeringPrincipal:
window.arguments[8] ||
Services.scriptSecurityManager.getSystemPrincipal(),
allowInheritPrincipal: window.arguments[9],
csp: window.arguments[10],
fromExternal: true,
});
} catch (e) {}
} elseif (window.arguments.length >= 3) { // window.arguments[1]: extraOptions (nsIPropertyBag) // [2]: referrerInfo (nsIReferrerInfo) // [3]: postData (nsIInputStream) // [4]: allowThirdPartyFixup (bool) // [5]: userContextId (int) // [6]: originPrincipal (nsIPrincipal) // [7]: originStoragePrincipal (nsIPrincipal) // [8]: triggeringPrincipal (nsIPrincipal) // [9]: allowInheritPrincipal (bool) // [10]: csp (nsIContentSecurityPolicy) // [11]: nsOpenWindowInfo
let userContextId =
window.arguments[5] != undefined
? window.arguments[5]
: Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
let hasValidUserGestureActivation = undefined;
let fromExternal = undefined;
let globalHistoryOptions = undefined;
let triggeringRemoteType = undefined;
let forceAllowDataURI = false;
let schemelessInput = Ci.nsILoadInfo.SchemelessInputTypeUnset; if (window.arguments[1]) { if (!(window.arguments[1] instanceof Ci.nsIPropertyBag2)) { thrownew Error( "window.arguments[1] must be null or Ci.nsIPropertyBag2!"
);
}
let extraOptions = window.arguments[1]; if (extraOptions.hasKey("hasValidUserGestureActivation")) {
hasValidUserGestureActivation = extraOptions.getPropertyAsBool( "hasValidUserGestureActivation"
);
} if (extraOptions.hasKey("fromExternal")) {
fromExternal = extraOptions.getPropertyAsBool("fromExternal");
} if (extraOptions.hasKey("triggeringSponsoredURL")) {
globalHistoryOptions = {
triggeringSponsoredURL: extraOptions.getPropertyAsACString( "triggeringSponsoredURL"
),
}; if (extraOptions.hasKey("triggeringSponsoredURLVisitTimeMS")) {
globalHistoryOptions.triggeringSponsoredURLVisitTimeMS =
extraOptions.getPropertyAsUint64( "triggeringSponsoredURLVisitTimeMS"
);
}
} if (extraOptions.hasKey("triggeringRemoteType")) {
triggeringRemoteType = extraOptions.getPropertyAsACString( "triggeringRemoteType"
);
} if (extraOptions.hasKey("forceAllowDataURI")) {
forceAllowDataURI =
extraOptions.getPropertyAsBool("forceAllowDataURI");
} if (extraOptions.hasKey("schemelessInput")) {
schemelessInput =
extraOptions.getPropertyAsUint32("schemelessInput");
}
}
try {
openLinkIn(uriToLoad, "current", {
referrerInfo: window.arguments[2] || null,
postData: window.arguments[3] || null,
allowThirdPartyFixup: window.arguments[4] || false,
userContextId, // pass the origin principal (if any) and force its use to create // an initial about:blank viewer if present:
originPrincipal: window.arguments[6],
originStoragePrincipal: window.arguments[7],
triggeringPrincipal: window.arguments[8], // TODO fix allowInheritPrincipal to default to false. // Default to true unless explicitly set to false because of bug 1475201.
allowInheritPrincipal: window.arguments[9] !== false,
csp: window.arguments[10],
forceAboutBlankViewerInCurrent: !!window.arguments[6],
forceAllowDataURI,
hasValidUserGestureActivation,
fromExternal,
globalHistoryOptions,
triggeringRemoteType,
schemelessInput,
});
} catch (e) {
console.error(e);
}
window.focus();
} else { // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3. // Such callers expect that window.arguments[0] is handled as a single URI.
loadOneOrMoreURIs(
uriToLoad,
Services.scriptSecurityManager.getSystemPrincipal(), null
);
}
});
},
/** * Use this function as an entry point to schedule tasks that * need to run once per window after startup, and can be scheduled * by using an idle callback. * * The functions scheduled here will fire from idle callbacks * once every window has finished being restored by session * restore, and after the equivalent only-once tasks * have run (from _scheduleStartupIdleTasks in BrowserGlue.sys.mjs).
*/
_schedulePerWindowIdleTasks() { // Bail out if the window has been closed in the meantime. if (window.closed) { return;
}
function scheduleIdleTask(func, options) {
requestIdleCallback(function idleTaskRunner() { if (!window.closed) {
func();
}
}, options);
}
scheduleIdleTask(() => { // Initialize the Sync UI
gSync.init();
});
scheduleIdleTask(
() => { // Initialize the download manager some time after the app starts so that // auto-resume downloads begin (such as after crashing or quitting with // active downloads) and speeds up the first-load of the download manager UI. // If the user manually opens the download manager before the timeout, the // downloads will start right away, and initializing again won't hurt. try {
DownloadsCommon.initializeAllDataLinks();
ChromeUtils.importESModule( "resource:///modules/DownloadsTaskbar.sys.mjs"
).DownloadsTaskbar.registerIndicator(window); if (AppConstants.platform == "macosx") {
ChromeUtils.importESModule( "resource:///modules/DownloadsMacFinderProgress.sys.mjs"
).DownloadsMacFinderProgress.register();
}
} catch (ex) {
console.error(ex);
}
},
{ timeout: 10000 }
);
if (Win7Features) {
scheduleIdleTask(() => Win7Features.onOpenWindow());
}
// This should always go last, since the idle tasks (except for the ones with // 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.resolve();
Services.obs.notifyObservers(
window, "browser-idle-startup-tasks-finished"
);
});
},
// Returns the URI(s) to load at startup if it is immediately known, or a // promise resolving to the URI to load.
get uriToLoadPromise() { deletethis.uriToLoadPromise; return (this.uriToLoadPromise = (function () { // window.arguments[0]: URI to load (string), or an nsIArray of // nsISupportsStrings to load, or a xul:tab of // a tabbrowser, which will be replaced by this // window (for this case, all other arguments are // ignored).
let uri = window.arguments?.[0]; if (!uri || window.XULElement.isInstance(uri)) { returnnull;
}
let defaultArgs = BrowserHandler.defaultArgs;
// If the given URI is different from the homepage, we want to load it. if (uri != defaultArgs) {
AboutNewTab.noteNonDefaultStartup();
if (uri instanceof Ci.nsIArray) { // Transform the nsIArray of nsISupportsString's into a JS Array of // JS strings. return Array.from(
uri.enumerate(Ci.nsISupportsString),
supportStr => supportStr.data
);
} elseif (uri instanceof Ci.nsISupportsString) { return uri.data;
} return uri;
}
// The URI appears to be the the homepage. We want to load it only if // session restore isn't about to override the homepage.
let willOverride = SessionStartup.willOverrideHomepage; if (typeof willOverride == "boolean") { return willOverride ? null : uri;
} return willOverride.then(willOverrideHomepage =>
willOverrideHomepage ? null : uri
);
})());
},
// Calls the given callback with the URI to load at startup. // Synchronously if possible, or after uriToLoadPromise resolves otherwise.
_callWithURIToLoad(callback) {
let uriToLoad = this.uriToLoadPromise; if (uriToLoad && uriToLoad.then) {
uriToLoad.then(callback);
} else {
callback(uriToLoad);
}
},
onUnload() {
gUIDensity.uninit();
CustomTitlebar.uninit();
ToolbarIconColor.uninit();
// In certain scenarios it's possible for unload to be fired before onload, // (e.g. if the window is being closed after browser.js loads but before the // load completes). In that case, there's nothing to do here. if (!this._loadHandled) { return;
}
// First clean up services initialized in gBrowserInit.onLoad (or those whose // uninit methods don't depend on the services having been initialized).
// Now either cancel delayedStartup, or clean up the services initialized from // it. if (this._boundDelayedStartup) { this._cancelDelayedStartup();
} else { if (Win7Features) {
Win7Features.onCloseWindow();
}
Services.prefs.removeObserver(ctrlTab.prefName, ctrlTab);
ctrlTab.uninit();
gBrowserThumbnails.uninit();
gProtectionsHandler.uninit();
FullZoom.destroy();
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.