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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       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 "FilePickerParent.h"
       8             : #include "nsComponentManagerUtils.h"
       9             : #include "nsNetCID.h"
      10             : #include "nsIDocument.h"
      11             : #include "nsIDOMWindow.h"
      12             : #include "nsIFile.h"
      13             : #include "nsISimpleEnumerator.h"
      14             : #include "mozilla/Unused.h"
      15             : #include "mozilla/dom/FileBlobImpl.h"
      16             : #include "mozilla/dom/FileSystemSecurity.h"
      17             : #include "mozilla/dom/ContentParent.h"
      18             : #include "mozilla/dom/Element.h"
      19             : #include "mozilla/dom/TabParent.h"
      20             : #include "mozilla/dom/IPCBlobUtils.h"
      21             : 
      22             : using mozilla::Unused;
      23             : using namespace mozilla::dom;
      24             : 
      25           0 : NS_IMPL_ISUPPORTS(FilePickerParent::FilePickerShownCallback,
      26             :                   nsIFilePickerShownCallback);
      27             : 
      28             : NS_IMETHODIMP
      29           0 : FilePickerParent::FilePickerShownCallback::Done(int16_t aResult)
      30             : {
      31           0 :   if (mFilePickerParent) {
      32           0 :     mFilePickerParent->Done(aResult);
      33             :   }
      34           0 :   return NS_OK;
      35             : }
      36             : 
      37             : void
      38           0 : FilePickerParent::FilePickerShownCallback::Destroy()
      39             : {
      40           0 :   mFilePickerParent = nullptr;
      41           0 : }
      42             : 
      43           0 : FilePickerParent::~FilePickerParent()
      44             : {
      45           0 : }
      46             : 
      47             : // We run code in three places:
      48             : // 1. The main thread calls Dispatch() to start the runnable.
      49             : // 2. The stream transport thread stat()s the file in Run() and then dispatches
      50             : // the same runnable on the main thread.
      51             : // 3. The main thread sends the results over IPC.
      52           0 : FilePickerParent::IORunnable::IORunnable(FilePickerParent* aFPParent,
      53             :                                          nsTArray<nsCOMPtr<nsIFile>>& aFiles,
      54           0 :                                          bool aIsDirectory)
      55             :   : mozilla::Runnable("dom::FilePickerParent::IORunnable")
      56             :   , mFilePickerParent(aFPParent)
      57           0 :   , mIsDirectory(aIsDirectory)
      58             : {
      59           0 :   mFiles.SwapElements(aFiles);
      60           0 :   MOZ_ASSERT_IF(aIsDirectory, mFiles.Length() == 1);
      61           0 : }
      62             : 
      63             : bool
      64           0 : FilePickerParent::IORunnable::Dispatch()
      65             : {
      66           0 :   MOZ_ASSERT(NS_IsMainThread());
      67             : 
      68           0 :   mEventTarget = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
      69           0 :   if (!mEventTarget) {
      70           0 :     return false;
      71             :   }
      72             : 
      73           0 :   nsresult rv = mEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
      74           0 :   return NS_SUCCEEDED(rv);
      75             : }
      76             : 
      77             : NS_IMETHODIMP
      78           0 : FilePickerParent::IORunnable::Run()
      79             : {
      80             :   // If we're on the main thread, then that means we're done. Just send the
      81             :   // results.
      82           0 :   if (NS_IsMainThread()) {
      83           0 :     if (mFilePickerParent) {
      84           0 :       mFilePickerParent->SendFilesOrDirectories(mResults);
      85             :     }
      86           0 :     return NS_OK;
      87             :   }
      88             : 
      89             :   // We're not on the main thread, so do the IO.
      90             : 
      91           0 :   for (uint32_t i = 0; i < mFiles.Length(); ++i) {
      92           0 :     if (mIsDirectory) {
      93           0 :       nsAutoString path;
      94           0 :       nsresult rv = mFiles[i]->GetPath(path);
      95           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
      96           0 :         continue;
      97             :       }
      98             : 
      99           0 :       BlobImplOrString* data = mResults.AppendElement();
     100           0 :       data->mType = BlobImplOrString::eDirectoryPath;
     101           0 :       data->mDirectoryPath = path;
     102           0 :       continue;
     103             :     }
     104             : 
     105           0 :     RefPtr<BlobImpl> blobImpl = new FileBlobImpl(mFiles[i]);
     106             : 
     107           0 :     ErrorResult error;
     108           0 :     blobImpl->GetSize(error);
     109           0 :     if (NS_WARN_IF(error.Failed())) {
     110           0 :       error.SuppressException();
     111           0 :       continue;
     112             :     }
     113             : 
     114           0 :     blobImpl->GetLastModified(error);
     115           0 :     if (NS_WARN_IF(error.Failed())) {
     116           0 :       error.SuppressException();
     117           0 :       continue;
     118             :     }
     119             : 
     120           0 :     BlobImplOrString* data = mResults.AppendElement();
     121           0 :     data->mType = BlobImplOrString::eBlobImpl;
     122           0 :     data->mBlobImpl = blobImpl;
     123             :   }
     124             : 
     125             :   // Dispatch ourselves back on the main thread.
     126           0 :   if (NS_FAILED(NS_DispatchToMainThread(this))) {
     127             :     // It's hard to see how we can recover gracefully in this case. The child
     128             :     // process is waiting for an IPC, but that can only happen on the main
     129             :     // thread.
     130           0 :     MOZ_CRASH();
     131             :   }
     132             : 
     133           0 :   return NS_OK;
     134             : }
     135             : 
     136             : void
     137           0 : FilePickerParent::IORunnable::Destroy()
     138             : {
     139           0 :   mFilePickerParent = nullptr;
     140           0 : }
     141             : 
     142             : void
     143           0 : FilePickerParent::SendFilesOrDirectories(const nsTArray<BlobImplOrString>& aData)
     144             : {
     145           0 :   nsIContentParent* parent = TabParent::GetFrom(Manager())->Manager();
     146             : 
     147           0 :   if (mMode == nsIFilePicker::modeGetFolder) {
     148           0 :     MOZ_ASSERT(aData.Length() <= 1);
     149           0 :     if (aData.IsEmpty()) {
     150           0 :       Unused << Send__delete__(this, void_t(), mResult);
     151           0 :       return;
     152             :     }
     153             : 
     154           0 :     MOZ_ASSERT(aData[0].mType == BlobImplOrString::eDirectoryPath);
     155             : 
     156             :     // Let's inform the security singleton about the given access of this tab on
     157             :     // this directory path.
     158           0 :     RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
     159           0 :     fss->GrantAccessToContentProcess(parent->ChildID(),
     160           0 :                                      aData[0].mDirectoryPath);
     161             : 
     162           0 :     InputDirectory input;
     163           0 :     input.directoryPath() = aData[0].mDirectoryPath;
     164           0 :     Unused << Send__delete__(this, input, mResult);
     165           0 :     return;
     166             :   }
     167             : 
     168           0 :   InfallibleTArray<IPCBlob> ipcBlobs;
     169             : 
     170           0 :   for (unsigned i = 0; i < aData.Length(); i++) {
     171           0 :     IPCBlob ipcBlob;
     172             : 
     173           0 :     MOZ_ASSERT(aData[i].mType == BlobImplOrString::eBlobImpl);
     174           0 :     nsresult rv = IPCBlobUtils::Serialize(aData[i].mBlobImpl, parent, ipcBlob);
     175           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     176           0 :       break;
     177             :     }
     178             : 
     179           0 :     ipcBlobs.AppendElement(ipcBlob);
     180             :   }
     181             : 
     182           0 :   InputBlobs inblobs;
     183           0 :   inblobs.blobs().SwapElements(ipcBlobs);
     184             : 
     185           0 :   Unused << Send__delete__(this, inblobs, mResult);
     186             : }
     187             : 
     188             : void
     189           0 : FilePickerParent::Done(int16_t aResult)
     190             : {
     191           0 :   mResult = aResult;
     192             : 
     193           0 :   if (mResult != nsIFilePicker::returnOK) {
     194           0 :     Unused << Send__delete__(this, void_t(), mResult);
     195           0 :     return;
     196             :   }
     197             : 
     198           0 :   nsTArray<nsCOMPtr<nsIFile>> files;
     199           0 :   if (mMode == nsIFilePicker::modeOpenMultiple) {
     200           0 :     nsCOMPtr<nsISimpleEnumerator> iter;
     201           0 :     NS_ENSURE_SUCCESS_VOID(mFilePicker->GetFiles(getter_AddRefs(iter)));
     202             : 
     203           0 :     nsCOMPtr<nsISupports> supports;
     204           0 :     bool loop = true;
     205           0 :     while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) {
     206           0 :       iter->GetNext(getter_AddRefs(supports));
     207           0 :       if (supports) {
     208           0 :         nsCOMPtr<nsIFile> file = do_QueryInterface(supports);
     209           0 :         MOZ_ASSERT(file);
     210           0 :         files.AppendElement(file);
     211             :       }
     212             :     }
     213             :   } else {
     214           0 :     nsCOMPtr<nsIFile> file;
     215           0 :     mFilePicker->GetFile(getter_AddRefs(file));
     216           0 :     if (file) {
     217           0 :       files.AppendElement(file);
     218             :     }
     219             :   }
     220             : 
     221           0 :   if (files.IsEmpty()) {
     222           0 :     Unused << Send__delete__(this, void_t(), mResult);
     223           0 :     return;
     224             :   }
     225             : 
     226           0 :   MOZ_ASSERT(!mRunnable);
     227           0 :   mRunnable = new IORunnable(this, files, mMode == nsIFilePicker::modeGetFolder);
     228             : 
     229             :   // Dispatch to background thread to do I/O:
     230           0 :   if (!mRunnable->Dispatch()) {
     231           0 :     Unused << Send__delete__(this, void_t(), nsIFilePicker::returnCancel);
     232             :   }
     233             : }
     234             : 
     235             : bool
     236           0 : FilePickerParent::CreateFilePicker()
     237             : {
     238           0 :   mFilePicker = do_CreateInstance("@mozilla.org/filepicker;1");
     239           0 :   if (!mFilePicker) {
     240           0 :     return false;
     241             :   }
     242             : 
     243           0 :   Element* element = TabParent::GetFrom(Manager())->GetOwnerElement();
     244           0 :   if (!element) {
     245           0 :     return false;
     246             :   }
     247             : 
     248           0 :   nsCOMPtr<mozIDOMWindowProxy> window = element->OwnerDoc()->GetWindow();
     249           0 :   if (!window) {
     250           0 :     return false;
     251             :   }
     252             : 
     253           0 :   return NS_SUCCEEDED(mFilePicker->Init(window, mTitle, mMode));
     254             : }
     255             : 
     256             : mozilla::ipc::IPCResult
     257           0 : FilePickerParent::RecvOpen(const int16_t& aSelectedType,
     258             :                            const bool& aAddToRecentDocs,
     259             :                            const nsString& aDefaultFile,
     260             :                            const nsString& aDefaultExtension,
     261             :                            InfallibleTArray<nsString>&& aFilters,
     262             :                            InfallibleTArray<nsString>&& aFilterNames,
     263             :                            const nsString& aDisplayDirectory,
     264             :                            const nsString& aDisplaySpecialDirectory,
     265             :                            const nsString& aOkButtonLabel)
     266             : {
     267           0 :   if (!CreateFilePicker()) {
     268           0 :     Unused << Send__delete__(this, void_t(), nsIFilePicker::returnCancel);
     269           0 :     return IPC_OK();
     270             :   }
     271             : 
     272           0 :   mFilePicker->SetAddToRecentDocs(aAddToRecentDocs);
     273             : 
     274           0 :   for (uint32_t i = 0; i < aFilters.Length(); ++i) {
     275           0 :     mFilePicker->AppendFilter(aFilterNames[i], aFilters[i]);
     276             :   }
     277             : 
     278           0 :   mFilePicker->SetDefaultString(aDefaultFile);
     279           0 :   mFilePicker->SetDefaultExtension(aDefaultExtension);
     280           0 :   mFilePicker->SetFilterIndex(aSelectedType);
     281           0 :   mFilePicker->SetOkButtonLabel(aOkButtonLabel);
     282             : 
     283           0 :   if (!aDisplayDirectory.IsEmpty()) {
     284           0 :     nsCOMPtr<nsIFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
     285           0 :     if (localFile) {
     286           0 :       localFile->InitWithPath(aDisplayDirectory);
     287           0 :       mFilePicker->SetDisplayDirectory(localFile);
     288             :     }
     289           0 :   } else if (!aDisplaySpecialDirectory.IsEmpty()) {
     290           0 :     mFilePicker->SetDisplaySpecialDirectory(aDisplaySpecialDirectory);
     291             :   }
     292             : 
     293           0 :   mCallback = new FilePickerShownCallback(this);
     294             : 
     295           0 :   mFilePicker->Open(mCallback);
     296           0 :   return IPC_OK();
     297             : }
     298             : 
     299             : void
     300           0 : FilePickerParent::ActorDestroy(ActorDestroyReason aWhy)
     301             : {
     302           0 :   if (mCallback) {
     303           0 :     mCallback->Destroy();
     304           0 :     mCallback = nullptr;
     305             :   }
     306           0 :   if (mRunnable) {
     307           0 :     mRunnable->Destroy();
     308           0 :     mRunnable = nullptr;
     309             :   }
     310           0 : }

Generated by: LCOV version 1.13