Bug 923310 - Crash in HTMLInputElement in B2G, r=jwatt

This commit is contained in:
Andrea Marchesini 2013-10-09 13:15:14 +02:00
parent 2e504006a1
commit 89d6130ac5
5 changed files with 109 additions and 8 deletions

View File

@ -163,7 +163,10 @@ nsDOMFileBase::GetMozFullPath(nsAString &aFileName)
NS_IMETHODIMP
nsDOMFileBase::GetMozFullPathInternal(nsAString &aFileName)
{
NS_ASSERTION(mIsFile, "Should only be called on files");
if (!mIsFile) {
return NS_ERROR_FAILURE;
}
aFileName.Truncate();
return NS_OK;
}

View File

@ -529,6 +529,12 @@ private:
nsTArray<nsCOMPtr<nsIDOMFile> > mFileList;
};
/**
* This may return nullptr if aDomFile's implementation of
* nsIDOMFile::mozFullPathInternal does not successfully return a non-empty
* string that is a valid path. This can happen on Firefox OS, for example,
* where the file picker can create Blobs.
*/
static already_AddRefed<nsIFile>
DOMFileToLocalFile(nsIDOMFile* aDomFile)
{
@ -630,10 +636,12 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
// Store the last used directory using the content pref service:
nsCOMPtr<nsIFile> file = DOMFileToLocalFile(newFiles[0]);
nsCOMPtr<nsIFile> lastUsedDir;
file->GetParent(getter_AddRefs(lastUsedDir));
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
mInput->OwnerDoc(), lastUsedDir);
if (file) {
nsCOMPtr<nsIFile> lastUsedDir;
file->GetParent(getter_AddRefs(lastUsedDir));
HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
mInput->OwnerDoc(), lastUsedDir);
}
// The text control frame (if there is one) isn't going to send a change
// event because it will think this is done by a script.

View File

@ -386,3 +386,4 @@ support-files =
[test_ul_attributes_reflection.html]
[test_undoManager.html]
[test_video_wakelock.html]
[test_input_files_not_nsIFile.html]

View File

@ -0,0 +1,48 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for &lt;input type='file'&gt; handling when its "files" do not implement nsIFile</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="content">
<input id='a' type='file'>
</div>
<button id='b' onclick="document.getElementById('a').click();">Show Filepicker</button>
<input type="file" id="file" />
<pre id="test">
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
var MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init(window);
SimpleTest.waitForFocus(function() {
MockFilePicker.useBlobFile();
MockFilePicker.returnValue = MockFilePicker.returnOK;
var b = document.getElementById('b');
b.focus(); // Be sure the element is visible.
document.getElementById('a').addEventListener("change", function(aEvent) {
ok(true, "change event correctly sent");
SimpleTest.executeSoon(function() {
MockFilePicker.cleanup();
SimpleTest.finish();
});
}, false);
b.click();
});
</script>
</pre>
</body>
</html>

View File

@ -48,7 +48,11 @@ this.MockFilePicker = {
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)) {
@ -86,6 +90,22 @@ this.MockFilePicker = {
var file = FileUtils.getFile("TmpD", ["testfile"]);
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0644);
this.returnFiles = [file];
},
useBlobFile: function() {
var blob = new this.window.Blob([]);
var file = new this.window.File(blob, { name: 'helloworld.txt', type: 'plain/text' });
this.returnFiles = [file];
},
isNsIFile: function(aFile) {
let ret = false;
try {
if (aFile.QueryInterface(Ci.nsIFile))
ret = true;
} catch(e) {}
return ret;
}
};
@ -113,12 +133,21 @@ MockFilePickerInstance.prototype = {
filterIndex: 0,
displayDirectory: null,
get file() {
if (MockFilePicker.returnFiles.length >= 1)
if (MockFilePicker.returnFiles.length >= 1 &&
// window.File does not implement nsIFile
MockFilePicker.isNsIFile(MockFilePicker.returnFiles[0])) {
return MockFilePicker.returnFiles[0];
}
return null;
},
get domfile() {
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]);
@ -126,8 +155,12 @@ MockFilePickerInstance.prototype = {
return null;
},
get fileURL() {
if (MockFilePicker.returnFiles.length >= 1)
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() {
@ -138,13 +171,17 @@ MockFilePickerInstance.prototype = {
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 domfiles() {
let utils = this.parent.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
.getInterface(Ci.nsIDOMWindowUtils);
return {
index: 0,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
@ -152,6 +189,10 @@ MockFilePickerInstance.prototype = {
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++]);
}
};