Backed out changeset 17e20404362d (bug 1258489)
authorWes Kocher <wkocher@mozilla.com>
Mon, 23 May 2016 12:46:05 -0700
changeset 323031 7aba31d799f29fe0747a8409fe62b6d113b0deb2
parent 323030 602500597e5f03371d43cf9ac9c3abac77342476
child 323032 e94aa4bc6f1a837abe1439356b31d4b39639ab4f
push id9671
push userraliiev@mozilla.com
push dateMon, 06 Jun 2016 20:27:52 +0000
treeherdermozilla-aurora@cea65ca3d0bd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1258489
milestone49.0a1
backs out17e20404362d916a9034c6f67895748878e599dd
Backed out changeset 17e20404362d (bug 1258489)
dom/base/nsGkAtomList.h
dom/filesystem/Directory.cpp
dom/filesystem/Directory.h
dom/filesystem/tests/mochitest.ini
dom/filesystem/tests/test_webkitdirectory.html
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/webidl/Directory.webidl
dom/webidl/HTMLInputElement.webidl
testing/specialpowers/content/MockFilePicker.jsm
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -1299,17 +1299,16 @@ GK_ATOM(viewport_maximum_scale, "viewpor
 GK_ATOM(viewport_minimum_scale, "viewport-minimum-scale")
 GK_ATOM(viewport_user_scalable, "viewport-user-scalable")
 GK_ATOM(viewport_width, "viewport-width")
 GK_ATOM(visibility, "visibility")
 GK_ATOM(visuallyselected, "visuallyselected")
 GK_ATOM(vlink, "vlink")
 GK_ATOM(vspace, "vspace")
 GK_ATOM(wbr, "wbr")
-GK_ATOM(webkitdirectory, "webkitdirectory")
 GK_ATOM(when, "when")
 GK_ATOM(where, "where")
 GK_ATOM(widget, "widget")
 GK_ATOM(width, "width")
 GK_ATOM(window, "window")
 GK_ATOM(headerWindowTarget, "window-target")
 GK_ATOM(windowtype, "windowtype")
 GK_ATOM(withParam, "with-param")
--- a/dom/filesystem/Directory.cpp
+++ b/dom/filesystem/Directory.cpp
@@ -161,31 +161,16 @@ Directory::GetRoot(FileSystemBase* aFile
     return nullptr;
   }
 
   FileSystemPermissionRequest::RequestForTask(task);
   return task->GetPromise();
 }
 
 /* static */ already_AddRefed<Directory>
-Directory::Constructor(const GlobalObject& aGlobal,
-                       const nsAString& aRealPath,
-                       ErrorResult& aRv)
-{
-  nsCOMPtr<nsIFile> path;
-  aRv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(aRealPath),
-                              true, getter_AddRefs(path));
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  return Create(aGlobal.GetAsSupports(), path);
-}
-
-/* static */ already_AddRefed<Directory>
 Directory::Create(nsISupports* aParent, nsIFile* aFile,
                   FileSystemBase* aFileSystem)
 {
   MOZ_ASSERT(aParent);
   MOZ_ASSERT(aFile);
 
 #ifdef DEBUG
   bool isDir;
--- a/dom/filesystem/Directory.h
+++ b/dom/filesystem/Directory.h
@@ -58,21 +58,16 @@ public:
 
   static bool
   WebkitBlinkDirectoryPickerEnabled(JSContext* aCx, JSObject* aObj);
 
   static already_AddRefed<Promise>
   GetRoot(FileSystemBase* aFileSystem, ErrorResult& aRv);
 
   static already_AddRefed<Directory>
-  Constructor(const GlobalObject& aGlobal,
-              const nsAString& aRealPath,
-              ErrorResult& aRv);
-
-  static already_AddRefed<Directory>
   Create(nsISupports* aParent, nsIFile* aDirectory,
          FileSystemBase* aFileSystem = 0);
 
   // ========= Begin WebIDL bindings. ===========
 
   nsISupports*
   GetParentObject() const;
 
--- a/dom/filesystem/tests/mochitest.ini
+++ b/dom/filesystem/tests/mochitest.ini
@@ -1,9 +1,8 @@
 [DEFAULT]
 support-files =
   filesystem_commons.js
   script_fileList.js
   worker_basic.js
 
 [test_basic.html]
-[test_webkitdirectory.html]
 [test_worker_basic.html]
deleted file mode 100644
--- a/dom/filesystem/tests/test_webkitdirectory.html
+++ /dev/null
@@ -1,122 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for webkitdirectory and webkitRelativePath</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-
-<body>
-<input id="inputFileWebkitDirectory" type="file" webkitdirectory></input>
-<input id="inputFileWebkitDirectoryAndDirectory" type="file" webkitdirectory directory></input>
-<input id="inputFileDirectory" type="file" directory></input>
-
-<script type="application/javascript;version=1.7">
-
-function populateInputFile(aInputFile) {
-  var url = SimpleTest.getTestFileURL("script_fileList.js");
-  var script = SpecialPowers.loadChromeScript(url);
-
-  var MockFilePicker = SpecialPowers.MockFilePicker;
-  MockFilePicker.init(window, "A Mock File Picker", SpecialPowers.Ci.nsIFilePicker.modeOpen);
-
-  function onOpened(message) {
-    MockFilePicker.useDirectory(message.dir);
-
-    var input = document.getElementById(aInputFile);
-    input.addEventListener('change', function() {
-      MockFilePicker.cleanup();
-      script.destroy();
-      next();
-    });
-
-    input.click();
-  }
-
-  script.addMessageListener("dir.opened", onOpened);
-  script.sendAsyncMessage("dir.open", { path: 'test' });
-}
-
-function checkFile(file, fileList) {
-  for (var i = 0; i < fileList.length; ++i) {
-    ok(fileList[i] instanceof File, "We want just files.");
-    if (fileList[i].name == file.name) {
-      is(fileList[i].webkitRelativePath, file.path, "Path matches");
-      return;
-    }
-  }
-
-  ok(false, "File not found.");
-}
-
-function test_fileList(aInputFile, aWhat) {
-  var input = document.getElementById(aInputFile);
-  var fileList = input.files;
-
-  if (aWhat == null) {
-    is(fileList, null, "We want a null fileList for " + aInputFile);
-    next();
-    return;
-  }
-
-  is(fileList.length, aWhat.length, "We want just " + aWhat.length + " elements for " + aInputFile);
-  for (var i = 0; i < aWhat.length; ++i) {
-    checkFile(aWhat[i], fileList);
-  }
-
-  next();
-}
-
-function test_webkitdirectory_attribute() {
-  var a = document.createElement("input");
-  a.setAttribute("type", "file");
-
-  ok("webkitdirectory" in a, "HTMLInputElement.webkitdirectory exists");
-
-  ok(!a.hasAttribute("webkitdirectory"), "No webkitdirectory DOM attribute by default");
-  ok(!a.webkitdirectory, "No webkitdirectory attribute by default");
-
-  a.webkitdirectory = true;
-
-  ok(a.hasAttribute("webkitdirectory"), "Webkitdirectory DOM attribute is set");
-  ok(a.webkitdirectory, "Webkitdirectory attribute is set");
-
-  next();
-}
-
-function test_setup() {
-  SpecialPowers.pushPrefEnv({"set": [["dom.input.dirpicker", true],
-                                     ["dom.webkitBlink.dirPicker.enabled", true]]}, next);
-}
-
-var tests = [
-  test_setup,
-
-  function() { populateInputFile('inputFileWebkitDirectory'); },
-  function() { populateInputFile('inputFileWebkitDirectoryAndDirectory'); },
-  function() { populateInputFile('inputFileDirectory'); },
-
-  function() { test_fileList('inputFileWebkitDirectory', [ { name: 'foo.txt', path: '/foo.txt' },
-                                                           { name: 'bar.txt', path: '/subdir/bar.txt' }]); },
-  function() { test_fileList('inputFileWebkitDirectoryAndDirectory', [ { name: 'foo.txt', path: '/foo.txt' },
-                                                                       { name: 'bar.txt', path: '/subdir/bar.txt' }]); },
-  function() { test_fileList('inputFileDirectory', null); },
-
-  test_webkitdirectory_attribute,
-];
-
-function next() {
-  if (!tests.length) {
-    SimpleTest.finish();
-    return;
-  }
-
-  var test = tests.shift();
-  test();
-}
-
-SimpleTest.waitForExplicitFinish();
-next();
-</script>
-</body>
-</html>
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -213,28 +213,16 @@ const Decimal HTMLInputElement::kStepAny
   0x23e2,                                          \
   0x4479,                                          \
   {0xb5, 0x13, 0x7b, 0x36, 0x93, 0x43, 0xe3, 0xa0} \
 }
 
 #define PROGRESS_STR "progress"
 static const uint32_t kProgressEventInterval = 50; // ms
 
-class GetFilesCallback
-{
-public:
-  NS_INLINE_DECL_REFCOUNTING(GetFilesCallback);
-
-  virtual void
-  Callback(nsresult aStatus, const Sequence<RefPtr<File>>& aFiles) = 0;
-
-protected:
-  virtual ~GetFilesCallback() {}
-};
-
 // Retrieving the list of files can be very time/IO consuming. We use this
 // helper class to do it just once.
 class GetFilesHelper final : public Runnable
 {
 public:
   static already_AddRefed<GetFilesHelper>
   Create(nsIGlobalObject* aGlobal,
          const nsTArray<OwningFileOrDirectory>& aFilesOrDirectory,
@@ -302,31 +290,16 @@ public:
       mPromises.AppendElement(aPromise);
       return;
     }
 
     MOZ_ASSERT(mPromises.IsEmpty());
     ResolveOrRejectPromise(aPromise);
   }
 
-  void
-  AddCallback(GetFilesCallback* aCallback)
-  {
-    MOZ_ASSERT(aCallback);
-
-    // Still working.
-    if (!mListingCompleted) {
-      mCallbacks.AppendElement(aCallback);
-      return;
-    }
-
-    MOZ_ASSERT(mCallbacks.IsEmpty());
-    RunCallback(aCallback);
-  }
-
   // CC methods
   void Unlink()
   {
     mGlobal = nullptr;
     mFiles.Clear();
     mPromises.Clear();
   }
 
@@ -375,24 +348,16 @@ private:
     // Let's process the pending promises.
     nsTArray<RefPtr<Promise>> promises;
     promises.SwapElements(mPromises);
 
     for (uint32_t i = 0; i < promises.Length(); ++i) {
       ResolveOrRejectPromise(promises[i]);
     }
 
-    // Let's process the pending callbacks.
-    nsTArray<RefPtr<GetFilesCallback>> callbacks;
-    callbacks.SwapElements(mCallbacks);
-
-    for (uint32_t i = 0; i < callbacks.Length(); ++i) {
-      RunCallback(callbacks[i]);
-    }
-
     return NS_OK;
   }
 
   void
   RunIO()
   {
     MOZ_ASSERT(!NS_IsMainThread());
     MOZ_ASSERT(!mDirectoryPath.IsEmpty());
@@ -537,26 +502,16 @@ private:
     if (NS_FAILED(mErrorResult)) {
       aPromise->MaybeReject(mErrorResult);
       return;
     }
 
     aPromise->MaybeResolve(mFiles);
   }
 
-  void
-  RunCallback(GetFilesCallback* aCallback)
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-    MOZ_ASSERT(mListingCompleted);
-    MOZ_ASSERT(aCallback);
-
-    aCallback->Callback(mErrorResult, mFiles);
-  }
-
   nsCOMPtr<nsIGlobalObject> mGlobal;
 
   bool mRecursiveFlag;
   bool mListingCompleted;
   nsString mDirectoryPath;
 
   // We populate this array in the I/O thread with the paths of the Files that
   // we want to send as result to the promise objects.
@@ -568,88 +523,16 @@ private:
 
   // This is the real File sequence that we expose via Promises.
   Sequence<RefPtr<File>> mFiles;
 
   // Error code to propagate.
   nsresult mErrorResult;
 
   nsTArray<RefPtr<Promise>> mPromises;
-  nsTArray<RefPtr<GetFilesCallback>> mCallbacks;
-};
-
-// An helper class for the dispatching of the 'change' event.
-class DispatchChangeEventCallback final : public GetFilesCallback
-{
-public:
-  explicit DispatchChangeEventCallback(HTMLInputElement* aInputElement)
-    : mInputElement(aInputElement)
-  {
-    MOZ_ASSERT(aInputElement);
-  }
-
-  virtual void
-  Callback(nsresult aStatus, const Sequence<RefPtr<File>>& aFiles) override
-  {
-    nsTArray<OwningFileOrDirectory> array;
-    for (uint32_t i = 0; i < aFiles.Length(); ++i) {
-      OwningFileOrDirectory* element = array.AppendElement();
-      element->SetAsFile() = aFiles[i];
-    }
-
-    mInputElement->SetFilesOrDirectories(array, true);
-    NS_WARN_IF(NS_FAILED(DispatchEvents()));
-  }
-
-  nsresult
-  DispatchEvents()
-  {
-    nsresult rv = NS_OK;
-    rv = nsContentUtils::DispatchTrustedEvent(mInputElement->OwnerDoc(),
-                                              static_cast<nsIDOMHTMLInputElement*>(mInputElement.get()),
-                                              NS_LITERAL_STRING("input"), true,
-                                              false);
-    NS_WARN_IF(NS_FAILED(rv));
-
-    rv = nsContentUtils::DispatchTrustedEvent(mInputElement->OwnerDoc(),
-                                              static_cast<nsIDOMHTMLInputElement*>(mInputElement.get()),
-                                              NS_LITERAL_STRING("change"), true,
-                                              false);
-
-    return rv;
-  }
-
-private:
-  RefPtr<HTMLInputElement> mInputElement;
-};
-
-// This callback is used for postponing the calling of SetFilesOrDirectories
-// when the exploration of the directory is completed.
-class AfterSetFilesOrDirectoriesCallback : public GetFilesCallback
-{
-public:
-  AfterSetFilesOrDirectoriesCallback(HTMLInputElement* aInputElement,
-                                     bool aSetValueChanged)
-    : mInputElement(aInputElement)
-    , mSetValueChanged(aSetValueChanged)
-  {
-    MOZ_ASSERT(aInputElement);
-  }
-
-  void
-  Callback(nsresult aStatus, const Sequence<RefPtr<File>>& aFiles) override
-  {
-    if (NS_SUCCEEDED(aStatus)) {
-      mInputElement->AfterSetFilesOrDirectoriesInternal(mSetValueChanged);
-    }
-  }
-
-private:
-  RefPtr<HTMLInputElement> mInputElement;
-  bool mSetValueChanged;
 };
 
 class HTMLInputElementState final : public nsISupports
 {
   public:
     NS_DECLARE_STATIC_IID_ACCESSOR(NS_INPUT_ELEMENT_STATE_IID)
     NS_DECL_ISUPPORTS
 
@@ -974,32 +857,29 @@ HTMLInputElement::nsFilePickerShownCallb
       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);
 
-  RefPtr<DispatchChangeEventCallback> dispatchChangeEventCallback =
-    new DispatchChangeEventCallback(mInput);
-
-  if (Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) &&
-      mInput->HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory)) {
-    ErrorResult error;
-    GetFilesHelper* helper = mInput->GetOrCreateGetFilesHelper(true, error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-
-    helper->AddCallback(dispatchChangeEventCallback);
-    return NS_OK;
-  }
-
-  return dispatchChangeEventCallback->DispatchEvents();
+  nsresult rv = NS_OK;
+  rv = nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
+                                            static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
+                                            NS_LITERAL_STRING("input"), true,
+                                            false);
+  NS_WARN_IF(NS_FAILED(rv));
+
+  rv = nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
+                                            static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
+                                            NS_LITERAL_STRING("change"), true,
+                                            false);
+
+  return rv;
 }
 
 NS_IMPL_ISUPPORTS(HTMLInputElement::nsFilePickerShownCallback,
                   nsIFilePickerShownCallback)
 
 class nsColorPickerShownCallback final
   : public nsIColorPickerShownCallback
 {
@@ -3033,29 +2913,16 @@ HTMLInputElement::SetFiles(nsIDOMFileLis
   }
 
   AfterSetFilesOrDirectories(aSetValueChanged);
 }
 
 void
 HTMLInputElement::AfterSetFilesOrDirectories(bool aSetValueChanged)
 {
-  if (Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) &&
-      HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory)) {
-    // This will call AfterSetFilesOrDirectoriesInternal eventually.
-    ExploreDirectoryRecursively(aSetValueChanged);
-    return;
-  }
-
-  AfterSetFilesOrDirectoriesInternal(aSetValueChanged);
-}
-
-void
-HTMLInputElement::AfterSetFilesOrDirectoriesInternal(bool aSetValueChanged)
-{
   // No need to flush here, if there's no frame at this point we
   // don't need to force creation of one just to tell it about this
   // new value.  We just want the display to update as needed.
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
   if (formControlFrame) {
     nsAutoString readableValue;
     GetDisplayFileName(readableValue);
     formControlFrame->SetFormProperty(nsGkAtoms::value, readableValue);
@@ -3108,19 +2975,17 @@ HTMLInputElement::FireChangeEventIfNeede
 FileList*
 HTMLInputElement::GetFiles()
 {
   if (mType != NS_FORM_INPUT_FILE) {
     return nullptr;
   }
 
   if (Preferences::GetBool("dom.input.dirpicker", false) &&
-      HasAttr(kNameSpaceID_None, nsGkAtoms::directory) &&
-      (!Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) ||
-       !HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory))) {
+      HasAttr(kNameSpaceID_None, nsGkAtoms::directory)) {
     return nullptr;
   }
 
   if (!mFileList) {
     mFileList = new FileList(static_cast<nsIContent*>(this));
     UpdateFileList();
   }
 
@@ -4200,20 +4065,18 @@ HTMLInputElement::MaybeInitPickers(Event
     // If the user clicked on the "Choose folder..." button we open the
     // directory picker, else we open the file picker.
     FilePickerType type = FILE_PICKER_FILE;
     nsCOMPtr<nsIContent> target =
       do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
     if (target &&
         target->GetParent() == this &&
         target->IsRootOfNativeAnonymousSubtree() &&
-        (target->HasAttr(kNameSpaceID_None, nsGkAtoms::directory) ||
-         target->HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory))) {
-      MOZ_ASSERT(Preferences::GetBool("dom.input.dirpicker", false) ||
-                 Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false),
+        target->HasAttr(kNameSpaceID_None, nsGkAtoms::directory)) {
+      MOZ_ASSERT(Preferences::GetBool("dom.input.dirpicker", false),
                  "No API or UI should have been exposed to allow this code to "
                  "be reached");
       type = FILE_PICKER_DIRECTORY;
     }
     return InitFilePicker(type);
   }
   if (mType == NS_FORM_INPUT_COLOR) {
     return InitColorPicker();
@@ -5413,18 +5276,17 @@ nsChangeHint
 HTMLInputElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                          int32_t aModType) const
 {
   nsChangeHint retval =
     nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
   if (aAttribute == nsGkAtoms::type ||
       // The presence or absence of the 'directory' attribute determines what
       // buttons we show for type=file.
-      aAttribute == nsGkAtoms::directory ||
-      aAttribute == nsGkAtoms::webkitdirectory) {
+      aAttribute == nsGkAtoms::directory) {
     retval |= NS_STYLE_HINT_FRAMECHANGE;
   } else if (mType == NS_FORM_INPUT_IMAGE &&
              (aAttribute == nsGkAtoms::alt ||
               aAttribute == nsGkAtoms::value)) {
     // We might need to rebuild our alt text.  Just go ahead and
     // reconstruct our frame.  This should be quite rare..
     retval |= NS_STYLE_HINT_FRAMECHANGE;
   } else if (aAttribute == nsGkAtoms::value) {
@@ -5550,28 +5412,51 @@ HTMLInputElement::GetFilesAndDirectories
 already_AddRefed<Promise>
 HTMLInputElement::GetFiles(bool aRecursiveFlag, ErrorResult& aRv)
 {
   if (mType != NS_FORM_INPUT_FILE) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
 
-  GetFilesHelper* helper = GetOrCreateGetFilesHelper(aRecursiveFlag, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-   }
-  MOZ_ASSERT(helper);
-
   nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
   MOZ_ASSERT(global);
   if (!global) {
     return nullptr;
   }
 
+  RefPtr<GetFilesHelper> helper;
+  if (aRecursiveFlag) {
+    if (!mGetFilesRecursiveHelper) {
+      mGetFilesRecursiveHelper =
+       GetFilesHelper::Create(global,
+                              GetFilesOrDirectoriesInternal(),
+                              aRecursiveFlag, aRv);
+      if (NS_WARN_IF(aRv.Failed())) {
+        return nullptr;
+      }
+    }
+
+    helper = mGetFilesRecursiveHelper;
+  } else {
+    if (!mGetFilesNonRecursiveHelper) {
+      mGetFilesNonRecursiveHelper =
+       GetFilesHelper::Create(global,
+                              GetFilesOrDirectoriesInternal(),
+                              aRecursiveFlag, aRv);
+      if (NS_WARN_IF(aRv.Failed())) {
+        return nullptr;
+      }
+    }
+
+    helper = mGetFilesNonRecursiveHelper;
+  }
+
+  MOZ_ASSERT(helper);
+
   RefPtr<Promise> p = Promise::Create(global, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   helper->AddPromise(p);
   return p.forget();
 }
@@ -8082,66 +7967,12 @@ HTMLInputElement::ClearGetFilesHelpers()
   }
 
   if (mGetFilesNonRecursiveHelper) {
     mGetFilesNonRecursiveHelper->Unlink();
     mGetFilesNonRecursiveHelper = nullptr;
   }
 }
 
-GetFilesHelper*
-HTMLInputElement::GetOrCreateGetFilesHelper(bool aRecursiveFlag,
-                                            ErrorResult& aRv)
-{
-  nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
-  MOZ_ASSERT(global);
-  if (!global) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
-  }
-
-  if (aRecursiveFlag) {
-    if (!mGetFilesRecursiveHelper) {
-      mGetFilesRecursiveHelper =
-       GetFilesHelper::Create(global,
-                              GetFilesOrDirectoriesInternal(),
-                              aRecursiveFlag, aRv);
-      if (NS_WARN_IF(aRv.Failed())) {
-        return nullptr;
-      }
-    }
-
-    return mGetFilesRecursiveHelper;
-  }
-
-  if (!mGetFilesNonRecursiveHelper) {
-    mGetFilesNonRecursiveHelper =
-     GetFilesHelper::Create(global,
-                            GetFilesOrDirectoriesInternal(),
-                            aRecursiveFlag, aRv);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return nullptr;
-    }
-  }
-
-  return mGetFilesNonRecursiveHelper;
-}
-
-void
-HTMLInputElement::ExploreDirectoryRecursively(bool aSetValueChanged)
-{
-  ErrorResult rv;
-  GetFilesHelper* helper = GetOrCreateGetFilesHelper(true /* recursionFlag */,
-                                                     rv);
-  if (NS_WARN_IF(rv.Failed())) {
-    AfterSetFilesOrDirectoriesInternal(aSetValueChanged);
-    return;
-  }
-
-  RefPtr<AfterSetFilesOrDirectoriesCallback> callback =
-    new AfterSetFilesOrDirectoriesCallback(this, aSetValueChanged);
-  helper->AddCallback(callback);
-}
-
 } // namespace dom
 } // namespace mozilla
 
 #undef NS_ORIGINAL_CHECKED_VALUE
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -32,19 +32,17 @@ class nsIRadioVisitor;
 
 namespace mozilla {
 
 class EventChainPostVisitor;
 class EventChainPreVisitor;
 
 namespace dom {
 
-class AfterSetFilesOrDirectoriesRunnable;
 class Date;
-class DispatchChangeEventCallback;
 class File;
 class FileList;
 class GetFilesHelper;
 
 /**
  * A class we use to create a singleton object that is used to keep track of
  * the last directory from which the user has picked files (via
  * <input type=file>) on a per-domain basis. The implementation uses
@@ -104,19 +102,16 @@ public:
 class HTMLInputElement final : public nsGenericHTMLFormElementWithState,
                                public nsImageLoadingContent,
                                public nsIDOMHTMLInputElement,
                                public nsITextControlElement,
                                public nsIPhonetic,
                                public nsIDOMNSEditableElement,
                                public nsIConstraintValidation
 {
-  friend class AfterSetFilesOrDirectoriesCallback;
-  friend class DispatchChangeEventCallback;
-
 public:
   using nsIConstraintValidation::GetValidationMessage;
   using nsIConstraintValidation::CheckValidity;
   using nsIConstraintValidation::ReportValidity;
   using nsIConstraintValidation::WillValidate;
   using nsIConstraintValidation::Validity;
   using nsGenericHTMLFormElementWithState::GetForm;
 
@@ -700,26 +695,16 @@ public:
     return HasAttr(kNameSpaceID_None, nsGkAtoms::directory);
   }
 
   void SetDirectoryAttr(bool aValue, ErrorResult& aRv)
   {
     SetHTMLBoolAttr(nsGkAtoms::directory, aValue, aRv);
   }
 
-  bool WebkitDirectoryAttr() const
-  {
-    return HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory);
-  }
-
-  void SetWebkitDirectoryAttr(bool aValue, ErrorResult& aRv)
-  {
-    SetHTMLBoolAttr(nsGkAtoms::webkitdirectory, aValue, aRv);
-  }
-
   bool IsFilesAndDirectoriesSupported() const;
 
   already_AddRefed<Promise> GetFilesAndDirectories(ErrorResult& aRv);
 
   already_AddRefed<Promise> GetFiles(bool aRecursiveFlag, ErrorResult& aRv);
 
   void ChooseDirectory(ErrorResult& aRv);
 
@@ -948,26 +933,18 @@ protected:
 
   /**
    * Update mFileList with the currently selected file.
    */
   void UpdateFileList();
 
   /**
    * Called after calling one of the SetFilesOrDirectories() functions.
-   * This method can explore the directory recursively if needed.
    */
   void AfterSetFilesOrDirectories(bool aSetValueChanged);
-  void AfterSetFilesOrDirectoriesInternal(bool aSetValueChanged);
-
-  /**
-   * Recursively explore the directory and populate mFileOrDirectories correctly
-   * for webkitdirectory.
-   */
-  void ExploreDirectoryRecursively(bool aSetValuechanged);
 
   /**
    * Determine whether the editor needs to be initialized explicitly for
    * a particular event.
    */
   bool NeedToInitializeEditorForEvent(EventChainPreVisitor& aVisitor) const;
 
   /**
@@ -1274,19 +1251,16 @@ protected:
    * Use this function before trying to open a picker.
    * It checks if the page is allowed to open a new pop-up.
    * If it returns true, you should not create the picker.
    *
    * @return true if popup should be blocked, false otherwise
    */
   bool IsPopupBlocked() const;
 
-  GetFilesHelper* GetOrCreateGetFilesHelper(bool aRecursiveFlag,
-                                            ErrorResult& aRv);
-
   void ClearGetFilesHelpers();
 
   nsCOMPtr<nsIControllers> mControllers;
 
   /*
    * In mInputData, the mState field is used if IsSingleLineTextControl returns
    * true and mValue is used otherwise.  We have to be careful when handling it
    * on a type change.
--- a/dom/webidl/Directory.webidl
+++ b/dom/webidl/Directory.webidl
@@ -10,20 +10,17 @@
  * path should be a descendent path like "path/to/file.txt" and not contain a
  * segment of ".." or ".". So the paths aren't allowed to walk up the directory
  * tree. For example, paths like "../foo", "..", "/foo/bar" or "foo/../bar" are
  * not allowed.
  *
  * http://w3c.github.io/filesystem-api/#idl-def-Directory
  * https://microsoftedge.github.io/directory-upload/proposal.html#directory-interface
  */
-
-// This chromeConstructor is used by the MockFilePicker for testing only.
-[ChromeConstructor(DOMString path),
- Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface Directory {
   /*
    * The leaf name of the directory.
    */
   [Throws]
   readonly attribute DOMString name;
 
   /*
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -204,19 +204,16 @@ partial interface HTMLInputElement {
   [Throws, Pref="dom.input.dirpicker"]
   Promise<sequence<(File or Directory)>> getFilesAndDirectories();
 
   [Throws, Pref="dom.input.dirpicker"]
   Promise<sequence<File>> getFiles(optional boolean recursiveFlag = false);
 
   [Throws, Pref="dom.input.dirpicker"]
   void chooseDirectory();
-
-  [Pref="dom.webkitBlink.dirPicker.enabled", BinaryName="WebkitDirectoryAttr", SetterThrows]
-  attribute boolean webkitdirectory;
 };
 
 [NoInterfaceObject]
 interface MozPhonetic {
   [Pure, ChromeOnly]
   readonly attribute DOMString phonetic;
 };
 
--- a/testing/specialpowers/content/MockFilePicker.jsm
+++ b/testing/specialpowers/content/MockFilePicker.jsm
@@ -98,21 +98,16 @@ this.MockFilePicker = {
   },
 
   useBlobFile: function() {
     var blob = new this.window.Blob([]);
     var file = new this.window.File([blob], 'helloworld.txt', { type: 'plain/text' });
     this.returnFiles = [file];
   },
 
-  useDirectory: function(aPath) {
-    var directory = new this.window.Directory(aPath);
-    this.returnFiles = [directory];
-  },
-
   isNsIFile: function(aFile) {
     let ret = false;
     try {
       if (aFile.QueryInterface(Ci.nsIFile))
         ret = true;
     } catch(e) {}
 
     return ret;