1 /* -*- Mode: C++; tab-width: 2; 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/. */
8 #include "nsPIDOMWindow.h"
9 #include "nsIDocShell.h"
10 #include "nsIInterfaceRequestorUtils.h"
11 #include "nsIBaseWindow.h"
12 #include "nsIWidget.h"
14 #include "nsIStringBundle.h"
15 #include "nsXPIDLString.h"
16 #include "nsIServiceManager.h"
17 #include "nsCOMArray.h"
19 #include "nsDOMFile.h"
20 #include "nsEnumeratorUtils.h"
21 #include "mozilla/Services.h"
22 #include "WidgetUtils.h"
23 #include "nsThreadUtils.h"
25 #include "nsBaseFilePicker.h"
27 using namespace mozilla::widget
;
28 using namespace mozilla::dom
;
30 #define FILEPICKER_TITLES "chrome://global/locale/filepicker.properties"
31 #define FILEPICKER_FILTERS "chrome://global/content/filepicker.properties"
34 * A runnable to dispatch from the main thread to the main thread to display
35 * the file picker while letting the showAsync method return right away.
37 class AsyncShowFilePicker
: public nsRunnable
40 AsyncShowFilePicker(nsIFilePicker
*aFilePicker
,
41 nsIFilePickerShownCallback
*aCallback
) :
42 mFilePicker(aFilePicker
),
49 NS_ASSERTION(NS_IsMainThread(),
50 "AsyncShowFilePicker should be on the main thread!");
52 // It's possible that some widget implementations require GUI operations
53 // to be on the main thread, so that's why we're not dispatching to another
54 // thread and calling back to the main after it's done.
55 int16_t result
= nsIFilePicker::returnCancel
;
56 nsresult rv
= mFilePicker
->Show(&result
);
58 NS_ERROR("FilePicker's Show() implementation failed!");
62 mCallback
->Done(result
);
68 nsRefPtr
<nsIFilePicker
> mFilePicker
;
69 nsRefPtr
<nsIFilePickerShownCallback
> mCallback
;
72 class nsBaseFilePickerEnumerator
: public nsISimpleEnumerator
77 explicit nsBaseFilePickerEnumerator(nsISimpleEnumerator
* iterator
)
82 GetNext(nsISupports
** aResult
)
84 nsCOMPtr
<nsISupports
> tmp
;
85 nsresult rv
= mIterator
->GetNext(getter_AddRefs(tmp
));
86 NS_ENSURE_SUCCESS(rv
, rv
);
92 nsCOMPtr
<nsIFile
> localFile
= do_QueryInterface(tmp
);
94 return NS_ERROR_FAILURE
;
97 nsCOMPtr
<nsIDOMFile
> domFile
= DOMFile::CreateFromFile(localFile
);
98 domFile
.forget(aResult
);
103 HasMoreElements(bool* aResult
)
105 return mIterator
->HasMoreElements(aResult
);
109 virtual ~nsBaseFilePickerEnumerator()
113 nsCOMPtr
<nsISimpleEnumerator
> mIterator
;
116 NS_IMPL_ISUPPORTS(nsBaseFilePickerEnumerator
, nsISimpleEnumerator
)
118 nsBaseFilePicker::nsBaseFilePicker()
119 : mAddToRecentDocs(true)
120 , mMode(nsIFilePicker::modeOpen
)
125 nsBaseFilePicker::~nsBaseFilePicker()
130 NS_IMETHODIMP
nsBaseFilePicker::Init(nsIDOMWindow
*aParent
,
131 const nsAString
& aTitle
,
134 NS_PRECONDITION(aParent
, "Null parent passed to filepicker, no file "
136 nsCOMPtr
<nsIWidget
> widget
= WidgetUtils::DOMWindowToWidget(aParent
);
137 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
140 InitNative(widget
, aTitle
);
146 nsBaseFilePicker::Open(nsIFilePickerShownCallback
*aCallback
)
148 nsCOMPtr
<nsIRunnable
> filePickerEvent
=
149 new AsyncShowFilePicker(this, aCallback
);
150 return NS_DispatchToMainThread(filePickerEvent
);
154 nsBaseFilePicker::AppendFilters(int32_t aFilterMask
)
156 nsCOMPtr
<nsIStringBundleService
> stringService
=
157 mozilla::services::GetStringBundleService();
159 return NS_ERROR_FAILURE
;
161 nsCOMPtr
<nsIStringBundle
> titleBundle
, filterBundle
;
163 nsresult rv
= stringService
->CreateBundle(FILEPICKER_TITLES
,
164 getter_AddRefs(titleBundle
));
166 return NS_ERROR_FAILURE
;
168 rv
= stringService
->CreateBundle(FILEPICKER_FILTERS
, getter_AddRefs(filterBundle
));
170 return NS_ERROR_FAILURE
;
173 nsXPIDLString filter
;
175 if (aFilterMask
& filterAll
) {
176 titleBundle
->GetStringFromName(MOZ_UTF16("allTitle"), getter_Copies(title
));
177 filterBundle
->GetStringFromName(MOZ_UTF16("allFilter"), getter_Copies(filter
));
178 AppendFilter(title
,filter
);
180 if (aFilterMask
& filterHTML
) {
181 titleBundle
->GetStringFromName(MOZ_UTF16("htmlTitle"), getter_Copies(title
));
182 filterBundle
->GetStringFromName(MOZ_UTF16("htmlFilter"), getter_Copies(filter
));
183 AppendFilter(title
,filter
);
185 if (aFilterMask
& filterText
) {
186 titleBundle
->GetStringFromName(MOZ_UTF16("textTitle"), getter_Copies(title
));
187 filterBundle
->GetStringFromName(MOZ_UTF16("textFilter"), getter_Copies(filter
));
188 AppendFilter(title
,filter
);
190 if (aFilterMask
& filterImages
) {
191 titleBundle
->GetStringFromName(MOZ_UTF16("imageTitle"), getter_Copies(title
));
192 filterBundle
->GetStringFromName(MOZ_UTF16("imageFilter"), getter_Copies(filter
));
193 AppendFilter(title
,filter
);
195 if (aFilterMask
& filterAudio
) {
196 titleBundle
->GetStringFromName(MOZ_UTF16("audioTitle"), getter_Copies(title
));
197 filterBundle
->GetStringFromName(MOZ_UTF16("audioFilter"), getter_Copies(filter
));
198 AppendFilter(title
,filter
);
200 if (aFilterMask
& filterVideo
) {
201 titleBundle
->GetStringFromName(MOZ_UTF16("videoTitle"), getter_Copies(title
));
202 filterBundle
->GetStringFromName(MOZ_UTF16("videoFilter"), getter_Copies(filter
));
203 AppendFilter(title
,filter
);
205 if (aFilterMask
& filterXML
) {
206 titleBundle
->GetStringFromName(MOZ_UTF16("xmlTitle"), getter_Copies(title
));
207 filterBundle
->GetStringFromName(MOZ_UTF16("xmlFilter"), getter_Copies(filter
));
208 AppendFilter(title
,filter
);
210 if (aFilterMask
& filterXUL
) {
211 titleBundle
->GetStringFromName(MOZ_UTF16("xulTitle"), getter_Copies(title
));
212 filterBundle
->GetStringFromName(MOZ_UTF16("xulFilter"), getter_Copies(filter
));
213 AppendFilter(title
, filter
);
215 if (aFilterMask
& filterApps
) {
216 titleBundle
->GetStringFromName(MOZ_UTF16("appsTitle"), getter_Copies(title
));
217 // Pass the magic string "..apps" to the platform filepicker, which it
218 // should recognize and do the correct platform behavior for.
219 AppendFilter(title
, NS_LITERAL_STRING("..apps"));
224 // Set the filter index
225 NS_IMETHODIMP
nsBaseFilePicker::GetFilterIndex(int32_t *aFilterIndex
)
231 NS_IMETHODIMP
nsBaseFilePicker::SetFilterIndex(int32_t aFilterIndex
)
236 NS_IMETHODIMP
nsBaseFilePicker::GetFiles(nsISimpleEnumerator
**aFiles
)
238 NS_ENSURE_ARG_POINTER(aFiles
);
239 nsCOMArray
<nsIFile
> files
;
242 // if we get into the base class, the platform
243 // doesn't implement GetFiles() yet.
245 nsCOMPtr
<nsIFile
> file
;
246 rv
= GetFile(getter_AddRefs(file
));
247 NS_ENSURE_SUCCESS(rv
,rv
);
249 files
.AppendObject(file
);
251 return NS_NewArrayEnumerator(aFiles
, files
);
254 // Set the display directory
255 NS_IMETHODIMP
nsBaseFilePicker::SetDisplayDirectory(nsIFile
*aDirectory
)
258 mDisplayDirectory
= nullptr;
261 nsCOMPtr
<nsIFile
> directory
;
262 nsresult rv
= aDirectory
->Clone(getter_AddRefs(directory
));
265 mDisplayDirectory
= do_QueryInterface(directory
, &rv
);
269 // Get the display directory
270 NS_IMETHODIMP
nsBaseFilePicker::GetDisplayDirectory(nsIFile
**aDirectory
)
272 *aDirectory
= nullptr;
273 if (!mDisplayDirectory
)
275 nsCOMPtr
<nsIFile
> directory
;
276 nsresult rv
= mDisplayDirectory
->Clone(getter_AddRefs(directory
));
280 directory
.forget(aDirectory
);
285 nsBaseFilePicker::GetAddToRecentDocs(bool *aFlag
)
287 *aFlag
= mAddToRecentDocs
;
292 nsBaseFilePicker::SetAddToRecentDocs(bool aFlag
)
294 mAddToRecentDocs
= aFlag
;
299 nsBaseFilePicker::GetMode(int16_t* aMode
)
306 nsBaseFilePicker::GetDomfile(nsIDOMFile
** aDomfile
)
308 nsCOMPtr
<nsIFile
> localFile
;
309 nsresult rv
= GetFile(getter_AddRefs(localFile
));
310 NS_ENSURE_SUCCESS(rv
, rv
);
317 nsRefPtr
<DOMFile
> domFile
= DOMFile::CreateFromFile(localFile
);
318 domFile
.forget(aDomfile
);
323 nsBaseFilePicker::GetDomfiles(nsISimpleEnumerator
** aDomfiles
)
325 nsCOMPtr
<nsISimpleEnumerator
> iter
;
326 nsresult rv
= GetFiles(getter_AddRefs(iter
));
327 NS_ENSURE_SUCCESS(rv
, rv
);
329 nsRefPtr
<nsBaseFilePickerEnumerator
> retIter
=
330 new nsBaseFilePickerEnumerator(iter
);
332 retIter
.forget(aDomfiles
);