diff options
Diffstat (limited to 'testing/specialpowers/content/MockFilePicker.jsm')
-rw-r--r-- | testing/specialpowers/content/MockFilePicker.jsm | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/testing/specialpowers/content/MockFilePicker.jsm b/testing/specialpowers/content/MockFilePicker.jsm new file mode 100644 index 000000000..4c93cd0e2 --- /dev/null +++ b/testing/specialpowers/content/MockFilePicker.jsm @@ -0,0 +1,235 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +this.EXPORTED_SYMBOLS = ["MockFilePicker"]; + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cm = Components.manager; +const Cu = Components.utils; + +const CONTRACT_ID = "@mozilla.org/filepicker;1"; + +Cu.import("resource://gre/modules/FileUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +// Allow stuff from this scope to be accessed from non-privileged scopes. This +// would crash if used outside of automation. +Cu.forcePermissiveCOWs(); + +var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); +var oldClassID, oldFactory; +var newClassID = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID(); +var newFactory = function (window) { + return { + createInstance: function(aOuter, aIID) { + if (aOuter) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return new MockFilePickerInstance(window).QueryInterface(aIID); + }, + lockFactory: function(aLock) { + throw Components.results.NS_ERROR_NOT_IMPLEMENTED; + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) + }; +} + +this.MockFilePicker = { + returnOK: Ci.nsIFilePicker.returnOK, + returnCancel: Ci.nsIFilePicker.returnCancel, + returnReplace: Ci.nsIFilePicker.returnReplace, + + filterAll: Ci.nsIFilePicker.filterAll, + filterHTML: Ci.nsIFilePicker.filterHTML, + filterText: Ci.nsIFilePicker.filterText, + filterImages: Ci.nsIFilePicker.filterImages, + filterXML: Ci.nsIFilePicker.filterXML, + filterXUL: Ci.nsIFilePicker.filterXUL, + filterApps: Ci.nsIFilePicker.filterApps, + filterAllowURLs: Ci.nsIFilePicker.filterAllowURLs, + filterAudio: Ci.nsIFilePicker.filterAudio, + filterVideo: Ci.nsIFilePicker.filterVideo, + + window: null, + + init: function(window) { + this.window = window; + + this.reset(); + this.factory = newFactory(window); + if (!registrar.isCIDRegistered(newClassID)) { + oldClassID = registrar.contractIDToCID(CONTRACT_ID); + oldFactory = Cm.getClassObject(Cc[CONTRACT_ID], Ci.nsIFactory); + registrar.unregisterFactory(oldClassID, oldFactory); + registrar.registerFactory(newClassID, "", CONTRACT_ID, this.factory); + } + }, + + reset: function() { + this.appendFilterCallback = null; + this.appendFiltersCallback = null; + this.displayDirectory = null; + this.filterIndex = 0; + this.mode = null; + this.returnFiles = []; + this.returnValue = null; + this.showCallback = null; + this.shown = false; + this.showing = false; + }, + + cleanup: function() { + var previousFactory = this.factory; + this.reset(); + this.factory = null; + if (oldFactory) { + registrar.unregisterFactory(newClassID, previousFactory); + registrar.registerFactory(oldClassID, "", CONTRACT_ID, oldFactory); + } + }, + + useAnyFile: function() { + var file = FileUtils.getDir("TmpD", [], false); + file.append("testfile"); + file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644); + this.returnFiles = [file]; + }, + + useBlobFile: function() { + var blob = new this.window.Blob([]); + var file = new this.window.File([blob], 'helloworld.txt', { type: 'plain/text' }); + this.returnFiles = [file]; + }, + + useDirectory: function(aPath) { + var directory = new this.window.Directory(aPath); + this.returnFiles = [directory]; + }, + + isNsIFile: function(aFile) { + let ret = false; + try { + if (aFile.QueryInterface(Ci.nsIFile)) + ret = true; + } catch(e) {} + + return ret; + } +}; + +function MockFilePickerInstance(window) { + this.window = window; +}; +MockFilePickerInstance.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIFilePicker]), + init: function(aParent, aTitle, aMode) { + MockFilePicker.mode = aMode; + this.filterIndex = MockFilePicker.filterIndex; + this.parent = aParent; + }, + appendFilter: function(aTitle, aFilter) { + if (typeof MockFilePicker.appendFilterCallback == "function") + MockFilePicker.appendFilterCallback(this, aTitle, aFilter); + }, + appendFilters: function(aFilterMask) { + if (typeof MockFilePicker.appendFiltersCallback == "function") + MockFilePicker.appendFiltersCallback(this, aFilterMask); + }, + defaultString: "", + defaultExtension: "", + parent: null, + filterIndex: 0, + displayDirectory: null, + get file() { + if (MockFilePicker.returnFiles.length >= 1 && + // window.File does not implement nsIFile + MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) { + return MockFilePicker.returnFiles[0]; + } + + return null; + }, + + // We don't support directories here. + get domFileOrDirectory() { + if (MockFilePicker.returnFiles.length >= 1) { + // window.File does not implement nsIFile + if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) { + return MockFilePicker.returnFiles[0]; + } + + let utils = this.parent.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + return utils.wrapDOMFile(MockFilePicker.returnFiles[0]); + } + return null; + }, + get fileURL() { + if (MockFilePicker.returnFiles.length >= 1 && + // window.File does not implement nsIFile + MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) { + return Services.io.newFileURI(MockFilePicker.returnFiles[0]); + } + + return null; + }, + get files() { + return { + index: 0, + QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]), + hasMoreElements: function() { + return this.index < MockFilePicker.returnFiles.length; + }, + getNext: function() { + // window.File does not implement nsIFile + if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[this.index])) { + return null; + } + return MockFilePicker.returnFiles[this.index++]; + } + }; + }, + get domFileOrDirectoryEnumerator() { + let utils = this.parent.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + return { + index: 0, + QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]), + hasMoreElements: function() { + return this.index < MockFilePicker.returnFiles.length; + }, + getNext: function() { + // window.File does not implement nsIFile + if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[this.index])) { + return MockFilePicker.returnFiles[this.index++]; + } + return utils.wrapDOMFile(MockFilePicker.returnFiles[this.index++]); + } + }; + }, + show: function() { + MockFilePicker.displayDirectory = this.displayDirectory; + MockFilePicker.shown = true; + if (typeof MockFilePicker.showCallback == "function") { + var returnValue = MockFilePicker.showCallback(this); + if (typeof returnValue != "undefined") + return returnValue; + } + return MockFilePicker.returnValue; + }, + open: function(aFilePickerShownCallback) { + MockFilePicker.showing = true; + this.window.setTimeout(function() { + let result = Components.interfaces.nsIFilePicker.returnCancel; + try { + result = this.show(); + } catch(ex) { + } + if (aFilePickerShownCallback) { + aFilePickerShownCallback.done(result); + } + }.bind(this), 0); + } +}; |