1 // Copyright 2015 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 #include "services/network/throttling/throttling_upload_data_stream.h"
6 
7 #include "base/bind.h"
8 #include "net/base/net_errors.h"
9 
10 namespace network {
11 
ThrottlingUploadDataStream(net::UploadDataStream * upload_data_stream)12 ThrottlingUploadDataStream::ThrottlingUploadDataStream(
13     net::UploadDataStream* upload_data_stream)
14     : net::UploadDataStream(upload_data_stream->is_chunked(),
15                             upload_data_stream->identifier()),
16       throttle_callback_(
17           base::BindRepeating(&ThrottlingUploadDataStream::ThrottleCallback,
18                               base::Unretained(this))),
19       throttled_byte_count_(0),
20       upload_data_stream_(upload_data_stream) {}
21 
~ThrottlingUploadDataStream()22 ThrottlingUploadDataStream::~ThrottlingUploadDataStream() {
23   if (interceptor_)
24     interceptor_->StopThrottle(throttle_callback_);
25 }
26 
SetInterceptor(ThrottlingNetworkInterceptor * interceptor)27 void ThrottlingUploadDataStream::SetInterceptor(
28     ThrottlingNetworkInterceptor* interceptor) {
29   DCHECK(!interceptor_);
30   if (interceptor)
31     interceptor_ = interceptor->GetWeakPtr();
32 }
33 
IsInMemory() const34 bool ThrottlingUploadDataStream::IsInMemory() const {
35   return false;
36 }
37 
InitInternal(const net::NetLogWithSource & net_log)38 int ThrottlingUploadDataStream::InitInternal(
39     const net::NetLogWithSource& net_log) {
40   throttled_byte_count_ = 0;
41   int result = upload_data_stream_->Init(
42       base::BindOnce(&ThrottlingUploadDataStream::StreamInitCallback,
43                      base::Unretained(this)),
44       net_log);
45   if (result == net::OK && !is_chunked())
46     SetSize(upload_data_stream_->size());
47   return result;
48 }
49 
StreamInitCallback(int result)50 void ThrottlingUploadDataStream::StreamInitCallback(int result) {
51   if (!is_chunked())
52     SetSize(upload_data_stream_->size());
53   OnInitCompleted(result);
54 }
55 
ReadInternal(net::IOBuffer * buf,int buf_len)56 int ThrottlingUploadDataStream::ReadInternal(net::IOBuffer* buf, int buf_len) {
57   int result = upload_data_stream_->Read(
58       buf, buf_len,
59       base::BindOnce(&ThrottlingUploadDataStream::StreamReadCallback,
60                      base::Unretained(this)));
61   return ThrottleRead(result);
62 }
63 
StreamReadCallback(int result)64 void ThrottlingUploadDataStream::StreamReadCallback(int result) {
65   result = ThrottleRead(result);
66   if (result != net::ERR_IO_PENDING)
67     OnReadCompleted(result);
68 }
69 
ThrottleRead(int result)70 int ThrottlingUploadDataStream::ThrottleRead(int result) {
71   if (is_chunked() && upload_data_stream_->IsEOF())
72     SetIsFinalChunk();
73 
74   if (!interceptor_ || result < 0)
75     return result;
76 
77   if (result > 0)
78     throttled_byte_count_ += result;
79   return interceptor_->StartThrottle(result, throttled_byte_count_,
80                                      base::TimeTicks(), false, true,
81                                      throttle_callback_);
82 }
83 
ThrottleCallback(int result,int64_t bytes)84 void ThrottlingUploadDataStream::ThrottleCallback(int result, int64_t bytes) {
85   throttled_byte_count_ = bytes;
86   OnReadCompleted(result);
87 }
88 
ResetInternal()89 void ThrottlingUploadDataStream::ResetInternal() {
90   upload_data_stream_->Reset();
91   throttled_byte_count_ = 0;
92   if (interceptor_)
93     interceptor_->StopThrottle(throttle_callback_);
94 }
95 
96 }  // namespace network
97