Revert "Trim down FileWrapper class to be merely a wrapper owning a FILE*"

This reverts commit 80b95de7651caa0cfeb684ffc200860989f667dc.

Reason for revert: Speculative revert for downstream breakage. Possibly FileAudioDevice broken?

Original change's description:
> Trim down FileWrapper class to be merely a wrapper owning a FILE*
> 
> Bug: webrtc:6463
> Change-Id: If71e2f3a75dc1863bc805ab71de1e2d33294f805
> Reviewed-on: https://webrtc-review.googlesource.com/c/117881
> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
> Reviewed-by: Alex Loiko <aleloi@webrtc.org>
> Commit-Queue: Niels Moller <nisse@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26311}

TBR=aleloi@webrtc.org,kwiberg@webrtc.org,nisse@webrtc.org,tommi@webrtc.org

Change-Id: I46d37afbf9acb5f62f04e09d944114c1da96eb36
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:6463
Reviewed-on: https://webrtc-review.googlesource.com/c/118380
Reviewed-by: Niels Moller <nisse@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26318}
diff --git a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc
index 956d790..8e04e8e 100644
--- a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc
+++ b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc
@@ -67,13 +67,14 @@
 #endif
 
  private:
-  FileWrapper dump_file_;
+  std::unique_ptr<FileWrapper> dump_file_;
 };
 
-DebugDumpWriterImpl::DebugDumpWriterImpl(FILE* file_handle) {
+DebugDumpWriterImpl::DebugDumpWriterImpl(FILE* file_handle)
+    : dump_file_(FileWrapper::Create()) {
 #if WEBRTC_ENABLE_PROTOBUF
-  dump_file_ = FileWrapper(file_handle);
-  RTC_CHECK(dump_file_.is_open());
+  dump_file_->OpenFromFileHandle(file_handle);
+  RTC_CHECK(dump_file_->is_open());
 #else
   RTC_NOTREACHED();
 #endif
@@ -109,7 +110,7 @@
         *metrics.uplink_recoverable_packet_loss_fraction);
   }
 
-  DumpEventToFile(event, &dump_file_);
+  DumpEventToFile(event, dump_file_.get());
 #endif  // WEBRTC_ENABLE_PROTOBUF
 }
 
@@ -142,7 +143,7 @@
   if (config.num_channels)
     dump_config->set_num_channels(*config.num_channels);
 
-  DumpEventToFile(event, &dump_file_);
+  DumpEventToFile(event, dump_file_.get());
 #endif  // WEBRTC_ENABLE_PROTOBUF
 }
 
@@ -156,7 +157,7 @@
   event.set_type(Event::CONTROLLER_MANAGER_CONFIG);
   event.mutable_controller_manager_config()->CopyFrom(
       controller_manager_config);
-  DumpEventToFile(event, &dump_file_);
+  DumpEventToFile(event, dump_file_.get());
 }
 #endif  // WEBRTC_ENABLE_PROTOBUF
 
diff --git a/modules/audio_device/dummy/file_audio_device.cc b/modules/audio_device/dummy/file_audio_device.cc
index cb3fa27..ea736e0 100644
--- a/modules/audio_device/dummy/file_audio_device.cc
+++ b/modules/audio_device/dummy/file_audio_device.cc
@@ -43,10 +43,15 @@
       _recording(false),
       _lastCallPlayoutMillis(0),
       _lastCallRecordMillis(0),
+      _outputFile(*FileWrapper::Create()),
+      _inputFile(*FileWrapper::Create()),
       _outputFilename(outputFilename),
       _inputFilename(inputFilename) {}
 
-FileAudioDevice::~FileAudioDevice() {}
+FileAudioDevice::~FileAudioDevice() {
+  delete &_outputFile;
+  delete &_inputFile;
+}
 
 int32_t FileAudioDevice::ActiveAudioLayer(
     AudioDeviceModule::AudioLayer& audioLayer) const {
@@ -205,15 +210,13 @@
   }
 
   // PLAYOUT
-  if (!_outputFilename.empty()) {
-    _outputFile = FileWrapper::OpenWriteOnly(_outputFilename.c_str());
-    if (!_outputFile.is_open()) {
-      RTC_LOG(LS_ERROR) << "Failed to open playout file: " << _outputFilename;
-      _playing = false;
-      delete[] _playoutBuffer;
-      _playoutBuffer = NULL;
-      return -1;
-    }
+  if (!_outputFilename.empty() &&
+      !_outputFile.OpenFile(_outputFilename.c_str(), false)) {
+    RTC_LOG(LS_ERROR) << "Failed to open playout file: " << _outputFilename;
+    _playing = false;
+    delete[] _playoutBuffer;
+    _playoutBuffer = NULL;
+    return -1;
   }
 
   _ptrThreadPlay.reset(new rtc::PlatformThread(
@@ -243,7 +246,7 @@
   _playoutFramesLeft = 0;
   delete[] _playoutBuffer;
   _playoutBuffer = NULL;
-  _outputFile.Close();
+  _outputFile.CloseFile();
 
   RTC_LOG(LS_INFO) << "Stopped playout capture to output file: "
                    << _outputFilename;
@@ -264,16 +267,13 @@
     _recordingBuffer = new int8_t[_recordingBufferSizeIn10MS];
   }
 
-  if (!_inputFilename.empty()) {
-    _inputFile = FileWrapper::OpenReadOnly(_inputFilename.c_str());
-    if (_inputFile.is_open()) {
-      RTC_LOG(LS_ERROR) << "Failed to open audio input file: "
-                        << _inputFilename;
-      _recording = false;
-      delete[] _recordingBuffer;
-      _recordingBuffer = NULL;
-      return -1;
-    }
+  if (!_inputFilename.empty() &&
+      !_inputFile.OpenFile(_inputFilename.c_str(), true)) {
+    RTC_LOG(LS_ERROR) << "Failed to open audio input file: " << _inputFilename;
+    _recording = false;
+    delete[] _recordingBuffer;
+    _recordingBuffer = NULL;
+    return -1;
   }
 
   _ptrThreadRec.reset(new rtc::PlatformThread(
@@ -304,7 +304,7 @@
     delete[] _recordingBuffer;
     _recordingBuffer = NULL;
   }
-  _inputFile.Close();
+  _inputFile.CloseFile();
 
   RTC_LOG(LS_INFO) << "Stopped recording from input file: " << _inputFilename;
   return 0;
diff --git a/modules/audio_device/dummy/file_audio_device.h b/modules/audio_device/dummy/file_audio_device.h
index 85dce07..375c6f6 100644
--- a/modules/audio_device/dummy/file_audio_device.h
+++ b/modules/audio_device/dummy/file_audio_device.h
@@ -154,8 +154,8 @@
   int64_t _lastCallPlayoutMillis;
   int64_t _lastCallRecordMillis;
 
-  FileWrapper _outputFile;
-  FileWrapper _inputFile;
+  FileWrapper& _outputFile;
+  FileWrapper& _inputFile;
   std::string _outputFilename;
   std::string _inputFilename;
 };
diff --git a/modules/audio_processing/aec_dump/aec_dump_impl.cc b/modules/audio_processing/aec_dump/aec_dump_impl.cc
index 588d24d..9020f2b 100644
--- a/modules/audio_processing/aec_dump/aec_dump_impl.cc
+++ b/modules/audio_processing/aec_dump/aec_dump_impl.cc
@@ -55,7 +55,7 @@
 
 }  // namespace
 
-AecDumpImpl::AecDumpImpl(FileWrapper debug_file,
+AecDumpImpl::AecDumpImpl(std::unique_ptr<FileWrapper> debug_file,
                          int64_t max_log_size_bytes,
                          rtc::TaskQueue* worker_queue)
     : debug_file_(std::move(debug_file)),
@@ -196,7 +196,7 @@
 }
 
 std::unique_ptr<WriteToFileTask> AecDumpImpl::CreateWriteToFileTask() {
-  return absl::make_unique<WriteToFileTask>(&debug_file_,
+  return absl::make_unique<WriteToFileTask>(debug_file_.get(),
                                             &num_bytes_left_for_log_);
 }
 
@@ -204,20 +204,24 @@
                                                 int64_t max_log_size_bytes,
                                                 rtc::TaskQueue* worker_queue) {
   RTC_DCHECK(worker_queue);
+  std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
   FILE* handle = rtc::FdopenPlatformFileForWriting(file);
   if (!handle) {
     return nullptr;
   }
-  return absl::make_unique<AecDumpImpl>(FileWrapper(handle), max_log_size_bytes,
-                                        worker_queue);
+  if (!debug_file->OpenFromFileHandle(handle)) {
+    return nullptr;
+  }
+  return absl::make_unique<AecDumpImpl>(std::move(debug_file),
+                                        max_log_size_bytes, worker_queue);
 }
 
 std::unique_ptr<AecDump> AecDumpFactory::Create(std::string file_name,
                                                 int64_t max_log_size_bytes,
                                                 rtc::TaskQueue* worker_queue) {
   RTC_DCHECK(worker_queue);
-  FileWrapper debug_file = FileWrapper::OpenWriteOnly(file_name.c_str());
-  if (!debug_file.is_open()) {
+  std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
+  if (!debug_file->OpenFile(file_name.c_str(), false)) {
     return nullptr;
   }
   return absl::make_unique<AecDumpImpl>(std::move(debug_file),
@@ -229,7 +233,11 @@
                                                 rtc::TaskQueue* worker_queue) {
   RTC_DCHECK(worker_queue);
   RTC_DCHECK(handle);
-  return absl::make_unique<AecDumpImpl>(FileWrapper(handle), max_log_size_bytes,
-                                        worker_queue);
+  std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
+  if (!debug_file->OpenFromFileHandle(handle)) {
+    return nullptr;
+  }
+  return absl::make_unique<AecDumpImpl>(std::move(debug_file),
+                                        max_log_size_bytes, worker_queue);
 }
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec_dump/aec_dump_impl.h b/modules/audio_processing/aec_dump/aec_dump_impl.h
index c247c1b..df949ca 100644
--- a/modules/audio_processing/aec_dump/aec_dump_impl.h
+++ b/modules/audio_processing/aec_dump/aec_dump_impl.h
@@ -46,7 +46,7 @@
 class AecDumpImpl : public AecDump {
  public:
   // Does member variables initialization shared across all c-tors.
-  AecDumpImpl(FileWrapper debug_file,
+  AecDumpImpl(std::unique_ptr<FileWrapper> debug_file,
               int64_t max_log_size_bytes,
               rtc::TaskQueue* worker_queue);
 
@@ -73,7 +73,7 @@
  private:
   std::unique_ptr<WriteToFileTask> CreateWriteToFileTask();
 
-  FileWrapper debug_file_;
+  std::unique_ptr<FileWrapper> debug_file_;
   int64_t num_bytes_left_for_log_ = 0;
   rtc::RaceChecker race_checker_;
   rtc::TaskQueue* worker_queue_;
diff --git a/modules/audio_processing/aec_dump/write_to_file_task.cc b/modules/audio_processing/aec_dump/write_to_file_task.cc
index d11f10b..8dddd47 100644
--- a/modules/audio_processing/aec_dump/write_to_file_task.cc
+++ b/modules/audio_processing/aec_dump/write_to_file_task.cc
@@ -39,15 +39,17 @@
 }
 
 bool WriteToFileTask::Run() {
+  if (!debug_file_->is_open()) {
+    return true;
+  }
+
   ProtoString event_string;
   event_.SerializeToString(&event_string);
 
   const size_t event_byte_size = event_.ByteSizeLong();
 
   if (!IsRoomForNextEvent(event_byte_size)) {
-    // Ensure that no further events are written, even if they're smaller than
-    // the current event.
-    *num_bytes_left_for_log_ = 0;
+    debug_file_->CloseFile();
     return true;
   }
 
diff --git a/modules/audio_processing/aec_dump/write_to_file_task.h b/modules/audio_processing/aec_dump/write_to_file_task.h
index 4b04a45..711afb2 100644
--- a/modules/audio_processing/aec_dump/write_to_file_task.h
+++ b/modules/audio_processing/aec_dump/write_to_file_task.h
@@ -48,9 +48,9 @@
 
   bool Run() override;
 
-  webrtc::FileWrapper* const debug_file_;
+  webrtc::FileWrapper* debug_file_;
   audioproc::Event event_;
-  int64_t* const num_bytes_left_for_log_;
+  int64_t* num_bytes_left_for_log_;
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/transient/click_annotate.cc b/modules/audio_processing/transient/click_annotate.cc
index 21641f8..ce646b5 100644
--- a/modules/audio_processing/transient/click_annotate.cc
+++ b/modules/audio_processing/transient/click_annotate.cc
@@ -39,14 +39,16 @@
     return 0;
   }
 
-  FileWrapper pcm_file = FileWrapper::OpenReadOnly(argv[1]);
-  if (!pcm_file.is_open()) {
+  std::unique_ptr<FileWrapper> pcm_file(FileWrapper::Create());
+  pcm_file->OpenFile(argv[1], true);
+  if (!pcm_file->is_open()) {
     printf("\nThe %s could not be opened.\n\n", argv[1]);
     return -1;
   }
 
-  FileWrapper dat_file = FileWrapper::OpenWriteOnly(argv[2]);
-  if (!dat_file.is_open()) {
+  std::unique_ptr<FileWrapper> dat_file(FileWrapper::Create());
+  dat_file->OpenFile(argv[2], false);
+  if (!dat_file->is_open()) {
     printf("\nThe %s could not be opened.\n\n", argv[2]);
     return -1;
   }
@@ -71,7 +73,7 @@
 
   // Read first buffer from the PCM test file.
   size_t file_samples_read = ReadInt16FromFileToFloatBuffer(
-      &pcm_file, audio_buffer_length, audio_buffer.get());
+      pcm_file.get(), audio_buffer_length, audio_buffer.get());
   for (int time = 0; file_samples_read > 0; time += chunk_size_ms) {
     // Pad the rest of the buffer with zeros.
     for (size_t i = file_samples_read; i < audio_buffer_length; ++i) {
@@ -89,19 +91,19 @@
 
     // Read next buffer from the PCM test file.
     file_samples_read = ReadInt16FromFileToFloatBuffer(
-        &pcm_file, audio_buffer_length, audio_buffer.get());
+        pcm_file.get(), audio_buffer_length, audio_buffer.get());
   }
 
   size_t floats_written =
-      WriteFloatBufferToFile(&dat_file, send_times.size(), &send_times[0]);
+      WriteFloatBufferToFile(dat_file.get(), send_times.size(), &send_times[0]);
 
   if (floats_written == 0) {
     printf("\nThe send times could not be written to DAT file\n\n");
     return -1;
   }
 
-  pcm_file.Close();
-  dat_file.Close();
+  pcm_file->CloseFile();
+  dat_file->CloseFile();
 
   return lost_packets;
 }
diff --git a/modules/audio_processing/transient/file_utils_unittest.cc b/modules/audio_processing/transient/file_utils_unittest.cc
index 0bded02..ced06b1 100644
--- a/modules/audio_processing/transient/file_utils_unittest.cc
+++ b/modules/audio_processing/transient/file_utils_unittest.cc
@@ -158,20 +158,22 @@
 TEST_F(TransientFileUtilsTest, MAYBE_ReadInt16BufferFromFile) {
   std::string test_filename = kTestFileName;
 
-  FileWrapper file = FileWrapper::OpenReadOnly(test_filename.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kTestFileName.c_str();
+  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
+
+  file->OpenFile(test_filename.c_str(), true);  // Read only.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kTestFileName.c_str();
 
   const size_t kBufferLength = 12;
   std::unique_ptr<int16_t[]> buffer(new int16_t[kBufferLength]);
 
   EXPECT_EQ(kBufferLength,
-            ReadInt16BufferFromFile(&file, kBufferLength, buffer.get()));
+            ReadInt16BufferFromFile(file.get(), kBufferLength, buffer.get()));
   EXPECT_EQ(22377, buffer[4]);
   EXPECT_EQ(16389, buffer[7]);
   EXPECT_EQ(17631, buffer[kBufferLength - 1]);
 
-  file.Rewind();
+  file->Rewind();
 
   // The next test is for checking the case where there are not as much data as
   // needed in the file, but reads to the end, and it returns the number of
@@ -179,7 +181,7 @@
   const size_t kBufferLenghtLargerThanFile = kBufferLength * 2;
   buffer.reset(new int16_t[kBufferLenghtLargerThanFile]);
   EXPECT_EQ(kBufferLength,
-            ReadInt16BufferFromFile(&file, kBufferLenghtLargerThanFile,
+            ReadInt16BufferFromFile(file.get(), kBufferLenghtLargerThanFile,
                                     buffer.get()));
   EXPECT_EQ(11544, buffer[0]);
   EXPECT_EQ(22377, buffer[4]);
@@ -196,22 +198,24 @@
 TEST_F(TransientFileUtilsTest, MAYBE_ReadInt16FromFileToFloatBuffer) {
   std::string test_filename = kTestFileName;
 
-  FileWrapper file = FileWrapper::OpenReadOnly(test_filename.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kTestFileName.c_str();
+  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
+
+  file->OpenFile(test_filename.c_str(), true);  // Read only.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kTestFileName.c_str();
 
   const size_t kBufferLength = 12;
   std::unique_ptr<float[]> buffer(new float[kBufferLength]);
 
-  EXPECT_EQ(kBufferLength,
-            ReadInt16FromFileToFloatBuffer(&file, kBufferLength, buffer.get()));
+  EXPECT_EQ(kBufferLength, ReadInt16FromFileToFloatBuffer(
+                               file.get(), kBufferLength, buffer.get()));
 
   EXPECT_DOUBLE_EQ(11544, buffer[0]);
   EXPECT_DOUBLE_EQ(22377, buffer[4]);
   EXPECT_DOUBLE_EQ(16389, buffer[7]);
   EXPECT_DOUBLE_EQ(17631, buffer[kBufferLength - 1]);
 
-  file.Rewind();
+  file->Rewind();
 
   // The next test is for checking the case where there are not as much data as
   // needed in the file, but reads to the end, and it returns the number of
@@ -219,8 +223,8 @@
   const size_t kBufferLenghtLargerThanFile = kBufferLength * 2;
   buffer.reset(new float[kBufferLenghtLargerThanFile]);
   EXPECT_EQ(kBufferLength,
-            ReadInt16FromFileToFloatBuffer(&file, kBufferLenghtLargerThanFile,
-                                           buffer.get()));
+            ReadInt16FromFileToFloatBuffer(
+                file.get(), kBufferLenghtLargerThanFile, buffer.get()));
   EXPECT_DOUBLE_EQ(11544, buffer[0]);
   EXPECT_DOUBLE_EQ(22377, buffer[4]);
   EXPECT_DOUBLE_EQ(16389, buffer[7]);
@@ -236,21 +240,23 @@
 TEST_F(TransientFileUtilsTest, MAYBE_ReadInt16FromFileToDoubleBuffer) {
   std::string test_filename = kTestFileName;
 
-  FileWrapper file = FileWrapper::OpenReadOnly(test_filename.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kTestFileName.c_str();
+  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
+
+  file->OpenFile(test_filename.c_str(), true);  // Read only.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kTestFileName.c_str();
 
   const size_t kBufferLength = 12;
   std::unique_ptr<double[]> buffer(new double[kBufferLength]);
 
-  EXPECT_EQ(kBufferLength, ReadInt16FromFileToDoubleBuffer(&file, kBufferLength,
-                                                           buffer.get()));
+  EXPECT_EQ(kBufferLength, ReadInt16FromFileToDoubleBuffer(
+                               file.get(), kBufferLength, buffer.get()));
   EXPECT_DOUBLE_EQ(11544, buffer[0]);
   EXPECT_DOUBLE_EQ(22377, buffer[4]);
   EXPECT_DOUBLE_EQ(16389, buffer[7]);
   EXPECT_DOUBLE_EQ(17631, buffer[kBufferLength - 1]);
 
-  file.Rewind();
+  file->Rewind();
 
   // The next test is for checking the case where there are not as much data as
   // needed in the file, but reads to the end, and it returns the number of
@@ -258,8 +264,8 @@
   const size_t kBufferLenghtLargerThanFile = kBufferLength * 2;
   buffer.reset(new double[kBufferLenghtLargerThanFile]);
   EXPECT_EQ(kBufferLength,
-            ReadInt16FromFileToDoubleBuffer(&file, kBufferLenghtLargerThanFile,
-                                            buffer.get()));
+            ReadInt16FromFileToDoubleBuffer(
+                file.get(), kBufferLenghtLargerThanFile, buffer.get()));
   EXPECT_DOUBLE_EQ(11544, buffer[0]);
   EXPECT_DOUBLE_EQ(22377, buffer[4]);
   EXPECT_DOUBLE_EQ(16389, buffer[7]);
@@ -274,20 +280,22 @@
 TEST_F(TransientFileUtilsTest, MAYBE_ReadFloatBufferFromFile) {
   std::string test_filename = kTestFileNamef;
 
-  FileWrapper file = FileWrapper::OpenReadOnly(test_filename.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kTestFileNamef.c_str();
+  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
+
+  file->OpenFile(test_filename.c_str(), true);  // Read only.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kTestFileNamef.c_str();
 
   const size_t kBufferLength = 3;
   std::unique_ptr<float[]> buffer(new float[kBufferLength]);
 
   EXPECT_EQ(kBufferLength,
-            ReadFloatBufferFromFile(&file, kBufferLength, buffer.get()));
+            ReadFloatBufferFromFile(file.get(), kBufferLength, buffer.get()));
   EXPECT_FLOAT_EQ(kPi, buffer[0]);
   EXPECT_FLOAT_EQ(kE, buffer[1]);
   EXPECT_FLOAT_EQ(kAvogadro, buffer[2]);
 
-  file.Rewind();
+  file->Rewind();
 
   // The next test is for checking the case where there are not as much data as
   // needed in the file, but reads to the end, and it returns the number of
@@ -295,7 +303,7 @@
   const size_t kBufferLenghtLargerThanFile = kBufferLength * 2;
   buffer.reset(new float[kBufferLenghtLargerThanFile]);
   EXPECT_EQ(kBufferLength,
-            ReadFloatBufferFromFile(&file, kBufferLenghtLargerThanFile,
+            ReadFloatBufferFromFile(file.get(), kBufferLenghtLargerThanFile,
                                     buffer.get()));
   EXPECT_FLOAT_EQ(kPi, buffer[0]);
   EXPECT_FLOAT_EQ(kE, buffer[1]);
@@ -310,20 +318,22 @@
 TEST_F(TransientFileUtilsTest, MAYBE_ReadDoubleBufferFromFile) {
   std::string test_filename = kTestFileName;
 
-  FileWrapper file = FileWrapper::OpenReadOnly(test_filename.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kTestFileName.c_str();
+  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
+
+  file->OpenFile(test_filename.c_str(), true);  // Read only.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kTestFileName.c_str();
 
   const size_t kBufferLength = 3;
   std::unique_ptr<double[]> buffer(new double[kBufferLength]);
 
   EXPECT_EQ(kBufferLength,
-            ReadDoubleBufferFromFile(&file, kBufferLength, buffer.get()));
+            ReadDoubleBufferFromFile(file.get(), kBufferLength, buffer.get()));
   EXPECT_DOUBLE_EQ(kPi, buffer[0]);
   EXPECT_DOUBLE_EQ(kE, buffer[1]);
   EXPECT_DOUBLE_EQ(kAvogadro, buffer[2]);
 
-  file.Rewind();
+  file->Rewind();
 
   // The next test is for checking the case where there are not as much data as
   // needed in the file, but reads to the end, and it returns the number of
@@ -331,7 +341,7 @@
   const size_t kBufferLenghtLargerThanFile = kBufferLength * 2;
   buffer.reset(new double[kBufferLenghtLargerThanFile]);
   EXPECT_EQ(kBufferLength,
-            ReadDoubleBufferFromFile(&file, kBufferLenghtLargerThanFile,
+            ReadDoubleBufferFromFile(file.get(), kBufferLenghtLargerThanFile,
                                      buffer.get()));
   EXPECT_DOUBLE_EQ(kPi, buffer[0]);
   EXPECT_DOUBLE_EQ(kE, buffer[1]);
@@ -344,12 +354,14 @@
 #define MAYBE_WriteInt16BufferToFile WriteInt16BufferToFile
 #endif
 TEST_F(TransientFileUtilsTest, MAYBE_WriteInt16BufferToFile) {
+  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
+
   std::string kOutFileName =
       CreateTempFilename(test::OutputPath(), "utils_test");
 
-  FileWrapper file = FileWrapper::OpenWriteOnly(kOutFileName.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kOutFileName.c_str();
+  file->OpenFile(kOutFileName.c_str(), false);  // Write mode.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kOutFileName.c_str();
 
   const size_t kBufferLength = 3;
   std::unique_ptr<int16_t[]> written_buffer(new int16_t[kBufferLength]);
@@ -359,17 +371,17 @@
   written_buffer[1] = 2;
   written_buffer[2] = 3;
 
-  EXPECT_EQ(kBufferLength,
-            WriteInt16BufferToFile(&file, kBufferLength, written_buffer.get()));
+  EXPECT_EQ(kBufferLength, WriteInt16BufferToFile(file.get(), kBufferLength,
+                                                  written_buffer.get()));
 
-  file.Close();
+  file->CloseFile();
 
-  file = FileWrapper::OpenReadOnly(kOutFileName.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kOutFileName.c_str();
+  file->OpenFile(kOutFileName.c_str(), true);  // Read only.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kOutFileName.c_str();
 
-  EXPECT_EQ(kBufferLength,
-            ReadInt16BufferFromFile(&file, kBufferLength, read_buffer.get()));
+  EXPECT_EQ(kBufferLength, ReadInt16BufferFromFile(file.get(), kBufferLength,
+                                                   read_buffer.get()));
   EXPECT_EQ(0, memcmp(written_buffer.get(), read_buffer.get(),
                       kBufferLength * sizeof(written_buffer[0])));
 }
@@ -380,12 +392,14 @@
 #define MAYBE_WriteFloatBufferToFile WriteFloatBufferToFile
 #endif
 TEST_F(TransientFileUtilsTest, MAYBE_WriteFloatBufferToFile) {
+  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
+
   std::string kOutFileName =
       CreateTempFilename(test::OutputPath(), "utils_test");
 
-  FileWrapper file = FileWrapper::OpenWriteOnly(kOutFileName.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kOutFileName.c_str();
+  file->OpenFile(kOutFileName.c_str(), false);  // Write mode.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kOutFileName.c_str();
 
   const size_t kBufferLength = 3;
   std::unique_ptr<float[]> written_buffer(new float[kBufferLength]);
@@ -395,17 +409,17 @@
   written_buffer[1] = static_cast<float>(kE);
   written_buffer[2] = static_cast<float>(kAvogadro);
 
-  EXPECT_EQ(kBufferLength,
-            WriteFloatBufferToFile(&file, kBufferLength, written_buffer.get()));
+  EXPECT_EQ(kBufferLength, WriteFloatBufferToFile(file.get(), kBufferLength,
+                                                  written_buffer.get()));
 
-  file.Close();
+  file->CloseFile();
 
-  file = FileWrapper::OpenReadOnly(kOutFileName.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kOutFileName.c_str();
+  file->OpenFile(kOutFileName.c_str(), true);  // Read only.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kOutFileName.c_str();
 
-  EXPECT_EQ(kBufferLength,
-            ReadFloatBufferFromFile(&file, kBufferLength, read_buffer.get()));
+  EXPECT_EQ(kBufferLength, ReadFloatBufferFromFile(file.get(), kBufferLength,
+                                                   read_buffer.get()));
   EXPECT_EQ(0, memcmp(written_buffer.get(), read_buffer.get(),
                       kBufferLength * sizeof(written_buffer[0])));
 }
@@ -416,12 +430,14 @@
 #define MAYBE_WriteDoubleBufferToFile WriteDoubleBufferToFile
 #endif
 TEST_F(TransientFileUtilsTest, MAYBE_WriteDoubleBufferToFile) {
+  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
+
   std::string kOutFileName =
       CreateTempFilename(test::OutputPath(), "utils_test");
 
-  FileWrapper file = FileWrapper::OpenWriteOnly(kOutFileName.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kOutFileName.c_str();
+  file->OpenFile(kOutFileName.c_str(), false);  // Write mode.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kOutFileName.c_str();
 
   const size_t kBufferLength = 3;
   std::unique_ptr<double[]> written_buffer(new double[kBufferLength]);
@@ -431,17 +447,17 @@
   written_buffer[1] = kE;
   written_buffer[2] = kAvogadro;
 
-  EXPECT_EQ(kBufferLength, WriteDoubleBufferToFile(&file, kBufferLength,
+  EXPECT_EQ(kBufferLength, WriteDoubleBufferToFile(file.get(), kBufferLength,
                                                    written_buffer.get()));
 
-  file.Close();
+  file->CloseFile();
 
-  file = FileWrapper::OpenReadOnly(kOutFileName.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kOutFileName.c_str();
+  file->OpenFile(kOutFileName.c_str(), true);  // Read only.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kOutFileName.c_str();
 
-  EXPECT_EQ(kBufferLength,
-            ReadDoubleBufferFromFile(&file, kBufferLength, read_buffer.get()));
+  EXPECT_EQ(kBufferLength, ReadDoubleBufferFromFile(file.get(), kBufferLength,
+                                                    read_buffer.get()));
   EXPECT_EQ(0, memcmp(written_buffer.get(), read_buffer.get(),
                       kBufferLength * sizeof(written_buffer[0])));
 }
@@ -457,7 +473,7 @@
   double value;
   std::unique_ptr<int16_t[]> int16_buffer(new int16_t[1]);
   std::unique_ptr<double[]> double_buffer(new double[1]);
-  FileWrapper file;
+  std::unique_ptr<FileWrapper> file(FileWrapper::Create());
 
   EXPECT_EQ(-1, ConvertByteArrayToDouble(NULL, &value));
   EXPECT_EQ(-1, ConvertByteArrayToDouble(kPiBytes, NULL));
@@ -465,35 +481,37 @@
   EXPECT_EQ(-1, ConvertDoubleToByteArray(kPi, NULL));
 
   // Tests with file not opened.
-  EXPECT_EQ(0u, ReadInt16BufferFromFile(&file, 1, int16_buffer.get()));
-  EXPECT_EQ(0u, ReadInt16FromFileToDoubleBuffer(&file, 1, double_buffer.get()));
-  EXPECT_EQ(0u, ReadDoubleBufferFromFile(&file, 1, double_buffer.get()));
-  EXPECT_EQ(0u, WriteInt16BufferToFile(&file, 1, int16_buffer.get()));
-  EXPECT_EQ(0u, WriteDoubleBufferToFile(&file, 1, double_buffer.get()));
+  EXPECT_EQ(0u, ReadInt16BufferFromFile(file.get(), 1, int16_buffer.get()));
+  EXPECT_EQ(
+      0u, ReadInt16FromFileToDoubleBuffer(file.get(), 1, double_buffer.get()));
+  EXPECT_EQ(0u, ReadDoubleBufferFromFile(file.get(), 1, double_buffer.get()));
+  EXPECT_EQ(0u, WriteInt16BufferToFile(file.get(), 1, int16_buffer.get()));
+  EXPECT_EQ(0u, WriteDoubleBufferToFile(file.get(), 1, double_buffer.get()));
 
-  file = FileWrapper::OpenReadOnly(test_filename.c_str());
-  ASSERT_TRUE(file.is_open()) << "File could not be opened:\n"
-                              << kTestFileName.c_str();
+  file->OpenFile(test_filename.c_str(), true);  // Read only.
+  ASSERT_TRUE(file->is_open()) << "File could not be opened:\n"
+                               << kTestFileName.c_str();
 
   EXPECT_EQ(0u, ReadInt16BufferFromFile(NULL, 1, int16_buffer.get()));
-  EXPECT_EQ(0u, ReadInt16BufferFromFile(&file, 1, NULL));
-  EXPECT_EQ(0u, ReadInt16BufferFromFile(&file, 0, int16_buffer.get()));
+  EXPECT_EQ(0u, ReadInt16BufferFromFile(file.get(), 1, NULL));
+  EXPECT_EQ(0u, ReadInt16BufferFromFile(file.get(), 0, int16_buffer.get()));
 
   EXPECT_EQ(0u, ReadInt16FromFileToDoubleBuffer(NULL, 1, double_buffer.get()));
-  EXPECT_EQ(0u, ReadInt16FromFileToDoubleBuffer(&file, 1, NULL));
-  EXPECT_EQ(0u, ReadInt16FromFileToDoubleBuffer(&file, 0, double_buffer.get()));
+  EXPECT_EQ(0u, ReadInt16FromFileToDoubleBuffer(file.get(), 1, NULL));
+  EXPECT_EQ(
+      0u, ReadInt16FromFileToDoubleBuffer(file.get(), 0, double_buffer.get()));
 
   EXPECT_EQ(0u, ReadDoubleBufferFromFile(NULL, 1, double_buffer.get()));
-  EXPECT_EQ(0u, ReadDoubleBufferFromFile(&file, 1, NULL));
-  EXPECT_EQ(0u, ReadDoubleBufferFromFile(&file, 0, double_buffer.get()));
+  EXPECT_EQ(0u, ReadDoubleBufferFromFile(file.get(), 1, NULL));
+  EXPECT_EQ(0u, ReadDoubleBufferFromFile(file.get(), 0, double_buffer.get()));
 
   EXPECT_EQ(0u, WriteInt16BufferToFile(NULL, 1, int16_buffer.get()));
-  EXPECT_EQ(0u, WriteInt16BufferToFile(&file, 1, NULL));
-  EXPECT_EQ(0u, WriteInt16BufferToFile(&file, 0, int16_buffer.get()));
+  EXPECT_EQ(0u, WriteInt16BufferToFile(file.get(), 1, NULL));
+  EXPECT_EQ(0u, WriteInt16BufferToFile(file.get(), 0, int16_buffer.get()));
 
   EXPECT_EQ(0u, WriteDoubleBufferToFile(NULL, 1, double_buffer.get()));
-  EXPECT_EQ(0u, WriteDoubleBufferToFile(&file, 1, NULL));
-  EXPECT_EQ(0u, WriteDoubleBufferToFile(&file, 0, double_buffer.get()));
+  EXPECT_EQ(0u, WriteDoubleBufferToFile(file.get(), 1, NULL));
+  EXPECT_EQ(0u, WriteDoubleBufferToFile(file.get(), 0, double_buffer.get()));
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/transient/transient_detector_unittest.cc b/modules/audio_processing/transient/transient_detector_unittest.cc
index 0425133..11dd8aa 100644
--- a/modules/audio_processing/transient/transient_detector_unittest.cc
+++ b/modules/audio_processing/transient/transient_detector_unittest.cc
@@ -47,10 +47,13 @@
     detect_file_name << "audio_processing/transient/detect"
                      << (sample_rate_hz / 1000) << "kHz";
 
-    FileWrapper detect_file = FileWrapper::OpenReadOnly(
-        test::ResourcePath(detect_file_name.str(), "dat").c_str());
+    std::unique_ptr<FileWrapper> detect_file(FileWrapper::Create());
 
-    bool file_opened = detect_file.is_open();
+    detect_file->OpenFile(
+        test::ResourcePath(detect_file_name.str(), "dat").c_str(),
+        true);  // Read only.
+
+    bool file_opened = detect_file->is_open();
     ASSERT_TRUE(file_opened) << "File could not be opened.\n"
                              << detect_file_name.str().c_str();
 
@@ -59,8 +62,11 @@
     audio_file_name << "audio_processing/transient/audio"
                     << (sample_rate_hz / 1000) << "kHz";
 
-    FileWrapper audio_file = FileWrapper::OpenReadOnly(
-        test::ResourcePath(audio_file_name.str(), "pcm").c_str());
+    std::unique_ptr<FileWrapper> audio_file(FileWrapper::Create());
+
+    audio_file->OpenFile(
+        test::ResourcePath(audio_file_name.str(), "pcm").c_str(),
+        true);  // Read only.
 
     // Create detector.
     TransientDetector detector(sample_rate_hz);
@@ -72,14 +78,14 @@
 
     size_t frames_read = 0;
 
-    while (ReadInt16FromFileToFloatBuffer(&audio_file, buffer_length,
+    while (ReadInt16FromFileToFloatBuffer(audio_file.get(), buffer_length,
                                           buffer.get()) == buffer_length) {
       ++frames_read;
 
       float detector_value =
           detector.Detect(buffer.get(), buffer_length, NULL, 0);
       double file_value;
-      ASSERT_EQ(1u, ReadDoubleBufferFromFile(&detect_file, 1, &file_value))
+      ASSERT_EQ(1u, ReadDoubleBufferFromFile(detect_file.get(), 1, &file_value))
           << "Detect test file is malformed.\n";
 
       // Compare results with data from the matlab test file.
@@ -87,8 +93,8 @@
           << "Frame: " << frames_read;
     }
 
-    detect_file.Close();
-    audio_file.Close();
+    detect_file->CloseFile();
+    audio_file->CloseFile();
   }
 }
 
diff --git a/modules/audio_processing/transient/wpd_tree_unittest.cc b/modules/audio_processing/transient/wpd_tree_unittest.cc
index 11f75e6..1d6dbe8 100644
--- a/modules/audio_processing/transient/wpd_tree_unittest.cc
+++ b/modules/audio_processing/transient/wpd_tree_unittest.cc
@@ -80,27 +80,31 @@
                kDaubechies8LowPassCoefficients, kDaubechies8CoefficientsLength,
                kLevels);
   // Allocate and open all matlab and out files.
-  FileWrapper matlab_files_data[kLeaves];
-  FileWrapper out_files_data[kLeaves];
+  std::unique_ptr<FileWrapper> matlab_files_data[kLeaves];
+  std::unique_ptr<FileWrapper> out_files_data[kLeaves];
 
   for (int i = 0; i < kLeaves; ++i) {
     // Matlab files.
+    matlab_files_data[i].reset(FileWrapper::Create());
+
     rtc::StringBuilder matlab_stream;
     matlab_stream << "audio_processing/transient/wpd" << i;
     std::string matlab_string = test::ResourcePath(matlab_stream.str(), "dat");
-    matlab_files_data[i] = FileWrapper::OpenReadOnly(matlab_string.c_str());
+    matlab_files_data[i]->OpenFile(matlab_string.c_str(), true);  // Read only.
 
-    bool file_opened = matlab_files_data[i].is_open();
+    bool file_opened = matlab_files_data[i]->is_open();
     ASSERT_TRUE(file_opened) << "File could not be opened.\n" << matlab_string;
 
     // Out files.
+    out_files_data[i].reset(FileWrapper::Create());
+
     rtc::StringBuilder out_stream;
     out_stream << test::OutputPath() << "wpd_" << i << ".out";
     std::string out_string = out_stream.str();
 
-    out_files_data[i] = FileWrapper::OpenWriteOnly(out_string.c_str());
+    out_files_data[i]->OpenFile(out_string.c_str(), false);  // Write mode.
 
-    file_opened = out_files_data[i].is_open();
+    file_opened = out_files_data[i]->is_open();
     ASSERT_TRUE(file_opened) << "File could not be opened.\n" << out_string;
   }
 
@@ -108,9 +112,11 @@
   std::string test_file_name = test::ResourcePath(
       "audio_processing/transient/ajm-macbook-1-spke16m", "pcm");
 
-  FileWrapper test_file = FileWrapper::OpenReadOnly(test_file_name.c_str());
+  std::unique_ptr<FileWrapper> test_file(FileWrapper::Create());
 
-  bool file_opened = test_file.is_open();
+  test_file->OpenFile(test_file_name.c_str(), true);  // Read only.
+
+  bool file_opened = test_file->is_open();
   ASSERT_TRUE(file_opened) << "File could not be opened.\n" << test_file_name;
 
   float test_buffer[kTestBufferSize];
@@ -123,8 +129,8 @@
   size_t frames_read = 0;
 
   // Read first buffer from the PCM test file.
-  size_t file_samples_read =
-      ReadInt16FromFileToFloatBuffer(&test_file, kTestBufferSize, test_buffer);
+  size_t file_samples_read = ReadInt16FromFileToFloatBuffer(
+      test_file.get(), kTestBufferSize, test_buffer);
   while (file_samples_read > 0 && frames_read < kMaxFramesToTest) {
     ++frames_read;
 
@@ -141,7 +147,7 @@
     for (int i = 0; i < kLeaves; ++i) {
       // Compare data values
       size_t matlab_samples_read = ReadDoubleBufferFromFile(
-          &matlab_files_data[i], kLeavesSamples, matlab_buffer);
+          matlab_files_data[i].get(), kLeavesSamples, matlab_buffer);
 
       ASSERT_EQ(kLeavesSamples, matlab_samples_read)
           << "Matlab test files are malformed.\n"
@@ -156,21 +162,22 @@
       }
 
       // Write results to out files.
-      WriteFloatBufferToFile(&out_files_data[i], kLeavesSamples, node_data);
+      WriteFloatBufferToFile(out_files_data[i].get(), kLeavesSamples,
+                             node_data);
     }
 
     // Read next buffer from the PCM test file.
     file_samples_read = ReadInt16FromFileToFloatBuffer(
-        &test_file, kTestBufferSize, test_buffer);
+        test_file.get(), kTestBufferSize, test_buffer);
   }
 
   // Close all matlab and out files.
   for (int i = 0; i < kLeaves; ++i) {
-    matlab_files_data[i].Close();
-    out_files_data[i].Close();
+    matlab_files_data[i]->CloseFile();
+    out_files_data[i]->CloseFile();
   }
 
-  test_file.Close();
+  test_file->CloseFile();
 }
 
 }  // namespace webrtc
diff --git a/rtc_base/system/file_wrapper.cc b/rtc_base/system/file_wrapper.cc
index dbea1ca..c033a79 100644
--- a/rtc_base/system/file_wrapper.cc
+++ b/rtc_base/system/file_wrapper.cc
@@ -34,13 +34,22 @@
 }  // namespace
 
 // static
-FileWrapper FileWrapper::OpenReadOnly(const char* file_name_utf8) {
-  return FileWrapper(FileOpen(file_name_utf8, true));
+FileWrapper* FileWrapper::Create() {
+  return new FileWrapper();
 }
 
 // static
-FileWrapper FileWrapper::OpenWriteOnly(const char* file_name_utf8) {
-  return FileWrapper(FileOpen(file_name_utf8, false));
+FileWrapper FileWrapper::Open(const char* file_name_utf8, bool read_only) {
+  return FileWrapper(FileOpen(file_name_utf8, read_only), 0);
+}
+
+FileWrapper::FileWrapper() {}
+
+FileWrapper::FileWrapper(FILE* file, size_t max_size)
+    : file_(file), max_size_in_bytes_(max_size) {}
+
+FileWrapper::~FileWrapper() {
+  CloseFileImpl();
 }
 
 FileWrapper::FileWrapper(FileWrapper&& other) {
@@ -48,39 +57,95 @@
 }
 
 FileWrapper& FileWrapper::operator=(FileWrapper&& other) {
-  Close();
   file_ = other.file_;
+  max_size_in_bytes_ = other.max_size_in_bytes_;
+  position_ = other.position_;
   other.file_ = nullptr;
   return *this;
 }
 
-bool FileWrapper::Rewind() {
-  RTC_DCHECK(file_);
-  return fseek(file_, 0, SEEK_SET) == 0;
+void FileWrapper::CloseFile() {
+  rtc::CritScope lock(&lock_);
+  CloseFileImpl();
 }
 
-bool FileWrapper::Flush() {
-  RTC_DCHECK(file_);
-  return fflush(file_) == 0;
+int FileWrapper::Rewind() {
+  rtc::CritScope lock(&lock_);
+  if (file_ != nullptr) {
+    position_ = 0;
+    return fseek(file_, 0, SEEK_SET);
+  }
+  return -1;
 }
 
-size_t FileWrapper::Read(void* buf, size_t length) {
-  RTC_DCHECK(file_);
-  return fread(buf, 1, length, file_);
+void FileWrapper::SetMaxFileSize(size_t bytes) {
+  rtc::CritScope lock(&lock_);
+  max_size_in_bytes_ = bytes;
+}
+
+int FileWrapper::Flush() {
+  rtc::CritScope lock(&lock_);
+  return FlushImpl();
+}
+
+bool FileWrapper::OpenFile(const char* file_name_utf8, bool read_only) {
+  size_t length = strlen(file_name_utf8);
+  if (length > kMaxFileNameSize - 1)
+    return false;
+
+  rtc::CritScope lock(&lock_);
+  if (file_ != nullptr)
+    return false;
+
+  file_ = FileOpen(file_name_utf8, read_only);
+  return file_ != nullptr;
+}
+
+bool FileWrapper::OpenFromFileHandle(FILE* handle) {
+  if (!handle)
+    return false;
+  rtc::CritScope lock(&lock_);
+  CloseFileImpl();
+  file_ = handle;
+  return true;
+}
+
+int FileWrapper::Read(void* buf, size_t length) {
+  rtc::CritScope lock(&lock_);
+  if (file_ == nullptr)
+    return -1;
+
+  size_t bytes_read = fread(buf, 1, length, file_);
+  return static_cast<int>(bytes_read);
 }
 
 bool FileWrapper::Write(const void* buf, size_t length) {
-  RTC_DCHECK(file_);
-  return fwrite(buf, 1, length, file_) == length;
+  if (buf == nullptr)
+    return false;
+
+  rtc::CritScope lock(&lock_);
+
+  if (file_ == nullptr)
+    return false;
+
+  // Check if it's time to stop writing.
+  if (max_size_in_bytes_ > 0 && (position_ + length) > max_size_in_bytes_)
+    return false;
+
+  size_t num_bytes = fwrite(buf, 1, length, file_);
+  position_ += num_bytes;
+
+  return num_bytes == length;
 }
 
-bool FileWrapper::Close() {
-  if (file_ == nullptr)
-    return true;
-
-  bool success = fclose(file_) == 0;
+void FileWrapper::CloseFileImpl() {
+  if (file_ != nullptr)
+    fclose(file_);
   file_ = nullptr;
-  return success;
+}
+
+int FileWrapper::FlushImpl() {
+  return (file_ != nullptr) ? fflush(file_) : -1;
 }
 
 }  // namespace webrtc
diff --git a/rtc_base/system/file_wrapper.h b/rtc_base/system/file_wrapper.h
index d56e131..f2ed51a 100644
--- a/rtc_base/system/file_wrapper.h
+++ b/rtc_base/system/file_wrapper.h
@@ -20,57 +20,64 @@
 
 namespace webrtc {
 
+// TODO(tommi): Rename to rtc::File and move to base.
 class FileWrapper final {
  public:
-  // Opens a file, in read or write mode. Use the is_open() method on the
-  // returned object to check if the open operation was successful. The file is
-  // closed by the destructor.
-  static FileWrapper OpenReadOnly(const char* file_name_utf8);
-  static FileWrapper OpenWriteOnly(const char* file_name_utf8);
+  static const size_t kMaxFileNameSize = 1024;
 
-  FileWrapper() = default;
+  // Factory methods.
+  // TODO(tommi): Remove Create().
+  static FileWrapper* Create();
+  static FileWrapper Open(const char* file_name_utf8, bool read_only);
 
-  // Takes over ownership of |file|, closing it on destruction.
-  explicit FileWrapper(FILE* file) : file_(file) {}
-  ~FileWrapper() { Close(); }
+  FileWrapper(FILE* file, size_t max_size);
+  ~FileWrapper();
+
+  // Support for move semantics.
+  FileWrapper(FileWrapper&& other);
+  FileWrapper& operator=(FileWrapper&& other);
+
+  // Returns true if a file has been opened.
+  bool is_open() const { return file_ != nullptr; }
+
+  // Opens a file in read or write mode, decided by the read_only parameter.
+  bool OpenFile(const char* file_name_utf8, bool read_only);
+
+  // Initializes the wrapper from an existing handle.  The wrapper
+  // takes ownership of |handle| and closes it in CloseFile().
+  bool OpenFromFileHandle(FILE* handle);
+
+  void CloseFile();
+
+  // Limits the file size to |bytes|. Writing will fail after the cap
+  // is hit. Pass zero to use an unlimited size.
+  // TODO(tommi): Could we move this out into a separate class?
+  void SetMaxFileSize(size_t bytes);
+
+  // Flush any pending writes.  Note: Flushing when closing, is not required.
+  int Flush();
+
+  // Rewinds the file to the start.
+  int Rewind();
+  int Read(void* buf, size_t length);
+  bool Write(const void* buf, size_t length);
+
+ private:
+  FileWrapper();
+
+  void CloseFileImpl();
+  int FlushImpl();
+
+  // TODO(tommi): Remove the lock.
+  rtc::CriticalSection lock_;
+
+  FILE* file_ = nullptr;
+  size_t position_ = 0;
+  size_t max_size_in_bytes_ = 0;
 
   // Copying is not supported.
   FileWrapper(const FileWrapper&) = delete;
   FileWrapper& operator=(const FileWrapper&) = delete;
-
-  // Support for move semantics.
-  FileWrapper(FileWrapper&&);
-  FileWrapper& operator=(FileWrapper&&);
-
-  // Returns true if a file has been opened. If the file is not open, no methods
-  // but is_open and Close may be called.
-  bool is_open() const { return file_ != nullptr; }
-
-  // Closes the file, and implies Flush. Returns true on success, false if
-  // writing buffered data fails. On failure, the file is nevertheless closed.
-  // Calling Close on an already closed file does nothing and returns success.
-  bool Close();
-
-  // Write any buffered data to the underlying file. Returns true on success,
-  // false on write error. Note: Flushing when closing, is not required.
-  // TODO(nisse): Delete this method.
-  bool Flush();
-
-  // Seeks to the beginning of file. Returns true on success, false on failure,
-  // e.g., if the underlying file isn't seekable.
-  // TODO(nisse): Delete this method.
-  bool Rewind();
-
-  // Returns number of bytes read. Short count indicates EOF or error.
-  size_t Read(void* buf, size_t length);
-
-  // Returns true if all data was successfully written (or buffered), or false
-  // if there was an error. Writing buffered data can fail later, and is
-  // reported with return value from Flush or Close.
-  bool Write(const void* buf, size_t length);
-
- private:
-  FILE* file_ = nullptr;
 };
 
 }  // namespace webrtc