Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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/. */
6 :
7 : #include "nsFilePickerProxy.h"
8 : #include "nsComponentManagerUtils.h"
9 : #include "nsIFile.h"
10 : #include "mozilla/dom/Directory.h"
11 : #include "mozilla/dom/File.h"
12 : #include "mozilla/dom/TabChild.h"
13 : #include "mozilla/dom/IPCBlobUtils.h"
14 :
15 : using namespace mozilla::dom;
16 :
17 0 : NS_IMPL_ISUPPORTS(nsFilePickerProxy, nsIFilePicker)
18 :
19 0 : nsFilePickerProxy::nsFilePickerProxy()
20 : : mSelectedType(0)
21 0 : , mIPCActive(false)
22 : {
23 0 : }
24 :
25 0 : nsFilePickerProxy::~nsFilePickerProxy()
26 : {
27 0 : }
28 :
29 : NS_IMETHODIMP
30 0 : nsFilePickerProxy::Init(mozIDOMWindowProxy* aParent, const nsAString& aTitle,
31 : int16_t aMode)
32 : {
33 0 : TabChild* tabChild = TabChild::GetFrom(aParent);
34 0 : if (!tabChild) {
35 0 : return NS_ERROR_FAILURE;
36 : }
37 :
38 0 : mParent = nsPIDOMWindowOuter::From(aParent);
39 :
40 0 : mMode = aMode;
41 :
42 0 : NS_ADDREF_THIS();
43 0 : tabChild->SendPFilePickerConstructor(this, nsString(aTitle), aMode);
44 :
45 0 : mIPCActive = true;
46 0 : return NS_OK;
47 : }
48 :
49 : void
50 0 : nsFilePickerProxy::InitNative(nsIWidget* aParent, const nsAString& aTitle)
51 : {
52 0 : }
53 :
54 : NS_IMETHODIMP
55 0 : nsFilePickerProxy::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
56 : {
57 0 : mFilterNames.AppendElement(aTitle);
58 0 : mFilters.AppendElement(aFilter);
59 0 : return NS_OK;
60 : }
61 :
62 : NS_IMETHODIMP
63 0 : nsFilePickerProxy::GetDefaultString(nsAString& aDefaultString)
64 : {
65 0 : aDefaultString = mDefault;
66 0 : return NS_OK;
67 : }
68 :
69 : NS_IMETHODIMP
70 0 : nsFilePickerProxy::SetDefaultString(const nsAString& aDefaultString)
71 : {
72 0 : mDefault = aDefaultString;
73 0 : return NS_OK;
74 : }
75 :
76 : NS_IMETHODIMP
77 0 : nsFilePickerProxy::GetDefaultExtension(nsAString& aDefaultExtension)
78 : {
79 0 : aDefaultExtension = mDefaultExtension;
80 0 : return NS_OK;
81 : }
82 :
83 : NS_IMETHODIMP
84 0 : nsFilePickerProxy::SetDefaultExtension(const nsAString& aDefaultExtension)
85 : {
86 0 : mDefaultExtension = aDefaultExtension;
87 0 : return NS_OK;
88 : }
89 :
90 : NS_IMETHODIMP
91 0 : nsFilePickerProxy::GetFilterIndex(int32_t* aFilterIndex)
92 : {
93 0 : *aFilterIndex = mSelectedType;
94 0 : return NS_OK;
95 : }
96 :
97 : NS_IMETHODIMP
98 0 : nsFilePickerProxy::SetFilterIndex(int32_t aFilterIndex)
99 : {
100 0 : mSelectedType = aFilterIndex;
101 0 : return NS_OK;
102 : }
103 :
104 : NS_IMETHODIMP
105 0 : nsFilePickerProxy::GetFile(nsIFile** aFile)
106 : {
107 0 : MOZ_ASSERT(false, "GetFile is unimplemented; use GetDomFileOrDirectory");
108 : return NS_ERROR_FAILURE;
109 : }
110 :
111 : NS_IMETHODIMP
112 0 : nsFilePickerProxy::GetFileURL(nsIURI** aFileURL)
113 : {
114 0 : MOZ_ASSERT(false, "GetFileURL is unimplemented; use GetDomFileOrDirectory");
115 : return NS_ERROR_FAILURE;
116 : }
117 :
118 : NS_IMETHODIMP
119 0 : nsFilePickerProxy::GetFiles(nsISimpleEnumerator** aFiles)
120 : {
121 0 : MOZ_ASSERT(false, "GetFiles is unimplemented; use GetDomFileOrDirectoryEnumerator");
122 : return NS_ERROR_FAILURE;
123 : }
124 :
125 : NS_IMETHODIMP
126 0 : nsFilePickerProxy::Show(int16_t* aReturn)
127 : {
128 0 : MOZ_ASSERT(false, "Show is unimplemented; use Open");
129 : return NS_ERROR_NOT_IMPLEMENTED;
130 : }
131 :
132 : NS_IMETHODIMP
133 0 : nsFilePickerProxy::Open(nsIFilePickerShownCallback* aCallback)
134 : {
135 0 : mCallback = aCallback;
136 :
137 0 : nsString displayDirectory;
138 0 : if (mDisplayDirectory) {
139 0 : mDisplayDirectory->GetPath(displayDirectory);
140 : }
141 :
142 0 : if (!mIPCActive) {
143 0 : return NS_ERROR_FAILURE;
144 : }
145 :
146 0 : SendOpen(mSelectedType, mAddToRecentDocs, mDefault, mDefaultExtension,
147 : mFilters, mFilterNames, displayDirectory, mDisplaySpecialDirectory,
148 0 : mOkButtonLabel);
149 :
150 0 : return NS_OK;
151 : }
152 :
153 : mozilla::ipc::IPCResult
154 0 : nsFilePickerProxy::Recv__delete__(const MaybeInputData& aData,
155 : const int16_t& aResult)
156 : {
157 0 : if (aData.type() == MaybeInputData::TInputBlobs) {
158 0 : const InfallibleTArray<IPCBlob>& blobs = aData.get_InputBlobs().blobs();
159 0 : for (uint32_t i = 0; i < blobs.Length(); ++i) {
160 0 : RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(blobs[i]);
161 0 : NS_ENSURE_TRUE(blobImpl, IPC_OK());
162 :
163 0 : if (!blobImpl->IsFile()) {
164 0 : return IPC_OK();
165 : }
166 :
167 : nsPIDOMWindowInner* inner =
168 0 : mParent ? mParent->GetCurrentInnerWindow() : nullptr;
169 0 : RefPtr<File> file = File::Create(inner, blobImpl);
170 0 : MOZ_ASSERT(file);
171 :
172 0 : OwningFileOrDirectory* element = mFilesOrDirectories.AppendElement();
173 0 : element->SetAsFile() = file;
174 : }
175 0 : } else if (aData.type() == MaybeInputData::TInputDirectory) {
176 0 : nsCOMPtr<nsIFile> file;
177 0 : const nsAString& path(aData.get_InputDirectory().directoryPath());
178 0 : nsresult rv = NS_NewLocalFile(path, true, getter_AddRefs(file));
179 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
180 0 : return IPC_OK();
181 : }
182 :
183 : RefPtr<Directory> directory =
184 0 : Directory::Create(mParent->GetCurrentInnerWindow(), file);
185 0 : MOZ_ASSERT(directory);
186 :
187 0 : OwningFileOrDirectory* element = mFilesOrDirectories.AppendElement();
188 0 : element->SetAsDirectory() = directory;
189 : }
190 :
191 0 : if (mCallback) {
192 0 : mCallback->Done(aResult);
193 0 : mCallback = nullptr;
194 : }
195 :
196 0 : return IPC_OK();
197 : }
198 :
199 : NS_IMETHODIMP
200 0 : nsFilePickerProxy::GetDomFileOrDirectory(nsISupports** aValue)
201 : {
202 0 : *aValue = nullptr;
203 0 : if (mFilesOrDirectories.IsEmpty()) {
204 0 : return NS_OK;
205 : }
206 :
207 0 : MOZ_ASSERT(mFilesOrDirectories.Length() == 1);
208 :
209 0 : if (mFilesOrDirectories[0].IsFile()) {
210 0 : nsCOMPtr<nsIDOMBlob> blob = mFilesOrDirectories[0].GetAsFile().get();
211 0 : blob.forget(aValue);
212 0 : return NS_OK;
213 : }
214 :
215 0 : MOZ_ASSERT(mFilesOrDirectories[0].IsDirectory());
216 0 : RefPtr<Directory> directory = mFilesOrDirectories[0].GetAsDirectory();
217 0 : directory.forget(aValue);
218 0 : return NS_OK;
219 : }
220 :
221 : namespace {
222 :
223 : class SimpleEnumerator final : public nsISimpleEnumerator
224 : {
225 : public:
226 : NS_DECL_ISUPPORTS
227 :
228 : explicit
229 0 : SimpleEnumerator(const nsTArray<OwningFileOrDirectory>& aFilesOrDirectories)
230 0 : : mFilesOrDirectories(aFilesOrDirectories)
231 0 : , mIndex(0)
232 0 : {}
233 :
234 : NS_IMETHOD
235 0 : HasMoreElements(bool* aRetvalue) override
236 : {
237 0 : MOZ_ASSERT(aRetvalue);
238 0 : *aRetvalue = mIndex < mFilesOrDirectories.Length();
239 0 : return NS_OK;
240 : }
241 :
242 : NS_IMETHOD
243 0 : GetNext(nsISupports** aValue) override
244 : {
245 0 : NS_ENSURE_TRUE(mIndex < mFilesOrDirectories.Length(), NS_ERROR_FAILURE);
246 :
247 0 : uint32_t index = mIndex++;
248 :
249 0 : if (mFilesOrDirectories[index].IsFile()) {
250 0 : nsCOMPtr<nsIDOMBlob> blob = mFilesOrDirectories[index].GetAsFile().get();
251 0 : blob.forget(aValue);
252 0 : return NS_OK;
253 : }
254 :
255 0 : MOZ_ASSERT(mFilesOrDirectories[index].IsDirectory());
256 0 : RefPtr<Directory> directory = mFilesOrDirectories[index].GetAsDirectory();
257 0 : directory.forget(aValue);
258 0 : return NS_OK;
259 : }
260 :
261 : private:
262 0 : ~SimpleEnumerator()
263 0 : {}
264 :
265 : nsTArray<mozilla::dom::OwningFileOrDirectory> mFilesOrDirectories;
266 : uint32_t mIndex;
267 : };
268 :
269 0 : NS_IMPL_ISUPPORTS(SimpleEnumerator, nsISimpleEnumerator)
270 :
271 : } // namespace
272 :
273 : NS_IMETHODIMP
274 0 : nsFilePickerProxy::GetDomFileOrDirectoryEnumerator(nsISimpleEnumerator** aDomfiles)
275 : {
276 : RefPtr<SimpleEnumerator> enumerator =
277 0 : new SimpleEnumerator(mFilesOrDirectories);
278 0 : enumerator.forget(aDomfiles);
279 0 : return NS_OK;
280 : }
281 :
282 : void
283 0 : nsFilePickerProxy::ActorDestroy(ActorDestroyReason aWhy)
284 : {
285 0 : mIPCActive = false;
286 :
287 0 : if (mCallback) {
288 0 : mCallback->Done(nsIFilePicker::returnCancel);
289 0 : mCallback = nullptr;
290 : }
291 0 : }
|