LCOV - code coverage report
Current view: top level - widget - nsBaseFilePicker.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 194 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 33 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : #include "nsCOMPtr.h"
       8             : #include "nsPIDOMWindow.h"
       9             : #include "nsIDocShell.h"
      10             : #include "nsIInterfaceRequestorUtils.h"
      11             : #include "nsIBaseWindow.h"
      12             : #include "nsIWidget.h"
      13             : 
      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/Directory.h"
      21             : #include "mozilla/dom/File.h"
      22             : #include "mozilla/Services.h"
      23             : #include "WidgetUtils.h"
      24             : #include "nsThreadUtils.h"
      25             : 
      26             : #include "nsBaseFilePicker.h"
      27             : 
      28             : using namespace mozilla::widget;
      29             : using namespace mozilla::dom;
      30             : 
      31             : #define FILEPICKER_TITLES "chrome://global/locale/filepicker.properties"
      32             : #define FILEPICKER_FILTERS "chrome://global/content/filepicker.properties"
      33             : 
      34             : namespace {
      35             : 
      36             : nsresult
      37           0 : LocalFileToDirectoryOrBlob(nsPIDOMWindowInner* aWindow,
      38             :                            bool aIsDirectory,
      39             :                            nsIFile* aFile,
      40             :                            nsISupports** aResult)
      41             : {
      42           0 :   if (aIsDirectory) {
      43             : #ifdef DEBUG
      44             :     bool isDir;
      45           0 :     aFile->IsDirectory(&isDir);
      46           0 :     MOZ_ASSERT(isDir);
      47             : #endif
      48             : 
      49           0 :     RefPtr<Directory> directory = Directory::Create(aWindow, aFile);
      50           0 :     MOZ_ASSERT(directory);
      51             : 
      52           0 :     directory.forget(aResult);
      53           0 :     return NS_OK;
      54             :   }
      55             : 
      56           0 :   nsCOMPtr<nsIDOMBlob> blob = File::CreateFromFile(aWindow, aFile);
      57           0 :   blob.forget(aResult);
      58           0 :   return NS_OK;
      59             : }
      60             : 
      61             : } // anonymous namespace
      62             : 
      63             : /**
      64             :  * A runnable to dispatch from the main thread to the main thread to display
      65             :  * the file picker while letting the showAsync method return right away.
      66             : */
      67           0 : class AsyncShowFilePicker : public mozilla::Runnable
      68             : {
      69             : public:
      70           0 :   AsyncShowFilePicker(nsIFilePicker* aFilePicker,
      71             :                       nsIFilePickerShownCallback* aCallback)
      72           0 :     : mozilla::Runnable("AsyncShowFilePicker")
      73             :     , mFilePicker(aFilePicker)
      74           0 :     , mCallback(aCallback)
      75             :   {
      76           0 :   }
      77             : 
      78           0 :   NS_IMETHOD Run() override
      79             :   {
      80           0 :     NS_ASSERTION(NS_IsMainThread(),
      81             :                  "AsyncShowFilePicker should be on the main thread!");
      82             : 
      83             :     // It's possible that some widget implementations require GUI operations
      84             :     // to be on the main thread, so that's why we're not dispatching to another
      85             :     // thread and calling back to the main after it's done.
      86           0 :     int16_t result = nsIFilePicker::returnCancel;
      87           0 :     nsresult rv = mFilePicker->Show(&result);
      88           0 :     if (NS_FAILED(rv)) {
      89           0 :       NS_ERROR("FilePicker's Show() implementation failed!");
      90             :     }
      91             : 
      92           0 :     if (mCallback) {
      93           0 :       mCallback->Done(result);
      94             :     }
      95           0 :     return NS_OK;
      96             :   }
      97             : 
      98             : private:
      99             :   RefPtr<nsIFilePicker> mFilePicker;
     100             :   RefPtr<nsIFilePickerShownCallback> mCallback;
     101             : };
     102             : 
     103             : class nsBaseFilePickerEnumerator : public nsISimpleEnumerator
     104             : {
     105             : public:
     106             :   NS_DECL_ISUPPORTS
     107             : 
     108           0 :   nsBaseFilePickerEnumerator(nsPIDOMWindowOuter* aParent,
     109             :                              nsISimpleEnumerator* iterator,
     110             :                              int16_t aMode)
     111           0 :     : mIterator(iterator)
     112             :     , mParent(aParent->GetCurrentInnerWindow())
     113           0 :     , mMode(aMode)
     114           0 :   {}
     115             : 
     116             :   NS_IMETHOD
     117           0 :   GetNext(nsISupports** aResult) override
     118             :   {
     119           0 :     nsCOMPtr<nsISupports> tmp;
     120           0 :     nsresult rv = mIterator->GetNext(getter_AddRefs(tmp));
     121           0 :     NS_ENSURE_SUCCESS(rv, rv);
     122             : 
     123           0 :     if (!tmp) {
     124           0 :       return NS_OK;
     125             :     }
     126             : 
     127           0 :     nsCOMPtr<nsIFile> localFile = do_QueryInterface(tmp);
     128           0 :     if (!localFile) {
     129           0 :       return NS_ERROR_FAILURE;
     130             :     }
     131             : 
     132           0 :     return LocalFileToDirectoryOrBlob(mParent,
     133           0 :                                       mMode == nsIFilePicker::modeGetFolder,
     134             :                                       localFile,
     135           0 :                                       aResult);
     136             :   }
     137             : 
     138             :   NS_IMETHOD
     139           0 :   HasMoreElements(bool* aResult) override
     140             :   {
     141           0 :     return mIterator->HasMoreElements(aResult);
     142             :   }
     143             : 
     144             : protected:
     145           0 :   virtual ~nsBaseFilePickerEnumerator()
     146           0 :   {}
     147             : 
     148             : private:
     149             :   nsCOMPtr<nsISimpleEnumerator> mIterator;
     150             :   nsCOMPtr<nsPIDOMWindowInner> mParent;
     151             :   int16_t mMode;
     152             : };
     153             : 
     154           0 : NS_IMPL_ISUPPORTS(nsBaseFilePickerEnumerator, nsISimpleEnumerator)
     155             : 
     156           0 : nsBaseFilePicker::nsBaseFilePicker()
     157             :   : mAddToRecentDocs(true)
     158           0 :   , mMode(nsIFilePicker::modeOpen)
     159             : {
     160             : 
     161           0 : }
     162             : 
     163           0 : nsBaseFilePicker::~nsBaseFilePicker()
     164             : {
     165             : 
     166           0 : }
     167             : 
     168           0 : NS_IMETHODIMP nsBaseFilePicker::Init(mozIDOMWindowProxy* aParent,
     169             :                                      const nsAString& aTitle,
     170             :                                      int16_t aMode)
     171             : {
     172           0 :   NS_PRECONDITION(aParent, "Null parent passed to filepicker, no file "
     173             :                   "picker for you!");
     174             : 
     175           0 :   mParent = nsPIDOMWindowOuter::From(aParent);
     176             : 
     177           0 :   nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(mParent->GetOuterWindow());
     178           0 :   NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
     179             : 
     180             : 
     181           0 :   mMode = aMode;
     182           0 :   InitNative(widget, aTitle);
     183             : 
     184           0 :   return NS_OK;
     185             : }
     186             : 
     187             : NS_IMETHODIMP
     188           0 : nsBaseFilePicker::Open(nsIFilePickerShownCallback *aCallback)
     189             : {
     190             :   nsCOMPtr<nsIRunnable> filePickerEvent =
     191           0 :     new AsyncShowFilePicker(this, aCallback);
     192           0 :   return NS_DispatchToMainThread(filePickerEvent);
     193             : }
     194             : 
     195             : NS_IMETHODIMP
     196           0 : nsBaseFilePicker::AppendFilters(int32_t aFilterMask)
     197             : {
     198             :   nsCOMPtr<nsIStringBundleService> stringService =
     199           0 :     mozilla::services::GetStringBundleService();
     200           0 :   if (!stringService)
     201           0 :     return NS_ERROR_FAILURE;
     202             : 
     203           0 :   nsCOMPtr<nsIStringBundle> titleBundle, filterBundle;
     204             : 
     205           0 :   nsresult rv = stringService->CreateBundle(FILEPICKER_TITLES,
     206           0 :                                             getter_AddRefs(titleBundle));
     207           0 :   if (NS_FAILED(rv))
     208           0 :     return NS_ERROR_FAILURE;
     209             : 
     210           0 :   rv = stringService->CreateBundle(FILEPICKER_FILTERS, getter_AddRefs(filterBundle));
     211           0 :   if (NS_FAILED(rv))
     212           0 :     return NS_ERROR_FAILURE;
     213             : 
     214           0 :   nsXPIDLString title;
     215           0 :   nsXPIDLString filter;
     216             : 
     217           0 :   if (aFilterMask & filterAll) {
     218           0 :     titleBundle->GetStringFromName(u"allTitle", getter_Copies(title));
     219           0 :     filterBundle->GetStringFromName(u"allFilter", getter_Copies(filter));
     220           0 :     AppendFilter(title,filter);
     221             :   }
     222           0 :   if (aFilterMask & filterHTML) {
     223           0 :     titleBundle->GetStringFromName(u"htmlTitle", getter_Copies(title));
     224           0 :     filterBundle->GetStringFromName(u"htmlFilter", getter_Copies(filter));
     225           0 :     AppendFilter(title,filter);
     226             :   }
     227           0 :   if (aFilterMask & filterText) {
     228           0 :     titleBundle->GetStringFromName(u"textTitle", getter_Copies(title));
     229           0 :     filterBundle->GetStringFromName(u"textFilter", getter_Copies(filter));
     230           0 :     AppendFilter(title,filter);
     231             :   }
     232           0 :   if (aFilterMask & filterImages) {
     233           0 :     titleBundle->GetStringFromName(u"imageTitle", getter_Copies(title));
     234           0 :     filterBundle->GetStringFromName(u"imageFilter", getter_Copies(filter));
     235           0 :     AppendFilter(title,filter);
     236             :   }
     237           0 :   if (aFilterMask & filterAudio) {
     238           0 :     titleBundle->GetStringFromName(u"audioTitle", getter_Copies(title));
     239           0 :     filterBundle->GetStringFromName(u"audioFilter", getter_Copies(filter));
     240           0 :     AppendFilter(title,filter);
     241             :   }
     242           0 :   if (aFilterMask & filterVideo) {
     243           0 :     titleBundle->GetStringFromName(u"videoTitle", getter_Copies(title));
     244           0 :     filterBundle->GetStringFromName(u"videoFilter", getter_Copies(filter));
     245           0 :     AppendFilter(title,filter);
     246             :   }
     247           0 :   if (aFilterMask & filterXML) {
     248           0 :     titleBundle->GetStringFromName(u"xmlTitle", getter_Copies(title));
     249           0 :     filterBundle->GetStringFromName(u"xmlFilter", getter_Copies(filter));
     250           0 :     AppendFilter(title,filter);
     251             :   }
     252           0 :   if (aFilterMask & filterXUL) {
     253           0 :     titleBundle->GetStringFromName(u"xulTitle", getter_Copies(title));
     254           0 :     filterBundle->GetStringFromName(u"xulFilter", getter_Copies(filter));
     255           0 :     AppendFilter(title, filter);
     256             :   }
     257           0 :   if (aFilterMask & filterApps) {
     258           0 :     titleBundle->GetStringFromName(u"appsTitle", getter_Copies(title));
     259             :     // Pass the magic string "..apps" to the platform filepicker, which it
     260             :     // should recognize and do the correct platform behavior for.
     261           0 :     AppendFilter(title, NS_LITERAL_STRING("..apps"));
     262             :   }
     263           0 :   return NS_OK;
     264             : }
     265             : 
     266             : // Set the filter index
     267           0 : NS_IMETHODIMP nsBaseFilePicker::GetFilterIndex(int32_t *aFilterIndex)
     268             : {
     269           0 :   *aFilterIndex = 0;
     270           0 :   return NS_OK;
     271             : }
     272             : 
     273           0 : NS_IMETHODIMP nsBaseFilePicker::SetFilterIndex(int32_t aFilterIndex)
     274             : {
     275           0 :   return NS_OK;
     276             : }
     277             : 
     278           0 : NS_IMETHODIMP nsBaseFilePicker::GetFiles(nsISimpleEnumerator **aFiles)
     279             : {
     280           0 :   NS_ENSURE_ARG_POINTER(aFiles);
     281           0 :   nsCOMArray <nsIFile> files;
     282             :   nsresult rv;
     283             : 
     284             :   // if we get into the base class, the platform
     285             :   // doesn't implement GetFiles() yet.
     286             :   // so we fake it.
     287           0 :   nsCOMPtr <nsIFile> file;
     288           0 :   rv = GetFile(getter_AddRefs(file));
     289           0 :   NS_ENSURE_SUCCESS(rv,rv);
     290             : 
     291           0 :   files.AppendObject(file);
     292             : 
     293           0 :   return NS_NewArrayEnumerator(aFiles, files);
     294             : }
     295             : 
     296             : // Set the display directory
     297           0 : NS_IMETHODIMP nsBaseFilePicker::SetDisplayDirectory(nsIFile *aDirectory)
     298             : {
     299             :   // if displaySpecialDirectory has been previously called, let's abort this
     300             :   // operation.
     301           0 :   if (!mDisplaySpecialDirectory.IsEmpty()) {
     302           0 :     return NS_OK;
     303             :   }
     304             : 
     305           0 :   if (!aDirectory) {
     306           0 :     mDisplayDirectory = nullptr;
     307           0 :     return NS_OK;
     308             :   }
     309           0 :   nsCOMPtr<nsIFile> directory;
     310           0 :   nsresult rv = aDirectory->Clone(getter_AddRefs(directory));
     311           0 :   if (NS_FAILED(rv))
     312           0 :     return rv;
     313           0 :   mDisplayDirectory = do_QueryInterface(directory, &rv);
     314           0 :   return rv;
     315             : }
     316             : 
     317             : // Get the display directory
     318           0 : NS_IMETHODIMP nsBaseFilePicker::GetDisplayDirectory(nsIFile **aDirectory)
     319             : {
     320           0 :   *aDirectory = nullptr;
     321             : 
     322             :   // if displaySpecialDirectory has been previously called, let's abort this
     323             :   // operation.
     324           0 :   if (!mDisplaySpecialDirectory.IsEmpty()) {
     325           0 :     return NS_OK;
     326             :   }
     327             : 
     328           0 :   if (!mDisplayDirectory)
     329           0 :     return NS_OK;
     330           0 :   nsCOMPtr<nsIFile> directory;
     331           0 :   nsresult rv = mDisplayDirectory->Clone(getter_AddRefs(directory));
     332           0 :   if (NS_FAILED(rv)) {
     333           0 :     return rv;
     334             :   }
     335           0 :   directory.forget(aDirectory);
     336           0 :   return NS_OK;
     337             : }
     338             : 
     339             : // Set the display special directory
     340           0 : NS_IMETHODIMP nsBaseFilePicker::SetDisplaySpecialDirectory(const nsAString& aDirectory)
     341             : {
     342             :   // if displayDirectory has been previously called, let's abort this operation.
     343           0 :   if (mDisplayDirectory && mDisplaySpecialDirectory.IsEmpty()) {
     344           0 :     return NS_OK;
     345             :   }
     346             : 
     347           0 :   mDisplaySpecialDirectory = aDirectory;
     348           0 :   if (mDisplaySpecialDirectory.IsEmpty()) {
     349           0 :     mDisplayDirectory = nullptr;
     350           0 :     return NS_OK;
     351             :   }
     352             : 
     353           0 :   return NS_GetSpecialDirectory(NS_ConvertUTF16toUTF8(mDisplaySpecialDirectory).get(),
     354           0 :                                 getter_AddRefs(mDisplayDirectory));
     355             : }
     356             : 
     357             : // Get the display special directory
     358           0 : NS_IMETHODIMP nsBaseFilePicker::GetDisplaySpecialDirectory(nsAString& aDirectory)
     359             : {
     360           0 :   aDirectory = mDisplaySpecialDirectory;
     361           0 :   return NS_OK;
     362             : }
     363             : 
     364             : NS_IMETHODIMP
     365           0 : nsBaseFilePicker::GetAddToRecentDocs(bool *aFlag)
     366             : {
     367           0 :   *aFlag = mAddToRecentDocs;
     368           0 :   return NS_OK;
     369             : }
     370             : 
     371             : NS_IMETHODIMP
     372           0 : nsBaseFilePicker::SetAddToRecentDocs(bool aFlag)
     373             : {
     374           0 :   mAddToRecentDocs = aFlag;
     375           0 :   return NS_OK;
     376             : }
     377             : 
     378             : NS_IMETHODIMP
     379           0 : nsBaseFilePicker::GetMode(int16_t* aMode)
     380             : {
     381           0 :   *aMode = mMode;
     382           0 :   return NS_OK;
     383             : }
     384             : 
     385             : NS_IMETHODIMP
     386           0 : nsBaseFilePicker::SetOkButtonLabel(const nsAString& aLabel)
     387             : {
     388           0 :   mOkButtonLabel = aLabel;
     389           0 :   return NS_OK;
     390             : }
     391             : 
     392             : NS_IMETHODIMP
     393           0 : nsBaseFilePicker::GetOkButtonLabel(nsAString& aLabel)
     394             : {
     395           0 :   aLabel = mOkButtonLabel;
     396           0 :   return NS_OK;
     397             : }
     398             : 
     399             : NS_IMETHODIMP
     400           0 : nsBaseFilePicker::GetDomFileOrDirectory(nsISupports** aValue)
     401             : {
     402           0 :   nsCOMPtr<nsIFile> localFile;
     403           0 :   nsresult rv = GetFile(getter_AddRefs(localFile));
     404           0 :   NS_ENSURE_SUCCESS(rv, rv);
     405             : 
     406           0 :   if (!localFile) {
     407           0 :     *aValue = nullptr;
     408           0 :     return NS_OK;
     409             :   }
     410             : 
     411           0 :   auto* innerParent = mParent ? mParent->GetCurrentInnerWindow() : nullptr;
     412             : 
     413           0 :   return LocalFileToDirectoryOrBlob(innerParent,
     414           0 :                                     mMode == nsIFilePicker::modeGetFolder,
     415             :                                     localFile,
     416           0 :                                     aValue);
     417             : }
     418             : 
     419             : NS_IMETHODIMP
     420           0 : nsBaseFilePicker::GetDomFileOrDirectoryEnumerator(nsISimpleEnumerator** aValue)
     421             : {
     422           0 :   nsCOMPtr<nsISimpleEnumerator> iter;
     423           0 :   nsresult rv = GetFiles(getter_AddRefs(iter));
     424           0 :   NS_ENSURE_SUCCESS(rv, rv);
     425             : 
     426             :   RefPtr<nsBaseFilePickerEnumerator> retIter =
     427           0 :     new nsBaseFilePickerEnumerator(mParent, iter, mMode);
     428             : 
     429           0 :   retIter.forget(aValue);
     430           0 :   return NS_OK;
     431             : }
     432             : 

Generated by: LCOV version 1.13