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
16 namespace content {
17
ResolveProxyMsgHelper(net::URLRequestContextGetter * getter)18 ResolveProxyMsgHelper::ResolveProxyMsgHelper(
19 net::URLRequestContextGetter* getter)
20 : BrowserMessageFilter(ViewMsgStart),
21 context_getter_(getter),
22 proxy_service_(NULL) {
23 }
24
ResolveProxyMsgHelper(net::ProxyService * proxy_service)25 ResolveProxyMsgHelper::ResolveProxyMsgHelper(net::ProxyService* proxy_service)
26 : BrowserMessageFilter(ViewMsgStart),
27 proxy_service_(proxy_service) {
28 }
29
OnMessageReceived(const IPC::Message & message)30 bool 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
OnResolveProxy(const GURL & url,IPC::Message * reply_msg)39 void 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
~ResolveProxyMsgHelper()49 ResolveProxyMsgHelper::~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
OnResolveProxyCompleted(int result)66 void 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
StartPendingRequest()82 void 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