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