Backed out changesets c6ca1aa3887a, d741e117a033, 1fd26e822e73, and 720962c9f993 (bug 961665) for build bustage and xpcshell failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 13 Mar 2014 10:32:57 -0400
changeset 191682 f547db6d8bc871d0ded1a832d91c62b36cdda7f1
parent 191681 9ba5ff374b3f8ed80f1f37da2779ae112a01ed81
child 191683 80fda301471ebba05b8bc00742da9a4eb8a3d665
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs961665
milestone30.0a1
backs outc6ca1aa3887a9b20452025a25a0c5d9616b77cae
d741e117a0332b13e60a9cb38b7cda2ace659e85
1fd26e822e737317d63cfa135a5c86fd7386b63d
720962c9f993403a96e9869e00ec11c422c7f7fa
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
Backed out changesets c6ca1aa3887a, d741e117a033, 1fd26e822e73, and 720962c9f993 (bug 961665) for build bustage and xpcshell failures.
b2g/installer/package-manifest.in
browser/installer/package-manifest.in
dom/webidl/NativeOSFileInternals.webidl
dom/webidl/moz.build
mobile/android/installer/package-manifest.in
toolkit/components/build/nsToolkitCompsModule.cpp
toolkit/components/crashes/CrashManager.jsm
toolkit/components/osfile/NativeOSFileInternals.cpp
toolkit/components/osfile/NativeOSFileInternals.h
toolkit/components/osfile/modules/moz.build
toolkit/components/osfile/modules/osfile_async_front.jsm
toolkit/components/osfile/modules/osfile_async_worker.js
toolkit/components/osfile/modules/osfile_native.jsm
toolkit/components/osfile/modules/osfile_shared_front.jsm
toolkit/components/osfile/modules/osfile_unix_allthreads.jsm
toolkit/components/osfile/modules/osfile_win_allthreads.jsm
toolkit/components/osfile/moz.build
toolkit/components/osfile/nsINativeOSFileInternals.idl
toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
toolkit/components/osfile/tests/xpcshell/head.js
toolkit/components/osfile/tests/xpcshell/test_creationDate.js
toolkit/components/osfile/tests/xpcshell/test_exception.js
toolkit/components/osfile/tests/xpcshell/test_open.js
toolkit/components/osfile/tests/xpcshell/test_path_constants.js
toolkit/components/osfile/tests/xpcshell/test_read_write.js
toolkit/components/osfile/tests/xpcshell/xpcshell.ini
toolkit/crashreporter/test/unit/test_crash_AsyncShutdown.js
xpcom/io/nsLocalFileWin.cpp
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -292,17 +292,16 @@
 @BINPATH@/components/captivedetect.xpt
 #endif
 @BINPATH@/components/shellservice.xpt
 @BINPATH@/components/shistory.xpt
 @BINPATH@/components/spellchecker.xpt
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/telemetry.xpt
 @BINPATH@/components/toolkit_finalizationwitness.xpt
-@BINPATH@/components/toolkit_osfile.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
 #endif
 @BINPATH@/components/txtsvc.xpt
 @BINPATH@/components/txmgr.xpt
 #ifdef MOZ_USE_NATIVE_UCONV
 @BINPATH@/components/ucnative.xpt
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -305,17 +305,16 @@
 #ifdef MOZ_CAPTIVEDETECT
 @BINPATH@/components/captivedetect.xpt
 #endif
 @BINPATH@/browser/components/shellservice.xpt
 @BINPATH@/components/shistory.xpt
 @BINPATH@/components/spellchecker.xpt
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/toolkit_finalizationwitness.xpt
-@BINPATH@/components/toolkit_osfile.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
 #endif
 @BINPATH@/components/txtsvc.xpt
 @BINPATH@/components/txmgr.xpt
 @BINPATH@/components/uconv.xpt
 @BINPATH@/components/unicharutil.xpt
deleted file mode 100644
--- a/dom/webidl/NativeOSFileInternals.webidl
+++ /dev/null
@@ -1,21 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtaone at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Options for nsINativeOSFileInternals::Read
- */
-dictionary NativeOSFileReadOptions
-{
-  /**
-   * If specified, convert the raw bytes to a String
-   * with the specified encoding. Otherwise, return
-   * the raw bytes as a TypedArray.
-   */
-  DOMString? encoding;
-
-  /**
-   * If specified, limit the number of bytes to read.
-   */
-  unsigned long long? bytes;
-};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -239,17 +239,16 @@ WEBIDL_FILES = [
     'MozMobileConnection.webidl',
     'MozNamedAttrMap.webidl',
     'MozNetworkStats.webidl',
     'MozPowerManager.webidl',
     'MozTimeManager.webidl',
     'MozWakeLock.webidl',
     'MutationEvent.webidl',
     'MutationObserver.webidl',
-    'NativeOSFileInternals.webidl',
     'NetDashboard.webidl',
     'NetworkOptions.webidl',
     'Node.webidl',
     'NodeFilter.webidl',
     'NodeIterator.webidl',
     'NodeList.webidl',
     'Notification.webidl',
     'NotifyAudioAvailableEvent.webidl',
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -241,17 +241,16 @@
 @BINPATH@/components/captivedetect.xpt
 #endif
 @BINPATH@/components/shellservice.xpt
 @BINPATH@/components/shistory.xpt
 @BINPATH@/components/spellchecker.xpt
 @BINPATH@/components/storage.xpt
 @BINPATH@/components/telemetry.xpt
 @BINPATH@/components/toolkit_finalizationwitness.xpt
-@BINPATH@/components/toolkit_osfile.xpt
 @BINPATH@/components/toolkitprofile.xpt
 #ifdef MOZ_ENABLE_XREMOTE
 @BINPATH@/components/toolkitremote.xpt
 #endif
 @BINPATH@/components/txtsvc.xpt
 @BINPATH@/components/txmgr.xpt
 @BINPATH@/components/uconv.xpt
 @BINPATH@/components/unicharutil.xpt
--- a/toolkit/components/build/nsToolkitCompsModule.cpp
+++ b/toolkit/components/build/nsToolkitCompsModule.cpp
@@ -30,17 +30,16 @@
 #include "nsUrlClassifierDBService.h"
 #include "nsUrlClassifierStreamUpdater.h"
 #include "nsUrlClassifierUtils.h"
 #include "nsUrlClassifierPrefixSet.h"
 #endif
 
 #include "nsBrowserStatusFilter.h"
 #include "mozilla/FinalizationWitnessService.h"
-#include "mozilla/NativeOSFileInternals.h"
 
 using namespace mozilla;
 
 /////////////////////////////////////////////////////////////////////////////
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsAppStartup, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsUserInfo)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFindService)
@@ -85,17 +84,16 @@ nsUrlClassifierDBServiceConstructor(nsIS
 }
 #endif
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBrowserStatusFilter)
 #if defined(USE_MOZ_UPDATER)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsUpdateProcessor)
 #endif
 NS_GENERIC_FACTORY_CONSTRUCTOR(FinalizationWitnessService)
-NS_GENERIC_FACTORY_CONSTRUCTOR(NativeOSFileInternalsService)
 
 NS_DEFINE_NAMED_CID(NS_TOOLKIT_APPSTARTUP_CID);
 NS_DEFINE_NAMED_CID(NS_USERINFO_CID);
 NS_DEFINE_NAMED_CID(NS_ALERTSSERVICE_CID);
 #if defined(XP_WIN) && !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
 NS_DEFINE_NAMED_CID(NS_PARENTALCONTROLSSERVICE_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_DOWNLOADMANAGER_CID);
@@ -111,17 +109,16 @@ NS_DEFINE_NAMED_CID(NS_URLCLASSIFIERSTRE
 NS_DEFINE_NAMED_CID(NS_URLCLASSIFIERUTILS_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_BROWSERSTATUSFILTER_CID);
 NS_DEFINE_NAMED_CID(NS_CHARSETMENU_CID);
 #if defined(USE_MOZ_UPDATER)
 NS_DEFINE_NAMED_CID(NS_UPDATEPROCESSOR_CID);
 #endif
 NS_DEFINE_NAMED_CID(FINALIZATIONWITNESSSERVICE_CID);
-NS_DEFINE_NAMED_CID(NATIVE_OSFILE_INTERNALS_SERVICE_CID);
 
 static const Module::CIDEntry kToolkitCIDs[] = {
   { &kNS_TOOLKIT_APPSTARTUP_CID, false, nullptr, nsAppStartupConstructor },
   { &kNS_USERINFO_CID, false, nullptr, nsUserInfoConstructor },
   { &kNS_ALERTSSERVICE_CID, false, nullptr, nsAlertsServiceConstructor },
 #if defined(XP_WIN) && !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
   { &kNS_PARENTALCONTROLSSERVICE_CID, false, nullptr, nsParentalControlsServiceWinConstructor },
 #endif
@@ -138,17 +135,16 @@ static const Module::CIDEntry kToolkitCI
   { &kNS_URLCLASSIFIERUTILS_CID, false, nullptr, nsUrlClassifierUtilsConstructor },
 #endif
   { &kNS_BROWSERSTATUSFILTER_CID, false, nullptr, nsBrowserStatusFilterConstructor },
   { &kNS_CHARSETMENU_CID, false, nullptr, NS_NewCharsetMenu },
 #if defined(USE_MOZ_UPDATER)
   { &kNS_UPDATEPROCESSOR_CID, false, nullptr, nsUpdateProcessorConstructor },
 #endif
   { &kFINALIZATIONWITNESSSERVICE_CID, false, nullptr, FinalizationWitnessServiceConstructor },
-  { &kNATIVE_OSFILE_INTERNALS_SERVICE_CID, false, nullptr, NativeOSFileInternalsServiceConstructor },
   { nullptr }
 };
 
 static const Module::ContractIDEntry kToolkitContracts[] = {
   { NS_APPSTARTUP_CONTRACTID, &kNS_TOOLKIT_APPSTARTUP_CID },
   { NS_USERINFO_CONTRACTID, &kNS_USERINFO_CID },
   { NS_ALERTSERVICE_CONTRACTID, &kNS_ALERTSSERVICE_CID },
 #if defined(XP_WIN) && !defined(MOZ_DISABLE_PARENTAL_CONTROLS)
@@ -168,17 +164,16 @@ static const Module::ContractIDEntry kTo
   { NS_URLCLASSIFIERUTILS_CONTRACTID, &kNS_URLCLASSIFIERUTILS_CID },
 #endif
   { NS_BROWSERSTATUSFILTER_CONTRACTID, &kNS_BROWSERSTATUSFILTER_CID },
   { NS_RDF_DATASOURCE_CONTRACTID_PREFIX NS_CHARSETMENU_PID, &kNS_CHARSETMENU_CID },
 #if defined(USE_MOZ_UPDATER)
   { NS_UPDATEPROCESSOR_CONTRACTID, &kNS_UPDATEPROCESSOR_CID },
 #endif
   { FINALIZATIONWITNESSSERVICE_CONTRACTID, &kFINALIZATIONWITNESSSERVICE_CID },
-  { NATIVE_OSFILE_INTERNALS_SERVICE_CONTRACTID, &kNATIVE_OSFILE_INTERNALS_SERVICE_CID },
   { nullptr }
 };
 
 static const Module kToolkitModule = {
   Module::kVersion,
   kToolkitCIDs,
   kToolkitContracts
 };
--- a/toolkit/components/crashes/CrashManager.jsm
+++ b/toolkit/components/crashes/CrashManager.jsm
@@ -590,17 +590,17 @@ CrashStore.prototype = Object.freeze({
         v: 1,
         crashes: new Map(),
         corruptDate: null,
       };
       this._countsByDay = new Map();
 
       try {
         let decoder = new TextDecoder();
-        let data = yield OS.File.read(this._storePath, {compression: "lz4"});
+        let data = yield OS.File.read(this._storePath, null, {compression: "lz4"});
         data = JSON.parse(decoder.decode(data));
 
         if (data.corruptDate) {
           this._data.corruptDate = new Date(data.corruptDate);
         }
 
         // actualCounts is used to validate that the derived counts by
         // days stored in the payload matches up to actual data.
deleted file mode 100644
--- a/toolkit/components/osfile/NativeOSFileInternals.cpp
+++ /dev/null
@@ -1,921 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Native implementation of some OS.File operations.
- */
-
-#include "nsString.h"
-#include "nsNetCID.h"
-#include "nsThreadUtils.h"
-#include "nsXPCOMCID.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsServiceManagerUtils.h"
-#include "nsProxyRelease.h"
-
-#include "nsINativeOSFileInternals.h"
-#include "NativeOSFileInternals.h"
-#include "mozilla/dom/NativeOSFileInternalsBinding.h"
-
-#include "nsIUnicodeDecoder.h"
-#include "nsIEventTarget.h"
-
-#include "mozilla/dom/EncodingUtils.h"
-#include "mozilla/DebugOnly.h"
-#include "mozilla/Scoped.h"
-#include "mozilla/HoldDropJSObjects.h"
-#include "mozilla/TimeStamp.h"
-
-#include "prio.h"
-#include "prerror.h"
-#include "private/pprio.h"
-
-#include "jsapi.h"
-#include "jsfriendapi.h"
-#include "js/Utility.h"
-#include "xpcpublic.h"
-
-#include <algorithm>
-#if defined(XP_UNIX)
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/uio.h>
-#endif // defined (XP_UNIX)
-
-#if defined(XP_WIN)
-#include <Windows.h>
-#endif // defined (XP_WIN)
-
-namespace mozilla {
-
-MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRFileDesc, PRFileDesc, PR_Close)
-
-namespace {
-
-// Utilities for safely manipulating ArrayBuffer contents even in the
-// absence of a JSContext.
-
-/**
- * The C buffer underlying to an ArrayBuffer. Throughout the code, we manipulate
- * this instead of a void* buffer, as this lets us transfer data across threads
- * and into JavaScript without copy.
- */
-struct ArrayBufferContents {
-  /**
-   * The header of the ArrayBuffer. This is the pointer actually used by JSAPI.
-   */
-  void* header;
-  /**
-   * The data of the ArrayBuffer. This is the pointer manipulated to
-   * read/write the contents of the buffer.
-   */
-  uint8_t* data;
-  /**
-   * The number of bytes in the ArrayBuffer.
-   */
-  size_t nbytes;
-};
-
-/**
- * RAII for ArrayBufferContents.
- */
-struct ScopedArrayBufferContentsTraits {
-  typedef ArrayBufferContents type;
-  const static type empty() {
-    type result = {0, 0, 0};
-    return result;
-  }
-  const static void release(type ptr) {
-    js_free(ptr.header);
-    ptr.header = nullptr;
-    ptr.data = nullptr;
-    ptr.nbytes = 0;
-  }
-};
-
-struct ScopedArrayBufferContents: public Scoped<ScopedArrayBufferContentsTraits> {
-  ScopedArrayBufferContents(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM):
-    Scoped<ScopedArrayBufferContentsTraits>(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT)
-  { }
-  ScopedArrayBufferContents(const ArrayBufferContents& v
-                            MOZ_GUARD_OBJECT_NOTIFIER_PARAM):
-    Scoped<ScopedArrayBufferContentsTraits>(v MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
-  { }
-  ScopedArrayBufferContents& operator=(ArrayBufferContents ptr) {
-    Scoped<ScopedArrayBufferContentsTraits>::operator=(ptr);
-    return *this;
-  }
-
-  /**
-   * Request memory for this ArrayBufferContent. This memory may later
-   * be used to create an ArrayBuffer object (possibly on another
-   * thread) without copy.
-   *
-   * @return true In case of success, false otherwise.
-   */
-  bool Allocate(uint32_t length) {
-    dispose();
-    ArrayBufferContents& value = rwget();
-    if (JS_AllocateArrayBufferContents(/*no context available*/nullptr,
-                                       length,
-                                       &value.header,
-                                       &value.data)) {
-      value.nbytes = length;
-      return true;
-    }
-    return false;
-  }
-private:
-  explicit ScopedArrayBufferContents(ScopedArrayBufferContents& source) MOZ_DELETE;
-  ScopedArrayBufferContents& operator=(ScopedArrayBufferContents& source) MOZ_DELETE;
-};
-
-///////// Cross-platform issues
-
-// Platform specific constants. As OS.File always uses OS-level
-// errors, we need to map a few high-level errors to OS-level
-// constants.
-#if defined(XP_UNIX)
-#define OS_ERROR_NOMEM ENOMEM
-#define OS_ERROR_INVAL EINVAL
-#define OS_ERROR_TOO_LARGE EFBIG
-#define OS_ERROR_RACE EIO
-#elif defined(XP_WIN)
-#define OS_ERROR_NOMEM ERROR_NOT_ENOUGH_MEMORY
-#define OS_ERROR_INVAL ERROR_BAD_ARGUMENTS
-#define OS_ERROR_TOO_LARGE ERROR_FILE_TOO_LARGE
-#define OS_ERROR_RACE ERROR_SHARING_VIOLATION
-#else
-#error "We do not have platform-specific constants for this platform"
-#endif
-
-///////// Results of OS.File operations
-
-/**
- * Base class for results passed to the callbacks.
- *
- * This base class implements caching of JS values returned to the client.
- * We make use of this caching in derived classes e.g. to avoid accidents
- * when we transfer data allocated on another thread into JS. Note that
- * this caching can lead to cycles (e.g. if a client adds a back-reference
- * in the JS value), so we implement all Cycle Collector primitives in
- * AbstractResult.
- */
-class AbstractResult: public nsINativeOSFileResult {
-public:
-  NS_DECL_NSINATIVEOSFILERESULT
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AbstractResult)
-
-  /**
-   * Construct the result object. Must be called on the main thread
-   * as the AbstractResult is cycle-collected.
-   *
-   * @param aStartDate The instant at which the operation was
-   * requested.  Used to collect Telemetry statistics.
-   */
-  AbstractResult(TimeStamp aStartDate)
-    : mStartDate(aStartDate)
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-    mozilla::HoldJSObjects(this);
-  }
-  virtual ~AbstractResult() {
-    MOZ_ASSERT(NS_IsMainThread());
-    DropJSData();
-    mozilla::DropJSObjects(this);
-  }
-
-  /**
-   * Setup the AbstractResult once data is available.
-   *
-   * @param aDispatchDate The instant at which the IO thread received
-   * the operation request. Used to collect Telemetry statistics.
-   * @param aExecutionDuration The duration of the operation on the
-   * IO thread.
-   */
-  void Init(TimeStamp aDispatchDate,
-            TimeDuration aExecutionDuration) {
-    MOZ_ASSERT(!NS_IsMainThread());
-
-    mDispatchDuration = (aDispatchDate - mStartDate);
-    mExecutionDuration = aExecutionDuration;
-  }
-
-  /**
-   * Drop any data that could lead to a cycle.
-   */
-  void DropJSData() {
-    mCachedResult = JS::UndefinedValue();
-  }
-
-protected:
-  virtual nsresult GetCacheableResult(JSContext *cx, JS::MutableHandleValue aResult) = 0;
-
-private:
-  TimeStamp mStartDate;
-  TimeDuration mDispatchDuration;
-  TimeDuration mExecutionDuration;
-  JS::Heap<JS::Value> mCachedResult;
-};
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(AbstractResult)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(AbstractResult)
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(AbstractResult)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AbstractResult)
-  NS_INTERFACE_MAP_ENTRY(nsINativeOSFileResult)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(AbstractResult)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedResult)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AbstractResult)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AbstractResult)
-  tmp->DropJSData();
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMETHODIMP
-AbstractResult::GetDispatchDurationMS(double *aDispatchDuration)
-{
-  *aDispatchDuration = mDispatchDuration.ToMilliseconds();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-AbstractResult::GetExecutionDurationMS(double *aExecutionDuration)
-{
-  *aExecutionDuration = mExecutionDuration.ToMilliseconds();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-AbstractResult::GetResult(JSContext *cx, JS::MutableHandleValue aResult)
-{
-  if (mCachedResult.isUndefined()) {
-    nsresult rv = GetCacheableResult(cx, aResult);
-    if (NS_FAILED(rv)) {
-      return rv;
-    }
-    mCachedResult = aResult;
-    return NS_OK;
-  }
-  aResult.set(mCachedResult);
-  return NS_OK;
-}
-
-/**
- * Return a result as a string.
- *
- * In this implementation, attribute |result| is a string. Strings are
- * passed to JS without copy.
- */
-class StringResult MOZ_FINAL : public AbstractResult
-{
-public:
-  StringResult(TimeStamp aStartDate)
-    : AbstractResult(aStartDate)
-  {
-  }
-
-  /**
-   * Initialize the object once the contents of the result as available.
-   *
-   * @param aContents The string to pass to JavaScript. Ownership of the
-   * string and its contents is passed to StringResult. The string must
-   * be valid UTF-16.
-   */
-  void Init(TimeStamp aDispatchDate,
-            TimeDuration aExecutionDuration,
-            nsString& aContents) {
-    AbstractResult::Init(aDispatchDate, aExecutionDuration);
-    mContents = aContents;
-  }
-
-protected:
-  nsresult GetCacheableResult(JSContext* cx, JS::MutableHandleValue aResult) MOZ_OVERRIDE;
-
-private:
-  nsString mContents;
-};
-
-nsresult
-StringResult::GetCacheableResult(JSContext* cx, JS::MutableHandleValue aResult)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mContents.get());
-
-  // Convert mContents to a js string without copy. Note that this
-  // may have the side-effect of stealing the contents of the string
-  // from XPCOM and into JS.
-  if (!xpc::StringToJsval(cx, mContents, aResult)) {
-    return NS_ERROR_FAILURE;
-  }
-  return NS_OK;
-}
-
-
-/**
- * Return a result as a Uint8Array.
- *
- * In this implementation, attribute |result| is a Uint8Array. The array
- * is passed to JS without memory copy.
- */
-class TypedArrayResult MOZ_FINAL : public AbstractResult
-{
-public:
-  TypedArrayResult(TimeStamp aStartDate)
-    : AbstractResult(aStartDate)
-  {
-  }
-
-  /**
-   * @param aContents The contents to pass to JS. Calling this method.
-   * transmits ownership of the ArrayBufferContents to the TypedArrayResult.
-   * Do not reuse this value anywhere else.
-   */
-  void Init(TimeStamp aDispatchDate,
-            TimeDuration aExecutionDuration,
-            ArrayBufferContents aContents) {
-    AbstractResult::Init(aDispatchDate, aExecutionDuration);
-    mContents = aContents;
-  }
-
-protected:
-  nsresult GetCacheableResult(JSContext* cx, JS::MutableHandleValue aResult) MOZ_OVERRIDE;
-private:
-  ScopedArrayBufferContents mContents;
-};
-
-nsresult
-TypedArrayResult::GetCacheableResult(JSContext* cx, JS::MutableHandle<JS::Value> aResult)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  // We cannot simply construct a typed array using contents.header as
-  // this would allow us to have several otherwise unrelated
-  // ArrayBuffers with the same underlying C buffer. As this would be
-  // very unsafe, we need to cache the result once we have it.
-
-  const ArrayBufferContents& contents = mContents.get();
-  MOZ_ASSERT(contents.data);
-
-  JS::Rooted<JSObject*>
-    arrayBuffer(cx, JS_NewArrayBufferWithContents(cx, contents.header));
-  if (!arrayBuffer) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  JS::Rooted<JSObject*>
-    result(cx, JS_NewUint8ArrayWithBuffer(cx, arrayBuffer,
-                                          0, contents.nbytes));
-  if (!result) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  // The memory of contents has been allocated on a thread that
-  // doesn't have a JSRuntime, hence without a context. Now that we
-  // have a context, attach the memory to where it belongs.
-  JS_updateMallocCounter(cx, contents.nbytes);
-  mContents.forget();
-
-  aResult.setObject(*result);
-  return NS_OK;
-}
-
-//////// Callback events
-
-/**
- * An event used to notify asynchronously of an error.
- */
-class ErrorEvent MOZ_FINAL : public nsRunnable {
-public:
-  /**
-   * @param aOnSuccess The success callback.
-   * @param aOnError The error callback.
-   * @param aDiscardedResult The discarded result.
-   * @param aOperation The name of the operation, used for error reporting.
-   * @param aOSError The OS error of the operation, as returned by errno/
-   * GetLastError().
-   *
-   * Note that we pass both the success callback and the error
-   * callback, as well as the discarded result to ensure that they are
-   * all released on the main thread, rather than on the IO thread
-   * (which would hopefully segfault). Also, we pass the callbacks as
-   * alread_AddRefed to ensure that we do not manipulate main-thread
-   * only refcounters off the main thread.
-   */
-  ErrorEvent(already_AddRefed<nsINativeOSFileSuccessCallback> aOnSuccess,
-             already_AddRefed<nsINativeOSFileErrorCallback> aOnError,
-             already_AddRefed<AbstractResult> aDiscardedResult,
-             const nsACString& aOperation,
-             int32_t aOSError)
-    : mOnSuccess(aOnSuccess)
-    , mOnError(aOnError)
-    , mDiscardedResult(aDiscardedResult)
-    , mOSError(aOSError)
-    , mOperation(aOperation)
-    {
-      MOZ_ASSERT(!NS_IsMainThread());
-    }
-
-  NS_METHOD Run() {
-    MOZ_ASSERT(NS_IsMainThread());
-    (void)mOnError->Complete(mOperation, mOSError);
-
-    // Ensure that the callbacks are released on the main thread.
-    mOnSuccess = nullptr;
-    mOnError = nullptr;
-    mDiscardedResult = nullptr;
-
-    return NS_OK;
-  }
- private:
-  // The callbacks. Maintained as nsRefPtr as they are generally
-  // xpconnect values, which cannot be manipulated with nsCOMPtr off
-  // the main thread. We store both the success callback and the
-  // error callback to ensure that they are safely released on the
-  // main thread.
-  nsRefPtr<nsINativeOSFileSuccessCallback> mOnSuccess;
-  nsRefPtr<nsINativeOSFileErrorCallback> mOnError;
-  nsRefPtr<AbstractResult> mDiscardedResult;
-  int32_t mOSError;
-  nsCString mOperation;
-};
-
-/**
- * An event used to notify of a success.
- */
-class SuccessEvent MOZ_FINAL : public nsRunnable {
-public:
-  /**
-   * @param aOnSuccess The success callback.
-   * @param aOnError The error callback.
-   *
-   * Note that we pass both the success callback and the error
-   * callback to ensure that they are both released on the main
-   * thread, rather than on the IO thread (which would hopefully
-   * segfault). Also, we pass them as alread_AddRefed to ensure that
-   * we do not manipulate xpconnect refcounters off the main thread
-   * (which is illegal).
-   */
-  SuccessEvent(already_AddRefed<nsINativeOSFileSuccessCallback> aOnSuccess,
-               already_AddRefed<nsINativeOSFileErrorCallback> aOnError,
-               already_AddRefed<nsINativeOSFileResult> aResult)
-    : mOnSuccess(aOnSuccess)
-    , mOnError(aOnError)
-    , mResult(aResult)
-    {
-      MOZ_ASSERT(!NS_IsMainThread());
-    }
-
-  NS_METHOD Run() {
-    MOZ_ASSERT(NS_IsMainThread());
-    (void)mOnSuccess->Complete(mResult);
-
-    // Ensure that the callbacks are released on the main thread.
-    mOnSuccess = nullptr;
-    mOnError = nullptr;
-    mResult = nullptr;
-
-    return NS_OK;
-  }
- private:
-  // The callbacks. Maintained as nsRefPtr as they are generally
-  // xpconnect values, which cannot be manipulated with nsCOMPtr off
-  // the main thread. We store both the success callback and the
-  // error callback to ensure that they are safely released on the
-  // main thread.
-  nsRefPtr<nsINativeOSFileSuccessCallback> mOnSuccess;
-  nsRefPtr<nsINativeOSFileErrorCallback> mOnError;
-  nsRefPtr<nsINativeOSFileResult> mResult;
-};
-
-
-//////// Action events
-
-/**
- * Base class shared by actions.
- */
-class AbstractDoEvent: public nsRunnable {
-public:
-  AbstractDoEvent(already_AddRefed<nsINativeOSFileSuccessCallback> aOnSuccess,
-                  already_AddRefed<nsINativeOSFileErrorCallback> aOnError)
-    : mOnSuccess(aOnSuccess)
-    , mOnError(aOnError)
-#if defined(DEBUG)
-    , mResolved(false)
-#endif // defined(DEBUG)
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-  }
-
-  /**
-   * Fail, asynchronously.
-   */
-  void Fail(const nsACString& aOperation,
-            already_AddRefed<AbstractResult> aDiscardedResult,
-            int32_t aOSError = 0) {
-    Resolve();
-    nsRefPtr<ErrorEvent> event = new ErrorEvent(mOnSuccess.forget(),
-                                                mOnError.forget(),
-                                                aDiscardedResult,
-                                                aOperation,
-                                                aOSError);
-    nsresult rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
-    if (NS_FAILED(rv)) {
-      // Last ditch attempt to release on the main thread - some of
-      // the members of event are not thread-safe, so letting the
-      // pointer go out of scope would cause a crash.
-      nsCOMPtr<nsIThread> main = do_GetMainThread();
-      NS_ProxyRelease(main, event);
-    }
-  }
-
-  /**
-   * Succeed, asynchronously.
-   */
-  void Succeed(already_AddRefed<nsINativeOSFileResult> aResult) {
-    Resolve();
-    nsRefPtr<SuccessEvent> event = new SuccessEvent(mOnSuccess.forget(),
-                                                    mOnError.forget(),
-                                                    aResult);
-    nsresult rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
-    if (NS_FAILED(rv)) {
-      // Last ditch attempt to release on the main thread - some of
-      // the members of event are not thread-safe, so letting the
-      // pointer go out of scope would cause a crash.
-      nsCOMPtr<nsIThread> main = do_GetMainThread();
-      NS_ProxyRelease(main, event);
-    }
-
-  }
-
-private:
-
-  /**
-   * Mark the event as complete, for debugging purposes.
-   */
-  void Resolve() {
-#if defined(DEBUG)
-    MOZ_ASSERT(!mResolved);
-    mResolved = true;
-#endif // defined(DEBUG)
-  }
-
-private:
-  nsRefPtr<nsINativeOSFileSuccessCallback> mOnSuccess;
-  nsRefPtr<nsINativeOSFileErrorCallback> mOnError;
-#if defined(DEBUG)
-  // |true| once the action is complete
-  bool mResolved;
-#endif // defined(DEBUG)
-};
-
-/**
- * An abstract event implementing reading from a file.
- *
- * Concrete subclasses are responsible for handling the
- * data obtained from the file and possibly post-processing it.
- */
-class AbstractReadEvent: public AbstractDoEvent {
-public:
-  /**
-   * @param aPath The path of the file.
-   */
-  AbstractReadEvent(const nsAString& aPath,
-                    const uint64_t aBytes,
-                    already_AddRefed<nsINativeOSFileSuccessCallback> aOnSuccess,
-                    already_AddRefed<nsINativeOSFileErrorCallback>  aOnError)
-    : AbstractDoEvent(aOnSuccess, aOnError)
-    , mPath(aPath)
-    , mBytes(aBytes)
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-  }
-
-  NS_METHOD Run() MOZ_OVERRIDE {
-    MOZ_ASSERT(!NS_IsMainThread());
-    TimeStamp dispatchDate = TimeStamp::Now();
-
-    nsresult rv = BeforeRead();
-    if (NS_FAILED(rv)) {
-      // Error reporting is handled by BeforeRead();
-      return NS_OK;
-    }
-
-    ScopedArrayBufferContents buffer;
-    rv = Read(buffer);
-    if (NS_FAILED(rv)) {
-      // Error reporting is handled by Read();
-      return NS_OK;
-    }
-
-    AfterRead(dispatchDate, buffer);
-    return NS_OK;
-  }
-
- private:
-  /**
-   * Read synchronously.
-   *
-   * Must be called off the main thread.
-   *
-   * @param aBuffer The destination buffer.
-   */
-  nsresult Read(ScopedArrayBufferContents& aBuffer)
-  {
-    MOZ_ASSERT(!NS_IsMainThread());
-
-    ScopedPRFileDesc file;
-#if defined(XP_WIN)
-    // On Windows, we can't use PR_OpenFile because it doesn't
-    // handle UTF-16 encoding, which is pretty bad. In addition,
-    // PR_OpenFile opens files without sharing, which is not the
-    // general semantics of OS.File.
-    HANDLE handle =
-      ::CreateFileW(mPath.get(),
-                    GENERIC_READ,
-                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                    /*Security attributes*/nullptr,
-                    OPEN_EXISTING,
-                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
-                    /*Template file*/ nullptr);
-
-    if (handle == INVALID_HANDLE_VALUE) {
-      Fail(NS_LITERAL_CSTRING("open"), nullptr, ::GetLastError());
-      return NS_ERROR_FAILURE;
-    }
-
-    file = PR_ImportFile((PROsfd)handle);
-    if (!file) {
-      // |file| is closed by PR_ImportFile
-      Fail(NS_LITERAL_CSTRING("ImportFile"), nullptr, PR_GetOSError());
-      return NS_ERROR_FAILURE;
-    }
-
-#else
-    // On other platforms, PR_OpenFile will do.
-    NS_ConvertUTF16toUTF8 path(mPath);
-    file = PR_OpenFile(path.get(), PR_RDONLY, 0);
-    if (!file) {
-      Fail(NS_LITERAL_CSTRING("open"), nullptr, PR_GetOSError());
-      return NS_ERROR_FAILURE;
-    }
-
-#endif // defined(XP_XIN)
-
-    PRFileInfo64 stat;
-    if (PR_GetOpenFileInfo64(file, &stat) != PR_SUCCESS) {
-      Fail(NS_LITERAL_CSTRING("stat"), nullptr, PR_GetOSError());
-      return NS_ERROR_FAILURE;
-    }
-
-    uint64_t bytes = std::min((uint64_t)stat.size, mBytes);
-    if (bytes > UINT32_MAX) {
-      Fail(NS_LITERAL_CSTRING("Arithmetics"), nullptr, OS_ERROR_INVAL);
-      return NS_ERROR_FAILURE;
-    }
-
-    if (!aBuffer.Allocate(bytes)) {
-      Fail(NS_LITERAL_CSTRING("allocate"), nullptr, OS_ERROR_NOMEM);
-      return NS_ERROR_FAILURE;
-    }
-
-    uint64_t total_read = 0;
-    int32_t just_read = 0;
-    char* dest_chars = reinterpret_cast<char*>(aBuffer.rwget().data);
-    do {
-      just_read = PR_Read(file, dest_chars + total_read,
-                          std::min(uint64_t(PR_INT32_MAX), bytes - total_read));
-      if (just_read == -1) {
-        Fail(NS_LITERAL_CSTRING("read"), nullptr, PR_GetOSError());
-        return NS_ERROR_FAILURE;
-      }
-      total_read += just_read;
-    } while (just_read != 0 && total_read < bytes);
-    if (total_read != bytes) {
-      // We seem to have a race condition here.
-      Fail(NS_LITERAL_CSTRING("read"), nullptr, OS_ERROR_RACE);
-      return NS_ERROR_FAILURE;
-    }
-
-    return NS_OK;
-  }
-
-protected:
-  /**
-   * Any steps that need to be taken before reading.
-   *
-   * In case of error, this method should call Fail() and return
-   * a failure code.
-   */
-  virtual
-  nsresult BeforeRead() {
-    return NS_OK;
-  }
-
-  /**
-   * Proceed after reading.
-   */
-  virtual
-  void AfterRead(TimeStamp aDispatchDate, ScopedArrayBufferContents& aBuffer) = 0;
-
- protected:
-  const nsString mPath;
-  const uint64_t mBytes;
-};
-
-/**
- * An implementation of a Read event that provides the data
- * as a TypedArray.
- */
-class DoReadToTypedArrayEvent MOZ_FINAL : public AbstractReadEvent {
-public:
-  DoReadToTypedArrayEvent(const nsAString& aPath,
-                          const uint32_t aBytes,
-                          already_AddRefed<nsINativeOSFileSuccessCallback> aOnSuccess,
-                          already_AddRefed<nsINativeOSFileErrorCallback>  aOnError)
-    : AbstractReadEvent(aPath, aBytes,
-                        aOnSuccess, aOnError)
-    , mResult(new TypedArrayResult(TimeStamp::Now()))
-  { }
-
-  ~DoReadToTypedArrayEvent() {
-    // If AbstractReadEvent::Run() has bailed out, we may need to cleanup
-    // mResult, which is main-thread only data
-    if (!mResult) {
-      return;
-    }
-    nsCOMPtr<nsIThread> main = do_GetMainThread();
-    (void)NS_ProxyRelease(main, mResult);
-  }
-
-protected:
-  void AfterRead(TimeStamp aDispatchDate,
-                 ScopedArrayBufferContents& aBuffer) MOZ_OVERRIDE {
-    MOZ_ASSERT(!NS_IsMainThread());
-    mResult->Init(aDispatchDate, TimeStamp::Now() - aDispatchDate, aBuffer.forget());
-    Succeed(mResult.forget());
-  }
-
- private:
-  nsRefPtr<TypedArrayResult> mResult;
-};
-
-/**
- * An implementation of a Read event that provides the data
- * as a JavaScript string.
- */
-class DoReadToStringEvent MOZ_FINAL : public AbstractReadEvent {
-public:
-  DoReadToStringEvent(const nsAString& aPath,
-                      const nsACString& aEncoding,
-                      const uint32_t aBytes,
-                      already_AddRefed<nsINativeOSFileSuccessCallback> aOnSuccess,
-                      already_AddRefed<nsINativeOSFileErrorCallback>  aOnError)
-    : AbstractReadEvent(aPath, aBytes, aOnSuccess, aOnError)
-    , mEncoding(aEncoding)
-    , mResult(new StringResult(TimeStamp::Now()))
-  { }
-
-  ~DoReadToStringEvent() {
-    // If AbstraactReadEvent::Run() has bailed out, we may need to cleanup
-    // mResult, which is main-thread only data
-    if (!mResult) {
-      return;
-    }
-    nsCOMPtr<nsIThread> main = do_GetMainThread();
-    (void)NS_ProxyRelease(main, mResult);
-  }
-
-protected:
-  nsresult BeforeRead() MOZ_OVERRIDE {
-    // Obtain the decoder. We do this before reading to avoid doing
-    // any unnecessary I/O in case the name of the encoding is incorrect.
-    MOZ_ASSERT(!NS_IsMainThread());
-    nsAutoCString encodingName;
-    if (!dom::EncodingUtils::FindEncodingForLabel(mEncoding, encodingName)) {
-      Fail(NS_LITERAL_CSTRING("Decode"), mResult.forget(), OS_ERROR_INVAL);
-      return NS_ERROR_FAILURE;
-    }
-    mDecoder = dom::EncodingUtils::DecoderForEncoding(encodingName);
-    if (!mDecoder) {
-      Fail(NS_LITERAL_CSTRING("DecoderForEncoding"), mResult.forget(), OS_ERROR_INVAL);
-      return NS_ERROR_FAILURE;
-    }
-
-    return NS_OK;
-  }
-
-  void AfterRead(TimeStamp aDispatchDate,
-                 ScopedArrayBufferContents& aBuffer) MOZ_OVERRIDE {
-    MOZ_ASSERT(!NS_IsMainThread());
-
-    int32_t maxChars;
-    const char* sourceChars = reinterpret_cast<const char*>(aBuffer.get().data);
-    int32_t sourceBytes = aBuffer.get().nbytes;
-    if (sourceBytes < 0) {
-      Fail(NS_LITERAL_CSTRING("arithmetics"), mResult.forget(), OS_ERROR_TOO_LARGE);
-      return;
-    }
-
-    nsresult rv = mDecoder->GetMaxLength(sourceChars, sourceBytes, &maxChars);
-    if (NS_FAILED(rv)) {
-      Fail(NS_LITERAL_CSTRING("GetMaxLength"), mResult.forget(), OS_ERROR_INVAL);
-      return;
-    }
-
-    if (maxChars < 0) {
-      Fail(NS_LITERAL_CSTRING("arithmetics"), mResult.forget(), OS_ERROR_TOO_LARGE);
-      return;
-    }
-
-    nsString resultString;
-    resultString.SetLength(maxChars);
-    if (resultString.Length() != (nsString::size_type)maxChars) {
-      Fail(NS_LITERAL_CSTRING("allocation"), mResult.forget(), OS_ERROR_TOO_LARGE);
-      return;
-    }
-
-
-    rv = mDecoder->Convert(sourceChars, &sourceBytes,
-                           resultString.BeginWriting(), &maxChars);
-    MOZ_ASSERT(NS_SUCCEEDED(rv));
-    resultString.SetLength(maxChars);
-
-    mResult->Init(aDispatchDate, TimeStamp::Now() - aDispatchDate, resultString);
-    Succeed(mResult.forget());
-  }
-
- private:
-  nsCString mEncoding;
-  nsCOMPtr<nsIUnicodeDecoder> mDecoder;
-  nsRefPtr<StringResult> mResult;
-};
-
-} // osfile
-
-// The OS.File service
-
-NS_IMPL_ISUPPORTS1(NativeOSFileInternalsService, nsINativeOSFileInternalsService);
-
-NS_IMETHODIMP
-NativeOSFileInternalsService::Read(const nsAString& aPath,
-                                   JS::HandleValue aOptions,
-                                   nsINativeOSFileSuccessCallback *aOnSuccess,
-                                   nsINativeOSFileErrorCallback *aOnError,
-                                   JSContext* cx)
-{
-  // Extract options
-  nsCString encoding;
-  uint64_t bytes = UINT64_MAX;
-
-  if (aOptions.isObject()) {
-    dom::NativeOSFileReadOptions dict;
-    if (!dict.Init(cx, aOptions)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-
-    if (dict.mEncoding.WasPassed()) {
-      CopyUTF16toUTF8(dict.mEncoding.Value(), encoding);
-    }
-
-    if (dict.mBytes.WasPassed() && !dict.mBytes.Value().IsNull()) {
-      bytes = dict.mBytes.Value().Value();
-    }
-  }
-
-  // Prepare the off main thread event and dispatch it
-  nsCOMPtr<nsINativeOSFileSuccessCallback> onSuccess(aOnSuccess);
-  nsCOMPtr<nsINativeOSFileErrorCallback> onError(aOnError);
-
-  nsRefPtr<AbstractDoEvent> event;
-  if (encoding.IsEmpty()) {
-    event = new DoReadToTypedArrayEvent(aPath, bytes,
-                                        onSuccess.forget(),
-                                        onError.forget());
-  } else {
-    event = new DoReadToStringEvent(aPath, encoding, bytes,
-                                    onSuccess.forget(),
-                                    onError.forget());
-  }
-
-  nsresult rv;
-  nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
-
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  return target->Dispatch(event, NS_DISPATCH_NORMAL);
-}
-
-} // namespace mozilla
-
deleted file mode 100644
--- a/toolkit/components/osfile/NativeOSFileInternals.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_nativeosfileinternalservice_h__
-#define mozilla_nativeosfileinternalservice_h__
-
-#include "nsINativeOSFileInternals.h"
-#include "mozilla/Attributes.h"
-
-namespace mozilla {
-
-class NativeOSFileInternalsService MOZ_FINAL : public nsINativeOSFileInternalsService {
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSINATIVEOSFILEINTERNALSSERVICE
-private:
-  // Avoid accidental use of built-in operator=
-  void operator=(const NativeOSFileInternalsService& other) MOZ_DELETE;
-};
-
-} // namespace mozilla
-
-#endif // mozilla_finalizationwitnessservice_h__
--- a/toolkit/components/osfile/modules/moz.build
+++ b/toolkit/components/osfile/modules/moz.build
@@ -5,17 +5,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 JS_MODULES_PATH = 'modules/osfile'
 
 EXTRA_JS_MODULES += [
     '_PromiseWorker.jsm',
     'osfile_async_front.jsm',
     'osfile_async_worker.js',
-    'osfile_native.jsm',
     'osfile_shared_allthreads.jsm',
     'osfile_shared_front.jsm',
     'osfile_unix_allthreads.jsm',
     'osfile_unix_back.jsm',
     'osfile_unix_front.jsm',
     'osfile_win_allthreads.jsm',
     'osfile_win_back.jsm',
     'osfile_win_front.jsm',
--- a/toolkit/components/osfile/modules/osfile_async_front.jsm
+++ b/toolkit/components/osfile/modules/osfile_async_front.jsm
@@ -53,17 +53,16 @@ Cu.import("resource://gre/modules/Promis
 Cu.import("resource://gre/modules/Task.jsm", this);
 
 // The implementation of communications
 Cu.import("resource://gre/modules/osfile/_PromiseWorker.jsm", this);
 
 Cu.import("resource://gre/modules/Services.jsm", this);
 Cu.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
 Cu.import("resource://gre/modules/AsyncShutdown.jsm", this);
-let Native = Cu.import("resource://gre/modules/osfile/osfile_native.jsm", {});
 
 /**
  * Constructors for decoding standard exceptions
  * received from the worker.
  */
 const EXCEPTION_CONSTRUCTORS = {
   EvalError: function(error) {
     return new EvalError(error.message, error.fileName, error.lineNumber);
@@ -344,17 +343,17 @@ const PREF_OSFILE_LOG_REDIRECT = "toolki
 
 /**
  * Safely read a PREF_OSFILE_LOG preference.
  * Returns a value read or, in case of an error, oldPref or false.
  *
  * @param bool oldPref
  *        An optional value that the DEBUG flag was set to previously.
  */
-function readDebugPref(prefName, oldPref = false) {
+let readDebugPref = function readDebugPref(prefName, oldPref = false) {
   let pref = oldPref;
   try {
     pref = Services.prefs.getBoolPref(prefName);
   } catch (x) {
     // In case of an error when reading a pref keep it as is.
   }
   // If neither pref nor oldPref were set, default it to false.
   return pref;
@@ -375,29 +374,16 @@ Services.prefs.addObserver(PREF_OSFILE_L
 SharedAll.Config.DEBUG = readDebugPref(PREF_OSFILE_LOG, false);
 
 Services.prefs.addObserver(PREF_OSFILE_LOG_REDIRECT,
   function prefObserver(aSubject, aTopic, aData) {
     SharedAll.Config.TEST = readDebugPref(PREF_OSFILE_LOG_REDIRECT, OS.Shared.TEST);
   }, false);
 SharedAll.Config.TEST = readDebugPref(PREF_OSFILE_LOG_REDIRECT, false);
 
-
-/**
- * If |true|, use the native implementaiton of OS.File methods
- * whenever possible. Otherwise, force the use of the JS version.
- */
-let nativeWheneverAvailable = true;
-const PREF_OSFILE_NATIVE = "toolkit.osfile.native";
-Services.prefs.addObserver(PREF_OSFILE_NATIVE,
-  function prefObserver(aSubject, aTopic, aData) {
-    nativeWheneverAvailable = readDebugPref(PREF_OSFILE_NATIVE, nativeWheneverAvailable);
-  }, false);
-
-
 // Update worker's DEBUG flag if it's true.
 // Don't start the worker just for this, though.
 if (SharedAll.Config.DEBUG && Scheduler.launched) {
   Scheduler.post("SET_DEBUG", [true]);
 }
 
 // Observer topics used for monitoring shutdown
 const WEB_WORKERS_SHUTDOWN_TOPIC = "web-workers-shutdown";
@@ -922,42 +908,22 @@ File.makeDir = function makeDir(path, op
  * - {number} bytes An upper bound to the number of bytes to read.
  * - {string} compression If "lz4" and if the file is compressed using the lz4
  * compression algorithm, decompress the file contents on the fly.
  *
  * @resolves {Uint8Array} A buffer holding the bytes
  * read from the file.
  */
 File.read = function read(path, bytes, options = {}) {
-  if (typeof bytes == "object") {
-    // Passing |bytes| as an argument is deprecated.
-    // We should now be passing it as a field of |options|.
-    options = bytes || {};
-  } else {
-    options = clone(options, ["outExecutionDuration"]);
-    if (typeof bytes != "undefined") {
-      options.bytes = bytes;
-    }
-  }
-
-  if (options.compression || !nativeWheneverAvailable) {
-    // We need to use the JS implementation.
-    let promise = Scheduler.post("read",
-      [Type.path.toMsg(path), bytes, options], path);
-    return promise.then(
-      function onSuccess(data) {
-        if (typeof data == "string") {
-          return data;
-        }
-        return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
-      });
-  }
-
-  // Otherwise, use the native implementation.
-  return Scheduler.push(() => Native.read(path, options));
+  let promise = Scheduler.post("read",
+    [Type.path.toMsg(path), bytes, options], path);
+  return promise.then(
+    function onSuccess(data) {
+      return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
+    });
 };
 
 /**
  * Find outs if a file exists.
  *
  * @param {string} path The path to the file.
  *
  * @return {bool} true if the file exists, false otherwise.
--- a/toolkit/components/osfile/modules/osfile_async_worker.js
+++ b/toolkit/components/osfile/modules/osfile_async_worker.js
@@ -357,19 +357,16 @@ const EXCEPTION_NAMES = {
 
      return {
        path: openedFile.path,
        file: resourceId
      };
    },
    read: function read(path, bytes, options) {
      let data = File.read(Type.path.fromMsg(path), bytes, options);
-     if (typeof data == "string") {
-       return data;
-     }
      return new Meta({
          buffer: data.buffer,
          byteOffset: data.byteOffset,
          byteLength: data.byteLength
      }, {
        transfers: [data.buffer]
      });
    },
deleted file mode 100644
--- a/toolkit/components/osfile/modules/osfile_native.jsm
+++ /dev/null
@@ -1,70 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- * Native (xpcom) implementation of key OS.File functions
- */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = ["read"];
-
-let {results: Cr, utils: Cu, interfaces: Ci} = Components;
-
-let SharedAll = Cu.import("resource://gre/modules/osfile/osfile_shared_allthreads.jsm", {});
-
-let SysAll = {};
-if (SharedAll.Constants.Win) {
-  Cu.import("resource://gre/modules/osfile/osfile_win_allthreads.jsm", SysAll);
-} else if (SharedAll.Constants.libc) {
-  Cu.import("resource://gre/modules/osfile/osfile_unix_allthreads.jsm", SysAll);
-} else {
-  throw new Error("I am neither under Windows nor under a Posix system");
-}
-let {Promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
-let {XPCOMUtils} = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
-
-/**
- * The native service holding the implementation of the functions.
- */
-XPCOMUtils.defineLazyServiceGetter(this,
-  "Internals",
-  "@mozilla.org/toolkit/osfile/native-internals;1",
-  "nsINativeOSFileInternalsService");
-
-/**
- * Native implementation of OS.File.read
- *
- * This implementation does not handle option |compression|.
- */
-this.read = function(path, options = {}) {
-  // Sanity check on types of options
-  if ("encoding" in options && typeof options.encoding != "string") {
-    return Promise.reject(new TypeError("Invalid type for option encoding"));
-  }
-  if ("compression" in options && typeof options.compression != "string") {
-    return Promise.reject(new TypeError("Invalid type for option compression"));
-  }
-  if ("bytes" in options && typeof options.bytes != "number") {
-    return Promise.reject(new TypeError("Invalid type for option bytes"));
-  }
-
-  let deferred = Promise.defer();
-  Internals.read(path,
-    options,
-    function onSuccess(success) {
-      success.QueryInterface(Ci.nsINativeOSFileResult);
-      if ("outExecutionDuration" in options) {
-        options.outExecutionDuration =
-          success.executionDurationMS +
-          (options.outExecutionDuration || 0);
-      }
-      deferred.resolve(success.result);
-    },
-    function onError(operation, oserror) {
-      deferred.reject(new SysAll.Error(operation, oserror, path));
-    }
-  );
-  return deferred.promise;
-};
--- a/toolkit/components/osfile/modules/osfile_shared_front.jsm
+++ b/toolkit/components/osfile/modules/osfile_shared_front.jsm
@@ -326,45 +326,24 @@ AbstractFile.normalizeOpenMode = functio
  * @return {Uint8Array} A buffer holding the bytes
  * and the number of bytes read from the file.
  */
 AbstractFile.read = function read(path, bytes, options = {}) {
   if (bytes && typeof bytes == "object") {
     options = bytes;
     bytes = options.bytes || null;
   }
-  if ("encoding" in options && typeof options.encoding != "string") {
-    throw new TypeError("Invalid type for option encoding");
-  }
-  if ("compression" in options && typeof options.compression != "string") {
-    throw new TypeError("Invalid type for option compression: " + options.compression);
-  }
-  if ("bytes" in options && typeof options.bytes != "number") {
-    throw new TypeError("Invalid type for option bytes");
-  }
   let file = exports.OS.File.open(path);
   try {
     let buffer = file.read(bytes, options);
-    if ("compression" in options) {
-      if (options.compression == "lz4") {
-        buffer = Lz4.decompressFileContent(buffer, options);
-      } else {
-        throw OS.File.Error.invalidArgument("Compression");
-      }
-    }
-    if (!("encoding" in options)) {
+    if ("compression" in options && options.compression == "lz4") {
+      return Lz4.decompressFileContent(buffer, options);
+    } else {
       return buffer;
     }
-    let decoder;
-    try {
-      decoder = new TextDecoder(options.encoding);
-    } catch (ex if ex instanceof TypeError) {
-      throw OS.File.Error.invalidArgument("Decode");
-    }
-    return decoder.decode(buffer);
   } finally {
     file.close();
   }
 };
 
 /**
  * Write a file, atomically.
  *
--- a/toolkit/components/osfile/modules/osfile_unix_allthreads.jsm
+++ b/toolkit/components/osfile/modules/osfile_unix_allthreads.jsm
@@ -134,25 +134,16 @@ Object.defineProperty(OSError.prototype,
  * |true| if the error was raised because permission is denied to
  * access a file or directory, |false| otherwise.
  */
 Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
   get: function becauseAccessDenied() {
     return this.unixErrno == Const.EACCES;
   }
 });
-/**
- * |true| if the error was raised because some invalid argument was passed,
- * |false| otherwise.
- */
-Object.defineProperty(OSError.prototype, "becauseInvalidArgument", {
-  get: function becauseInvalidArgument() {
-    return this.unixErrno == Const.EINVAL;
-  }
-});
 
 /**
  * Serialize an instance of OSError to something that can be
  * transmitted across threads (not necessarily a string).
  */
 OSError.toMsg = function toMsg(error) {
   return {
     operation: error.operation,
@@ -335,20 +326,16 @@ OSError.closed = function closed(operati
 OSError.exists = function exists(operation, path) {
   return new OSError(operation, Const.EEXIST, path);
 };
 
 OSError.noSuchFile = function noSuchFile(operation, path) {
   return new OSError(operation, Const.ENOENT, path);
 };
 
-OSError.invalidArgument = function invalidArgument(operation) {
-  return new OSError(operation, Const.EINVAL);
-};
-
 let EXPORTED_SYMBOLS = [
   "declareFFI",
   "libc",
   "Error",
   "AbstractInfo",
   "AbstractEntry",
   "Type",
   "POS_START",
--- a/toolkit/components/osfile/modules/osfile_win_allthreads.jsm
+++ b/toolkit/components/osfile/modules/osfile_win_allthreads.jsm
@@ -156,25 +156,16 @@ Object.defineProperty(OSError.prototype,
  * |true| if the error was raised because permission is denied to
  * access a file or directory, |false| otherwise.
  */
 Object.defineProperty(OSError.prototype, "becauseAccessDenied", {
   get: function becauseAccessDenied() {
     return this.winLastError == Const.ERROR_ACCESS_DENIED;
   }
 });
-/**
- * |true| if the error was raised because some invalid argument was passed,
- * |false| otherwise.
- */
-Object.defineProperty(OSError.prototype, "becauseInvalidArgument", {
-  get: function becauseInvalidArgument() {
-    return this.winLastError == Const.ERROR_NOT_SUPPORTED;
-  }
-});
 
 /**
  * Serialize an instance of OSError to something that can be
  * transmitted across threads (not necessarily a string).
  */
 OSError.toMsg = function toMsg(error) {
   return {
     operation: error.operation,
@@ -372,20 +363,16 @@ OSError.closed = function closed(operati
 OSError.exists = function exists(operation, path) {
   return new OSError(operation, Const.ERROR_FILE_EXISTS, path);
 };
 
 OSError.noSuchFile = function noSuchFile(operation, path) {
   return new OSError(operation, Const.ERROR_FILE_NOT_FOUND, path);
 };
 
-OSError.invalidArgument = function invalidArgument(operation) {
-  return new OSError(operation, Const.ERROR_NOT_SUPPORTED);
-};
-
 let EXPORTED_SYMBOLS = [
   "declareFFI",
   "libc",
   "Error",
   "AbstractInfo",
   "AbstractEntry",
   "Type",
   "POS_START",
--- a/toolkit/components/osfile/moz.build
+++ b/toolkit/components/osfile/moz.build
@@ -6,27 +6,12 @@
 
 DIRS += [
     'modules',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += ['tests/mochi/chrome.ini']
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 
-SOURCES += [
-    'NativeOSFileInternals.cpp',
-]
-
-XPIDL_MODULE = 'toolkit_osfile'
-
-XPIDL_SOURCES += [
-    'nsINativeOSFileInternals.idl',
-]
-
-EXPORTS.mozilla += [
-    'NativeOSFileInternals.h',
-]
-
 EXTRA_PP_JS_MODULES += [
     'osfile.jsm',
 ]
 
-FINAL_LIBRARY = 'toolkitcomps'
deleted file mode 100644
--- a/toolkit/components/osfile/nsINativeOSFileInternals.idl
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* vim: set ts=2 et sw=2 tw=40: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-/**
- * The result of a successful asynchronous operation.
- */
-[scriptable, builtinclass, uuid(08B4CF29-3D65-4E79-B522-A694C322ED07)]
-interface nsINativeOSFileResult: nsISupports
-{
-  /**
-   * The actual value produced by the operation.
-   *
-   * Actual type of this value depends on the options passed to the
-   * operation.
-   */
-  [implicit_jscontext]
-  readonly attribute jsval result;
-
-  /**
-   * Delay between when the operation was requested on the main thread and
-   * when the operation was started off main thread.
-   */
-  readonly attribute double dispatchDurationMS;
-
-  /**
-   * Duration of the off main thread execution.
-   */
-  readonly attribute double executionDurationMS;
-};
-
-/**
- * A callback invoked in case of success.
- */
-[scriptable, function, uuid(2C1922CA-CA1B-4099-8B61-EC23CFF49412)]
-interface nsINativeOSFileSuccessCallback: nsISupports
-{
-  void complete(in nsINativeOSFileResult result);
-};
-
-/**
- * A callback invoked in case of error.
- */
-[scriptable, function, uuid(F612E0FC-6736-4D24-AA50-FD661B3B40B6)]
-interface nsINativeOSFileErrorCallback: nsISupports
-{
-  /**
-   * @param operation The name of the failed operation. Provided to aid
-   * debugging only, may change without notice.
-   * @param OSstatus The OS status of the operation (errno under Unix,
-   * GetLastError under Windows).
-   */
-  void complete(in ACString operation, in long OSstatus);
-};
-
-/**
- * A service providing native implementations of some of the features
- * of OS.File.
- */
-[scriptable, builtinclass, uuid(913362AD-1526-4623-9E6B-A2EB08AFBBB9)]
-interface nsINativeOSFileInternalsService: nsISupports
-{
-  /**
-   * Implementation of OS.File.read
-   *
-   * @param path The absolute path to the file to read.
-   * @param options An object that may contain some of the following fields
-   * - {number} bytes The maximal number of bytes to read.
-   * - {string} encoding If provided, return the result as a string, decoded
-   *   using this encoding. Otherwise, pass the result as an ArrayBuffer.
-   *   Invalid encodings cause onError to be called with the platform-specific
-   *   "invalid argument" constant.
-   * - {string} compression Unimplemented at the moment.
-   * @param onSuccess The success callback.
-   * @param onError The error callback.
-   */
-  [implicit_jscontext]
-  void read(in AString path, in jsval options,
-            in nsINativeOSFileSuccessCallback onSuccess,
-            in nsINativeOSFileErrorCallback onError);
-};
-
-
-%{ C++
-
-#define NATIVE_OSFILE_INTERNALS_SERVICE_CID {0x63A69303,0x8A64,0x45A9,{0x84, 0x8C, 0xD4, 0xE2, 0x79, 0x27, 0x94, 0xE6}}
-#define NATIVE_OSFILE_INTERNALS_SERVICE_CONTRACTID "@mozilla.org/toolkit/osfile/native-internals;1"
-
-%}
--- a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
+++ b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
@@ -150,16 +150,17 @@ let test = maketest("Main", function mai
   return Task.spawn(function() {
     SimpleTest.waitForExplicitFinish();
     yield test_constants();
     yield test_path();
     yield test_stat();
     yield test_debug();
     yield test_info_features_detect();
     yield test_read_write();
+    yield test_read_write_all();
     yield test_position();
     yield test_iter();
     yield test_exists();
     yield test_debug_test();
     info("Test is over");
     SimpleTest.finish();
   });
 });
@@ -297,16 +298,102 @@ let test_read_write = maketest("read_wri
     test.is(stat.size, size, "Both files have the same size");
     yield reference_compare_files(pathSource, pathDest, test);
 
     // Cleanup.
     OS.File.remove(pathDest);
   });
 });
 
+/**
+ * Test OS.File.writeAtomic
+ */
+let test_read_write_all = maketest("read_write_all", function read_write_all(test) {
+  return Task.spawn(function() {
+    let pathDest = OS.Path.join(OS.Constants.Path.tmpDir,
+      "osfile async test read writeAtomic.tmp");
+    let tmpPath = pathDest + ".tmp";
+
+    let test_with_options = function(options, suffix) {
+      return Task.spawn(function() {
+        let optionsBackup = JSON.parse(JSON.stringify(options));
+
+        // Check that read + writeAtomic performs a correct copy
+        let currentDir = yield OS.File.getCurrentDirectory();
+        let pathSource = OS.Path.join(currentDir, EXISTING_FILE);
+        let contents = yield OS.File.read(pathSource);
+        test.ok(contents, "Obtained contents");
+        let bytesWritten = yield OS.File.writeAtomic(pathDest, contents, options);
+        test.is(contents.byteLength, bytesWritten, "Wrote the correct number of bytes (" + suffix + ")");
+
+        // Check that options are not altered
+        test.is(Object.keys(options).length, Object.keys(optionsBackup).length,
+          "The number of options was not changed");
+        for (let k in options) {
+          test.is(options[k], optionsBackup[k], "Option was not changed (" + suffix + ")");
+        }
+        yield reference_compare_files(pathSource, pathDest, test);
+
+        // Check that temporary file was removed or doesn't exist
+        test.info("Compare complete");
+        test.ok(!(new FileUtils.File(tmpPath).exists()), "No temporary file at the end of the run (" + suffix + ")");
+
+        // Check that writeAtomic fails if noOverwrite is true and the destination
+        // file already exists!
+        let view = new Uint8Array(contents.buffer, 10, 200);
+        try {
+          let opt = JSON.parse(JSON.stringify(options));
+          opt.noOverwrite = true;
+          yield OS.File.writeAtomic(pathDest, view, opt);
+          test.fail("With noOverwrite, writeAtomic should have refused to overwrite file (" + suffix + ")");
+        } catch (err) {
+          test.info("With noOverwrite, writeAtomic correctly failed (" + suffix + ")");
+          test.ok(err instanceof OS.File.Error, "writeAtomic correctly failed with a file error (" + suffix + ")");
+          test.ok(err.becauseExists, "writeAtomic file error confirmed that the file already exists (" + suffix + ")");
+        }
+        yield reference_compare_files(pathSource, pathDest, test);
+        test.ok(!(new FileUtils.File(tmpPath).exists()), "Temporary file was removed");
+
+        // Now write a subset
+        let START = 10;
+        let LENGTH = 100;
+        view = new Uint8Array(contents.buffer, START, LENGTH);
+        bytesWritten = yield OS.File.writeAtomic(pathDest, view, options);
+        test.is(bytesWritten, LENGTH, "Partial write wrote the correct number of bytes (" + suffix + ")");
+        let array2 = yield OS.File.read(pathDest);
+        let view1 = new Uint8Array(contents.buffer, START, LENGTH);
+        test.is(view1.length, array2.length, "Re-read partial write with the correct number of bytes (" + suffix + ")");
+        let decoder = new TextDecoder();
+        test.is(decoder.decode(view1), decoder.decode(array2), "Comparing re-read of partial write (" + suffix + ")");
+
+        // Write strings, default encoding
+        let ARBITRARY_STRING = "aeiouyâêîôûçß•";
+        yield OS.File.writeAtomic(pathDest, ARBITRARY_STRING, options);
+        let array = yield OS.File.read(pathDest);
+        let IN_STRING = decoder.decode(array);
+        test.is(ARBITRARY_STRING, IN_STRING, "String write + read with default encoding works (" + suffix + ")");
+
+        let opt16 = JSON.parse(JSON.stringify(options));
+        opt16.encoding = "utf-16";
+        yield OS.File.writeAtomic(pathDest, ARBITRARY_STRING, opt16);
+        array = yield OS.File.read(pathDest);
+        IN_STRING = (new TextDecoder("utf-16")).decode(array);
+        test.is(ARBITRARY_STRING, IN_STRING, "String write + read with utf-16 encoding works (" + suffix + ")");
+
+        // Cleanup.
+        OS.File.remove(pathDest);
+      });
+    };
+
+    yield test_with_options({tmpPath: tmpPath}, "Renaming, not flushing");
+    yield test_with_options({tmpPath: tmpPath, flush: true}, "Renaming, flushing");
+    yield test_with_options({}, "Not renaming, not flushing");
+    yield test_with_options({flush: true}, "Not renaming, flushing");
+  });
+});
 
 /**
  * Test file.{getPosition, setPosition}
  */
 let test_position = maketest("position", function position(test) {
   return Task.spawn(function() {
     let file = yield OS.File.open(EXISTING_FILE);
 
deleted file mode 100644
--- a/toolkit/components/osfile/tests/xpcshell/head.js
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-let {utils: Cu, interfaces: Ci} = Components;
-
-let {OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
-let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
-let {Promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
-let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
-let {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
-let {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
-
-Services.prefs.setBoolPref("toolkit.osfile.log", true);
-
-/**
- * As add_task, but execute the test both with native operations and
- * without.
- */
-function add_test_pair(generator) {
-  add_task(function*() {
-    do_print("Executing test " + generator.name + " with native operations");
-    Services.prefs.setBoolPref("toolkit.osfile.native", true);
-    return Task.spawn(generator);
-  });
-  add_task(function*() {
-    do_print("Executing test " + generator.name + " without native operations");
-    Services.prefs.setBoolPref("toolkit.osfile.native", false);
-    return Task.spawn(generator);
-  });
-}
-
-/**
- * Fetch asynchronously the contents of a file using xpcom.
- *
- * Used for comparing xpcom-based results to os.file-based results.
- *
- * @param {string} path The _absolute_ path to the file.
- * @return {promise}
- * @resolves {string} The contents of the file.
- */
-function reference_fetch_file(path, test) {
-  do_print("Fetching file " + path);
-  let deferred = Promise.defer();
-  let file = new FileUtils.File(path);
-  NetUtil.asyncFetch(file,
-    function(stream, status) {
-      if (!Components.isSuccessCode(status)) {
-        deferred.reject(status);
-        return;
-      }
-      let result, reject;
-      try {
-        result = NetUtil.readInputStreamToString(stream, stream.available());
-      } catch (x) {
-        reject = x;
-      }
-      stream.close();
-      if (reject) {
-        deferred.reject(reject);
-      } else {
-        deferred.resolve(result);
-      }
-  });
-  return deferred.promise;
-};
-
-/**
- * Compare asynchronously the contents two files using xpcom.
- *
- * Used for comparing xpcom-based results to os.file-based results.
- *
- * @param {string} a The _absolute_ path to the first file.
- * @param {string} b The _absolute_ path to the second file.
- *
- * @resolves {null}
- */
-function reference_compare_files(a, b, test) {
-  return Task.spawn(function*() {
-    do_print("Comparing files " + a + " and " + b);
-    let a_contents = yield reference_fetch_file(a, test);
-    let b_contents = yield reference_fetch_file(b, test);
-    do_check_eq(a_contents, b_contents);
-  });
-};
--- a/toolkit/components/osfile/tests/xpcshell/test_creationDate.js
+++ b/toolkit/components/osfile/tests/xpcshell/test_creationDate.js
@@ -1,10 +1,18 @@
 "use strict";
 
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/osfile.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
+Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
+
 function run_test() {
   do_test_pending();
   run_next_test();
 }
 
 /**
  * Test to ensure that deprecation warning is issued on use
  * of creationDate.
--- a/toolkit/components/osfile/tests/xpcshell/test_exception.js
+++ b/toolkit/components/osfile/tests/xpcshell/test_exception.js
@@ -1,89 +1,27 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-/**
- * Test that functions throw the appropriate exceptions.
- */
-
 "use strict";
 
-let EXISTING_FILE = do_get_file("xpcshell.ini").path;
-
+Components.utils.import("resource://gre/modules/osfile.jsm");
 
-// Tests on |open|
+function run_test() {
+  do_test_pending();
+  run_next_test();
+}
 
-add_test_pair(function test_typeerror() {
+add_task(function test_typeerror() {
   let exn;
   try {
     let fd = yield OS.File.open("/tmp", {no_such_key: 1});
     do_print("Fd: " + fd);
   } catch (ex) {
     exn = ex;
   }
   do_print("Exception: " + exn);
   do_check_true(exn.constructor.name == "TypeError");
 });
 
-// Tests on |read|
-
-add_test_pair(function* test_bad_encoding() {
-  do_print("Testing with a wrong encoding");
-  try {
-    yield OS.File.read(EXISTING_FILE, { encoding: "baby-speak-encoded" });
-    do_throw("Should have thrown with an ex.becauseInvalidArgument");
-  } catch (ex if ex.becauseInvalidArgument) {
-    do_print("Wrong encoding caused the correct exception");
-  }
-
-  try {
-    yield OS.File.read(EXISTING_FILE, { encoding: 4 });
-    do_throw("Should have thrown a TypeError");
-  } catch (ex if ex.constructor.name == "TypeError") {
-    // Note that TypeError doesn't carry across compartments
-    do_print("Non-string encoding caused the correct exception");
-  }
- });
-
-add_test_pair(function* test_bad_compression() {
-  do_print("Testing with a non-existing compression");
-  try {
-    yield OS.File.read(EXISTING_FILE, { compression: "mmmh-crunchy" });
-    do_throw("Should have thrown with an ex.becauseInvalidArgument");
-  } catch (ex if ex.becauseInvalidArgument) {
-    do_print("Wrong encoding caused the correct exception");
-  }
-
-  do_print("Testing with a bad type for option compression");
-  try {
-    yield OS.File.read(EXISTING_FILE, { compression: 5 });
-    do_throw("Should have thrown a TypeError");
-  } catch (ex if ex.constructor.name == "TypeError") {
-    // Note that TypeError doesn't carry across compartments
-    do_print("Non-string encoding caused the correct exception");
-  }
+add_task(function() {
+  do_test_finished();
 });
-
-add_test_pair(function* test_bad_bytes() {
-  do_print("Testing with a bad type for option bytes");
-  try {
-    yield OS.File.read(EXISTING_FILE, { bytes: "five" });
-    do_throw("Should have thrown a TypeError");
-  } catch (ex if ex.constructor.name == "TypeError") {
-    // Note that TypeError doesn't carry across compartments
-    do_print("Non-number bytes caused the correct exception");
-  }
-});
-
-add_test_pair(function* read_non_existent() {
-  do_print("Testing with a non-existent file");
-  try {
-    yield OS.File.read("I/do/not/exist");
-    do_throw("Should have thrown with an ex.becauseNoSuchFile");
-  } catch (ex if ex.becauseNoSuchFile) {
-    do_print("Correct exceptions");
-  }
-});
-
-function run_test() {
-  run_next_test();
-}
--- a/toolkit/components/osfile/tests/xpcshell/test_open.js
+++ b/toolkit/components/osfile/tests/xpcshell/test_open.js
@@ -1,16 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 Components.utils.import("resource://gre/modules/osfile.jsm");
 
 function run_test() {
+  do_test_pending();
   run_next_test();
 }
 
 /**
  * Test OS.File.open for reading:
  * - with an existing file (should succeed);
  * - with a non-existing file (should fail);
  * - with inconsistent arguments (should fail).
@@ -63,8 +64,12 @@ add_task(function test_error_attributes 
   try {
     yield OS.File.open(fpath, {truncate: true}, {});
     do_check_true(false, "Opening path suceeded (it should fail) " + fpath);
   } catch (err) {
     do_check_true(err instanceof OS.File.Error);
     do_check_true(err.becauseNoSuchFile);
   }
 });
+
+add_task(function() {
+  do_test_finished();
+});
--- a/toolkit/components/osfile/tests/xpcshell/test_path_constants.js
+++ b/toolkit/components/osfile/tests/xpcshell/test_path_constants.js
@@ -1,14 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/osfile.jsm", this);
+Cu.import("resource://gre/modules/Services.jsm", this);
 Cu.import("resource://gre/modules/ctypes.jsm", this);
 Cu.import("resource://testing-common/AppData.jsm", this);
 
 
 function run_test() {
   run_next_test();
 }
 
deleted file mode 100644
--- a/toolkit/components/osfile/tests/xpcshell/test_read_write.js
+++ /dev/null
@@ -1,100 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-let {utils: Cu} = Components;
-
-let SHARED_PATH;
-
-let EXISTING_FILE = do_get_file("xpcshell.ini").path;
-
-add_task(function* init() {
-  do_get_profile();
-  SHARED_PATH = OS.Path.join(OS.Constants.Path.profileDir, "test_osfile_read.tmp");
-});
-
-
-// Check that OS.File.read() is executed after the previous operation
-add_test_pair(function* ordering() {
-  let string1 = "Initial state " + Math.random();
-  let string2 = "After writing " + Math.random();
-  yield OS.File.writeAtomic(SHARED_PATH, string1);
-  OS.File.writeAtomic(SHARED_PATH, string2);
-  let string3 = yield OS.File.read(SHARED_PATH, { encoding: "utf-8" });
-  do_check_eq(string3, string2);
-});
-
-add_test_pair(function* read_write_all() {
-  let DEST_PATH = SHARED_PATH + Math.random();
-  let TMP_PATH = DEST_PATH + ".tmp";
-
-  let test_with_options = function(options, suffix) {
-    return Task.spawn(function*() {
-      do_print("Running test read_write_all with options " + JSON.stringify(options));
-      let TEST = "read_write_all " + suffix;
-
-      let optionsBackup = JSON.parse(JSON.stringify(options));
-
-      // Check that read + writeAtomic performs a correct copy
-      let currentDir = yield OS.File.getCurrentDirectory();
-      let pathSource = OS.Path.join(currentDir, EXISTING_FILE);
-      let contents = yield OS.File.read(pathSource);
-      do_check_true(!!contents); // Content is not empty
-
-      let bytesWritten = yield OS.File.writeAtomic(DEST_PATH, contents, options);
-      do_check_eq(contents.byteLength, bytesWritten); // Correct number of bytes written
-
-      // Check that options are not altered
-      do_check_eq(JSON.stringify(options), JSON.stringify(optionsBackup));
-      yield reference_compare_files(pathSource, DEST_PATH, TEST);
-
-      // Check that temporary file was removed or never created exist
-      do_check_false(new FileUtils.File(TMP_PATH).exists());
-
-      // Check that writeAtomic fails if noOverwrite is true and the destination
-      // file already exists!
-      let view = new Uint8Array(contents.buffer, 10, 200);
-      try {
-        let opt = JSON.parse(JSON.stringify(options));
-        opt.noOverwrite = true;
-        yield OS.File.writeAtomic(DEST_PATH, view, opt);
-        do_throw("With noOverwrite, writeAtomic should have refused to overwrite file (" + suffix + ")");
-      } catch (err if err instanceof OS.File.Error && err.becauseExists) {
-        do_print("With noOverwrite, writeAtomic correctly failed (" + suffix + ")");
-      }
-      yield reference_compare_files(pathSource, DEST_PATH, TEST);
-
-      // Check that temporary file was removed or never created
-      do_check_false(new FileUtils.File(TMP_PATH).exists());
-
-      // Now write a subset
-      let START = 10;
-      let LENGTH = 100;
-      view = new Uint8Array(contents.buffer, START, LENGTH);
-      bytesWritten = yield OS.File.writeAtomic(DEST_PATH, view, options);
-      do_check_eq(bytesWritten, LENGTH);
-
-      let array2 = yield OS.File.read(DEST_PATH);
-      let view1 = new Uint8Array(contents.buffer, START, LENGTH);
-      do_check_eq(view1.length, array2.length);
-      let decoder = new TextDecoder();
-      do_check_eq(decoder.decode(view1), decoder.decode(array2));
-
-
-      // Cleanup.
-      yield OS.File.remove(DEST_PATH);
-      yield OS.File.remove(TMP_PATH);
-    });
-  };
-
-  yield test_with_options({tmpPath: TMP_PATH}, "Renaming, not flushing");
-  yield test_with_options({tmpPath: TMP_PATH, flush: true}, "Renaming, flushing");
-  yield test_with_options({}, "Not renaming, not flushing");
-  yield test_with_options({flush: true}, "Not renaming, flushing");
-});
-
-
-function run_test() {
-  run_next_test();
-}
--- a/toolkit/components/osfile/tests/xpcshell/xpcshell.ini
+++ b/toolkit/components/osfile/tests/xpcshell/xpcshell.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-head = head.js
+head =
 tail =
 
 [test_available_free_space.js]
 [test_osfile_closed.js]
 [test_path.js]
 [test_osfile_async.js]
 [test_osfile_async_append.js]
 [test_osfile_async_bytes.js]
@@ -20,12 +20,11 @@ tail =
 [test_path_constants.js]
 [test_removeDir.js]
 [test_reset.js]
 [test_shutdown.js]
 [test_unique.js]
 [test_open.js]
 [test_telemetry.js]
 [test_duration.js]
-[test_read_write.js]
 [test_compression.js]
 [test_osfile_writeAtomic_backupTo_option.js]
 [test_osfile_error.js]
--- a/toolkit/crashreporter/test/unit/test_crash_AsyncShutdown.js
+++ b/toolkit/crashreporter/test/unit/test_crash_AsyncShutdown.js
@@ -35,17 +35,16 @@ function after_crash(mdump, extra) {
 // the latest operation succeeded
 
 function setup_osfile_crash_noerror() {
   Components.utils.import("resource://gre/modules/Services.jsm", this);
   Components.utils.import("resource://gre/modules/osfile.jsm", this);
 
   Services.prefs.setBoolPref("toolkit.osfile.debug.failshutdown", true);
   Services.prefs.setIntPref("toolkit.asyncshutdown.crash_timeout", 1);
-  Services.prefs.setBoolPref("toolkit.osfile.native", false);
 
   OS.File.getCurrentDirectory();
   Services.obs.notifyObservers(null, "profile-before-change", null);
   dump("Waiting for crash\n");
 };
 
 function after_osfile_crash_noerror(mdump, extra) {
   do_print("after OS.File crash: " + JSON.stringify(extra.AsyncShutdownTimeout));
@@ -64,29 +63,29 @@ function after_osfile_crash_noerror(mdum
 // the latest operation failed
 
 function setup_osfile_crash_exn() {
   Components.utils.import("resource://gre/modules/Services.jsm", this);
   Components.utils.import("resource://gre/modules/osfile.jsm", this);
 
   Services.prefs.setBoolPref("toolkit.osfile.debug.failshutdown", true);
   Services.prefs.setIntPref("toolkit.asyncshutdown.crash_timeout", 1);
-  Services.prefs.setBoolPref("toolkit.osfile.native", false);
 
   OS.File.read("I do not exist");
   Services.obs.notifyObservers(null, "profile-before-change", null);
   dump("Waiting for crash\n");
 };
 
 function after_osfile_crash_exn(mdump, extra) {
   do_print("after OS.File crash: " + JSON.stringify(extra.AsyncShutdownTimeout));
   let info = JSON.parse(extra.AsyncShutdownTimeout);
   let state = info.conditions[0].state;
   do_print("Keys: " + Object.keys(state).join(", "));
   do_check_eq(info.phase, "profile-before-change");
+  do_check_true(state.launched);
   do_check_false(state.shutdown);
   do_check_true(state.worker);
   do_check_true(!!state.latestSent);
   do_check_eq(state.latestSent[1], "read");
 }
 
 function run_test() {
   do_crash(setup_crash, after_crash);
--- a/xpcom/io/nsLocalFileWin.cpp
+++ b/xpcom/io/nsLocalFileWin.cpp
@@ -587,17 +587,17 @@ struct PRFilePrivate {
 // OpenDir, CloseDir, ReadDir) should go away once the corresponding 
 // UTF-16 APIs are implemented on all the supported platforms (or at least 
 // Windows 9x/ME) in NSPR. Currently, they're only implemented on 
 // Windows NT4 or later. (bug 330665)
 //-----------------------------------------------------------------------------
 
 // copied from nsprpub/pr/src/{io/prfile.c | md/windows/w95io.c} : 
 // PR_Open and _PR_MD_OPEN
-nsresult
+static nsresult
 OpenFile(const nsAFlatString &name, int osflags, int mode,
          PRFileDesc **fd)
 {
     int32_t access = 0;
 
     int32_t disposition = 0;
     int32_t attributes = 0;