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 3 // found in the LICENSE file. 4 5 #include "content/browser/resolve_proxy_msg_helper.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/compiler_specific.h" 10 #include "content/common/view_messages.h" 11 #include "net/base/net_errors.h" 12 #include "net/url_request/url_request_context.h" 13 #include "net/url_request/url_request_context_getter.h" 14 15 namespace content { 16 17 ResolveProxyMsgHelper::ResolveProxyMsgHelper( 18 net::URLRequestContextGetter* getter) 19 : context_getter_(getter), 20 proxy_service_(NULL) { 21 } 22 23 ResolveProxyMsgHelper::ResolveProxyMsgHelper(net::ProxyService* proxy_service) 24 : proxy_service_(proxy_service) { 25 } 26 27 bool ResolveProxyMsgHelper::OnMessageReceived(const IPC::Message& message, 28 bool* message_was_ok) { 29 bool handled = true; 30 IPC_BEGIN_MESSAGE_MAP_EX(ResolveProxyMsgHelper, message, *message_was_ok) 31 IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ResolveProxy, OnResolveProxy) 32 IPC_MESSAGE_UNHANDLED(handled = false) 33 IPC_END_MESSAGE_MAP() 34 return handled; 35 } 36 37 void ResolveProxyMsgHelper::OnResolveProxy(const GURL& url, 38 IPC::Message* reply_msg) { 39 // Enqueue the pending request. 40 pending_requests_.push_back(PendingRequest(url, reply_msg)); 41 42 // If nothing is in progress, start. 43 if (pending_requests_.size() == 1) 44 StartPendingRequest(); 45 } 46 47 ResolveProxyMsgHelper::~ResolveProxyMsgHelper() { 48 // Clear all pending requests if the ProxyService is still alive (if we have a 49 // default request context or override). 50 if (!pending_requests_.empty()) { 51 PendingRequest req = pending_requests_.front(); 52 proxy_service_->CancelPacRequest(req.pac_req); 53 } 54 55 for (PendingRequestList::iterator it = pending_requests_.begin(); 56 it != pending_requests_.end(); 57 ++it) { 58 delete it->reply_msg; 59 } 60 61 pending_requests_.clear(); 62 } 63 64 void ResolveProxyMsgHelper::OnResolveProxyCompleted(int result) { 65 CHECK(!pending_requests_.empty()); 66 67 const PendingRequest& completed_req = pending_requests_.front(); 68 ViewHostMsg_ResolveProxy::WriteReplyParams( 69 completed_req.reply_msg, result == net::OK, proxy_info_.ToPacString()); 70 Send(completed_req.reply_msg); 71 72 // Clear the current (completed) request. 73 pending_requests_.pop_front(); 74 75 // Start the next request. 76 if (!pending_requests_.empty()) 77 StartPendingRequest(); 78 } 79 80 void ResolveProxyMsgHelper::StartPendingRequest() { 81 PendingRequest& req = pending_requests_.front(); 82 83 // Verify the request wasn't started yet. 84 DCHECK(NULL == req.pac_req); 85 86 if (context_getter_.get()) { 87 proxy_service_ = context_getter_->GetURLRequestContext()->proxy_service(); 88 context_getter_ = NULL; 89 } 90 91 // Start the request. 92 int result = proxy_service_->ResolveProxy( 93 req.url, &proxy_info_, 94 base::Bind(&ResolveProxyMsgHelper::OnResolveProxyCompleted, 95 base::Unretained(this)), 96 &req.pac_req, net::BoundNetLog()); 97 98 // Completed synchronously. 99 if (result != net::ERR_IO_PENDING) 100 OnResolveProxyCompleted(result); 101 } 102 103 } // namespace content 104