mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 16:58:38 +09:00
Rename Toolkit's webextensions component directory to better reflect what it is.
This commit is contained in:
parent
6955450f7a
commit
d7d16e7fbb
242 changed files with 4 additions and 2 deletions
217
toolkit/components/webextensions/ext-browser-content.js
Normal file
217
toolkit/components/webextensions/ext-browser-content.js
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/* 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";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "clearTimeout",
|
||||
"resource://gre/modules/Timer.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "require",
|
||||
"resource://devtools/shared/Loader.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
|
||||
"resource://gre/modules/Timer.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "colorUtils", () => {
|
||||
return require("devtools/shared/css/color").colorUtils;
|
||||
});
|
||||
|
||||
const {
|
||||
stylesheetMap,
|
||||
} = ExtensionUtils;
|
||||
|
||||
/* globals addMessageListener, content, docShell, sendAsyncMessage */
|
||||
|
||||
// Minimum time between two resizes.
|
||||
const RESIZE_TIMEOUT = 100;
|
||||
|
||||
const BrowserListener = {
|
||||
init({allowScriptsToClose, fixedWidth, maxHeight, maxWidth, stylesheets}) {
|
||||
this.fixedWidth = fixedWidth;
|
||||
this.stylesheets = stylesheets || [];
|
||||
|
||||
this.maxWidth = maxWidth;
|
||||
this.maxHeight = maxHeight;
|
||||
|
||||
this.oldBackground = null;
|
||||
|
||||
if (allowScriptsToClose) {
|
||||
content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.allowScriptsToClose();
|
||||
}
|
||||
|
||||
addEventListener("DOMWindowCreated", this, true);
|
||||
addEventListener("load", this, true);
|
||||
addEventListener("DOMContentLoaded", this, true);
|
||||
addEventListener("DOMWindowClose", this, true);
|
||||
addEventListener("MozScrolledAreaChanged", this, true);
|
||||
},
|
||||
|
||||
destroy() {
|
||||
removeEventListener("DOMWindowCreated", this, true);
|
||||
removeEventListener("load", this, true);
|
||||
removeEventListener("DOMContentLoaded", this, true);
|
||||
removeEventListener("DOMWindowClose", this, true);
|
||||
removeEventListener("MozScrolledAreaChanged", this, true);
|
||||
},
|
||||
|
||||
receiveMessage({name, data}) {
|
||||
if (name === "Extension:InitBrowser") {
|
||||
this.init(data);
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "DOMWindowCreated":
|
||||
if (event.target === content.document) {
|
||||
let winUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
for (let url of this.stylesheets) {
|
||||
winUtils.addSheet(stylesheetMap.get(url), winUtils.AGENT_SHEET);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "DOMWindowClose":
|
||||
if (event.target === content) {
|
||||
event.preventDefault();
|
||||
|
||||
sendAsyncMessage("Extension:DOMWindowClose");
|
||||
}
|
||||
break;
|
||||
|
||||
case "DOMContentLoaded":
|
||||
if (event.target === content.document) {
|
||||
sendAsyncMessage("Extension:BrowserContentLoaded", {url: content.location.href});
|
||||
this.handleDOMChange(true);
|
||||
}
|
||||
break;
|
||||
|
||||
case "load":
|
||||
if (event.target.contentWindow === content) {
|
||||
// For about:addons inline <browsers>, we currently receive a load
|
||||
// event on the <browser> element, but no load or DOMContentLoaded
|
||||
// events from the content window.
|
||||
sendAsyncMessage("Extension:BrowserContentLoaded", {url: content.location.href});
|
||||
} else if (event.target !== content.document) {
|
||||
break;
|
||||
}
|
||||
|
||||
// We use a capturing listener, so we get this event earlier than any
|
||||
// load listeners in the content page. Resizing after a timeout ensures
|
||||
// that we calculate the size after the entire event cycle has completed
|
||||
// (unless someone spins the event loop, anyway), and hopefully after
|
||||
// the content has made any modifications.
|
||||
Promise.resolve().then(() => {
|
||||
this.handleDOMChange(true);
|
||||
});
|
||||
|
||||
// Mutation observer to make sure the panel shrinks when the content does.
|
||||
new content.MutationObserver(this.handleDOMChange.bind(this)).observe(
|
||||
content.document.documentElement, {
|
||||
attributes: true,
|
||||
characterData: true,
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
break;
|
||||
|
||||
case "MozScrolledAreaChanged":
|
||||
this.handleDOMChange();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// Resizes the browser to match the preferred size of the content (debounced).
|
||||
handleDOMChange(ignoreThrottling = false) {
|
||||
if (ignoreThrottling && this.resizeTimeout) {
|
||||
clearTimeout(this.resizeTimeout);
|
||||
this.resizeTimeout = null;
|
||||
}
|
||||
|
||||
if (this.resizeTimeout == null) {
|
||||
this.resizeTimeout = setTimeout(() => {
|
||||
try {
|
||||
if (content) {
|
||||
this._handleDOMChange("delayed");
|
||||
}
|
||||
} finally {
|
||||
this.resizeTimeout = null;
|
||||
}
|
||||
}, RESIZE_TIMEOUT);
|
||||
|
||||
this._handleDOMChange();
|
||||
}
|
||||
},
|
||||
|
||||
_handleDOMChange(detail) {
|
||||
let doc = content.document;
|
||||
|
||||
let body = doc.body;
|
||||
if (!body || doc.compatMode === "BackCompat") {
|
||||
// In quirks mode, the root element is used as the scroll frame, and the
|
||||
// body lies about its scroll geometry, and returns the values for the
|
||||
// root instead.
|
||||
body = doc.documentElement;
|
||||
}
|
||||
|
||||
|
||||
let result;
|
||||
if (this.fixedWidth) {
|
||||
// If we're in a fixed-width area (namely a slide-in subview of the main
|
||||
// menu panel), we need to calculate the view height based on the
|
||||
// preferred height of the content document's root scrollable element at the
|
||||
// current width, rather than the complete preferred dimensions of the
|
||||
// content window.
|
||||
|
||||
// Compensate for any offsets (margin, padding, ...) between the scroll
|
||||
// area of the body and the outer height of the document.
|
||||
let getHeight = elem => elem.getBoundingClientRect(elem).height;
|
||||
let bodyPadding = getHeight(doc.documentElement) - getHeight(body);
|
||||
|
||||
let height = Math.ceil(body.scrollHeight + bodyPadding);
|
||||
|
||||
result = {height, detail};
|
||||
} else {
|
||||
let background = doc.defaultView.getComputedStyle(body).backgroundColor;
|
||||
let bgColor = colorUtils.colorToRGBA(background);
|
||||
if (bgColor.a !== 1) {
|
||||
// Ignore non-opaque backgrounds.
|
||||
background = null;
|
||||
}
|
||||
|
||||
if (background !== this.oldBackground) {
|
||||
sendAsyncMessage("Extension:BrowserBackgroundChanged", {background});
|
||||
}
|
||||
this.oldBackground = background;
|
||||
|
||||
|
||||
// Adjust the size of the browser based on its content's preferred size.
|
||||
let {contentViewer} = docShell;
|
||||
let ratio = content.devicePixelRatio;
|
||||
|
||||
let w = {}, h = {};
|
||||
contentViewer.getContentSizeConstrained(this.maxWidth * ratio,
|
||||
this.maxHeight * ratio,
|
||||
w, h);
|
||||
|
||||
let width = Math.ceil(w.value / ratio);
|
||||
let height = Math.ceil(h.value / ratio);
|
||||
|
||||
result = {width, height, detail};
|
||||
}
|
||||
|
||||
sendAsyncMessage("Extension:BrowserResized", result);
|
||||
},
|
||||
};
|
||||
|
||||
addMessageListener("Extension:InitBrowser", BrowserListener);
|
||||
Loading…
Add table
Add a link
Reference in a new issue