summaryrefslogtreecommitdiffstats
path: root/toolkit/content/widgets/editor.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/content/widgets/editor.js')
-rw-r--r--toolkit/content/widgets/editor.js203
1 files changed, 203 insertions, 0 deletions
diff --git a/toolkit/content/widgets/editor.js b/toolkit/content/widgets/editor.js
new file mode 100644
index 0000000000..9e5ffb542e
--- /dev/null
+++ b/toolkit/content/widgets/editor.js
@@ -0,0 +1,203 @@
+/* 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`.
+{
+ /* globals XULFrameElement */
+
+ class MozEditor extends XULFrameElement {
+ connectedCallback() {
+ this._editorContentListener = {
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIURIContentListener",
+ "nsISupportsWeakReference",
+ ]),
+ doContent(contentType, isContentPreferred, request, contentHandler) {
+ return false;
+ },
+ isPreferred(contentType, desiredContentType) {
+ return false;
+ },
+ canHandleContent(contentType, isContentPreferred, desiredContentType) {
+ return false;
+ },
+ loadCookie: null,
+ parentContentListener: null,
+ };
+
+ this._finder = null;
+
+ this._fastFind = null;
+
+ this._lastSearchString = null;
+
+ // Make window editable immediately only
+ // if the "editortype" attribute is supplied
+ // This allows using same contentWindow for different editortypes,
+ // where the type is determined during the apps's window.onload handler.
+ if (this.editortype) {
+ this.makeEditable(this.editortype, true);
+ }
+ }
+
+ get finder() {
+ if (!this._finder) {
+ if (!this.docShell) {
+ return null;
+ }
+
+ let { Finder } = ChromeUtils.importESModule(
+ "resource://gre/modules/Finder.sys.mjs"
+ );
+ this._finder = new Finder(this.docShell);
+ }
+ return this._finder;
+ }
+
+ get fastFind() {
+ if (!this._fastFind) {
+ if (!("@mozilla.org/typeaheadfind;1" in Cc)) {
+ return null;
+ }
+
+ if (!this.docShell) {
+ return null;
+ }
+
+ this._fastFind = Cc["@mozilla.org/typeaheadfind;1"].createInstance(
+ Ci.nsITypeAheadFind
+ );
+ this._fastFind.init(this.docShell);
+ }
+ return this._fastFind;
+ }
+
+ set editortype(val) {
+ this.setAttribute("editortype", val);
+ }
+
+ get editortype() {
+ return this.getAttribute("editortype");
+ }
+
+ get currentURI() {
+ return this.webNavigation.currentURI;
+ }
+
+ get webBrowserFind() {
+ return this.docShell
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIWebBrowserFind);
+ }
+
+ get editingSession() {
+ return this.docShell.editingSession;
+ }
+
+ get commandManager() {
+ return this.webNavigation
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsICommandManager);
+ }
+
+ set fullZoom(val) {
+ this.browsingContext.fullZoom = val;
+ }
+
+ get fullZoom() {
+ return this.browsingContext.fullZoom;
+ }
+
+ set textZoom(val) {
+ this.browsingContext.textZoom = val;
+ }
+
+ get textZoom() {
+ return this.browsingContext.textZoom;
+ }
+
+ get isSyntheticDocument() {
+ return this.contentDocument.isSyntheticDocument;
+ }
+
+ get messageManager() {
+ if (this.frameLoader) {
+ return this.frameLoader.messageManager;
+ }
+ return null;
+ }
+
+ // Copied from toolkit/content/widgets/browser-custom-element.js.
+ // Send an asynchronous message to the remote child via an actor.
+ // Note: use this only for messages through an actor. For old-style
+ // messages, use the message manager.
+ // The value of the scope argument determines which browsing contexts
+ // are sent to:
+ // 'all' - send to actors associated with all descendant child frames.
+ // 'roots' - send only to actors associated with process roots.
+ // undefined/'' - send only to the top-level actor and not any descendants.
+ sendMessageToActor(messageName, args, actorName, scope) {
+ if (!this.frameLoader) {
+ return;
+ }
+
+ function sendToChildren(browsingContext, childScope) {
+ let windowGlobal = browsingContext.currentWindowGlobal;
+ // If 'roots' is set, only send if windowGlobal.isProcessRoot is true.
+ if (
+ windowGlobal &&
+ (childScope != "roots" || windowGlobal.isProcessRoot)
+ ) {
+ windowGlobal.getActor(actorName).sendAsyncMessage(messageName, args);
+ }
+
+ // Iterate as long as scope in assigned. Note that we use the original
+ // passed in scope, not childScope here.
+ if (scope) {
+ for (let context of browsingContext.children) {
+ sendToChildren(context, scope);
+ }
+ }
+ }
+
+ // Pass no second argument to always send to the top-level browsing context.
+ sendToChildren(this.browsingContext);
+ }
+
+ get outerWindowID() {
+ return this.docShell.outerWindowID;
+ }
+
+ makeEditable(editortype, waitForUrlLoad) {
+ let win = this.contentWindow;
+ this.editingSession.makeWindowEditable(
+ win,
+ editortype,
+ waitForUrlLoad,
+ true,
+ false
+ );
+ this.setAttribute("editortype", editortype);
+
+ this.docShell
+ .QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIURIContentListener).parentContentListener =
+ this._editorContentListener;
+ }
+
+ getEditor(containingWindow) {
+ return this.editingSession.getEditorForWindow(containingWindow);
+ }
+
+ getHTMLEditor(containingWindow) {
+ var editor = this.editingSession.getEditorForWindow(containingWindow);
+ return editor.QueryInterface(Ci.nsIHTMLEditor);
+ }
+ }
+
+ customElements.define("editor", MozEditor);
+}