1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsFilePickerProxy.h"
8 #include "nsComponentManagerUtils.h"
10 #include "nsSimpleEnumerator.h"
11 #include "mozilla/dom/BlobImpl.h"
12 #include "mozilla/dom/Directory.h"
13 #include "mozilla/dom/File.h"
14 #include "mozilla/dom/BrowserChild.h"
15 #include "mozilla/dom/IPCBlobUtils.h"
17 using namespace mozilla::dom
;
19 NS_IMPL_ISUPPORTS(nsFilePickerProxy
, nsIFilePicker
)
21 nsFilePickerProxy::nsFilePickerProxy()
22 : mSelectedType(0), mCapture(captureNone
), mIPCActive(false) {}
24 nsFilePickerProxy::~nsFilePickerProxy() = default;
27 nsFilePickerProxy::Init(mozIDOMWindowProxy
* aParent
, const nsAString
& aTitle
,
28 nsIFilePicker::Mode aMode
) {
29 BrowserChild
* browserChild
= BrowserChild::GetFrom(aParent
);
31 return NS_ERROR_FAILURE
;
34 mParent
= nsPIDOMWindowOuter::From(aParent
);
38 browserChild
->SendPFilePickerConstructor(this, aTitle
, aMode
);
44 void nsFilePickerProxy::InitNative(nsIWidget
* aParent
,
45 const nsAString
& aTitle
) {}
48 nsFilePickerProxy::AppendFilter(const nsAString
& aTitle
,
49 const nsAString
& aFilter
) {
50 mFilterNames
.AppendElement(aTitle
);
51 mFilters
.AppendElement(aFilter
);
56 nsFilePickerProxy::GetCapture(nsIFilePicker::CaptureTarget
* aCapture
) {
62 nsFilePickerProxy::SetCapture(nsIFilePicker::CaptureTarget aCapture
) {
68 nsFilePickerProxy::GetDefaultString(nsAString
& aDefaultString
) {
69 aDefaultString
= mDefault
;
74 nsFilePickerProxy::SetDefaultString(const nsAString
& aDefaultString
) {
75 mDefault
= aDefaultString
;
80 nsFilePickerProxy::GetDefaultExtension(nsAString
& aDefaultExtension
) {
81 aDefaultExtension
= mDefaultExtension
;
86 nsFilePickerProxy::SetDefaultExtension(const nsAString
& aDefaultExtension
) {
87 mDefaultExtension
= aDefaultExtension
;
92 nsFilePickerProxy::GetFilterIndex(int32_t* aFilterIndex
) {
93 *aFilterIndex
= mSelectedType
;
98 nsFilePickerProxy::SetFilterIndex(int32_t aFilterIndex
) {
99 mSelectedType
= aFilterIndex
;
104 nsFilePickerProxy::GetFile(nsIFile
** aFile
) {
105 MOZ_ASSERT(false, "GetFile is unimplemented; use GetDomFileOrDirectory");
106 return NS_ERROR_FAILURE
;
110 nsFilePickerProxy::GetFileURL(nsIURI
** aFileURL
) {
111 MOZ_ASSERT(false, "GetFileURL is unimplemented; use GetDomFileOrDirectory");
112 return NS_ERROR_FAILURE
;
116 nsFilePickerProxy::GetFiles(nsISimpleEnumerator
** aFiles
) {
118 "GetFiles is unimplemented; use GetDomFileOrDirectoryEnumerator");
119 return NS_ERROR_FAILURE
;
122 nsresult
nsFilePickerProxy::Show(nsIFilePicker::ResultCode
* aReturn
) {
123 MOZ_ASSERT(false, "Show is unimplemented; use Open");
124 return NS_ERROR_NOT_IMPLEMENTED
;
128 nsFilePickerProxy::Open(nsIFilePickerShownCallback
* aCallback
) {
129 mCallback
= aCallback
;
131 nsString displayDirectory
;
132 if (mDisplayDirectory
) {
133 mDisplayDirectory
->GetPath(displayDirectory
);
137 return NS_ERROR_FAILURE
;
140 SendOpen(mSelectedType
, mAddToRecentDocs
, mDefault
, mDefaultExtension
,
141 mFilters
, mFilterNames
, mRawFilters
, displayDirectory
,
142 mDisplaySpecialDirectory
, mOkButtonLabel
, mCapture
);
147 mozilla::ipc::IPCResult
nsFilePickerProxy::Recv__delete__(
148 const MaybeInputData
& aData
, const nsIFilePicker::ResultCode
& aResult
) {
149 nsPIDOMWindowInner
* inner
=
150 mParent
? mParent
->GetCurrentInnerWindow() : nullptr;
152 if (NS_WARN_IF(!inner
)) {
156 if (aData
.type() == MaybeInputData::TInputBlobs
) {
157 const nsTArray
<IPCBlob
>& blobs
= aData
.get_InputBlobs().blobs();
158 for (uint32_t i
= 0; i
< blobs
.Length(); ++i
) {
159 RefPtr
<BlobImpl
> blobImpl
= IPCBlobUtils::Deserialize(blobs
[i
]);
160 NS_ENSURE_TRUE(blobImpl
, IPC_OK());
162 if (!blobImpl
->IsFile()) {
166 RefPtr
<File
> file
= File::Create(inner
->AsGlobal(), blobImpl
);
167 if (NS_WARN_IF(!file
)) {
171 OwningFileOrDirectory
* element
= mFilesOrDirectories
.AppendElement();
172 element
->SetAsFile() = file
;
174 } else if (aData
.type() == MaybeInputData::TInputDirectory
) {
175 nsCOMPtr
<nsIFile
> file
;
176 const nsAString
& path(aData
.get_InputDirectory().directoryPath());
177 nsresult rv
= NS_NewLocalFile(path
, true, getter_AddRefs(file
));
178 if (NS_WARN_IF(NS_FAILED(rv
))) {
182 RefPtr
<Directory
> directory
= Directory::Create(inner
->AsGlobal(), file
);
183 MOZ_ASSERT(directory
);
185 OwningFileOrDirectory
* element
= mFilesOrDirectories
.AppendElement();
186 element
->SetAsDirectory() = directory
;
190 mCallback
->Done(aResult
);
198 nsFilePickerProxy::GetDomFileOrDirectory(nsISupports
** aValue
) {
200 if (mFilesOrDirectories
.IsEmpty()) {
204 MOZ_ASSERT(mFilesOrDirectories
.Length() == 1);
206 if (mFilesOrDirectories
[0].IsFile()) {
207 nsCOMPtr
<nsISupports
> blob
= ToSupports(mFilesOrDirectories
[0].GetAsFile());
212 MOZ_ASSERT(mFilesOrDirectories
[0].IsDirectory());
213 RefPtr
<Directory
> directory
= mFilesOrDirectories
[0].GetAsDirectory();
214 directory
.forget(aValue
);
220 class SimpleEnumerator final
: public nsSimpleEnumerator
{
222 explicit SimpleEnumerator(
223 const nsTArray
<OwningFileOrDirectory
>& aFilesOrDirectories
)
224 : mFilesOrDirectories(aFilesOrDirectories
.Clone()), mIndex(0) {}
227 HasMoreElements(bool* aRetvalue
) override
{
228 MOZ_ASSERT(aRetvalue
);
229 *aRetvalue
= mIndex
< mFilesOrDirectories
.Length();
234 GetNext(nsISupports
** aValue
) override
{
235 NS_ENSURE_TRUE(mIndex
< mFilesOrDirectories
.Length(), NS_ERROR_FAILURE
);
237 uint32_t index
= mIndex
++;
239 if (mFilesOrDirectories
[index
].IsFile()) {
240 nsCOMPtr
<nsISupports
> blob
=
241 ToSupports(mFilesOrDirectories
[index
].GetAsFile());
246 MOZ_ASSERT(mFilesOrDirectories
[index
].IsDirectory());
247 RefPtr
<Directory
> directory
= mFilesOrDirectories
[index
].GetAsDirectory();
248 directory
.forget(aValue
);
253 nsTArray
<mozilla::dom::OwningFileOrDirectory
> mFilesOrDirectories
;
260 nsFilePickerProxy::GetDomFileOrDirectoryEnumerator(
261 nsISimpleEnumerator
** aDomfiles
) {
262 RefPtr
<SimpleEnumerator
> enumerator
=
263 new SimpleEnumerator(mFilesOrDirectories
);
264 enumerator
.forget(aDomfiles
);
268 void nsFilePickerProxy::ActorDestroy(ActorDestroyReason aWhy
) {
272 mCallback
->Done(nsIFilePicker::returnCancel
);