OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/url_request/sdch_dictionary_fetcher.h" | 5 #include "net/url_request/sdch_dictionary_fetcher.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
53 // TODO(rdsmith): log this error to the net log of the URLRequest | 53 // TODO(rdsmith): log this error to the net log of the URLRequest |
54 // initiating this fetch, once URLRequest will be passed here. | 54 // initiating this fetch, once URLRequest will be passed here. |
55 SdchManager::SdchErrorRecovery( | 55 SdchManager::SdchErrorRecovery( |
56 SDCH_DICTIONARY_PREVIOUSLY_SCHEDULED_TO_DOWNLOAD); | 56 SDCH_DICTIONARY_PREVIOUSLY_SCHEDULED_TO_DOWNLOAD); |
57 return; | 57 return; |
58 } | 58 } |
59 | 59 |
60 attempted_load_.insert(dictionary_url); | 60 attempted_load_.insert(dictionary_url); |
61 fetch_queue_.push(dictionary_url); | 61 fetch_queue_.push(dictionary_url); |
62 | 62 |
63 next_state_ = STATE_IDLE; | 63 next_state_ = STATE_SEND_REQUEST; |
64 | 64 |
65 // There are no callbacks to user code from the dictionary fetcher, | 65 // There are no callbacks to user code from the dictionary fetcher, |
66 // and Schedule() is only called from user code, so this call to DoLoop() | 66 // and Schedule() is only called from user code, so this call to DoLoop() |
67 // does not require an |if (in_loop_) return;| guard. | 67 // does not require an |if (in_loop_) return;| guard. |
68 DoLoop(OK); | 68 DoLoop(OK); |
69 } | 69 } |
70 | 70 |
71 void SdchDictionaryFetcher::Cancel() { | 71 void SdchDictionaryFetcher::Cancel() { |
72 DCHECK(CalledOnValidThread()); | 72 DCHECK(CalledOnValidThread()); |
73 | 73 |
74 next_state_ = STATE_NONE; | 74 next_state_ = STATE_NONE; |
75 | 75 |
76 while (!fetch_queue_.empty()) | 76 while (!fetch_queue_.empty()) |
77 fetch_queue_.pop(); | 77 fetch_queue_.pop(); |
78 attempted_load_.clear(); | 78 attempted_load_.clear(); |
79 weak_factory_.InvalidateWeakPtrs(); | 79 weak_factory_.InvalidateWeakPtrs(); |
80 current_request_.reset(NULL); | 80 current_request_.reset(NULL); |
81 buffer_ = NULL; | 81 buffer_ = NULL; |
82 dictionary_.clear(); | 82 dictionary_.clear(); |
83 } | 83 } |
84 | 84 |
85 void SdchDictionaryFetcher::OnResponseStarted(URLRequest* request) { | 85 void SdchDictionaryFetcher::OnResponseStarted(URLRequest* request) { |
86 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. | 86 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. |
87 tracked_objects::ScopedTracker tracking_profile( | 87 tracked_objects::ScopedTracker tracking_profile( |
88 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 88 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
89 "423948 SdchDictionaryFetcher::OnResponseStarted")); | 89 "423948 SdchDictionaryFetcher::OnResponseStarted")); |
90 | 90 |
91 DCHECK(CalledOnValidThread()); | 91 DCHECK(CalledOnValidThread()); |
92 DCHECK_EQ(request, current_request_.get()); | 92 DCHECK_EQ(request, current_request_.get()); |
93 DCHECK_EQ(next_state_, STATE_REQUEST_STARTED); | 93 DCHECK_EQ(next_state_, STATE_SEND_REQUEST_COMPLETE); |
94 | 94 DCHECK(!in_loop_); |
95 // The response has started, so the stream can be read from. | |
96 next_state_ = STATE_REQUEST_READING; | |
97 | |
98 // If this function was synchronously called, the containing | |
99 // state machine loop will handle the state transition. Otherwise, | |
100 // restart the state machine loop. | |
101 if (in_loop_) | |
102 return; | |
103 | 95 |
104 DoLoop(request->status().error()); | 96 DoLoop(request->status().error()); |
105 } | 97 } |
106 | 98 |
107 void SdchDictionaryFetcher::OnReadCompleted(URLRequest* request, | 99 void SdchDictionaryFetcher::OnReadCompleted(URLRequest* request, |
108 int bytes_read) { | 100 int bytes_read) { |
109 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. | 101 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. |
110 tracked_objects::ScopedTracker tracking_profile( | 102 tracked_objects::ScopedTracker tracking_profile( |
111 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 103 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
112 "423948 SdchDictionaryFetcher::OnReadCompleted")); | 104 "423948 SdchDictionaryFetcher::OnReadCompleted")); |
113 | 105 |
114 DCHECK(CalledOnValidThread()); | 106 DCHECK(CalledOnValidThread()); |
115 DCHECK_EQ(request, current_request_.get()); | 107 DCHECK_EQ(request, current_request_.get()); |
116 DCHECK_EQ(next_state_, STATE_REQUEST_READING); | 108 DCHECK_EQ(next_state_, STATE_READ_BODY_COMPLETE); |
109 DCHECK(!in_loop_); | |
117 | 110 |
118 // No state transition is required in this function; the | 111 DoLoop(HandleReadCompletion(bytes_read)); |
119 // completion of the request is detected in DoRead(). | 112 } |
120 | 113 |
121 if (request->status().is_success()) | 114 int SdchDictionaryFetcher::HandleReadCompletion(int bytes_read) { |
mmenke
2015/01/26 16:40:12
I suggest moving the append and state transition i
Randy Smith (Not in Mondays)
2015/01/26 19:52:21
Done.
| |
115 int error = current_request_->status().error(); | |
116 if (current_request_->status().is_success() && bytes_read < 0) { | |
mmenke
2015/01/26 16:40:12
Can this even happen?
Randy Smith (Not in Mondays)
2015/01/26 19:52:23
That's a fascinating question. I thought the answ
| |
117 error = current_request_->status().status() == URLRequestStatus::CANCELED | |
118 ? ERR_ABORTED | |
119 : ERR_FAILED; | |
120 current_request_->net_log().AddEventWithNetErrorCode( | |
121 NetLog::TYPE_SDCH_DICTIONARY_FETCH_IMPLIED_ERROR, error); | |
122 } | |
123 | |
124 if (error == OK && bytes_read > 0) | |
122 dictionary_.append(buffer_->data(), bytes_read); | 125 dictionary_.append(buffer_->data(), bytes_read); |
123 | 126 |
124 // If this function was synchronously called, the containing | 127 if (error == OK && bytes_read == 0) |
125 // state machine loop will handle the state transition. Otherwise, | 128 next_state_ = STATE_REQUEST_COMPLETE; |
126 // restart the state machine loop. | |
127 if (in_loop_) | |
128 return; | |
129 | 129 |
130 DoLoop(request->status().error()); | 130 return error; |
131 } | 131 } |
132 | 132 |
133 int SdchDictionaryFetcher::DoLoop(int rv) { | 133 int SdchDictionaryFetcher::DoLoop(int rv) { |
134 DCHECK(!in_loop_); | 134 DCHECK(!in_loop_); |
135 base::AutoReset<bool> auto_reset_in_loop(&in_loop_, true); | 135 base::AutoReset<bool> auto_reset_in_loop(&in_loop_, true); |
136 | 136 |
137 do { | 137 do { |
138 State state = next_state_; | 138 State state = next_state_; |
139 next_state_ = STATE_NONE; | 139 next_state_ = STATE_NONE; |
140 switch (state) { | 140 switch (state) { |
141 case STATE_IDLE: | 141 case STATE_SEND_REQUEST: |
142 rv = DoDispatchRequest(rv); | 142 rv = DoSendRequest(rv); |
143 break; | 143 break; |
144 case STATE_REQUEST_STARTED: | 144 case STATE_SEND_REQUEST_COMPLETE: |
145 rv = DoRequestStarted(rv); | 145 rv = DoSendRequestComplete(rv); |
146 break; | 146 break; |
147 case STATE_REQUEST_READING: | 147 case STATE_READ_BODY: |
148 rv = DoRead(rv); | 148 rv = DoReadBody(rv); |
149 break; | |
150 case STATE_READ_BODY_COMPLETE: | |
151 rv = DoReadBodyComplete(rv); | |
149 break; | 152 break; |
150 case STATE_REQUEST_COMPLETE: | 153 case STATE_REQUEST_COMPLETE: |
151 rv = DoCompleteRequest(rv); | 154 rv = DoCompleteRequest(rv); |
152 break; | 155 break; |
153 case STATE_NONE: | 156 case STATE_NONE: |
154 NOTREACHED(); | 157 NOTREACHED(); |
155 } | 158 } |
156 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 159 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
157 | 160 |
158 return rv; | 161 return rv; |
159 } | 162 } |
160 | 163 |
161 int SdchDictionaryFetcher::DoDispatchRequest(int rv) { | 164 int SdchDictionaryFetcher::DoSendRequest(int rv) { |
162 DCHECK(CalledOnValidThread()); | 165 DCHECK(CalledOnValidThread()); |
163 | 166 |
164 // |rv| is ignored, as the result from the previous request doesn't | 167 // |rv| is ignored, as the result from the previous request doesn't |
165 // affect the next request. | 168 // affect the next request. |
166 | 169 |
167 if (fetch_queue_.empty() || current_request_.get()) { | 170 if (fetch_queue_.empty() || current_request_.get()) { |
168 next_state_ = STATE_NONE; | 171 next_state_ = STATE_NONE; |
169 return OK; | 172 return OK; |
170 } | 173 } |
171 | 174 |
175 next_state_ = STATE_SEND_REQUEST_COMPLETE; | |
176 | |
172 current_request_ = | 177 current_request_ = |
173 context_->CreateRequest(fetch_queue_.front(), IDLE, this, NULL); | 178 context_->CreateRequest(fetch_queue_.front(), IDLE, this, NULL); |
174 current_request_->SetLoadFlags(LOAD_DO_NOT_SEND_COOKIES | | 179 current_request_->SetLoadFlags(LOAD_DO_NOT_SEND_COOKIES | |
175 LOAD_DO_NOT_SAVE_COOKIES); | 180 LOAD_DO_NOT_SAVE_COOKIES); |
176 buffer_ = new IOBuffer(kBufferSize); | 181 buffer_ = new IOBuffer(kBufferSize); |
177 fetch_queue_.pop(); | 182 fetch_queue_.pop(); |
178 | 183 |
179 next_state_ = STATE_REQUEST_STARTED; | |
180 current_request_->Start(); | 184 current_request_->Start(); |
181 current_request_->net_log().AddEvent(NetLog::TYPE_SDCH_DICTIONARY_FETCH); | 185 current_request_->net_log().AddEvent(NetLog::TYPE_SDCH_DICTIONARY_FETCH); |
182 | 186 |
183 return OK; | |
184 } | |
185 | |
186 int SdchDictionaryFetcher::DoRequestStarted(int rv) { | |
187 DCHECK(CalledOnValidThread()); | |
188 DCHECK_EQ(rv, OK); // Can only come straight from above function. | |
189 | |
190 // The transition to STATE_REQUEST_READING occurs in the | |
191 // OnResponseStarted() callback triggered by URLRequest::Start() | |
192 // (called in DoDispatchRequest(), above). If that callback did not | |
193 // occur synchronously, this routine is executed; it returns ERR_IO_PENDING, | |
194 // indicating to the controlling loop that no further work should be done | |
195 // until the callback occurs (which will re-invoke DoLoop()). | |
196 next_state_ = STATE_REQUEST_STARTED; | |
197 return ERR_IO_PENDING; | 187 return ERR_IO_PENDING; |
198 } | 188 } |
199 | 189 |
200 int SdchDictionaryFetcher::DoRead(int rv) { | 190 int SdchDictionaryFetcher::DoSendRequestComplete(int rv) { |
201 DCHECK(CalledOnValidThread()); | 191 DCHECK(CalledOnValidThread()); |
202 | 192 |
203 // If there's been an error, abort the current request. | 193 // If there's been an error, abort the current request. |
204 if (rv != OK) { | 194 if (rv != OK) { |
205 current_request_.reset(); | 195 current_request_.reset(); |
206 buffer_ = NULL; | 196 buffer_ = NULL; |
207 next_state_ = STATE_IDLE; | 197 next_state_ = STATE_SEND_REQUEST; |
208 | 198 |
209 return OK; | 199 return OK; |
210 } | 200 } |
211 | 201 |
212 next_state_ = STATE_REQUEST_READING; | 202 next_state_ = STATE_READ_BODY; |
203 return OK; | |
204 } | |
205 | |
206 int SdchDictionaryFetcher::DoReadBody(int rv) { | |
207 DCHECK(CalledOnValidThread()); | |
208 | |
209 // If there's been an error, abort the current request. | |
210 if (rv != OK) { | |
211 current_request_.reset(); | |
212 buffer_ = NULL; | |
213 next_state_ = STATE_SEND_REQUEST; | |
214 | |
215 return OK; | |
216 } | |
217 | |
218 next_state_ = STATE_READ_BODY_COMPLETE; | |
213 int bytes_read = 0; | 219 int bytes_read = 0; |
214 current_request_->Read(buffer_.get(), kBufferSize, &bytes_read); | 220 current_request_->Read(buffer_.get(), kBufferSize, &bytes_read); |
215 if (current_request_->status().is_io_pending()) | 221 if (current_request_->status().is_io_pending()) |
216 return ERR_IO_PENDING; | 222 return ERR_IO_PENDING; |
217 | 223 |
218 if (bytes_read < 0 || !current_request_->status().is_success()) { | 224 return HandleReadCompletion(bytes_read); |
219 if (current_request_->status().error() != OK) | 225 } |
220 return current_request_->status().error(); | |
221 | 226 |
222 // An error with request status of OK should not happen, | 227 int SdchDictionaryFetcher::DoReadBodyComplete(int rv) { |
223 // but there's enough machinery underneath URLRequest::Read() | 228 DCHECK(CalledOnValidThread()); |
224 // that this routine checks for that case. | 229 |
225 net::Error error = | 230 // If there's been an error, abort the current request. |
226 current_request_->status().status() == URLRequestStatus::CANCELED ? | 231 if (rv != OK) { |
227 ERR_ABORTED : ERR_FAILED; | 232 current_request_.reset(); |
228 current_request_->net_log().AddEventWithNetErrorCode( | 233 buffer_ = NULL; |
229 NetLog::TYPE_SDCH_DICTIONARY_FETCH_IMPLIED_ERROR, error); | 234 next_state_ = STATE_SEND_REQUEST; |
230 return error; | 235 |
236 return OK; | |
231 } | 237 } |
232 | 238 |
233 if (bytes_read == 0) | 239 DCHECK(current_request_->status().is_success()); |
234 next_state_ = STATE_REQUEST_COMPLETE; | 240 |
235 else | 241 next_state_ = STATE_READ_BODY; |
236 dictionary_.append(buffer_->data(), bytes_read); | |
237 | 242 |
238 return OK; | 243 return OK; |
239 } | 244 } |
240 | 245 |
241 int SdchDictionaryFetcher::DoCompleteRequest(int rv) { | 246 int SdchDictionaryFetcher::DoCompleteRequest(int rv) { |
242 DCHECK(CalledOnValidThread()); | 247 DCHECK(CalledOnValidThread()); |
243 | 248 |
244 // If the dictionary was successfully fetched, add it to the manager. | 249 // HandleReadCompletion() only transitions to this state |
245 if (rv == OK) { | 250 // on success. |
246 dictionary_fetched_callback_.Run(dictionary_, current_request_->url(), | 251 DCHECK_EQ(OK, rv); |
247 current_request_->net_log()); | |
248 } | |
249 | 252 |
253 dictionary_fetched_callback_.Run(dictionary_, current_request_->url(), | |
254 current_request_->net_log()); | |
250 current_request_.reset(); | 255 current_request_.reset(); |
251 buffer_ = NULL; | 256 buffer_ = NULL; |
252 dictionary_.clear(); | 257 dictionary_.clear(); |
253 | 258 |
254 next_state_ = STATE_IDLE; | 259 next_state_ = STATE_SEND_REQUEST; |
255 | 260 |
256 return OK; | 261 return OK; |
257 } | 262 } |
258 | 263 |
259 } // namespace net | 264 } // namespace net |
OLD | NEW |