Bug 1289255 - Implement DataTransferItem.webkitGetAsEntry, r=baku
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Fri, 29 Jul 2016 14:42:33 +0300
changeset 347315 5e254e995379e6cfda29c286bb40440e2ee705b8
parent 347314 f1f06933167fde6fe0f9a606819667e6e6285315
child 347316 aecec706235936d68cf24ab65b49b970da5a5b2e
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1289255
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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();
+};