Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/ipc/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 8 kB image not shown  

Quelle  FilePickerParent.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "FilePickerParent.h"
#include "nsComponentManagerUtils.h"
#include "nsNetCID.h"
#include "mozilla/dom/Document.h"
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/CanonicalBrowsingContext.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/FileSystemSecurity.h"
#include "mozilla/dom/IPCBlobUtils.h"

using mozilla::Unused;
using namespace mozilla::dom;

NS_IMPL_ISUPPORTS(FilePickerParent::FilePickerShownCallback,
                  nsIFilePickerShownCallback);

NS_IMETHODIMP
FilePickerParent::FilePickerShownCallback::Done(
    nsIFilePicker::ResultCode aResult) {
  if (mFilePickerParent) {
    mFilePickerParent->Done(aResult);
  }
  return NS_OK;
}

void FilePickerParent::FilePickerShownCallback::Destroy() {
  mFilePickerParent = nullptr;
}

FilePickerParent::~FilePickerParent() = default;

// We run code in three places:
// 1. The main thread calls Dispatch() to start the runnable.
// 2. The stream transport thread stat()s the file in Run() and then dispatches
// the same runnable on the main thread.
// 3. The main thread sends the results over IPC.
FilePickerParent::IORunnable::IORunnable(FilePickerParent* aFPParent,
                                         nsTArray<nsCOMPtr<nsIFile>>&& aFiles,
                                         bool aIsDirectory)
    : mozilla::Runnable("dom::FilePickerParent::IORunnable"),
      mFilePickerParent(aFPParent),
      mFiles(std::move(aFiles)),
      mIsDirectory(aIsDirectory) {
  MOZ_ASSERT_IF(aIsDirectory, mFiles.Length() == 1);
}

bool FilePickerParent::IORunnable::Dispatch() {
  MOZ_ASSERT(NS_IsMainThread());

  mEventTarget = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
  if (!mEventTarget) {
    return false;
  }

  nsresult rv = mEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
  return NS_SUCCEEDED(rv);
}

NS_IMETHODIMP
FilePickerParent::IORunnable::Run() {
  // If we're on the main thread, then that means we're done. Just send the
  // results.
  if (NS_IsMainThread()) {
    if (mFilePickerParent) {
      mFilePickerParent->SendFilesOrDirectories(mResults);
    }
    return NS_OK;
  }

  // We're not on the main thread, so do the IO.

  for (uint32_t i = 0; i < mFiles.Length(); ++i) {
    if (mIsDirectory) {
      nsAutoString path;
      nsresult rv = mFiles[i]->GetPath(path);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        continue;
      }

      BlobImplOrString* data = mResults.AppendElement();
      data->mType = BlobImplOrString::eDirectoryPath;
      data->mDirectoryPath = path;
      continue;
    }

    RefPtr<BlobImpl> blobImpl = new FileBlobImpl(mFiles[i]);

    ErrorResult error;
    blobImpl->GetSize(error);
    if (NS_WARN_IF(error.Failed())) {
      error.SuppressException();
      continue;
    }

    blobImpl->GetLastModified(error);
    if (NS_WARN_IF(error.Failed())) {
      error.SuppressException();
      continue;
    }

    BlobImplOrString* data = mResults.AppendElement();
    data->mType = BlobImplOrString::eBlobImpl;
    data->mBlobImpl = blobImpl;
  }

  // Dispatch ourselves back on the main thread.
  if (NS_FAILED(NS_DispatchToMainThread(this))) {
    // It's hard to see how we can recover gracefully in this case. The child
    // process is waiting for an IPC, but that can only happen on the main
    // thread.
    MOZ_CRASH();
  }

  return NS_OK;
}

void FilePickerParent::IORunnable::Destroy() { mFilePickerParent = nullptr; }

void FilePickerParent::SendFilesOrDirectories(
    const nsTArray<BlobImplOrString>& aData) {
  ContentParent* parent = BrowserParent::GetFrom(Manager())->Manager();

  if (mMode == nsIFilePicker::modeGetFolder) {
    MOZ_ASSERT(aData.Length() <= 1);
    if (aData.IsEmpty()) {
      Unused << Send__delete__(this, void_t(), mResult);
      return;
    }

    MOZ_ASSERT(aData[0].mType == BlobImplOrString::eDirectoryPath);

    // Let's inform the security singleton about the given access of this tab on
    // this directory path.
    RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
    fss->GrantAccessToContentProcess(parent->ChildID(),
                                     aData[0].mDirectoryPath);

    InputDirectory input;
    input.directoryPath() = aData[0].mDirectoryPath;
    Unused << Send__delete__(this, input, mResult);
    return;
  }

  nsTArray<IPCBlob> ipcBlobs;

  for (unsigned i = 0; i < aData.Length(); i++) {
    IPCBlob ipcBlob;

    MOZ_ASSERT(aData[i].mType == BlobImplOrString::eBlobImpl);
    nsresult rv = IPCBlobUtils::Serialize(aData[i].mBlobImpl, ipcBlob);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      break;
    }

    ipcBlobs.AppendElement(ipcBlob);
  }

  InputBlobs inblobs;
  inblobs.blobs() = std::move(ipcBlobs);

  Unused << Send__delete__(this, inblobs, mResult);
}

void FilePickerParent::Done(nsIFilePicker::ResultCode aResult) {
  mResult = aResult;

  if (mResult != nsIFilePicker::returnOK) {
    Unused << Send__delete__(this, void_t(), mResult);
    return;
  }

  nsTArray<nsCOMPtr<nsIFile>> files;
  if (mMode == nsIFilePicker::modeOpenMultiple) {
    nsCOMPtr<nsISimpleEnumerator> iter;
    NS_ENSURE_SUCCESS_VOID(mFilePicker->GetFiles(getter_AddRefs(iter)));

    nsCOMPtr<nsISupports> supports;
    bool loop = true;
    while (NS_SUCCEEDED(iter->HasMoreElements(&loop)) && loop) {
      iter->GetNext(getter_AddRefs(supports));
      if (supports) {
        nsCOMPtr<nsIFile> file = do_QueryInterface(supports);
        MOZ_ASSERT(file);
        files.AppendElement(file);
      }
    }
  } else {
    nsCOMPtr<nsIFile> file;
    mFilePicker->GetFile(getter_AddRefs(file));
    if (file) {
      files.AppendElement(file);
    }
  }

  if (files.IsEmpty()) {
    Unused << Send__delete__(this, void_t(), mResult);
    return;
  }

  MOZ_ASSERT(!mRunnable);
  mRunnable = new IORunnable(this, std::move(files),
                             mMode == nsIFilePicker::modeGetFolder);

  // Dispatch to background thread to do I/O:
  if (!mRunnable->Dispatch()) {
    Unused << Send__delete__(this, void_t(), nsIFilePicker::returnCancel);
  }
}

bool FilePickerParent::CreateFilePicker() {
  if (!mBrowsingContext) {
    return false;
  }

  mFilePicker = do_CreateInstance("@mozilla.org/filepicker;1");

  if (!mFilePicker) {
    return false;
  }

  return NS_SUCCEEDED(mFilePicker->Init(mBrowsingContext, mTitle, mMode));
}

mozilla::ipc::IPCResult FilePickerParent::RecvOpen(
    const int16_t& aSelectedType, const bool& aAddToRecentDocs,
    const nsString& aDefaultFile, const nsString& aDefaultExtension,
    nsTArray<nsString>&& aFilters, nsTArray<nsString>&& aFilterNames,
    nsTArray<nsString>&& aRawFilters, const nsString& aDisplayDirectory,
    const nsString& aDisplaySpecialDirectory, const nsString& aOkButtonLabel,
    const nsIFilePicker::CaptureTarget& aCapture) {
  if (!CreateFilePicker()) {
    Unused << Send__delete__(this, void_t(), nsIFilePicker::returnCancel);
    return IPC_OK();
  }

  mFilePicker->SetAddToRecentDocs(aAddToRecentDocs);

  for (uint32_t i = 0; i < aFilters.Length(); ++i) {
    mFilePicker->AppendFilter(aFilterNames[i], aFilters[i]);
  }

  for (uint32_t i = 0; i < aRawFilters.Length(); ++i) {
    mFilePicker->AppendRawFilter(aRawFilters[i]);
  }

  mFilePicker->SetDefaultString(aDefaultFile);
  mFilePicker->SetDefaultExtension(aDefaultExtension);
  mFilePicker->SetFilterIndex(aSelectedType);
  mFilePicker->SetOkButtonLabel(aOkButtonLabel);
  mFilePicker->SetCapture(aCapture);

  if (!aDisplayDirectory.IsEmpty()) {
    nsCOMPtr<nsIFile> localFile;
    if (NS_SUCCEEDED(
            NS_NewLocalFile(aDisplayDirectory, getter_AddRefs(localFile)))) {
      mFilePicker->SetDisplayDirectory(localFile);
    }
  } else if (!aDisplaySpecialDirectory.IsEmpty()) {
    mFilePicker->SetDisplaySpecialDirectory(aDisplaySpecialDirectory);
  }

  MOZ_ASSERT(!mCallback);
  mCallback = new FilePickerShownCallback(this);

  mFilePicker->Open(mCallback);
  return IPC_OK();
}

void FilePickerParent::ActorDestroy(ActorDestroyReason aWhy) {
  if (mCallback) {
    mCallback->Destroy();
    mCallback = nullptr;
  }
  if (mRunnable) {
    mRunnable->Destroy();
    mRunnable = nullptr;
  }
}

Messung V0.5
C=94 H=90 G=91

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.