Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / http / http_response_body_drainer.cc
1 // Copyright (c) 2012 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 "net/http/http_response_body_drainer.h"
6
7 #include "base/compiler_specific.h"
8 #include "base/logging.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
11 #include "net/http/http_network_session.h"
12 #include "net/http/http_stream.h"
13
14 namespace net {
15
16 HttpResponseBodyDrainer::HttpResponseBodyDrainer(HttpStream* stream)
17     : stream_(stream),
18       next_state_(STATE_NONE),
19       total_read_(0),
20       session_(NULL) {}
21
22 HttpResponseBodyDrainer::~HttpResponseBodyDrainer() {}
23
24 void HttpResponseBodyDrainer::Start(HttpNetworkSession* session) {
25   read_buf_ = new IOBuffer(kDrainBodyBufferSize);
26   next_state_ = STATE_DRAIN_RESPONSE_BODY;
27   int rv = DoLoop(OK);
28
29   if (rv == ERR_IO_PENDING) {
30     timer_.Start(FROM_HERE,
31                  base::TimeDelta::FromSeconds(kTimeoutInSeconds),
32                  this,
33                  &HttpResponseBodyDrainer::OnTimerFired);
34     session_ = session;
35     session->AddResponseDrainer(this);
36     return;
37   }
38
39   Finish(rv);
40 }
41
42 int HttpResponseBodyDrainer::DoLoop(int result) {
43   DCHECK_NE(next_state_, STATE_NONE);
44
45   int rv = result;
46   do {
47     State state = next_state_;
48     next_state_ = STATE_NONE;
49     switch (state) {
50       case STATE_DRAIN_RESPONSE_BODY:
51         DCHECK_EQ(OK, rv);
52         rv = DoDrainResponseBody();
53         break;
54       case STATE_DRAIN_RESPONSE_BODY_COMPLETE:
55         rv = DoDrainResponseBodyComplete(rv);
56         break;
57       default:
58         NOTREACHED() << "bad state";
59         rv = ERR_UNEXPECTED;
60         break;
61     }
62   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
63
64   return rv;
65 }
66
67 int HttpResponseBodyDrainer::DoDrainResponseBody() {
68   next_state_ = STATE_DRAIN_RESPONSE_BODY_COMPLETE;
69
70   return stream_->ReadResponseBody(
71       read_buf_.get(),
72       kDrainBodyBufferSize - total_read_,
73       base::Bind(&HttpResponseBodyDrainer::OnIOComplete,
74                  base::Unretained(this)));
75 }
76
77 int HttpResponseBodyDrainer::DoDrainResponseBodyComplete(int result) {
78   DCHECK_NE(ERR_IO_PENDING, result);
79
80   if (result < 0)
81     return result;
82
83   total_read_ += result;
84   if (stream_->IsResponseBodyComplete())
85     return OK;
86
87   DCHECK_LE(total_read_, kDrainBodyBufferSize);
88   if (total_read_ >= kDrainBodyBufferSize)
89     return ERR_RESPONSE_BODY_TOO_BIG_TO_DRAIN;
90
91   if (result == 0)
92     return ERR_CONNECTION_CLOSED;
93
94   next_state_ = STATE_DRAIN_RESPONSE_BODY;
95   return OK;
96 }
97
98 void HttpResponseBodyDrainer::OnIOComplete(int result) {
99   int rv = DoLoop(result);
100   if (rv != ERR_IO_PENDING) {
101     timer_.Stop();
102     Finish(rv);
103   }
104 }
105
106 void HttpResponseBodyDrainer::OnTimerFired() {
107   Finish(ERR_TIMED_OUT);
108 }
109
110 void HttpResponseBodyDrainer::Finish(int result) {
111   DCHECK_NE(ERR_IO_PENDING, result);
112
113   if (session_)
114     session_->RemoveResponseDrainer(this);
115
116   if (result < 0) {
117     stream_->Close(true /* no keep-alive */);
118   } else {
119     DCHECK_EQ(OK, result);
120     stream_->Close(false /* keep-alive */);
121   }
122
123   delete this;
124 }
125
126 }  // namespace net