static void
AppendBlobImplAsDirectory(nsTArray<OwningFileOrDirectory>& aArray,
                          BlobImpl* aBlobImpl,
                          nsIContent* aContent)
{
  MOZ_ASSERT(aBlobImpl);
  MOZ_ASSERT(aBlobImpl->IsDirectory());

  nsAutoString fullpath;
  ErrorResult err;
  aBlobImpl->GetMozFullPath(fullpath, err);
  if (err.Failed()) {
    err.SuppressException();
    return;
  }

  nsCOMPtr<nsIFile> file;
  NS_ConvertUTF16toUTF8 path(fullpath);
  nsresult rv = NS_NewNativeLocalFile(path, true, getter_AddRefs(file));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return;
  }

  nsPIDOMWindowInner* inner = aContent->OwnerDoc()->GetInnerWindow();
  if (!inner || !inner->IsCurrentInnerWindow()) {
    return;
  }

  RefPtr<Directory> directory =
    Directory::Create(inner, file);
  MOZ_ASSERT(directory);

  OwningFileOrDirectory* element = aArray.AppendElement();
  element->SetAsDirectory() = directory;
}
Example #2
0
void
GetDirectoryListingTaskChild::SetSuccessRequestResult(const FileSystemResponseValue& aValue,
                                                      ErrorResult& aRv)
{
  mFileSystem->AssertIsOnOwningThread();
  MOZ_ASSERT(aValue.type() ==
               FileSystemResponseValue::TFileSystemDirectoryListingResponse);

  FileSystemDirectoryListingResponse r = aValue;
  for (uint32_t i = 0; i < r.data().Length(); ++i) {
    const FileSystemDirectoryListingResponseData& data = r.data()[i];

    OwningFileOrDirectory* ofd = mTargetData.AppendElement(fallible);
    if (!ofd) {
      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
      return;
    }

    if (data.type() == FileSystemDirectoryListingResponseData::TFileSystemDirectoryListingResponseFile) {
      const FileSystemDirectoryListingResponseFile& d =
        data.get_FileSystemDirectoryListingResponseFile();

      RefPtr<BlobImpl> blobImpl =
        static_cast<BlobChild*>(d.blobChild())->GetBlobImpl();
      MOZ_ASSERT(blobImpl);

      RefPtr<File> file = File::Create(mFileSystem->GetParentObject(), blobImpl);
      MOZ_ASSERT(file);

      ofd->SetAsFile() = file;
    } else {
      MOZ_ASSERT(data.type() == FileSystemDirectoryListingResponseData::TFileSystemDirectoryListingResponseDirectory);
      const FileSystemDirectoryListingResponseDirectory& d =
        data.get_FileSystemDirectoryListingResponseDirectory();

      nsCOMPtr<nsIFile> path;
      aRv = NS_NewLocalFile(d.directoryRealPath(), true, getter_AddRefs(path));
      if (NS_WARN_IF(aRv.Failed())) {
        return;
      }

      RefPtr<Directory> directory =
        Directory::Create(mFileSystem->GetParentObject(), path, mFileSystem);
      MOZ_ASSERT(directory);

      ofd->SetAsDirectory() = directory;
    }
  }
}
bool
nsFilePickerProxy::Recv__delete__(const MaybeInputData& aData,
                                  const int16_t& aResult)
{
    if (aData.type() == MaybeInputData::TInputBlobs) {
        const InfallibleTArray<PBlobChild*>& blobs = aData.get_InputBlobs().blobsChild();
        for (uint32_t i = 0; i < blobs.Length(); ++i) {
            BlobChild* actor = static_cast<BlobChild*>(blobs[i]);
            RefPtr<BlobImpl> blobImpl = actor->GetBlobImpl();
            NS_ENSURE_TRUE(blobImpl, true);

            if (!blobImpl->IsFile()) {
                return true;
            }

            nsPIDOMWindowInner* inner =
                mParent ? mParent->GetCurrentInnerWindow() : nullptr;
            RefPtr<File> file = File::Create(inner, blobImpl);
            MOZ_ASSERT(file);

            OwningFileOrDirectory* element = mFilesOrDirectories.AppendElement();
            element->SetAsFile() = file;
        }
    } else if (aData.type() == MaybeInputData::TInputDirectory) {
        nsCOMPtr<nsIFile> file;
        NS_ConvertUTF16toUTF8 path(aData.get_InputDirectory().directoryPath());
        nsresult rv = NS_NewNativeLocalFile(path, true, getter_AddRefs(file));
        if (NS_WARN_IF(NS_FAILED(rv))) {
            return true;
        }

        RefPtr<Directory> directory =
            Directory::Create(mParent->GetCurrentInnerWindow(), file,
                              Directory::eDOMRootDirectory);
        MOZ_ASSERT(directory);

        OwningFileOrDirectory* element = mFilesOrDirectories.AppendElement();
        element->SetAsDirectory() = directory;
    }

    if (mCallback) {
        mCallback->Done(aResult);
        mCallback = nullptr;
    }

    return true;
}
/**
 * This is called when we receive a drop or a dragover.
 */
NS_IMETHODIMP
nsFileControlFrame::DnDListener::HandleEvent(nsIDOMEvent* aEvent)
{
  NS_ASSERTION(mFrame, "We should have been unregistered");

  bool defaultPrevented = false;
  aEvent->GetDefaultPrevented(&defaultPrevented);
  if (defaultPrevented) {
    return NS_OK;
  }

  nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
  if (!dragEvent) {
    return NS_OK;
  }

  nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
  dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
  if (!IsValidDropData(dataTransfer)) {
    return NS_OK;
  }


  nsCOMPtr<nsIContent> content = mFrame->GetContent();
  bool supportsMultiple = content && content->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
  if (!CanDropTheseFiles(dataTransfer, supportsMultiple)) {
    dataTransfer->SetDropEffect(NS_LITERAL_STRING("none"));
    aEvent->StopPropagation();
    return NS_OK;
  }

  nsAutoString eventType;
  aEvent->GetType(eventType);
  if (eventType.EqualsLiteral("dragover")) {
    // Prevent default if we can accept this drag data
    aEvent->PreventDefault();
    return NS_OK;
  }

  if (eventType.EqualsLiteral("drop")) {
    aEvent->StopPropagation();
    aEvent->PreventDefault();

    NS_ASSERTION(content, "The frame has no content???");

    HTMLInputElement* inputElement = HTMLInputElement::FromContent(content);
    NS_ASSERTION(inputElement, "No input element for this file upload control frame!");

    nsCOMPtr<nsIDOMFileList> fileList;
    dataTransfer->GetFiles(getter_AddRefs(fileList));

    RefPtr<BlobImpl> webkitDir;
    nsresult rv =
      GetBlobImplForWebkitDirectory(fileList, getter_AddRefs(webkitDir));
    NS_ENSURE_SUCCESS(rv, NS_OK);

    nsTArray<OwningFileOrDirectory> array;
    if (webkitDir) {
      AppendBlobImplAsDirectory(array, webkitDir, content);
      inputElement->MozSetDndFilesAndDirectories(array);
    } else {
      bool blinkFileSystemEnabled =
        Preferences::GetBool("dom.webkitBlink.filesystem.enabled", false);
      if (blinkFileSystemEnabled) {
        FileList* files = static_cast<FileList*>(fileList.get());
        if (files) {
          for (uint32_t i = 0; i < files->Length(); ++i) {
            File* file = files->Item(i);
            if (file) {
              if (file->Impl() && file->Impl()->IsDirectory()) {
                AppendBlobImplAsDirectory(array, file->Impl(), content);
              } else {
                OwningFileOrDirectory* element = array.AppendElement();
                element->SetAsFile() = file;
              }
            }
          }
        }
      }

      // This is rather ugly. Pass the directories as Files using SetFiles,
      // but then if blink filesystem API is enabled, it wants
      // FileOrDirectory array.
      inputElement->SetFiles(fileList, true);
      if (blinkFileSystemEnabled) {
        inputElement->UpdateEntries(array);
      }
      nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
                                           NS_LITERAL_STRING("input"), true,
                                           false);
      nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
                                           NS_LITERAL_STRING("change"), true,
                                           false);
    }
  }

  return NS_OK;
}