1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3
* The contents of this file are subject to the Mozilla Public
4
* License Version 1.1 (the "License"); you may not use this file
5
* except in compliance with the License. You may obtain a copy of
6
* the License at http://www.mozilla.org/MPL/
8
* Software distributed under the License is distributed on an "AS
9
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10
* implied. See the License for the specific language governing
11
* rights and limitations under the License.
13
* The Original Code is mozilla.org code.
15
* The Initial Developer of the Original Code is Netscape
16
* Communications Corporation. Portions created by Netscape are
17
* Copyright (C) 2000 Netscape Communications Corporation. All
20
* Contributor(s): Stuart Parmenter <pavlov@netscape.com>
24
* No magic constructor behaviour, as is de rigeur for XPCOM.
25
* If you must perform some initialization, and it could possibly fail (even
26
* due to an out-of-memory condition), you should use an Init method, which
27
* can convey failure appropriately (thrown exception in JS,
28
* NS_FAILED(nsresult) return in C++).
30
* In JS, you can actually cheat, because a thrown exception will cause the
31
* CreateInstance call to fail in turn, but not all languages are so lucky.
32
* (Though ANSI C++ provides exceptions, they are verboten in Mozilla code
33
* for portability reasons -- and even when you're building completely
34
* platform-specific code, you can't throw across an XPCOM method boundary.)
38
const DEBUG = false; /* set to true to enable debug messages */
40
const FILEPICKER_CONTRACTID = "@mozilla.org/filepicker;1";
41
const FILEPICKER_CID = Components.ID("{54ae32f8-1dd2-11b2-a209-df7c505370f8}");
42
const LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1";
43
const APPSHELL_SERV_CONTRACTID = "@mozilla.org/appshell/appShellService;1";
44
const STRBUNDLE_SERV_CONTRACTID = "@mozilla.org/intl/stringbundle;1";
46
const nsIAppShellService = Components.interfaces.nsIAppShellService;
47
const nsILocalFile = Components.interfaces.nsILocalFile;
48
const nsIFileURL = Components.interfaces.nsIFileURL;
49
const nsISupports = Components.interfaces.nsISupports;
50
const nsIFactory = Components.interfaces.nsIFactory;
51
const nsIFilePicker = Components.interfaces.nsIFilePicker;
52
const nsIInterfaceRequestor = Components.interfaces.nsIInterfaceRequestor
53
const nsIDOMWindow = Components.interfaces.nsIDOMWindow;
54
const nsIStringBundleService = Components.interfaces.nsIStringBundleService;
55
const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
56
const nsIDocShellTreeItem = Components.interfaces.nsIDocShellTreeItem;
57
const nsIBaseWindow = Components.interfaces.nsIBaseWindow;
60
var lastDirectory = null;
62
function nsFilePicker()
65
bundle = srGetStrBundle("chrome://global/locale/filepicker.properties");
68
this.mDefaultString = "";
69
this.mFilterIndex = 0;
71
this.mDisplayDirectory = Components.classes[LOCAL_FILE_CONTRACTID].createInstance(nsILocalFile);
72
this.mDisplayDirectory.initWithPath(lastDirectory);
74
this.mDisplayDirectory = null;
76
this.mFilterTitles = new Array();
77
this.mFilters = new Array();
80
nsFilePicker.prototype = {
82
/* attribute nsILocalFile displayDirectory; */
83
set displayDirectory(a) { this.mDisplayDirectory = a; },
84
get displayDirectory() { return this.mDisplayDirectory; },
86
/* readonly attribute nsILocalFile file; */
87
set file(a) { throw "readonly property"; },
88
get file() { return this.mFilesEnumerator.mFiles[0]; },
90
/* readonly attribute nsISimpleEnumerator files; */
91
set files(a) { throw "readonly property"; },
92
get files() { return this.mFilesEnumerator; },
94
/* readonly attribute nsIFileURL fileURL; */
95
set fileURL(a) { throw "readonly property"; },
97
if (this.mFilesEnumerator) {
98
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
99
.getService(Components.interfaces.nsIIOService);
100
var url = ioService.newFileURI(this.file);
106
/* attribute wstring defaultString; */
107
set defaultString(a) { this.mDefaultString = a; },
108
get defaultString() { return this.mDefaultString; },
110
/* attribute wstring defaultExtension */
111
set defaultExtension(ext) { },
112
get defaultExtension() { return ""; },
114
/* attribute long filterIndex; */
115
set filterIndex(a) { this.mFilterIndex = a; },
116
get filterIndex() { return this.mFilterIndex; },
119
mFilesEnumerator: undefined,
123
init: function(parent, title, mode) {
124
this.mParentWindow = parent;
129
appendFilters: function(filterMask) {
130
if (filterMask & nsIFilePicker.filterHTML) {
131
this.appendFilter(bundle.GetStringFromName("htmlTitle"),
132
bundle.GetStringFromName("htmlFilter"));
134
if (filterMask & nsIFilePicker.filterText) {
135
this.appendFilter(bundle.GetStringFromName("textTitle"),
136
bundle.GetStringFromName("textFilter"));
138
if (filterMask & nsIFilePicker.filterImages) {
139
this.appendFilter(bundle.GetStringFromName("imageTitle"),
140
bundle.GetStringFromName("imageFilter"));
142
if (filterMask & nsIFilePicker.filterXML) {
143
this.appendFilter(bundle.GetStringFromName("xmlTitle"),
144
bundle.GetStringFromName("xmlFilter"));
146
if (filterMask & nsIFilePicker.filterXUL) {
147
this.appendFilter(bundle.GetStringFromName("xulTitle"),
148
bundle.GetStringFromName("xulFilter"));
150
if (filterMask & nsIFilePicker.filterApps) {
151
// We use "..apps" as a special filter for executable files
152
this.appendFilter(bundle.GetStringFromName("appsTitle"),
155
if (filterMask & nsIFilePicker.filterAll) {
156
this.appendFilter(bundle.GetStringFromName("allTitle"),
157
bundle.GetStringFromName("allFilter"));
161
appendFilter: function(title, extensions) {
162
this.mFilterTitles.push(title);
163
this.mFilters.push(extensions);
166
QueryInterface: function(iid) {
167
if (!iid.equals(nsIFilePicker) &&
168
!iid.equals(nsISupports))
169
throw Components.results.NS_ERROR_NO_INTERFACE;
174
var o = new Object();
175
o.title = this.mTitle;
177
o.displayDirectory = this.mDisplayDirectory;
178
o.defaultString = this.mDefaultString;
179
o.filterIndex = this.mFilterIndex;
180
o.filters = new Object();
181
o.filters.titles = this.mFilterTitles;
182
o.filters.types = this.mFilters;
183
o.retvals = new Object();
186
if (this.mParentWindow) {
187
parent = this.mParentWindow;
188
} else if (typeof(window) == "object" && window != null) {
192
var appShellService = Components.classes[APPSHELL_SERV_CONTRACTID].getService(nsIAppShellService);
193
parent = appShellService.hiddenDOMWindow;
195
debug("Can't get parent. xpconnect hates me so we can't get one from the appShellService.\n");
200
var parentWin = null;
202
parentWin = parent.QueryInterface(nsIInterfaceRequestor)
203
.getInterface(nsIWebNavigation)
204
.QueryInterface(nsIDocShellTreeItem)
206
.QueryInterface(nsIInterfaceRequestor)
207
.getInterface(nsIBaseWindow);
209
dump("file picker couldn't get base window\n"+ex+"\n");
213
parentWin.blurSuppression = true;
214
parent.openDialog("chrome://global/content/filepicker.xul",
216
"chrome,modal,titlebar,resizable=yes,dependent=yes",
219
parentWin.blurSuppression = false;
221
this.mFilterIndex = o.retvals.filterIndex;
222
this.mFilesEnumerator = o.retvals.files;
223
lastDirectory = o.retvals.directory;
224
return o.retvals.buttonStatus;
225
} catch(ex) { dump("unable to open file picker\n" + ex + "\n"); }
232
debug = function (s) { dump("-*- filepicker: " + s + "\n"); }
234
debug = function (s) {}
238
var filePickerModule = new Object();
240
filePickerModule.registerSelf =
241
function (compMgr, fileSpec, location, type)
243
debug("registering (all right -- a JavaScript module!)");
244
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
246
compMgr.registerFactoryLocation(FILEPICKER_CID,
247
"FilePicker JS Component",
254
filePickerModule.getClassObject =
255
function (compMgr, cid, iid) {
256
if (!cid.equals(FILEPICKER_CID))
257
throw Components.results.NS_ERROR_NO_INTERFACE;
259
if (!iid.equals(Components.interfaces.nsIFactory))
260
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
262
return filePickerFactory;
265
filePickerModule.canUnload =
268
debug("Unloading component.");
273
var filePickerFactory = new Object();
275
filePickerFactory.createInstance =
276
function (outer, iid) {
278
debug("IID:" + nsIFilePicker);
280
throw Components.results.NS_ERROR_NO_AGGREGATION;
282
return (new nsFilePicker()).QueryInterface(iid);
286
function NSGetModule(compMgr, fileSpec) {
287
return filePickerModule;
292
/* crap from strres.js that I want to use for string bundles since I can't include another .js file.... */
294
var strBundleService = null;
296
function srGetStrBundle(path)
298
var strBundle = null;
300
if (!strBundleService) {
302
strBundleService = Components.classes[STRBUNDLE_SERV_CONTRACTID].getService(nsIStringBundleService);
304
dump("\n--** strBundleService createInstance failed **--\n");
309
strBundle = strBundleService.createBundle(path);
311
dump("\n--** strBundle createInstance failed **--\n");