OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/browser/net/url_request_slow_download_job.h" | 5 #include "content/browser/net/url_request_slow_download_job.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "googleurl/src/gurl.h" | 11 #include "googleurl/src/gurl.h" |
12 #include "net/base/io_buffer.h" | 12 #include "net/base/io_buffer.h" |
13 #include "net/base/net_errors.h" | |
13 #include "net/http/http_response_headers.h" | 14 #include "net/http/http_response_headers.h" |
14 #include "net/url_request/url_request.h" | 15 #include "net/url_request/url_request.h" |
15 #include "net/url_request/url_request_filter.h" | 16 #include "net/url_request/url_request_filter.h" |
17 #include "net/url_request/url_request_status.h" | |
16 | 18 |
17 const int kFirstDownloadSize = 1024 * 35; | 19 const int kFirstDownloadSize = 1024 * 35; |
18 const int kSecondDownloadSize = 1024 * 10; | 20 const int kSecondDownloadSize = 1024 * 10; |
19 | 21 |
20 const char URLRequestSlowDownloadJob::kUnknownSizeUrl[] = | 22 const char URLRequestSlowDownloadJob::kUnknownSizeUrl[] = |
21 "http://url.handled.by.slow.download/download-unknown-size"; | 23 "http://url.handled.by.slow.download/download-unknown-size"; |
22 const char URLRequestSlowDownloadJob::kKnownSizeUrl[] = | 24 const char URLRequestSlowDownloadJob::kKnownSizeUrl[] = |
23 "http://url.handled.by.slow.download/download-known-size"; | 25 "http://url.handled.by.slow.download/download-known-size"; |
24 const char URLRequestSlowDownloadJob::kFinishDownloadUrl[] = | 26 const char URLRequestSlowDownloadJob::kFinishDownloadUrl[] = |
25 "http://url.handled.by.slow.download/download-finish"; | 27 "http://url.handled.by.slow.download/download-finish"; |
28 const char URLRequestSlowDownloadJob::kErrorFinishDownloadUrl[] = | |
29 "http://url.handled.by.slow.download/download-error"; | |
26 | 30 |
27 std::vector<URLRequestSlowDownloadJob*> | 31 std::vector<URLRequestSlowDownloadJob*> |
28 URLRequestSlowDownloadJob::kPendingRequests; | 32 URLRequestSlowDownloadJob::kPendingRequests; |
29 | 33 |
34 // Return whether this is the finish or error URL | |
brettw
2011/07/06 16:44:13
Nit: Need period.
Randy Smith (Not in Mondays)
2011/07/07 22:02:23
Done.
| |
35 static bool IsCompletionUrl(GURL url) { | |
36 return (LowerCaseEqualsASCII( | |
37 URLRequestSlowDownloadJob::kFinishDownloadUrl, url.spec().c_str()) || | |
brettw
2011/07/06 16:44:13
This statement is almost impossible to read. I'd p
Randy Smith (Not in Mondays)
2011/07/07 22:02:23
Done (though it's easier to read with the change r
| |
38 LowerCaseEqualsASCII( | |
eroman
2011/07/06 22:19:01
Why use lowercase URL comparison throughout rather
Randy Smith (Not in Mondays)
2011/07/07 22:02:23
There's no good reason except for compatibility wi
| |
39 URLRequestSlowDownloadJob::kErrorFinishDownloadUrl, | |
40 url.spec().c_str())); | |
41 } | |
42 | |
30 void URLRequestSlowDownloadJob::Start() { | 43 void URLRequestSlowDownloadJob::Start() { |
31 MessageLoop::current()->PostTask( | 44 MessageLoop::current()->PostTask( |
32 FROM_HERE, | 45 FROM_HERE, |
33 method_factory_.NewRunnableMethod( | 46 method_factory_.NewRunnableMethod( |
34 &URLRequestSlowDownloadJob::StartAsync)); | 47 &URLRequestSlowDownloadJob::StartAsync)); |
35 } | 48 } |
36 | 49 |
37 // static | 50 // static |
38 void URLRequestSlowDownloadJob::AddUrlHandler() { | 51 void URLRequestSlowDownloadJob::AddUrlHandler() { |
39 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); | 52 net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); |
40 filter->AddUrlHandler(GURL(kUnknownSizeUrl), | 53 filter->AddUrlHandler(GURL(kUnknownSizeUrl), |
41 &URLRequestSlowDownloadJob::Factory); | 54 &URLRequestSlowDownloadJob::Factory); |
42 filter->AddUrlHandler(GURL(kKnownSizeUrl), | 55 filter->AddUrlHandler(GURL(kKnownSizeUrl), |
43 &URLRequestSlowDownloadJob::Factory); | 56 &URLRequestSlowDownloadJob::Factory); |
44 filter->AddUrlHandler(GURL(kFinishDownloadUrl), | 57 filter->AddUrlHandler(GURL(kFinishDownloadUrl), |
45 &URLRequestSlowDownloadJob::Factory); | 58 &URLRequestSlowDownloadJob::Factory); |
59 filter->AddUrlHandler(GURL(kErrorFinishDownloadUrl), | |
60 &URLRequestSlowDownloadJob::Factory); | |
46 } | 61 } |
47 | 62 |
48 /*static */ | 63 /*static */ |
49 net::URLRequestJob* URLRequestSlowDownloadJob::Factory( | 64 net::URLRequestJob* URLRequestSlowDownloadJob::Factory( |
50 net::URLRequest* request, | 65 net::URLRequest* request, |
51 const std::string& scheme) { | 66 const std::string& scheme) { |
52 URLRequestSlowDownloadJob* job = new URLRequestSlowDownloadJob(request); | 67 URLRequestSlowDownloadJob* job = new URLRequestSlowDownloadJob(request); |
53 if (request->url().spec() != kFinishDownloadUrl) | 68 if (!IsCompletionUrl(request->url())) |
54 URLRequestSlowDownloadJob::kPendingRequests.push_back(job); | 69 URLRequestSlowDownloadJob::kPendingRequests.push_back(job); |
55 return job; | 70 return job; |
56 } | 71 } |
57 | 72 |
58 /* static */ | 73 /* static */ |
59 void URLRequestSlowDownloadJob::FinishPendingRequests() { | 74 void URLRequestSlowDownloadJob::FinishPendingRequests(bool error) { |
60 typedef std::vector<URLRequestSlowDownloadJob*> JobList; | 75 typedef std::vector<URLRequestSlowDownloadJob*> JobList; |
61 for (JobList::iterator it = kPendingRequests.begin(); it != | 76 for (JobList::iterator it = kPendingRequests.begin(); it != |
62 kPendingRequests.end(); ++it) { | 77 kPendingRequests.end(); ++it) { |
eroman
2011/07/06 22:19:01
The following comment predates this change.... but
Randy Smith (Not in Mondays)
2011/07/07 22:02:23
Done.
| |
63 (*it)->set_should_finish_download(); | 78 if (error) { |
79 (*it)->set_should_error_download(); | |
80 } else { | |
81 (*it)->set_should_finish_download(); | |
82 } | |
64 } | 83 } |
65 kPendingRequests.clear(); | 84 kPendingRequests.clear(); |
66 } | 85 } |
67 | 86 |
68 URLRequestSlowDownloadJob::URLRequestSlowDownloadJob(net::URLRequest* request) | 87 URLRequestSlowDownloadJob::URLRequestSlowDownloadJob(net::URLRequest* request) |
69 : net::URLRequestJob(request), | 88 : net::URLRequestJob(request), |
70 first_download_size_remaining_(kFirstDownloadSize), | 89 first_download_size_remaining_(kFirstDownloadSize), |
71 should_finish_download_(false), | 90 should_finish_download_(false), |
72 should_send_second_chunk_(false), | 91 should_send_second_chunk_(false), |
92 should_error_download_(false), | |
73 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {} | 93 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {} |
74 | 94 |
75 void URLRequestSlowDownloadJob::StartAsync() { | 95 void URLRequestSlowDownloadJob::StartAsync() { |
76 if (LowerCaseEqualsASCII(kFinishDownloadUrl, request_->url().spec().c_str())) | 96 if (LowerCaseEqualsASCII(kFinishDownloadUrl, request_->url().spec().c_str())) |
eroman
2011/07/06 22:19:01
Same comment as before: I think we should use exac
Randy Smith (Not in Mondays)
2011/07/07 22:02:23
Done.
| |
77 URLRequestSlowDownloadJob::FinishPendingRequests(); | 97 URLRequestSlowDownloadJob::FinishPendingRequests(false); |
98 | |
99 if (LowerCaseEqualsASCII(kErrorFinishDownloadUrl, | |
eroman
2011/07/06 22:19:01
ditto
Randy Smith (Not in Mondays)
2011/07/07 22:02:23
Done.
| |
100 request_->url().spec().c_str())) { | |
101 URLRequestSlowDownloadJob::FinishPendingRequests(true); | |
102 } | |
78 | 103 |
79 NotifyHeadersComplete(); | 104 NotifyHeadersComplete(); |
80 } | 105 } |
81 | 106 |
82 bool URLRequestSlowDownloadJob::ReadRawData(net::IOBuffer* buf, int buf_size, | 107 bool URLRequestSlowDownloadJob::ReadRawData(net::IOBuffer* buf, int buf_size, |
83 int *bytes_read) { | 108 int *bytes_read) { |
84 if (LowerCaseEqualsASCII(kFinishDownloadUrl, | 109 if (IsCompletionUrl(request_->url())) { |
85 request_->url().spec().c_str())) { | |
86 *bytes_read = 0; | 110 *bytes_read = 0; |
87 return true; | 111 return true; |
88 } | 112 } |
89 | 113 |
90 if (should_send_second_chunk_) { | 114 if (should_send_second_chunk_) { |
91 DCHECK(buf_size > kSecondDownloadSize); | 115 DCHECK(buf_size > kSecondDownloadSize); |
92 for (int i = 0; i < kSecondDownloadSize; ++i) { | 116 for (int i = 0; i < kSecondDownloadSize; ++i) { |
93 buf->data()[i] = '*'; | 117 buf->data()[i] = '*'; |
94 } | 118 } |
95 *bytes_read = kSecondDownloadSize; | 119 *bytes_read = kSecondDownloadSize; |
(...skipping 29 matching lines...) Expand all Loading... | |
125 | 149 |
126 // Return false to signal there is pending data. | 150 // Return false to signal there is pending data. |
127 return false; | 151 return false; |
128 } | 152 } |
129 | 153 |
130 void URLRequestSlowDownloadJob::CheckDoneStatus() { | 154 void URLRequestSlowDownloadJob::CheckDoneStatus() { |
131 if (should_finish_download_) { | 155 if (should_finish_download_) { |
132 should_send_second_chunk_ = true; | 156 should_send_second_chunk_ = true; |
133 SetStatus(net::URLRequestStatus()); | 157 SetStatus(net::URLRequestStatus()); |
134 NotifyReadComplete(kSecondDownloadSize); | 158 NotifyReadComplete(kSecondDownloadSize); |
159 } else if (should_error_download_) { | |
160 NotifyDone( | |
161 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); | |
135 } else { | 162 } else { |
136 MessageLoop::current()->PostDelayedTask( | 163 MessageLoop::current()->PostDelayedTask( |
137 FROM_HERE, | 164 FROM_HERE, |
138 method_factory_.NewRunnableMethod( | 165 method_factory_.NewRunnableMethod( |
139 &URLRequestSlowDownloadJob::CheckDoneStatus), | 166 &URLRequestSlowDownloadJob::CheckDoneStatus), |
140 100); | 167 100); |
141 } | 168 } |
142 } | 169 } |
143 | 170 |
144 // Public virtual version. | 171 // Public virtual version. |
145 void URLRequestSlowDownloadJob::GetResponseInfo(net::HttpResponseInfo* info) { | 172 void URLRequestSlowDownloadJob::GetResponseInfo(net::HttpResponseInfo* info) { |
146 // Forward to private const version. | 173 // Forward to private const version. |
147 GetResponseInfoConst(info); | 174 GetResponseInfoConst(info); |
148 } | 175 } |
149 | 176 |
150 URLRequestSlowDownloadJob::~URLRequestSlowDownloadJob() {} | 177 URLRequestSlowDownloadJob::~URLRequestSlowDownloadJob() {} |
151 | 178 |
152 // Private const version. | 179 // Private const version. |
153 void URLRequestSlowDownloadJob::GetResponseInfoConst( | 180 void URLRequestSlowDownloadJob::GetResponseInfoConst( |
154 net::HttpResponseInfo* info) const { | 181 net::HttpResponseInfo* info) const { |
155 // Send back mock headers. | 182 // Send back mock headers. |
156 std::string raw_headers; | 183 std::string raw_headers; |
157 if (LowerCaseEqualsASCII(kFinishDownloadUrl, | 184 if (IsCompletionUrl(request_->url())) { |
158 request_->url().spec().c_str())) { | |
159 raw_headers.append( | 185 raw_headers.append( |
160 "HTTP/1.1 200 OK\n" | 186 "HTTP/1.1 200 OK\n" |
161 "Content-type: text/plain\n"); | 187 "Content-type: text/plain\n"); |
162 } else { | 188 } else { |
163 raw_headers.append( | 189 raw_headers.append( |
164 "HTTP/1.1 200 OK\n" | 190 "HTTP/1.1 200 OK\n" |
165 "Content-type: application/octet-stream\n" | 191 "Content-type: application/octet-stream\n" |
166 "Cache-Control: max-age=0\n"); | 192 "Cache-Control: max-age=0\n"); |
167 | 193 |
168 if (LowerCaseEqualsASCII(kKnownSizeUrl, request_->url().spec().c_str())) { | 194 if (LowerCaseEqualsASCII(kKnownSizeUrl, request_->url().spec().c_str())) { |
169 raw_headers.append(base::StringPrintf( | 195 raw_headers.append(base::StringPrintf( |
170 "Content-Length: %d\n", | 196 "Content-Length: %d\n", |
171 kFirstDownloadSize + kSecondDownloadSize)); | 197 kFirstDownloadSize + kSecondDownloadSize)); |
172 } | 198 } |
173 } | 199 } |
174 | 200 |
175 // ParseRawHeaders expects \0 to end each header line. | 201 // ParseRawHeaders expects \0 to end each header line. |
176 ReplaceSubstringsAfterOffset(&raw_headers, 0, "\n", std::string("\0", 1)); | 202 ReplaceSubstringsAfterOffset(&raw_headers, 0, "\n", std::string("\0", 1)); |
177 info->headers = new net::HttpResponseHeaders(raw_headers); | 203 info->headers = new net::HttpResponseHeaders(raw_headers); |
178 } | 204 } |
179 | 205 |
180 bool URLRequestSlowDownloadJob::GetMimeType(std::string* mime_type) const { | 206 bool URLRequestSlowDownloadJob::GetMimeType(std::string* mime_type) const { |
181 net::HttpResponseInfo info; | 207 net::HttpResponseInfo info; |
182 GetResponseInfoConst(&info); | 208 GetResponseInfoConst(&info); |
183 return info.headers && info.headers->GetMimeType(mime_type); | 209 return info.headers && info.headers->GetMimeType(mime_type); |
184 } | 210 } |
OLD | NEW |