• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/base/elements_upload_data_stream.h"
6 
7 #include <utility>
8 
9 #include "base/check_op.h"
10 #include "base/functional/bind.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h"
13 #include "net/base/upload_bytes_element_reader.h"
14 #include "net/base/upload_element_reader.h"
15 
16 namespace net {
17 
ElementsUploadDataStream(std::vector<std::unique_ptr<UploadElementReader>> element_readers,int64_t identifier)18 ElementsUploadDataStream::ElementsUploadDataStream(
19     std::vector<std::unique_ptr<UploadElementReader>> element_readers,
20     int64_t identifier)
21     : UploadDataStream(false, identifier),
22       element_readers_(std::move(element_readers)) {}
23 
24 ElementsUploadDataStream::~ElementsUploadDataStream() = default;
25 
CreateWithReader(std::unique_ptr<UploadElementReader> reader,int64_t identifier)26 std::unique_ptr<UploadDataStream> ElementsUploadDataStream::CreateWithReader(
27     std::unique_ptr<UploadElementReader> reader,
28     int64_t identifier) {
29   std::vector<std::unique_ptr<UploadElementReader>> readers;
30   readers.push_back(std::move(reader));
31   return std::make_unique<ElementsUploadDataStream>(std::move(readers),
32                                                     identifier);
33 }
34 
InitInternal(const NetLogWithSource & net_log)35 int ElementsUploadDataStream::InitInternal(const NetLogWithSource& net_log) {
36   return InitElements(0);
37 }
38 
ReadInternal(IOBuffer * buf,int buf_len)39 int ElementsUploadDataStream::ReadInternal(
40     IOBuffer* buf,
41     int buf_len) {
42   DCHECK_GT(buf_len, 0);
43   return ReadElements(base::MakeRefCounted<DrainableIOBuffer>(buf, buf_len));
44 }
45 
IsInMemory() const46 bool ElementsUploadDataStream::IsInMemory() const {
47   for (const std::unique_ptr<UploadElementReader>& it : element_readers_) {
48     if (!it->IsInMemory())
49       return false;
50   }
51   return true;
52 }
53 
54 const std::vector<std::unique_ptr<UploadElementReader>>*
GetElementReaders() const55 ElementsUploadDataStream::GetElementReaders() const {
56   return &element_readers_;
57 }
58 
ResetInternal()59 void ElementsUploadDataStream::ResetInternal() {
60   weak_ptr_factory_.InvalidateWeakPtrs();
61   read_error_ = OK;
62   element_index_ = 0;
63 }
64 
InitElements(size_t start_index)65 int ElementsUploadDataStream::InitElements(size_t start_index) {
66   // Call Init() for all elements.
67   for (size_t i = start_index; i < element_readers_.size(); ++i) {
68     UploadElementReader* reader = element_readers_[i].get();
69     // When new_result is ERR_IO_PENDING, InitInternal() will be called
70     // with start_index == i + 1 when reader->Init() finishes.
71     int result = reader->Init(
72         base::BindOnce(&ElementsUploadDataStream::OnInitElementCompleted,
73                        weak_ptr_factory_.GetWeakPtr(), i));
74     DCHECK(result != ERR_IO_PENDING || !reader->IsInMemory());
75     DCHECK_LE(result, OK);
76     if (result != OK)
77       return result;
78   }
79 
80   uint64_t total_size = 0;
81   for (const std::unique_ptr<UploadElementReader>& it : element_readers_) {
82     total_size += it->GetContentLength();
83   }
84   SetSize(total_size);
85   return OK;
86 }
87 
OnInitElementCompleted(size_t index,int result)88 void ElementsUploadDataStream::OnInitElementCompleted(size_t index,
89                                                       int result) {
90   DCHECK_NE(ERR_IO_PENDING, result);
91 
92   // Check the last result.
93   if (result == OK)
94     result = InitElements(index + 1);
95 
96   if (result != ERR_IO_PENDING)
97     OnInitCompleted(result);
98 }
99 
ReadElements(const scoped_refptr<DrainableIOBuffer> & buf)100 int ElementsUploadDataStream::ReadElements(
101     const scoped_refptr<DrainableIOBuffer>& buf) {
102   while (read_error_ == OK && element_index_ < element_readers_.size()) {
103     UploadElementReader* reader = element_readers_[element_index_].get();
104 
105     if (reader->BytesRemaining() == 0) {
106       ++element_index_;
107       continue;
108     }
109 
110     if (buf->BytesRemaining() == 0)
111       break;
112 
113     int result = reader->Read(
114         buf.get(), buf->BytesRemaining(),
115         base::BindOnce(&ElementsUploadDataStream::OnReadElementCompleted,
116                        weak_ptr_factory_.GetWeakPtr(), buf));
117     if (result == ERR_IO_PENDING)
118       return ERR_IO_PENDING;
119     ProcessReadResult(buf, result);
120   }
121 
122   if (buf->BytesConsumed() > 0)
123     return buf->BytesConsumed();
124 
125   return read_error_;
126 }
127 
OnReadElementCompleted(const scoped_refptr<DrainableIOBuffer> & buf,int result)128 void ElementsUploadDataStream::OnReadElementCompleted(
129     const scoped_refptr<DrainableIOBuffer>& buf,
130     int result) {
131   ProcessReadResult(buf, result);
132 
133   result = ReadElements(buf);
134   if (result != ERR_IO_PENDING)
135     OnReadCompleted(result);
136 }
137 
ProcessReadResult(const scoped_refptr<DrainableIOBuffer> & buf,int result)138 void ElementsUploadDataStream::ProcessReadResult(
139     const scoped_refptr<DrainableIOBuffer>& buf,
140     int result) {
141   DCHECK_NE(ERR_IO_PENDING, result);
142   DCHECK(!read_error_);
143 
144   if (result >= 0) {
145     buf->DidConsume(result);
146   } else {
147     read_error_ = result;
148   }
149 }
150 
151 }  // namespace net
152