michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: this.EXPORTED_SYMBOLS = ["MockFilePicker"]; michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cm = Components.manager; michael@0: const Cu = Components.utils; michael@0: michael@0: const CONTRACT_ID = "@mozilla.org/filepicker;1"; michael@0: michael@0: Cu.import("resource://gre/modules/FileUtils.jsm"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: michael@0: var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); michael@0: var oldClassID, oldFactory; michael@0: var newClassID = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID(); michael@0: var newFactory = function (window) { michael@0: return { michael@0: createInstance: function(aOuter, aIID) { michael@0: if (aOuter) michael@0: throw Components.results.NS_ERROR_NO_AGGREGATION; michael@0: return new MockFilePickerInstance(window).QueryInterface(aIID); michael@0: }, michael@0: lockFactory: function(aLock) { michael@0: throw Components.results.NS_ERROR_NOT_IMPLEMENTED; michael@0: }, michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) michael@0: }; michael@0: } michael@0: michael@0: this.MockFilePicker = { michael@0: returnOK: Ci.nsIFilePicker.returnOK, michael@0: returnCancel: Ci.nsIFilePicker.returnCancel, michael@0: returnReplace: Ci.nsIFilePicker.returnReplace, michael@0: michael@0: filterAll: Ci.nsIFilePicker.filterAll, michael@0: filterHTML: Ci.nsIFilePicker.filterHTML, michael@0: filterText: Ci.nsIFilePicker.filterText, michael@0: filterImages: Ci.nsIFilePicker.filterImages, michael@0: filterXML: Ci.nsIFilePicker.filterXML, michael@0: filterXUL: Ci.nsIFilePicker.filterXUL, michael@0: filterApps: Ci.nsIFilePicker.filterApps, michael@0: filterAllowURLs: Ci.nsIFilePicker.filterAllowURLs, michael@0: filterAudio: Ci.nsIFilePicker.filterAudio, michael@0: filterVideo: Ci.nsIFilePicker.filterVideo, michael@0: michael@0: window: null, michael@0: michael@0: init: function(window) { michael@0: this.window = window; michael@0: michael@0: this.reset(); michael@0: this.factory = newFactory(window); michael@0: if (!registrar.isCIDRegistered(newClassID)) { michael@0: oldClassID = registrar.contractIDToCID(CONTRACT_ID); michael@0: oldFactory = Cm.getClassObject(Cc[CONTRACT_ID], Ci.nsIFactory); michael@0: registrar.unregisterFactory(oldClassID, oldFactory); michael@0: registrar.registerFactory(newClassID, "", CONTRACT_ID, this.factory); michael@0: } michael@0: }, michael@0: michael@0: reset: function() { michael@0: this.appendFilterCallback = null; michael@0: this.appendFiltersCallback = null; michael@0: this.displayDirectory = null; michael@0: this.filterIndex = 0; michael@0: this.mode = null; michael@0: this.returnFiles = []; michael@0: this.returnValue = null; michael@0: this.showCallback = null; michael@0: this.shown = false; michael@0: this.showing = false; michael@0: }, michael@0: michael@0: cleanup: function() { michael@0: var previousFactory = this.factory; michael@0: this.reset(); michael@0: this.factory = null; michael@0: if (oldFactory) { michael@0: registrar.unregisterFactory(newClassID, previousFactory); michael@0: registrar.registerFactory(oldClassID, "", CONTRACT_ID, oldFactory); michael@0: } michael@0: }, michael@0: michael@0: useAnyFile: function() { michael@0: var file = FileUtils.getDir("TmpD", [], false); michael@0: file.append("testfile"); michael@0: file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0644); michael@0: this.returnFiles = [file]; michael@0: }, michael@0: michael@0: useBlobFile: function() { michael@0: var blob = new this.window.Blob([]); michael@0: var file = new this.window.File(blob, { name: 'helloworld.txt', type: 'plain/text' }); michael@0: this.returnFiles = [file]; michael@0: }, michael@0: michael@0: isNsIFile: function(aFile) { michael@0: let ret = false; michael@0: try { michael@0: if (aFile.QueryInterface(Ci.nsIFile)) michael@0: ret = true; michael@0: } catch(e) {} michael@0: michael@0: return ret; michael@0: } michael@0: }; michael@0: michael@0: function MockFilePickerInstance(window) { michael@0: this.window = window; michael@0: }; michael@0: MockFilePickerInstance.prototype = { michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIFilePicker]), michael@0: init: function(aParent, aTitle, aMode) { michael@0: MockFilePicker.mode = aMode; michael@0: this.filterIndex = MockFilePicker.filterIndex; michael@0: this.parent = aParent; michael@0: }, michael@0: appendFilter: function(aTitle, aFilter) { michael@0: if (typeof MockFilePicker.appendFilterCallback == "function") michael@0: MockFilePicker.appendFilterCallback(this, aTitle, aFilter); michael@0: }, michael@0: appendFilters: function(aFilterMask) { michael@0: if (typeof MockFilePicker.appendFiltersCallback == "function") michael@0: MockFilePicker.appendFiltersCallback(this, aFilterMask); michael@0: }, michael@0: defaultString: "", michael@0: defaultExtension: "", michael@0: parent: null, michael@0: filterIndex: 0, michael@0: displayDirectory: null, michael@0: get file() { michael@0: if (MockFilePicker.returnFiles.length >= 1 && michael@0: // window.File does not implement nsIFile michael@0: MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) { michael@0: return MockFilePicker.returnFiles[0]; michael@0: } michael@0: michael@0: return null; michael@0: }, michael@0: get domfile() { michael@0: if (MockFilePicker.returnFiles.length >= 1) { michael@0: // window.File does not implement nsIFile michael@0: if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) { michael@0: return MockFilePicker.returnFiles[0]; michael@0: } michael@0: michael@0: let utils = this.parent.QueryInterface(Ci.nsIInterfaceRequestor) michael@0: .getInterface(Ci.nsIDOMWindowUtils); michael@0: return utils.wrapDOMFile(MockFilePicker.returnFiles[0]); michael@0: } michael@0: return null; michael@0: }, michael@0: get fileURL() { michael@0: if (MockFilePicker.returnFiles.length >= 1 && michael@0: // window.File does not implement nsIFile michael@0: MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) { michael@0: return Services.io.newFileURI(MockFilePicker.returnFiles[0]); michael@0: } michael@0: michael@0: return null; michael@0: }, michael@0: get files() { michael@0: return { michael@0: index: 0, michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]), michael@0: hasMoreElements: function() { michael@0: return this.index < MockFilePicker.returnFiles.length; michael@0: }, michael@0: getNext: function() { michael@0: // window.File does not implement nsIFile michael@0: if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[this.index])) { michael@0: return null; michael@0: } michael@0: return MockFilePicker.returnFiles[this.index++]; michael@0: } michael@0: }; michael@0: }, michael@0: get domfiles() { michael@0: let utils = this.parent.QueryInterface(Ci.nsIInterfaceRequestor) michael@0: .getInterface(Ci.nsIDOMWindowUtils); michael@0: return { michael@0: index: 0, michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]), michael@0: hasMoreElements: function() { michael@0: return this.index < MockFilePicker.returnFiles.length; michael@0: }, michael@0: getNext: function() { michael@0: // window.File does not implement nsIFile michael@0: if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[this.index])) { michael@0: return MockFilePicker.returnFiles[this.index++]; michael@0: } michael@0: return utils.wrapDOMFile(MockFilePicker.returnFiles[this.index++]); michael@0: } michael@0: }; michael@0: }, michael@0: show: function() { michael@0: MockFilePicker.displayDirectory = this.displayDirectory; michael@0: MockFilePicker.shown = true; michael@0: if (typeof MockFilePicker.showCallback == "function") { michael@0: var returnValue = MockFilePicker.showCallback(this); michael@0: if (typeof returnValue != "undefined") michael@0: return returnValue; michael@0: } michael@0: return MockFilePicker.returnValue; michael@0: }, michael@0: open: function(aFilePickerShownCallback) { michael@0: MockFilePicker.showing = true; michael@0: this.window.setTimeout(function() { michael@0: let result = Components.interfaces.nsIFilePicker.returnCancel; michael@0: try { michael@0: result = this.show(); michael@0: } catch(ex) { michael@0: } michael@0: if (aFilePickerShownCallback) { michael@0: aFilePickerShownCallback.done(result); michael@0: } michael@0: }.bind(this), 0); michael@0: } michael@0: }; michael@0: michael@0: // Expose everything to content. We call reset() here so that all of the relevant michael@0: // lazy expandos get added. michael@0: MockFilePicker.reset(); michael@0: function exposeAll(obj) { michael@0: var props = {}; michael@0: for (var prop in obj) michael@0: props[prop] = 'rw'; michael@0: obj.__exposedProps__ = props; michael@0: } michael@0: exposeAll(MockFilePicker); michael@0: exposeAll(MockFilePickerInstance.prototype);