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