1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker // This file defines FileStream::Context class. 6*6777b538SAndroid Build Coastguard Worker // The general design of FileStream is as follows: file_stream.h defines 7*6777b538SAndroid Build Coastguard Worker // FileStream class which basically is just an "wrapper" not containing any 8*6777b538SAndroid Build Coastguard Worker // specific implementation details. It re-routes all its method calls to 9*6777b538SAndroid Build Coastguard Worker // the instance of FileStream::Context (FileStream holds a scoped_ptr to 10*6777b538SAndroid Build Coastguard Worker // FileStream::Context instance). Context was extracted into a different class 11*6777b538SAndroid Build Coastguard Worker // to be able to do and finish all async operations even when FileStream 12*6777b538SAndroid Build Coastguard Worker // instance is deleted. So FileStream's destructor can schedule file 13*6777b538SAndroid Build Coastguard Worker // closing to be done by Context in WorkerPool (or the TaskRunner passed to 14*6777b538SAndroid Build Coastguard Worker // constructor) and then just return (releasing Context pointer from 15*6777b538SAndroid Build Coastguard Worker // scoped_ptr) without waiting for actual closing to complete. 16*6777b538SAndroid Build Coastguard Worker // Implementation of FileStream::Context is divided in two parts: some methods 17*6777b538SAndroid Build Coastguard Worker // and members are platform-independent and some depend on the platform. This 18*6777b538SAndroid Build Coastguard Worker // header file contains the complete definition of Context class including all 19*6777b538SAndroid Build Coastguard Worker // platform-dependent parts (because of that it has a lot of #if-#else 20*6777b538SAndroid Build Coastguard Worker // branching). Implementations of all platform-independent methods are 21*6777b538SAndroid Build Coastguard Worker // located in file_stream_context.cc, and all platform-dependent methods are 22*6777b538SAndroid Build Coastguard Worker // in file_stream_context_{win,posix}.cc. This separation provides better 23*6777b538SAndroid Build Coastguard Worker // readability of Context's code. And we tried to make as much Context code 24*6777b538SAndroid Build Coastguard Worker // platform-independent as possible. So file_stream_context_{win,posix}.cc are 25*6777b538SAndroid Build Coastguard Worker // much smaller than file_stream_context.cc now. 26*6777b538SAndroid Build Coastguard Worker 27*6777b538SAndroid Build Coastguard Worker #ifndef NET_BASE_FILE_STREAM_CONTEXT_H_ 28*6777b538SAndroid Build Coastguard Worker #define NET_BASE_FILE_STREAM_CONTEXT_H_ 29*6777b538SAndroid Build Coastguard Worker 30*6777b538SAndroid Build Coastguard Worker #include <stdint.h> 31*6777b538SAndroid Build Coastguard Worker 32*6777b538SAndroid Build Coastguard Worker #include "base/files/file.h" 33*6777b538SAndroid Build Coastguard Worker #include "base/logging.h" 34*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h" 35*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump_for_io.h" 36*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h" 37*6777b538SAndroid Build Coastguard Worker #include "base/task/task_runner.h" 38*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h" 39*6777b538SAndroid Build Coastguard Worker #include "net/base/completion_once_callback.h" 40*6777b538SAndroid Build Coastguard Worker #include "net/base/file_stream.h" 41*6777b538SAndroid Build Coastguard Worker 42*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 43*6777b538SAndroid Build Coastguard Worker #include <errno.h> 44*6777b538SAndroid Build Coastguard Worker #endif 45*6777b538SAndroid Build Coastguard Worker 46*6777b538SAndroid Build Coastguard Worker namespace base { 47*6777b538SAndroid Build Coastguard Worker class FilePath; 48*6777b538SAndroid Build Coastguard Worker } 49*6777b538SAndroid Build Coastguard Worker 50*6777b538SAndroid Build Coastguard Worker namespace net { 51*6777b538SAndroid Build Coastguard Worker 52*6777b538SAndroid Build Coastguard Worker class IOBuffer; 53*6777b538SAndroid Build Coastguard Worker 54*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) 55*6777b538SAndroid Build Coastguard Worker class FileStream::Context : public base::MessagePumpForIO::IOHandler { 56*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 57*6777b538SAndroid Build Coastguard Worker class FileStream::Context { 58*6777b538SAndroid Build Coastguard Worker #endif 59*6777b538SAndroid Build Coastguard Worker 60*6777b538SAndroid Build Coastguard Worker public: 61*6777b538SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////// 62*6777b538SAndroid Build Coastguard Worker // Platform-dependent methods implemented in 63*6777b538SAndroid Build Coastguard Worker // file_stream_context_{win,posix}.cc. 64*6777b538SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////// 65*6777b538SAndroid Build Coastguard Worker 66*6777b538SAndroid Build Coastguard Worker explicit Context(scoped_refptr<base::TaskRunner> task_runner); 67*6777b538SAndroid Build Coastguard Worker Context(base::File file, scoped_refptr<base::TaskRunner> task_runner); 68*6777b538SAndroid Build Coastguard Worker Context(const Context&) = delete; 69*6777b538SAndroid Build Coastguard Worker Context& operator=(const Context&) = delete; 70*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) 71*6777b538SAndroid Build Coastguard Worker ~Context() override; 72*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 73*6777b538SAndroid Build Coastguard Worker ~Context(); 74*6777b538SAndroid Build Coastguard Worker #endif 75*6777b538SAndroid Build Coastguard Worker 76*6777b538SAndroid Build Coastguard Worker int Read(IOBuffer* buf, int buf_len, CompletionOnceCallback callback); 77*6777b538SAndroid Build Coastguard Worker 78*6777b538SAndroid Build Coastguard Worker int Write(IOBuffer* buf, int buf_len, CompletionOnceCallback callback); 79*6777b538SAndroid Build Coastguard Worker async_in_progress()80*6777b538SAndroid Build Coastguard Worker bool async_in_progress() const { return async_in_progress_; } 81*6777b538SAndroid Build Coastguard Worker 82*6777b538SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////// 83*6777b538SAndroid Build Coastguard Worker // Platform-independent methods implemented in file_stream_context.cc. 84*6777b538SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////// 85*6777b538SAndroid Build Coastguard Worker 86*6777b538SAndroid Build Coastguard Worker // Destroys the context. It can be deleted in the method or deletion can be 87*6777b538SAndroid Build Coastguard Worker // deferred if some asynchronous operation is now in progress or if file is 88*6777b538SAndroid Build Coastguard Worker // not closed yet. 89*6777b538SAndroid Build Coastguard Worker void Orphan(); 90*6777b538SAndroid Build Coastguard Worker 91*6777b538SAndroid Build Coastguard Worker void Open(const base::FilePath& path, 92*6777b538SAndroid Build Coastguard Worker int open_flags, 93*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback); 94*6777b538SAndroid Build Coastguard Worker 95*6777b538SAndroid Build Coastguard Worker void Close(CompletionOnceCallback callback); 96*6777b538SAndroid Build Coastguard Worker 97*6777b538SAndroid Build Coastguard Worker // Seeks |offset| bytes from the start of the file. 98*6777b538SAndroid Build Coastguard Worker void Seek(int64_t offset, Int64CompletionOnceCallback callback); 99*6777b538SAndroid Build Coastguard Worker 100*6777b538SAndroid Build Coastguard Worker void GetFileInfo(base::File::Info* file_info, 101*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback); 102*6777b538SAndroid Build Coastguard Worker 103*6777b538SAndroid Build Coastguard Worker void Flush(CompletionOnceCallback callback); 104*6777b538SAndroid Build Coastguard Worker 105*6777b538SAndroid Build Coastguard Worker bool IsOpen() const; 106*6777b538SAndroid Build Coastguard Worker 107*6777b538SAndroid Build Coastguard Worker private: 108*6777b538SAndroid Build Coastguard Worker struct IOResult { 109*6777b538SAndroid Build Coastguard Worker IOResult(); 110*6777b538SAndroid Build Coastguard Worker IOResult(int64_t result, logging::SystemErrorCode os_error); 111*6777b538SAndroid Build Coastguard Worker static IOResult FromOSError(logging::SystemErrorCode os_error); 112*6777b538SAndroid Build Coastguard Worker 113*6777b538SAndroid Build Coastguard Worker int64_t result; 114*6777b538SAndroid Build Coastguard Worker logging::SystemErrorCode os_error; // Set only when result < 0. 115*6777b538SAndroid Build Coastguard Worker }; 116*6777b538SAndroid Build Coastguard Worker 117*6777b538SAndroid Build Coastguard Worker struct OpenResult { 118*6777b538SAndroid Build Coastguard Worker public: 119*6777b538SAndroid Build Coastguard Worker OpenResult(); 120*6777b538SAndroid Build Coastguard Worker OpenResult(base::File file, IOResult error_code); 121*6777b538SAndroid Build Coastguard Worker OpenResult(OpenResult&& other); 122*6777b538SAndroid Build Coastguard Worker OpenResult& operator=(OpenResult&& other); 123*6777b538SAndroid Build Coastguard Worker OpenResult(const OpenResult&) = delete; 124*6777b538SAndroid Build Coastguard Worker OpenResult& operator=(const OpenResult&) = delete; 125*6777b538SAndroid Build Coastguard Worker 126*6777b538SAndroid Build Coastguard Worker base::File file; 127*6777b538SAndroid Build Coastguard Worker IOResult error_code; 128*6777b538SAndroid Build Coastguard Worker }; 129*6777b538SAndroid Build Coastguard Worker 130*6777b538SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////// 131*6777b538SAndroid Build Coastguard Worker // Platform-independent methods implemented in file_stream_context.cc. 132*6777b538SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////// 133*6777b538SAndroid Build Coastguard Worker 134*6777b538SAndroid Build Coastguard Worker OpenResult OpenFileImpl(const base::FilePath& path, int open_flags); 135*6777b538SAndroid Build Coastguard Worker 136*6777b538SAndroid Build Coastguard Worker IOResult GetFileInfoImpl(base::File::Info* file_info); 137*6777b538SAndroid Build Coastguard Worker 138*6777b538SAndroid Build Coastguard Worker IOResult CloseFileImpl(); 139*6777b538SAndroid Build Coastguard Worker 140*6777b538SAndroid Build Coastguard Worker IOResult FlushFileImpl(); 141*6777b538SAndroid Build Coastguard Worker 142*6777b538SAndroid Build Coastguard Worker void OnOpenCompleted(CompletionOnceCallback callback, OpenResult open_result); 143*6777b538SAndroid Build Coastguard Worker 144*6777b538SAndroid Build Coastguard Worker void CloseAndDelete(); 145*6777b538SAndroid Build Coastguard Worker 146*6777b538SAndroid Build Coastguard Worker Int64CompletionOnceCallback IntToInt64(CompletionOnceCallback callback); 147*6777b538SAndroid Build Coastguard Worker 148*6777b538SAndroid Build Coastguard Worker // Called when Open() or Seek() completes. |result| contains the result or a 149*6777b538SAndroid Build Coastguard Worker // network error code. 150*6777b538SAndroid Build Coastguard Worker void OnAsyncCompleted(Int64CompletionOnceCallback callback, 151*6777b538SAndroid Build Coastguard Worker const IOResult& result); 152*6777b538SAndroid Build Coastguard Worker 153*6777b538SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////// 154*6777b538SAndroid Build Coastguard Worker // Platform-dependent methods implemented in 155*6777b538SAndroid Build Coastguard Worker // file_stream_context_{win,posix}.cc. 156*6777b538SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////// 157*6777b538SAndroid Build Coastguard Worker 158*6777b538SAndroid Build Coastguard Worker // Adjusts the position from where the data is read. 159*6777b538SAndroid Build Coastguard Worker IOResult SeekFileImpl(int64_t offset); 160*6777b538SAndroid Build Coastguard Worker 161*6777b538SAndroid Build Coastguard Worker void OnFileOpened(); 162*6777b538SAndroid Build Coastguard Worker 163*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) 164*6777b538SAndroid Build Coastguard Worker void IOCompletionIsPending(CompletionOnceCallback callback, IOBuffer* buf); 165*6777b538SAndroid Build Coastguard Worker 166*6777b538SAndroid Build Coastguard Worker // Implementation of MessagePumpForIO::IOHandler. 167*6777b538SAndroid Build Coastguard Worker void OnIOCompleted(base::MessagePumpForIO::IOContext* context, 168*6777b538SAndroid Build Coastguard Worker DWORD bytes_read, 169*6777b538SAndroid Build Coastguard Worker DWORD error) override; 170*6777b538SAndroid Build Coastguard Worker 171*6777b538SAndroid Build Coastguard Worker // Invokes the user callback. 172*6777b538SAndroid Build Coastguard Worker void InvokeUserCallback(); 173*6777b538SAndroid Build Coastguard Worker 174*6777b538SAndroid Build Coastguard Worker // Deletes an orphaned context. 175*6777b538SAndroid Build Coastguard Worker void DeleteOrphanedContext(); 176*6777b538SAndroid Build Coastguard Worker 177*6777b538SAndroid Build Coastguard Worker // The ReadFile call on Windows can execute synchronously at times. 178*6777b538SAndroid Build Coastguard Worker // http://support.microsoft.com/kb/156932. This ends up blocking the calling 179*6777b538SAndroid Build Coastguard Worker // thread which is undesirable. To avoid this we execute the ReadFile call 180*6777b538SAndroid Build Coastguard Worker // on a worker thread. 181*6777b538SAndroid Build Coastguard Worker // The |context| parameter is a pointer to the current Context instance. It 182*6777b538SAndroid Build Coastguard Worker // is safe to pass this as is to the pool as the Context instance should 183*6777b538SAndroid Build Coastguard Worker // remain valid until the pending Read operation completes. 184*6777b538SAndroid Build Coastguard Worker // The |file| parameter is the handle to the file being read. 185*6777b538SAndroid Build Coastguard Worker // The |buf| parameter is the buffer where we want the ReadFile to read the 186*6777b538SAndroid Build Coastguard Worker // data into. 187*6777b538SAndroid Build Coastguard Worker // The |buf_len| parameter contains the number of bytes to be read. 188*6777b538SAndroid Build Coastguard Worker // The |overlapped| parameter is a pointer to the OVERLAPPED structure being 189*6777b538SAndroid Build Coastguard Worker // used. 190*6777b538SAndroid Build Coastguard Worker // The |origin_thread_task_runner| is a task runner instance used to post 191*6777b538SAndroid Build Coastguard Worker // tasks back to the originating thread. 192*6777b538SAndroid Build Coastguard Worker static void ReadAsync( 193*6777b538SAndroid Build Coastguard Worker FileStream::Context* context, 194*6777b538SAndroid Build Coastguard Worker HANDLE file, 195*6777b538SAndroid Build Coastguard Worker scoped_refptr<IOBuffer> buf, 196*6777b538SAndroid Build Coastguard Worker int buf_len, 197*6777b538SAndroid Build Coastguard Worker OVERLAPPED* overlapped, 198*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SingleThreadTaskRunner> origin_thread_task_runner); 199*6777b538SAndroid Build Coastguard Worker 200*6777b538SAndroid Build Coastguard Worker // This callback executes on the main calling thread. It informs the caller 201*6777b538SAndroid Build Coastguard Worker // about the result of the ReadFile call. 202*6777b538SAndroid Build Coastguard Worker // The |read_file_ret| parameter contains the return value of the ReadFile 203*6777b538SAndroid Build Coastguard Worker // call. 204*6777b538SAndroid Build Coastguard Worker // The |bytes_read| contains the number of bytes read from the file, if 205*6777b538SAndroid Build Coastguard Worker // ReadFile succeeds. 206*6777b538SAndroid Build Coastguard Worker // The |os_error| parameter contains the value of the last error returned by 207*6777b538SAndroid Build Coastguard Worker // the ReadFile API. 208*6777b538SAndroid Build Coastguard Worker void ReadAsyncResult(BOOL read_file_ret, DWORD bytes_read, DWORD os_error); 209*6777b538SAndroid Build Coastguard Worker 210*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 211*6777b538SAndroid Build Coastguard Worker // ReadFileImpl() is a simple wrapper around read() that handles EINTR 212*6777b538SAndroid Build Coastguard Worker // signals and calls RecordAndMapError() to map errno to net error codes. 213*6777b538SAndroid Build Coastguard Worker IOResult ReadFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); 214*6777b538SAndroid Build Coastguard Worker 215*6777b538SAndroid Build Coastguard Worker // WriteFileImpl() is a simple wrapper around write() that handles EINTR 216*6777b538SAndroid Build Coastguard Worker // signals and calls MapSystemError() to map errno to net error codes. 217*6777b538SAndroid Build Coastguard Worker // It tries to write to completion. 218*6777b538SAndroid Build Coastguard Worker IOResult WriteFileImpl(scoped_refptr<IOBuffer> buf, int buf_len); 219*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IS_WIN) 220*6777b538SAndroid Build Coastguard Worker 221*6777b538SAndroid Build Coastguard Worker base::File file_; 222*6777b538SAndroid Build Coastguard Worker bool async_in_progress_ = false; 223*6777b538SAndroid Build Coastguard Worker 224*6777b538SAndroid Build Coastguard Worker bool orphaned_ = false; 225*6777b538SAndroid Build Coastguard Worker const scoped_refptr<base::TaskRunner> task_runner_; 226*6777b538SAndroid Build Coastguard Worker 227*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN) 228*6777b538SAndroid Build Coastguard Worker base::MessagePumpForIO::IOContext io_context_; 229*6777b538SAndroid Build Coastguard Worker CompletionOnceCallback callback_; 230*6777b538SAndroid Build Coastguard Worker scoped_refptr<IOBuffer> in_flight_buf_; 231*6777b538SAndroid Build Coastguard Worker // This flag is set to true when we receive a Read request which is queued to 232*6777b538SAndroid Build Coastguard Worker // the thread pool. 233*6777b538SAndroid Build Coastguard Worker bool async_read_initiated_ = false; 234*6777b538SAndroid Build Coastguard Worker // This flag is set to true when we receive a notification ReadAsyncResult() 235*6777b538SAndroid Build Coastguard Worker // on the calling thread which indicates that the asynchronous Read 236*6777b538SAndroid Build Coastguard Worker // operation is complete. 237*6777b538SAndroid Build Coastguard Worker bool async_read_completed_ = false; 238*6777b538SAndroid Build Coastguard Worker // This flag is set to true when we receive an IO completion notification for 239*6777b538SAndroid Build Coastguard Worker // an asynchronously initiated Read operation. OnIOComplete(). 240*6777b538SAndroid Build Coastguard Worker bool io_complete_for_read_received_ = false; 241*6777b538SAndroid Build Coastguard Worker // Tracks the result of the IO completion operation. Set in OnIOComplete. 242*6777b538SAndroid Build Coastguard Worker int result_ = 0; 243*6777b538SAndroid Build Coastguard Worker #endif 244*6777b538SAndroid Build Coastguard Worker }; 245*6777b538SAndroid Build Coastguard Worker 246*6777b538SAndroid Build Coastguard Worker } // namespace net 247*6777b538SAndroid Build Coastguard Worker 248*6777b538SAndroid Build Coastguard Worker #endif // NET_BASE_FILE_STREAM_CONTEXT_H_ 249