| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 URLRequest, meaning it is a "simple" version | 6 // The class is implemented using net::URLRequest, meaning it is a "simple" |
| 7 // 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 URLRequest only provides an asynchronous resource loading API, this | 10 // Because net::URLRequest only provides an asynchronous resource loading API, |
| 11 // file makes use of URLRequest from a background IO thread. Requests for | 11 // this file makes use of net::URLRequest from a background IO thread. Requests |
| 12 // cookies and synchronously loaded resources result in the main thread of the | 12 // for cookies and synchronously loaded resources result in the main thread of |
| 13 // application blocking until the IO thread completes the operation. (See | 13 // the application blocking until the IO thread completes the operation. (See |
| 14 // GetCookies and SyncLoad) | 14 // GetCookies and SyncLoad) |
| 15 // | 15 // |
| 16 // Main thread IO thread | 16 // Main thread IO thread |
| 17 // ----------- --------- | 17 // ----------- --------- |
| 18 // ResourceLoaderBridge <---o---------> RequestProxy (normal case) | 18 // ResourceLoaderBridge <---o---------> RequestProxy (normal case) |
| 19 // \ -> URLRequest | 19 // \ -> net::URLRequest |
| 20 // o-------> SyncRequestProxy (synchronous case) | 20 // o-------> SyncRequestProxy (synchronous case) |
| 21 // -> URLRequest | 21 // -> net::URLRequest |
| 22 // SetCookie <------------------------> CookieSetter | 22 // SetCookie <------------------------> CookieSetter |
| 23 // -> net_util::SetCookie | 23 // -> net_util::SetCookie |
| 24 // GetCookies <-----------------------> CookieGetter | 24 // GetCookies <-----------------------> CookieGetter |
| 25 // -> net_util::GetCookies | 25 // -> net_util::GetCookies |
| 26 // | 26 // |
| 27 // NOTE: The implementation in this file may be used to have WebKit fetch | 27 // NOTE: The implementation in this file may be used to have WebKit fetch |
| 28 // resources in-process. For example, it is handy for building a single- | 28 // resources in-process. For example, it is handy for building a single- |
| 29 // process WebKit embedding (e.g., test_shell) that can use URLRequest to | 29 // process WebKit embedding (e.g., test_shell) that can use net::URLRequest to |
| 30 // perform URL loads. See renderer/resource_dispatcher.h for details on an | 30 // perform URL loads. See renderer/resource_dispatcher.h for details on an |
| 31 // alternate implementation that defers fetching to another process. | 31 // alternate implementation that defers fetching to another process. |
| 32 | 32 |
| 33 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h" | 33 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h" |
| 34 | 34 |
| 35 #include "base/file_path.h" | 35 #include "base/file_path.h" |
| 36 #include "base/file_util.h" | 36 #include "base/file_util.h" |
| 37 #include "base/logging.h" | 37 #include "base/logging.h" |
| 38 #include "base/message_loop.h" | 38 #include "base/message_loop.h" |
| 39 #include "base/message_loop_proxy.h" | 39 #include "base/message_loop_proxy.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 cache_mode(in_cache_mode), | 90 cache_mode(in_cache_mode), |
| 91 no_proxy(in_no_proxy), | 91 no_proxy(in_no_proxy), |
| 92 accept_all_cookies(false) {} | 92 accept_all_cookies(false) {} |
| 93 | 93 |
| 94 FilePath cache_path; | 94 FilePath cache_path; |
| 95 net::HttpCache::Mode cache_mode; | 95 net::HttpCache::Mode cache_mode; |
| 96 bool no_proxy; | 96 bool no_proxy; |
| 97 bool accept_all_cookies; | 97 bool accept_all_cookies; |
| 98 }; | 98 }; |
| 99 | 99 |
| 100 static URLRequestJob* BlobURLRequestJobFactory(URLRequest* request, | 100 static URLRequestJob* BlobURLRequestJobFactory(net::URLRequest* request, |
| 101 const std::string& scheme) { | 101 const std::string& scheme) { |
| 102 webkit_blob::BlobStorageController* blob_storage_controller = | 102 webkit_blob::BlobStorageController* blob_storage_controller = |
| 103 static_cast<TestShellRequestContext*>(request->context())-> | 103 static_cast<TestShellRequestContext*>(request->context())-> |
| 104 blob_storage_controller(); | 104 blob_storage_controller(); |
| 105 return new webkit_blob::BlobURLRequestJob( | 105 return new webkit_blob::BlobURLRequestJob( |
| 106 request, | 106 request, |
| 107 blob_storage_controller->GetBlobDataFromUrl(request->url()), | 107 blob_storage_controller->GetBlobDataFromUrl(request->url()), |
| 108 NULL); | 108 NULL); |
| 109 } | 109 } |
| 110 | 110 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 140 } | 140 } |
| 141 | 141 |
| 142 g_request_context->AddRef(); | 142 g_request_context->AddRef(); |
| 143 | 143 |
| 144 SimpleAppCacheSystem::InitializeOnIOThread(g_request_context); | 144 SimpleAppCacheSystem::InitializeOnIOThread(g_request_context); |
| 145 SimpleSocketStreamBridge::InitializeOnIOThread(g_request_context); | 145 SimpleSocketStreamBridge::InitializeOnIOThread(g_request_context); |
| 146 SimpleFileWriter::InitializeOnIOThread(g_request_context); | 146 SimpleFileWriter::InitializeOnIOThread(g_request_context); |
| 147 TestShellWebBlobRegistryImpl::InitializeOnIOThread( | 147 TestShellWebBlobRegistryImpl::InitializeOnIOThread( |
| 148 g_request_context->blob_storage_controller()); | 148 g_request_context->blob_storage_controller()); |
| 149 | 149 |
| 150 URLRequest::RegisterProtocolFactory("blob", &BlobURLRequestJobFactory); | 150 net::URLRequest::RegisterProtocolFactory("blob", &BlobURLRequestJobFactory); |
| 151 } | 151 } |
| 152 | 152 |
| 153 virtual void CleanUp() { | 153 virtual void CleanUp() { |
| 154 // In reverse order of initialization. | 154 // In reverse order of initialization. |
| 155 TestShellWebBlobRegistryImpl::Cleanup(); | 155 TestShellWebBlobRegistryImpl::Cleanup(); |
| 156 SimpleFileWriter::CleanupOnIOThread(); | 156 SimpleFileWriter::CleanupOnIOThread(); |
| 157 SimpleSocketStreamBridge::Cleanup(); | 157 SimpleSocketStreamBridge::Cleanup(); |
| 158 SimpleAppCacheSystem::CleanupOnIOThread(); | 158 SimpleAppCacheSystem::CleanupOnIOThread(); |
| 159 | 159 |
| 160 if (g_request_context) { | 160 if (g_request_context) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 186 ResourceType::Type request_type; | 186 ResourceType::Type request_type; |
| 187 int appcache_host_id; | 187 int appcache_host_id; |
| 188 bool download_to_file; | 188 bool download_to_file; |
| 189 scoped_refptr<net::UploadData> upload; | 189 scoped_refptr<net::UploadData> upload; |
| 190 }; | 190 }; |
| 191 | 191 |
| 192 // The interval for calls to RequestProxy::MaybeUpdateUploadProgress | 192 // The interval for calls to RequestProxy::MaybeUpdateUploadProgress |
| 193 static const int kUpdateUploadProgressIntervalMsec = 100; | 193 static const int kUpdateUploadProgressIntervalMsec = 100; |
| 194 | 194 |
| 195 // The RequestProxy does most of its work on the IO thread. The Start and | 195 // The RequestProxy does most of its work on the IO thread. The Start and |
| 196 // Cancel methods are proxied over to the IO thread, where an URLRequest object | 196 // Cancel methods are proxied over to the IO thread, where an net::URLRequest |
| 197 // is instantiated. | 197 // object is instantiated. |
| 198 class RequestProxy : public URLRequest::Delegate, | 198 class RequestProxy : public net::URLRequest::Delegate, |
| 199 public base::RefCountedThreadSafe<RequestProxy> { | 199 public base::RefCountedThreadSafe<RequestProxy> { |
| 200 public: | 200 public: |
| 201 // Takes ownership of the params. | 201 // Takes ownership of the params. |
| 202 RequestProxy() | 202 RequestProxy() |
| 203 : download_to_file_(false), | 203 : download_to_file_(false), |
| 204 buf_(new net::IOBuffer(kDataSize)), | 204 buf_(new net::IOBuffer(kDataSize)), |
| 205 last_upload_position_(0) { | 205 last_upload_position_(0) { |
| 206 } | 206 } |
| 207 | 207 |
| 208 void DropPeer() { | 208 void DropPeer() { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 228 friend class base::RefCountedThreadSafe<RequestProxy>; | 228 friend class base::RefCountedThreadSafe<RequestProxy>; |
| 229 | 229 |
| 230 virtual ~RequestProxy() { | 230 virtual ~RequestProxy() { |
| 231 // If we have a request, then we'd better be on the io thread! | 231 // If we have a request, then we'd better be on the io thread! |
| 232 DCHECK(!request_.get() || | 232 DCHECK(!request_.get() || |
| 233 MessageLoop::current() == g_io_thread->message_loop()); | 233 MessageLoop::current() == g_io_thread->message_loop()); |
| 234 } | 234 } |
| 235 | 235 |
| 236 // -------------------------------------------------------------------------- | 236 // -------------------------------------------------------------------------- |
| 237 // The following methods are called on the owner's thread in response to | 237 // The following methods are called on the owner's thread in response to |
| 238 // various URLRequest callbacks. The event hooks, defined below, trigger | 238 // various net::URLRequest callbacks. The event hooks, defined below, trigger |
| 239 // these methods asynchronously. | 239 // these methods asynchronously. |
| 240 | 240 |
| 241 void NotifyReceivedRedirect(const GURL& new_url, | 241 void NotifyReceivedRedirect(const GURL& new_url, |
| 242 const ResourceResponseInfo& info) { | 242 const ResourceResponseInfo& info) { |
| 243 bool has_new_first_party_for_cookies = false; | 243 bool has_new_first_party_for_cookies = false; |
| 244 GURL new_first_party_for_cookies; | 244 GURL new_first_party_for_cookies; |
| 245 if (peer_ && peer_->OnReceivedRedirect(new_url, info, | 245 if (peer_ && peer_->OnReceivedRedirect(new_url, info, |
| 246 &has_new_first_party_for_cookies, | 246 &has_new_first_party_for_cookies, |
| 247 &new_first_party_for_cookies)) { | 247 &new_first_party_for_cookies)) { |
| 248 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 248 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 // actions performed on the owner's thread. | 310 // actions performed on the owner's thread. |
| 311 | 311 |
| 312 void AsyncStart(RequestParams* params) { | 312 void AsyncStart(RequestParams* params) { |
| 313 // Might need to resolve the blob references in the upload data. | 313 // Might need to resolve the blob references in the upload data. |
| 314 if (params->upload) { | 314 if (params->upload) { |
| 315 static_cast<TestShellRequestContext*>(g_request_context)-> | 315 static_cast<TestShellRequestContext*>(g_request_context)-> |
| 316 blob_storage_controller()->ResolveBlobReferencesInUploadData( | 316 blob_storage_controller()->ResolveBlobReferencesInUploadData( |
| 317 params->upload.get()); | 317 params->upload.get()); |
| 318 } | 318 } |
| 319 | 319 |
| 320 request_.reset(new URLRequest(params->url, this)); | 320 request_.reset(new net::URLRequest(params->url, this)); |
| 321 request_->set_method(params->method); | 321 request_->set_method(params->method); |
| 322 request_->set_first_party_for_cookies(params->first_party_for_cookies); | 322 request_->set_first_party_for_cookies(params->first_party_for_cookies); |
| 323 request_->set_referrer(params->referrer.spec()); | 323 request_->set_referrer(params->referrer.spec()); |
| 324 net::HttpRequestHeaders headers; | 324 net::HttpRequestHeaders headers; |
| 325 headers.AddHeadersFromString(params->headers); | 325 headers.AddHeadersFromString(params->headers); |
| 326 request_->SetExtraRequestHeaders(headers); | 326 request_->SetExtraRequestHeaders(headers); |
| 327 request_->set_load_flags(params->load_flags); | 327 request_->set_load_flags(params->load_flags); |
| 328 request_->set_upload(params->upload.get()); | 328 request_->set_upload(params->upload.get()); |
| 329 request_->set_context(g_request_context); | 329 request_->set_context(g_request_context); |
| 330 SimpleAppCacheSystem::SetExtraRequestInfo( | 330 SimpleAppCacheSystem::SetExtraRequestInfo( |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 OnReceivedData(bytes_read); | 384 OnReceivedData(bytes_read); |
| 385 } else if (!request_->status().is_io_pending()) { | 385 } else if (!request_->status().is_io_pending()) { |
| 386 Done(); | 386 Done(); |
| 387 } // else wait for OnReadCompleted | 387 } // else wait for OnReadCompleted |
| 388 } else { | 388 } else { |
| 389 Done(); | 389 Done(); |
| 390 } | 390 } |
| 391 } | 391 } |
| 392 | 392 |
| 393 // -------------------------------------------------------------------------- | 393 // -------------------------------------------------------------------------- |
| 394 // The following methods are event hooks (corresponding to URLRequest | 394 // The following methods are event hooks (corresponding to net::URLRequest |
| 395 // callbacks) that run on the IO thread. They are designed to be overridden | 395 // callbacks) that run on the IO thread. They are designed to be overridden |
| 396 // by the SyncRequestProxy subclass. | 396 // by the SyncRequestProxy subclass. |
| 397 | 397 |
| 398 virtual void OnReceivedRedirect( | 398 virtual void OnReceivedRedirect( |
| 399 const GURL& new_url, | 399 const GURL& new_url, |
| 400 const ResourceResponseInfo& info, | 400 const ResourceResponseInfo& info, |
| 401 bool* defer_redirect) { | 401 bool* defer_redirect) { |
| 402 *defer_redirect = true; // See AsyncFollowDeferredRedirect | 402 *defer_redirect = true; // See AsyncFollowDeferredRedirect |
| 403 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 403 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
| 404 this, &RequestProxy::NotifyReceivedRedirect, new_url, info)); | 404 this, &RequestProxy::NotifyReceivedRedirect, new_url, info)); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 430 file_stream_.Close(); | 430 file_stream_.Close(); |
| 431 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 431 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
| 432 this, | 432 this, |
| 433 &RequestProxy::NotifyCompletedRequest, | 433 &RequestProxy::NotifyCompletedRequest, |
| 434 status, | 434 status, |
| 435 security_info, | 435 security_info, |
| 436 complete_time)); | 436 complete_time)); |
| 437 } | 437 } |
| 438 | 438 |
| 439 // -------------------------------------------------------------------------- | 439 // -------------------------------------------------------------------------- |
| 440 // URLRequest::Delegate implementation: | 440 // net::URLRequest::Delegate implementation: |
| 441 | 441 |
| 442 virtual void OnReceivedRedirect(URLRequest* request, | 442 virtual void OnReceivedRedirect(net::URLRequest* request, |
| 443 const GURL& new_url, | 443 const GURL& new_url, |
| 444 bool* defer_redirect) { | 444 bool* defer_redirect) { |
| 445 DCHECK(request->status().is_success()); | 445 DCHECK(request->status().is_success()); |
| 446 ResourceResponseInfo info; | 446 ResourceResponseInfo info; |
| 447 PopulateResponseInfo(request, &info); | 447 PopulateResponseInfo(request, &info); |
| 448 OnReceivedRedirect(new_url, info, defer_redirect); | 448 OnReceivedRedirect(new_url, info, defer_redirect); |
| 449 } | 449 } |
| 450 | 450 |
| 451 virtual void OnResponseStarted(URLRequest* request) { | 451 virtual void OnResponseStarted(net::URLRequest* request) { |
| 452 if (request->status().is_success()) { | 452 if (request->status().is_success()) { |
| 453 ResourceResponseInfo info; | 453 ResourceResponseInfo info; |
| 454 PopulateResponseInfo(request, &info); | 454 PopulateResponseInfo(request, &info); |
| 455 OnReceivedResponse(info, false); | 455 OnReceivedResponse(info, false); |
| 456 AsyncReadData(); // start reading | 456 AsyncReadData(); // start reading |
| 457 } else { | 457 } else { |
| 458 Done(); | 458 Done(); |
| 459 } | 459 } |
| 460 } | 460 } |
| 461 | 461 |
| 462 virtual void OnSSLCertificateError(URLRequest* request, | 462 virtual void OnSSLCertificateError(net::URLRequest* request, |
| 463 int cert_error, | 463 int cert_error, |
| 464 net::X509Certificate* cert) { | 464 net::X509Certificate* cert) { |
| 465 // Allow all certificate errors. | 465 // Allow all certificate errors. |
| 466 request->ContinueDespiteLastError(); | 466 request->ContinueDespiteLastError(); |
| 467 } | 467 } |
| 468 | 468 |
| 469 virtual void OnReadCompleted(URLRequest* request, int bytes_read) { | 469 virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) { |
| 470 if (request->status().is_success() && bytes_read > 0) { | 470 if (request->status().is_success() && bytes_read > 0) { |
| 471 OnReceivedData(bytes_read); | 471 OnReceivedData(bytes_read); |
| 472 } else { | 472 } else { |
| 473 Done(); | 473 Done(); |
| 474 } | 474 } |
| 475 } | 475 } |
| 476 | 476 |
| 477 // -------------------------------------------------------------------------- | 477 // -------------------------------------------------------------------------- |
| 478 // Helpers and data: | 478 // Helpers and data: |
| 479 | 479 |
| 480 void Done() { | 480 void Done() { |
| 481 if (upload_progress_timer_.IsRunning()) { | 481 if (upload_progress_timer_.IsRunning()) { |
| 482 MaybeUpdateUploadProgress(); | 482 MaybeUpdateUploadProgress(); |
| 483 upload_progress_timer_.Stop(); | 483 upload_progress_timer_.Stop(); |
| 484 } | 484 } |
| 485 DCHECK(request_.get()); | 485 DCHECK(request_.get()); |
| 486 OnCompletedRequest(request_->status(), std::string(), base::Time()); | 486 OnCompletedRequest(request_->status(), std::string(), base::Time()); |
| 487 request_.reset(); // destroy on the io thread | 487 request_.reset(); // destroy on the io thread |
| 488 } | 488 } |
| 489 | 489 |
| 490 // Called on the IO thread. | 490 // Called on the IO thread. |
| 491 void MaybeUpdateUploadProgress() { | 491 void MaybeUpdateUploadProgress() { |
| 492 // If a redirect is received upload is cancelled in URLRequest, we should | 492 // If a redirect is received upload is cancelled in net::URLRequest, we |
| 493 // try to stop the |upload_progress_timer_| timer and return. | 493 // should try to stop the |upload_progress_timer_| timer and return. |
| 494 if (!request_->has_upload()) { | 494 if (!request_->has_upload()) { |
| 495 if (upload_progress_timer_.IsRunning()) | 495 if (upload_progress_timer_.IsRunning()) |
| 496 upload_progress_timer_.Stop(); | 496 upload_progress_timer_.Stop(); |
| 497 return; | 497 return; |
| 498 } | 498 } |
| 499 | 499 |
| 500 uint64 size = request_->get_upload()->GetContentLength(); | 500 uint64 size = request_->get_upload()->GetContentLength(); |
| 501 uint64 position = request_->GetUploadProgress(); | 501 uint64 position = request_->GetUploadProgress(); |
| 502 if (position == last_upload_position_) | 502 if (position == last_upload_position_) |
| 503 return; // no progress made since last time | 503 return; // no progress made since last time |
| (...skipping 11 matching lines...) Expand all Loading... |
| 515 bool too_much_time_passed = time_since_last > kOneSecond; | 515 bool too_much_time_passed = time_since_last > kOneSecond; |
| 516 | 516 |
| 517 if (is_finished || enough_new_progress || too_much_time_passed) { | 517 if (is_finished || enough_new_progress || too_much_time_passed) { |
| 518 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 518 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
| 519 this, &RequestProxy::NotifyUploadProgress, position, size)); | 519 this, &RequestProxy::NotifyUploadProgress, position, size)); |
| 520 last_upload_ticks_ = base::TimeTicks::Now(); | 520 last_upload_ticks_ = base::TimeTicks::Now(); |
| 521 last_upload_position_ = position; | 521 last_upload_position_ = position; |
| 522 } | 522 } |
| 523 } | 523 } |
| 524 | 524 |
| 525 void PopulateResponseInfo(URLRequest* request, | 525 void PopulateResponseInfo(net::URLRequest* request, |
| 526 ResourceResponseInfo* info) const { | 526 ResourceResponseInfo* info) const { |
| 527 info->request_time = request->request_time(); | 527 info->request_time = request->request_time(); |
| 528 info->response_time = request->response_time(); | 528 info->response_time = request->response_time(); |
| 529 info->headers = request->response_headers(); | 529 info->headers = request->response_headers(); |
| 530 request->GetMimeType(&info->mime_type); | 530 request->GetMimeType(&info->mime_type); |
| 531 request->GetCharset(&info->charset); | 531 request->GetCharset(&info->charset); |
| 532 info->content_length = request->GetExpectedContentSize(); | 532 info->content_length = request->GetExpectedContentSize(); |
| 533 if (downloaded_file_) | 533 if (downloaded_file_) |
| 534 info->download_file_path = downloaded_file_->path(); | 534 info->download_file_path = downloaded_file_->path(); |
| 535 SimpleAppCacheSystem::GetExtraResponseInfo( | 535 SimpleAppCacheSystem::GetExtraResponseInfo( |
| 536 request, | 536 request, |
| 537 &info->appcache_id, | 537 &info->appcache_id, |
| 538 &info->appcache_manifest_url); | 538 &info->appcache_manifest_url); |
| 539 } | 539 } |
| 540 | 540 |
| 541 scoped_ptr<URLRequest> request_; | 541 scoped_ptr<net::URLRequest> request_; |
| 542 | 542 |
| 543 // Support for request.download_to_file behavior. | 543 // Support for request.download_to_file behavior. |
| 544 bool download_to_file_; | 544 bool download_to_file_; |
| 545 net::FileStream file_stream_; | 545 net::FileStream file_stream_; |
| 546 scoped_refptr<DeletableFileReference> downloaded_file_; | 546 scoped_refptr<DeletableFileReference> downloaded_file_; |
| 547 | 547 |
| 548 // Size of our async IO data buffers | 548 // Size of our async IO data buffers |
| 549 static const int kDataSize = 16*1024; | 549 static const int kDataSize = 16*1024; |
| 550 | 550 |
| 551 // read buffer for async IO | 551 // read buffer for async IO |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 | 928 |
| 929 // static | 929 // static |
| 930 scoped_refptr<base::MessageLoopProxy> | 930 scoped_refptr<base::MessageLoopProxy> |
| 931 SimpleResourceLoaderBridge::GetIoThread() { | 931 SimpleResourceLoaderBridge::GetIoThread() { |
| 932 if (!EnsureIOThread()) { | 932 if (!EnsureIOThread()) { |
| 933 LOG(DFATAL) << "Failed to create IO thread."; | 933 LOG(DFATAL) << "Failed to create IO thread."; |
| 934 return NULL; | 934 return NULL; |
| 935 } | 935 } |
| 936 return g_io_thread->message_loop_proxy(); | 936 return g_io_thread->message_loop_proxy(); |
| 937 } | 937 } |
| OLD | NEW |