Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Side by Side Diff: content/browser/net/url_request_slow_download_job.cc

Issue 7294013: Modified cancel and interrupt processing to avoid race with history. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed various problems surfaced by trybots. Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698