| 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 // This file contains an implementation of the ResourceLoaderBridge class. | 5 // This file contains an implementation of the ResourceLoaderBridge class. |
| 6 // The class is implemented using net::URLRequest, meaning it is a "simple" | 6 // The class is implemented using net::URLRequest, meaning it is a "simple" |
| 7 // version that directly issues requests. The more complicated one used in the | 7 // version that directly issues requests. The more complicated one used in the |
| 8 // browser uses IPC. | 8 // browser uses IPC. |
| 9 // | 9 // |
| 10 // Because net::URLRequest only provides an asynchronous resource loading API, | 10 // Because net::URLRequest only provides an asynchronous resource loading API, |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 void DropPeer() { | 199 void DropPeer() { |
| 200 peer_ = NULL; | 200 peer_ = NULL; |
| 201 } | 201 } |
| 202 | 202 |
| 203 void Start(ResourceLoaderBridge::Peer* peer, RequestParams* params) { | 203 void Start(ResourceLoaderBridge::Peer* peer, RequestParams* params) { |
| 204 peer_ = peer; | 204 peer_ = peer; |
| 205 owner_loop_ = MessageLoop::current(); | 205 owner_loop_ = MessageLoop::current(); |
| 206 | 206 |
| 207 ConvertRequestParamsForFileOverHTTPIfNeeded(params); | 207 ConvertRequestParamsForFileOverHTTPIfNeeded(params); |
| 208 // proxy over to the io thread | 208 // proxy over to the io thread |
| 209 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 209 g_io_thread->message_loop()->PostTask( |
| 210 this, &RequestProxy::AsyncStart, params)); | 210 FROM_HERE, |
| 211 base::Bind(&RequestProxy::AsyncStart, this, params)); |
| 211 } | 212 } |
| 212 | 213 |
| 213 void Cancel() { | 214 void Cancel() { |
| 214 // proxy over to the io thread | 215 // proxy over to the io thread |
| 215 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 216 g_io_thread->message_loop()->PostTask( |
| 216 this, &RequestProxy::AsyncCancel)); | 217 FROM_HERE, |
| 218 base::Bind(&RequestProxy::AsyncCancel, this)); |
| 217 } | 219 } |
| 218 | 220 |
| 219 protected: | 221 protected: |
| 220 friend class base::RefCountedThreadSafe<RequestProxy>; | 222 friend class base::RefCountedThreadSafe<RequestProxy>; |
| 221 | 223 |
| 222 virtual ~RequestProxy() { | 224 virtual ~RequestProxy() { |
| 223 // If we have a request, then we'd better be on the io thread! | 225 // If we have a request, then we'd better be on the io thread! |
| 224 DCHECK(!request_.get() || | 226 DCHECK(!request_.get() || |
| 225 MessageLoop::current() == g_io_thread->message_loop()); | 227 MessageLoop::current() == g_io_thread->message_loop()); |
| 226 } | 228 } |
| 227 | 229 |
| 228 // -------------------------------------------------------------------------- | 230 // -------------------------------------------------------------------------- |
| 229 // The following methods are called on the owner's thread in response to | 231 // The following methods are called on the owner's thread in response to |
| 230 // various net::URLRequest callbacks. The event hooks, defined below, trigger | 232 // various net::URLRequest callbacks. The event hooks, defined below, trigger |
| 231 // these methods asynchronously. | 233 // these methods asynchronously. |
| 232 | 234 |
| 233 void NotifyReceivedRedirect(const GURL& new_url, | 235 void NotifyReceivedRedirect(const GURL& new_url, |
| 234 const ResourceResponseInfo& info) { | 236 const ResourceResponseInfo& info) { |
| 235 bool has_new_first_party_for_cookies = false; | 237 bool has_new_first_party_for_cookies = false; |
| 236 GURL new_first_party_for_cookies; | 238 GURL new_first_party_for_cookies; |
| 237 if (peer_ && peer_->OnReceivedRedirect(new_url, info, | 239 if (peer_ && peer_->OnReceivedRedirect(new_url, info, |
| 238 &has_new_first_party_for_cookies, | 240 &has_new_first_party_for_cookies, |
| 239 &new_first_party_for_cookies)) { | 241 &new_first_party_for_cookies)) { |
| 240 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 242 g_io_thread->message_loop()->PostTask( |
| 241 this, &RequestProxy::AsyncFollowDeferredRedirect, | 243 FROM_HERE, |
| 242 has_new_first_party_for_cookies, new_first_party_for_cookies)); | 244 base::Bind(&RequestProxy::AsyncFollowDeferredRedirect, this, |
| 245 has_new_first_party_for_cookies, |
| 246 new_first_party_for_cookies)); |
| 243 } else { | 247 } else { |
| 244 Cancel(); | 248 Cancel(); |
| 245 } | 249 } |
| 246 } | 250 } |
| 247 | 251 |
| 248 void NotifyReceivedResponse(const ResourceResponseInfo& info) { | 252 void NotifyReceivedResponse(const ResourceResponseInfo& info) { |
| 249 if (peer_) | 253 if (peer_) |
| 250 peer_->OnReceivedResponse(info); | 254 peer_->OnReceivedResponse(info); |
| 251 } | 255 } |
| 252 | 256 |
| 253 void NotifyReceivedData(int bytes_read) { | 257 void NotifyReceivedData(int bytes_read) { |
| 254 if (!peer_) | 258 if (!peer_) |
| 255 return; | 259 return; |
| 256 | 260 |
| 257 // Make a local copy of buf_, since AsyncReadData reuses it. | 261 // Make a local copy of buf_, since AsyncReadData reuses it. |
| 258 scoped_array<char> buf_copy(new char[bytes_read]); | 262 scoped_array<char> buf_copy(new char[bytes_read]); |
| 259 memcpy(buf_copy.get(), buf_->data(), bytes_read); | 263 memcpy(buf_copy.get(), buf_->data(), bytes_read); |
| 260 | 264 |
| 261 // Continue reading more data into buf_ | 265 // Continue reading more data into buf_ |
| 262 // Note: Doing this before notifying our peer ensures our load events get | 266 // Note: Doing this before notifying our peer ensures our load events get |
| 263 // dispatched in a manner consistent with DumpRenderTree (and also avoids a | 267 // dispatched in a manner consistent with DumpRenderTree (and also avoids a |
| 264 // race condition). If the order of the next 2 functions were reversed, the | 268 // race condition). If the order of the next 2 functions were reversed, the |
| 265 // peer could generate new requests in reponse to the received data, which | 269 // peer could generate new requests in reponse to the received data, which |
| 266 // when run on the io thread, could race against this function in doing | 270 // when run on the io thread, could race against this function in doing |
| 267 // another InvokeLater. See bug 769249. | 271 // another InvokeLater. See bug 769249. |
| 268 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 272 g_io_thread->message_loop()->PostTask( |
| 269 this, &RequestProxy::AsyncReadData)); | 273 FROM_HERE, |
| 274 base::Bind(&RequestProxy::AsyncReadData, this)); |
| 270 | 275 |
| 271 peer_->OnReceivedData(buf_copy.get(), bytes_read, -1); | 276 peer_->OnReceivedData(buf_copy.get(), bytes_read, -1); |
| 272 } | 277 } |
| 273 | 278 |
| 274 void NotifyDownloadedData(int bytes_read) { | 279 void NotifyDownloadedData(int bytes_read) { |
| 275 if (!peer_) | 280 if (!peer_) |
| 276 return; | 281 return; |
| 277 | 282 |
| 278 // Continue reading more data, see the comment in NotifyReceivedData. | 283 // Continue reading more data, see the comment in NotifyReceivedData. |
| 279 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 284 g_io_thread->message_loop()->PostTask( |
| 280 this, &RequestProxy::AsyncReadData)); | 285 FROM_HERE, |
| 286 base::Bind(&RequestProxy::AsyncReadData, this)); |
| 281 | 287 |
| 282 peer_->OnDownloadedData(bytes_read); | 288 peer_->OnDownloadedData(bytes_read); |
| 283 } | 289 } |
| 284 | 290 |
| 285 void NotifyCompletedRequest(const net::URLRequestStatus& status, | 291 void NotifyCompletedRequest(const net::URLRequestStatus& status, |
| 286 const std::string& security_info, | 292 const std::string& security_info, |
| 287 const base::Time& complete_time) { | 293 const base::Time& complete_time) { |
| 288 if (peer_) { | 294 if (peer_) { |
| 289 peer_->OnCompletedRequest(status, security_info, complete_time); | 295 peer_->OnCompletedRequest(status, security_info, complete_time); |
| 290 DropPeer(); // ensure no further notifications | 296 DropPeer(); // ensure no further notifications |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 // -------------------------------------------------------------------------- | 390 // -------------------------------------------------------------------------- |
| 385 // The following methods are event hooks (corresponding to net::URLRequest | 391 // The following methods are event hooks (corresponding to net::URLRequest |
| 386 // callbacks) that run on the IO thread. They are designed to be overridden | 392 // callbacks) that run on the IO thread. They are designed to be overridden |
| 387 // by the SyncRequestProxy subclass. | 393 // by the SyncRequestProxy subclass. |
| 388 | 394 |
| 389 virtual void OnReceivedRedirect( | 395 virtual void OnReceivedRedirect( |
| 390 const GURL& new_url, | 396 const GURL& new_url, |
| 391 const ResourceResponseInfo& info, | 397 const ResourceResponseInfo& info, |
| 392 bool* defer_redirect) { | 398 bool* defer_redirect) { |
| 393 *defer_redirect = true; // See AsyncFollowDeferredRedirect | 399 *defer_redirect = true; // See AsyncFollowDeferredRedirect |
| 394 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 400 owner_loop_->PostTask( |
| 395 this, &RequestProxy::NotifyReceivedRedirect, new_url, info)); | 401 FROM_HERE, |
| 402 base::Bind(&RequestProxy::NotifyReceivedRedirect, this, new_url, info)); |
| 396 } | 403 } |
| 397 | 404 |
| 398 virtual void OnReceivedResponse( | 405 virtual void OnReceivedResponse( |
| 399 const ResourceResponseInfo& info) { | 406 const ResourceResponseInfo& info) { |
| 400 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 407 owner_loop_->PostTask( |
| 401 this, &RequestProxy::NotifyReceivedResponse, info)); | 408 FROM_HERE, |
| 409 base::Bind(&RequestProxy::NotifyReceivedResponse, this, info)); |
| 402 } | 410 } |
| 403 | 411 |
| 404 virtual void OnReceivedData(int bytes_read) { | 412 virtual void OnReceivedData(int bytes_read) { |
| 405 if (download_to_file_) { | 413 if (download_to_file_) { |
| 406 file_stream_.Write(buf_->data(), bytes_read, NULL); | 414 file_stream_.Write(buf_->data(), bytes_read, NULL); |
| 407 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 415 owner_loop_->PostTask( |
| 408 this, &RequestProxy::NotifyDownloadedData, bytes_read)); | 416 FROM_HERE, |
| 417 base::Bind(&RequestProxy::NotifyDownloadedData, this, bytes_read)); |
| 409 return; | 418 return; |
| 410 } | 419 } |
| 411 | 420 |
| 412 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 421 owner_loop_->PostTask( |
| 413 this, &RequestProxy::NotifyReceivedData, bytes_read)); | 422 FROM_HERE, |
| 423 base::Bind(&RequestProxy::NotifyReceivedData, this, bytes_read)); |
| 414 } | 424 } |
| 415 | 425 |
| 416 virtual void OnCompletedRequest(const net::URLRequestStatus& status, | 426 virtual void OnCompletedRequest(const net::URLRequestStatus& status, |
| 417 const std::string& security_info, | 427 const std::string& security_info, |
| 418 const base::Time& complete_time) { | 428 const base::Time& complete_time) { |
| 419 if (download_to_file_) | 429 if (download_to_file_) |
| 420 file_stream_.Close(); | 430 file_stream_.Close(); |
| 421 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 431 owner_loop_->PostTask( |
| 422 this, | 432 FROM_HERE, |
| 423 &RequestProxy::NotifyCompletedRequest, | 433 base::Bind(&RequestProxy::NotifyCompletedRequest, this, status, |
| 424 status, | 434 security_info, complete_time)); |
| 425 security_info, | |
| 426 complete_time)); | |
| 427 } | 435 } |
| 428 | 436 |
| 429 // -------------------------------------------------------------------------- | 437 // -------------------------------------------------------------------------- |
| 430 // net::URLRequest::Delegate implementation: | 438 // net::URLRequest::Delegate implementation: |
| 431 | 439 |
| 432 virtual void OnReceivedRedirect(net::URLRequest* request, | 440 virtual void OnReceivedRedirect(net::URLRequest* request, |
| 433 const GURL& new_url, | 441 const GURL& new_url, |
| 434 bool* defer_redirect) OVERRIDE { | 442 bool* defer_redirect) OVERRIDE { |
| 435 DCHECK(request->status().is_success()); | 443 DCHECK(request->status().is_success()); |
| 436 ResourceResponseInfo info; | 444 ResourceResponseInfo info; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 uint64 amt_since_last = position - last_upload_position_; | 546 uint64 amt_since_last = position - last_upload_position_; |
| 539 base::TimeDelta time_since_last = base::TimeTicks::Now() - | 547 base::TimeDelta time_since_last = base::TimeTicks::Now() - |
| 540 last_upload_ticks_; | 548 last_upload_ticks_; |
| 541 | 549 |
| 542 bool is_finished = (size == position); | 550 bool is_finished = (size == position); |
| 543 bool enough_new_progress = (amt_since_last > (size / | 551 bool enough_new_progress = (amt_since_last > (size / |
| 544 kHalfPercentIncrements)); | 552 kHalfPercentIncrements)); |
| 545 bool too_much_time_passed = time_since_last > kOneSecond; | 553 bool too_much_time_passed = time_since_last > kOneSecond; |
| 546 | 554 |
| 547 if (is_finished || enough_new_progress || too_much_time_passed) { | 555 if (is_finished || enough_new_progress || too_much_time_passed) { |
| 548 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 556 owner_loop_->PostTask( |
| 549 this, &RequestProxy::NotifyUploadProgress, position, size)); | 557 FROM_HERE, |
| 558 base::Bind(&RequestProxy::NotifyUploadProgress, this, position, |
| 559 size)); |
| 550 last_upload_ticks_ = base::TimeTicks::Now(); | 560 last_upload_ticks_ = base::TimeTicks::Now(); |
| 551 last_upload_position_ = position; | 561 last_upload_position_ = position; |
| 552 } | 562 } |
| 553 } | 563 } |
| 554 | 564 |
| 555 void PopulateResponseInfo(net::URLRequest* request, | 565 void PopulateResponseInfo(net::URLRequest* request, |
| 556 ResourceResponseInfo* info) const { | 566 ResourceResponseInfo* info) const { |
| 557 info->request_time = request->request_time(); | 567 info->request_time = request->request_time(); |
| 558 info->response_time = request->response_time(); | 568 info->response_time = request->response_time(); |
| 559 info->headers = request->response_headers(); | 569 info->headers = request->response_headers(); |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 const GURL& first_party_for_cookies, | 967 const GURL& first_party_for_cookies, |
| 958 const std::string& cookie) { | 968 const std::string& cookie) { |
| 959 // Proxy to IO thread to synchronize w/ network loading. | 969 // Proxy to IO thread to synchronize w/ network loading. |
| 960 | 970 |
| 961 if (!EnsureIOThread()) { | 971 if (!EnsureIOThread()) { |
| 962 NOTREACHED(); | 972 NOTREACHED(); |
| 963 return; | 973 return; |
| 964 } | 974 } |
| 965 | 975 |
| 966 scoped_refptr<CookieSetter> cookie_setter(new CookieSetter()); | 976 scoped_refptr<CookieSetter> cookie_setter(new CookieSetter()); |
| 967 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 977 g_io_thread->message_loop()->PostTask( |
| 968 cookie_setter.get(), &CookieSetter::Set, url, cookie)); | 978 FROM_HERE, |
| 979 base::Bind(&CookieSetter::Set, cookie_setter.get(), url, cookie)); |
| 969 } | 980 } |
| 970 | 981 |
| 971 // static | 982 // static |
| 972 std::string SimpleResourceLoaderBridge::GetCookies( | 983 std::string SimpleResourceLoaderBridge::GetCookies( |
| 973 const GURL& url, const GURL& first_party_for_cookies) { | 984 const GURL& url, const GURL& first_party_for_cookies) { |
| 974 // Proxy to IO thread to synchronize w/ network loading | 985 // Proxy to IO thread to synchronize w/ network loading |
| 975 | 986 |
| 976 if (!EnsureIOThread()) { | 987 if (!EnsureIOThread()) { |
| 977 NOTREACHED(); | 988 NOTREACHED(); |
| 978 return std::string(); | 989 return std::string(); |
| 979 } | 990 } |
| 980 | 991 |
| 981 scoped_refptr<CookieGetter> getter(new CookieGetter()); | 992 scoped_refptr<CookieGetter> getter(new CookieGetter()); |
| 982 | 993 |
| 983 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 994 g_io_thread->message_loop()->PostTask( |
| 984 getter.get(), &CookieGetter::Get, url)); | 995 FROM_HERE, |
| 996 base::Bind(&CookieGetter::Get, getter.get(), url)); |
| 985 | 997 |
| 986 return getter->GetResult(); | 998 return getter->GetResult(); |
| 987 } | 999 } |
| 988 | 1000 |
| 989 // static | 1001 // static |
| 990 bool SimpleResourceLoaderBridge::EnsureIOThread() { | 1002 bool SimpleResourceLoaderBridge::EnsureIOThread() { |
| 991 if (g_io_thread) | 1003 if (g_io_thread) |
| 992 return true; | 1004 return true; |
| 993 | 1005 |
| 994 #if defined(OS_MACOSX) || defined(OS_WIN) | 1006 #if defined(OS_MACOSX) || defined(OS_WIN) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1032 | 1044 |
| 1033 // static | 1045 // static |
| 1034 void SimpleResourceLoaderBridge::AllowFileOverHTTP( | 1046 void SimpleResourceLoaderBridge::AllowFileOverHTTP( |
| 1035 const std::string& file_path_template, const GURL& http_prefix) { | 1047 const std::string& file_path_template, const GURL& http_prefix) { |
| 1036 DCHECK(!file_path_template.empty()); | 1048 DCHECK(!file_path_template.empty()); |
| 1037 DCHECK(http_prefix.is_valid() && | 1049 DCHECK(http_prefix.is_valid() && |
| 1038 (http_prefix.SchemeIs("http") || http_prefix.SchemeIs("https"))); | 1050 (http_prefix.SchemeIs("http") || http_prefix.SchemeIs("https"))); |
| 1039 g_file_over_http_params = new FileOverHTTPParams(file_path_template, | 1051 g_file_over_http_params = new FileOverHTTPParams(file_path_template, |
| 1040 http_prefix); | 1052 http_prefix); |
| 1041 } | 1053 } |
| OLD | NEW |