Bug 1289255 - Implement DataTransferItem.webkitGetAsEntry, r=baku
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Fri, 29 Jul 2016 14:42:33 +0300
changeset 332349 5e254e995379e6cfda29c286bb40440e2ee705b8
parent 332348 f1f06933167fde6fe0f9a606819667e6e6285315
child 332350 aecec706235936d68cf24ab65b49b970da5a5b2e
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1289255
milestone50.0a1
Bug 1289255 - Implement DataTransferItem.webkitGetAsEntry, r=baku
dom/events/DataTransferItem.cpp
dom/events/DataTransferItem.h
dom/filesystem/compat/FileEntry.cpp
dom/webidl/DataTransferItem.webidl
--- a/dom/events/DataTransferItem.cpp
+++ b/dom/events/DataTransferItem.cpp
@@ -4,16 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DataTransferItem.h"
 #include "DataTransferItemList.h"
 
 #include "mozilla/ContentEvents.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/dom/DataTransferItemBinding.h"
+#include "mozilla/dom/Directory.h"
+#include "mozilla/dom/DirectoryEntry.h"
+#include "mozilla/dom/DOMFileSystem.h"
+#include "mozilla/dom/Event.h"
+#include "mozilla/dom/FileEntry.h"
 #include "nsIClipboard.h"
 #include "nsISupportsPrimitives.h"
 #include "nsNetUtil.h"
 #include "nsQueryObject.h"
 #include "nsContentUtils.h"
 #include "nsVariant.h"
 
 namespace {
@@ -263,16 +268,88 @@ DataTransferItem::GetAsFile(ErrorResult&
       MOZ_ASSERT(false, "One of the above code paths should be taken");
     }
   }
 
   RefPtr<File> file = mCachedFile;
   return file.forget();
 }
 
+already_AddRefed<Entry>
+DataTransferItem::GetAsEntry(ErrorResult& aRv)
+{
+  RefPtr<File> file = GetAsFile(aRv);
+  if (NS_WARN_IF(aRv.Failed()) || !file) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIGlobalObject> global;
+  RefPtr<DataTransfer> dataTransfer;
+  RefPtr<DataTransferItemList> list = GetParentObject();
+  if (!list) {
+    return nullptr;
+  }
+
+  dataTransfer = list->GetParentObject();
+  if (!dataTransfer) {
+    return nullptr;
+  }
+
+  // This is annoying, but DataTransfer may have various things as parent.
+  nsCOMPtr<EventTarget> target =
+    do_QueryInterface(dataTransfer->GetParentObject());
+  if (target) {
+    global = target->GetOwnerGlobal();
+  } else {
+    nsCOMPtr<nsIDOMEvent> event =
+      do_QueryInterface(dataTransfer->GetParentObject());
+    if (event) {
+      global = event->InternalDOMEvent()->GetParentObject();
+    }
+  }
+
+  if (!global) {
+    return nullptr;
+  }
+
+  RefPtr<DOMFileSystem> fs = DOMFileSystem::Create(global);
+  RefPtr<Entry> entry;
+  BlobImpl* impl = file->Impl();
+  MOZ_ASSERT(impl);
+
+  if (impl->IsDirectory()) {
+    nsAutoString fullpath;
+    impl->GetMozFullPathInternal(fullpath, aRv);
+    if (aRv.Failed()) {
+      aRv.SuppressException();
+      return nullptr;
+    }
+
+    nsCOMPtr<nsIFile> directoryFile;
+    nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(fullpath),
+                                        true, getter_AddRefs(directoryFile));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return nullptr;
+    }
+
+    RefPtr<Directory> directory = Directory::Create(global, directoryFile);
+    entry = new DirectoryEntry(global, directory, fs);
+  } else {
+    entry = new FileEntry(global, file, fs);
+  }
+
+  Sequence<RefPtr<Entry>> entries;
+  if (!entries.AppendElement(entry, fallible)) {
+    return nullptr;
+  }
+
+  fs->CreateRoot(entries);
+  return entry.forget();
+}
+
 already_AddRefed<File>
 DataTransferItem::CreateFileFromInputStream(nsIInputStream* aStream)
 {
   const char* key = nullptr;
   for (uint32_t i = 0; i < ArrayLength(kFileMimeNameMap); ++i) {
     if (mType.EqualsASCII(kFileMimeNameMap[i].mMimeName)) {
       key = kFileMimeNameMap[i].mFileName;
       break;
--- a/dom/events/DataTransferItem.h
+++ b/dom/events/DataTransferItem.h
@@ -9,16 +9,17 @@
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DOMString.h"
 #include "mozilla/dom/File.h"
 
 namespace mozilla {
 namespace dom {
 
+class Entry;
 class FunctionStringCallback;
 
 class DataTransferItem final : public nsISupports
                              , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DataTransferItem);
@@ -69,16 +70,18 @@ public:
   }
   void SetKind(eKind aKind)
   {
     mKind = aKind;
   }
 
   already_AddRefed<File> GetAsFile(ErrorResult& aRv);
 
+  already_AddRefed<Entry> GetAsEntry(ErrorResult& aRv);
+
   DataTransferItemList* GetParentObject() const
   {
     return mParent;
   }
 
   nsIPrincipal* Principal() const
   {
     return mPrincipal;
--- a/dom/filesystem/compat/FileEntry.cpp
+++ b/dom/filesystem/compat/FileEntry.cpp
@@ -70,16 +70,26 @@ FileEntry::GetName(nsAString& aName, Err
 {
   mFile->GetName(aName);
 }
 
 void
 FileEntry::GetFullPath(nsAString& aPath, ErrorResult& aRv) const
 {
   mFile->GetPath(aPath);
+  if (aPath.IsEmpty()) {
+    // We're under the root directory. webkitRelativePath
+    // (implemented as GetPath) is for cases when file is selected because its
+    // ancestor directory is selected. But that is not the case here, so need to
+    // manually prepend '/'.
+    nsAutoString name;
+    mFile->GetName(name);
+    aPath.AssignLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL);
+    aPath.Append(name);
+  }
 }
 
 void
 FileEntry::CreateWriter(VoidCallback& aSuccessCallback,
                         const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback) const
 {
   ErrorCallbackHelper::Call(GetParentObject(), aErrorCallback,
                             NS_ERROR_DOM_SECURITY_ERR);
--- a/dom/webidl/DataTransferItem.webidl
+++ b/dom/webidl/DataTransferItem.webidl
@@ -12,8 +12,13 @@ interface DataTransferItem {
   readonly attribute DOMString type;
   [Throws]
   void getAsString(FunctionStringCallback? _callback);
   [Throws]
   File? getAsFile();
 };
 
 callback FunctionStringCallback = void (DOMString data);
+
+partial interface DataTransferItem {
+  [Pref="dom.webkitBlink.filesystem.enabled", BinaryName="getAsEntry", Throws]
+  Entry? webkitGetAsEntry();
+};