diff options
author | Thomas Groman <tgroman@nuegia.net> | 2019-12-16 19:48:42 -0800 |
---|---|---|
committer | Thomas Groman <tgroman@nuegia.net> | 2019-12-16 19:48:42 -0800 |
commit | 4492b5f8e774bf3b4f21e4e468fc052cbcbb468a (patch) | |
tree | 37970571a7dcbeb6b58c991ce718ce7001ac97d6 /components/fuel | |
download | webbrowser-4492b5f8e774bf3b4f21e4e468fc052cbcbb468a.tar webbrowser-4492b5f8e774bf3b4f21e4e468fc052cbcbb468a.tar.gz webbrowser-4492b5f8e774bf3b4f21e4e468fc052cbcbb468a.tar.lz webbrowser-4492b5f8e774bf3b4f21e4e468fc052cbcbb468a.tar.xz webbrowser-4492b5f8e774bf3b4f21e4e468fc052cbcbb468a.zip |
initial commit
Diffstat (limited to 'components/fuel')
-rw-r--r-- | components/fuel/fuelApplication.js | 822 | ||||
-rw-r--r-- | components/fuel/fuelApplication.manifest | 3 | ||||
-rw-r--r-- | components/fuel/fuelIApplication.idl | 347 | ||||
-rw-r--r-- | components/fuel/moz.build | 14 |
4 files changed, 1186 insertions, 0 deletions
diff --git a/components/fuel/fuelApplication.js b/components/fuel/fuelApplication.js new file mode 100644 index 0000000..bc3a091 --- /dev/null +++ b/components/fuel/fuelApplication.js @@ -0,0 +1,822 @@ +/* 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/. */ + +const Ci = Components.interfaces; +const Cc = Components.classes; + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Deprecated", + "resource://gre/modules/Deprecated.jsm"); + +const APPLICATION_CID = Components.ID("fe74cf80-aa2d-11db-abbd-0800200c9a66"); +const APPLICATION_CONTRACTID = "@mozilla.org/fuel/application;1"; + +//================================================= +// Singleton that holds services and utilities +var Utilities = { + get bookmarks() { + let bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]. + getService(Ci.nsINavBookmarksService); + this.__defineGetter__("bookmarks", function() bookmarks); + return this.bookmarks; + }, + + get bookmarksObserver() { + let bookmarksObserver = new BookmarksObserver(); + this.__defineGetter__("bookmarksObserver", function() bookmarksObserver); + return this.bookmarksObserver; + }, + + get annotations() { + let annotations = Cc["@mozilla.org/browser/annotation-service;1"]. + getService(Ci.nsIAnnotationService); + this.__defineGetter__("annotations", function() annotations); + return this.annotations; + }, + + get history() { + let history = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsINavHistoryService); + this.__defineGetter__("history", function() history); + return this.history; + }, + + get windowMediator() { + let windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"]. + getService(Ci.nsIWindowMediator); + this.__defineGetter__("windowMediator", function() windowMediator); + return this.windowMediator; + }, + + makeURI: function fuelutil_makeURI(aSpec) { + if (!aSpec) + return null; + var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); + return ios.newURI(aSpec, null, null); + }, + + free: function fuelutil_free() { + delete this.bookmarks; + delete this.bookmarksObserver; + delete this.annotations; + delete this.history; + delete this.windowMediator; + } +}; + + +//================================================= +// Window implementation + +var fuelWindowMap = new WeakMap(); +function getWindow(aWindow) { + let fuelWindow = fuelWindowMap.get(aWindow); + if (!fuelWindow) { + fuelWindow = new Window(aWindow); + fuelWindowMap.set(aWindow, fuelWindow); + } + return fuelWindow; +} + +// Don't call new Window() directly; use getWindow instead. +function Window(aWindow) { + this._window = aWindow; + this._events = new Events(); + + this._watch("TabOpen"); + this._watch("TabMove"); + this._watch("TabClose"); + this._watch("TabSelect"); +} + +Window.prototype = { + get events() { + return this._events; + }, + + get _tabbrowser() { + return this._window.getBrowser(); + }, + + /* + * Helper used to setup event handlers on the XBL element. Note that the events + * are actually dispatched to tabs, so we capture them. + */ + _watch: function win_watch(aType) { + this._tabbrowser.tabContainer.addEventListener(aType, this, + /* useCapture = */ true); + }, + + handleEvent: function win_handleEvent(aEvent) { + this._events.dispatch(aEvent.type, getBrowserTab(this, aEvent.originalTarget.linkedBrowser)); + }, + + get tabs() { + var tabs = []; + var browsers = this._tabbrowser.browsers; + for (var i=0; i<browsers.length; i++) + tabs.push(getBrowserTab(this, browsers[i])); + return tabs; + }, + + get activeTab() { + return getBrowserTab(this, this._tabbrowser.selectedBrowser); + }, + + open: function win_open(aURI) { + return getBrowserTab(this, this._tabbrowser.addTab(aURI.spec).linkedBrowser); + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.fuelIWindow]) +}; + +//================================================= +// BrowserTab implementation + +var fuelBrowserTabMap = new WeakMap(); +function getBrowserTab(aFUELWindow, aBrowser) { + let fuelBrowserTab = fuelBrowserTabMap.get(aBrowser); + if (!fuelBrowserTab) { + fuelBrowserTab = new BrowserTab(aFUELWindow, aBrowser); + fuelBrowserTabMap.set(aBrowser, fuelBrowserTab); + } + else { + // This tab may have moved to another window, so make sure its cached + // window is up-to-date. + fuelBrowserTab._window = aFUELWindow; + } + + return fuelBrowserTab; +} + +// Don't call new BrowserTab() directly; call getBrowserTab instead. +function BrowserTab(aFUELWindow, aBrowser) { + this._window = aFUELWindow; + this._browser = aBrowser; + this._events = new Events(); + + this._watch("load"); +} + +BrowserTab.prototype = { + get _tabbrowser() { + return this._window._tabbrowser; + }, + + get uri() { + return this._browser.currentURI; + }, + + get index() { + var tabs = this._tabbrowser.tabs; + for (var i=0; i<tabs.length; i++) { + if (tabs[i].linkedBrowser == this._browser) + return i; + } + return -1; + }, + + get events() { + return this._events; + }, + + get window() { + return this._window; + }, + + get document() { + return this._browser.contentDocument; + }, + + /* + * Helper used to setup event handlers on the XBL element + */ + _watch: function bt_watch(aType) { + this._browser.addEventListener(aType, this, + /* useCapture = */ true); + }, + + handleEvent: function bt_handleEvent(aEvent) { + if (aEvent.type == "load") { + if (!(aEvent.originalTarget instanceof Ci.nsIDOMDocument)) + return; + + if (aEvent.originalTarget.defaultView instanceof Ci.nsIDOMWindow && + aEvent.originalTarget.defaultView.frameElement) + return; + } + this._events.dispatch(aEvent.type, this); + }, + /* + * Helper used to determine the index offset of the browsertab + */ + _getTab: function bt_gettab() { + var tabs = this._tabbrowser.tabs; + return tabs[this.index] || null; + }, + + load: function bt_load(aURI) { + this._browser.loadURI(aURI.spec, null, null); + }, + + focus: function bt_focus() { + this._tabbrowser.selectedTab = this._getTab(); + this._tabbrowser.focus(); + }, + + close: function bt_close() { + this._tabbrowser.removeTab(this._getTab()); + }, + + moveBefore: function bt_movebefore(aBefore) { + this._tabbrowser.moveTabTo(this._getTab(), aBefore.index); + }, + + moveToEnd: function bt_moveend() { + this._tabbrowser.moveTabTo(this._getTab(), this._tabbrowser.browsers.length); + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBrowserTab]) +}; + + +//================================================= +// Annotations implementation +function Annotations(aId) { + this._id = aId; +} + +Annotations.prototype = { + get names() { + return Utilities.annotations.getItemAnnotationNames(this._id); + }, + + has: function ann_has(aName) { + return Utilities.annotations.itemHasAnnotation(this._id, aName); + }, + + get: function ann_get(aName) { + if (this.has(aName)) + return Utilities.annotations.getItemAnnotation(this._id, aName); + return null; + }, + + set: function ann_set(aName, aValue, aExpiration) { + Utilities.annotations.setItemAnnotation(this._id, aName, aValue, 0, aExpiration); + }, + + remove: function ann_remove(aName) { + if (aName) + Utilities.annotations.removeItemAnnotation(this._id, aName); + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.fuelIAnnotations]) +}; + + +//================================================= +// BookmarksObserver implementation (internal class) +// +// BookmarksObserver is a global singleton which watches the browser's +// bookmarks and sends you events when things change. +// +// You can register three different kinds of event listeners on +// BookmarksObserver, using addListener, addFolderListener, and +// addRootlistener. +// +// - addListener(aId, aEvent, aListener) lets you listen to a specific +// bookmark. You can listen to the "change", "move", and "remove" events. +// +// - addFolderListener(aId, aEvent, aListener) lets you listen to a specific +// bookmark folder. You can listen to "addchild" and "removechild". +// +// - addRootListener(aEvent, aListener) lets you listen to the root bookmark +// node. This lets you hear "add", "remove", and "change" events on all +// bookmarks. +// + +function BookmarksObserver() { + this._eventsDict = {}; + this._folderEventsDict = {}; + this._rootEvents = new Events(); + Utilities.bookmarks.addObserver(this, /* ownsWeak = */ true); +} + +BookmarksObserver.prototype = { + onBeginUpdateBatch: function () {}, + onEndUpdateBatch: function () {}, + onItemVisited: function () {}, + + onItemAdded: function bo_onItemAdded(aId, aFolder, aIndex, aItemType, aURI) { + this._rootEvents.dispatch("add", aId); + this._dispatchToEvents("addchild", aId, this._folderEventsDict[aFolder]); + }, + + onItemRemoved: function bo_onItemRemoved(aId, aFolder, aIndex) { + this._rootEvents.dispatch("remove", aId); + this._dispatchToEvents("remove", aId, this._eventsDict[aId]); + this._dispatchToEvents("removechild", aId, this._folderEventsDict[aFolder]); + }, + + onItemChanged: function bo_onItemChanged(aId, aProperty, aIsAnnotationProperty, aValue) { + this._rootEvents.dispatch("change", aProperty); + this._dispatchToEvents("change", aProperty, this._eventsDict[aId]); + }, + + onItemMoved: function bo_onItemMoved(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) { + this._dispatchToEvents("move", aId, this._eventsDict[aId]); + }, + + _dispatchToEvents: function bo_dispatchToEvents(aEvent, aData, aEvents) { + if (aEvents) { + aEvents.dispatch(aEvent, aData); + } + }, + + _addListenerToDict: function bo_addListenerToDict(aId, aEvent, aListener, aDict) { + var events = aDict[aId]; + if (!events) { + events = new Events(); + aDict[aId] = events; + } + events.addListener(aEvent, aListener); + }, + + _removeListenerFromDict: function bo_removeListenerFromDict(aId, aEvent, aListener, aDict) { + var events = aDict[aId]; + if (!events) { + return; + } + events.removeListener(aEvent, aListener); + if (events._listeners.length == 0) { + delete aDict[aId]; + } + }, + + addListener: function bo_addListener(aId, aEvent, aListener) { + this._addListenerToDict(aId, aEvent, aListener, this._eventsDict); + }, + + removeListener: function bo_removeListener(aId, aEvent, aListener) { + this._removeListenerFromDict(aId, aEvent, aListener, this._eventsDict); + }, + + addFolderListener: function addFolderListener(aId, aEvent, aListener) { + this._addListenerToDict(aId, aEvent, aListener, this._folderEventsDict); + }, + + removeFolderListener: function removeFolderListener(aId, aEvent, aListener) { + this._removeListenerFromDict(aId, aEvent, aListener, this._folderEventsDict); + }, + + addRootListener: function addRootListener(aEvent, aListener) { + this._rootEvents.addListener(aEvent, aListener); + }, + + removeRootListener: function removeRootListener(aEvent, aListener) { + this._rootEvents.removeListener(aEvent, aListener); + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarksObserver, + Ci.nsISupportsWeakReference]) +}; + +//================================================= +// Bookmark implementation +// +// Bookmark event listeners are stored in BookmarksObserver, not in the +// Bookmark objects themselves. Thus, you don't have to hold on to a Bookmark +// object in order for your event listener to stay valid, and Bookmark objects +// not kept alive by the extension can be GC'ed. +// +// A consequence of this is that if you have two different Bookmark objects x +// and y for the same bookmark (i.e., x != y but x.id == y.id), and you do +// +// x.addListener("foo", fun); +// y.removeListener("foo", fun); +// +// the second line will in fact remove the listener added in the first line. +// + +function Bookmark(aId, aParent, aType) { + this._id = aId; + this._parent = aParent; + this._type = aType || "bookmark"; + this._annotations = new Annotations(this._id); + + // Our _events object forwards to bookmarksObserver. + var self = this; + this._events = { + addListener: function bookmarkevents_al(aEvent, aListener) { + Utilities.bookmarksObserver.addListener(self._id, aEvent, aListener); + }, + removeListener: function bookmarkevents_rl(aEvent, aListener) { + Utilities.bookmarksObserver.removeListener(self._id, aEvent, aListener); + }, + QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents]) + }; + + // For our onItemMoved listener, which updates this._parent. + Utilities.bookmarks.addObserver(this, /* ownsWeak = */ true); +} + +Bookmark.prototype = { + get id() { + return this._id; + }, + + get title() { + return Utilities.bookmarks.getItemTitle(this._id); + }, + + set title(aTitle) { + Utilities.bookmarks.setItemTitle(this._id, aTitle); + }, + + get uri() { + return Utilities.bookmarks.getBookmarkURI(this._id); + }, + + set uri(aURI) { + return Utilities.bookmarks.changeBookmarkURI(this._id, aURI); + }, + + get description() { + return this._annotations.get("bookmarkProperties/description"); + }, + + set description(aDesc) { + this._annotations.set("bookmarkProperties/description", aDesc, Ci.nsIAnnotationService.EXPIRE_NEVER); + }, + + get keyword() { + return Utilities.bookmarks.getKeywordForBookmark(this._id); + }, + + set keyword(aKeyword) { + Utilities.bookmarks.setKeywordForBookmark(this._id, aKeyword); + }, + + get type() { + return this._type; + }, + + get parent() { + return this._parent; + }, + + set parent(aFolder) { + Utilities.bookmarks.moveItem(this._id, aFolder.id, Utilities.bookmarks.DEFAULT_INDEX); + // this._parent is updated in onItemMoved + }, + + get annotations() { + return this._annotations; + }, + + get events() { + return this._events; + }, + + remove : function bm_remove() { + Utilities.bookmarks.removeItem(this._id); + }, + + onBeginUpdateBatch: function () {}, + onEndUpdateBatch: function () {}, + onItemAdded: function () {}, + onItemVisited: function () {}, + onItemRemoved: function () {}, + onItemChanged: function () {}, + + onItemMoved: function(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) { + if (aId == this._id) { + this._parent = new BookmarkFolder(aNewParent, Utilities.bookmarks.getFolderIdForItem(aNewParent)); + } + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBookmark, + Ci.nsINavBookmarksObserver, + Ci.nsISupportsWeakReference]) +}; + + +//================================================= +// BookmarkFolder implementation +// +// As with Bookmark, events on BookmarkFolder are handled by the +// BookmarksObserver singleton. +// + +function BookmarkFolder(aId, aParent) { + this._id = aId; + this._parent = aParent; + this._annotations = new Annotations(this._id); + + // Our event listeners are handled by the BookmarksObserver singleton. This + // is a bit complicated because there are three different kinds of events we + // might want to listen to here: + // + // - If this._parent is null, we're the root bookmark folder, and all our + // listeners should be root listeners. + // + // - Otherwise, events ending with "child" (addchild, removechild) are + // handled by a folder listener. + // + // - Other events are handled by a vanilla bookmark listener. + + var self = this; + this._events = { + addListener: function bmfevents_al(aEvent, aListener) { + if (self._parent) { + if (/child$/.test(aEvent)) { + Utilities.bookmarksObserver.addFolderListener(self._id, aEvent, aListener); + } + else { + Utilities.bookmarksObserver.addListener(self._id, aEvent, aListener); + } + } + else { + Utilities.bookmarksObserver.addRootListener(aEvent, aListener); + } + }, + removeListener: function bmfevents_rl(aEvent, aListener) { + if (self._parent) { + if (/child$/.test(aEvent)) { + Utilities.bookmarksObserver.removeFolderListener(self._id, aEvent, aListener); + } + else { + Utilities.bookmarksObserver.removeListener(self._id, aEvent, aListener); + } + } + else { + Utilities.bookmarksObserver.removeRootListener(aEvent, aListener); + } + }, + QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents]) + }; + + // For our onItemMoved listener, which updates this._parent. + Utilities.bookmarks.addObserver(this, /* ownsWeak = */ true); +} + +BookmarkFolder.prototype = { + get id() { + return this._id; + }, + + get title() { + return Utilities.bookmarks.getItemTitle(this._id); + }, + + set title(aTitle) { + Utilities.bookmarks.setItemTitle(this._id, aTitle); + }, + + get description() { + return this._annotations.get("bookmarkProperties/description"); + }, + + set description(aDesc) { + this._annotations.set("bookmarkProperties/description", aDesc, Ci.nsIAnnotationService.EXPIRE_NEVER); + }, + + get type() { + return "folder"; + }, + + get parent() { + return this._parent; + }, + + set parent(aFolder) { + Utilities.bookmarks.moveItem(this._id, aFolder.id, Utilities.bookmarks.DEFAULT_INDEX); + // this._parent is updated in onItemMoved + }, + + get annotations() { + return this._annotations; + }, + + get events() { + return this._events; + }, + + get children() { + var items = []; + + var options = Utilities.history.getNewQueryOptions(); + var query = Utilities.history.getNewQuery(); + query.setFolders([this._id], 1); + var result = Utilities.history.executeQuery(query, options); + var rootNode = result.root; + rootNode.containerOpen = true; + var cc = rootNode.childCount; + for (var i=0; i<cc; ++i) { + var node = rootNode.getChild(i); + if (node.type == node.RESULT_TYPE_FOLDER) { + var folder = new BookmarkFolder(node.itemId, this._id); + items.push(folder); + } + else if (node.type == node.RESULT_TYPE_SEPARATOR) { + var separator = new Bookmark(node.itemId, this._id, "separator"); + items.push(separator); + } + else { + var bookmark = new Bookmark(node.itemId, this._id, "bookmark"); + items.push(bookmark); + } + } + rootNode.containerOpen = false; + + return items; + }, + + addBookmark: function bmf_addbm(aTitle, aUri) { + var newBookmarkID = Utilities.bookmarks.insertBookmark(this._id, aUri, Utilities.bookmarks.DEFAULT_INDEX, aTitle); + var newBookmark = new Bookmark(newBookmarkID, this, "bookmark"); + return newBookmark; + }, + + addSeparator: function bmf_addsep() { + var newBookmarkID = Utilities.bookmarks.insertSeparator(this._id, Utilities.bookmarks.DEFAULT_INDEX); + var newBookmark = new Bookmark(newBookmarkID, this, "separator"); + return newBookmark; + }, + + addFolder: function bmf_addfolder(aTitle) { + var newFolderID = Utilities.bookmarks.createFolder(this._id, aTitle, Utilities.bookmarks.DEFAULT_INDEX); + var newFolder = new BookmarkFolder(newFolderID, this); + return newFolder; + }, + + remove: function bmf_remove() { + Utilities.bookmarks.removeItem(this._id); + }, + + // observer + onBeginUpdateBatch: function () {}, + onEndUpdateBatch : function () {}, + onItemAdded : function () {}, + onItemRemoved : function () {}, + onItemChanged : function () {}, + + onItemMoved: function bf_onItemMoved(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) { + if (this._id == aId) { + this._parent = new BookmarkFolder(aNewParent, Utilities.bookmarks.getFolderIdForItem(aNewParent)); + } + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBookmarkFolder, + Ci.nsINavBookmarksObserver, + Ci.nsISupportsWeakReference]) +}; + +//================================================= +// BookmarkRoots implementation +function BookmarkRoots() { +} + +BookmarkRoots.prototype = { + get menu() { + if (!this._menu) + this._menu = new BookmarkFolder(Utilities.bookmarks.bookmarksMenuFolder, null); + + return this._menu; + }, + + get toolbar() { + if (!this._toolbar) + this._toolbar = new BookmarkFolder(Utilities.bookmarks.toolbarFolder, null); + + return this._toolbar; + }, + + get tags() { + if (!this._tags) + this._tags = new BookmarkFolder(Utilities.bookmarks.tagsFolder, null); + + return this._tags; + }, + + get unfiled() { + if (!this._unfiled) + this._unfiled = new BookmarkFolder(Utilities.bookmarks.unfiledBookmarksFolder, null); + + return this._unfiled; + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.fuelIBookmarkRoots]) +}; + + +//================================================= +// Factory - Treat Application as a singleton +// XXX This is required, because we're registered for the 'JavaScript global +// privileged property' category, whose handler always calls createInstance. +// See bug 386535. +var gSingleton = null; +var ApplicationFactory = { + createInstance: function af_ci(aOuter, aIID) { + if (aOuter != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + + if (gSingleton == null) { + gSingleton = new Application(); + } + + return gSingleton.QueryInterface(aIID); + } +}; + + +#include ../../../../toolkit/components/exthelper/extApplication.js + +//================================================= +// Application constructor +function Application() { + Deprecated.warning("FUEL is deprecated, you should use the standard Toolkit API instead.", + "https://github.com/MoonchildProductions/UXP/issues/1083"); + this.initToolkitHelpers(); +} + +//================================================= +// Application implementation +function ApplicationPrototype() { + // for nsIClassInfo + XPCOMUtils + this.classID = APPLICATION_CID; + + // redefine the default factory for XPCOMUtils + this._xpcom_factory = ApplicationFactory; + + // for nsISupports + this.QueryInterface = XPCOMUtils.generateQI([ + Ci.fuelIApplication, + Ci.extIApplication, + Ci.nsIObserver, + Ci.nsISupportsWeakReference + ]); + + // for nsIClassInfo + this.classInfo = XPCOMUtils.generateCI({ + classID: APPLICATION_CID, + contractID: APPLICATION_CONTRACTID, + interfaces: [ + Ci.fuelIApplication, + Ci.extIApplication, + Ci.nsIObserver + ], + flags: Ci.nsIClassInfo.SINGLETON + }); + + // for nsIObserver + this.observe = function (aSubject, aTopic, aData) { + // Call the extApplication version of this function first + var superPrototype = Object.getPrototypeOf(Object.getPrototypeOf(this)); + superPrototype.observe.call(this, aSubject, aTopic, aData); + if (aTopic == "xpcom-shutdown") { + this._obs.removeObserver(this, "xpcom-shutdown"); + Utilities.free(); + } + }; + + Object.defineProperty(this, "bookmarks", { + get: function bookmarks () { + let bookmarks = new BookmarkRoots(); + Object.defineProperty(this, "bookmarks", { value: bookmarks }); + return this.bookmarks; + }, + enumerable: true, + configurable: true + }); + + Object.defineProperty(this, "windows", { + get: function windows() { + var win = []; + var browserEnum = Utilities.windowMediator.getEnumerator("navigator:browser"); + + while (browserEnum.hasMoreElements()) + win.push(getWindow(browserEnum.getNext())); + + return win; + }, + enumerable: true, + configurable: true + }); + + Object.defineProperty(this, "activeWindow", { + get: () => getWindow(Utilities.windowMediator.getMostRecentWindow("navigator:browser")), + enumerable: true, + configurable: true + }); + +}; + +// set the proto, defined in extApplication.js +ApplicationPrototype.prototype = extApplication.prototype; + +Application.prototype = new ApplicationPrototype(); + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Application]); + diff --git a/components/fuel/fuelApplication.manifest b/components/fuel/fuelApplication.manifest new file mode 100644 index 0000000..67e6d0f --- /dev/null +++ b/components/fuel/fuelApplication.manifest @@ -0,0 +1,3 @@ +component {fe74cf80-aa2d-11db-abbd-0800200c9a66} fuelApplication.js +contract @mozilla.org/fuel/application;1 {fe74cf80-aa2d-11db-abbd-0800200c9a66} +category JavaScript-global-privileged-property Application @mozilla.org/fuel/application;1 diff --git a/components/fuel/fuelIApplication.idl b/components/fuel/fuelIApplication.idl new file mode 100644 index 0000000..69b51b0 --- /dev/null +++ b/components/fuel/fuelIApplication.idl @@ -0,0 +1,347 @@ +/* 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/. */ + +#include "nsISupports.idl" +#include "extIApplication.idl" + +interface nsIVariant; +interface nsIURI; +interface nsIDOMHTMLDocument; + +interface fuelIBookmarkFolder; +interface fuelIBrowserTab; + +/** + * Interface representing a collection of annotations associated + * with a bookmark or bookmark folder. + */ +[scriptable, uuid(335c9292-91a1-4ca0-ad0b-07d5f63ed6cd)] +interface fuelIAnnotations : nsISupports +{ + /** + * Array of the annotation names associated with the owning item + */ + readonly attribute nsIVariant names; + + /** + * Determines if an annotation exists with the given name. + * @param aName + * The name of the annotation + * @returns true if an annotation exists with the given name, + * false otherwise. + */ + boolean has(in AString aName); + + /** + * Gets the value of an annotation with the given name. + * @param aName + * The name of the annotation + * @returns A variant containing the value of the annotation. Supports + * string, boolean and number. + */ + nsIVariant get(in AString aName); + + /** + * Sets the value of an annotation with the given name. + * @param aName + * The name of the annotation + * @param aValue + * The new value of the annotation. Supports string, boolean + * and number + * @param aExpiration + * The expiration policy for the annotation. + * See nsIAnnotationService. + */ + void set(in AString aName, in nsIVariant aValue, in int32_t aExpiration); + + /** + * Removes the named annotation from the owner item. + * @param aName + * The name of annotation. + */ + void remove(in AString aName); +}; + + +/** + * Interface representing a bookmark item. + */ +[scriptable, uuid(808585b6-7568-4b26-8c62-545221bf2b8c)] +interface fuelIBookmark : nsISupports +{ + /** + * The id of the bookmark. + */ + readonly attribute long long id; + + /** + * The title of the bookmark. + */ + attribute AString title; + + /** + * The uri of the bookmark. + */ + attribute nsIURI uri; + + /** + * The description of the bookmark. + */ + attribute AString description; + + /** + * The keyword associated with the bookmark. + */ + attribute AString keyword; + + /** + * The type of the bookmark. + * values: "bookmark", "separator" + */ + readonly attribute AString type; + + /** + * The parent folder of the bookmark. + */ + attribute fuelIBookmarkFolder parent; + + /** + * The annotations object for the bookmark. + */ + readonly attribute fuelIAnnotations annotations; + + /** + * The events object for the bookmark. + * supports: "remove", "change", "visit", "move" + */ + readonly attribute extIEvents events; + + /** + * Removes the item from the parent folder. Used to + * delete a bookmark or separator + */ + void remove(); +}; + + +/** + * Interface representing a bookmark folder. Folders + * can hold bookmarks, separators and other folders. + */ +[scriptable, uuid(9f42fe20-52de-4a55-8632-a459c7716aa0)] +interface fuelIBookmarkFolder : nsISupports +{ + /** + * The id of the folder. + */ + readonly attribute long long id; + + /** + * The title of the folder. + */ + attribute AString title; + + /** + * The description of the folder. + */ + attribute AString description; + + /** + * The type of the folder. + * values: "folder" + */ + readonly attribute AString type; + + /** + * The parent folder of the folder. + */ + attribute fuelIBookmarkFolder parent; + + /** + * The annotations object for the folder. + */ + readonly attribute fuelIAnnotations annotations; + + /** + * The events object for the folder. + * supports: "add", "addchild", "remove", "removechild", "change", "move" + */ + readonly attribute extIEvents events; + + /** + * Array of all bookmarks, separators and folders contained + * in this folder. + */ + readonly attribute nsIVariant children; + + /** + * Adds a new child bookmark to this folder. + * @param aTitle + * The title of bookmark. + * @param aURI + * The uri of bookmark. + */ + fuelIBookmark addBookmark(in AString aTitle, in nsIURI aURI); + + /** + * Adds a new child separator to this folder. + */ + fuelIBookmark addSeparator(); + + /** + * Adds a new child folder to this folder. + * @param aTitle + * The title of folder. + */ + fuelIBookmarkFolder addFolder(in AString aTitle); + + /** + * Removes the folder from the parent folder. + */ + void remove(); +}; + +/** + * Interface representing a container for bookmark roots. Roots + * are the top level parents for the various types of bookmarks in the system. + */ +[scriptable, uuid(c9a80870-eb3c-11dc-95ff-0800200c9a66)] +interface fuelIBookmarkRoots : nsISupports +{ + /** + * The folder for the 'bookmarks menu' root. + */ + readonly attribute fuelIBookmarkFolder menu; + + /** + * The folder for the 'personal toolbar' root. + */ + readonly attribute fuelIBookmarkFolder toolbar; + + /** + * The folder for the 'tags' root. + */ + readonly attribute fuelIBookmarkFolder tags; + + /** + * The folder for the 'unfiled bookmarks' root. + */ + readonly attribute fuelIBookmarkFolder unfiled; +}; + +/** + * Interface representing a browser window. + */ +[scriptable, uuid(207edb28-eb5e-424e-a862-b0e97C8de866)] +interface fuelIWindow : nsISupports +{ + /** + * A collection of browser tabs within the browser window. + */ + readonly attribute nsIVariant tabs; + + /** + * The currently-active tab within the browser window. + */ + readonly attribute fuelIBrowserTab activeTab; + + /** + * Open a new browser tab, pointing to the specified URI. + * @param aURI + * The uri to open the browser tab to + */ + fuelIBrowserTab open(in nsIURI aURI); + + /** + * The events object for the browser window. + * supports: "TabOpen", "TabClose", "TabMove", "TabSelect" + */ + readonly attribute extIEvents events; +}; + +/** + * Interface representing a browser tab. + */ +[scriptable, uuid(3073ceff-777c-41ce-9ace-ab37268147c1)] +interface fuelIBrowserTab : nsISupports +{ + /** + * The current uri of this tab. + */ + readonly attribute nsIURI uri; + + /** + * The current index of this tab in the browser window. + */ + readonly attribute int32_t index; + + /** + * The browser window that is holding the tab. + */ + readonly attribute fuelIWindow window; + + /** + * The content document of the browser tab. + */ + readonly attribute nsIDOMHTMLDocument document; + + /** + * The events object for the browser tab. + * supports: "load" + */ + readonly attribute extIEvents events; + + /** + * Load a new URI into this browser tab. + * @param aURI + * The uri to load into the browser tab + */ + void load(in nsIURI aURI); + + /** + * Give focus to this browser tab, and bring it to the front. + */ + void focus(); + + /** + * Close the browser tab. This may not actually close the tab + * as script may abort the close operation. + */ + void close(); + + /** + * Moves this browser tab before another browser tab within the window. + * @param aBefore + * The tab before which the target tab will be moved + */ + void moveBefore(in fuelIBrowserTab aBefore); + + /** + * Move this browser tab to the last tab within the window. + */ + void moveToEnd(); +}; + +/** + * Interface for managing and accessing the applications systems + */ +[scriptable, uuid(fe74cf80-aa2d-11db-abbd-0800200c9a66)] +interface fuelIApplication : extIApplication +{ + /** + * The root bookmarks object for the application. + * Contains all the bookmark roots in the system. + */ + readonly attribute fuelIBookmarkRoots bookmarks; + + /** + * An array of browser windows within the application. + */ + readonly attribute nsIVariant windows; + + /** + * The currently active browser window. + */ + readonly attribute fuelIWindow activeWindow; +}; diff --git a/components/fuel/moz.build b/components/fuel/moz.build new file mode 100644 index 0000000..5c468f2 --- /dev/null +++ b/components/fuel/moz.build @@ -0,0 +1,14 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +XPIDL_SOURCES += ['fuelIApplication.idl'] + +XPIDL_MODULE = 'fuel' + +EXTRA_COMPONENTS += ['fuelApplication.manifest'] + +EXTRA_PP_COMPONENTS += ['fuelApplication.js'] + |