Bumping manifests a=b2g-bump
[gecko.git] / widget / nsBaseFilePicker.cpp
blobda745d357882a7222c12cd6cf41518de7dec9ca7
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/. */
7 #include "nsCOMPtr.h"
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"
18 #include "nsIFile.h"
19 #include "nsEnumeratorUtils.h"
20 #include "mozilla/dom/File.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"
33 /**
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
39 public:
40 AsyncShowFilePicker(nsIFilePicker *aFilePicker,
41 nsIFilePickerShownCallback *aCallback) :
42 mFilePicker(aFilePicker),
43 mCallback(aCallback)
47 NS_IMETHOD Run()
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);
57 if (NS_FAILED(rv)) {
58 NS_ERROR("FilePicker's Show() implementation failed!");
61 if (mCallback) {
62 mCallback->Done(result);
64 return NS_OK;
67 private:
68 nsRefPtr<nsIFilePicker> mFilePicker;
69 nsRefPtr<nsIFilePickerShownCallback> mCallback;
72 class nsBaseFilePickerEnumerator : public nsISimpleEnumerator
74 public:
75 NS_DECL_ISUPPORTS
77 explicit nsBaseFilePickerEnumerator(nsPIDOMWindow* aParent,
78 nsISimpleEnumerator* iterator)
79 : mIterator(iterator)
80 , mParent(aParent)
83 NS_IMETHOD
84 GetNext(nsISupports** aResult) MOZ_OVERRIDE
86 nsCOMPtr<nsISupports> tmp;
87 nsresult rv = mIterator->GetNext(getter_AddRefs(tmp));
88 NS_ENSURE_SUCCESS(rv, rv);
90 if (!tmp) {
91 return NS_OK;
94 nsCOMPtr<nsIFile> localFile = do_QueryInterface(tmp);
95 if (!localFile) {
96 return NS_ERROR_FAILURE;
99 nsCOMPtr<nsIDOMFile> domFile = File::CreateFromFile(mParent, localFile);
100 domFile.forget(aResult);
101 return NS_OK;
104 NS_IMETHOD
105 HasMoreElements(bool* aResult) MOZ_OVERRIDE
107 return mIterator->HasMoreElements(aResult);
110 protected:
111 virtual ~nsBaseFilePickerEnumerator()
114 private:
115 nsCOMPtr<nsISimpleEnumerator> mIterator;
116 nsCOMPtr<nsPIDOMWindow> mParent;
119 NS_IMPL_ISUPPORTS(nsBaseFilePickerEnumerator, nsISimpleEnumerator)
121 nsBaseFilePicker::nsBaseFilePicker()
122 : mAddToRecentDocs(true)
123 , mMode(nsIFilePicker::modeOpen)
128 nsBaseFilePicker::~nsBaseFilePicker()
133 NS_IMETHODIMP nsBaseFilePicker::Init(nsIDOMWindow *aParent,
134 const nsAString& aTitle,
135 int16_t aMode)
137 NS_PRECONDITION(aParent, "Null parent passed to filepicker, no file "
138 "picker for you!");
139 nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aParent);
140 NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
142 mParent = do_QueryInterface(aParent);
143 if (!mParent->IsInnerWindow()) {
144 mParent = mParent->GetCurrentInnerWindow();
147 mMode = aMode;
148 InitNative(widget, aTitle);
150 return NS_OK;
153 NS_IMETHODIMP
154 nsBaseFilePicker::Open(nsIFilePickerShownCallback *aCallback)
156 nsCOMPtr<nsIRunnable> filePickerEvent =
157 new AsyncShowFilePicker(this, aCallback);
158 return NS_DispatchToMainThread(filePickerEvent);
161 NS_IMETHODIMP
162 nsBaseFilePicker::AppendFilters(int32_t aFilterMask)
164 nsCOMPtr<nsIStringBundleService> stringService =
165 mozilla::services::GetStringBundleService();
166 if (!stringService)
167 return NS_ERROR_FAILURE;
169 nsCOMPtr<nsIStringBundle> titleBundle, filterBundle;
171 nsresult rv = stringService->CreateBundle(FILEPICKER_TITLES,
172 getter_AddRefs(titleBundle));
173 if (NS_FAILED(rv))
174 return NS_ERROR_FAILURE;
176 rv = stringService->CreateBundle(FILEPICKER_FILTERS, getter_AddRefs(filterBundle));
177 if (NS_FAILED(rv))
178 return NS_ERROR_FAILURE;
180 nsXPIDLString title;
181 nsXPIDLString filter;
183 if (aFilterMask & filterAll) {
184 titleBundle->GetStringFromName(MOZ_UTF16("allTitle"), getter_Copies(title));
185 filterBundle->GetStringFromName(MOZ_UTF16("allFilter"), getter_Copies(filter));
186 AppendFilter(title,filter);
188 if (aFilterMask & filterHTML) {
189 titleBundle->GetStringFromName(MOZ_UTF16("htmlTitle"), getter_Copies(title));
190 filterBundle->GetStringFromName(MOZ_UTF16("htmlFilter"), getter_Copies(filter));
191 AppendFilter(title,filter);
193 if (aFilterMask & filterText) {
194 titleBundle->GetStringFromName(MOZ_UTF16("textTitle"), getter_Copies(title));
195 filterBundle->GetStringFromName(MOZ_UTF16("textFilter"), getter_Copies(filter));
196 AppendFilter(title,filter);
198 if (aFilterMask & filterImages) {
199 titleBundle->GetStringFromName(MOZ_UTF16("imageTitle"), getter_Copies(title));
200 filterBundle->GetStringFromName(MOZ_UTF16("imageFilter"), getter_Copies(filter));
201 AppendFilter(title,filter);
203 if (aFilterMask & filterAudio) {
204 titleBundle->GetStringFromName(MOZ_UTF16("audioTitle"), getter_Copies(title));
205 filterBundle->GetStringFromName(MOZ_UTF16("audioFilter"), getter_Copies(filter));
206 AppendFilter(title,filter);
208 if (aFilterMask & filterVideo) {
209 titleBundle->GetStringFromName(MOZ_UTF16("videoTitle"), getter_Copies(title));
210 filterBundle->GetStringFromName(MOZ_UTF16("videoFilter"), getter_Copies(filter));
211 AppendFilter(title,filter);
213 if (aFilterMask & filterXML) {
214 titleBundle->GetStringFromName(MOZ_UTF16("xmlTitle"), getter_Copies(title));
215 filterBundle->GetStringFromName(MOZ_UTF16("xmlFilter"), getter_Copies(filter));
216 AppendFilter(title,filter);
218 if (aFilterMask & filterXUL) {
219 titleBundle->GetStringFromName(MOZ_UTF16("xulTitle"), getter_Copies(title));
220 filterBundle->GetStringFromName(MOZ_UTF16("xulFilter"), getter_Copies(filter));
221 AppendFilter(title, filter);
223 if (aFilterMask & filterApps) {
224 titleBundle->GetStringFromName(MOZ_UTF16("appsTitle"), getter_Copies(title));
225 // Pass the magic string "..apps" to the platform filepicker, which it
226 // should recognize and do the correct platform behavior for.
227 AppendFilter(title, NS_LITERAL_STRING("..apps"));
229 return NS_OK;
232 // Set the filter index
233 NS_IMETHODIMP nsBaseFilePicker::GetFilterIndex(int32_t *aFilterIndex)
235 *aFilterIndex = 0;
236 return NS_OK;
239 NS_IMETHODIMP nsBaseFilePicker::SetFilterIndex(int32_t aFilterIndex)
241 return NS_OK;
244 NS_IMETHODIMP nsBaseFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
246 NS_ENSURE_ARG_POINTER(aFiles);
247 nsCOMArray <nsIFile> files;
248 nsresult rv;
250 // if we get into the base class, the platform
251 // doesn't implement GetFiles() yet.
252 // so we fake it.
253 nsCOMPtr <nsIFile> file;
254 rv = GetFile(getter_AddRefs(file));
255 NS_ENSURE_SUCCESS(rv,rv);
257 files.AppendObject(file);
259 return NS_NewArrayEnumerator(aFiles, files);
262 // Set the display directory
263 NS_IMETHODIMP nsBaseFilePicker::SetDisplayDirectory(nsIFile *aDirectory)
265 if (!aDirectory) {
266 mDisplayDirectory = nullptr;
267 return NS_OK;
269 nsCOMPtr<nsIFile> directory;
270 nsresult rv = aDirectory->Clone(getter_AddRefs(directory));
271 if (NS_FAILED(rv))
272 return rv;
273 mDisplayDirectory = do_QueryInterface(directory, &rv);
274 return rv;
277 // Get the display directory
278 NS_IMETHODIMP nsBaseFilePicker::GetDisplayDirectory(nsIFile **aDirectory)
280 *aDirectory = nullptr;
281 if (!mDisplayDirectory)
282 return NS_OK;
283 nsCOMPtr<nsIFile> directory;
284 nsresult rv = mDisplayDirectory->Clone(getter_AddRefs(directory));
285 if (NS_FAILED(rv)) {
286 return rv;
288 directory.forget(aDirectory);
289 return NS_OK;
292 NS_IMETHODIMP
293 nsBaseFilePicker::GetAddToRecentDocs(bool *aFlag)
295 *aFlag = mAddToRecentDocs;
296 return NS_OK;
299 NS_IMETHODIMP
300 nsBaseFilePicker::SetAddToRecentDocs(bool aFlag)
302 mAddToRecentDocs = aFlag;
303 return NS_OK;
306 NS_IMETHODIMP
307 nsBaseFilePicker::GetMode(int16_t* aMode)
309 *aMode = mMode;
310 return NS_OK;
313 NS_IMETHODIMP
314 nsBaseFilePicker::GetDomfile(nsIDOMFile** aDomfile)
316 nsCOMPtr<nsIFile> localFile;
317 nsresult rv = GetFile(getter_AddRefs(localFile));
318 NS_ENSURE_SUCCESS(rv, rv);
320 if (!localFile) {
321 *aDomfile = nullptr;
322 return NS_OK;
325 nsRefPtr<File> domFile = File::CreateFromFile(mParent, localFile);
326 domFile.forget(aDomfile);
327 return NS_OK;
330 NS_IMETHODIMP
331 nsBaseFilePicker::GetDomfiles(nsISimpleEnumerator** aDomfiles)
333 nsCOMPtr<nsISimpleEnumerator> iter;
334 nsresult rv = GetFiles(getter_AddRefs(iter));
335 NS_ENSURE_SUCCESS(rv, rv);
337 nsRefPtr<nsBaseFilePickerEnumerator> retIter =
338 new nsBaseFilePickerEnumerator(mParent, iter);
340 retIter.forget(aDomfiles);
341 return NS_OK;