1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef SERVICES_NETWORK_CHUNKED_DATA_PIPE_UPLOAD_DATA_STREAM_H_
6 #define SERVICES_NETWORK_CHUNKED_DATA_PIPE_UPLOAD_DATA_STREAM_H_
7 
8 #include <stdint.h>
9 
10 #include <memory>
11 
12 #include "base/component_export.h"
13 #include "base/macros.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/optional.h"
16 #include "mojo/public/cpp/bindings/pending_remote.h"
17 #include "mojo/public/cpp/bindings/remote.h"
18 #include "mojo/public/cpp/system/data_pipe.h"
19 #include "mojo/public/cpp/system/simple_watcher.h"
20 #include "net/base/completion_once_callback.h"
21 #include "net/base/net_errors.h"
22 #include "net/base/upload_data_stream.h"
23 #include "services/network/public/cpp/resource_request_body.h"
24 #include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
25 
26 namespace net {
27 class IOBuffer;
28 }
29 
30 namespace network {
31 
32 // A subclass of net::UploadDataStream to read data pipes and provide the result
33 // as a chunked upload.
COMPONENT_EXPORT(NETWORK_SERVICE)34 class COMPONENT_EXPORT(NETWORK_SERVICE) ChunkedDataPipeUploadDataStream
35     : public net::UploadDataStream {
36  public:
37   // |resource_request_body| is just passed in to keep the object around for the
38   // life of the UploadDataStream.
39   ChunkedDataPipeUploadDataStream(
40       scoped_refptr<ResourceRequestBody> resource_request_body,
41       mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
42           chunked_data_pipe_getter);
43 
44   ~ChunkedDataPipeUploadDataStream() override;
45 
46  private:
47   // net::UploadDataStream implementation.
48   int InitInternal(const net::NetLogWithSource& net_log) override;
49   int ReadInternal(net::IOBuffer* buf, int buf_len) override;
50   void ResetInternal() override;
51 
52   // Callback invoked by ChunkedDataPipeGetter::GetSize. Can be called any time
53   // - could be called before any of the body is read, could be called after the
54   // entire body is read, could end up not being called, in the case the other
55   // end of the pipe is torn down before the entire upload body is received.
56   void OnSizeReceived(int32_t status, uint64_t size);
57 
58   // Called by |handle_watcher_| when data is available or the pipe was closed,
59   // and there's a pending Read() call.
60   void OnHandleReadable(MojoResult result);
61 
62   void OnDataPipeGetterClosed();
63 
64   scoped_refptr<ResourceRequestBody> resource_request_body_;
65   mojo::Remote<mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter_;
66   mojo::ScopedDataPipeConsumerHandle data_pipe_;
67   // Watcher for |data_pipe_|. Only armed while there's a pending read.
68   mojo::SimpleWatcher handle_watcher_;
69 
70   // Write buffer and its length. Populated when Read() is called but returns
71   // ERR_IO_PENDING. Cleared once the read completes, or ResetInternal() is
72   // invoked.
73   scoped_refptr<net::IOBuffer> buf_;
74   int buf_len_ = 0;
75 
76   // Total size of input, as passed to ReadCallback(). nullptr until size is
77   // received.
78   base::Optional<uint64_t> size_;
79 
80   uint64_t bytes_read_ = 0;
81 
82   // Set to a net::Error other than net::OK if the DataPipeGetter returns an
83   // error.
84   int status_ = net::OK;
85 
86   DISALLOW_COPY_AND_ASSIGN(ChunkedDataPipeUploadDataStream);
87 };
88 
89 }  // namespace network
90 
91 #endif  // SERVICES_NETWORK_CHUNKED_DATA_PIPE_UPLOAD_DATA_STREAM_H_
92