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 367374 938f7fd2ce2bb07943af61bde705c71e56a2191a
parent 367373 eafea39ebf3977beefda0a7cdcef8c8266060ca0
child 367375 0318d13a32f95f4afe7f36d983ebd154b721bc07
push id1369
push userjlorenzo@mozilla.com
push dateMon, 27 Feb 2017 14:59:41 +0000
treeherdermozilla-release@d75a1dba431f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot
bugs1303518
milestone52.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 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)