Bug 1335539 - Get rid of nsIDOMWindowUtils.wrapDOMFile, r=smaug, r=Gijs

This commit is contained in:
Andrea Marchesini 2017-03-03 09:42:54 +01:00
parent 24004054a8
commit 4d21d3a57a
35 changed files with 261 additions and 210 deletions

View File

@ -40,7 +40,7 @@ function triggerSave(aWindow, aCallback) {
fileName = fp.defaultString;
info("fileName: " + fileName);
destFile.append(fileName);
MockFilePicker.returnFiles = [destFile];
MockFilePicker.setFiles([destFile]);
MockFilePicker.filterIndex = 1; // kSaveAsType_URL
info("done showCallback");
};

View File

@ -45,7 +45,7 @@ function triggerSave(aWindow, aCallback) {
fileName = fp.defaultString;
info("fileName: " + fileName);
destFile.append(fileName);
MockFilePicker.returnFiles = [destFile];
MockFilePicker.setFiles([destFile]);
MockFilePicker.filterIndex = 1; // kSaveAsType_URL
info("done showCallback");
};

View File

@ -58,7 +58,7 @@ function promiseImageDownloaded() {
MockFilePicker.showCallback = function(fp) {
fileName = fp.defaultString;
destFile.append(fileName);
MockFilePicker.returnFiles = [destFile];
MockFilePicker.setFiles([destFile]);
MockFilePicker.filterIndex = 1; // kSaveAsType_URL
};

View File

@ -34,7 +34,7 @@ add_task(function* () {
MockFilePicker.showCallback = function(fp) {
fileName = fp.defaultString;
destFile.append(fileName);
MockFilePicker.returnFiles = [destFile];
MockFilePicker.setFiles([destFile]);
MockFilePicker.filterIndex = 1; // kSaveAsType_URL
};

View File

@ -85,7 +85,7 @@ add_task(function*() {
MockFilePicker.displayDirectory = destDir;
MockFilePicker.showCallback = function(fp) {
destFile.append(fp.defaultString);
MockFilePicker.returnFiles = [destFile];
MockFilePicker.setFiles([destFile]);
MockFilePicker.filterIndex = 1; // kSaveAsType_URL
};

View File

@ -10,14 +10,14 @@ async function installFile(filename) {
let MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init(window);
MockFilePicker.returnFiles = [file];
MockFilePicker.setFiles([file]);
MockFilePicker.afterOpenCallback = MockFilePicker.cleanup;
await BrowserOpenAddonsMgr("addons://list/extension");
let contentWin = gBrowser.selectedTab.linkedBrowser.contentWindow;
// Do the install...
contentWin.gViewController.doCommand("cmd_installFromFile");
MockFilePicker.cleanup();
}
add_task(() => testInstallMethod(installFile));

View File

@ -55,7 +55,7 @@ function test() {
is(gDownloadLastDir.file.path, aDisplayDir.path,
"gDownloadLastDir should be the expected display dir");
MockFilePicker.returnFiles = [aFile];
MockFilePicker.setFiles([aFile]);
MockFilePicker.displayDirectory = null;
launcher.saveDestinationAvailable = function(file) {

View File

@ -62,7 +62,7 @@ function test() {
is(gDownloadLastDir.file.path, aDisplayDir.path,
"gDownloadLastDir should be the expected display dir");
MockFilePicker.returnFiles = [aFile];
MockFilePicker.setFiles([aFile]);
MockFilePicker.displayDirectory = null;
aWin.promiseTargetFile(params).then(function() {
// File picker should start with expected display dir.

View File

@ -23,7 +23,7 @@ add_task(function* () {
});
add_task(function* () {
let { tab, document } = yield openAboutDebugging("addons");
let { tab, document, window } = yield openAboutDebugging("addons");
yield waitForInitialAddonList(document);
// Start an observer that looks for the install error before
@ -33,9 +33,9 @@ add_task(function* () {
// Mock the file picker to select a test addon
let MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init(null);
MockFilePicker.init(window);
let file = getSupportsFile("addons/bad/manifest.json");
MockFilePicker.returnFiles = [file.file];
MockFilePicker.setFiles([file.file]);
// Trigger the file picker by clicking on the button
document.getElementById("load-addon-from-file").click();

View File

@ -35,12 +35,13 @@ function* openAboutDebugging(page, win) {
let tab = yield addTab(url, { window: win });
let browser = tab.linkedBrowser;
let document = browser.contentDocument;
let window = browser.contentWindow;
if (!document.querySelector(".app")) {
yield waitForMutation(document.body, { childList: true });
}
return { tab, document };
return { tab, document, window };
}
/**
@ -115,7 +116,7 @@ function* installAddon({document, path, name, isWebExtension}) {
let MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init(window);
let file = getSupportsFile(path);
MockFilePicker.returnFiles = [file.file];
MockFilePicker.setFiles([file.file]);
let addonList = getAddonList(document);
let addonListMutation = waitForMutation(addonList, { childList: true });

View File

@ -190,7 +190,7 @@
// Pick custom binary, but act like the user aborted the file picker.
MockFilePicker.returnFiles = [];
MockFilePicker.setFiles([]);
yield set(form.version, "pick");
is(form.version.value, sim20.addonID, "Version selector reverted to last valid choice after customization abort");
@ -198,10 +198,10 @@
// Pick custom binary, and actually follow through. (success, verify value = "custom" and textContent = custom path)
MockFilePicker.useAnyFile();
yield MockFilePicker.useAnyFile();
yield set(form.version, "pick");
let fakeBinary = MockFilePicker.returnFiles[0];
let fakeBinary = MockFilePicker.file;
ok(form.version.value == "custom", "Version selector was set to a new custom binary");
ok(form.version.classList.contains("custom"), "Version selector is now customized");
@ -221,7 +221,7 @@
is(form.profile.value, "default", "Default simulator profile");
ok(!form.profile.classList.contains("custom"), "Profile selector is not customized");
MockFilePicker.returnFiles = [];
MockFilePicker.setFiles([]);
yield set(form.profile, "pick");
is(form.profile.value, "default", "Profile selector reverted to last valid choice after customization abort");
@ -229,7 +229,7 @@
let fakeProfile = FileUtils.getDir("TmpD", []);
MockFilePicker.returnFiles = [ fakeProfile ];
MockFilePicker.setFiles([ fakeProfile ]);
yield set(form.profile, "pick");
ok(form.profile.value == "custom", "Profile selector was set to a new custom directory");

View File

@ -2810,27 +2810,6 @@ nsDOMWindowUtils::GetContainerElement(nsIDOMElement** aResult)
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::WrapDOMFile(nsIFile *aFile,
nsISupports **aDOMFile)
{
if (!aFile) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
NS_ENSURE_STATE(window);
nsPIDOMWindowInner* innerWindow = window->GetCurrentInnerWindow();
if (!innerWindow) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMBlob> blob = File::CreateFromFile(innerWindow, aFile);
blob.forget(aDOMFile);
return NS_OK;
}
#ifdef DEBUG
static bool
CheckLeafLayers(Layer* aLayer, const nsIntPoint& aOffset, nsIntRegion* aCoveredRegion)

View File

@ -532,7 +532,6 @@ skip-if = toolkit == 'android' #bug 687032
[test_bug787778.html]
[test_bug789315.html]
[test_bug789856.html]
[test_bug793311.html]
[test_bug804395.html]
[test_bug809003.html]
[test_bug810494.html]

View File

@ -1,35 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=793311
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 793311</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug {793311} **/
SimpleTest.waitForExplicitFinish();
try {
SpecialPowers.DOMWindowUtils.wrapDOMFile(null);
ok(false, "wrapDOMFile(null) throws an exception");
} catch(e) {
ok(true, "wrapDOMFile(null) throws an exception");
}
SimpleTest.finish();
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=793311">Mozilla Bug 793311</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -50,6 +50,16 @@ public:
virtual bool IsSizeUnknown() const override { return false; }
virtual bool IsDateUnknown() const override { return false; }
void SetName(const nsAString& aName)
{
mName = aName;
}
void SetType(const nsAString& aType)
{
mContentType = aType;
}
protected:
virtual ~FileBlobImpl() = default;

View File

@ -82,7 +82,8 @@ FileCreatorHelper::CreateFileInternal(nsPIDOMWindowInner* aWindow,
RefPtr<BlobImpl> blobImpl;
aRv = CreateBlobImpl(aFile, aBag.mType, aBag.mName, lastModifiedPassed,
lastModified, aIsFromNsIFile, getter_AddRefs(blobImpl));
lastModified, aBag.mExistenceCheck, aIsFromNsIFile,
getter_AddRefs(blobImpl));
if (aRv.Failed()) {
return nullptr;
}
@ -130,7 +131,8 @@ FileCreatorHelper::SendRequest(nsIFile* aFile,
}
cc->FileCreationRequest(uuid, this, path, aBag.mType, aBag.mName,
aBag.mLastModified, aIsFromNsIFile);
aBag.mLastModified, aBag.mExistenceCheck,
aIsFromNsIFile);
}
void
@ -151,6 +153,7 @@ FileCreatorHelper::CreateBlobImplForIPC(const nsAString& aPath,
const nsAString& aName,
bool aLastModifiedPassed,
int64_t aLastModified,
bool aExistenceCheck,
bool aIsFromNsIFile,
BlobImpl** aBlobImpl)
{
@ -161,7 +164,7 @@ FileCreatorHelper::CreateBlobImplForIPC(const nsAString& aPath,
}
return CreateBlobImpl(file, aType, aName, aLastModifiedPassed, aLastModified,
aIsFromNsIFile, aBlobImpl);
aExistenceCheck, aIsFromNsIFile, aBlobImpl);
}
/* static */ nsresult
@ -170,9 +173,29 @@ FileCreatorHelper::CreateBlobImpl(nsIFile* aFile,
const nsAString& aName,
bool aLastModifiedPassed,
int64_t aLastModified,
bool aExistenceCheck,
bool aIsFromNsIFile,
BlobImpl** aBlobImpl)
{
if (!aExistenceCheck) {
RefPtr<FileBlobImpl> impl = new FileBlobImpl(aFile);
if (!aName.IsEmpty()) {
impl->SetName(aName);
}
if (!aType.IsEmpty()) {
impl->SetType(aType);
}
if (aLastModifiedPassed) {
impl->SetLastModified(aLastModified);
}
impl.forget(aBlobImpl);
return NS_OK;
}
RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
nsresult rv =
impl->InitializeChromeFile(aFile, aType, aName, aLastModifiedPassed,

View File

@ -51,6 +51,7 @@ public:
const nsAString& aName,
bool aLastModifiedPassed,
int64_t aLastModified,
bool aExistenceCheck,
bool aIsFromNsIFile,
BlobImpl** aBlobImpl);
@ -68,6 +69,7 @@ private:
const nsAString& aName,
bool aLastModifiedPassed,
int64_t aLastModified,
bool aExistenceCheck,
bool aIsFromNsIFile,
BlobImpl** aBlobImpl);

View File

@ -1563,12 +1563,6 @@ interface nsIDOMWindowUtils : nsISupports {
in AString value1,
in AString value2);
/**
* Wrap an nsIFile in an DOM File
* Returns a File object.
*/
nsISupports wrapDOMFile(in nsIFile aFile);
/**
* Get the type of the currently focused html input, if any.
*/

View File

@ -3175,6 +3175,7 @@ ContentChild::FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
const nsAString& aType,
const nsAString& aName,
const Optional<int64_t>& aLastModified,
bool aExistenceCheck,
bool aIsFromNsIFile)
{
MOZ_ASSERT(aHelper);
@ -3188,7 +3189,8 @@ ContentChild::FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
Unused << SendFileCreationRequest(aUUID, nsString(aFullPath), nsString(aType),
nsString(aName), lastModifiedPassed,
lastModified, aIsFromNsIFile);
lastModified, aExistenceCheck,
aIsFromNsIFile);
mFileCreationPending.Put(aUUID, aHelper);
}

View File

@ -633,7 +633,7 @@ public:
const nsAString& aFullPath, const nsAString& aType,
const nsAString& aName,
const Optional<int64_t>& aLastModified,
bool aIsFromNsIFile);
bool aExistenceCheck, bool aIsFromNsIFile);
private:
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);

View File

@ -5145,13 +5145,15 @@ ContentParent::RecvFileCreationRequest(const nsID& aID,
const nsString& aName,
const bool& aLastModifiedPassed,
const int64_t& aLastModified,
const bool& aExistenceCheck,
const bool& aIsFromNsIFile)
{
RefPtr<BlobImpl> blobImpl;
nsresult rv =
FileCreatorHelper::CreateBlobImplForIPC(aFullPath, aType, aName,
aLastModifiedPassed,
aLastModified, aIsFromNsIFile,
aLastModified, aExistenceCheck,
aIsFromNsIFile,
getter_AddRefs(blobImpl));
if (NS_WARN_IF(NS_FAILED(rv))) {
if (!SendFileCreationResponse(aID, FileCreationErrorResult(rv))) {

View File

@ -1112,6 +1112,7 @@ private:
const nsString& aType, const nsString& aName,
const bool& aLastModifiedPassed,
const int64_t& aLastModified,
const bool& aExistenceCheck,
const bool& aIsFromNsIFile) override;
virtual mozilla::ipc::IPCResult RecvAccumulateChildHistograms(

View File

@ -1177,7 +1177,8 @@ parent:
async FileCreationRequest(nsID aID, nsString aFullPath, nsString aType,
nsString aName, bool lastModifiedPassed,
int64_t lastModified, bool aIsFromNsIFile);
int64_t lastModified, bool aExistenceCheck,
bool aIsFromNsIFile);
async StoreAndBroadcastBlobURLRegistration(nsCString url, PBlob blob,
Principal principal);

View File

@ -25,7 +25,7 @@
function parentReady(message) {
MockFilePicker.init(content);
MockFilePicker.returnFiles = [message.data.file];
MockFilePicker.setFiles([message.data.file]);
MockFilePicker.returnValue = MockFilePicker.returnOK;
let input = content.document.getElementById("f");

View File

@ -26,6 +26,7 @@ dictionary FilePropertyBag {
dictionary ChromeFilePropertyBag : FilePropertyBag {
DOMString name = "";
boolean existenceCheck = true;
};
// Mozilla extensions

View File

@ -116,7 +116,7 @@ function runTest() {
} else {
var file = dirs[test[2]].clone();
file.append("file.file");
MockFilePicker.returnFiles = [file];
MockFilePicker.setFiles([file]);
content.setAttribute('src', domains[test[0]] + '/chrome/layout/forms/test/bug536567_subframe.html');
}
}

View File

@ -229,15 +229,13 @@ FilePicker.prototype = {
}
if (this._domWin) {
let utils = this._domWin.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
this._domFile = utils.wrapDOMFile(this.file);
return;
return this._domWin.File.createFromNsIFile(this.file, { existenceCheck: false });
}
return File.createFromNsIFile(this.file).then(domFile => {
this._domFile = domFile;
});
}).catch(() => {
return File.createFromNsIFile(this.file, { existenceCheck: false });
}).then(domFile => {
this._domFile = domFile;
}, () => {
}).then(() => {
if (this._callback) {
this._callback.done(this._filePath ?

View File

@ -53,6 +53,7 @@ this.MockFilePicker = {
filterVideo: Ci.nsIFilePicker.filterVideo,
window: null,
pendingPromises: [],
init: function(window) {
this.window = window;
@ -73,7 +74,7 @@ this.MockFilePicker = {
this.displayDirectory = null;
this.filterIndex = 0;
this.mode = null;
this.returnFiles = [];
this.returnData = [];
this.returnValue = null;
this.showCallback = null;
this.afterOpenCallback = null;
@ -91,32 +92,67 @@ this.MockFilePicker = {
}
},
internalFileData(obj) {
return {
nsIFile: "nsIFile" in obj ? obj.nsIFile : null,
domFile: "domFile" in obj ? obj.domFile : null,
domDirectory: "domDirectory" in obj ? obj.domDirectory : null,
};
},
useAnyFile: function() {
var file = FileUtils.getDir("TmpD", [], false);
file.append("testfile");
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o644);
this.returnFiles = [file];
let promise = this.window.File.createFromNsIFile(file)
.then(domFile => domFile, () => null)
// domFile can be null.
.then(domFile => {
this.returnData = [this.internalFileData({ nsIFile: file, domFile: domFile })];
}).then(() => file);
this.pendingPromises = [promise];
// We return a promise in order to support some existing mochitests.
return promise;
},
useBlobFile: function() {
var blob = new this.window.Blob([]);
var file = new this.window.File([blob], 'helloworld.txt', { type: 'plain/text' });
this.returnFiles = [file];
this.returnData = [this.internalFileData({ domFile: file })];
this.pendingPromises = [];
},
useDirectory: function(aPath) {
var directory = new this.window.Directory(aPath);
this.returnFiles = [directory];
this.returnData = [this.internalFileData({ domDirectory: directory })];
this.pendingPromises = [];
},
isNsIFile: function(aFile) {
let ret = false;
try {
if (aFile.QueryInterface(Ci.nsIFile))
ret = true;
} catch(e) {}
setFiles(files) {
this.returnData = [];
this.pendingPromises = [];
return ret;
for (let file of files) {
if (file instanceof this.window.File) {
this.returnData.push(this.internalFileData({ domFile: file }));
} else {
let promise = this.window.File.createFromNsIFile(file, { existenceCheck: false });
promise.then(domFile => {
this.returnData.push(this.internalFileData({ nsIFile: file, domFile: domFile }));
});
this.pendingPromises.push(promise);
}
}
},
getNsIFile() {
if (this.returnData.length >= 1) {
return this.returnData[0].nsIFile;
}
return null;
}
};
@ -144,10 +180,8 @@ MockFilePickerInstance.prototype = {
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];
if (MockFilePicker.returnData.length >= 1) {
return MockFilePicker.returnData[0].nsIFile;
}
return null;
@ -155,23 +189,24 @@ MockFilePickerInstance.prototype = {
// 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]);
if (MockFilePicker.returnData.length < 1) {
return null;
}
if (MockFilePicker.returnData[0].domFile) {
return MockFilePicker.returnData[0].domFile;
}
if (MockFilePicker.returnData[0].domDirectory) {
return MockFilePicker.returnData[0].domDirectory;
}
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]);
if (MockFilePicker.returnData.length >= 1 &&
MockFilePicker.returnData[0].nsIFile) {
return Services.io.newFileURI(MockFilePicker.returnData[0].nsIFile);
}
return null;
@ -181,14 +216,13 @@ MockFilePickerInstance.prototype = {
index: 0,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
hasMoreElements: function() {
return this.index < MockFilePicker.returnFiles.length;
return this.index < MockFilePicker.returnData.length;
},
getNext: function() {
// window.File does not implement nsIFile
if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[this.index])) {
if (!MockFilePicker.returnData[this.index].nsIFile) {
return null;
}
return MockFilePicker.returnFiles[this.index++];
return MockFilePicker.returnData[this.index++].nsIFile;
}
};
},
@ -199,46 +233,76 @@ MockFilePickerInstance.prototype = {
index: 0,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
hasMoreElements: function() {
return this.index < MockFilePicker.returnFiles.length;
return this.index < MockFilePicker.returnData.length;
},
getNext: function() {
// window.File does not implement nsIFile
if (!MockFilePicker.isNsIFile(MockFilePicker.returnFiles[this.index])) {
return MockFilePicker.returnFiles[this.index++];
if (MockFilePicker.returnData[this.index].domFile) {
return MockFilePicker.returnData[this.index++].domFile;
}
return utils.wrapDOMFile(MockFilePicker.returnFiles[this.index++]);
if (MockFilePicker.returnData[this.index].domDirectory) {
return MockFilePicker.returnData[this.index++].domDirectory;
}
return null;
}
};
},
show: function() {
throw "This is not implemented";
},
_openInternal: 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._openInternal();
} catch(ex) {
}
if (aFilePickerShownCallback) {
aFilePickerShownCallback.done(result);
}
if (typeof MockFilePicker.afterOpenCallback == "function") {
this.window.setTimeout(() => {
MockFilePicker.afterOpenCallback(this);
}, 0);
}
}.bind(this), 0);
this.window.setTimeout(() => {
// Maybe all the pending promises are already resolved, but we want to be sure.
Promise.all(MockFilePicker.pendingPromises).then(() => {
return Ci.nsIFilePicker.returnOK;
}, () => {
return Ci.nsIFilePicker.returnCancel;
}).then(result => {
// Nothing else has to be done.
MockFilePicker.pendingPromises = [];
if (result == Ci.nsIFilePicker.returnCancel) {
return result;
}
MockFilePicker.displayDirectory = this.displayDirectory;
MockFilePicker.shown = true;
if (typeof MockFilePicker.showCallback == "function") {
try {
var returnValue = MockFilePicker.showCallback(this);
if (typeof returnValue != "undefined") {
return returnValue;
}
} catch(ex) {
return Ci.nsIFilePicker.returnCancel;
}
}
return MockFilePicker.returnValue;
}).then(result => {
// Some additional result file can be set by the callback. Let's
// resolve the pending promises again.
return Promise.all(MockFilePicker.pendingPromises).then(() => {
return result;
}, () => {
return Ci.nsIFilePicker.returnCancel;
});
}).then(result => {
MockFilePicker.pendingPromises = [];
if (aFilePickerShownCallback) {
aFilePickerShownCallback.done(result);
}
if (typeof MockFilePicker.afterOpenCallback == "function") {
this.window.setTimeout(() => {
MockFilePicker.afterOpenCallback(this);
}, 0);
}
});
});
}
};

View File

@ -19,7 +19,7 @@ add_task(function* test_downloads_saveAs() {
try {
let id = await browser.downloads.download({url, saveAs: true});
browser.downloads.onChanged.addListener(delta => {
if (delta.state.current === "complete") {
if (delta.id == id && delta.state.current === "complete") {
browser.test.sendMessage("done", {ok: true, id});
}
});
@ -35,8 +35,7 @@ add_task(function* test_downloads_saveAs() {
const extension = ExtensionTestUtils.loadExtension(manifest);
MockFilePicker.init(window);
MockFilePicker.useAnyFile();
const [file] = MockFilePicker.returnFiles;
const file = yield MockFilePicker.useAnyFile();
yield extension.startup();
yield extension.awaitMessage("ready");
@ -45,6 +44,8 @@ add_task(function* test_downloads_saveAs() {
let result = yield extension.awaitMessage("done");
ok(result.ok, "downloads.download() works with saveAs");
ok(file.exists(), "the file exists.");
is(file.fileSize, 12, "downloaded file is the correct size");
file.remove(false);

View File

@ -104,35 +104,6 @@ nsFilePicker.prototype = {
if (!this.mFilesEnumerator) {
return null;
}
if (!this.mDOMFilesEnumerator) {
this.mDOMFilesEnumerator = {
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISimpleEnumerator]),
mFiles: [],
mIndex: 0,
hasMoreElements() {
return (this.mIndex < this.mFiles.length);
},
getNext() {
if (this.mIndex >= this.mFiles.length) {
throw Components.results.NS_ERROR_FAILURE;
}
return this.mFiles[this.mIndex++];
}
};
var utils = this.mParentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
for (var i = 0; i < this.mFilesEnumerator.mFiles.length; ++i) {
var file = utils.wrapDOMFile(this.mFilesEnumerator.mFiles[i]);
this.mDOMFilesEnumerator.mFiles.push(file);
}
}
return this.mDOMFilesEnumerator;
},
@ -230,16 +201,54 @@ nsFilePicker.prototype = {
open(aFilePickerShownCallback) {
var tm = Components.classes["@mozilla.org/thread-manager;1"]
.getService(Components.interfaces.nsIThreadManager);
tm.mainThread.dispatch(function() {
tm.mainThread.dispatch(() => {
let result = Components.interfaces.nsIFilePicker.returnCancel;
try {
result = this.show();
} catch (ex) {
}
if (aFilePickerShownCallback) {
aFilePickerShownCallback.done(result);
let promises = [];
// Let's create the DOMFileEnumerator right now because it requires some
// async operation.
if (this.mFilesEnumerator) {
this.mDOMFilesEnumerator = {
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISimpleEnumerator]),
mFiles: [],
mIndex: 0,
hasMoreElements() {
return (this.mIndex < this.mFiles.length);
},
getNext() {
if (this.mIndex >= this.mFiles.length) {
throw Components.results.NS_ERROR_FAILURE;
}
return this.mFiles[this.mIndex++];
}
};
for (let i = 0; i < this.mFilesEnumerator.mFiles.length; ++i) {
if (this.mFilesEnumerator.mFiles[i].exists()) {
let promise =
this.mParentWindow.File.createFromNsIFile(
this.mFilesEnumerator.mFiles[i]).then(file => {
this.mDOMFilesEnumerator.mFiles.push(file);
});
promises.push(promise);
}
}
}
}.bind(this), Components.interfaces.nsIThread.DISPATCH_NORMAL);
Promise.all(promises).then(() => {
if (aFilePickerShownCallback) {
aFilePickerShownCallback.done(result);
}
});
}, Components.interfaces.nsIThread.DISPATCH_NORMAL);
},
show() {

View File

@ -63,7 +63,8 @@ function* do_test(test) {
MockFilePicker.init(window);
MockFilePicker.returnValue = MockFilePicker.returnOK;
MockFilePicker.displayDirectory = FileUtils.getDir("TmpD", [], false);
MockFilePicker.returnFiles = [tempFile];
MockFilePicker.setFiles([tempFile]);
MockFilePicker.afterOpenCallback = MockFilePicker.cleanup;
try {
// Open the File Picker dialog (MockFilePicker) to select
@ -76,9 +77,7 @@ function* do_test(test) {
"The input should have at least one file selected");
info(`The input has ${input.files.length} file(s) selected.`);
});
} finally {
MockFilePicker.cleanup();
}
} catch (e) {}
} else {
info("No real file selection required.");
}

View File

@ -53,7 +53,7 @@ function test() {
var destDir = createTemporarySaveDirectory();
var file = destDir.clone();
file.append("no_default_file_name");
MockFilePicker.returnFiles = [file];
MockFilePicker.setFiles([file]);
MockFilePicker.showCallback = function(fp) {
MockFilePicker.filterIndex = 1; // kSaveAsType_URL
};
@ -80,7 +80,7 @@ function test() {
ok(downloadSuccess, "The inner frame should have been downloaded successfully");
// Read the entire saved file.
var file = MockFilePicker.returnFiles[0];
var file = MockFilePicker.getNsIFile();
var fileContents = readShortFile(file);
// Check if outer POST data is found (bug 471962).

View File

@ -91,7 +91,7 @@ add_task(function* test_install_from_file() {
get_addon_file_url("browser_bug567127_1.xpi"),
get_addon_file_url("browser_bug567127_2.xpi")
];
MockFilePicker.returnFiles = filePaths.map(aPath => aPath.file);
MockFilePicker.setFiles(filePaths.map(aPath => aPath.file));
// Set handler that executes the core test after the window opens,
// and resolves the promise when the window closes

View File

@ -287,7 +287,7 @@ add_test(function() {
testFile.append("\u2622");
var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile);
MockFilePicker.returnFiles = [testFile];
MockFilePicker.setFiles([testFile]);
MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
let promise = new Promise(resolve => {
@ -301,7 +301,7 @@ add_test(function() {
is(input.tooltipText, testFile.path, "Label tooltip should match file chosen");
is(Preferences.get("extensions.inlinesettings1.file", "wrong"), testFile.path, "File pref should match file chosen");
MockFilePicker.returnFiles = [curProcD];
MockFilePicker.setFiles([curProcD]);
MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel;
return new Promise(resolve => {
@ -320,7 +320,7 @@ add_test(function() {
is(input.value, "", "Label value should be empty");
is(input.tooltipText, "", "Label tooltip should be empty");
MockFilePicker.returnFiles = [testFile];
MockFilePicker.setFiles([testFile]);
MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
return new Promise(resolve => {
@ -333,7 +333,7 @@ add_test(function() {
is(input.tooltipText, testFile.path, "Label tooltip should match file chosen");
is(Preferences.get("extensions.inlinesettings1.directory", "wrong"), testFile.path, "Directory pref should match file chosen");
MockFilePicker.returnFiles = [curProcD];
MockFilePicker.setFiles([curProcD]);
MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel;
return new Promise(resolve => {

View File

@ -282,7 +282,7 @@ add_test(function() {
var profD = Services.dirsvc.get("ProfD", Ci.nsIFile);
var curProcD = Services.dirsvc.get("CurProcD", Ci.nsIFile);
MockFilePicker.returnFiles = [profD];
MockFilePicker.setFiles([profD]);
MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
let promise = new Promise(resolve => {
@ -296,7 +296,7 @@ add_test(function() {
is(input.tooltipText, profD.path, "Label tooltip should match file chosen");
is(Services.prefs.getCharPref("extensions.inlinesettings1.file"), profD.path, "File pref should match file chosen");
MockFilePicker.returnFiles = [curProcD];
MockFilePicker.setFiles([curProcD]);
MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel;
return promise = new Promise(resolve => {
@ -315,7 +315,7 @@ add_test(function() {
is(input.value, "", "Label value should be empty");
is(input.tooltipText, "", "Label tooltip should be empty");
MockFilePicker.returnFiles = [profD];
MockFilePicker.setFiles([profD]);
MockFilePicker.returnValue = Ci.nsIFilePicker.returnOK;
return new Promise(resolve => {
@ -328,7 +328,7 @@ add_test(function() {
is(input.tooltipText, profD.path, "Label tooltip should match file chosen");
is(Services.prefs.getCharPref("extensions.inlinesettings1.directory"), profD.path, "Directory pref should match file chosen");
MockFilePicker.returnFiles = [curProcD];
MockFilePicker.setFiles([curProcD]);
MockFilePicker.returnValue = Ci.nsIFilePicker.returnCancel;
return new Promise(resolve => {