зеркало из https://github.com/mozilla/gecko-dev.git
Bug 832923 - Implement <input type='file'> on B2G, r=mounir, r=fabrice
This commit is contained in:
Родитель
46ca3f76ad
Коммит
ccfb81cfa0
|
@ -308,6 +308,7 @@ var shell = {
|
|||
ppmm.addMessageListener("sms-handler", this);
|
||||
ppmm.addMessageListener("mail-handler", this);
|
||||
ppmm.addMessageListener("app-notification-send", AlertsHelper);
|
||||
ppmm.addMessageListener("file-picker", this);
|
||||
},
|
||||
|
||||
stop: function shell_stop() {
|
||||
|
@ -532,19 +533,34 @@ var shell = {
|
|||
},
|
||||
|
||||
receiveMessage: function shell_receiveMessage(message) {
|
||||
var names = { 'content-handler': 'view',
|
||||
'dial-handler' : 'dial',
|
||||
'mail-handler' : 'new',
|
||||
'sms-handler' : 'new' }
|
||||
var activities = { 'content-handler': { name: 'view', response: null },
|
||||
'dial-handler': { name: 'dial', response: null },
|
||||
'mail-handler': { name: 'new', response: null },
|
||||
'sms-handler': { name: 'new', response: null },
|
||||
'file-picker': { name: 'pick', response: 'file-picked' } };
|
||||
|
||||
if (!(message.name in names))
|
||||
if (!(message.name in activities))
|
||||
return;
|
||||
|
||||
let data = message.data;
|
||||
new MozActivity({
|
||||
name: names[message.name],
|
||||
let activity = activities[message.name];
|
||||
|
||||
let a = new MozActivity({
|
||||
name: activity.name,
|
||||
data: data
|
||||
});
|
||||
|
||||
if (activity.response) {
|
||||
a.onsuccess = function() {
|
||||
let sender = message.target.QueryInterface(Ci.nsIMessageSender);
|
||||
sender.sendAsyncMessage(activity.response, { success: true,
|
||||
result: a.result });
|
||||
}
|
||||
a.onerror = function() {
|
||||
let sender = message.target.QueryInterface(Ci.nsIMessageSender);
|
||||
sender.sendAsyncMessage(activity.response, { success: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -65,3 +65,7 @@ contract @mozilla.org/recovery-service;1 {b3caca5d-0bb0-48c6-912b-6be6cbf08832}
|
|||
# B2GAboutRedirector
|
||||
component {920400b1-cf8f-4760-a9c4-441417b15134} B2GAboutRedirector.js
|
||||
contract @mozilla.org/network/protocol/about;1?what=certerror {920400b1-cf8f-4760-a9c4-441417b15134}
|
||||
|
||||
# FilePicker.js
|
||||
component {436ff8f9-0acc-4b11-8ec7-e293efba3141} FilePicker.js
|
||||
contract @mozilla.org/filepicker;1 {436ff8f9-0acc-4b11-8ec7-e293efba3141}
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
* No magic constructor behaviour, as is de rigeur for XPCOM.
|
||||
* If you must perform some initialization, and it could possibly fail (even
|
||||
* due to an out-of-memory condition), you should use an Init method, which
|
||||
* can convey failure appropriately (thrown exception in JS,
|
||||
* NS_FAILED(nsresult) return in C++).
|
||||
*
|
||||
* In JS, you can actually cheat, because a thrown exception will cause the
|
||||
* CreateInstance call to fail in turn, but not all languages are so lucky.
|
||||
* (Though ANSI C++ provides exceptions, they are verboten in Mozilla code
|
||||
* for portability reasons -- and even when you're building completely
|
||||
* platform-specific code, you can't throw across an XPCOM method boundary.)
|
||||
*/
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
// FIXME: improve this list of filters.
|
||||
const IMAGE_FILTERS = ['image/gif', 'image/jpeg', 'image/pjpeg',
|
||||
'image/png', 'image/svg+xml', 'image/tiff',
|
||||
'image/vnd.microsoft.icon'];
|
||||
const VIDEO_FILTERS = ['video/mpeg', 'video/mp4', 'video/ogg',
|
||||
'video/quicktime', 'video/webm', 'video/x-matroska',
|
||||
'video/x-ms-wmv', 'video/x-flv'];
|
||||
const AUDIO_FILTERS = ['audio/basic', 'audio/L24', 'audio/mp4',
|
||||
'audio/mpeg', 'audio/ogg', 'audio/vorbis',
|
||||
'audio/vnd.rn-realaudio', 'audio/vnd.wave',
|
||||
'audio/webm'];
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, 'cpmm',
|
||||
'@mozilla.org/childprocessmessagemanager;1',
|
||||
'nsIMessageSender');
|
||||
|
||||
function FilePicker() {
|
||||
}
|
||||
|
||||
FilePicker.prototype = {
|
||||
classID: Components.ID('{436ff8f9-0acc-4b11-8ec7-e293efba3141}'),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFilePicker]),
|
||||
|
||||
/* members */
|
||||
|
||||
mParent: undefined,
|
||||
mFilterTypes: [],
|
||||
mFileEnumerator: undefined,
|
||||
mFilePickerShownCallback: undefined,
|
||||
|
||||
/* methods */
|
||||
|
||||
init: function(parent, title, mode) {
|
||||
this.mParent = parent;
|
||||
|
||||
if (mode != Ci.nsIFilePicker.modeOpen &&
|
||||
mode != Ci.nsIFilePicker.modeOpenMultiple) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
},
|
||||
|
||||
/* readonly attribute nsILocalFile file - not implemented; */
|
||||
/* readonly attribute nsISimpleEnumerator files - not implemented; */
|
||||
/* readonly attribute nsIURI fileURL - not implemented; */
|
||||
|
||||
get domfiles() {
|
||||
return this.mFilesEnumerator;
|
||||
},
|
||||
|
||||
get domfile() {
|
||||
return this.mFilesEnumerator ? this.mFilesEnumerator.mFiles[0] : null;
|
||||
},
|
||||
|
||||
appendFilters: function(filterMask) {
|
||||
this.mFilterTypes = null;
|
||||
|
||||
// Ci.nsIFilePicker.filterHTML is not supported
|
||||
// Ci.nsIFilePicker.filterText is not supported
|
||||
|
||||
if (filterMask & Ci.nsIFilePicker.filterImages) {
|
||||
this.mFilterTypes = IMAGE_FILTERS;
|
||||
}
|
||||
|
||||
// Ci.nsIFilePicker.filterXML is not supported
|
||||
// Ci.nsIFilePicker.filterXUL is not supported
|
||||
// Ci.nsIFilePicker.filterApps is not supported
|
||||
// Ci.nsIFilePicker.filterAllowURLs is not supported
|
||||
|
||||
if (filterMask & Ci.nsIFilePicker.filterVideo) {
|
||||
this.mFilterTypes = VIDEO_FILTERS;
|
||||
}
|
||||
|
||||
if (filterMask & Ci.nsIFilePicker.filterAudio) {
|
||||
this.mFilterTypes = AUDIO_FILTERS;
|
||||
}
|
||||
|
||||
// Ci.nsIFilePicker.filterAll is by default
|
||||
},
|
||||
|
||||
appendFilter: function(title, extensions) {
|
||||
// pick activity doesn't support extensions
|
||||
},
|
||||
|
||||
open: function(aFilePickerShownCallback) {
|
||||
this.mFilePickerShownCallback = aFilePickerShownCallback;
|
||||
|
||||
cpmm.addMessageListener('file-picked', this);
|
||||
|
||||
let detail = {};
|
||||
if (this.mFilterTypes) {
|
||||
detail.type = this.mFilterTypes;
|
||||
}
|
||||
|
||||
cpmm.sendAsyncMessage('file-picker', detail);
|
||||
},
|
||||
|
||||
fireSuccess: function(file) {
|
||||
this.mFilesEnumerator = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISimpleEnumerator]),
|
||||
|
||||
mFiles: [file],
|
||||
mIndex: 0,
|
||||
|
||||
hasMoreElements: function() {
|
||||
return (this.mIndex < this.mFiles.length);
|
||||
},
|
||||
|
||||
getNext: function() {
|
||||
if (this.mIndex >= this.mFiles.length) {
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
}
|
||||
return this.mFiles[this.mIndex++];
|
||||
}
|
||||
};
|
||||
|
||||
if (this.mFilePickerShownCallback) {
|
||||
this.mFilePickerShownCallback.done(Ci.nsIFilePicker.returnOK);
|
||||
this.mFilePickerShownCallback = null;
|
||||
}
|
||||
},
|
||||
|
||||
fireError: function() {
|
||||
if (this.mFilePickerShownCallback) {
|
||||
this.mFilePickerShownCallback.done(Ci.nsIFilePicker.returnCancel);
|
||||
this.mFilePickerShownCallback = null;
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function(message) {
|
||||
if (message.name !== 'file-picked') {
|
||||
return;
|
||||
}
|
||||
|
||||
cpmm.removeMessageListener('file-picked', this);
|
||||
|
||||
let data = message.data;
|
||||
if (!data.success || !data.result.blob) {
|
||||
this.fireError();
|
||||
return;
|
||||
}
|
||||
|
||||
var mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
|
||||
var mimeInfo = mimeSvc.getFromTypeAndExtension(data.result.blob.type, '');
|
||||
|
||||
var name = 'blob';
|
||||
if (mimeInfo) {
|
||||
name += '.' + mimeInfo.primaryExtension;
|
||||
}
|
||||
|
||||
let file = new this.mParent.File(data.result.blob,
|
||||
{ name: name,
|
||||
type: data.result.blob.type });
|
||||
if (file) {
|
||||
this.fireSuccess(file);
|
||||
} else {
|
||||
this.fireError();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([FilePicker]);
|
|
@ -19,6 +19,7 @@ EXTRA_PP_COMPONENTS = \
|
|||
ContentHandler.js \
|
||||
ContentPermissionPrompt.js \
|
||||
DirectoryProvider.js \
|
||||
FilePicker.js \
|
||||
MailtoProtocolHandler.js \
|
||||
MozKeyboard.js \
|
||||
ProcessGlobal.js \
|
||||
|
|
|
@ -379,10 +379,6 @@
|
|||
@BINPATH@/components/crypto-SDR.js
|
||||
@BINPATH@/components/jsconsole-clhandler.manifest
|
||||
@BINPATH@/components/jsconsole-clhandler.js
|
||||
#ifdef MOZ_GTK2
|
||||
@BINPATH@/components/nsFilePicker.manifest
|
||||
@BINPATH@/components/nsFilePicker.js
|
||||
#endif
|
||||
@BINPATH@/components/nsHelperAppDlg.manifest
|
||||
@BINPATH@/components/nsHelperAppDlg.js
|
||||
@BINPATH@/components/nsDownloadManagerUI.manifest
|
||||
|
@ -739,6 +735,7 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
|||
@BINPATH@/components/SmsProtocolHandler.js
|
||||
@BINPATH@/components/TelProtocolHandler.js
|
||||
@BINPATH@/components/B2GAboutRedirector.js
|
||||
@BINPATH@/components/FilePicker.js
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
@BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
|
||||
|
|
|
@ -267,49 +267,38 @@ nsHTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
|||
nsCOMArray<nsIDOMFile> newFiles;
|
||||
if (mMulti) {
|
||||
nsCOMPtr<nsISimpleEnumerator> iter;
|
||||
nsresult rv = mFilePicker->GetFiles(getter_AddRefs(iter));
|
||||
nsresult rv = mFilePicker->GetDomfiles(getter_AddRefs(iter));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISupports> tmp;
|
||||
bool prefSaved = false;
|
||||
bool loop = true;
|
||||
|
||||
while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) {
|
||||
iter->GetNext(getter_AddRefs(tmp));
|
||||
nsCOMPtr<nsIFile> localFile = do_QueryInterface(tmp);
|
||||
if (!localFile) {
|
||||
continue;
|
||||
}
|
||||
nsString path;
|
||||
localFile->GetPath(path);
|
||||
if (path.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
nsCOMPtr<nsIDOMFile> domFile =
|
||||
do_QueryObject(new nsDOMFileFile(localFile));
|
||||
nsCOMPtr<nsIDOMFile> domFile = do_QueryInterface(tmp);
|
||||
MOZ_ASSERT(domFile);
|
||||
|
||||
newFiles.AppendObject(domFile);
|
||||
|
||||
if (!prefSaved) {
|
||||
// Store the last used directory using the content pref service
|
||||
nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
|
||||
mInput->OwnerDoc(), localFile);
|
||||
mInput->OwnerDoc(), domFile);
|
||||
prefSaved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIFile> localFile;
|
||||
nsresult rv = mFilePicker->GetFile(getter_AddRefs(localFile));
|
||||
nsCOMPtr<nsIDOMFile> domFile;
|
||||
nsresult rv = mFilePicker->GetDomfile(getter_AddRefs(domFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (localFile) {
|
||||
nsString path;
|
||||
rv = localFile->GetPath(path);
|
||||
if (!path.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMFile> domFile=
|
||||
do_QueryObject(new nsDOMFileFile(localFile));
|
||||
newFiles.AppendObject(domFile);
|
||||
// Store the last used directory using the content pref service
|
||||
nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
|
||||
mInput->OwnerDoc(), localFile);
|
||||
}
|
||||
if (domFile) {
|
||||
newFiles.AppendObject(domFile);
|
||||
|
||||
// Store the last used directory using the content pref service
|
||||
nsHTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
|
||||
mInput->OwnerDoc(), domFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -502,16 +491,27 @@ UploadLastDir::FetchLastUsedDirectory(nsIDocument* aDoc, nsIFile** aFile)
|
|||
}
|
||||
|
||||
nsresult
|
||||
UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aFile)
|
||||
UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIDOMFile* aDomFile)
|
||||
{
|
||||
NS_PRECONDITION(aDoc, "aDoc is null");
|
||||
NS_PRECONDITION(aFile, "aFile is null");
|
||||
NS_PRECONDITION(aDomFile, "aDomFile is null");
|
||||
|
||||
nsString path;
|
||||
nsresult rv = aDomFile->GetMozFullPathInternal(path);
|
||||
if (NS_FAILED(rv) || path.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> localFile;
|
||||
rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
|
||||
getter_AddRefs(localFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> docURI = aDoc->GetDocumentURI();
|
||||
NS_PRECONDITION(docURI, "docURI is null");
|
||||
|
||||
nsCOMPtr<nsIFile> parentFile;
|
||||
aFile->GetParent(getter_AddRefs(parentFile));
|
||||
localFile->GetParent(getter_AddRefs(parentFile));
|
||||
if (!parentFile) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1882,6 +1882,9 @@ nsHTMLInputElement::GetDisplayFileName(nsAString& aValue) const
|
|||
for (int32_t i = 0; i < mFiles.Count(); ++i) {
|
||||
nsString str;
|
||||
mFiles[i]->GetMozFullPathInternal(str);
|
||||
if (str.IsEmpty()) {
|
||||
mFiles[i]->GetName(str);
|
||||
}
|
||||
if (i == 0) {
|
||||
aValue.Append(str);
|
||||
}
|
||||
|
|
|
@ -44,10 +44,10 @@ public:
|
|||
* Store the last used directory for this location using the
|
||||
* content pref service, if it is available
|
||||
* @param aURI URI of the current page
|
||||
* @param aFile file chosen by the user - the path to the parent of this
|
||||
* @param aDomFile file chosen by the user - the path to the parent of this
|
||||
* file will be stored
|
||||
*/
|
||||
nsresult StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aFile);
|
||||
nsresult StoreLastUsedDirectory(nsIDocument* aDoc, nsIDOMFile* aDomFile);
|
||||
};
|
||||
|
||||
class nsHTMLInputElement : public nsGenericHTMLFormElement,
|
||||
|
|
|
@ -97,6 +97,7 @@ MockFilePickerInstance.prototype = {
|
|||
init: function(aParent, aTitle, aMode) {
|
||||
MockFilePicker.mode = aMode;
|
||||
this.filterIndex = MockFilePicker.filterIndex;
|
||||
this.parent = aParent;
|
||||
},
|
||||
appendFilter: function(aTitle, aFilter) {
|
||||
if (typeof MockFilePicker.appendFilterCallback == "function")
|
||||
|
@ -108,6 +109,7 @@ MockFilePickerInstance.prototype = {
|
|||
},
|
||||
defaultString: "",
|
||||
defaultExtension: "",
|
||||
parent: null,
|
||||
filterIndex: 0,
|
||||
displayDirectory: null,
|
||||
get file() {
|
||||
|
@ -115,6 +117,14 @@ MockFilePickerInstance.prototype = {
|
|||
return MockFilePicker.returnFiles[0];
|
||||
return null;
|
||||
},
|
||||
get domfile() {
|
||||
if (MockFilePicker.returnFiles.length >= 1) {
|
||||
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)
|
||||
return Services.io.newFileURI(MockFilePicker.returnFiles[0]);
|
||||
|
@ -132,6 +142,20 @@ MockFilePickerInstance.prototype = {
|
|||
}
|
||||
};
|
||||
},
|
||||
get domfiles() {
|
||||
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() {
|
||||
return utils.wrapDOMFile(MockFilePicker.returnFiles[this.index++]);
|
||||
}
|
||||
};
|
||||
},
|
||||
show: function() {
|
||||
MockFilePicker.displayDirectory = this.displayDirectory;
|
||||
MockFilePicker.shown = true;
|
||||
|
|
|
@ -88,15 +88,53 @@ nsFilePicker.prototype = {
|
|||
},
|
||||
|
||||
/* readonly attribute nsILocalFile file; */
|
||||
set file(a) { throw "readonly property"; },
|
||||
get file() { return this.mFilesEnumerator.mFiles[0]; },
|
||||
|
||||
/* readonly attribute nsISimpleEnumerator files; */
|
||||
set files(a) { throw "readonly property"; },
|
||||
get files() { return this.mFilesEnumerator; },
|
||||
|
||||
/* readonly attribute nsIDOMFile domfile; */
|
||||
get domfile() {
|
||||
let enumerator = this.domfiles;
|
||||
return enumerator ? enumerator.mFiles[0] : null;
|
||||
},
|
||||
|
||||
/* readonly attribute nsISimpleEnumerator domfiles; */
|
||||
get domfiles() {
|
||||
if (!this.mFilesEnumerator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.mDOMFilesEnumerator) {
|
||||
this.mDOMFilesEnumerator {
|
||||
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISimpleEnumerator]),
|
||||
|
||||
mFiles: [],
|
||||
mIndex: 0,
|
||||
|
||||
hasMoreElements: function() {
|
||||
return (this.mIndex < this.mFiles.length);
|
||||
},
|
||||
|
||||
getNext: function() {
|
||||
if (this.mIndex >= this.mFiles.length) {
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
}
|
||||
return this.mFiles[this.mIndex++];
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0, i < this.mFilesEnumerator.mFiles.length; ++i) {
|
||||
var file = this.mParentWindow.wrapDOMFile(
|
||||
this.mFilesEnumerator.mFiles[i]);
|
||||
this.mDOMFilesEnumerator.mFiles.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
return this.mDOMFilesEnumerator;
|
||||
},
|
||||
|
||||
/* readonly attribute nsIURI fileURL; */
|
||||
set fileURL(a) { throw "readonly property"; },
|
||||
get fileURL() {
|
||||
if (this.mFileURL)
|
||||
return this.mFileURL;
|
||||
|
@ -128,6 +166,7 @@ nsFilePicker.prototype = {
|
|||
|
||||
/* members */
|
||||
mFilesEnumerator: undefined,
|
||||
mDOMFilesEnumerator: undefined,
|
||||
mParentWindow: null,
|
||||
|
||||
/* methods */
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
interface nsIFile;
|
||||
interface nsIURI;
|
||||
interface nsIDOMFile;
|
||||
interface nsIDOMWindow;
|
||||
interface nsISimpleEnumerator;
|
||||
|
||||
|
@ -23,7 +24,7 @@ interface nsIFilePickerShownCallback : nsISupports
|
|||
void done(in short aResult);
|
||||
};
|
||||
|
||||
[scriptable, uuid(60e2dfb6-3fc7-4A2C-8137-16bef44536fc)]
|
||||
[scriptable, uuid(a6a24df3-d20a-4b6a-96d4-4736b10a51b7)]
|
||||
interface nsIFilePicker : nsISupports
|
||||
{
|
||||
const short modeOpen = 0; // Load a file or directory
|
||||
|
@ -141,6 +142,21 @@ interface nsIFilePicker : nsISupports
|
|||
*/
|
||||
readonly attribute nsISimpleEnumerator files;
|
||||
|
||||
/**
|
||||
* Get the nsIDOMFile for the file.
|
||||
*
|
||||
* @return Returns the file currently selected as DOMFile
|
||||
*/
|
||||
readonly attribute nsIDOMFile domfile;
|
||||
|
||||
/**
|
||||
* Get the enumerator for the selected files
|
||||
* only works in the modeOpenMultiple mode
|
||||
*
|
||||
* @return Returns the files currently selected as DOMFiles
|
||||
*/
|
||||
readonly attribute nsISimpleEnumerator domfiles;
|
||||
|
||||
/**
|
||||
* Controls whether the chosen file(s) should be added to the system's recent
|
||||
* documents list. This attribute will be ignored if the system has no "Recent
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsDOMFile.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "WidgetUtils.h"
|
||||
|
@ -67,6 +68,51 @@ private:
|
|||
nsRefPtr<nsIFilePickerShownCallback> mCallback;
|
||||
};
|
||||
|
||||
class nsBaseFilePickerEnumerator : public nsISimpleEnumerator
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsBaseFilePickerEnumerator(nsISimpleEnumerator* iterator)
|
||||
: mIterator(iterator)
|
||||
{}
|
||||
|
||||
virtual ~nsBaseFilePickerEnumerator()
|
||||
{}
|
||||
|
||||
NS_IMETHOD
|
||||
GetNext(nsISupports** aResult)
|
||||
{
|
||||
nsCOMPtr<nsISupports> tmp;
|
||||
nsresult rv = mIterator->GetNext(getter_AddRefs(tmp));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!tmp) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> localFile = do_QueryInterface(tmp);
|
||||
if (!localFile) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(localFile);
|
||||
domFile.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
HasMoreElements(bool* aResult)
|
||||
{
|
||||
return mIterator->HasMoreElements(aResult);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsISimpleEnumerator> mIterator;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsBaseFilePickerEnumerator, nsISimpleEnumerator)
|
||||
|
||||
nsBaseFilePicker::nsBaseFilePicker() :
|
||||
mAddToRecentDocs(true)
|
||||
{
|
||||
|
@ -201,8 +247,6 @@ NS_IMETHODIMP nsBaseFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
|
|||
return NS_NewArrayEnumerator(aFiles, files);
|
||||
}
|
||||
|
||||
#ifdef BASEFILEPICKER_HAS_DISPLAYDIRECTORY
|
||||
|
||||
// Set the display directory
|
||||
NS_IMETHODIMP nsBaseFilePicker::SetDisplayDirectory(nsIFile *aDirectory)
|
||||
{
|
||||
|
@ -230,7 +274,6 @@ NS_IMETHODIMP nsBaseFilePicker::GetDisplayDirectory(nsIFile **aDirectory)
|
|||
return rv;
|
||||
return CallQueryInterface(directory, aDirectory);
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseFilePicker::GetAddToRecentDocs(bool *aFlag)
|
||||
|
@ -245,3 +288,35 @@ nsBaseFilePicker::SetAddToRecentDocs(bool aFlag)
|
|||
mAddToRecentDocs = aFlag;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseFilePicker::GetDomfile(nsIDOMFile** aDomfile)
|
||||
{
|
||||
nsCOMPtr<nsIFile> localFile;
|
||||
nsresult rv = GetFile(getter_AddRefs(localFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!localFile) {
|
||||
*aDomfile = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMFileFile> domFile = new nsDOMFileFile(localFile);
|
||||
domFile.forget(aDomfile);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBaseFilePicker::GetDomfiles(nsISimpleEnumerator** aDomfiles)
|
||||
{
|
||||
nsCOMPtr<nsISimpleEnumerator> iter;
|
||||
nsresult rv = GetFiles(getter_AddRefs(iter));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<nsBaseFilePickerEnumerator> retIter =
|
||||
new nsBaseFilePickerEnumerator(iter);
|
||||
|
||||
retIter.forget(aDomfiles);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
class nsIWidget;
|
||||
|
||||
#define BASEFILEPICKER_HAS_DISPLAYDIRECTORY 1
|
||||
|
||||
class nsBaseFilePicker : public nsIFilePicker
|
||||
{
|
||||
public:
|
||||
|
@ -32,22 +30,21 @@ public:
|
|||
NS_IMETHOD GetFilterIndex(int32_t *aFilterIndex);
|
||||
NS_IMETHOD SetFilterIndex(int32_t aFilterIndex);
|
||||
NS_IMETHOD GetFiles(nsISimpleEnumerator **aFiles);
|
||||
#ifdef BASEFILEPICKER_HAS_DISPLAYDIRECTORY
|
||||
NS_IMETHOD GetDisplayDirectory(nsIFile * *aDisplayDirectory);
|
||||
NS_IMETHOD SetDisplayDirectory(nsIFile * aDisplayDirectory);
|
||||
#endif
|
||||
NS_IMETHOD GetAddToRecentDocs(bool *aFlag);
|
||||
NS_IMETHOD SetAddToRecentDocs(bool aFlag);
|
||||
|
||||
NS_IMETHOD GetDomfile(nsIDOMFile** aDomfile);
|
||||
NS_IMETHOD GetDomfiles(nsISimpleEnumerator** aDomfiles);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void InitNative(nsIWidget *aParent, const nsAString& aTitle,
|
||||
int16_t aMode) = 0;
|
||||
|
||||
bool mAddToRecentDocs;
|
||||
#ifdef BASEFILEPICKER_HAS_DISPLAYDIRECTORY
|
||||
nsCOMPtr<nsIFile> mDisplayDirectory;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // nsBaseFilePicker_h__
|
||||
|
|
Загрузка…
Ссылка в новой задаче