Bug 1319370 - HTMLInputElement should select the directory for the FilePicker using the input type (file or directory), r=jwatt
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 23 Nov 2016 13:02:10 +0100
changeset 324078 7477d9a20031ca7147f9251977a618c5ee728672
parent 323934 4772a0f4bed2e9f0cce209eec7560ede79097398
child 324079 7f9e1e63b71081efcb4070bc5231cd130dca145a
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersjwatt
bugs1319370
milestone53.0a1
Bug 1319370 - HTMLInputElement should select the directory for the FilePicker using the input type (file or directory), r=jwatt
dom/filesystem/Directory.h
dom/html/HTMLInputElement.cpp
--- a/dom/filesystem/Directory.h
+++ b/dom/filesystem/Directory.h
@@ -139,16 +139,22 @@ public:
   SetContentFilters(const nsAString& aFilters);
 
   FileSystemBase*
   GetFileSystem(ErrorResult& aRv);
 
   bool
   ClonableToDifferentThreadOrProcess() const;
 
+  nsIFile*
+  GetInternalNsIFile() const
+  {
+    return mFile;
+  }
+
 private:
   Directory(nsISupports* aParent,
             nsIFile* aFile,
             FileSystemBase* aFileSystem = nullptr);
   ~Directory();
 
   /*
    * Convert relative DOM path to the absolute real path.
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -480,38 +480,47 @@ namespace {
 
 /**
  * This may return nullptr if the DOM File's implementation of
  * File::mozFullPathInternal does not successfully return a non-empty
  * string that is a valid path. This can happen on Firefox OS, for example,
  * where the file picker can create Blobs.
  */
 static already_AddRefed<nsIFile>
-DOMFileOrDirectoryToLocalFile(const OwningFileOrDirectory& aData)
-{
-  nsString path;
-
+LastUsedDirectory(const OwningFileOrDirectory& aData)
+{
   if (aData.IsFile()) {
-    ErrorResult rv;
-    aData.GetAsFile()->GetMozFullPathInternal(path, rv);
-    if (rv.Failed() || path.IsEmpty()) {
-      rv.SuppressException();
+    nsAutoString path;
+    ErrorResult error;
+    aData.GetAsFile()->GetMozFullPathInternal(path, error);
+    if (error.Failed() || path.IsEmpty()) {
+      error.SuppressException();
+      return nullptr;
+    }
+
+    nsCOMPtr<nsIFile> localFile;
+    nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
+                                        getter_AddRefs(localFile));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
       return nullptr;
     }
-  } else {
-    MOZ_ASSERT(aData.IsDirectory());
-    aData.GetAsDirectory()->GetFullRealPath(path);
-  }
-
-  nsCOMPtr<nsIFile> localFile;
-  nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
-                                      getter_AddRefs(localFile));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return nullptr;
-  }
+
+    nsCOMPtr<nsIFile> parentFile;
+    rv = localFile->GetParent(getter_AddRefs(parentFile));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return nullptr;
+    }
+
+    return parentFile.forget();
+  }
+
+  MOZ_ASSERT(aData.IsDirectory());
+
+  nsCOMPtr<nsIFile> localFile = aData.GetAsDirectory()->GetInternalNsIFile();
+  MOZ_ASSERT(localFile);
 
   return localFile.forget();
 }
 
 void
 GetDOMFileOrDirectoryName(const OwningFileOrDirectory& aData,
                           nsAString& aName)
 {
@@ -611,22 +620,19 @@ HTMLInputElement::nsFilePickerShownCallb
     }
   }
 
   if (newFilesOrDirectories.IsEmpty()) {
     return NS_OK;
   }
 
   // Store the last used directory using the content pref service:
-  nsCOMPtr<nsIFile> file =
-    DOMFileOrDirectoryToLocalFile(newFilesOrDirectories[0]);
-
-  if (file) {
-    nsCOMPtr<nsIFile> lastUsedDir;
-    file->GetParent(getter_AddRefs(lastUsedDir));
+  nsCOMPtr<nsIFile> lastUsedDir = LastUsedDirectory(newFilesOrDirectories[0]);
+
+  if (lastUsedDir) {
     HTMLInputElement::gUploadLastDir->StoreLastUsedDirectory(
       mInput->OwnerDoc(), lastUsedDir);
   }
 
   // The text control frame (if there is one) isn't going to send a change
   // event because it will think this is done by a script.
   // So, we can safely send one by ourself.
   mInput->SetFilesOrDirectories(newFilesOrDirectories, true);
@@ -989,36 +995,32 @@ HTMLInputElement::InitFilePicker(FilePic
   // cycles adding them for FILE_PICKER_DIRECTORY.
   if (HasAttr(kNameSpaceID_None, nsGkAtoms::accept) &&
       aType != FILE_PICKER_DIRECTORY) {
     SetFilePickerFiltersFromAccept(filePicker);
   } else {
     filePicker->AppendFilters(nsIFilePicker::filterAll);
   }
 
-  // Set default directry and filename
+  // Set default directory and filename
   nsAutoString defaultName;
 
   const nsTArray<OwningFileOrDirectory>& oldFiles =
     GetFilesOrDirectoriesInternal();
 
   nsCOMPtr<nsIFilePickerShownCallback> callback =
     new HTMLInputElement::nsFilePickerShownCallback(this, filePicker);
 
   if (!oldFiles.IsEmpty() &&
       aType != FILE_PICKER_DIRECTORY) {
-    nsString path;
-
-    nsCOMPtr<nsIFile> localFile = DOMFileOrDirectoryToLocalFile(oldFiles[0]);
-    if (localFile) {
-      nsCOMPtr<nsIFile> parentFile;
-      nsresult rv = localFile->GetParent(getter_AddRefs(parentFile));
-      if (NS_SUCCEEDED(rv)) {
-        filePicker->SetDisplayDirectory(parentFile);
-      }
+    nsAutoString path;
+
+    nsCOMPtr<nsIFile> parentFile = LastUsedDirectory(oldFiles[0]);
+    if (parentFile) {
+      filePicker->SetDisplayDirectory(parentFile);
     }
 
     // Unfortunately nsIFilePicker doesn't allow multiple files to be
     // default-selected, so only select something by default if exactly
     // one file was selected before.
     if (oldFiles.Length() == 1) {
       nsAutoString leafName;
       GetDOMFileOrDirectoryName(oldFiles[0], leafName);