xref: /aosp_15_r20/external/cronet/net/base/file_stream_context.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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