gecko-dev/toolkit/modules/BrowserUtils.jsm

151 строка
4.4 KiB
JavaScript

/* -*- mode: js; 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/. */
"use strict";
var EXPORTED_SYMBOLS = ["BrowserUtils"];
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
var BrowserUtils = {
/**
* Return or create a principal with the content of one, and the originAttributes
* of an existing principal (e.g. on a docshell, where the originAttributes ought
* not to change, that is, we should keep the userContextId, privateBrowsingId,
* etc. the same when changing the principal).
*
* @param principal
* The principal whose content/null/system-ness we want.
* @param existingPrincipal
* The principal whose originAttributes we want, usually the current
* principal of a docshell.
* @return an nsIPrincipal that matches the content/null/system-ness of the first
* param, and the originAttributes of the second.
*/
principalWithMatchingOA(principal, existingPrincipal) {
// Don't care about system principals:
if (principal.isSystemPrincipal) {
return principal;
}
// If the originAttributes already match, just return the principal as-is.
if (existingPrincipal.originSuffix == principal.originSuffix) {
return principal;
}
let secMan = Services.scriptSecurityManager;
if (principal.isContentPrincipal) {
return secMan.principalWithOA(
principal,
existingPrincipal.originAttributes
);
}
if (principal.isNullPrincipal) {
return secMan.createNullPrincipal(existingPrincipal.originAttributes);
}
throw new Error(
"Can't change the originAttributes of an expanded principal!"
);
},
/**
* Returns true if |mimeType| is text-based, or false otherwise.
*
* @param mimeType
* The MIME type to check.
*/
mimeTypeIsTextBased(mimeType) {
return (
mimeType.startsWith("text/") ||
mimeType.endsWith("+xml") ||
mimeType == "application/x-javascript" ||
mimeType == "application/javascript" ||
mimeType == "application/json" ||
mimeType == "application/xml"
);
},
/**
* Returns true if we can show a find bar, including FAYT, for the specified
* document location. The location must not be in a blacklist of specific
* "about:" pages for which find is disabled.
*
* This can be called from the parent process or from content processes.
*/
canFindInPage(location) {
return (
!location.startsWith("about:addons") &&
!location.startsWith(
"chrome://mozapps/content/extensions/aboutaddons.html"
) &&
!location.startsWith("about:preferences")
);
},
isFindbarVisible(docShell) {
const FINDER_JSM = "resource://gre/modules/Finder.jsm";
return (
Cu.isModuleLoaded(FINDER_JSM) &&
ChromeUtils.import(FINDER_JSM).Finder.isFindbarVisible(docShell)
);
},
/**
* Returns a Promise which resolves when the given observer topic has been
* observed.
*
* @param {string} topic
* The topic to observe.
* @param {function(nsISupports, string)} [test]
* An optional test function which, when called with the
* observer's subject and data, should return true if this is the
* expected notification, false otherwise.
* @returns {Promise<object>}
*/
promiseObserved(topic, test = () => true) {
return new Promise(resolve => {
let observer = (subject, topic, data) => {
if (test(subject, data)) {
Services.obs.removeObserver(observer, topic);
resolve({ subject, data });
}
};
Services.obs.addObserver(observer, topic);
});
},
isShareableURL(url) {
if (!url) {
return false;
}
// Disallow sharing URLs with more than 65535 characters.
if (url.spec.length > 65535) {
return false;
}
let scheme = url.scheme;
return !(
"about" == scheme ||
"resource" == scheme ||
"chrome" == scheme ||
"blob" == scheme ||
"moz-extension" == scheme
);
},
};
XPCOMUtils.defineLazyPreferenceGetter(
BrowserUtils,
"navigationRequireUserInteraction",
"browser.navigation.requireUserInteraction",
false
);