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