--- a/browser/fuel/public/fuelIApplication.idl
+++ b/browser/fuel/public/fuelIApplication.idl
@@ -1,360 +1,56 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FUEL.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Finkle <mfinkle@mozilla.com> (Original Author)
+ * John Resig <jresig@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
#include "nsISupports.idl"
+#include "extIApplication.idl"
interface nsIVariant;
interface nsIURI;
interface nsIDOMHTMLDocument;
-interface fuelIPreference;
interface fuelIBookmarkFolder;
interface fuelIBrowserTab;
/**
- * Interface that gives simplified access to the console
- */
-[scriptable, uuid(ae8482e0-aa5a-11db-abbd-0800200c9a66)]
-interface fuelIConsole : nsISupports
-{
- /**
- * Sends a given string to the console.
- * @param aMsg
- * The text to send to the console
- */
- void log(in AString aMsg);
-
- /**
- * Opens the error console window. The console window
- * is focused if already open.
- */
- void open();
-};
-
-
-/**
- * Interface holds information about an event.
- */
-[scriptable, function, uuid(05281820-ab62-11db-abbd-0800200c9a66)]
-interface fuelIEventItem : nsISupports
-{
- /**
- * The name of the event
- */
- readonly attribute AString type;
-
- /**
- * Can hold extra details and data associated with the event. This
- * is optional and event specific. If the event does not send extra
- * details, this is null.
- */
- readonly attribute AString data;
-
- /**
- * Cancels the event if it is cancelable.
- */
- void preventDefault();
-};
-
-
-/**
- * Interface used as a callback for listening to events.
- */
-[scriptable, function, uuid(2dfe3a50-ab2f-11db-abbd-0800200c9a66)]
-interface fuelIEventListener : nsISupports
-{
- /**
- * This method is called whenever an event occurs of the type for which
- * the fuelIEventListener interface was registered.
- *
- * @param aEvent
- * The fuelIEventItem associated with the event.
- */
- void handleEvent(in fuelIEventItem aEvent);
-};
-
-
-/**
- * Interface for supporting custom events.
- */
-[scriptable, uuid(3a8ec9d0-ab19-11db-abbd-0800200c9a66)]
-interface fuelIEvents : nsISupports
-{
- /**
- * Adds an event listener to the list. If multiple identical event listeners
- * are registered on the same event target with the same parameters the
- * duplicate instances are discarded. They do not cause the EventListener
- * to be called twice and since they are discarded they do not need to be
- * removed with the removeListener method.
- *
- * @param aEvent
- * The name of an event
- * @param aListener
- * The reference to a listener
- */
- void addListener(in AString aEvent, in fuelIEventListener aListener);
-
- /**
- * Removes an event listener from the list. Calling remove
- * with arguments which do not identify any currently registered
- * event listener has no effect.
- * @param aEvent
- * The name of an event
- * @param aListener
- * The reference to a listener
- */
- void removeListener(in AString aEvent, in fuelIEventListener aListener);
-};
-
-
-/**
- * Interface for simplified access to preferences. The interface has a
- * predefined root preference branch. The root branch is set based on the
- * context of the owner. For example, an extension's preferences have a root
- * of "extensions.<extensionid>.", while the application level preferences
- * have an empty root. All preference "aName" parameters used in this interface
- * are relative to the root branch.
- */
-[scriptable, uuid(ce697d40-aa5a-11db-abbd-0800200c9a66)]
-interface fuelIPreferenceBranch : nsISupports
-{
- /**
- * The name of the branch root.
- */
- readonly attribute AString root;
-
- /**
- * Array of fuelIPreference listing all preferences in this branch.
- */
- readonly attribute nsIVariant all;
-
- /**
- * The events object for the preferences
- * supports: "change"
- */
- readonly attribute fuelIEvents events;
-
- /**
- * Check to see if a preference exists.
- * @param aName
- * The name of preference
- * @returns true if the preference exists, false if not
- */
- boolean has(in AString aName);
-
- /**
- * Gets an object representing a preference
- * @param aName
- * The name of preference
- * @returns a preference object, or null if the preference does not exist
- */
- fuelIPreference get(in AString aName);
-
- /**
- * Gets the value of a preference. Returns a default value if
- * the preference does not exist.
- * @param aName
- * The name of preference
- * @param aDefaultValue
- * The value to return if preference does not exist
- * @returns value of the preference or the given default value if preference
- * does not exists.
- */
- nsIVariant getValue(in AString aName, in nsIVariant aDefaultValue);
-
- /**
- * Sets the value of a storage item with the given name.
- * @param aName
- * The name of an item
- * @param aValue
- * The value to assign to the item
- */
- void setValue(in AString aName, in nsIVariant aValue);
-
- /**
- * Resets all preferences in a branch back to their default values.
- */
- void reset();
-};
-
-/**
- * Interface for accessing a single preference. The data is not cached.
- * All reads access the current state of the preference.
- */
-[scriptable, uuid(2C7462E2-72C2-4473-9007-0E6AE71E23CA)]
-interface fuelIPreference : nsISupports
-{
- /**
- * The name of the preference.
- */
- readonly attribute AString name;
-
- /**
- * A string representing the type of preference (String, Boolean, or Number).
- */
- readonly attribute AString type;
-
- /**
- * Get/Set the value of the preference.
- */
- attribute nsIVariant value;
-
- /**
- * Get the locked state of the preference. Set to a boolean value to (un)lock it.
- */
- attribute boolean locked;
-
- /**
- * Check if a preference has been modified by the user, or not.
- */
- readonly attribute boolean modified;
-
- /**
- * The preference branch that contains this preference.
- */
- readonly attribute fuelIPreferenceBranch branch;
-
- /**
- * The events object for this preference.
- * supports: "change"
- */
- readonly attribute fuelIEvents events;
-
- /**
- * Resets a preference back to its default values.
- */
- void reset();
-};
-
-
-/**
- * Interface representing a simple storage system
- */
-[scriptable, uuid(0787ac44-29b9-4889-b97f-13573aec6971)]
-interface fuelISessionStorage : nsISupports
-{
- /**
- * The events object for the storage
- * supports: "change"
- */
- readonly attribute fuelIEvents events;
-
- /**
- * Determines if a storage item exists with the given name.
- * @param aName
- * The name of an item
- * @returns true if an item exists with the given name,
- * false otherwise.
- */
- boolean has(in AString aName);
-
- /**
- * Sets the value of a storage item with the given name.
- * @param aName
- * The name of an item
- * @param aValue
- * The value to assign to the item
- */
- void set(in AString aName, in nsIVariant aValue);
-
- /**
- * Gets the value of a storage item with the given name. Returns a
- * default value if the item does not exist.
- * @param aName
- * The name of an item
- * @param aDefaultValue
- * The value to return if no item exists with the given name
- * @returns value of the item or the given default value if no item
- * exists with the given name.
- */
- nsIVariant get(in AString aName, in nsIVariant aDefaultValue);
-};
-
-
-/**
- * Interface representing an extension
- */
-[scriptable, uuid(10cee02c-f6e0-4d61-ab27-c16572b18c46)]
-interface fuelIExtension : nsISupports
-{
- /**
- * The id of the extension.
- */
- readonly attribute AString id;
-
- /**
- * The name of the extension.
- */
- readonly attribute AString name;
-
- /**
- * Check if the extension is currently enabled, or not.
- */
- readonly attribute boolean enabled;
-
- /**
- * The version number of the extension.
- */
- readonly attribute AString version;
-
- /**
- * Indicates whether this is the extension's first run after install
- */
- readonly attribute boolean firstRun;
-
- /**
- * The preferences object for the extension. Defaults to the
- * "extensions.<extensionid>." branch.
- */
- readonly attribute fuelIPreferenceBranch prefs;
-
- /**
- * The storage object for the extension.
- */
- readonly attribute fuelISessionStorage storage;
-
- /**
- * The events object for the extension.
- * supports: "uninstall"
- */
- readonly attribute fuelIEvents events;
-};
-
-
-/**
- * Interface representing a list of all installed extensions
- */
-[scriptable, uuid(de281930-aa5a-11db-abbd-0800200c9a66)]
-interface fuelIExtensions : nsISupports
-{
- /**
- * Array of fuelIExtension listing all extensions in the application.
- */
- readonly attribute nsIVariant all;
-
- /**
- * Determines if an extension exists with the given id.
- * @param aId
- * The id of an extension
- * @returns true if an extension exists with the given id,
- * false otherwise.
- */
- boolean has(in AString aId);
-
- /**
- * Gets a fuelIExtension object for an extension.
- * @param aId
- * The id of an extension
- * @returns An extension object or null if no extension exists
- * with the given id.
- */
- fuelIExtension get(in AString aId);
-};
-
-
-/**
* 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
@@ -447,17 +143,17 @@ interface fuelIBookmark : nsISupports
* The annotations object for the bookmark.
*/
readonly attribute fuelIAnnotations annotations;
/**
* The events object for the bookmark.
* supports: "remove", "change", "visit", "move"
*/
- readonly attribute fuelIEvents events;
+ readonly attribute extIEvents events;
/**
* Removes the item from the parent folder. Used to
* delete a bookmark or separator
*/
void remove();
};
@@ -499,17 +195,17 @@ interface fuelIBookmarkFolder : nsISuppo
* 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 fuelIEvents events;
+ readonly attribute extIEvents events;
/**
* Array of all bookmarks, separators and folders contained
* in this folder.
*/
readonly attribute nsIVariant children;
/**
@@ -562,17 +258,17 @@ interface fuelIWindow : nsISupports
* 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 fuelIEvents events;
+ readonly attribute extIEvents events;
};
/**
* Interface representing a browser tab.
*/
[scriptable, uuid(3073ceff-777c-41ce-9ace-ab37268147c1)]
interface fuelIBrowserTab : nsISupports
{
@@ -595,17 +291,17 @@ interface fuelIBrowserTab : nsISupports
* The content document of the browser tab.
*/
readonly attribute nsIDOMHTMLDocument document;
/**
* The events object for the browser tab.
* supports: "load"
*/
- readonly attribute fuelIEvents events;
+ 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);
@@ -628,67 +324,23 @@ interface fuelIBrowserTab : nsISupports
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 : nsISupports
+interface fuelIApplication : extIApplication
{
/**
- * The id of the application.
- */
- readonly attribute AString id;
-
- /**
- * The name of the application.
- */
- readonly attribute AString name;
-
- /**
- * The version number of the application.
- */
- readonly attribute AString version;
-
- /**
- * The console object for the application.
- */
- readonly attribute fuelIConsole console;
-
- /**
- * The extensions object for the application. Contains a list
- * of all installed extensions.
- */
- readonly attribute fuelIExtensions extensions;
-
- /**
- * The preferences object for the application. Defaults to an empty
- * root branch.
- */
- readonly attribute fuelIPreferenceBranch prefs;
-
- /**
- * The storage object for the application.
- */
- readonly attribute fuelISessionStorage storage;
-
- /**
- * The events object for the application.
- * supports: "load", "ready", "quit", "unload"
- */
- readonly attribute fuelIEvents events;
-
- /**
* The root bookmarks object for the application.
*/
readonly attribute fuelIBookmarkFolder bookmarks;
/**
* An array of browser windows within the application.
*/
readonly attribute nsIVariant windows;
--- a/browser/fuel/src/fuelApplication.js
+++ b/browser/fuel/src/fuelApplication.js
@@ -36,530 +36,16 @@
* ***** END LICENSE BLOCK ***** */
const Ci = Components.interfaces;
const Cc = Components.classes;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
//=================================================
-// Shutdown - used to store cleanup functions which will
-// be called on Application shutdown
-var gShutdown = [];
-
-//=================================================
-// Console constructor
-function Console() {
- this._console = Components.classes["@mozilla.org/consoleservice;1"]
- .getService(Ci.nsIConsoleService);
-}
-
-//=================================================
-// Console implementation
-Console.prototype = {
- log : function cs_log(aMsg) {
- this._console.logStringMessage(aMsg);
- },
-
- open : function cs_open() {
- var wMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Ci.nsIWindowMediator);
- var console = wMediator.getMostRecentWindow("global:console");
- if (!console) {
- var wWatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
- .getService(Ci.nsIWindowWatcher);
- wWatch.openWindow(null, "chrome://global/content/console.xul", "_blank",
- "chrome,dialog=no,all", null);
- } else {
- // console was already open
- console.focus();
- }
- },
-
- QueryInterface : XPCOMUtils.generateQI([Ci.fuelIConsole])
-};
-
-
-//=================================================
-// EventItem constructor
-function EventItem(aType, aData) {
- this._type = aType;
- this._data = aData;
-}
-
-//=================================================
-// EventItem implementation
-EventItem.prototype = {
- _cancel : false,
-
- get type() {
- return this._type;
- },
-
- get data() {
- return this._data;
- },
-
- preventDefault : function ei_pd() {
- this._cancel = true;
- },
-
- QueryInterface : XPCOMUtils.generateQI([Ci.fuelIEventItem])
-};
-
-
-//=================================================
-// Events constructor
-function Events() {
- this._listeners = [];
-}
-
-//=================================================
-// Events implementation
-Events.prototype = {
- addListener : function evts_al(aEvent, aListener) {
- if (this._listeners.some(hasFilter))
- return;
-
- this._listeners.push({
- event: aEvent,
- listener: aListener
- });
-
- function hasFilter(element) {
- return element.event == aEvent && element.listener == aListener;
- }
- },
-
- removeListener : function evts_rl(aEvent, aListener) {
- this._listeners = this._listeners.filter(function(element){
- return element.event != aEvent && element.listener != aListener;
- });
- },
-
- dispatch : function evts_dispatch(aEvent, aEventItem) {
- eventItem = new EventItem(aEvent, aEventItem);
-
- this._listeners.forEach(function(key){
- if (key.event == aEvent) {
- key.listener.handleEvent ?
- key.listener.handleEvent(eventItem) :
- key.listener(eventItem);
- }
- });
-
- return !eventItem._cancel;
- },
-
- QueryInterface : XPCOMUtils.generateQI([Ci.fuelIEvents])
-};
-
-
-//=================================================
-// PreferenceBranch constructor
-function PreferenceBranch(aBranch) {
- if (!aBranch)
- aBranch = "";
-
- this._root = aBranch;
- this._prefs = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Ci.nsIPrefService);
-
- if (aBranch)
- this._prefs = this._prefs.getBranch(aBranch);
-
- this._prefs.QueryInterface(Ci.nsIPrefBranch);
- this._prefs.QueryInterface(Ci.nsIPrefBranch2);
-
- // we want to listen to "all" changes for this branch, so pass in a blank domain
- this._prefs.addObserver("", this, true);
- this._events = new Events();
-
- var self = this;
- gShutdown.push(function() { self._shutdown(); });
-}
-
-//=================================================
-// PreferenceBranch implementation
-PreferenceBranch.prototype = {
- // cleanup observer so we don't leak
- _shutdown: function prefs_shutdown() {
- this._prefs.removeObserver(this._root, this);
-
- this._prefs = null;
- this._events = null;
- },
-
- // for nsIObserver
- observe: function prefs_observe(aSubject, aTopic, aData) {
- if (aTopic == "nsPref:changed")
- this._events.dispatch("change", aData);
- },
-
- get root() {
- return this._root;
- },
-
- get all() {
- return this.find({});
- },
-
- get events() {
- return this._events;
- },
-
- // XXX: Disabled until we can figure out the wrapped object issues
- // name: "name" or /name/
- // path: "foo.bar." or "" or /fo+\.bar/
- // type: Boolean, Number, String (getPrefType)
- // locked: true, false (prefIsLocked)
- // modified: true, false (prefHasUserValue)
- find : function prefs_find(aOptions) {
- var retVal = [];
- var items = this._prefs.getChildList("", []);
-
- for (var i = 0; i < items.length; i++) {
- retVal.push(new Preference(items[i], this));
- }
-
- return retVal;
- },
-
- has : function prefs_has(aName) {
- return (this._prefs.getPrefType(aName) != Ci.nsIPrefBranch.PREF_INVALID);
- },
-
- get : function prefs_get(aName) {
- return this.has(aName) ? new Preference(aName, this) : null;
- },
-
- getValue : function prefs_gv(aName, aValue) {
- var type = this._prefs.getPrefType(aName);
-
- switch (type) {
- case Ci.nsIPrefBranch2.PREF_STRING:
- aValue = this._prefs.getComplexValue(aName, Ci.nsISupportsString).data;
- break;
- case Ci.nsIPrefBranch2.PREF_BOOL:
- aValue = this._prefs.getBoolPref(aName);
- break;
- case Ci.nsIPrefBranch2.PREF_INT:
- aValue = this._prefs.getIntPref(aName);
- break;
- }
-
- return aValue;
- },
-
- setValue : function prefs_sv(aName, aValue) {
- var type = aValue != null ? aValue.constructor.name : "";
-
- switch (type) {
- case "String":
- var str = Components.classes["@mozilla.org/supports-string;1"]
- .createInstance(Ci.nsISupportsString);
- str.data = aValue;
- this._prefs.setComplexValue(aName, Ci.nsISupportsString, str);
- break;
- case "Boolean":
- this._prefs.setBoolPref(aName, aValue);
- break;
- case "Number":
- this._prefs.setIntPref(aName, aValue);
- break;
- default:
- throw("Unknown preference value specified.");
- }
- },
-
- reset : function prefs_reset() {
- this._prefs.resetBranch("");
- },
-
- QueryInterface : XPCOMUtils.generateQI([Ci.fuelIPreferenceBranch, Ci.nsISupportsWeakReference])
-};
-
-
-//=================================================
-// Preference constructor
-function Preference(aName, aBranch) {
- this._name = aName;
- this._branch = aBranch;
- this._events = new Events();
-
- var self = this;
-
- this.branch.events.addListener("change", function(aEvent){
- if (aEvent.data == self.name)
- self.events.dispatch(aEvent.type, aEvent.data);
- });
-}
-
-//=================================================
-// Preference implementation
-Preference.prototype = {
- get name() {
- return this._name;
- },
-
- get type() {
- var value = "";
- var type = this._prefs.getPrefType(name);
-
- switch (type) {
- case Ci.nsIPrefBranch2.PREF_STRING:
- value = "String";
- break;
- case Ci.nsIPrefBranch2.PREF_BOOL:
- value = "Boolean";
- break;
- case Ci.nsIPrefBranch2.PREF_INT:
- value = "Number";
- break;
- }
-
- return value;
- },
-
- get value() {
- return this.branch.getValue(this._name, null);
- },
-
- set value(aValue) {
- return this.branch.setValue(this._name, aValue);
- },
-
- get locked() {
- return this.branch._prefs.prefIsLocked(this.name);
- },
-
- set locked(aValue) {
- this.branch._prefs[ aValue ? "lockPref" : "unlockPref" ](this.name);
- },
-
- get modified() {
- return this.branch._prefs.prefHasUserValue(this.name);
- },
-
- get branch() {
- return this._branch;
- },
-
- get events() {
- return this._events;
- },
-
- reset : function pref_reset() {
- this.branch._prefs.clearUserPref(this.name);
- },
-
- QueryInterface : XPCOMUtils.generateQI([Ci.fuelIPreference])
-};
-
-
-//=================================================
-// SessionStorage constructor
-function SessionStorage() {
- this._storage = {};
- this._events = new Events();
-}
-
-//=================================================
-// SessionStorage implementation
-SessionStorage.prototype = {
- get events() {
- return this._events;
- },
-
- has : function ss_has(aName) {
- return this._storage.hasOwnProperty(aName);
- },
-
- set : function ss_set(aName, aValue) {
- this._storage[aName] = aValue;
- this._events.dispatch("change", aName);
- },
-
- get : function ss_get(aName, aDefaultValue) {
- return this.has(aName) ? this._storage[aName] : aDefaultValue;
- },
-
- QueryInterface : XPCOMUtils.generateQI([Ci.fuelISessionStorage])
-};
-
-
-//=================================================
-// Extension constructor
-function Extension(aItem) {
- this._item = aItem;
- this._firstRun = false;
- this._prefs = new PreferenceBranch("extensions." + this._item.id + ".");
- this._storage = new SessionStorage();
- this._events = new Events();
-
- var installPref = "install-event-fired";
- if (!this._prefs.has(installPref)) {
- this._prefs.setValue(installPref, true);
- this._firstRun = true;
- }
-
- this._enabled = false;
- const PREFIX_ITEM_URI = "urn:mozilla:item:";
- const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#";
- var rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
- var itemResource = rdf.GetResource(PREFIX_ITEM_URI + this._item.id);
- if (itemResource) {
- var extmgr = Cc["@mozilla.org/extensions/manager;1"].getService(Ci.nsIExtensionManager);
- var ds = extmgr.datasource;
- var target = ds.GetTarget(itemResource, rdf.GetResource(PREFIX_NS_EM + "isDisabled"), true);
- if (target && target instanceof Ci.nsIRDFLiteral)
- this._enabled = (target.Value != "true");
- }
-
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Ci.nsIObserverService);
- os.addObserver(this, "em-action-requested", false);
-
- var self = this;
- gShutdown.push(function(){ self._shutdown(); });
-}
-
-//=================================================
-// Extension implementation
-Extension.prototype = {
- // cleanup observer so we don't leak
- _shutdown: function ext_shutdown() {
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Ci.nsIObserverService);
- os.removeObserver(this, "em-action-requested");
-
- this._prefs = null;
- this._storage = null;
- this._events = null;
- },
-
- // for nsIObserver
- observe: function ext_observe(aSubject, aTopic, aData)
- {
- if ((aSubject instanceof Ci.nsIUpdateItem) && (aSubject.id == this._item.id))
- {
- if (aData == "item-uninstalled")
- this._events.dispatch("uninstall", this._item.id);
- else if (aData == "item-disabled")
- this._events.dispatch("disable", this._item.id);
- else if (aData == "item-enabled")
- this._events.dispatch("enable", this._item.id);
- else if (aData == "item-cancel-action")
- this._events.dispatch("cancel", this._item.id);
- else if (aData == "item-upgraded")
- this._events.dispatch("upgrade", this._item.id);
- }
- },
-
- get id() {
- return this._item.id;
- },
-
- get name() {
- return this._item.name;
- },
-
- get enabled() {
- return this._enabled;
- },
-
- get version() {
- return this._item.version;
- },
-
- get firstRun() {
- return this._firstRun;
- },
-
- get storage() {
- return this._storage;
- },
-
- get prefs() {
- return this._prefs;
- },
-
- get events() {
- return this._events;
- },
-
- QueryInterface : XPCOMUtils.generateQI([Ci.fuelIExtension])
-};
-
-
-//=================================================
-// Extensions constructor
-function Extensions() {
- this._extmgr = Components.classes["@mozilla.org/extensions/manager;1"]
- .getService(Ci.nsIExtensionManager);
-
- this._cache = {};
-
- var self = this;
- gShutdown.push(function() { self._shutdown(); });
-}
-
-//=================================================
-// Extensions implementation
-Extensions.prototype = {
- _shutdown : function exts_shutdown() {
- this._extmgr = null;
- this._cache = null;
- },
-
- /*
- * Helper method to check cache before creating a new extension
- */
- _get : function exts_get(aId) {
- if (this._cache.hasOwnProperty(aId))
- return this._cache[aId];
-
- var newExt = new Extension(this._extmgr.getItemForID(aId));
- this._cache[aId] = newExt;
- return newExt;
- },
-
- get all() {
- return this.find({});
- },
-
- // XXX: Disabled until we can figure out the wrapped object issues
- // id: "some@id" or /id/
- // name: "name" or /name/
- // version: "1.0.1"
- // minVersion: "1.0"
- // maxVersion: "2.0"
- find : function exts_find(aOptions) {
- var retVal = [];
- var items = this._extmgr.getItemList(Ci.nsIUpdateItem.TYPE_EXTENSION, {});
-
- for (var i = 0; i < items.length; i++) {
- retVal.push(this._get(items[i].id));
- }
-
- return retVal;
- },
-
- has : function exts_has(aId) {
- return this._extmgr.getItemForID(aId) != null;
- },
-
- get : function exts_get(aId) {
- return this.has(aId) ? this._get(aId) : null;
- },
-
- QueryInterface : XPCOMUtils.generateQI([Ci.fuelIExtensions])
-};
-
-//=================================================
// Singleton that holds services and utilities
var Utilities = {
_bookmarks : null,
get bookmarks() {
if (!this._bookmarks) {
this._bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
}
@@ -1135,163 +621,53 @@ var ApplicationFactory = {
if (gSingleton == null) {
gSingleton = new Application();
}
return gSingleton.QueryInterface(aIID);
}
};
+
+
//=================================================
// Application constructor
function Application() {
- this._console = null;
- this._prefs = null;
- this._storage = null;
- this._events = null;
+ this.initToolkitHelpers();
this._bookmarks = null;
-
- this._info = Components.classes["@mozilla.org/xre/app-info;1"]
- .getService(Ci.nsIXULAppInfo);
-
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Ci.nsIObserverService);
-
- os.addObserver(this, "final-ui-startup", false);
- os.addObserver(this, "quit-application-requested", false);
- os.addObserver(this, "quit-application-granted", false);
- os.addObserver(this, "quit-application", false);
- os.addObserver(this, "xpcom-shutdown", false);
}
//=================================================
// Application implementation
Application.prototype = {
// for nsIClassInfo + XPCOMUtils
classDescription: "Application",
classID: Components.ID("fe74cf80-aa2d-11db-abbd-0800200c9a66"),
contractID: "@mozilla.org/fuel/application;1",
// redefine the default factory for XPCOMUtils
_xpcom_factory: ApplicationFactory,
- // get this contractID registered for certain categories via XPCOMUtils
- _xpcom_categories: [
- // make Application a startup observer
- { category: "app-startup", service: true },
-
- // add Application as a global property for easy access
- { category: "JavaScript global privileged property" }
- ],
-
- get id() {
- return this._info.ID;
- },
-
- get name() {
- return this._info.name;
- },
-
- get version() {
- return this._info.version;
- },
-
- // for nsIObserver
- observe: function app_observe(aSubject, aTopic, aData) {
- if (aTopic == "app-startup") {
- this._extensions = new Extensions();
- this.events.dispatch("load", "application");
- }
- else if (aTopic == "final-ui-startup") {
- this.events.dispatch("ready", "application");
- }
- else if (aTopic == "quit-application-requested") {
- // we can stop the quit by checking the return value
- if (this.events.dispatch("quit", "application") == false)
- aSubject.data = true;
- }
- else if (aTopic == "xpcom-shutdown") {
- this.events.dispatch("unload", "application");
-
- // call the cleanup functions and empty the array
- while (gShutdown.length) {
- gShutdown.shift()();
- }
-
- // release our observers
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Ci.nsIObserverService);
-
- os.removeObserver(this, "final-ui-startup");
-
- os.removeObserver(this, "quit-application-requested");
- os.removeObserver(this, "quit-application-granted");
- os.removeObserver(this, "quit-application");
-
- os.removeObserver(this, "xpcom-shutdown");
-
- this._info = null;
- this._console = null;
- this._prefs = null;
- this._storage = null;
- this._events = null;
- this._extensions = null;
- this._bookmarks = null;
-
- Utilities.free();
- }
- },
-
- // for nsIClassInfo
- flags : Ci.nsIClassInfo.SINGLETON,
- implementationLanguage : Ci.nsIProgrammingLanguage.JAVASCRIPT,
+ // for nsISupports
+ QueryInterface : XPCOMUtils.generateQI([Ci.fuelIApplication, Ci.nsIObserver, Ci.nsIClassInfo]),
getInterfaces : function app_gi(aCount) {
var interfaces = [Ci.fuelIApplication, Ci.nsIObserver, Ci.nsIClassInfo];
aCount.value = interfaces.length;
return interfaces;
},
- getHelperForLanguage : function app_ghfl(aCount) {
- return null;
- },
-
- // for nsISupports
- QueryInterface : XPCOMUtils.generateQI([Ci.fuelIApplication, Ci.nsIObserver, Ci.nsIClassInfo]),
-
- get console() {
- if (this._console == null)
- this._console = new Console();
-
- return this._console;
- },
-
- get storage() {
- if (this._storage == null)
- this._storage = new SessionStorage();
-
- return this._storage;
- },
-
- get prefs() {
- if (this._prefs == null)
- this._prefs = new PreferenceBranch("");
-
- return this._prefs;
- },
-
- get extensions() {
- return this._extensions;
- },
-
- get events() {
- if (this._events == null)
- this._events = new Events();
-
- return this._events;
+ // for nsIObserver
+ observe: function app_observe(aSubject, aTopic, aData) {
+ // Call the extApplication version of this function first
+ this.__proto__.__proto__.observe(aSubject, aTopic, aData);
+ if (aTopic == "xpcom-shutdown") {
+ this._bookmarks = null;
+ Utilities.free();
+ }
},
get bookmarks() {
if (this._bookmarks == null)
this._bookmarks = new BookmarkFolder(null, null);
return this._bookmarks;
},
@@ -1308,10 +684,14 @@ Application.prototype = {
get activeWindow() {
return new Window(Utilities.windowMediator.getMostRecentWindow("navigator:browser"));
}
};
//module initialization
function NSGetModule(aCompMgr, aFileSpec) {
+ // set the proto, defined in extApplication.js
+ Application.prototype.__proto__ = extApplication.prototype;
return XPCOMUtils.generateModule([Application]);
}
+
+#include ../../../toolkit/components/exthelper/extApplication.js
--- a/toolkit/components/Makefile.in
+++ b/toolkit/components/Makefile.in
@@ -56,16 +56,17 @@ DIRS += \
# These component dirs are built only for XUL apps
ifdef MOZ_XUL_APP
DIRS += \
apppicker \
filepicker \
console \
+ exthelper \
viewconfig \
typeaheadfind \
$(NULL)
ifneq (,$(filter cocoa, $(MOZ_WIDGET_TOOLKIT)))
TOOL_DIRS += alerts
else
DIRS += alerts
new file mode 100644
--- /dev/null
+++ b/toolkit/components/exthelper/Makefile.in
@@ -0,0 +1,50 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is FUEL.
+#
+# The Initial Developer of the Original Code is Mozilla Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2006
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Finkle <mfinkle@mozilla.com>
+# John Resig <jresig@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = exthelper
+XPIDL_MODULE = exthelper
+
+XPIDLSRCS = extIApplication.idl
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/toolkit/components/exthelper/extApplication.js
@@ -0,0 +1,692 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FUEL.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Finkle <mfinkle@mozilla.com> (Original Author)
+ * John Resig <jresig@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//=================================================
+// Shutdown - used to store cleanup functions which will
+// be called on Application shutdown
+var gShutdown = [];
+
+//=================================================
+// Console constructor
+function Console() {
+ this._console = Components.classes["@mozilla.org/consoleservice;1"]
+ .getService(Ci.nsIConsoleService);
+}
+
+//=================================================
+// Console implementation
+Console.prototype = {
+ log : function cs_log(aMsg) {
+ this._console.logStringMessage(aMsg);
+ },
+
+ open : function cs_open() {
+ var wMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Ci.nsIWindowMediator);
+ var console = wMediator.getMostRecentWindow("global:console");
+ if (!console) {
+ var wWatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
+ .getService(Ci.nsIWindowWatcher);
+ wWatch.openWindow(null, "chrome://global/content/console.xul", "_blank",
+ "chrome,dialog=no,all", null);
+ } else {
+ // console was already open
+ console.focus();
+ }
+ },
+
+ QueryInterface : XPCOMUtils.generateQI([Ci.extIConsole])
+};
+
+
+//=================================================
+// EventItem constructor
+function EventItem(aType, aData) {
+ this._type = aType;
+ this._data = aData;
+}
+
+//=================================================
+// EventItem implementation
+EventItem.prototype = {
+ _cancel : false,
+
+ get type() {
+ return this._type;
+ },
+
+ get data() {
+ return this._data;
+ },
+
+ preventDefault : function ei_pd() {
+ this._cancel = true;
+ },
+
+ QueryInterface : XPCOMUtils.generateQI([Ci.extIEventItem])
+};
+
+
+//=================================================
+// Events constructor
+function Events() {
+ this._listeners = [];
+}
+
+//=================================================
+// Events implementation
+Events.prototype = {
+ addListener : function evts_al(aEvent, aListener) {
+ if (this._listeners.some(hasFilter))
+ return;
+
+ this._listeners.push({
+ event: aEvent,
+ listener: aListener
+ });
+
+ function hasFilter(element) {
+ return element.event == aEvent && element.listener == aListener;
+ }
+ },
+
+ removeListener : function evts_rl(aEvent, aListener) {
+ this._listeners = this._listeners.filter(function(element){
+ return element.event != aEvent && element.listener != aListener;
+ });
+ },
+
+ dispatch : function evts_dispatch(aEvent, aEventItem) {
+ eventItem = new EventItem(aEvent, aEventItem);
+
+ this._listeners.forEach(function(key){
+ if (key.event == aEvent) {
+ key.listener.handleEvent ?
+ key.listener.handleEvent(eventItem) :
+ key.listener(eventItem);
+ }
+ });
+
+ return !eventItem._cancel;
+ },
+
+ QueryInterface : XPCOMUtils.generateQI([Ci.extIEvents])
+};
+
+
+//=================================================
+// PreferenceBranch constructor
+function PreferenceBranch(aBranch) {
+ if (!aBranch)
+ aBranch = "";
+
+ this._root = aBranch;
+ this._prefs = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Ci.nsIPrefService);
+
+ if (aBranch)
+ this._prefs = this._prefs.getBranch(aBranch);
+
+ this._prefs.QueryInterface(Ci.nsIPrefBranch);
+ this._prefs.QueryInterface(Ci.nsIPrefBranch2);
+
+ // we want to listen to "all" changes for this branch, so pass in a blank domain
+ this._prefs.addObserver("", this, true);
+ this._events = new Events();
+
+ var self = this;
+ gShutdown.push(function() { self._shutdown(); });
+}
+
+//=================================================
+// PreferenceBranch implementation
+PreferenceBranch.prototype = {
+ // cleanup observer so we don't leak
+ _shutdown: function prefs_shutdown() {
+ this._prefs.removeObserver(this._root, this);
+
+ this._prefs = null;
+ this._events = null;
+ },
+
+ // for nsIObserver
+ observe: function prefs_observe(aSubject, aTopic, aData) {
+ if (aTopic == "nsPref:changed")
+ this._events.dispatch("change", aData);
+ },
+
+ get root() {
+ return this._root;
+ },
+
+ get all() {
+ return this.find({});
+ },
+
+ get events() {
+ return this._events;
+ },
+
+ // XXX: Disabled until we can figure out the wrapped object issues
+ // name: "name" or /name/
+ // path: "foo.bar." or "" or /fo+\.bar/
+ // type: Boolean, Number, String (getPrefType)
+ // locked: true, false (prefIsLocked)
+ // modified: true, false (prefHasUserValue)
+ find : function prefs_find(aOptions) {
+ var retVal = [];
+ var items = this._prefs.getChildList("", []);
+
+ for (var i = 0; i < items.length; i++) {
+ retVal.push(new Preference(items[i], this));
+ }
+
+ return retVal;
+ },
+
+ has : function prefs_has(aName) {
+ return (this._prefs.getPrefType(aName) != Ci.nsIPrefBranch.PREF_INVALID);
+ },
+
+ get : function prefs_get(aName) {
+ return this.has(aName) ? new Preference(aName, this) : null;
+ },
+
+ getValue : function prefs_gv(aName, aValue) {
+ var type = this._prefs.getPrefType(aName);
+
+ switch (type) {
+ case Ci.nsIPrefBranch2.PREF_STRING:
+ aValue = this._prefs.getComplexValue(aName, Ci.nsISupportsString).data;
+ break;
+ case Ci.nsIPrefBranch2.PREF_BOOL:
+ aValue = this._prefs.getBoolPref(aName);
+ break;
+ case Ci.nsIPrefBranch2.PREF_INT:
+ aValue = this._prefs.getIntPref(aName);
+ break;
+ }
+
+ return aValue;
+ },
+
+ setValue : function prefs_sv(aName, aValue) {
+ var type = aValue != null ? aValue.constructor.name : "";
+
+ switch (type) {
+ case "String":
+ var str = Components.classes["@mozilla.org/supports-string;1"]
+ .createInstance(Ci.nsISupportsString);
+ str.data = aValue;
+ this._prefs.setComplexValue(aName, Ci.nsISupportsString, str);
+ break;
+ case "Boolean":
+ this._prefs.setBoolPref(aName, aValue);
+ break;
+ case "Number":
+ this._prefs.setIntPref(aName, aValue);
+ break;
+ default:
+ throw("Unknown preference value specified.");
+ }
+ },
+
+ reset : function prefs_reset() {
+ this._prefs.resetBranch("");
+ },
+
+ QueryInterface : XPCOMUtils.generateQI([Ci.extIPreferenceBranch, Ci.nsISupportsWeakReference])
+};
+
+
+//=================================================
+// Preference constructor
+function Preference(aName, aBranch) {
+ this._name = aName;
+ this._branch = aBranch;
+ this._events = new Events();
+
+ var self = this;
+
+ this.branch.events.addListener("change", function(aEvent){
+ if (aEvent.data == self.name)
+ self.events.dispatch(aEvent.type, aEvent.data);
+ });
+}
+
+//=================================================
+// Preference implementation
+Preference.prototype = {
+ get name() {
+ return this._name;
+ },
+
+ get type() {
+ var value = "";
+ var type = this._prefs.getPrefType(name);
+
+ switch (type) {
+ case Ci.nsIPrefBranch2.PREF_STRING:
+ value = "String";
+ break;
+ case Ci.nsIPrefBranch2.PREF_BOOL:
+ value = "Boolean";
+ break;
+ case Ci.nsIPrefBranch2.PREF_INT:
+ value = "Number";
+ break;
+ }
+
+ return value;
+ },
+
+ get value() {
+ return this.branch.getValue(this._name, null);
+ },
+
+ set value(aValue) {
+ return this.branch.setValue(this._name, aValue);
+ },
+
+ get locked() {
+ return this.branch._prefs.prefIsLocked(this.name);
+ },
+
+ set locked(aValue) {
+ this.branch._prefs[ aValue ? "lockPref" : "unlockPref" ](this.name);
+ },
+
+ get modified() {
+ return this.branch._prefs.prefHasUserValue(this.name);
+ },
+
+ get branch() {
+ return this._branch;
+ },
+
+ get events() {
+ return this._events;
+ },
+
+ reset : function pref_reset() {
+ this.branch._prefs.clearUserPref(this.name);
+ },
+
+ QueryInterface : XPCOMUtils.generateQI([Ci.extIPreference])
+};
+
+
+//=================================================
+// SessionStorage constructor
+function SessionStorage() {
+ this._storage = {};
+ this._events = new Events();
+}
+
+//=================================================
+// SessionStorage implementation
+SessionStorage.prototype = {
+ get events() {
+ return this._events;
+ },
+
+ has : function ss_has(aName) {
+ return this._storage.hasOwnProperty(aName);
+ },
+
+ set : function ss_set(aName, aValue) {
+ this._storage[aName] = aValue;
+ this._events.dispatch("change", aName);
+ },
+
+ get : function ss_get(aName, aDefaultValue) {
+ return this.has(aName) ? this._storage[aName] : aDefaultValue;
+ },
+
+ QueryInterface : XPCOMUtils.generateQI([Ci.extISessionStorage])
+};
+
+
+//=================================================
+// Extension constructor
+function Extension(aItem) {
+ this._item = aItem;
+ this._firstRun = false;
+ this._prefs = new PreferenceBranch("extensions." + this._item.id + ".");
+ this._storage = new SessionStorage();
+ this._events = new Events();
+
+ var installPref = "install-event-fired";
+ if (!this._prefs.has(installPref)) {
+ this._prefs.setValue(installPref, true);
+ this._firstRun = true;
+ }
+
+ this._enabled = false;
+ const PREFIX_ITEM_URI = "urn:mozilla:item:";
+ const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#";
+ var rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
+ var itemResource = rdf.GetResource(PREFIX_ITEM_URI + this._item.id);
+ if (itemResource) {
+ var extmgr = Cc["@mozilla.org/extensions/manager;1"].getService(Ci.nsIExtensionManager);
+ var ds = extmgr.datasource;
+ var target = ds.GetTarget(itemResource, rdf.GetResource(PREFIX_NS_EM + "isDisabled"), true);
+ if (target && target instanceof Ci.nsIRDFLiteral)
+ this._enabled = (target.Value != "true");
+ }
+
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+ os.addObserver(this, "em-action-requested", false);
+
+ var self = this;
+ gShutdown.push(function(){ self._shutdown(); });
+}
+
+//=================================================
+// Extension implementation
+Extension.prototype = {
+ // cleanup observer so we don't leak
+ _shutdown: function ext_shutdown() {
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+ os.removeObserver(this, "em-action-requested");
+
+ this._prefs = null;
+ this._storage = null;
+ this._events = null;
+ },
+
+ // for nsIObserver
+ observe: function ext_observe(aSubject, aTopic, aData)
+ {
+ if ((aSubject instanceof Ci.nsIUpdateItem) && (aSubject.id == this._item.id))
+ {
+ if (aData == "item-uninstalled")
+ this._events.dispatch("uninstall", this._item.id);
+ else if (aData == "item-disabled")
+ this._events.dispatch("disable", this._item.id);
+ else if (aData == "item-enabled")
+ this._events.dispatch("enable", this._item.id);
+ else if (aData == "item-cancel-action")
+ this._events.dispatch("cancel", this._item.id);
+ else if (aData == "item-upgraded")
+ this._events.dispatch("upgrade", this._item.id);
+ }
+ },
+
+ get id() {
+ return this._item.id;
+ },
+
+ get name() {
+ return this._item.name;
+ },
+
+ get enabled() {
+ return this._enabled;
+ },
+
+ get version() {
+ return this._item.version;
+ },
+
+ get firstRun() {
+ return this._firstRun;
+ },
+
+ get storage() {
+ return this._storage;
+ },
+
+ get prefs() {
+ return this._prefs;
+ },
+
+ get events() {
+ return this._events;
+ },
+
+ QueryInterface : XPCOMUtils.generateQI([Ci.extIExtension])
+};
+
+
+//=================================================
+// Extensions constructor
+function Extensions() {
+ this._extmgr = Components.classes["@mozilla.org/extensions/manager;1"]
+ .getService(Ci.nsIExtensionManager);
+
+ this._cache = {};
+
+ var self = this;
+ gShutdown.push(function() { self._shutdown(); });
+}
+
+//=================================================
+// Extensions implementation
+Extensions.prototype = {
+ _shutdown : function exts_shutdown() {
+ this._extmgr = null;
+ this._cache = null;
+ },
+
+ /*
+ * Helper method to check cache before creating a new extension
+ */
+ _get : function exts_get(aId) {
+ if (this._cache.hasOwnProperty(aId))
+ return this._cache[aId];
+
+ var newExt = new Extension(this._extmgr.getItemForID(aId));
+ this._cache[aId] = newExt;
+ return newExt;
+ },
+
+ get all() {
+ return this.find({});
+ },
+
+ // XXX: Disabled until we can figure out the wrapped object issues
+ // id: "some@id" or /id/
+ // name: "name" or /name/
+ // version: "1.0.1"
+ // minVersion: "1.0"
+ // maxVersion: "2.0"
+ find : function exts_find(aOptions) {
+ var retVal = [];
+ var items = this._extmgr.getItemList(Ci.nsIUpdateItem.TYPE_EXTENSION, {});
+
+ for (var i = 0; i < items.length; i++) {
+ retVal.push(this._get(items[i].id));
+ }
+
+ return retVal;
+ },
+
+ has : function exts_has(aId) {
+ return this._extmgr.getItemForID(aId) != null;
+ },
+
+ get : function exts_get(aId) {
+ return this.has(aId) ? this._get(aId) : null;
+ },
+
+ QueryInterface : XPCOMUtils.generateQI([Ci.extIExtensions])
+};
+
+//=================================================
+// extApplication constructor
+function extApplication() {
+}
+
+//=================================================
+// extApplication implementation
+extApplication.prototype = {
+ initToolkitHelpers: function extApp_initToolkitHelpers() {
+ this._console = null;
+ this._storage = null;
+ this._prefs = null;
+ this._extensions = null;
+ this._events = null;
+
+ this._info = Components.classes["@mozilla.org/xre/app-info;1"]
+ .getService(Ci.nsIXULAppInfo);
+
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+
+ os.addObserver(this, "final-ui-startup", false);
+ os.addObserver(this, "quit-application-requested", false);
+ os.addObserver(this, "quit-application-granted", false);
+ os.addObserver(this, "quit-application", false);
+ os.addObserver(this, "xpcom-shutdown", false);
+ },
+
+ // get this contractID registered for certain categories via XPCOMUtils
+ _xpcom_categories: [
+ // make Application a startup observer
+ { category: "app-startup", service: true },
+
+ // add Application as a global property for easy access
+ { category: "JavaScript global privileged property" }
+ ],
+
+ // for nsIClassInfo
+ flags : Ci.nsIClassInfo.SINGLETON,
+ implementationLanguage : Ci.nsIProgrammingLanguage.JAVASCRIPT,
+
+ getInterfaces : function app_gi(aCount) {
+ var interfaces = [Ci.extIApplication, Ci.nsIObserver, Ci.nsIClassInfo];
+ aCount.value = interfaces.length;
+ return interfaces;
+ },
+
+ getHelperForLanguage : function app_ghfl(aCount) {
+ return null;
+ },
+
+ // extIApplication
+ get id() {
+ return this._info.ID;
+ },
+
+ get name() {
+ return this._info.name;
+ },
+
+ get version() {
+ return this._info.version;
+ },
+
+ // for nsIObserver
+ observe: function app_observe(aSubject, aTopic, aData) {
+ if (aTopic == "app-startup") {
+ this.events.dispatch("load", "application");
+ }
+ else if (aTopic == "final-ui-startup") {
+ this.events.dispatch("ready", "application");
+ }
+ else if (aTopic == "quit-application-requested") {
+ // we can stop the quit by checking the return value
+ if (this.events.dispatch("quit", "application") == false)
+ aSubject.data = true;
+ }
+ else if (aTopic == "xpcom-shutdown") {
+ this.events.dispatch("unload", "application");
+
+ // call the cleanup functions and empty the array
+ while (gShutdown.length) {
+ gShutdown.shift()();
+ }
+
+ // release our observers
+ var os = Components.classes["@mozilla.org/observer-service;1"]
+ .getService(Ci.nsIObserverService);
+
+ os.removeObserver(this, "final-ui-startup");
+
+ os.removeObserver(this, "quit-application-requested");
+ os.removeObserver(this, "quit-application-granted");
+ os.removeObserver(this, "quit-application");
+
+ os.removeObserver(this, "xpcom-shutdown");
+
+ this._info = null;
+ this._console = null;
+ this._prefs = null;
+ this._storage = null;
+ this._events = null;
+ this._extensions = null;
+ }
+ },
+
+ get console() {
+ if (this._console == null)
+ this._console = new Console();
+
+ return this._console;
+ },
+
+ get storage() {
+ if (this._storage == null)
+ this._storage = new SessionStorage();
+
+ return this._storage;
+ },
+
+ get prefs() {
+ if (this._prefs == null)
+ this._prefs = new PreferenceBranch("");
+
+ return this._prefs;
+ },
+
+ get extensions() {
+ if (this._extensions == null)
+ this._extensions = new Extensions();
+
+ return this._extensions;
+ },
+
+ get events() {
+ if (this._events == null)
+ this._events = new Events();
+
+ return this._events;
+ }
+};
new file mode 100644
--- /dev/null
+++ b/toolkit/components/exthelper/extIApplication.idl
@@ -0,0 +1,429 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FUEL.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Mark Finkle <mfinkle@mozilla.com> (Original Author)
+ * John Resig <jresig@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIVariant;
+interface extIPreference;
+interface extISessionStorage;
+
+
+/**
+ * Interface that gives simplified access to the console
+ */
+[scriptable, uuid(ae8482e0-aa5a-11db-abbd-0800200c9a66)]
+interface extIConsole : nsISupports
+{
+ /**
+ * Sends a given string to the console.
+ * @param aMsg
+ * The text to send to the console
+ */
+ void log(in AString aMsg);
+
+ /**
+ * Opens the error console window. The console window
+ * is focused if already open.
+ */
+ void open();
+};
+
+
+/**
+ * Interface holds information about an event.
+ */
+[scriptable, function, uuid(05281820-ab62-11db-abbd-0800200c9a66)]
+interface extIEventItem : nsISupports
+{
+ /**
+ * The name of the event
+ */
+ readonly attribute AString type;
+
+ /**
+ * Can hold extra details and data associated with the event. This
+ * is optional and event specific. If the event does not send extra
+ * details, this is null.
+ */
+ readonly attribute AString data;
+
+ /**
+ * Cancels the event if it is cancelable.
+ */
+ void preventDefault();
+};
+
+
+/**
+ * Interface used as a callback for listening to events.
+ */
+[scriptable, function, uuid(2dfe3a50-ab2f-11db-abbd-0800200c9a66)]
+interface extIEventListener : nsISupports
+{
+ /**
+ * This method is called whenever an event occurs of the type for which
+ * the extIEventListener interface was registered.
+ *
+ * @param aEvent
+ * The extIEventItem associated with the event.
+ */
+ void handleEvent(in extIEventItem aEvent);
+};
+
+
+/**
+ * Interface for supporting custom events.
+ */
+[scriptable, uuid(3a8ec9d0-ab19-11db-abbd-0800200c9a66)]
+interface extIEvents : nsISupports
+{
+ /**
+ * Adds an event listener to the list. If multiple identical event listeners
+ * are registered on the same event target with the same parameters the
+ * duplicate instances are discarded. They do not cause the EventListener
+ * to be called twice and since they are discarded they do not need to be
+ * removed with the removeListener method.
+ *
+ * @param aEvent
+ * The name of an event
+ * @param aListener
+ * The reference to a listener
+ */
+ void addListener(in AString aEvent, in extIEventListener aListener);
+
+ /**
+ * Removes an event listener from the list. Calling remove
+ * with arguments which do not identify any currently registered
+ * event listener has no effect.
+ * @param aEvent
+ * The name of an event
+ * @param aListener
+ * The reference to a listener
+ */
+ void removeListener(in AString aEvent, in extIEventListener aListener);
+};
+
+
+/**
+ * Interface for simplified access to preferences. The interface has a
+ * predefined root preference branch. The root branch is set based on the
+ * context of the owner. For example, an extension's preferences have a root
+ * of "extensions.<extensionid>.", while the application level preferences
+ * have an empty root. All preference "aName" parameters used in this interface
+ * are relative to the root branch.
+ */
+[scriptable, uuid(ce697d40-aa5a-11db-abbd-0800200c9a66)]
+interface extIPreferenceBranch : nsISupports
+{
+ /**
+ * The name of the branch root.
+ */
+ readonly attribute AString root;
+
+ /**
+ * Array of extIPreference listing all preferences in this branch.
+ */
+ readonly attribute nsIVariant all;
+
+ /**
+ * The events object for the preferences
+ * supports: "change"
+ */
+ readonly attribute extIEvents events;
+
+ /**
+ * Check to see if a preference exists.
+ * @param aName
+ * The name of preference
+ * @returns true if the preference exists, false if not
+ */
+ boolean has(in AString aName);
+
+ /**
+ * Gets an object representing a preference
+ * @param aName
+ * The name of preference
+ * @returns a preference object, or null if the preference does not exist
+ */
+ extIPreference get(in AString aName);
+
+ /**
+ * Gets the value of a preference. Returns a default value if
+ * the preference does not exist.
+ * @param aName
+ * The name of preference
+ * @param aDefaultValue
+ * The value to return if preference does not exist
+ * @returns value of the preference or the given default value if preference
+ * does not exists.
+ */
+ nsIVariant getValue(in AString aName, in nsIVariant aDefaultValue);
+
+ /**
+ * Sets the value of a storage item with the given name.
+ * @param aName
+ * The name of an item
+ * @param aValue
+ * The value to assign to the item
+ */
+ void setValue(in AString aName, in nsIVariant aValue);
+
+ /**
+ * Resets all preferences in a branch back to their default values.
+ */
+ void reset();
+};
+
+/**
+ * Interface for accessing a single preference. The data is not cached.
+ * All reads access the current state of the preference.
+ */
+[scriptable, uuid(2C7462E2-72C2-4473-9007-0E6AE71E23CA)]
+interface extIPreference : nsISupports
+{
+ /**
+ * The name of the preference.
+ */
+ readonly attribute AString name;
+
+ /**
+ * A string representing the type of preference (String, Boolean, or Number).
+ */
+ readonly attribute AString type;
+
+ /**
+ * Get/Set the value of the preference.
+ */
+ attribute nsIVariant value;
+
+ /**
+ * Get the locked state of the preference. Set to a boolean value to (un)lock it.
+ */
+ attribute boolean locked;
+
+ /**
+ * Check if a preference has been modified by the user, or not.
+ */
+ readonly attribute boolean modified;
+
+ /**
+ * The preference branch that contains this preference.
+ */
+ readonly attribute extIPreferenceBranch branch;
+
+ /**
+ * The events object for this preference.
+ * supports: "change"
+ */
+ readonly attribute extIEvents events;
+
+ /**
+ * Resets a preference back to its default values.
+ */
+ void reset();
+};
+
+
+/**
+ * Interface representing an extension
+ */
+[scriptable, uuid(10cee02c-f6e0-4d61-ab27-c16572b18c46)]
+interface extIExtension : nsISupports
+{
+ /**
+ * The id of the extension.
+ */
+ readonly attribute AString id;
+
+ /**
+ * The name of the extension.
+ */
+ readonly attribute AString name;
+
+ /**
+ * Check if the extension is currently enabled, or not.
+ */
+ readonly attribute boolean enabled;
+
+ /**
+ * The version number of the extension.
+ */
+ readonly attribute AString version;
+
+ /**
+ * Indicates whether this is the extension's first run after install
+ */
+ readonly attribute boolean firstRun;
+
+ /**
+ * The preferences object for the extension. Defaults to the
+ * "extensions.<extensionid>." branch.
+ */
+ readonly attribute extIPreferenceBranch prefs;
+
+ /**
+ * The storage object for the extension.
+ */
+ readonly attribute extISessionStorage storage;
+
+ /**
+ * The events object for the extension.
+ * supports: "uninstall"
+ */
+ readonly attribute extIEvents events;
+};
+
+
+/**
+ * Interface representing a list of all installed extensions
+ */
+[scriptable, uuid(de281930-aa5a-11db-abbd-0800200c9a66)]
+interface extIExtensions : nsISupports
+{
+ /**
+ * Array of extIExtension listing all extensions in the application.
+ */
+ readonly attribute nsIVariant all;
+
+ /**
+ * Determines if an extension exists with the given id.
+ * @param aId
+ * The id of an extension
+ * @returns true if an extension exists with the given id,
+ * false otherwise.
+ */
+ boolean has(in AString aId);
+
+ /**
+ * Gets a extIExtension object for an extension.
+ * @param aId
+ * The id of an extension
+ * @returns An extension object or null if no extension exists
+ * with the given id.
+ */
+ extIExtension get(in AString aId);
+};
+
+/**
+ * Interface representing a simple storage system
+ */
+[scriptable, uuid(0787ac44-29b9-4889-b97f-13573aec6971)]
+interface extISessionStorage : nsISupports
+{
+ /**
+ * The events object for the storage
+ * supports: "change"
+ */
+ readonly attribute extIEvents events;
+
+ /**
+ * Determines if a storage item exists with the given name.
+ * @param aName
+ * The name of an item
+ * @returns true if an item exists with the given name,
+ * false otherwise.
+ */
+ boolean has(in AString aName);
+
+ /**
+ * Sets the value of a storage item with the given name.
+ * @param aName
+ * The name of an item
+ * @param aValue
+ * The value to assign to the item
+ */
+ void set(in AString aName, in nsIVariant aValue);
+
+ /**
+ * Gets the value of a storage item with the given name. Returns a
+ * default value if the item does not exist.
+ * @param aName
+ * The name of an item
+ * @param aDefaultValue
+ * The value to return if no item exists with the given name
+ * @returns value of the item or the given default value if no item
+ * exists with the given name.
+ */
+ nsIVariant get(in AString aName, in nsIVariant aDefaultValue);
+};
+
+[scriptable, uuid(ba9442ee-7070-44fb-8157-c111e1fa70b6)]
+interface extIApplication : nsISupports
+{
+ /**
+ * The id of the application.
+ */
+ readonly attribute AString id;
+
+ /**
+ * The name of the application.
+ */
+ readonly attribute AString name;
+
+ /**
+ * The version number of the application.
+ */
+ readonly attribute AString version;
+
+ /**
+ * The console object for the application.
+ */
+ readonly attribute extIConsole console;
+
+ /**
+ * The extensions object for the application. Contains a list
+ * of all installed extensions.
+ */
+ readonly attribute extIExtensions extensions;
+
+ /**
+ * The preferences object for the application. Defaults to an empty
+ * root branch.
+ */
+ readonly attribute extIPreferenceBranch prefs;
+
+ /**
+ * The storage object for the application.
+ */
+ readonly attribute extISessionStorage storage;
+
+ /**
+ * The events object for the application.
+ * supports: "load", "ready", "quit", "unload"
+ */
+ readonly attribute extIEvents events;
+};