|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 this.EXPORTED_SYMBOLS = ["MockFilePicker"]; |
|
6 |
|
7 const Cc = Components.classes; |
|
8 const Ci = Components.interfaces; |
|
9 const Cm = Components.manager; |
|
10 const Cu = Components.utils; |
|
11 |
|
12 const CONTRACT_ID = "@mozilla.org/filepicker;1"; |
|
13 |
|
14 Cu.import("resource://gre/modules/FileUtils.jsm"); |
|
15 Cu.import("resource://gre/modules/Services.jsm"); |
|
16 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
17 |
|
18 var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); |
|
19 var oldClassID, oldFactory; |
|
20 var newClassID = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID(); |
|
21 var newFactory = function (window) { |
|
22 return { |
|
23 createInstance: function(aOuter, aIID) { |
|
24 if (aOuter) |
|
25 throw Components.results.NS_ERROR_NO_AGGREGATION; |
|
26 return new MockFilePickerInstance(window).QueryInterface(aIID); |
|
27 }, |
|
28 lockFactory: function(aLock) { |
|
29 throw Components.results.NS_ERROR_NOT_IMPLEMENTED; |
|
30 }, |
|
31 QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) |
|
32 }; |
|
33 } |
|
34 |
|
35 this.MockFilePicker = { |
|
36 returnOK: Ci.nsIFilePicker.returnOK, |
|
37 returnCancel: Ci.nsIFilePicker.returnCancel, |
|
38 returnReplace: Ci.nsIFilePicker.returnReplace, |
|
39 |
|
40 filterAll: Ci.nsIFilePicker.filterAll, |
|
41 filterHTML: Ci.nsIFilePicker.filterHTML, |
|
42 filterText: Ci.nsIFilePicker.filterText, |
|
43 filterImages: Ci.nsIFilePicker.filterImages, |
|
44 filterXML: Ci.nsIFilePicker.filterXML, |
|
45 filterXUL: Ci.nsIFilePicker.filterXUL, |
|
46 filterApps: Ci.nsIFilePicker.filterApps, |
|
47 filterAllowURLs: Ci.nsIFilePicker.filterAllowURLs, |
|
48 filterAudio: Ci.nsIFilePicker.filterAudio, |
|
49 filterVideo: Ci.nsIFilePicker.filterVideo, |
|
50 |
|
51 window: null, |
|
52 |
|
53 init: function(window) { |
|
54 this.window = window; |
|
55 |
|
56 this.reset(); |
|
57 this.factory = newFactory(window); |
|
58 if (!registrar.isCIDRegistered(newClassID)) { |
|
59 oldClassID = registrar.contractIDToCID(CONTRACT_ID); |
|
60 oldFactory = Cm.getClassObject(Cc[CONTRACT_ID], Ci.nsIFactory); |
|
61 registrar.unregisterFactory(oldClassID, oldFactory); |
|
62 registrar.registerFactory(newClassID, "", CONTRACT_ID, this.factory); |
|
63 } |
|
64 }, |
|
65 |
|
66 reset: function() { |
|
67 this.appendFilterCallback = null; |
|
68 this.appendFiltersCallback = null; |
|
69 this.displayDirectory = null; |
|
70 this.filterIndex = 0; |
|
71 this.mode = null; |
|
72 this.returnFiles = []; |
|
73 this.returnValue = null; |
|
74 this.showCallback = null; |
|
75 this.shown = false; |
|
76 this.showing = false; |
|
77 }, |
|
78 |
|
79 cleanup: function() { |
|
80 var previousFactory = this.factory; |
|
81 this.reset(); |
|
82 this.factory = null; |
|
83 if (oldFactory) { |
|
84 registrar.unregisterFactory(newClassID, previousFactory); |
|
85 registrar.registerFactory(oldClassID, "", CONTRACT_ID, oldFactory); |
|
86 } |
|
87 }, |
|
88 |
|
89 useAnyFile: function() { |
|
90 var file = FileUtils.getDir("TmpD", [], false); |
|
91 file.append("testfile"); |
|
92 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0644); |
|
93 this.returnFiles = [file]; |
|
94 }, |
|
95 |
|
96 useBlobFile: function() { |
|
97 var blob = new this.window.Blob([]); |
|
98 var file = new this.window.File(blob, { name: 'helloworld.txt', type: 'plain/text' }); |
|
99 this.returnFiles = [file]; |
|
100 }, |
|
101 |
|
102 isNsIFile: function(aFile) { |
|
103 let ret = false; |
|
104 try { |
|
105 if (aFile.QueryInterface(Ci.nsIFile)) |
|
106 ret = true; |
|
107 } catch(e) {} |
|
108 |
|
109 return ret; |
|
110 } |
|
111 }; |
|
112 |
|
113 function MockFilePickerInstance(window) { |
|
114 this.window = window; |
|
115 }; |
|
116 MockFilePickerInstance.prototype = { |
|
117 QueryInterface: XPCOMUtils.generateQI([Ci.nsIFilePicker]), |
|
118 init: function(aParent, aTitle, aMode) { |
|
119 MockFilePicker.mode = aMode; |
|
120 this.filterIndex = MockFilePicker.filterIndex; |
|
121 this.parent = aParent; |
|
122 }, |
|
123 appendFilter: function(aTitle, aFilter) { |
|
124 if (typeof MockFilePicker.appendFilterCallback == "function") |
|
125 MockFilePicker.appendFilterCallback(this, aTitle, aFilter); |
|
126 }, |
|
127 appendFilters: function(aFilterMask) { |
|
128 if (typeof MockFilePicker.appendFiltersCallback == "function") |
|
129 MockFilePicker.appendFiltersCallback(this, aFilterMask); |
|
130 }, |
|
131 defaultString: "", |
|
132 defaultExtension: "", |
|
133 parent: null, |
|
134 filterIndex: 0, |
|
135 displayDirectory: null, |
|
136 get file() { |
|
137 if (MockFilePicker.returnFiles.length >= 1 && |
|
138 // window.File does not implement nsIFile |
|
139 MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) { |
|
140 return MockFilePicker.returnFiles[0]; |
|
141 } |
|
142 |
|
143 return null; |
|
144 }, |
|
145 get domfile() { |
|
146 if (MockFilePicker.returnFiles.length >= 1) { |
|
147 // window.File does not implement nsIFile |
|
148 if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) { |
|
149 return MockFilePicker.returnFiles[0]; |
|
150 } |
|
151 |
|
152 let utils = this.parent.QueryInterface(Ci.nsIInterfaceRequestor) |
|
153 .getInterface(Ci.nsIDOMWindowUtils); |
|
154 return utils.wrapDOMFile(MockFilePicker.returnFiles[0]); |
|
155 } |
|
156 return null; |
|
157 }, |
|
158 get fileURL() { |
|
159 if (MockFilePicker.returnFiles.length >= 1 && |
|
160 // window.File does not implement nsIFile |
|
161 MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) { |
|
162 return Services.io.newFileURI(MockFilePicker.returnFiles[0]); |
|
163 } |
|
164 |
|
165 return null; |
|
166 }, |
|
167 get files() { |
|
168 return { |
|
169 index: 0, |
|
170 QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]), |
|
171 hasMoreElements: function() { |
|
172 return this.index < MockFilePicker.returnFiles.length; |
|
173 }, |
|
174 getNext: function() { |
|
175 // window.File does not implement nsIFile |
|
176 if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[this.index])) { |
|
177 return null; |
|
178 } |
|
179 return MockFilePicker.returnFiles[this.index++]; |
|
180 } |
|
181 }; |
|
182 }, |
|
183 get domfiles() { |
|
184 let utils = this.parent.QueryInterface(Ci.nsIInterfaceRequestor) |
|
185 .getInterface(Ci.nsIDOMWindowUtils); |
|
186 return { |
|
187 index: 0, |
|
188 QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]), |
|
189 hasMoreElements: function() { |
|
190 return this.index < MockFilePicker.returnFiles.length; |
|
191 }, |
|
192 getNext: function() { |
|
193 // window.File does not implement nsIFile |
|
194 if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[this.index])) { |
|
195 return MockFilePicker.returnFiles[this.index++]; |
|
196 } |
|
197 return utils.wrapDOMFile(MockFilePicker.returnFiles[this.index++]); |
|
198 } |
|
199 }; |
|
200 }, |
|
201 show: function() { |
|
202 MockFilePicker.displayDirectory = this.displayDirectory; |
|
203 MockFilePicker.shown = true; |
|
204 if (typeof MockFilePicker.showCallback == "function") { |
|
205 var returnValue = MockFilePicker.showCallback(this); |
|
206 if (typeof returnValue != "undefined") |
|
207 return returnValue; |
|
208 } |
|
209 return MockFilePicker.returnValue; |
|
210 }, |
|
211 open: function(aFilePickerShownCallback) { |
|
212 MockFilePicker.showing = true; |
|
213 this.window.setTimeout(function() { |
|
214 let result = Components.interfaces.nsIFilePicker.returnCancel; |
|
215 try { |
|
216 result = this.show(); |
|
217 } catch(ex) { |
|
218 } |
|
219 if (aFilePickerShownCallback) { |
|
220 aFilePickerShownCallback.done(result); |
|
221 } |
|
222 }.bind(this), 0); |
|
223 } |
|
224 }; |
|
225 |
|
226 // Expose everything to content. We call reset() here so that all of the relevant |
|
227 // lazy expandos get added. |
|
228 MockFilePicker.reset(); |
|
229 function exposeAll(obj) { |
|
230 var props = {}; |
|
231 for (var prop in obj) |
|
232 props[prop] = 'rw'; |
|
233 obj.__exposedProps__ = props; |
|
234 } |
|
235 exposeAll(MockFilePicker); |
|
236 exposeAll(MockFilePickerInstance.prototype); |