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
,
29 BrowserChild
* browserChild
= BrowserChild::GetFrom(aParent
);
31 return NS_ERROR_FAILURE
;
34 mParent
= nsPIDOMWindowOuter::From(aParent
);
39 browserChild
->SendPFilePickerConstructor(this, nsString(aTitle
), aMode
);
45 void nsFilePickerProxy::InitNative(nsIWidget
* aParent
,
46 const nsAString
& aTitle
) {}
49 nsFilePickerProxy::AppendFilter(const nsAString
& aTitle
,
50 const nsAString
& aFilter
) {
51 mFilterNames
.AppendElement(aTitle
);
52 mFilters
.AppendElement(aFilter
);
57 nsFilePickerProxy::GetCapture(int16_t* aCapture
) {
63 nsFilePickerProxy::SetCapture(int16_t aCapture
) {
69 nsFilePickerProxy::GetDefaultString(nsAString
& aDefaultString
) {
70 aDefaultString
= mDefault
;
75 nsFilePickerProxy::SetDefaultString(const nsAString
& aDefaultString
) {
76 mDefault
= aDefaultString
;
81 nsFilePickerProxy::GetDefaultExtension(nsAString
& aDefaultExtension
) {
82 aDefaultExtension
= mDefaultExtension
;
87 nsFilePickerProxy::SetDefaultExtension(const nsAString
& aDefaultExtension
) {
88 mDefaultExtension
= aDefaultExtension
;
93 nsFilePickerProxy::GetFilterIndex(int32_t* aFilterIndex
) {
94 *aFilterIndex
= mSelectedType
;
99 nsFilePickerProxy::SetFilterIndex(int32_t aFilterIndex
) {
100 mSelectedType
= aFilterIndex
;
105 nsFilePickerProxy::GetFile(nsIFile
** aFile
) {
106 MOZ_ASSERT(false, "GetFile is unimplemented; use GetDomFileOrDirectory");
107 return NS_ERROR_FAILURE
;
111 nsFilePickerProxy::GetFileURL(nsIURI
** aFileURL
) {
112 MOZ_ASSERT(false, "GetFileURL is unimplemented; use GetDomFileOrDirectory");
113 return NS_ERROR_FAILURE
;
117 nsFilePickerProxy::GetFiles(nsISimpleEnumerator
** aFiles
) {
119 "GetFiles is unimplemented; use GetDomFileOrDirectoryEnumerator");
120 return NS_ERROR_FAILURE
;
123 nsresult
nsFilePickerProxy::Show(int16_t* aReturn
) {
124 MOZ_ASSERT(false, "Show is unimplemented; use Open");
125 return NS_ERROR_NOT_IMPLEMENTED
;
129 nsFilePickerProxy::Open(nsIFilePickerShownCallback
* aCallback
) {
130 mCallback
= aCallback
;
132 nsString displayDirectory
;
133 if (mDisplayDirectory
) {
134 mDisplayDirectory
->GetPath(displayDirectory
);
138 return NS_ERROR_FAILURE
;
141 SendOpen(mSelectedType
, mAddToRecentDocs
, mDefault
, mDefaultExtension
,
142 mFilters
, mFilterNames
, mRawFilters
, displayDirectory
,
143 mDisplaySpecialDirectory
, mOkButtonLabel
, mCapture
);
148 mozilla::ipc::IPCResult
nsFilePickerProxy::Recv__delete__(
149 const MaybeInputData
& aData
, const int16_t& aResult
) {
150 nsPIDOMWindowInner
* inner
=
151 mParent
? mParent
->GetCurrentInnerWindow() : nullptr;
153 if (NS_WARN_IF(!inner
)) {
157 if (aData
.type() == MaybeInputData::TInputBlobs
) {
158 const nsTArray
<IPCBlob
>& blobs
= aData
.get_InputBlobs().blobs();
159 for (uint32_t i
= 0; i
< blobs
.Length(); ++i
) {
160 RefPtr
<BlobImpl
> blobImpl
= IPCBlobUtils::Deserialize(blobs
[i
]);
161 NS_ENSURE_TRUE(blobImpl
, IPC_OK());
163 if (!blobImpl
->IsFile()) {
167 RefPtr
<File
> file
= File::Create(inner
->AsGlobal(), blobImpl
);
168 if (NS_WARN_IF(!file
)) {
172 OwningFileOrDirectory
* element
= mFilesOrDirectories
.AppendElement();
173 element
->SetAsFile() = file
;
175 } else if (aData
.type() == MaybeInputData::TInputDirectory
) {
176 nsCOMPtr
<nsIFile
> file
;
177 const nsAString
& path(aData
.get_InputDirectory().directoryPath());
178 nsresult rv
= NS_NewLocalFile(path
, true, getter_AddRefs(file
));
179 if (NS_WARN_IF(NS_FAILED(rv
))) {
183 RefPtr
<Directory
> directory
= Directory::Create(inner
->AsGlobal(), file
);
184 MOZ_ASSERT(directory
);
186 OwningFileOrDirectory
* element
= mFilesOrDirectories
.AppendElement();
187 element
->SetAsDirectory() = directory
;
191 mCallback
->Done(aResult
);
199 nsFilePickerProxy::GetDomFileOrDirectory(nsISupports
** aValue
) {
201 if (mFilesOrDirectories
.IsEmpty()) {
205 MOZ_ASSERT(mFilesOrDirectories
.Length() == 1);
207 if (mFilesOrDirectories
[0].IsFile()) {
208 nsCOMPtr
<nsISupports
> blob
= ToSupports(mFilesOrDirectories
[0].GetAsFile());
213 MOZ_ASSERT(mFilesOrDirectories
[0].IsDirectory());
214 RefPtr
<Directory
> directory
= mFilesOrDirectories
[0].GetAsDirectory();
215 directory
.forget(aValue
);
221 class SimpleEnumerator final
: public nsSimpleEnumerator
{
223 explicit SimpleEnumerator(
224 const nsTArray
<OwningFileOrDirectory
>& aFilesOrDirectories
)
225 : mFilesOrDirectories(aFilesOrDirectories
.Clone()), mIndex(0) {}
228 HasMoreElements(bool* aRetvalue
) override
{
229 MOZ_ASSERT(aRetvalue
);
230 *aRetvalue
= mIndex
< mFilesOrDirectories
.Length();
235 GetNext(nsISupports
** aValue
) override
{
236 NS_ENSURE_TRUE(mIndex
< mFilesOrDirectories
.Length(), NS_ERROR_FAILURE
);
238 uint32_t index
= mIndex
++;
240 if (mFilesOrDirectories
[index
].IsFile()) {
241 nsCOMPtr
<nsISupports
> blob
=
242 ToSupports(mFilesOrDirectories
[index
].GetAsFile());
247 MOZ_ASSERT(mFilesOrDirectories
[index
].IsDirectory());
248 RefPtr
<Directory
> directory
= mFilesOrDirectories
[index
].GetAsDirectory();
249 directory
.forget(aValue
);
254 nsTArray
<mozilla::dom::OwningFileOrDirectory
> mFilesOrDirectories
;
261 nsFilePickerProxy::GetDomFileOrDirectoryEnumerator(
262 nsISimpleEnumerator
** aDomfiles
) {
263 RefPtr
<SimpleEnumerator
> enumerator
=
264 new SimpleEnumerator(mFilesOrDirectories
);
265 enumerator
.forget(aDomfiles
);
269 void nsFilePickerProxy::ActorDestroy(ActorDestroyReason aWhy
) {
273 mCallback
->Done(nsIFilePicker::returnCancel
);