1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/xpwidgets/nsBaseFilePicker.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,333 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "nsCOMPtr.h" 1.11 +#include "nsPIDOMWindow.h" 1.12 +#include "nsIDocShell.h" 1.13 +#include "nsIInterfaceRequestorUtils.h" 1.14 +#include "nsIBaseWindow.h" 1.15 +#include "nsIWidget.h" 1.16 + 1.17 +#include "nsIStringBundle.h" 1.18 +#include "nsXPIDLString.h" 1.19 +#include "nsIServiceManager.h" 1.20 +#include "nsCOMArray.h" 1.21 +#include "nsIFile.h" 1.22 +#include "nsDOMFile.h" 1.23 +#include "nsEnumeratorUtils.h" 1.24 +#include "mozilla/Services.h" 1.25 +#include "WidgetUtils.h" 1.26 +#include "nsThreadUtils.h" 1.27 + 1.28 +#include "nsBaseFilePicker.h" 1.29 + 1.30 +using namespace mozilla::widget; 1.31 + 1.32 +#define FILEPICKER_TITLES "chrome://global/locale/filepicker.properties" 1.33 +#define FILEPICKER_FILTERS "chrome://global/content/filepicker.properties" 1.34 + 1.35 +/** 1.36 + * A runnable to dispatch from the main thread to the main thread to display 1.37 + * the file picker while letting the showAsync method return right away. 1.38 +*/ 1.39 +class AsyncShowFilePicker : public nsRunnable 1.40 +{ 1.41 +public: 1.42 + AsyncShowFilePicker(nsIFilePicker *aFilePicker, 1.43 + nsIFilePickerShownCallback *aCallback) : 1.44 + mFilePicker(aFilePicker), 1.45 + mCallback(aCallback) 1.46 + { 1.47 + } 1.48 + 1.49 + NS_IMETHOD Run() 1.50 + { 1.51 + NS_ASSERTION(NS_IsMainThread(), 1.52 + "AsyncShowFilePicker should be on the main thread!"); 1.53 + 1.54 + // It's possible that some widget implementations require GUI operations 1.55 + // to be on the main thread, so that's why we're not dispatching to another 1.56 + // thread and calling back to the main after it's done. 1.57 + int16_t result = nsIFilePicker::returnCancel; 1.58 + nsresult rv = mFilePicker->Show(&result); 1.59 + if (NS_FAILED(rv)) { 1.60 + NS_ERROR("FilePicker's Show() implementation failed!"); 1.61 + } 1.62 + 1.63 + if (mCallback) { 1.64 + mCallback->Done(result); 1.65 + } 1.66 + return NS_OK; 1.67 + } 1.68 + 1.69 +private: 1.70 + nsRefPtr<nsIFilePicker> mFilePicker; 1.71 + nsRefPtr<nsIFilePickerShownCallback> mCallback; 1.72 +}; 1.73 + 1.74 +class nsBaseFilePickerEnumerator : public nsISimpleEnumerator 1.75 +{ 1.76 +public: 1.77 + NS_DECL_ISUPPORTS 1.78 + 1.79 + nsBaseFilePickerEnumerator(nsISimpleEnumerator* iterator) 1.80 + : mIterator(iterator) 1.81 + {} 1.82 + 1.83 + virtual ~nsBaseFilePickerEnumerator() 1.84 + {} 1.85 + 1.86 + NS_IMETHOD 1.87 + GetNext(nsISupports** aResult) 1.88 + { 1.89 + nsCOMPtr<nsISupports> tmp; 1.90 + nsresult rv = mIterator->GetNext(getter_AddRefs(tmp)); 1.91 + NS_ENSURE_SUCCESS(rv, rv); 1.92 + 1.93 + if (!tmp) { 1.94 + return NS_OK; 1.95 + } 1.96 + 1.97 + nsCOMPtr<nsIFile> localFile = do_QueryInterface(tmp); 1.98 + if (!localFile) { 1.99 + return NS_ERROR_FAILURE; 1.100 + } 1.101 + 1.102 + nsCOMPtr<nsIDOMFile> domFile = new nsDOMFileFile(localFile); 1.103 + domFile.forget(aResult); 1.104 + return NS_OK; 1.105 + } 1.106 + 1.107 + NS_IMETHOD 1.108 + HasMoreElements(bool* aResult) 1.109 + { 1.110 + return mIterator->HasMoreElements(aResult); 1.111 + } 1.112 + 1.113 +private: 1.114 + nsCOMPtr<nsISimpleEnumerator> mIterator; 1.115 +}; 1.116 + 1.117 +NS_IMPL_ISUPPORTS(nsBaseFilePickerEnumerator, nsISimpleEnumerator) 1.118 + 1.119 +nsBaseFilePicker::nsBaseFilePicker() 1.120 + : mAddToRecentDocs(true) 1.121 + , mMode(nsIFilePicker::modeOpen) 1.122 +{ 1.123 + 1.124 +} 1.125 + 1.126 +nsBaseFilePicker::~nsBaseFilePicker() 1.127 +{ 1.128 + 1.129 +} 1.130 + 1.131 +NS_IMETHODIMP nsBaseFilePicker::Init(nsIDOMWindow *aParent, 1.132 + const nsAString& aTitle, 1.133 + int16_t aMode) 1.134 +{ 1.135 + NS_PRECONDITION(aParent, "Null parent passed to filepicker, no file " 1.136 + "picker for you!"); 1.137 + nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(aParent); 1.138 + NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE); 1.139 + 1.140 + mMode = aMode; 1.141 + InitNative(widget, aTitle); 1.142 + 1.143 + return NS_OK; 1.144 +} 1.145 + 1.146 +NS_IMETHODIMP 1.147 +nsBaseFilePicker::Open(nsIFilePickerShownCallback *aCallback) 1.148 +{ 1.149 + nsCOMPtr<nsIRunnable> filePickerEvent = 1.150 + new AsyncShowFilePicker(this, aCallback); 1.151 + return NS_DispatchToMainThread(filePickerEvent); 1.152 +} 1.153 + 1.154 +NS_IMETHODIMP 1.155 +nsBaseFilePicker::AppendFilters(int32_t aFilterMask) 1.156 +{ 1.157 + nsCOMPtr<nsIStringBundleService> stringService = 1.158 + mozilla::services::GetStringBundleService(); 1.159 + if (!stringService) 1.160 + return NS_ERROR_FAILURE; 1.161 + 1.162 + nsCOMPtr<nsIStringBundle> titleBundle, filterBundle; 1.163 + 1.164 + nsresult rv = stringService->CreateBundle(FILEPICKER_TITLES, 1.165 + getter_AddRefs(titleBundle)); 1.166 + if (NS_FAILED(rv)) 1.167 + return NS_ERROR_FAILURE; 1.168 + 1.169 + rv = stringService->CreateBundle(FILEPICKER_FILTERS, getter_AddRefs(filterBundle)); 1.170 + if (NS_FAILED(rv)) 1.171 + return NS_ERROR_FAILURE; 1.172 + 1.173 + nsXPIDLString title; 1.174 + nsXPIDLString filter; 1.175 + 1.176 + if (aFilterMask & filterAll) { 1.177 + titleBundle->GetStringFromName(MOZ_UTF16("allTitle"), getter_Copies(title)); 1.178 + filterBundle->GetStringFromName(MOZ_UTF16("allFilter"), getter_Copies(filter)); 1.179 + AppendFilter(title,filter); 1.180 + } 1.181 + if (aFilterMask & filterHTML) { 1.182 + titleBundle->GetStringFromName(MOZ_UTF16("htmlTitle"), getter_Copies(title)); 1.183 + filterBundle->GetStringFromName(MOZ_UTF16("htmlFilter"), getter_Copies(filter)); 1.184 + AppendFilter(title,filter); 1.185 + } 1.186 + if (aFilterMask & filterText) { 1.187 + titleBundle->GetStringFromName(MOZ_UTF16("textTitle"), getter_Copies(title)); 1.188 + filterBundle->GetStringFromName(MOZ_UTF16("textFilter"), getter_Copies(filter)); 1.189 + AppendFilter(title,filter); 1.190 + } 1.191 + if (aFilterMask & filterImages) { 1.192 + titleBundle->GetStringFromName(MOZ_UTF16("imageTitle"), getter_Copies(title)); 1.193 + filterBundle->GetStringFromName(MOZ_UTF16("imageFilter"), getter_Copies(filter)); 1.194 + AppendFilter(title,filter); 1.195 + } 1.196 + if (aFilterMask & filterAudio) { 1.197 + titleBundle->GetStringFromName(MOZ_UTF16("audioTitle"), getter_Copies(title)); 1.198 + filterBundle->GetStringFromName(MOZ_UTF16("audioFilter"), getter_Copies(filter)); 1.199 + AppendFilter(title,filter); 1.200 + } 1.201 + if (aFilterMask & filterVideo) { 1.202 + titleBundle->GetStringFromName(MOZ_UTF16("videoTitle"), getter_Copies(title)); 1.203 + filterBundle->GetStringFromName(MOZ_UTF16("videoFilter"), getter_Copies(filter)); 1.204 + AppendFilter(title,filter); 1.205 + } 1.206 + if (aFilterMask & filterXML) { 1.207 + titleBundle->GetStringFromName(MOZ_UTF16("xmlTitle"), getter_Copies(title)); 1.208 + filterBundle->GetStringFromName(MOZ_UTF16("xmlFilter"), getter_Copies(filter)); 1.209 + AppendFilter(title,filter); 1.210 + } 1.211 + if (aFilterMask & filterXUL) { 1.212 + titleBundle->GetStringFromName(MOZ_UTF16("xulTitle"), getter_Copies(title)); 1.213 + filterBundle->GetStringFromName(MOZ_UTF16("xulFilter"), getter_Copies(filter)); 1.214 + AppendFilter(title, filter); 1.215 + } 1.216 + if (aFilterMask & filterApps) { 1.217 + titleBundle->GetStringFromName(MOZ_UTF16("appsTitle"), getter_Copies(title)); 1.218 + // Pass the magic string "..apps" to the platform filepicker, which it 1.219 + // should recognize and do the correct platform behavior for. 1.220 + AppendFilter(title, NS_LITERAL_STRING("..apps")); 1.221 + } 1.222 + return NS_OK; 1.223 +} 1.224 + 1.225 +// Set the filter index 1.226 +NS_IMETHODIMP nsBaseFilePicker::GetFilterIndex(int32_t *aFilterIndex) 1.227 +{ 1.228 + *aFilterIndex = 0; 1.229 + return NS_OK; 1.230 +} 1.231 + 1.232 +NS_IMETHODIMP nsBaseFilePicker::SetFilterIndex(int32_t aFilterIndex) 1.233 +{ 1.234 + return NS_OK; 1.235 +} 1.236 + 1.237 +NS_IMETHODIMP nsBaseFilePicker::GetFiles(nsISimpleEnumerator **aFiles) 1.238 +{ 1.239 + NS_ENSURE_ARG_POINTER(aFiles); 1.240 + nsCOMArray <nsIFile> files; 1.241 + nsresult rv; 1.242 + 1.243 + // if we get into the base class, the platform 1.244 + // doesn't implement GetFiles() yet. 1.245 + // so we fake it. 1.246 + nsCOMPtr <nsIFile> file; 1.247 + rv = GetFile(getter_AddRefs(file)); 1.248 + NS_ENSURE_SUCCESS(rv,rv); 1.249 + 1.250 + files.AppendObject(file); 1.251 + 1.252 + return NS_NewArrayEnumerator(aFiles, files); 1.253 +} 1.254 + 1.255 +// Set the display directory 1.256 +NS_IMETHODIMP nsBaseFilePicker::SetDisplayDirectory(nsIFile *aDirectory) 1.257 +{ 1.258 + if (!aDirectory) { 1.259 + mDisplayDirectory = nullptr; 1.260 + return NS_OK; 1.261 + } 1.262 + nsCOMPtr<nsIFile> directory; 1.263 + nsresult rv = aDirectory->Clone(getter_AddRefs(directory)); 1.264 + if (NS_FAILED(rv)) 1.265 + return rv; 1.266 + mDisplayDirectory = do_QueryInterface(directory, &rv); 1.267 + return rv; 1.268 +} 1.269 + 1.270 +// Get the display directory 1.271 +NS_IMETHODIMP nsBaseFilePicker::GetDisplayDirectory(nsIFile **aDirectory) 1.272 +{ 1.273 + *aDirectory = nullptr; 1.274 + if (!mDisplayDirectory) 1.275 + return NS_OK; 1.276 + nsCOMPtr<nsIFile> directory; 1.277 + nsresult rv = mDisplayDirectory->Clone(getter_AddRefs(directory)); 1.278 + if (NS_FAILED(rv)) { 1.279 + return rv; 1.280 + } 1.281 + directory.forget(aDirectory); 1.282 + return NS_OK; 1.283 +} 1.284 + 1.285 +NS_IMETHODIMP 1.286 +nsBaseFilePicker::GetAddToRecentDocs(bool *aFlag) 1.287 +{ 1.288 + *aFlag = mAddToRecentDocs; 1.289 + return NS_OK; 1.290 +} 1.291 + 1.292 +NS_IMETHODIMP 1.293 +nsBaseFilePicker::SetAddToRecentDocs(bool aFlag) 1.294 +{ 1.295 + mAddToRecentDocs = aFlag; 1.296 + return NS_OK; 1.297 +} 1.298 + 1.299 +NS_IMETHODIMP 1.300 +nsBaseFilePicker::GetMode(int16_t* aMode) 1.301 +{ 1.302 + *aMode = mMode; 1.303 + return NS_OK; 1.304 +} 1.305 + 1.306 +NS_IMETHODIMP 1.307 +nsBaseFilePicker::GetDomfile(nsIDOMFile** aDomfile) 1.308 +{ 1.309 + nsCOMPtr<nsIFile> localFile; 1.310 + nsresult rv = GetFile(getter_AddRefs(localFile)); 1.311 + NS_ENSURE_SUCCESS(rv, rv); 1.312 + 1.313 + if (!localFile) { 1.314 + *aDomfile = nullptr; 1.315 + return NS_OK; 1.316 + } 1.317 + 1.318 + nsRefPtr<nsDOMFileFile> domFile = new nsDOMFileFile(localFile); 1.319 + domFile.forget(aDomfile); 1.320 + return NS_OK; 1.321 +} 1.322 + 1.323 +NS_IMETHODIMP 1.324 +nsBaseFilePicker::GetDomfiles(nsISimpleEnumerator** aDomfiles) 1.325 +{ 1.326 + nsCOMPtr<nsISimpleEnumerator> iter; 1.327 + nsresult rv = GetFiles(getter_AddRefs(iter)); 1.328 + NS_ENSURE_SUCCESS(rv, rv); 1.329 + 1.330 + nsRefPtr<nsBaseFilePickerEnumerator> retIter = 1.331 + new nsBaseFilePickerEnumerator(iter); 1.332 + 1.333 + retIter.forget(aDomfiles); 1.334 + return NS_OK; 1.335 +} 1.336 +