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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/net/resolve_proxy_msg_helper.h" 6 7 #include "base/compiler_specific.h" 8 #include "chrome/browser/profiles/profile.h" 9 #include "content/common/child_process_messages.h" 10 #include "net/base/net_errors.h" 11 #include "net/url_request/url_request_context.h" 12 #include "net/url_request/url_request_context_getter.h" 13 14 ResolveProxyMsgHelper::ResolveProxyMsgHelper(net::ProxyService* proxy_service) 15 : proxy_service_(NULL), 16 ALLOW_THIS_IN_INITIALIZER_LIST(callback_( 17 this, &ResolveProxyMsgHelper::OnResolveProxyCompleted)), 18 proxy_service_override_(proxy_service) { 19 } 20 21 bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message, 22 bool* message_was_ok) { 23 bool handled = true; 24 IPC_BEGIN_MESSAGE_MAP_EX(ResolveProxyMsgHelper, message, *message_was_ok) 25 IPC_MESSAGE_HANDLER_DELAY_REPLY(ChildProcessHostMsg_ResolveProxy, 26 OnResolveProxy) 27 IPC_MESSAGE_UNHANDLED(handled = false) 28 IPC_END_MESSAGE_MAP() 29 return handled; 30 } 31 32 void ResolveProxyMsgHelper::OnResolveProxy(const GURL& url, 33 IPC::Message* reply_msg) { 34 // Enqueue the pending request. 35 pending_requests_.push_back(PendingRequest(url, reply_msg)); 36 37 // If nothing is in progress, start. 38 if (pending_requests_.size() == 1) 39 StartPendingRequest(); 40 } 41 42 void ResolveProxyMsgHelper::OnResolveProxyCompleted(int result) { 43 CHECK(!pending_requests_.empty()); 44 45 const PendingRequest& completed_req = pending_requests_.front(); 46 ChildProcessHostMsg_ResolveProxy::WriteReplyParams( 47 completed_req.reply_msg, result, proxy_info_.ToPacString()); 48 Send(completed_req.reply_msg); 49 50 // Clear the current (completed) request. 51 pending_requests_.pop_front(); 52 proxy_service_ = NULL; 53 54 // Start the next request. 55 if (!pending_requests_.empty()) 56 StartPendingRequest(); 57 } 58 59 void ResolveProxyMsgHelper::StartPendingRequest() { 60 PendingRequest& req = pending_requests_.front(); 61 62 // Verify the request wasn't started yet. 63 DCHECK(NULL == req.pac_req); 64 DCHECK(NULL == proxy_service_); 65 66 // Start the request. 67 bool ok = GetProxyService(&proxy_service_); 68 69 if (!ok) { 70 // During shutdown, there may be no ProxyService to use, because the 71 // default ChromeURLRequestContext has already been NULL-ed out. 72 LOG(WARNING) << "Failed getting default URLRequestContext"; 73 OnResolveProxyCompleted(net::ERR_FAILED); 74 return; 75 } 76 77 int result = proxy_service_->ResolveProxy( 78 req.url, &proxy_info_, &callback_, &req.pac_req, net::BoundNetLog()); 79 80 // Completed synchronously. 81 if (result != net::ERR_IO_PENDING) 82 OnResolveProxyCompleted(result); 83 } 84 85 bool ResolveProxyMsgHelper::GetProxyService( 86 scoped_refptr<net::ProxyService>* out) const { 87 // Unit-tests specify their own proxy service to use. 88 if (proxy_service_override_) { 89 *out = proxy_service_override_; 90 return true; 91 } 92 93 // If there is no default request context (say during shut down). 94 net::URLRequestContextGetter* context_getter = 95 Profile::GetDefaultRequestContext(); 96 if (!context_getter) 97 return false; 98 99 // Otherwise use the browser's global proxy service. 100 *out = context_getter->GetURLRequestContext()->proxy_service(); 101 return true; 102 } 103 104 ResolveProxyMsgHelper::~ResolveProxyMsgHelper() { 105 // Clear all pending requests. 106 if (!pending_requests_.empty()) { 107 PendingRequest req = pending_requests_.front(); 108 proxy_service_->CancelPacRequest(req.pac_req); 109 } 110 111 for (PendingRequestList::iterator it = pending_requests_.begin(); 112 it != pending_requests_.end(); 113 ++it) { 114 delete it->reply_msg; 115 } 116 117 proxy_service_ = NULL; 118 pending_requests_.clear(); 119 } 120