• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 The Chromium Embedded Framework Authors. Portions
2 // Copyright (c) 2018 The Chromium Authors. All rights reserved. Use of this
3 // source code is governed by a BSD-style license that can be found in the
4 // LICENSE file.
5 
6 #ifndef CEF_LIBCEF_BROWSER_NET_SERVICE_STREAM_READER_URL_LOADER_H_
7 #define CEF_LIBCEF_BROWSER_NET_SERVICE_STREAM_READER_URL_LOADER_H_
8 
9 #include <map>
10 
11 #include "base/callback.h"
12 #include "base/threading/thread_checker.h"
13 #include "mojo/public/cpp/system/simple_watcher.h"
14 #include "net/http/http_byte_range.h"
15 #include "services/network/public/cpp/net_adapters.h"
16 #include "services/network/public/mojom/network_context.mojom.h"
17 #include "services/network/public/mojom/url_loader.mojom.h"
18 #include "services/network/public/mojom/url_response_head.mojom.h"
19 
20 namespace net_service {
21 
22 class InputStreamReader;
23 
24 // Abstract class representing an input stream. All methods are called in
25 // sequence on a worker thread, but not necessarily on the same thread.
26 class InputStream {
27  public:
~InputStream()28   virtual ~InputStream() {}
29 
30   // Callback for asynchronous continuation of Skip(). If |bytes_skipped| > 0
31   // then either Skip() will be called again until the requested number of
32   // bytes have been skipped or the request will proceed. If |bytes_skipped|
33   // <= 0 the request will fail with net::ERR_REQUEST_RANGE_NOT_SATISFIABLE.
34   using SkipCallback = base::OnceCallback<void(int64_t /* bytes_skipped */)>;
35 
36   // Skip over and discard |n| bytes of data from this input stream. If data
37   // is available immediately set |bytes_skipped| to the number of of bytes
38   // skipped and return true. To read the data at a later time set
39   // |bytes_skipped| to 0, return true and execute |callback| when the data is
40   // available. To indicate failure set |bytes_skipped| to < 0 (e.g.
41   // net::ERR_FAILED) and return false.
42   virtual bool Skip(int64_t n,
43                     int64_t* bytes_skipped,
44                     SkipCallback callback) = 0;
45 
46   // Callback for asynchronous continuation of Read(). If |bytes_read| == 0
47   // the response will be considered complete. If |bytes_read| > 0 then Read()
48   // will be called again until the request is complete (based on either the
49   // result or the expected content length). If |bytes_read| < 0 then the
50   // request will fail and the |bytes_read| value will be treated as the error
51   // code.
52   using ReadCallback = base::OnceCallback<void(int /* bytes_read */)>;
53 
54   // Read response data. If data is available immediately copy up to |length|
55   // bytes into |dest|, set |bytes_read| to the number of bytes copied, and
56   // return true. To read the data at a later time set |bytes_read| to 0, return
57   // true and execute |callback| when the data is available. To indicate
58   // response completion set |bytes_read| to 0 and return false. To indicate
59   // failure set |bytes_read| to < 0 (e.g. net::ERR_FAILED) and return false.
60   virtual bool Read(net::IOBuffer* dest,
61                     int length,
62                     int* bytes_read,
63                     ReadCallback callback) = 0;
64 };
65 
66 // Abstract class for handling intercepted resource responses. All methods are
67 // called on the IO thread unless otherwise indicated.
68 class ResourceResponse {
69  public:
~ResourceResponse()70   virtual ~ResourceResponse() {}
71 
72   // Callback for asynchronous continuation of Open(). If the InputStream is
73   // null the request will be canceled.
74   using OpenCallback = base::OnceCallback<void(std::unique_ptr<InputStream>)>;
75 
76   // This method is called on a worker thread. Return true and execute
77   // |callback| to continue the request. Return false to cancel the request.
78   // |request| may be different from the request used to create the
79   // StreamReaderURLLoader if a redirect was followed.
80   virtual bool OpenInputStream(int32_t request_id,
81                                const network::ResourceRequest& request,
82                                OpenCallback callback) = 0;
83 
84   // This method is called to populate the response headers.
85   using HeaderMap = std::multimap<std::string, std::string>;
86   virtual void GetResponseHeaders(int32_t request_id,
87                                   int* status_code,
88                                   std::string* reason_phrase,
89                                   std::string* mime_type,
90                                   std::string* charset,
91                                   int64_t* content_length,
92                                   HeaderMap* extra_headers) = 0;
93 };
94 
95 // Custom URLLoader implementation for loading network responses from stream.
96 // Methods are called on the IO thread unless otherwise indicated.
97 // Based on android_webview/browser/network_service/
98 // android_stream_reader_url_loader.h
99 class StreamReaderURLLoader : public network::mojom::URLLoader {
100  public:
101   // Delegate abstraction for obtaining input streams. All methods are called
102   // on the IO thread unless otherwise indicated.
103   class Delegate : public ResourceResponse {
104    public:
105     // This method is called if the result of calling OpenInputStream was null.
106     // The |restarted| parameter is set to true if the request was restarted
107     // with a new loader.
108     virtual void OnInputStreamOpenFailed(int32_t request_id,
109                                          bool* restarted) = 0;
110   };
111 
112   StreamReaderURLLoader(
113       int32_t request_id,
114       const network::ResourceRequest& request,
115       mojo::PendingRemote<network::mojom::URLLoaderClient> client,
116       mojo::PendingRemote<network::mojom::TrustedHeaderClient> header_client,
117       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
118       std::unique_ptr<Delegate> response_delegate);
119   ~StreamReaderURLLoader() override;
120 
121   void Start();
122 
123   void ContinueResponse(bool was_redirected);
124 
125   // network::mojom::URLLoader methods:
126   void FollowRedirect(
127       const std::vector<std::string>& removed_headers,
128       const net::HttpRequestHeaders& modified_headers,
129       const net::HttpRequestHeaders& modified_cors_exempt_headers,
130       const base::Optional<GURL>& new_url) override;
131   void SetPriority(net::RequestPriority priority,
132                    int intra_priority_value) override;
133   void PauseReadingBodyFromNet() override;
134   void ResumeReadingBodyFromNet() override;
135 
136  private:
137   void ContinueWithRequestHeaders(
138       int32_t result,
139       const base::Optional<net::HttpRequestHeaders>& headers);
140   void OnInputStreamOpened(std::unique_ptr<Delegate> returned_delegate,
141                            std::unique_ptr<InputStream> input_stream);
142 
143   void OnReaderSkipCompleted(int64_t bytes_skipped);
144   void HeadersComplete(int status_code, int64_t expected_content_length);
145   void ContinueWithResponseHeaders(
146       network::mojom::URLResponseHeadPtr pending_response,
147       int32_t result,
148       const base::Optional<std::string>& headers,
149       const base::Optional<GURL>& redirect_url);
150 
151   void SendBody();
152   void ReadMore();
153   void OnDataPipeWritable(MojoResult result);
154   void OnReaderReadCompleted(int bytes_read);
155   void RequestComplete(int status_code);
156 
157   void CleanUp();
158 
159   bool ParseRange(const net::HttpRequestHeaders& headers);
160   bool byte_range_valid() const;
161 
162   const int32_t request_id_;
163 
164   size_t header_length_ = 0;
165   int64_t total_bytes_read_ = 0;
166 
167   net::HttpByteRange byte_range_;
168   network::ResourceRequest request_;
169   mojo::Remote<network::mojom::URLLoaderClient> client_;
170   mojo::Remote<network::mojom::TrustedHeaderClient> header_client_;
171   const net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
172   std::unique_ptr<Delegate> response_delegate_;
173   scoped_refptr<InputStreamReader> input_stream_reader_;
174 
175   mojo::ScopedDataPipeProducerHandle producer_handle_;
176   scoped_refptr<network::NetToMojoPendingBuffer> pending_buffer_;
177   mojo::SimpleWatcher writable_handle_watcher_;
178   base::ThreadChecker thread_checker_;
179 
180   scoped_refptr<base::SequencedTaskRunner> stream_work_task_runner_;
181 
182   base::OnceClosure open_cancel_callback_;
183 
184   base::WeakPtrFactory<StreamReaderURLLoader> weak_factory_;
185 
186   DISALLOW_COPY_AND_ASSIGN(StreamReaderURLLoader);
187 };
188 
189 }  // namespace net_service
190 
191 #endif  // CEF_LIBCEF_BROWSER_NET_SERVICE_STREAM_READER_URL_LOADER_H_
192