diff options
author | satorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-17 22:10:34 +0000 |
---|---|---|
committer | satorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-17 22:10:34 +0000 |
commit | e3d66fde2328cc9220c25b51d06cc17b2f8522e7 (patch) | |
tree | c5da44e3c8bfcc898eb19e3176f57491fba16523 /net/base | |
parent | 17cb8a80ed6014b9071fb2a7daef0dc52bf8ab45 (diff) | |
download | chromium_src-e3d66fde2328cc9220c25b51d06cc17b2f8522e7.zip chromium_src-e3d66fde2328cc9220c25b51d06cc17b2f8522e7.tar.gz chromium_src-e3d66fde2328cc9220c25b51d06cc17b2f8522e7.tar.bz2 |
net: Add FileStream::Open() and Close() that perform asynchronously.
However, these aren't used yet. Clients of FileStream that reads/writes
files asynchronously should be migrated to use the new functions.
BUG=72001,114783
TEST=net_unittests.
Review URL: https://chromiumcodereview.appspot.com/9415031
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@122601 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/file_stream.h | 54 | ||||
-rw-r--r-- | net/base/file_stream_posix.cc | 157 | ||||
-rw-r--r-- | net/base/file_stream_unittest.cc | 95 | ||||
-rw-r--r-- | net/base/file_stream_win.cc | 163 |
4 files changed, 416 insertions, 53 deletions
diff --git a/net/base/file_stream.h b/net/base/file_stream.h index b9efb25..00e97d2 100644 --- a/net/base/file_stream.h +++ b/net/base/file_stream.h @@ -12,6 +12,7 @@ #pragma once #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/platform_file.h" #include "net/base/completion_callback.h" #include "net/base/net_export.h" @@ -47,21 +48,52 @@ class NET_EXPORT FileStream { // is destructed. FileStream(base::PlatformFile file, int flags, net::NetLog* net_log); + // If the file stream was opened with Open() or OpenSync(), the underlying + // file will be closed automatically by the destructor, if not closed + // manually. + // + // If the file was opened in the async mode, there must never be any + // pending async operations by the time the destructor is called. virtual ~FileStream(); - // Call this method to close the FileStream synchronously. - // It is OK to call Close multiple times. Redundant calls are ignored. - // Note that if there are any pending async operations, they'll be aborted. + // Call this method to close the FileStream, which was previously opened in + // the async mode (PLATFORM_FILE_ASYNC) asynchronously. + // + // Once the operation is done |callback| is run with OK (i.e. an error is + // not propagated just like CloseSync() does not). // - // TODO(satorux): Implement the asynchronous version of this. + // It is not OK to call Close() multiple times. The behavior is not defined. + // + // Note that there must never be any pending async operations. + virtual void Close(const CompletionCallback& callback); + + // Call this method to close the FileStream synchronously. + // It is OK to call CloseSync() multiple times. Redundant calls are + // ignored. Note that if there are any pending async operations, they'll + // be aborted. virtual void CloseSync(); + // Call this method to open the FileStream asynchronously. The remaining + // methods cannot be used unless the file is opened successfully. Returns + // ERR_IO_PENDING if the operation is started. If the operation cannot be + // started then an error code is returned. Once the operation is done, + // |callback| is run with the result code. open_flags is a bitfield of + // base::PlatformFileFlags. + // + // If the file stream is not closed manually, the underlying file will be + // automatically closed when FileStream is destructed in an asynchronous + // manner (i.e. the file stream is closed in the background but you don't + // know when). + virtual int Open(const FilePath& path, int open_flags, + const CompletionCallback& callback); + // Call this method to open the FileStream synchronously. // The remaining methods cannot be used unless this method returns OK. If // the file cannot be opened then an error code is returned. open_flags is // a bitfield of base::PlatformFileFlags // - // TODO(satorux): Implement the asynchronous version of this. + // If the file stream is not closed manually, the underlying file will be + // automatically closed when FileStream is destructed. virtual int OpenSync(const FilePath& path, int open_flags); // Returns true if Open succeeded and Close has not been called. @@ -152,7 +184,7 @@ class NET_EXPORT FileStream { // Truncates the file to be |bytes| length. This is only valid for writable // files. After truncation the file stream is positioned at |bytes|. The new - // position is retured, or a value < 0 on error. + // position is returned, or a value < 0 on error. // WARNING: one may not truncate a file beyond its current length on any // platform with this call. virtual int64 Truncate(int64 bytes); @@ -182,6 +214,14 @@ class NET_EXPORT FileStream { friend class AsyncContext; friend class FileStreamTest; + // Called when the file_ is opened asynchronously. |file| contains the + // platform file opened. |result| contains the result as a network error + // code. + void OnOpened(base::PlatformFile *file, int* result); + + // Called when the file_ is closed asynchronously. + void OnClosed(); + // This member is used to support asynchronous reads. It is non-null when // the FileStream was opened with PLATFORM_FILE_ASYNC. scoped_ptr<AsyncContext> async_context_; @@ -191,6 +231,8 @@ class NET_EXPORT FileStream { bool auto_closed_; bool record_uma_; net::BoundNetLog bound_net_log_; + base::WeakPtrFactory<FileStream> weak_ptr_factory_; + CompletionCallback callback_; DISALLOW_COPY_AND_ASSIGN(FileStream); }; diff --git a/net/base/file_stream_posix.cc b/net/base/file_stream_posix.cc index 86bf728..835d520 100644 --- a/net/base/file_stream_posix.cc +++ b/net/base/file_stream_posix.cc @@ -69,6 +69,41 @@ int RecordAndMapError(int error, return net_error; } +// Opens a file with some network logging. +// The opened file and the result code are written to |file| and |result|. +void OpenFile(const FilePath& path, + int open_flags, + bool record_uma, + const net::BoundNetLog& bound_net_log, + base::PlatformFile* file, + int* result) { + bound_net_log.BeginEvent( + net::NetLog::TYPE_FILE_STREAM_OPEN, + make_scoped_refptr( + new net::NetLogStringParameter("file_name", + path.AsUTF8Unsafe()))); + + *result = OK; + *file = base::CreatePlatformFile(path, open_flags, NULL, NULL); + if (*file == base::kInvalidPlatformFileValue) { + bound_net_log.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); + *result = RecordAndMapError(errno, FILE_ERROR_SOURCE_OPEN, record_uma, + bound_net_log); + } +} + +// Closes a file with some network logging. +void CloseFile(base::PlatformFile file, + const net::BoundNetLog& bound_net_log) { + bound_net_log.AddEvent(net::NetLog::TYPE_FILE_STREAM_CLOSE, NULL); + if (file == base::kInvalidPlatformFileValue) + return; + + if (!base::ClosePlatformFile(file)) + NOTREACHED(); + bound_net_log.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); +} + // ReadFile() is a simple wrapper around read() that handles EINTR signals and // calls MapSystemError() to map errno to net error codes. int ReadFile(base::PlatformFile file, @@ -328,7 +363,8 @@ FileStream::FileStream(net::NetLog* net_log) auto_closed_(true), record_uma_(false), bound_net_log_(net::BoundNetLog::Make(net_log, - net::NetLog::SOURCE_FILESTREAM)) { + net::NetLog::SOURCE_FILESTREAM)), + weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); } @@ -338,7 +374,8 @@ FileStream::FileStream(base::PlatformFile file, int flags, net::NetLog* net_log) auto_closed_(false), record_uma_(false), bound_net_log_(net::BoundNetLog::Make(net_log, - net::NetLog::SOURCE_FILESTREAM)) { + net::NetLog::SOURCE_FILESTREAM)), + weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to @@ -349,25 +386,80 @@ FileStream::FileStream(base::PlatformFile file, int flags, net::NetLog* net_log) } FileStream::~FileStream() { - if (auto_closed_) - CloseSync(); + if (auto_closed_) { + if (async_context_.get()) { + // Make sure we don't have a request in flight. + DCHECK(async_context_->callback().is_null()); + + // Close the file in the background. + const bool posted = base::WorkerPool::PostTask( + FROM_HERE, + base::Bind(&CloseFile, file_, bound_net_log_), + true /* task_is_slow */); + DCHECK(posted); + } else { + CloseSync(); + } + } bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); } -void FileStream::CloseSync() { - bound_net_log_.AddEvent(net::NetLog::TYPE_FILE_STREAM_CLOSE, NULL); +void FileStream::Close(const CompletionCallback& callback) { + DCHECK(callback_.is_null()); + callback_ = callback; + + // Make sure we don't have a request in flight. Unlike CloseSync(), don't + // abort existing asynchronous operations, as it'd block. + DCHECK(async_context_.get()); + DCHECK(async_context_->callback().is_null()); + + const bool posted = base::WorkerPool::PostTaskAndReply( + FROM_HERE, + base::Bind(&CloseFile, file_, bound_net_log_), + base::Bind(&FileStream::OnClosed, weak_ptr_factory_.GetWeakPtr()), + true /* task_is_slow */); + DCHECK(posted); +} +void FileStream::CloseSync() { // Abort any existing asynchronous operations. + + // TODO(satorux): Remove this once all async clients are migrated to use + // Close(). crbug.com/114783 async_context_.reset(); - if (file_ != base::kInvalidPlatformFileValue) { - if (!base::ClosePlatformFile(file_)) - NOTREACHED(); - file_ = base::kInvalidPlatformFileValue; + CloseFile(file_, bound_net_log_); + file_ = base::kInvalidPlatformFileValue; +} - bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); +int FileStream::Open(const FilePath& path, int open_flags, + const CompletionCallback& callback) { + if (IsOpen()) { + DLOG(FATAL) << "File is already open!"; + return ERR_UNEXPECTED; } + + DCHECK(callback_.is_null()); + callback_ = callback; + + open_flags_ = open_flags; + DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); + + base::PlatformFile* file = + new base::PlatformFile(base::kInvalidPlatformFileValue); + int* result = new int(OK); + const bool posted = base::WorkerPool::PostTaskAndReply( + FROM_HERE, + base::Bind(&OpenFile, path, open_flags, record_uma_, bound_net_log_, + file, result), + base::Bind(&FileStream::OnOpened, + weak_ptr_factory_.GetWeakPtr(), + base::Owned(file), + base::Owned(result)), + true /* task_is_slow */); + DCHECK(posted); + return ERR_IO_PENDING; } int FileStream::OpenSync(const FilePath& path, int open_flags) { @@ -376,27 +468,19 @@ int FileStream::OpenSync(const FilePath& path, int open_flags) { return ERR_UNEXPECTED; } - bound_net_log_.BeginEvent( - net::NetLog::TYPE_FILE_STREAM_OPEN, - make_scoped_refptr( - new net::NetLogStringParameter("file_name", - path.AsUTF8Unsafe()))); - open_flags_ = open_flags; - file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL); - if (file_ == base::kInvalidPlatformFileValue) { - int net_error = RecordAndMapError(errno, - FILE_ERROR_SOURCE_OPEN, - record_uma_, - bound_net_log_); - bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); - return net_error; - } + int result = OK; + OpenFile(path, open_flags_, record_uma_, bound_net_log_, &file_, &result); + if (result != OK) + return result; + + // TODO(satorux): Remove this once all async clients are migrated to use + // Open(). crbug.com/114783 if (open_flags_ & base::PLATFORM_FILE_ASYNC) async_context_.reset(new AsyncContext()); - return OK; + return result; } bool FileStream::IsOpen() const { @@ -596,4 +680,23 @@ void FileStream::SetBoundNetLogSource( bound_net_log_.source()))); } +void FileStream::OnClosed() { + file_ = base::kInvalidPlatformFileValue; + + CompletionCallback temp = callback_; + callback_.Reset(); + temp.Run(OK); +} + +void FileStream::OnOpened(base::PlatformFile* file, int* result) { + file_ = *file; + + if (*result == OK) + async_context_.reset(new AsyncContext()); + + CompletionCallback temp = callback_; + callback_.Reset(); + temp.Run(*result); +} + } // namespace net diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc index 537e6b1..91eb075 100644 --- a/net/base/file_stream_unittest.cc +++ b/net/base/file_stream_unittest.cc @@ -10,6 +10,9 @@ #include "base/message_loop.h" #include "base/path_service.h" #include "base/platform_file.h" +#include "base/synchronization/waitable_event.h" +#include "base/test/test_timeouts.h" +#include "net/base/capturing_net_log.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" @@ -30,6 +33,45 @@ IOBufferWithSize* CreateTestDataBuffer() { return buf; } +// This NetLog is used for notifying when a file stream is closed +// (i.e. TYPE_FILE_STREAM_CLOSE event is recorded). +class NetLogForNotifyingFileClosure : public NetLog { + public: + NetLogForNotifyingFileClosure() + : id_(0), + on_closure_(false /* manual_reset */, false /* initially_signaled */) { + } + + // Wait until a file closure event is recorded. + bool WaitForClosure() { + const base::TimeDelta timeout( + base::TimeDelta::FromMilliseconds( + TestTimeouts::action_max_timeout_ms())); + return on_closure_.TimedWait(timeout); + } + + // NetLog overrides: + virtual void AddEntry(EventType type, + const base::TimeTicks& time, + const Source& source, + EventPhase phase, + EventParameters* extra_parameters) { + if (type == TYPE_FILE_STREAM_CLOSE) { + on_closure_.Signal(); + } + } + + virtual uint32 NextID() { return id_++; } + virtual LogLevel GetLogLevel() const { return LOG_ALL; } + virtual void AddThreadSafeObserver(ThreadSafeObserver* observer) {} + virtual void RemoveThreadSafeObserver(ThreadSafeObserver* observer) {}; + + + private: + uint32 id_; + base::WaitableEvent on_closure_; +}; + } // namespace class FileStreamTest : public PlatformTest { @@ -972,6 +1014,59 @@ TEST_F(FileStreamTest, Truncate) { EXPECT_EQ("01230123", read_contents); } +TEST_F(FileStreamTest, AsyncBasicOpenClose) { + FileStream stream(NULL); + int flags = base::PLATFORM_FILE_OPEN | + base::PLATFORM_FILE_READ | + base::PLATFORM_FILE_ASYNC; + TestCompletionCallback callback; + int rv = stream.Open(temp_file_path(), flags, callback.callback()); + EXPECT_EQ(ERR_IO_PENDING, rv); + EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_TRUE(stream.IsOpen()); + + stream.Close(callback.callback()); + EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_FALSE(stream.IsOpen()); +} + +TEST_F(FileStreamTest, SyncCloseTwice) { + FileStream stream(NULL); + int flags = base::PLATFORM_FILE_OPEN | + base::PLATFORM_FILE_READ; + int rv = stream.OpenSync(temp_file_path(), flags); + EXPECT_EQ(OK, rv); + EXPECT_TRUE(stream.IsOpen()); + + // Closing twice should be safe. + stream.CloseSync(); + EXPECT_FALSE(stream.IsOpen()); + + stream.CloseSync(); + EXPECT_FALSE(stream.IsOpen()); +} + +TEST_F(FileStreamTest, AsyncCloseTwice) { + FileStream stream(NULL); + int flags = base::PLATFORM_FILE_OPEN | + base::PLATFORM_FILE_READ | + base::PLATFORM_FILE_ASYNC; + TestCompletionCallback callback; + int rv = stream.Open(temp_file_path(), flags, callback.callback()); + EXPECT_EQ(ERR_IO_PENDING, rv); + EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_TRUE(stream.IsOpen()); + + // Closing twice should be safe. + stream.Close(callback.callback()); + EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_FALSE(stream.IsOpen()); + + stream.Close(callback.callback()); + EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_FALSE(stream.IsOpen()); +} + } // namespace } // namespace net diff --git a/net/base/file_stream_win.cc b/net/base/file_stream_win.cc index aa2b045..8ee7cbe 100644 --- a/net/base/file_stream_win.cc +++ b/net/base/file_stream_win.cc @@ -11,6 +11,7 @@ #include "base/message_loop.h" #include "base/metrics/histogram.h" #include "base/threading/thread_restrictions.h" +#include "base/threading/worker_pool.h" #include "net/base/file_stream_metrics.h" #include "net/base/file_stream_net_log_parameters.h" #include "net/base/io_buffer.h" @@ -56,6 +57,47 @@ int RecordAndMapError(int error, return net_error; } +// Opens a file with some network logging. +// The opened file and the result code are written to |file| and |result|. +void OpenFile(const FilePath& path, + int open_flags, + bool record_uma, + const net::BoundNetLog& bound_net_log, + base::PlatformFile* file, + int* result) { + bound_net_log.BeginEvent( + net::NetLog::TYPE_FILE_STREAM_OPEN, + make_scoped_refptr( + new net::NetLogStringParameter("file_name", + path.AsUTF8Unsafe()))); + + *file = base::CreatePlatformFile(path, open_flags, NULL, NULL); + if (*file == INVALID_HANDLE_VALUE) { + DWORD error = GetLastError(); + LOG(WARNING) << "Failed to open file: " << error; + *result = RecordAndMapError(error, + FILE_ERROR_SOURCE_OPEN, + record_uma, + bound_net_log); + bound_net_log.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); + return; + } +} + +// Closes a file with some network logging. +void CloseFile(base::PlatformFile file, + const net::BoundNetLog& bound_net_log) { + bound_net_log.AddEvent(net::NetLog::TYPE_FILE_STREAM_CLOSE, NULL); + if (file == INVALID_HANDLE_VALUE) + return; + + CancelIo(file); + + if (!base::ClosePlatformFile(file)) + NOTREACHED(); + bound_net_log.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); +} + } // namespace // FileStream::AsyncContext ---------------------------------------------- @@ -153,7 +195,8 @@ FileStream::FileStream(net::NetLog* net_log) auto_closed_(true), record_uma_(false), bound_net_log_(net::BoundNetLog::Make(net_log, - net::NetLog::SOURCE_FILESTREAM)) { + net::NetLog::SOURCE_FILESTREAM)), + weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); } @@ -163,7 +206,8 @@ FileStream::FileStream(base::PlatformFile file, int flags, net::NetLog* net_log) auto_closed_(false), record_uma_(false), bound_net_log_(net::BoundNetLog::Make(net_log, - net::NetLog::SOURCE_FILESTREAM)) { + net::NetLog::SOURCE_FILESTREAM)), + weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { bound_net_log_.BeginEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to @@ -176,18 +220,54 @@ FileStream::FileStream(base::PlatformFile file, int flags, net::NetLog* net_log) } FileStream::~FileStream() { - if (auto_closed_) - CloseSync(); + if (auto_closed_) { + if (async_context_.get()) { + // Make sure we don't have a request in flight. + DCHECK(async_context_->callback().is_null()); + + // Close the file in the background. + const bool posted = base::WorkerPool::PostTask( + FROM_HERE, + base::Bind(&CloseFile, file_, bound_net_log_), + true /* task_is_slow */); + DCHECK(posted); + } else { + CloseSync(); + } + } bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); } +void FileStream::Close(const CompletionCallback& callback) { + DCHECK(callback_.is_null()); + callback_ = callback; + + // Make sure we don't have a request in flight. Unlike CloseSync(), don't + // abort existing asynchronous operations, as it'd block. + DCHECK(async_context_.get()); + DCHECK(async_context_->callback().is_null()); + + const bool posted = base::WorkerPool::PostTaskAndReply( + FROM_HERE, + base::Bind(&CloseFile, file_, bound_net_log_), + base::Bind(&FileStream::OnClosed, weak_ptr_factory_.GetWeakPtr()), + true /* task_is_slow */); + DCHECK(posted); +} + void FileStream::CloseSync() { + // The logic here is similar to CloseFile() but async_context_.reset() is + // caled in this function. + bound_net_log_.AddEvent(net::NetLog::TYPE_FILE_STREAM_CLOSE, NULL); if (file_ != INVALID_HANDLE_VALUE) CancelIo(file_); + // TODO(satorux): Remove this once all async clients are migrated to use + // Close(). crbug.com/114783 async_context_.reset(); + if (file_ != INVALID_HANDLE_VALUE) { if (!base::ClosePlatformFile(file_)) NOTREACHED(); @@ -197,31 +277,50 @@ void FileStream::CloseSync() { } } -int FileStream::OpenSync(const FilePath& path, int open_flags) { +int FileStream::Open(const FilePath& path, int open_flags, + const CompletionCallback& callback) { if (IsOpen()) { DLOG(FATAL) << "File is already open!"; return ERR_UNEXPECTED; } - bound_net_log_.BeginEvent( - net::NetLog::TYPE_FILE_STREAM_OPEN, - make_scoped_refptr( - new net::NetLogStringParameter("file_name", - path.AsUTF8Unsafe()))); + DCHECK(callback_.is_null()); + callback_ = callback; open_flags_ = open_flags; - file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL); - if (file_ == INVALID_HANDLE_VALUE) { - DWORD error = GetLastError(); - LOG(WARNING) << "Failed to open file: " << error; - int net_error = RecordAndMapError(error, - FILE_ERROR_SOURCE_OPEN, - record_uma_, - bound_net_log_); - bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_OPEN, NULL); - return net_error; + DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); + + base::PlatformFile* file = + new base::PlatformFile(base::kInvalidPlatformFileValue); + int* result = new int(OK); + const bool posted = base::WorkerPool::PostTaskAndReply( + FROM_HERE, + base::Bind(&OpenFile, path, open_flags, record_uma_, bound_net_log_, + file, result), + base::Bind(&FileStream::OnOpened, + weak_ptr_factory_.GetWeakPtr(), + base::Owned(file), + base::Owned(result)), + true /* task_is_slow */); + DCHECK(posted); + return ERR_IO_PENDING; +} + +int FileStream::OpenSync(const FilePath& path, int open_flags) { + if (IsOpen()) { + DLOG(FATAL) << "File is already open!"; + return ERR_UNEXPECTED; } + open_flags_ = open_flags; + + int result = OK; + OpenFile(path, open_flags_, record_uma_, bound_net_log_, &file_, &result); + if (result != OK) + return result; + + // TODO(satorux): Remove this once all async clients are migrated to use + // Open(). crbug.com/114783 if (open_flags_ & base::PLATFORM_FILE_ASYNC) { async_context_.reset(new AsyncContext(bound_net_log_)); if (record_uma_) @@ -515,4 +614,28 @@ void FileStream::SetBoundNetLogSource( bound_net_log_.source()))); } +void FileStream::OnClosed() { + file_ = INVALID_HANDLE_VALUE; + + CompletionCallback temp = callback_; + callback_.Reset(); + temp.Run(OK); +} + +void FileStream::OnOpened(base::PlatformFile* file, int* result) { + file_ = *file; + + if (*result == OK) { + async_context_.reset(new AsyncContext(bound_net_log_)); + if (record_uma_) + async_context_->EnableErrorStatistics(); + MessageLoopForIO::current()->RegisterIOHandler(file_, + async_context_.get()); + } + + CompletionCallback temp = callback_; + callback_.Reset(); + temp.Run(*result); +} + } // namespace net |