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

Side by Side Diff: android_webview/browser/net/android_stream_reader_url_request_job.cc

Issue 11428052: [android_webview] Fix use after free in intercepted requests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years 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) 2012 The Chromium Authors. All rights reserved. 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 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 "android_webview/browser/net/android_stream_reader_url_request_job.h" 5 #include "android_webview/browser/net/android_stream_reader_url_request_job.h"
6 6
7 #include "android_webview/browser/input_stream.h" 7 #include "android_webview/browser/input_stream.h"
8 #include "android_webview/browser/net/input_stream_reader.h" 8 #include "android_webview/browser/net/input_stream_reader.h"
9 #include "base/android/jni_android.h" 9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h" 10 #include "base/android/jni_string.h"
(...skipping 12 matching lines...) Expand all
23 #include "net/http/http_util.h" 23 #include "net/http/http_util.h"
24 #include "net/url_request/url_request.h" 24 #include "net/url_request/url_request.h"
25 #include "net/url_request/url_request_job_manager.h" 25 #include "net/url_request/url_request_job_manager.h"
26 26
27 using android_webview::InputStream; 27 using android_webview::InputStream;
28 using android_webview::InputStreamReader; 28 using android_webview::InputStreamReader;
29 using base::android::AttachCurrentThread; 29 using base::android::AttachCurrentThread;
30 using base::PostTaskAndReplyWithResult; 30 using base::PostTaskAndReplyWithResult;
31 using content::BrowserThread; 31 using content::BrowserThread;
32 32
33 AndroidStreamReaderURLRequestJob::InputStreamReaderWrapper::
34 InputStreamReaderWrapper(
35 scoped_ptr<InputStream> input_stream,
36 scoped_ptr<InputStreamReader> input_stream_reader)
37 : input_stream_(input_stream.Pass()),
38 input_stream_reader_(input_stream_reader.Pass()) {
39 DCHECK(input_stream_);
40 DCHECK(input_stream_reader_);
41 }
42
43 AndroidStreamReaderURLRequestJob::InputStreamReaderWrapper::
44 ~InputStreamReaderWrapper() {
45 }
46
47 int AndroidStreamReaderURLRequestJob::InputStreamReaderWrapper::Seek(
48 const net::HttpByteRange& byte_range) {
49 return input_stream_reader_->Seek(byte_range);
50 }
51
52 int AndroidStreamReaderURLRequestJob::InputStreamReaderWrapper::ReadRawData(
53 net::IOBuffer* buffer, int buffer_size) {
54 return input_stream_reader_->ReadRawData(buffer, buffer_size);
55 }
56
33 AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob( 57 AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob(
34 net::URLRequest* request, 58 net::URLRequest* request,
35 net::NetworkDelegate* network_delegate, 59 net::NetworkDelegate* network_delegate,
36 scoped_ptr<Delegate> delegate) 60 scoped_ptr<Delegate> delegate)
37 : URLRequestJob(request, network_delegate), 61 : URLRequestJob(request, network_delegate),
38 delegate_(delegate.Pass()), 62 delegate_(delegate.Pass()),
39 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { 63 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
40 DCHECK(delegate_.get()); 64 DCHECK(delegate_.get());
41 } 65 }
42 66
43 AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() { 67 AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() {
44 } 68 }
45 69
46 void AndroidStreamReaderURLRequestJob::Start() { 70 void AndroidStreamReaderURLRequestJob::Start() {
47 // Start reading asynchronously so that all error reporting and data 71 // Start reading asynchronously so that all error reporting and data
48 // callbacks happen as they would for network requests. 72 // callbacks happen as they would for network requests.
49 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); 73 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
50 MessageLoop::current()->PostTask( 74 MessageLoop::current()->PostTask(
51 FROM_HERE, 75 FROM_HERE,
52 base::Bind( 76 base::Bind(
53 &AndroidStreamReaderURLRequestJob::StartAsync, 77 &AndroidStreamReaderURLRequestJob::StartAsync,
54 weak_factory_.GetWeakPtr())); 78 weak_factory_.GetWeakPtr()));
55 } 79 }
56 80
57 void AndroidStreamReaderURLRequestJob::Kill() { 81 void AndroidStreamReaderURLRequestJob::Kill() {
58 weak_factory_.InvalidateWeakPtrs(); 82 weak_factory_.InvalidateWeakPtrs();
59 URLRequestJob::Kill(); 83 URLRequestJob::Kill();
60 } 84 }
61 85
62 scoped_refptr<InputStreamReader> 86 scoped_ptr<InputStreamReader>
63 AndroidStreamReaderURLRequestJob::CreateStreamReader(InputStream* stream) { 87 AndroidStreamReaderURLRequestJob::CreateStreamReader(InputStream* stream) {
64 return make_scoped_refptr(new InputStreamReader(stream)); 88 return make_scoped_ptr(new InputStreamReader(stream));
65 } 89 }
66 90
67 void AndroidStreamReaderURLRequestJob::StartAsync() { 91 void AndroidStreamReaderURLRequestJob::StartAsync() {
68 JNIEnv* env = AttachCurrentThread(); 92 JNIEnv* env = AttachCurrentThread();
69 DCHECK(env); 93 DCHECK(env);
70 94
71 // This could be done in the InputStreamReader but would force more 95 // This could be done in the InputStreamReader but would force more
72 // complex synchronization in the delegate. 96 // complex synchronization in the delegate.
73 stream_ = delegate_->OpenInputStream(env, request()); 97 scoped_ptr<android_webview::InputStream> stream(
74 if (!stream_) { 98 delegate_->OpenInputStream(env, request()));
75 NotifyDone( 99
76 net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED)); 100 if (!stream) {
101 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
102 net::ERR_FAILED));
77 return; 103 return;
78 } 104 }
79 105
80 DCHECK(!input_stream_reader_); 106 scoped_ptr<InputStreamReader> input_stream_reader(
81 input_stream_reader_ = CreateStreamReader(stream_.get()); 107 CreateStreamReader(stream.get()));
82 CHECK(input_stream_reader_); 108 DCHECK(input_stream_reader);
109
110 DCHECK(!input_stream_reader_wrapper_);
111 input_stream_reader_wrapper_ =
112 new InputStreamReaderWrapper(stream.Pass(), input_stream_reader.Pass());
83 113
84 PostTaskAndReplyWithResult( 114 PostTaskAndReplyWithResult(
85 GetWorkerThreadRunner(), 115 GetWorkerThreadRunner(),
86 FROM_HERE, 116 FROM_HERE,
87 base::Bind(&InputStreamReader::Seek, input_stream_reader_, byte_range_), 117 base::Bind(&InputStreamReaderWrapper::Seek,
118 input_stream_reader_wrapper_,
119 byte_range_),
88 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted, 120 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted,
89 weak_factory_.GetWeakPtr())); 121 weak_factory_.GetWeakPtr()));
90 } 122 }
91 123
92 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted( 124 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) {
93 int result) {
94 // Clear the IO_PENDING status set in Start(). 125 // Clear the IO_PENDING status set in Start().
95 SetStatus(net::URLRequestStatus()); 126 SetStatus(net::URLRequestStatus());
96 if (result >= 0) { 127 if (result >= 0) {
97 set_expected_content_size(result); 128 set_expected_content_size(result);
98 NotifyHeadersComplete(); 129 NotifyHeadersComplete();
99 } else { 130 } else {
100 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); 131 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
101 } 132 }
102 } 133 }
103 134
104 void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted( 135 void AndroidStreamReaderURLRequestJob::OnReaderReadCompleted(int result) {
105 int result) {
106 // The URLRequest API contract requires that: 136 // The URLRequest API contract requires that:
107 // * NotifyDone be called once, to set the status code, indicate the job is 137 // * NotifyDone be called once, to set the status code, indicate the job is
108 // finished (there will be no further IO), 138 // finished (there will be no further IO),
109 // * NotifyReadComplete be called if false is returned from ReadRawData to 139 // * NotifyReadComplete be called if false is returned from ReadRawData to
110 // indicate that the IOBuffer will not be used by the job anymore. 140 // indicate that the IOBuffer will not be used by the job anymore.
111 // There might be multiple calls to ReadRawData (and thus multiple calls to 141 // There might be multiple calls to ReadRawData (and thus multiple calls to
112 // NotifyReadComplete), which is why NotifyDone is called only on errors 142 // NotifyReadComplete), which is why NotifyDone is called only on errors
113 // (result < 0) and end of data (result == 0). 143 // (result < 0) and end of data (result == 0).
114 if (result == 0) { 144 if (result == 0) {
115 NotifyDone(net::URLRequestStatus()); 145 NotifyDone(net::URLRequestStatus());
116 } else if (result < 0) { 146 } else if (result < 0) {
117 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); 147 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
118 } else { 148 } else {
119 // Clear the IO_PENDING status. 149 // Clear the IO_PENDING status.
120 SetStatus(net::URLRequestStatus()); 150 SetStatus(net::URLRequestStatus());
121 } 151 }
122 NotifyReadComplete(result); 152 NotifyReadComplete(result);
123 } 153 }
124 154
125 base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() { 155 base::TaskRunner* AndroidStreamReaderURLRequestJob::GetWorkerThreadRunner() {
126 return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool()); 156 return static_cast<base::TaskRunner*>(BrowserThread::GetBlockingPool());
127 } 157 }
128 158
129 bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest, 159 bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest,
130 int dest_size, 160 int dest_size,
131 int* bytes_read) { 161 int* bytes_read) {
132 DCHECK(input_stream_reader_); 162 DCHECK(input_stream_reader_wrapper_);
133 163
134 PostTaskAndReplyWithResult( 164 PostTaskAndReplyWithResult(
135 GetWorkerThreadRunner(), 165 GetWorkerThreadRunner(),
136 FROM_HERE, 166 FROM_HERE,
137 base::Bind(&InputStreamReader::ReadRawData, 167 base::Bind(&InputStreamReaderWrapper::ReadRawData,
138 input_stream_reader_, 168 input_stream_reader_wrapper_,
139 base::Unretained(dest), 169 base::Unretained(dest),
140 dest_size), 170 dest_size),
141 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted, 171 base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted,
142 weak_factory_.GetWeakPtr())); 172 weak_factory_.GetWeakPtr()));
143 173
144 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); 174 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
145 return false; 175 return false;
146 } 176 }
147 177
148 bool AndroidStreamReaderURLRequestJob::GetMimeType( 178 bool AndroidStreamReaderURLRequestJob::GetMimeType(
149 std::string* mime_type) const { 179 std::string* mime_type) const {
150 JNIEnv* env = AttachCurrentThread(); 180 JNIEnv* env = AttachCurrentThread();
151 DCHECK(env); 181 DCHECK(env);
152 182
153 if (!stream_) 183 if (!input_stream_reader_wrapper_)
154 return false; 184 return false;
155 185
156 return delegate_->GetMimeType(env, request(), *stream_, mime_type); 186 return delegate_->GetMimeType(
187 env, request(), input_stream_reader_wrapper_->input_stream(), mime_type);
157 } 188 }
158 189
159 bool AndroidStreamReaderURLRequestJob::GetCharset( 190 bool AndroidStreamReaderURLRequestJob::GetCharset(std::string* charset) {
160 std::string* charset) {
161 JNIEnv* env = AttachCurrentThread(); 191 JNIEnv* env = AttachCurrentThread();
162 DCHECK(env); 192 DCHECK(env);
163 193
164 if (!stream_) 194 if (!input_stream_reader_wrapper_)
165 return false; 195 return false;
166 196
167 return delegate_->GetCharset(env, request(), *stream_, charset); 197 return delegate_->GetCharset(
198 env, request(), input_stream_reader_wrapper_->input_stream(), charset);
168 } 199 }
169 200
170 void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders( 201 void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders(
171 const net::HttpRequestHeaders& headers) { 202 const net::HttpRequestHeaders& headers) {
172 std::string range_header; 203 std::string range_header;
173 if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { 204 if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
174 // We only extract the "Range" header so that we know how many bytes in the 205 // We only extract the "Range" header so that we know how many bytes in the
175 // stream to skip and how many to read after that. 206 // stream to skip and how many to read after that.
176 std::vector<net::HttpByteRange> ranges; 207 std::vector<net::HttpByteRange> ranges;
177 if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { 208 if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
178 if (ranges.size() == 1) { 209 if (ranges.size() == 1) {
179 byte_range_ = ranges[0]; 210 byte_range_ = ranges[0];
180 } else { 211 } else {
181 // We don't support multiple range requests in one single URL request, 212 // We don't support multiple range requests in one single URL request,
182 // because we need to do multipart encoding here. 213 // because we need to do multipart encoding here.
183 NotifyDone(net::URLRequestStatus( 214 NotifyDone(net::URLRequestStatus(
184 net::URLRequestStatus::FAILED, 215 net::URLRequestStatus::FAILED,
185 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE)); 216 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
186 } 217 }
187 } 218 }
188 } 219 }
189 } 220 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698