mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			238 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (c) 2019 The Chromium Embedded Framework Authors. Portions
 | |
| // Copyright (c) 2018 The Chromium Authors. All rights reserved. Use of this
 | |
| // source code is governed by a BSD-style license that can be found in the
 | |
| // LICENSE file.
 | |
| 
 | |
| #ifndef CEF_LIBCEF_BROWSER_NET_SERVICE_STREAM_READER_URL_LOADER_H_
 | |
| #define CEF_LIBCEF_BROWSER_NET_SERVICE_STREAM_READER_URL_LOADER_H_
 | |
| 
 | |
| #include <map>
 | |
| 
 | |
| #include "base/callback.h"
 | |
| #include "base/threading/thread_checker.h"
 | |
| #include "mojo/public/cpp/system/simple_watcher.h"
 | |
| #include "net/http/http_byte_range.h"
 | |
| #include "services/network/public/cpp/net_adapters.h"
 | |
| #include "services/network/public/cpp/resource_response.h"
 | |
| #include "services/network/public/mojom/network_context.mojom.h"
 | |
| #include "services/network/public/mojom/url_loader.mojom.h"
 | |
| 
 | |
| namespace net_service {
 | |
| 
 | |
| class InputStreamReader;
 | |
| 
 | |
| // Abstract class representing an input stream. All methods are called in
 | |
| // sequence on a worker thread, but not necessarily on the same thread.
 | |
| class InputStream {
 | |
|  public:
 | |
|   virtual ~InputStream() {}
 | |
| 
 | |
|   // Callback for asynchronous continuation of Skip(). If |bytes_skipped| > 0
 | |
|   // then either Skip() will be called again until the requested number of
 | |
|   // bytes have been skipped or the request will proceed. If |bytes_skipped|
 | |
|   // <= 0 the request will fail with net::ERR_REQUEST_RANGE_NOT_SATISFIABLE.
 | |
|   using SkipCallback = base::OnceCallback<void(int64_t /* bytes_skipped */)>;
 | |
| 
 | |
|   // Skip over and discard |n| bytes of data from this input stream. If data
 | |
|   // is available immediately set |bytes_skipped| to the number of of bytes
 | |
|   // skipped and return true. To read the data at a later time set
 | |
|   // |bytes_skipped| to 0, return true and execute |callback| when the data is
 | |
|   // available. To indicate failure set |bytes_skipped| to < 0 (e.g.
 | |
|   // net::ERR_FAILED) and return false.
 | |
|   virtual bool Skip(int64_t n,
 | |
|                     int64_t* bytes_skipped,
 | |
|                     SkipCallback callback) = 0;
 | |
| 
 | |
|   // Callback for asynchronous continuation of Read(). If |bytes_read| == 0
 | |
|   // the response will be considered complete. If |bytes_read| > 0 then Read()
 | |
|   // will be called again until the request is complete (based on either the
 | |
|   // result or the expected content length). If |bytes_read| < 0 then the
 | |
|   // request will fail and the |bytes_read| value will be treated as the error
 | |
|   // code.
 | |
|   using ReadCallback = base::OnceCallback<void(int /* bytes_read */)>;
 | |
| 
 | |
|   // Read response data. If data is available immediately copy up to |length|
 | |
|   // bytes into |dest|, set |bytes_read| to the number of bytes copied, and
 | |
|   // return true. To read the data at a later time set |bytes_read| to 0, return
 | |
|   // true and execute |callback| when the data is available. To indicate
 | |
|   // response completion set |bytes_read| to 0 and return false. To indicate
 | |
|   // failure set |bytes_read| to < 0 (e.g. net::ERR_FAILED) and return false.
 | |
|   virtual bool Read(net::IOBuffer* dest,
 | |
|                     int length,
 | |
|                     int* bytes_read,
 | |
|                     ReadCallback callback) = 0;
 | |
| };
 | |
| 
 | |
| // Unique identifier for RequestHandler callbacks.
 | |
| // Based on components/viz/common/surfaces/frame_sink_id.h
 | |
| class RequestId {
 | |
|  public:
 | |
|   constexpr RequestId() : request_id_(0), routing_id_(0) {}
 | |
| 
 | |
|   constexpr RequestId(const RequestId& other)
 | |
|       : request_id_(other.request_id_), routing_id_(other.routing_id_) {}
 | |
| 
 | |
|   constexpr RequestId(uint32_t request_id, uint32_t routing_id)
 | |
|       : request_id_(request_id), routing_id_(routing_id) {}
 | |
| 
 | |
|   constexpr bool is_valid() const {
 | |
|     return request_id_ != 0 || routing_id_ != 0;
 | |
|   }
 | |
| 
 | |
|   constexpr uint32_t request_id() const { return request_id_; }
 | |
| 
 | |
|   constexpr uint32_t routing_id() const { return routing_id_; }
 | |
| 
 | |
|   bool operator==(const RequestId& other) const {
 | |
|     return request_id_ == other.request_id_ && routing_id_ == other.routing_id_;
 | |
|   }
 | |
| 
 | |
|   bool operator!=(const RequestId& other) const { return !(*this == other); }
 | |
| 
 | |
|   bool operator<(const RequestId& other) const {
 | |
|     return std::tie(request_id_, routing_id_) <
 | |
|            std::tie(other.request_id_, other.routing_id_);
 | |
|   }
 | |
| 
 | |
|   size_t hash() const { return base::HashInts(request_id_, routing_id_); }
 | |
| 
 | |
|   std::string ToString() const;
 | |
| 
 | |
|   std::string ToString(base::StringPiece debug_label) const;
 | |
| 
 | |
|  private:
 | |
|   uint32_t request_id_;
 | |
|   uint32_t routing_id_;
 | |
| };
 | |
| 
 | |
| std::ostream& operator<<(std::ostream& out, const RequestId& request_id);
 | |
| 
 | |
| struct RequestIdHash {
 | |
|   size_t operator()(const RequestId& key) const { return key.hash(); }
 | |
| };
 | |
| 
 | |
| // Abstract class for handling intercepted resource responses. All methods are
 | |
| // called on the IO thread unless otherwise indicated.
 | |
| class ResourceResponse {
 | |
|  public:
 | |
|   virtual ~ResourceResponse() {}
 | |
| 
 | |
|   // Callback for asynchronous continuation of Open(). If the InputStream is
 | |
|   // null the request will be canceled.
 | |
|   using OpenCallback = base::OnceCallback<void(std::unique_ptr<InputStream>)>;
 | |
| 
 | |
|   // This method is called on a worker thread. Return true and execute
 | |
|   // |callback| to continue the request. Return false to cancel the request.
 | |
|   // |request| may be different from the request used to create the
 | |
|   // StreamReaderURLLoader if a redirect was followed.
 | |
|   virtual bool OpenInputStream(const RequestId& id,
 | |
|                                const network::ResourceRequest& request,
 | |
|                                OpenCallback callback) = 0;
 | |
| 
 | |
|   // This method is called to populate the response headers.
 | |
|   using HeaderMap = std::multimap<std::string, std::string>;
 | |
|   virtual void GetResponseHeaders(const RequestId& id,
 | |
|                                   int* status_code,
 | |
|                                   std::string* reason_phrase,
 | |
|                                   std::string* mime_type,
 | |
|                                   std::string* charset,
 | |
|                                   int64_t* content_length,
 | |
|                                   HeaderMap* extra_headers) = 0;
 | |
| };
 | |
| 
 | |
| // Custom URLLoader implementation for loading network responses from stream.
 | |
| // Methods are called on the IO thread unless otherwise indicated.
 | |
| // Based on android_webview/browser/network_service/
 | |
| // android_stream_reader_url_loader.h
 | |
| class StreamReaderURLLoader : public network::mojom::URLLoader {
 | |
|  public:
 | |
|   // Delegate abstraction for obtaining input streams. All methods are called
 | |
|   // on the IO thread unless otherwise indicated.
 | |
|   class Delegate : public ResourceResponse {
 | |
|    public:
 | |
|     // This method is called if the result of calling OpenInputStream was null.
 | |
|     // The |restarted| parameter is set to true if the request was restarted
 | |
|     // with a new loader.
 | |
|     virtual void OnInputStreamOpenFailed(const RequestId& id,
 | |
|                                          bool* restarted) = 0;
 | |
|   };
 | |
| 
 | |
|   StreamReaderURLLoader(
 | |
|       const RequestId& request_id,
 | |
|       const network::ResourceRequest& request,
 | |
|       network::mojom::URLLoaderClientPtr client,
 | |
|       network::mojom::TrustedHeaderClientPtr header_client,
 | |
|       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
 | |
|       std::unique_ptr<Delegate> response_delegate);
 | |
|   ~StreamReaderURLLoader() override;
 | |
| 
 | |
|   void Start();
 | |
| 
 | |
|   void ContinueResponse(bool was_redirected);
 | |
| 
 | |
|   // network::mojom::URLLoader methods:
 | |
|   void FollowRedirect(const std::vector<std::string>& removed_headers,
 | |
|                       const net::HttpRequestHeaders& modified_headers,
 | |
|                       const base::Optional<GURL>& new_url) override;
 | |
|   void SetPriority(net::RequestPriority priority,
 | |
|                    int intra_priority_value) override;
 | |
|   void PauseReadingBodyFromNet() override;
 | |
|   void ResumeReadingBodyFromNet() override;
 | |
| 
 | |
|  private:
 | |
|   void ContinueWithRequestHeaders(
 | |
|       int32_t result,
 | |
|       const base::Optional<net::HttpRequestHeaders>& headers);
 | |
|   void OnInputStreamOpened(std::unique_ptr<Delegate> returned_delegate,
 | |
|                            std::unique_ptr<InputStream> input_stream);
 | |
| 
 | |
|   void OnReaderSkipCompleted(int64_t bytes_skipped);
 | |
|   void HeadersComplete(int status_code, int64_t expected_content_length);
 | |
|   void ContinueWithResponseHeaders(int32_t result,
 | |
|                                    const base::Optional<std::string>& headers,
 | |
|                                    const GURL& redirect_url);
 | |
| 
 | |
|   void SendBody();
 | |
|   void ReadMore();
 | |
|   void OnDataPipeWritable(MojoResult result);
 | |
|   void OnReaderReadCompleted(int bytes_read);
 | |
|   void RequestComplete(int status_code);
 | |
| 
 | |
|   void CleanUp();
 | |
| 
 | |
|   bool ParseRange(const net::HttpRequestHeaders& headers);
 | |
|   bool byte_range_valid() const;
 | |
| 
 | |
|   const RequestId request_id_;
 | |
| 
 | |
|   network::ResourceResponseHead pending_response_;
 | |
| 
 | |
|   size_t header_length_ = 0;
 | |
|   int64_t total_bytes_read_ = 0;
 | |
| 
 | |
|   net::HttpByteRange byte_range_;
 | |
|   network::ResourceRequest request_;
 | |
|   network::mojom::URLLoaderClientPtr client_;
 | |
|   network::mojom::TrustedHeaderClientPtr header_client_;
 | |
|   const net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
 | |
|   std::unique_ptr<Delegate> response_delegate_;
 | |
|   scoped_refptr<InputStreamReader> input_stream_reader_;
 | |
| 
 | |
|   mojo::ScopedDataPipeProducerHandle producer_handle_;
 | |
|   scoped_refptr<network::NetToMojoPendingBuffer> pending_buffer_;
 | |
|   mojo::SimpleWatcher writable_handle_watcher_;
 | |
|   base::ThreadChecker thread_checker_;
 | |
| 
 | |
|   scoped_refptr<base::SequencedTaskRunner> stream_work_task_runner_;
 | |
| 
 | |
|   base::OnceClosure open_cancel_callback_;
 | |
| 
 | |
|   base::WeakPtrFactory<StreamReaderURLLoader> weak_factory_;
 | |
| 
 | |
|   DISALLOW_COPY_AND_ASSIGN(StreamReaderURLLoader);
 | |
| };
 | |
| 
 | |
| }  // namespace net_service
 | |
| 
 | |
| #endif  // CEF_LIBCEF_BROWSER_NET_SERVICE_STREAM_READER_URL_LOADER_H_
 |