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 : BrowserMessageFilter(ViewMsgStart), 20 context_getter_(getter), 21 proxy_service_(NULL) { 22 } 23 24 ResolveProxyMsgHelper::ResolveProxyMsgHelper(net::ProxyService* proxy_service) 25 : BrowserMessageFilter(ViewMsgStart), 26 proxy_service_(proxy_service) { 27 } 28 29 bool 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 38 void 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 48 ResolveProxyMsgHelper::~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 65 void 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 81 void 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