Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
1 /* -*- Mode: C++; tab-width: 2; 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/. */
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 "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;
29 #define FILEPICKER_TITLES "chrome://global/locale/filepicker.properties"
30 #define FILEPICKER_FILTERS "chrome://global/content/filepicker.properties"
32 /**
33 * A runnable to dispatch from the main thread to the main thread to display
34 * the file picker while letting the showAsync method return right away.
35 */
36 class AsyncShowFilePicker : public nsRunnable
37 {
38 public:
39 AsyncShowFilePicker(nsIFilePicker *aFilePicker,
40 nsIFilePickerShownCallback *aCallback) :
41 mFilePicker(aFilePicker),
42 mCallback(aCallback)
43 {
44 }
46 NS_IMETHOD Run()
47 {
48 NS_ASSERTION(NS_IsMainThread(),
49 "AsyncShowFilePicker should be on the main thread!");
51 // It's possible that some widget implementations require GUI operations
52 // to be on the main thread, so that's why we're not dispatching to another
53 // thread and calling back to the main after it's done.
54 int16_t result = nsIFilePicker::returnCancel;
55 nsresult rv = mFilePicker->Show(&result);
56 if (NS_FAILED(rv)) {
57 NS_ERROR("FilePicker's Show() implementation failed!");
58 }
60 if (mCallback) {
61 mCallback->Done(result);
62 }
63 return NS_OK;
64 }
66 private:
67 nsRefPtr<nsIFilePicker> mFilePicker;
68 nsRefPtr<nsIFilePickerShownCallback> mCallback;
69 };
71 class nsBaseFilePickerEnumerator : public nsISimpleEnumerator
72 {
73 public:
74 NS_DECL_ISUPPORTS
76 nsBaseFilePickerEnumerator(nsISimpleEnumerator* iterator)
77 : mIterator(iterator)
78 {}
80 virtual ~nsBaseFilePickerEnumerator()
81 {}
83 NS_IMETHOD
84 GetNext(nsISupports** aResult)
85 {
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;
92 }
94 nsCOMPtr<nsIFile> localFile = do_QueryInterface(tmp);
95 if (!localFile) {
96 return NS_ERROR_FAILURE;
97 }
99 nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(localFile);
100 domFile.forget(aResult);
101 return NS_OK;
102 }
104 NS_IMETHOD
105 HasMoreElements(bool* aResult)
106 {
107 return mIterator->HasMoreElements(aResult);
108 }
110 private:
111 nsCOMPtr<nsISimpleEnumerator> mIterator;
112 };
114 NS_IMPL_ISUPPORTS(nsBaseFilePickerEnumerator, nsISimpleEnumerator)
116 nsBaseFilePicker::nsBaseFilePicker()
117 : mAddToRecentDocs(true)
118 , mMode(nsIFilePicker::modeOpen)
119 {
121 }
123 nsBaseFilePicker::~nsBaseFilePicker()
124 {
126 }
128 NS_IMETHODIMP nsBaseFilePicker::Init(nsIDOMWindow *aParent,
129 const nsAString& aTitle,
130 int16_t aMode)
131 {
132 NS_PRECONDITION(aParent, "Null parent passed to filepicker, no file "
133 "picker for you!");
134 nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aParent);
135 NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
137 mMode = aMode;
138 InitNative(widget, aTitle);
140 return NS_OK;
141 }
143 NS_IMETHODIMP
144 nsBaseFilePicker::Open(nsIFilePickerShownCallback *aCallback)
145 {
146 nsCOMPtr<nsIRunnable> filePickerEvent =
147 new AsyncShowFilePicker(this, aCallback);
148 return NS_DispatchToMainThread(filePickerEvent);
149 }
151 NS_IMETHODIMP
152 nsBaseFilePicker::AppendFilters(int32_t aFilterMask)
153 {
154 nsCOMPtr<nsIStringBundleService> stringService =
155 mozilla::services::GetStringBundleService();
156 if (!stringService)
157 return NS_ERROR_FAILURE;
159 nsCOMPtr<nsIStringBundle> titleBundle, filterBundle;
161 nsresult rv = stringService->CreateBundle(FILEPICKER_TITLES,
162 getter_AddRefs(titleBundle));
163 if (NS_FAILED(rv))
164 return NS_ERROR_FAILURE;
166 rv = stringService->CreateBundle(FILEPICKER_FILTERS, getter_AddRefs(filterBundle));
167 if (NS_FAILED(rv))
168 return NS_ERROR_FAILURE;
170 nsXPIDLString title;
171 nsXPIDLString filter;
173 if (aFilterMask & filterAll) {
174 titleBundle->GetStringFromName(MOZ_UTF16("allTitle"), getter_Copies(title));
175 filterBundle->GetStringFromName(MOZ_UTF16("allFilter"), getter_Copies(filter));
176 AppendFilter(title,filter);
177 }
178 if (aFilterMask & filterHTML) {
179 titleBundle->GetStringFromName(MOZ_UTF16("htmlTitle"), getter_Copies(title));
180 filterBundle->GetStringFromName(MOZ_UTF16("htmlFilter"), getter_Copies(filter));
181 AppendFilter(title,filter);
182 }
183 if (aFilterMask & filterText) {
184 titleBundle->GetStringFromName(MOZ_UTF16("textTitle"), getter_Copies(title));
185 filterBundle->GetStringFromName(MOZ_UTF16("textFilter"), getter_Copies(filter));
186 AppendFilter(title,filter);
187 }
188 if (aFilterMask & filterImages) {
189 titleBundle->GetStringFromName(MOZ_UTF16("imageTitle"), getter_Copies(title));
190 filterBundle->GetStringFromName(MOZ_UTF16("imageFilter"), getter_Copies(filter));
191 AppendFilter(title,filter);
192 }
193 if (aFilterMask & filterAudio) {
194 titleBundle->GetStringFromName(MOZ_UTF16("audioTitle"), getter_Copies(title));
195 filterBundle->GetStringFromName(MOZ_UTF16("audioFilter"), getter_Copies(filter));
196 AppendFilter(title,filter);
197 }
198 if (aFilterMask & filterVideo) {
199 titleBundle->GetStringFromName(MOZ_UTF16("videoTitle"), getter_Copies(title));
200 filterBundle->GetStringFromName(MOZ_UTF16("videoFilter"), getter_Copies(filter));
201 AppendFilter(title,filter);
202 }
203 if (aFilterMask & filterXML) {
204 titleBundle->GetStringFromName(MOZ_UTF16("xmlTitle"), getter_Copies(title));
205 filterBundle->GetStringFromName(MOZ_UTF16("xmlFilter"), getter_Copies(filter));
206 AppendFilter(title,filter);
207 }
208 if (aFilterMask & filterXUL) {
209 titleBundle->GetStringFromName(MOZ_UTF16("xulTitle"), getter_Copies(title));
210 filterBundle->GetStringFromName(MOZ_UTF16("xulFilter"), getter_Copies(filter));
211 AppendFilter(title, filter);
212 }
213 if (aFilterMask & filterApps) {
214 titleBundle->GetStringFromName(MOZ_UTF16("appsTitle"), getter_Copies(title));
215 // Pass the magic string "..apps" to the platform filepicker, which it
216 // should recognize and do the correct platform behavior for.
217 AppendFilter(title, NS_LITERAL_STRING("..apps"));
218 }
219 return NS_OK;
220 }
222 // Set the filter index
223 NS_IMETHODIMP nsBaseFilePicker::GetFilterIndex(int32_t *aFilterIndex)
224 {
225 *aFilterIndex = 0;
226 return NS_OK;
227 }
229 NS_IMETHODIMP nsBaseFilePicker::SetFilterIndex(int32_t aFilterIndex)
230 {
231 return NS_OK;
232 }
234 NS_IMETHODIMP nsBaseFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
235 {
236 NS_ENSURE_ARG_POINTER(aFiles);
237 nsCOMArray <nsIFile> files;
238 nsresult rv;
240 // if we get into the base class, the platform
241 // doesn't implement GetFiles() yet.
242 // so we fake it.
243 nsCOMPtr <nsIFile> file;
244 rv = GetFile(getter_AddRefs(file));
245 NS_ENSURE_SUCCESS(rv,rv);
247 files.AppendObject(file);
249 return NS_NewArrayEnumerator(aFiles, files);
250 }
252 // Set the display directory
253 NS_IMETHODIMP nsBaseFilePicker::SetDisplayDirectory(nsIFile *aDirectory)
254 {
255 if (!aDirectory) {
256 mDisplayDirectory = nullptr;
257 return NS_OK;
258 }
259 nsCOMPtr<nsIFile> directory;
260 nsresult rv = aDirectory->Clone(getter_AddRefs(directory));
261 if (NS_FAILED(rv))
262 return rv;
263 mDisplayDirectory = do_QueryInterface(directory, &rv);
264 return rv;
265 }
267 // Get the display directory
268 NS_IMETHODIMP nsBaseFilePicker::GetDisplayDirectory(nsIFile **aDirectory)
269 {
270 *aDirectory = nullptr;
271 if (!mDisplayDirectory)
272 return NS_OK;
273 nsCOMPtr<nsIFile> directory;
274 nsresult rv = mDisplayDirectory->Clone(getter_AddRefs(directory));
275 if (NS_FAILED(rv)) {
276 return rv;
277 }
278 directory.forget(aDirectory);
279 return NS_OK;
280 }
282 NS_IMETHODIMP
283 nsBaseFilePicker::GetAddToRecentDocs(bool *aFlag)
284 {
285 *aFlag = mAddToRecentDocs;
286 return NS_OK;
287 }
289 NS_IMETHODIMP
290 nsBaseFilePicker::SetAddToRecentDocs(bool aFlag)
291 {
292 mAddToRecentDocs = aFlag;
293 return NS_OK;
294 }
296 NS_IMETHODIMP
297 nsBaseFilePicker::GetMode(int16_t* aMode)
298 {
299 *aMode = mMode;
300 return NS_OK;
301 }
303 NS_IMETHODIMP
304 nsBaseFilePicker::GetDomfile(nsIDOMFile** aDomfile)
305 {
306 nsCOMPtr<nsIFile> localFile;
307 nsresult rv = GetFile(getter_AddRefs(localFile));
308 NS_ENSURE_SUCCESS(rv, rv);
310 if (!localFile) {
311 *aDomfile = nullptr;
312 return NS_OK;
313 }
315 nsRefPtr<nsDOMFileFile> domFile = new nsDOMFileFile(localFile);
316 domFile.forget(aDomfile);
317 return NS_OK;
318 }
320 NS_IMETHODIMP
321 nsBaseFilePicker::GetDomfiles(nsISimpleEnumerator** aDomfiles)
322 {
323 nsCOMPtr<nsISimpleEnumerator> iter;
324 nsresult rv = GetFiles(getter_AddRefs(iter));
325 NS_ENSURE_SUCCESS(rv, rv);
327 nsRefPtr<nsBaseFilePickerEnumerator> retIter =
328 new nsBaseFilePickerEnumerator(iter);
330 retIter.forget(aDomfiles);
331 return NS_OK;
332 }