Bug 1303518 - Remove the chrome only constructor for File, r=qdot
authorAndrea Marchesini <amarchesini@mozilla.com>
Fri, 11 Nov 2016 18:56:44 +0100
changeset 348965 938f7fd2ce2bb07943af61bde705c71e56a2191a
parent 348964 eafea39ebf3977beefda0a7cdcef8c8266060ca0
child 348966 0318d13a32f95f4afe7f36d983ebd154b721bc07
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs1303518
milestone52.0a1
Bug 1303518 - Remove the chrome only constructor for File, r=qdot
browser/components/migration/MSMigrationUtils.jsm
dom/base/File.cpp
dom/base/File.h
dom/base/test/bug403852_fileOpener.js
dom/base/test/bug578096LoadChromeScript.js
dom/base/test/chrome/test_bug914381.html
dom/base/test/chrome/test_fileconstructor.xul
dom/base/test/chrome/test_fileconstructor_tempfile.xul
dom/base/test/create_file_objects.js
dom/base/test/file_bug1198095.js
dom/base/test/fileapi_chromeScript.js
dom/base/test/script_bug1238440.js
dom/base/test/script_postmessages_fileList.js
dom/filesystem/compat/tests/script_entries.js
dom/filesystem/tests/script_fileList.js
dom/html/test/formSubmission_chrome.js
dom/html/test/simpleFileOpener.js
dom/indexedDB/test/unit/xpcshell-head-parent-process.js
dom/webidl/File.webidl
dom/workers/test/fileapi_chromeScript.js
dom/workers/test/script_bug1301094.js
js/xpconnect/tests/unit/component-file.js
js/xpconnect/tests/unit/test_file2.js
mobile/android/components/FilePicker.js
testing/marionette/interaction.js
testing/specialpowers/content/SpecialPowersObserver.jsm
testing/web-platform/meta/FileAPI/idlharness.html.ini
testing/web-platform/meta/FileAPI/idlharness.worker.js.ini
toolkit/components/aboutmemory/content/aboutMemory.js
toolkit/crashreporter/CrashSubmit.jsm
toolkit/modules/PropertyListUtils.jsm
--- a/browser/components/migration/MSMigrationUtils.jsm
+++ b/browser/components/migration/MSMigrationUtils.jsm
@@ -559,17 +559,17 @@ Cookies.prototype = {
       } catch (ex) {
         Components.utils.reportError("Unable to migrate cookie: " + ex);
         success = false;
       } finally {
         aCallback(success);
       }
     };
     fileReader.addEventListener("loadend", onLoadEnd, false);
-    fileReader.readAsText(new File(aFile));
+    fileReader.readAsText(File.createFromNsIFile(aFile));
   },
 
   /**
    * Parses a cookie file buffer and returns an array of the contained cookies.
    *
    * The cookie file format is a newline-separated-values with a "*" used as
    * delimeter between multiple records.
    * Each cookie has the following fields:
--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -559,46 +559,20 @@ File::Constructor(const GlobalObject& aG
     impl->SetLastModified(aBag.mLastModified.Value());
   }
 
   RefPtr<File> file = new File(aGlobal.GetAsSupports(), impl);
   return file.forget();
 }
 
 /* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
-                  Blob& aData,
-                  const ChromeFilePropertyBag& aBag,
-                  ErrorResult& aRv)
-{
-  if (!nsContentUtils::ThreadsafeIsCallerChrome()) {
-    aRv.ThrowTypeError<MSG_NOT_SEQUENCE>(NS_LITERAL_STRING("Argument 1 of File.constructor"));
-    return nullptr;
-  }
-
-  RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
-  impl->InitializeChromeFile(aData, aBag, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-  MOZ_ASSERT(impl->IsFile());
-
-  if (aBag.mLastModified.WasPassed()) {
-    impl->SetLastModified(aBag.mLastModified.Value());
-  }
-
-  RefPtr<File> domFile = new File(aGlobal.GetAsSupports(), impl);
-  return domFile.forget();
-}
-
-/* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
-                  nsIFile* aData,
-                  const ChromeFilePropertyBag& aBag,
-                  ErrorResult& aRv)
+File::CreateFromNsIFile(const GlobalObject& aGlobal,
+                        nsIFile* aData,
+                        const ChromeFilePropertyBag& aBag,
+                        ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!nsContentUtils::IsCallerChrome()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
@@ -614,20 +588,20 @@ File::Constructor(const GlobalObject& aG
     impl->SetLastModified(aBag.mLastModified.Value());
   }
 
   RefPtr<File> domFile = new File(aGlobal.GetAsSupports(), impl);
   return domFile.forget();
 }
 
 /* static */ already_AddRefed<File>
-File::Constructor(const GlobalObject& aGlobal,
-                  const nsAString& aData,
-                  const ChromeFilePropertyBag& aBag,
-                  ErrorResult& aRv)
+File::CreateFromFileName(const GlobalObject& aGlobal,
+                         const nsAString& aData,
+                         const ChromeFilePropertyBag& aBag,
+                         ErrorResult& aRv)
 {
   if (!nsContentUtils::ThreadsafeIsCallerChrome()) {
     aRv.ThrowTypeError<MSG_MISSING_ARGUMENTS>(NS_LITERAL_STRING("File"));
     return nullptr;
   }
 
   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
 
--- a/dom/base/File.h
+++ b/dom/base/File.h
@@ -206,36 +206,29 @@ public:
   // File constructor
   static already_AddRefed<File>
   Constructor(const GlobalObject& aGlobal,
               const Sequence<BlobPart>& aData,
               const nsAString& aName,
               const FilePropertyBag& aBag,
               ErrorResult& aRv);
 
-  // File constructor - ChromeOnly
-  static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              Blob& aData,
-              const ChromeFilePropertyBag& aBag,
-              ErrorResult& aRv);
-
-  // File constructor - ChromeOnly
+  // ChromeOnly
   static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              const nsAString& aData,
-              const ChromeFilePropertyBag& aBag,
-              ErrorResult& aRv);
+  CreateFromFileName(const GlobalObject& aGlobal,
+                     const nsAString& aData,
+                     const ChromeFilePropertyBag& aBag,
+                     ErrorResult& aRv);
 
-  // File constructor - ChromeOnly
+  // ChromeOnly
   static already_AddRefed<File>
-  Constructor(const GlobalObject& aGlobal,
-              nsIFile* aData,
-              const ChromeFilePropertyBag& aBag,
-              ErrorResult& aRv);
+  CreateFromNsIFile(const GlobalObject& aGlobal,
+                    nsIFile* aData,
+                    const ChromeFilePropertyBag& aBag,
+                    ErrorResult& aRv);
 
   void GetName(nsAString& aName) const;
 
   int64_t GetLastModified(ErrorResult& aRv);
 
   Date GetLastModifiedDate(ErrorResult& aRv);
 
   // GetPath and SetPath are currently used only for the webkitRelativePath
--- a/dom/base/test/bug403852_fileOpener.js
+++ b/dom/base/test/bug403852_fileOpener.js
@@ -4,14 +4,14 @@ Cu.importGlobalProperties(["File"]);
 var testFile = Cc["@mozilla.org/file/directory_service;1"]
                  .getService(Ci.nsIDirectoryService)
                  .QueryInterface(Ci.nsIProperties)
                  .get("ProfD", Ci.nsIFile);
 testFile.append("prefs.js");
 
 addMessageListener("file.open", function () {
   sendAsyncMessage("file.opened", {
-    file: new File(testFile),
+    file: File.createFromNsIFile(testFile),
     mtime: testFile.lastModifiedTime,
-    fileWithDate: new File(testFile, { lastModified: 123 }),
+    fileWithDate: File.createFromNsIFile(testFile, { lastModified: 123 }),
     fileDate: 123,
   });
 });
--- a/dom/base/test/bug578096LoadChromeScript.js
+++ b/dom/base/test/bug578096LoadChromeScript.js
@@ -2,15 +2,15 @@ var file;
 Components.utils.importGlobalProperties(["File"]);
 
 addMessageListener("file.create", function (message) {
   file = Components.classes["@mozilla.org/file/directory_service;1"]
              .getService(Components.interfaces.nsIProperties)
              .get("TmpD", Components.interfaces.nsIFile);
   file.append("foo.txt");
   file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
-  sendAsyncMessage("file.created", new File(file));
+  sendAsyncMessage("file.created", File.createFromNsIFile(file));
 });
 
 addMessageListener("file.remove", function (message) {
   file.remove(false);
   sendAsyncMessage("file.removed", {});
 });
--- a/dom/base/test/chrome/test_bug914381.html
+++ b/dom/base/test/chrome/test_bug914381.html
@@ -30,19 +30,19 @@ function createFileWithData(fileData) {
   outStream.write(fileData, fileData.length);
   outStream.close();
 
   return testFile;
 }
 
 /** Test for Bug 914381. File's created in JS using an nsIFile should allow mozGetFullPathInternal calls to succeed **/
 var file = createFileWithData("Test bug 914381");
-var f = new File(file);
+var f = File.createFromNsIFile(file);
 is(f.mozFullPathInternal, undefined, "mozFullPathInternal is undefined from js");
 is(f.mozFullPath, file.path, "mozFullPath returns path if created with nsIFile");
 
-f = new File(file.path);
+f = File.createFromFileName(file.path);
 is(f.mozFullPathInternal, undefined, "mozFullPathInternal is undefined from js");
 is(f.mozFullPath, "", "mozFullPath returns blank if created with a string");
 </script>
 </pre>
 </body>
 </html>
--- a/dom/base/test/chrome/test_fileconstructor.xul
+++ b/dom/base/test/chrome/test_fileconstructor.xul
@@ -37,43 +37,36 @@ var file = Components.classes["@mozilla.
 // man I wish this were simpler ...
 file.append("chrome");
 file.append("dom");
 file.append("base");
 file.append("test");
 file.append("chrome");
 file.append("fileconstructor_file.png");
 
-doTest(new File(file.path));
-doTest(new File(file));
+doTest(File.createFromFileName(file.path));
+doTest(File.createFromNsIFile(file));
 function doTest(domfile) {
   ok(domfile instanceof File, "File() should return a File");
   is(domfile.type, "image/png", "File should be a PNG");
   is(domfile.size, 95, "File has size 95 (and more importantly we can read it)");
 }
 
 try {
-  var boomfile = new File();
-  ok(false, "This should never be reached!");
-} catch (e) {
-  ok(true, "Botched file constructor attempts throw and do not crash.");
-}
-
-try {
-  var nonexistentfile = new File("i/sure/hope/this/does/not/exist/anywhere.txt");
+  var nonexistentfile = File.createFromFileName("i/sure/hope/this/does/not/exist/anywhere.txt");
   ok(false, "This should never be reached!");
 } catch (e) {
   ok(true, "Attempt to construct a non-existent file should fail.");
 }
 
 try {
   var dir = Components.classes["@mozilla.org/file/directory_service;1"]
                       .getService(Components.interfaces.nsIProperties)
                       .get("CurWorkD", Components.interfaces.nsIFile);
-  var dirfile = new File(dir);
+  var dirfile = File.createFromNsIFile(dir);
   ok(false, "This should never be reached!");
 } catch (e) {
   ok(true, "Attempt to construct a file from a directory should fail.");
 }
 ]]>
 </script>
 
 </window>
--- a/dom/base/test/chrome/test_fileconstructor_tempfile.xul
+++ b/dom/base/test/chrome/test_fileconstructor_tempfile.xul
@@ -67,17 +67,17 @@ try {
                     .createInstance(Ci.nsIFileOutputStream);
   outStream.init(tmp, 0x02 | 0x08 | 0x20, // write, create, truncate
                  0666, 0);
   outStream.write(fileData, fileData.length);
   outStream.close();
 
   // Create a scoped DOMFile so the gc will happily get rid of it.
   {
-    let dirfile = new File(tmp, { temporary: true });
+    let dirfile = File.createFromNsIFile(tmp, { temporary: true });
     ok(true, "Temporary File() created");
     let reader = new FileReader();
     reader.readAsArrayBuffer(dirfile);
     reader.onload = function(event) {
       let buffer = event.target.result;
       ok(buffer.byteLength > 0,
          "Blob size should be > 0 : " + buffer.byteLength);
       cleanup(tmp);
--- a/dom/base/test/create_file_objects.js
+++ b/dom/base/test/create_file_objects.js
@@ -1,10 +1,10 @@
 Components.utils.importGlobalProperties(['File']);
 
 addMessageListener("create-file-objects", function(message) {
   let files = []
   for (fileName of message.fileNames) {
-    files.push(new File(fileName));
+    files.push(File.createFromFileName(fileName));
   }
 
   sendAsyncMessage("created-file-objects", files);
 });
--- a/dom/base/test/file_bug1198095.js
+++ b/dom/base/test/file_bug1198095.js
@@ -8,17 +8,17 @@ function createFileWithData(message) {
 
   var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
   outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
                  0o666, 0);
 
   outStream.write(message, message.length);
   outStream.close();
 
-  var domFile = new File(testFile);
+  var domFile = File.createFromNsIFile(testFile);
   return domFile;
 }
 
 addMessageListener("file.open", function (message) {
   sendAsyncMessage("file.opened", createFileWithData(message));
 });
 
 addMessageListener("file.modify", function (message) {
--- a/dom/base/test/fileapi_chromeScript.js
+++ b/dom/base/test/fileapi_chromeScript.js
@@ -12,17 +12,17 @@ function createFileWithData(fileData) {
   var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
   outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
                  0o666, 0);
   if (willDelete) {
     fileData = "some irrelevant test data\n";
   }
   outStream.write(fileData, fileData.length);
   outStream.close();
-  var domFile = new File(testFile);
+  var domFile = File.createFromNsIFile(testFile);
   if (willDelete) {
     testFile.remove(/* recursive: */ false);
   }
   return domFile;
 }
 
 addMessageListener("files.open", function (message) {
   sendAsyncMessage("files.opened", message.map(createFileWithData));
--- a/dom/base/test/script_bug1238440.js
+++ b/dom/base/test/script_bug1238440.js
@@ -6,17 +6,17 @@ var tmpFile;
 function writeFile(text, answer) {
   var stream = Cc["@mozilla.org/network/file-output-stream;1"]
                  .createInstance(Ci.nsIFileOutputStream);
   stream.init(tmpFile, 0x02 | 0x08 | 0x10, 0o600, 0);
   stream.write(text, text.length);
   stream.close();
 
   sendAsyncMessage(answer, {
-    file: new File(tmpFile)
+    file: File.createFromNsIFile(tmpFile)
   });
 }
 
 addMessageListener("file.open", function (e) {
   tmpFile = Cc["@mozilla.org/file/directory_service;1"]
               .getService(Ci.nsIDirectoryService)
               .QueryInterface(Ci.nsIProperties)
               .get('TmpD', Ci.nsIFile)
--- a/dom/base/test/script_postmessages_fileList.js
+++ b/dom/base/test/script_postmessages_fileList.js
@@ -4,17 +4,17 @@ Cu.importGlobalProperties(["File"]);
 addMessageListener("file.open", function () {
   var testFile = Cc["@mozilla.org/file/directory_service;1"]
                    .getService(Ci.nsIDirectoryService)
                    .QueryInterface(Ci.nsIProperties)
                    .get("ProfD", Ci.nsIFile);
   testFile.append("prefs.js");
 
   sendAsyncMessage("file.opened", {
-    file: new File(testFile)
+    file: File.createFromNsIFile(testFile)
   });
 });
 
 addMessageListener("dir.open", function () {
   var testFile = Cc["@mozilla.org/file/directory_service;1"]
                    .getService(Ci.nsIDirectoryService)
                    .QueryInterface(Ci.nsIProperties)
                    .get("ProfD", Ci.nsIFile);
--- a/dom/filesystem/compat/tests/script_entries.js
+++ b/dom/filesystem/compat/tests/script_entries.js
@@ -31,17 +31,17 @@ addMessageListener("entries.open", funct
   file2.append('bar.txt');
   file2.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
 
   var dir2 = dir1.clone();
   dir2.append('subsubdir');
   dir2.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o700);
 
   sendAsyncMessage("entries.opened", {
-    data: [ new Directory(tmpDir.path), new File(tmpFile) ]
+    data: [ new Directory(tmpDir.path), File.createFromNsIFile(tmpFile) ]
   });
 });
 
 addMessageListener("entries.delete", function(e) {
   tmpFile.remove(true);
   tmpDir.remove(true);
   sendAsyncMessage("entries.deleted");
 });
--- a/dom/filesystem/tests/script_fileList.js
+++ b/dom/filesystem/tests/script_fileList.js
@@ -119,11 +119,11 @@ addMessageListener("dir.open", function 
 addMessageListener("file.open", function (e) {
   var testFile = Cc["@mozilla.org/file/directory_service;1"]
                    .getService(Ci.nsIDirectoryService)
                    .QueryInterface(Ci.nsIProperties)
                    .get("ProfD", Ci.nsIFile);
   testFile.append("prefs.js");
 
   sendAsyncMessage("file.opened", {
-    file: new File(testFile)
+    file: File.createFromNsIFile(testFile)
   });
 });
--- a/dom/html/test/formSubmission_chrome.js
+++ b/dom/html/test/formSubmission_chrome.js
@@ -1,6 +1,6 @@
 var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 Cu.importGlobalProperties(["File"]);
 
 addMessageListener("files.open", function (message) {
-  sendAsyncMessage("files.opened", message.map(path => new File(path)));
+  sendAsyncMessage("files.opened", message.map(path => File.createFromFileName(path)));
 });
--- a/dom/html/test/simpleFileOpener.js
+++ b/dom/html/test/simpleFileOpener.js
@@ -9,17 +9,17 @@ addMessageListener("file.open", function
       file = Cc["@mozilla.org/file/directory_service;1"]
                .getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
       file.append(stem);
       file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
     }
     sendAsyncMessage("file.opened", {
       fullPath: file.path,
       leafName: file.leafName,
-      domFile: new File(file),
+      domFile: File.createFromNsIFile(file),
     });
   } catch(e) {
     sendAsyncMessage("fail", e.toString());
   }
 });
 
 addMessageListener("file.remove", function () {
   try {
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
+++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
@@ -632,17 +632,17 @@ var SpecialPowers = {
       }
         let outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
         outStream.init(testFile, 0x02 | 0x08 | 0x20, // PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE
                        filePerms, 0);
         if (request.data) {
           outStream.write(request.data, request.data.length);
           outStream.close();
         }
-        filePaths.push(new File(testFile.path, request.options));
+        filePaths.push(File.createFromFileName(testFile.path, request.options));
         createdFiles.push(testFile);
     });
 
     setTimeout(function () {
       callback(filePaths);
     }, 0);
   },
 
--- a/dom/webidl/File.webidl
+++ b/dom/webidl/File.webidl
@@ -6,22 +6,16 @@
  * The origin of this IDL file is
  * https://w3c.github.io/FileAPI/#file
  */
 
 interface nsIFile;
 
 [Constructor(sequence<BlobPart> fileBits,
              USVString fileName, optional FilePropertyBag options),
-
- // These constructors are just for chrome callers:
- Constructor(Blob fileBits, optional ChromeFilePropertyBag options),
- Constructor(nsIFile fileBits, optional ChromeFilePropertyBag options),
- Constructor(USVString fileBits, optional ChromeFilePropertyBag options),
-
  Exposed=(Window,Worker)]
 interface File : Blob {
   readonly attribute DOMString name;
 
   [GetterThrows]
   readonly attribute long long lastModified;
 };
 
@@ -40,9 +34,17 @@ partial interface File {
   [GetterThrows, Deprecated="FileLastModifiedDate"]
   readonly attribute Date lastModifiedDate;
 
   [BinaryName="path", Func="mozilla::dom::Directory::WebkitBlinkDirectoryPickerEnabled"]
   readonly attribute USVString webkitRelativePath;
 
   [GetterThrows, ChromeOnly]
   readonly attribute DOMString mozFullPath;
+
+  [ChromeOnly, Throws]
+  static File createFromNsIFile(nsIFile file,
+                                optional ChromeFilePropertyBag options);
+
+  [ChromeOnly, Throws]
+  static File createFromFileName(USVString fileName,
+                                 optional ChromeFilePropertyBag options);
 };
--- a/dom/workers/test/fileapi_chromeScript.js
+++ b/dom/workers/test/fileapi_chromeScript.js
@@ -12,17 +12,17 @@ function createFileWithData(fileData) {
   var outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
   outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
                  0o666, 0);
   if (willDelete) {
     fileData = "some irrelevant test data\n";
   }
   outStream.write(fileData, fileData.length);
   outStream.close();
-  var domFile = new File(testFile);
+  var domFile = File.createFromNsIFile(testFile);
   if (willDelete) {
     testFile.remove(/* recursive: */ false);
   }
   return domFile;
 }
 
 addMessageListener("files.open", function (message) {
   sendAsyncMessage("files.opened", message.map(createFileWithData));
--- a/dom/workers/test/script_bug1301094.js
+++ b/dom/workers/test/script_bug1301094.js
@@ -5,11 +5,11 @@ addMessageListener("file.open", function
   var tmpFile = Cc["@mozilla.org/file/directory_service;1"]
                   .getService(Ci.nsIDirectoryService)
                   .QueryInterface(Ci.nsIProperties)
                   .get('TmpD', Ci.nsIFile)
   tmpFile.append('file.txt');
   tmpFile.createUnique(Components.interfaces.nsIFile.FILE_TYPE, 0o600);
 
   sendAsyncMessage("file.opened", {
-    data: new File(tmpFile)
+    data: File.createFromNsIFile(tmpFile)
   });
 });
--- a/js/xpconnect/tests/unit/component-file.js
+++ b/js/xpconnect/tests/unit/component-file.js
@@ -26,19 +26,19 @@ FileComponent.prototype =
 
     // find the current directory path
     var file = Components.classes["@mozilla.org/file/directory_service;1"]
                .getService(Ci.nsIProperties)
                .get("CurWorkD", Ci.nsIFile);
     file.append("xpcshell.ini");
 
     // should be able to construct a file
-    var f1 = new File(file.path);
+    var f1 = File.createFromFileName(file.path);
     // and with nsIFiles
-    var f2 = new File(file);
+    var f2 = File.createFromNsIFile(file);
 
     // do some tests
     do_check_true(f1 instanceof File, "Should be a DOM File");
     do_check_true(f2 instanceof File, "Should be a DOM File");
 
     do_check_true(f1.name == "xpcshell.ini", "Should be the right file");
     do_check_true(f2.name == "xpcshell.ini", "Should be the right file");
 
@@ -64,17 +64,17 @@ FileComponent.prototype =
     do_check_true(threw, "Passing a random object should fail");
 
     var threw = false
     try {
       // Directories fail
       var dir = Components.classes["@mozilla.org/file/directory_service;1"]
                           .getService(Ci.nsIProperties)
                           .get("CurWorkD", Ci.nsIFile);
-      var f7 = new File(dir)
+      var f7 = File.createFromNsIFile(dir)
     } catch (e) {
       threw = true;
     }
     do_check_true(threw, "Can't create a File object for a directory");
 
     return true;
   },
 
--- a/js/xpconnect/tests/unit/test_file2.js
+++ b/js/xpconnect/tests/unit/test_file2.js
@@ -11,19 +11,19 @@ function run_test() {
 
   // find the current directory path
   var file = Components.classes["@mozilla.org/file/directory_service;1"]
              .getService(Ci.nsIProperties)
              .get("CurWorkD", Ci.nsIFile);
   file.append("xpcshell.ini");
 
   // should be able to construct a file
-  var f1 = new File(file.path);
+  var f1 = File.createFromFileName(file.path);
   // and with nsIFiles
-  var f2 = new File(file);
+  var f2 = File.createFromNsIFile(file);
 
   // do some tests
   do_check_true(f1 instanceof File, "Should be a DOM File");
   do_check_true(f2 instanceof File, "Should be a DOM File");
 
   do_check_true(f1.name == "xpcshell.ini", "Should be the right file");
   do_check_true(f2.name == "xpcshell.ini", "Should be the right file");
 
@@ -49,14 +49,14 @@ function run_test() {
   do_check_true(threw, "Passing a random object should fail");
 
   var threw = false
   try {
     // Directories fail
     var dir = Components.classes["@mozilla.org/file/directory_service;1"]
                         .getService(Ci.nsIProperties)
                         .get("CurWorkD", Ci.nsIFile);
-    var f7 = File(dir)
+    var f7 = File.createFromNsIFile(dir)
   } catch (e) {
     threw = true;
   }
   do_check_true(threw, "Can't create a File object for a directory");
 }
--- a/mobile/android/components/FilePicker.js
+++ b/mobile/android/components/FilePicker.js
@@ -148,28 +148,28 @@ FilePicker.prototype = {
     }
 
     let win = this._domWin;
     if (win) {
       let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
       return utils.wrapDOMFile(f);
     }
 
-    return new File(f);
+    return File.createFromNsIFile(f);
   },
 
   get domFileOrDirectoryEnumerator() {
     let win = this._domWin;
     return this.getEnumerator([this.file], function(file) {
       if (win) {
         let utils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
         return utils.wrapDOMFile(file);
       }
 
-      return new File(file);
+      return File.createFromNsIFile(file);
     });
   },
 
   get addToRecentDocs() {
     return this._addToRecentDocs;
   },
 
   set addToRecentDocs(val) {
--- a/testing/marionette/interaction.js
+++ b/testing/marionette/interaction.js
@@ -229,17 +229,17 @@ interaction.selectOption = function(el) 
  * @param {HTMLInputElement} el
  *     An <input type=file> element.
  * @param {string} path
  *     Full path to file.
  */
 interaction.uploadFile = function(el, path) {
   let file;
   try {
-    file = new File(path);
+    file = File.createFromFileName(path);
   } catch (e) {
     throw new InvalidArgumentError("File not found: " + path);
   }
 
   let fs = Array.prototype.slice.call(el.files);
   fs.push(file);
 
   // <input type=file> opens OS widget dialogue
--- a/testing/specialpowers/content/SpecialPowersObserver.jsm
+++ b/testing/specialpowers/content/SpecialPowersObserver.jsm
@@ -265,17 +265,17 @@ SpecialPowersObserver.prototype.receiveM
           }
           let outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
           outStream.init(testFile, 0x02 | 0x08 | 0x20, // PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE
                          filePerms, 0);
           if (request.data) {
             outStream.write(request.data, request.data.length);
             outStream.close();
           }
-          filePaths.push(new File(testFile.path, request.options));
+          filePaths.push(File.createFromFileName(testFile.path, request.options));
           createdFiles.push(testFile);
         });
         aMessage.target
                 .QueryInterface(Ci.nsIFrameLoaderOwner)
                 .frameLoader
                 .messageManager
                 .sendAsyncMessage("SpecialPowers.FilesCreated", filePaths);
       } catch (e) {
--- a/testing/web-platform/meta/FileAPI/idlharness.html.ini
+++ b/testing/web-platform/meta/FileAPI/idlharness.html.ini
@@ -10,19 +10,16 @@
     expected: FAIL
 
   [Blob interface: new Blob(["TEST"\]) must inherit property "isClosed" with the proper type (2)]
     expected: FAIL
 
   [Blob interface: new Blob(["TEST"\]) must inherit property "close" with the proper type (4)]
     expected: FAIL
 
-  [File interface object length]
-    expected: FAIL
-
   [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "isClosed" with the proper type (2)]
     expected: FAIL
 
   [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "close" with the proper type (4)]
     expected: FAIL
 
   [FileReaderSync interface object length]
     expected: FAIL
--- a/testing/web-platform/meta/FileAPI/idlharness.worker.js.ini
+++ b/testing/web-platform/meta/FileAPI/idlharness.worker.js.ini
@@ -10,19 +10,16 @@
     expected: FAIL
 
   [Blob interface: new Blob(["TEST"\]) must inherit property "isClosed" with the proper type (2)]
     expected: FAIL
 
   [Blob interface: new Blob(["TEST"\]) must inherit property "close" with the proper type (4)]
     expected: FAIL
 
-  [File interface object length]
-    expected: FAIL
-
   [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "isClosed" with the proper type (2)]
     expected: FAIL
 
   [Blob interface: new File(["myFileBits"\], "myFileName") must inherit property "close" with the proper type (4)]
     expected: FAIL
 
   [FileList interface object length]
     expected: FAIL
--- a/toolkit/components/aboutmemory/content/aboutMemory.js
+++ b/toolkit/components/aboutmemory/content/aboutMemory.js
@@ -644,17 +644,17 @@ function loadMemoryReportsFromFile(aFile
     reader.onload = (aEvent) => {
       // Clear "Loading..." from above.
       updateTitleMainAndFooter(aTitleNote, "", SHOW_FOOTER);
       aFn(aEvent.target.result);
     };
 
     // If it doesn't have a .gz suffix, read it as a (legacy) ungzipped file.
     if (!aFilename.endsWith(".gz")) {
-      reader.readAsText(new File(aFilename));
+      reader.readAsText(File.createFromFileName(aFilename));
       return;
     }
 
     // Read compressed gzip file.
     let converter = new nsGzipConverter();
     converter.asyncConvertData("gzip", "uncompressed", {
       data: [],
       onStartRequest: function(aR, aC) {},
--- a/toolkit/crashreporter/CrashSubmit.jsm
+++ b/toolkit/crashreporter/CrashSubmit.jsm
@@ -282,26 +282,26 @@ Submitter.prototype = {
         formData.append(name, value);
       }
     }
     if (this.noThrottle) {
       // tell the server not to throttle this, since it was manually submitted
       formData.append("Throttleable", "0");
     }
     // add the minidumps
-    formData.append("upload_file_minidump", new File(this.dump.path));
+    formData.append("upload_file_minidump", File.createFromFileName(this.dump.path));
     if (this.memory) {
-      formData.append("memory_report", new File(this.memory.path));
+      formData.append("memory_report", File.createFromFileName(this.memory.path));
     }
     if (this.additionalDumps.length > 0) {
       let names = [];
       for (let i of this.additionalDumps) {
         names.push(i.name);
         formData.append("upload_file_minidump_"+i.name,
-                        new File(i.dump.path));
+                        File.createFromFileName(i.dump.path));
       }
     }
 
     let manager = Services.crashmanager;
     let submissionID = manager.generateSubmissionID();
 
     xhr.addEventListener("readystatechange", (evt) => {
       if (xhr.readyState == 4) {
--- a/toolkit/modules/PropertyListUtils.jsm
+++ b/toolkit/modules/PropertyListUtils.jsm
@@ -92,17 +92,17 @@ this.PropertyListUtils = Object.freeze({
     // call aCallback.
     Services.tm.mainThread.dispatch(function() {
       let file = aFile;
       try {
         if (file instanceof Ci.nsILocalFile) {
           if (!file.exists())
             throw new Error("The file pointed by aFile does not exist");
 
-          file = new File(file);
+          file = File.createFromNsIFile(file);
         }
 
         let fileReader = new FileReader();
         let onLoadEnd = function() {
           let root = null;
           try {
             fileReader.removeEventListener("loadend", onLoadEnd, false);
             if (fileReader.readyState != fileReader.DONE)