Move and rename FdopenPlatformFile to file_util

This CL also improves error handling and adds a unit test.

BUG=322664

Review URL: https://codereview.chromium.org/319543004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275986 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/file_util.h b/base/file_util.h
index 9c9072f..bb04e62 100644
--- a/base/file_util.h
+++ b/base/file_util.h
@@ -308,6 +308,10 @@
 // Closes file opened by OpenFile. Returns true on success.
 BASE_EXPORT bool CloseFile(FILE* file);
 
+// Associates a standard FILE stream with an existing File. Note that this
+// functions take ownership of the existing File.
+BASE_EXPORT FILE* FileToFILE(File file, const char* mode);
+
 // Truncates an open file to end at the location of the current file pointer.
 // This is a cross-platform analog to Windows' SetEndOfFile() function.
 BASE_EXPORT bool TruncateFile(FILE* file);
diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc
index d9328ee7..92e8cad 100644
--- a/base/file_util_posix.cc
+++ b/base/file_util_posix.cc
@@ -654,6 +654,16 @@
   return result;
 }
 
+// NaCl doesn't implement system calls to open files directly.
+#if !defined(OS_NACL)
+FILE* FileToFILE(File file, const char* mode) {
+  FILE* stream = fdopen(file.GetPlatformFile(), mode);
+  if (stream)
+    file.TakePlatformFile();
+  return stream;
+}
+#endif  // !defined(OS_NACL)
+
 int ReadFile(const FilePath& filename, char* data, int max_size) {
   ThreadRestrictions::AssertIOAllowed();
   int fd = HANDLE_EINTR(open(filename.value().c_str(), O_RDONLY));
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index 83f211f5..239563d 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -1685,6 +1685,21 @@
   }
 }
 
+TEST_F(FileUtilTest, FileToFILE) {
+  File file;
+  FILE* stream = FileToFILE(file.Pass(), "w");
+  EXPECT_FALSE(stream);
+
+  FilePath file_name = temp_dir_.path().Append(FPL("The file.txt"));
+  file = File(file_name, File::FLAG_CREATE | File::FLAG_WRITE);
+  EXPECT_TRUE(file.IsValid());
+
+  stream = FileToFILE(file.Pass(), "w");
+  EXPECT_TRUE(stream);
+  EXPECT_FALSE(file.IsValid());
+  EXPECT_TRUE(CloseFile(stream));
+}
+
 TEST_F(FileUtilTest, CreateNewTempDirectoryTest) {
   FilePath temp_dir;
   ASSERT_TRUE(CreateNewTempDirectory(FilePath::StringType(), &temp_dir));
diff --git a/base/file_util_win.cc b/base/file_util_win.cc
index 90bc47f..e3cd1f8 100644
--- a/base/file_util_win.cc
+++ b/base/file_util_win.cc
@@ -5,6 +5,7 @@
 #include "base/file_util.h"
 
 #include <windows.h>
+#include <io.h>
 #include <psapi.h>
 #include <shellapi.h>
 #include <shlobj.h>
@@ -578,6 +579,20 @@
   return _wfsopen(filename.value().c_str(), w_mode.c_str(), _SH_DENYNO);
 }
 
+FILE* FileToFILE(File file, const char* mode) {
+  if (!file.IsValid())
+    return NULL;
+  int fd =
+      _open_osfhandle(reinterpret_cast<intptr_t>(file.GetPlatformFile()), 0);
+  if (fd < 0)
+    return NULL;
+  file.TakePlatformFile();
+  FILE* stream = _fdopen(fd, mode);
+  if (!stream)
+    _close(fd);
+  return stream;
+}
+
 int ReadFile(const FilePath& filename, char* data, int max_size) {
   ThreadRestrictions::AssertIOAllowed();
   base::win::ScopedHandle file(CreateFile(filename.value().c_str(),
diff --git a/base/platform_file.h b/base/platform_file.h
index a2693a7..27686d1 100644
--- a/base/platform_file.h
+++ b/base/platform_file.h
@@ -134,8 +134,6 @@
 BASE_EXPORT PlatformFileError ErrnoToPlatformFileError(int saved_errno);
 #endif
 
-BASE_EXPORT FILE* FdopenPlatformFile(PlatformFile file, const char* mode);
-
 // Closes a file handle. Returns |true| on success and |false| otherwise.
 BASE_EXPORT bool ClosePlatformFile(PlatformFile file);
 
diff --git a/base/platform_file_posix.cc b/base/platform_file_posix.cc
index ff92b90..cee1f611 100644
--- a/base/platform_file_posix.cc
+++ b/base/platform_file_posix.cc
@@ -117,13 +117,6 @@
 
 }  // namespace
 
-// NaCl doesn't implement system calls to open files directly.
-#if !defined(OS_NACL)
-FILE* FdopenPlatformFile(PlatformFile file, const char* mode) {
-  return fdopen(file, mode);
-}
-#endif  // !defined(OS_NACL)
-
 bool ClosePlatformFile(PlatformFile file) {
   base::ThreadRestrictions::AssertIOAllowed();
   return !IGNORE_EINTR(close(file));
diff --git a/base/platform_file_win.cc b/base/platform_file_win.cc
index 351d25c..af786ab 100644
--- a/base/platform_file_win.cc
+++ b/base/platform_file_win.cc
@@ -13,15 +13,6 @@
 
 namespace base {
 
-FILE* FdopenPlatformFile(PlatformFile file, const char* mode) {
-  if (file == kInvalidPlatformFileValue)
-    return NULL;
-  int fd = _open_osfhandle(reinterpret_cast<intptr_t>(file), 0);
-  if (fd < 0)
-    return NULL;
-  return _fdopen(fd, mode);
-}
-
 bool ClosePlatformFile(PlatformFile file) {
   base::ThreadRestrictions::AssertIOAllowed();
   return (CloseHandle(file) != 0);
diff --git a/content/renderer/media/media_stream_audio_processor.cc b/content/renderer/media/media_stream_audio_processor.cc
index 2c0fcc3..f929b14 100644
--- a/content/renderer/media/media_stream_audio_processor.cc
+++ b/content/renderer/media/media_stream_audio_processor.cc
@@ -240,8 +240,7 @@
 
 void MediaStreamAudioProcessor::StartAecDump(base::File aec_dump_file) {
   if (audio_processing_)
-    StartEchoCancellationDump(audio_processing_.get(),
-                              aec_dump_file.TakePlatformFile());
+    StartEchoCancellationDump(audio_processing_.get(), aec_dump_file.Pass());
 }
 
 void MediaStreamAudioProcessor::StopAecDump() {
diff --git a/content/renderer/media/media_stream_audio_processor_options.cc b/content/renderer/media/media_stream_audio_processor_options.cc
index eda4a39..5ebb2a2a 100644
--- a/content/renderer/media/media_stream_audio_processor_options.cc
+++ b/content/renderer/media/media_stream_audio_processor_options.cc
@@ -4,6 +4,7 @@
 
 #include "content/renderer/media/media_stream_audio_processor_options.h"
 
+#include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/metrics/field_trial.h"
@@ -258,10 +259,10 @@
 }
 
 void StartEchoCancellationDump(AudioProcessing* audio_processing,
-                               const base::PlatformFile& aec_dump_file) {
-  DCHECK_NE(aec_dump_file, base::kInvalidPlatformFileValue);
+                               base::File aec_dump_file) {
+  DCHECK(aec_dump_file.IsValid());
 
-  FILE* stream = base::FdopenPlatformFile(aec_dump_file, "w");
+  FILE* stream = base::FileToFILE(aec_dump_file.Pass(), "w");
   if (!stream) {
     LOG(ERROR) << "Failed to open AEC dump file";
     return;
diff --git a/content/renderer/media/media_stream_audio_processor_options.h b/content/renderer/media/media_stream_audio_processor_options.h
index a051fa4..4683555 100644
--- a/content/renderer/media/media_stream_audio_processor_options.h
+++ b/content/renderer/media/media_stream_audio_processor_options.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "base/platform_file.h"
+#include "base/files/file.h"
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
@@ -109,7 +109,7 @@
 
 // Starts the echo cancellation dump in |audio_processing|.
 void StartEchoCancellationDump(AudioProcessing* audio_processing,
-                               const base::PlatformFile& aec_dump_file);
+                               base::File aec_dump_file);
 
 // Stops the echo cancellation dump in |audio_processing|.
 // This method has no impact if echo cancellation dump has not been started on