Bug 359675 - provide an option to manually fill forms and log in. p=poshannessy@mozil...
[wine-gecko.git] / browser / fuel / src / fuelApplication.js
blob13dce1e62a5eee46ace4c1328a3616d974b7f86a
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is FUEL.
16 * The Initial Developer of the Original Code is Mozilla Corporation.
17 * Portions created by the Initial Developer are Copyright (C) 2006
18 * the Initial Developer. All Rights Reserved.
20 * Contributor(s):
21 * Mark Finkle <mfinkle@mozilla.com> (Original Author)
22 * John Resig <jresig@mozilla.com> (Original Author)
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 const Ci = Components.interfaces;
39 const Cc = Components.classes;
41 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
43 //=================================================
44 // Singleton that holds services and utilities
45 var Utilities = {
46 _bookmarks : null,
47 get bookmarks() {
48 if (!this._bookmarks) {
49 this._bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
50 getService(Ci.nsINavBookmarksService);
52 return this._bookmarks;
55 _livemarks : null,
56 get livemarks() {
57 if (!this._livemarks) {
58 this._livemarks = Cc["@mozilla.org/browser/livemark-service;2"].
59 getService(Ci.nsILivemarkService);
61 return this._livemarks;
64 _annotations : null,
65 get annotations() {
66 if (!this._annotations) {
67 this._annotations = Cc["@mozilla.org/browser/annotation-service;1"].
68 getService(Ci.nsIAnnotationService);
70 return this._annotations;
73 _history : null,
74 get history() {
75 if (!this._history) {
76 this._history = Cc["@mozilla.org/browser/nav-history-service;1"].
77 getService(Ci.nsINavHistoryService);
79 return this._history;
82 _windowMediator : null,
83 get windowMediator() {
84 if (!this._windowMediator) {
85 this._windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
86 getService(Ci.nsIWindowMediator);
88 return this._windowMediator;
91 makeURI : function(aSpec) {
92 if (!aSpec)
93 return null;
94 var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
95 return ios.newURI(aSpec, null, null);
98 free : function() {
99 this._bookmarks = null;
100 this._livemarks = null;
101 this._annotations = null;
102 this._history = null;
103 this._windowMediator = null;
108 //=================================================
109 // Window implementation
110 function Window(aWindow) {
111 this._window = aWindow;
112 this._tabbrowser = aWindow.getBrowser();
113 this._events = new Events();
114 this._cleanup = {};
116 this._watch("TabOpen");
117 this._watch("TabMove");
118 this._watch("TabClose");
119 this._watch("TabSelect");
121 var self = this;
122 gShutdown.push(function() { self._shutdown(); });
125 Window.prototype = {
126 get events() {
127 return this._events;
131 * Helper used to setup event handlers on the XBL element. Note that the events
132 * are actually dispatched to tabs, so we capture them.
134 _watch : function win_watch(aType) {
135 var self = this;
136 this._tabbrowser.addEventListener(aType,
137 this._cleanup[aType] = function(e){ self._event(e); },
138 true);
142 * Helper event callback used to redirect events made on the XBL element
144 _event : function win_event(aEvent) {
145 this._events.dispatch(aEvent.type, "");
148 get tabs() {
149 var tabs = [];
150 var browsers = this._tabbrowser.browsers;
152 for (var i=0; i<browsers.length; i++)
153 tabs.push(new BrowserTab(this._window, browsers[i]));
155 return tabs;
158 get activeTab() {
159 return new BrowserTab(this._window, this._tabbrowser.selectedBrowser);
162 open : function win_open(aURI) {
163 return new BrowserTab(this._window, this._tabbrowser.addTab(aURI.spec).linkedBrowser);
166 _shutdown : function win_shutdown() {
167 for (var type in this._cleanup)
168 this._tabbrowser.removeEventListener(type, this._cleanup[type], true);
169 this._cleanup = null;
171 this._window = null;
172 this._tabbrowser = null;
173 this._events = null;
176 QueryInterface : XPCOMUtils.generateQI([Ci.fuelIWindow])
180 //=================================================
181 // BrowserTab implementation
182 function BrowserTab(aWindow, aBrowser) {
183 this._window = aWindow;
184 this._tabbrowser = aWindow.getBrowser();
185 this._browser = aBrowser;
186 this._events = new Events();
187 this._cleanup = {};
189 this._watch("load");
191 var self = this;
192 gShutdown.push(function() { self._shutdown(); });
195 BrowserTab.prototype = {
196 get uri() {
197 return this._browser.currentURI;
200 get index() {
201 var tabs = this._tabbrowser.mTabs;
202 for (var i=0; i<tabs.length; i++) {
203 if (tabs[i].linkedBrowser == this._browser)
204 return i;
206 return -1;
209 get events() {
210 return this._events;
213 get window() {
214 return this._window;
217 get document() {
218 return this._browser.contentDocument;
222 * Helper used to setup event handlers on the XBL element
224 _watch : function bt_watch(aType) {
225 var self = this;
226 this._browser.addEventListener(aType,
227 this._cleanup[aType] = function(e){ self._event(e); },
228 true);
232 * Helper event callback used to redirect events made on the XBL element
234 _event : function bt_event(aEvent) {
235 if (aEvent.type == "load") {
236 if (!(aEvent.originalTarget instanceof Ci.nsIDOMHTMLDocument))
237 return;
239 if (aEvent.originalTarget.defaultView instanceof Ci.nsIDOMWindowInternal &&
240 aEvent.originalTarget.defaultView.frameElement)
241 return;
244 this._events.dispatch(aEvent.type, "");
248 * Helper used to determine the index offset of the browsertab
250 _getTab : function bt_gettab() {
251 var tabs = this._tabbrowser.mTabs;
252 return tabs[this.index] || null;
255 load : function bt_load(aURI) {
256 this._browser.loadURI(aURI.spec, null, null);
259 focus : function bt_focus() {
260 this._tabbrowser.selectedTab = this._getTab();
261 this._tabbrowser.focus();
264 close : function bt_close() {
265 this._tabbrowser.removeTab(this._getTab());
268 moveBefore : function bt_movebefore(aBefore) {
269 this._tabbrowser.moveTabTo(this._getTab(), aBefore.index);
272 moveToEnd : function bt_moveend() {
273 this._tabbrowser.moveTabTo(this._getTab(), this._tabbrowser.browsers.length);
276 _shutdown : function bt_shutdown() {
277 for (var type in this._cleanup)
278 this._browser.removeEventListener(type, this._cleanup[type], true);
279 this._cleanup = null;
281 this._window = null;
282 this._tabbrowser = null;
283 this._browser = null;
284 this._events = null;
287 QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBrowserTab])
291 //=================================================
292 // Annotations implementation
293 function Annotations(aId) {
294 this._id = aId;
297 Annotations.prototype = {
298 get names() {
299 return Utilities.annotations.getItemAnnotationNames(this._id, {});
302 has : function ann_has(aName) {
303 return Utilities.annotations.itemHasAnnotation(this._id, aName);
306 get : function(aName) {
307 if (this.has(aName))
308 return Utilities.annotations.getItemAnnotation(this._id, aName);
309 return null;
312 set : function(aName, aValue, aExpiration) {
313 Utilities.annotations.setItemAnnotation(this._id, aName, aValue, 0, aExpiration);
316 remove : function ann_remove(aName) {
317 if (aName)
318 Utilities.annotations.removeItemAnnotation(this._id, aName);
321 QueryInterface : XPCOMUtils.generateQI([Ci.fuelIAnnotations])
325 //=================================================
326 // Bookmark implementation
327 function Bookmark(aId, aParent, aType) {
328 this._id = aId;
329 this._parent = aParent;
330 this._type = aType || "bookmark";
331 this._annotations = new Annotations(this._id);
332 this._events = new Events();
334 Utilities.bookmarks.addObserver(this, false);
336 var self = this;
337 gShutdown.push(function() { self._shutdown(); });
340 Bookmark.prototype = {
341 _shutdown : function bm_shutdown() {
342 this._annotations = null;
343 this._events = null;
345 Utilities.bookmarks.removeObserver(this);
348 get id() {
349 return this._id;
352 get title() {
353 return Utilities.bookmarks.getItemTitle(this._id);
356 set title(aTitle) {
357 Utilities.bookmarks.setItemTitle(this._id, aTitle);
360 get uri() {
361 return Utilities.bookmarks.getBookmarkURI(this._id);
364 set uri(aURI) {
365 return Utilities.bookmarks.changeBookmarkURI(this._id, aURI);
368 get description() {
369 return this._annotations.get("bookmarkProperties/description");
372 set description(aDesc) {
373 this._annotations.set("bookmarkProperties/description", aDesc, Ci.nsIAnnotationService.EXPIRE_NEVER);
376 get keyword() {
377 return Utilities.bookmarks.getKeywordForBookmark(this._id);
380 set keyword(aKeyword) {
381 Utilities.bookmarks.setKeywordForBookmark(this._id, aKeyword);
384 get type() {
385 return this._type;
388 get parent() {
389 return this._parent;
392 set parent(aFolder) {
393 Utilities.bookmarks.moveItem(this._id, aFolder.id, Utilities.bookmarks.DEFAULT_INDEX);
394 // this._parent is updated in onItemMoved
397 get annotations() {
398 return this._annotations;
401 get events() {
402 return this._events;
405 remove : function bm_remove() {
406 Utilities.bookmarks.removeItem(this._id);
409 // observer
410 onBeginUpdateBatch : function bm_obub() {
413 onEndUpdateBatch : function bm_oeub() {
416 onItemAdded : function bm_oia(aId, aFolder, aIndex) {
417 // bookmark object doesn't exist at this point
420 onItemRemoved : function bm_oir(aId, aFolder, aIndex) {
421 if (this._id == aId)
422 this._events.dispatch("remove", aId);
425 onItemChanged : function bm_oic(aId, aProperty, aIsAnnotationProperty, aValue) {
426 if (this._id == aId)
427 this._events.dispatch("change", aProperty);
430 onItemVisited: function bm_oiv(aId, aVisitID, aTime) {
433 onItemMoved: function bm_oim(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
434 if (this._id == aId) {
435 this._parent = new BookmarkFolder(aNewParent, Utilities.bookmarks.getFolderIdForItem(aNewParent));
436 this._events.dispatch("move", aId);
440 QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmark, Ci.nsINavBookmarkObserver])
444 //=================================================
445 // BookmarkFolder implementation
446 function BookmarkFolder(aId, aParent) {
447 this._id = aId;
448 this._parent = aParent;
449 this._annotations = new Annotations(this._id);
450 this._events = new Events();
452 Utilities.bookmarks.addObserver(this, false);
454 var self = this;
455 gShutdown.push(function() { self._shutdown(); });
458 BookmarkFolder.prototype = {
459 _shutdown : function bmf_shutdown() {
460 this._annotations = null;
461 this._events = null;
463 Utilities.bookmarks.removeObserver(this);
466 get id() {
467 return this._id;
470 get title() {
471 return Utilities.bookmarks.getItemTitle(this._id);
474 set title(aTitle) {
475 Utilities.bookmarks.setItemTitle(this._id, aTitle);
478 get description() {
479 return this._annotations.get("bookmarkProperties/description");
482 set description(aDesc) {
483 this._annotations.set("bookmarkProperties/description", aDesc, Ci.nsIAnnotationService.EXPIRE_NEVER);
486 get type() {
487 return "folder";
490 get parent() {
491 return this._parent;
494 set parent(aFolder) {
495 Utilities.bookmarks.moveItem(this._id, aFolder.id, Utilities.bookmarks.DEFAULT_INDEX);
496 // this._parent is updated in onItemMoved
499 get annotations() {
500 return this._annotations;
503 get events() {
504 return this._events;
507 get children() {
508 var items = [];
510 var options = Utilities.history.getNewQueryOptions();
511 var query = Utilities.history.getNewQuery();
512 query.setFolders([this._id], 1);
513 var result = Utilities.history.executeQuery(query, options);
514 var rootNode = result.root;
515 rootNode.containerOpen = true;
516 var cc = rootNode.childCount;
517 for (var i=0; i<cc; ++i) {
518 var node = rootNode.getChild(i);
519 if (node.type == node.RESULT_TYPE_FOLDER) {
520 var folder = new BookmarkFolder(node.itemId, this._id);
521 items.push(folder);
523 else if (node.type == node.RESULT_TYPE_SEPARATOR) {
524 var separator = new Bookmark(node.itemId, this._id, "separator");
525 items.push(separator);
527 else {
528 var bookmark = new Bookmark(node.itemId, this._id, "bookmark");
529 items.push(bookmark);
532 rootNode.containerOpen = false;
534 return items;
537 addBookmark : function bmf_addbm(aTitle, aUri) {
538 var newBookmarkID = Utilities.bookmarks.insertBookmark(this._id, aUri, Utilities.bookmarks.DEFAULT_INDEX, aTitle);
539 var newBookmark = new Bookmark(newBookmarkID, this, "bookmark");
540 return newBookmark;
543 addSeparator : function bmf_addsep() {
544 var newBookmarkID = Utilities.bookmarks.insertSeparator(this._id, Utilities.bookmarks.DEFAULT_INDEX);
545 var newBookmark = new Bookmark(newBookmarkID, this, "separator");
546 return newBookmark;
549 addFolder : function bmf_addfolder(aTitle) {
550 var newFolderID = Utilities.bookmarks.createFolder(this._id, aTitle, Utilities.bookmarks.DEFAULT_INDEX);
551 var newFolder = new BookmarkFolder(newFolderID, this);
552 return newFolder;
555 remove : function bmf_remove() {
556 Utilities.bookmarks.removeFolder(this._id);
559 // observer
560 onBeginUpdateBatch : function bmf_obub() {
563 onEndUpdateBatch : function bmf_oeub() {
566 onItemAdded : function bmf_oia(aId, aFolder, aIndex) {
567 // handle root folder events
568 if (!this._parent)
569 this._events.dispatch("add", aId);
571 // handle this folder events
572 if (this._id == aFolder)
573 this._events.dispatch("addchild", aId);
576 onItemRemoved : function bmf_oir(aId, aFolder, aIndex) {
577 // handle root folder events
578 if (!this._parent || this._id == aId)
579 this._events.dispatch("remove", aId);
581 // handle this folder events
582 if (this._id == aFolder)
583 this._events.dispatch("removechild", aId);
586 onItemChanged : function bmf_oic(aId, aProperty, aIsAnnotationProperty, aValue) {
587 // handle root folder and this folder events
588 if (!this._parent || this._id == aId)
589 this._events.dispatch("change", aProperty);
592 onItemVisited: function bmf_oiv(aId, aVisitID, aTime) {
595 onItemMoved: function bmf_oim(aId, aOldParent, aOldIndex, aNewParent, aNewIndex) {
596 // handle this folder event, root folder cannot be moved
597 if (this._id == aId) {
598 this._parent = new BookmarkFolder(aNewParent, Utilities.bookmarks.getFolderIdForItem(aNewParent));
599 this._events.dispatch("move", aId);
603 QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmarkFolder, Ci.nsINavBookmarkObserver])
606 //=================================================
607 // BookmarkRoots implementation
608 function BookmarkRoots() {
609 var self = this;
610 gShutdown.push(function() { self._shutdown(); });
613 BookmarkRoots.prototype = {
614 _shutdown : function bmr_shutdown() {
615 this._menu = null;
616 this._toolbar = null;
617 this._tags = null;
618 this._unfiled = null;
621 get menu() {
622 if (!this._menu)
623 this._menu = new BookmarkFolder(Utilities.bookmarks.bookmarksMenuFolder, null);
625 return this._menu;
628 get toolbar() {
629 if (!this._toolbar)
630 this._toolbar = new BookmarkFolder(Utilities.bookmarks.toolbarFolder, null);
632 return this._toolbar;
635 get tags() {
636 if (!this._tags)
637 this._tags = new BookmarkFolder(Utilities.bookmarks.tagsFolder, null);
639 return this._tags;
642 get unfiled() {
643 if (!this._unfiled)
644 this._unfiled = new BookmarkFolder(Utilities.bookmarks.unfiledBookmarksFolder, null);
646 return this._unfiled;
649 QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmarkRoots])
653 //=================================================
654 // Factory - Treat Application as a singleton
655 // XXX This is required, because we're registered for the 'JavaScript global
656 // privileged property' category, whose handler always calls createInstance.
657 // See bug 386535.
658 var gSingleton = null;
659 var ApplicationFactory = {
660 createInstance: function af_ci(aOuter, aIID) {
661 if (aOuter != null)
662 throw Components.results.NS_ERROR_NO_AGGREGATION;
664 if (gSingleton == null) {
665 gSingleton = new Application();
668 return gSingleton.QueryInterface(aIID);
674 //=================================================
675 // Application constructor
676 function Application() {
677 this.initToolkitHelpers();
678 this._bookmarks = null;
681 //=================================================
682 // Application implementation
683 Application.prototype = {
684 // for nsIClassInfo + XPCOMUtils
685 classDescription: "Application",
686 classID: Components.ID("fe74cf80-aa2d-11db-abbd-0800200c9a66"),
687 contractID: "@mozilla.org/fuel/application;1",
689 // redefine the default factory for XPCOMUtils
690 _xpcom_factory: ApplicationFactory,
692 // for nsISupports
693 QueryInterface : XPCOMUtils.generateQI([Ci.fuelIApplication, Ci.extIApplication, Ci.nsIObserver, Ci.nsIClassInfo]),
695 getInterfaces : function app_gi(aCount) {
696 var interfaces = [Ci.fuelIApplication, Ci.extIApplication, Ci.nsIObserver, Ci.nsIClassInfo];
697 aCount.value = interfaces.length;
698 return interfaces;
701 // for nsIObserver
702 observe: function app_observe(aSubject, aTopic, aData) {
703 // Call the extApplication version of this function first
704 this.__proto__.__proto__.observe.call(this, aSubject, aTopic, aData);
705 if (aTopic == "xpcom-shutdown") {
706 this._bookmarks = null;
707 Utilities.free();
711 get bookmarks() {
712 if (this._bookmarks == null)
713 this._bookmarks = new BookmarkRoots();
715 return this._bookmarks;
718 get windows() {
719 var win = [];
720 var enum = Utilities.windowMediator.getEnumerator("navigator:browser");
722 while (enum.hasMoreElements())
723 win.push(new Window(enum.getNext()));
725 return win;
728 get activeWindow() {
729 return new Window(Utilities.windowMediator.getMostRecentWindow("navigator:browser"));
733 //module initialization
734 function NSGetModule(aCompMgr, aFileSpec) {
735 // set the proto, defined in extApplication.js
736 Application.prototype.__proto__ = extApplication.prototype;
737 return XPCOMUtils.generateModule([Application]);
740 #include ../../../toolkit/components/exthelper/extApplication.js