Enables compositing support for webview.
[chromium-blink-merge.git] / net / proxy / proxy_resolver_js_bindings.cc
blob84dcafda4dca6f680f2c79086c264c9b5ead1457
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.
5 #include "net/proxy/proxy_resolver_js_bindings.h"
7 #include "base/bind.h"
8 #include "base/compiler_specific.h"
9 #include "base/logging.h"
10 #include "base/string_util.h"
11 #include "base/values.h"
12 #include "net/base/address_list.h"
13 #include "net/base/host_cache.h"
14 #include "net/base/host_resolver.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/net_log.h"
17 #include "net/base/net_util.h"
18 #include "net/proxy/proxy_resolver_error_observer.h"
19 #include "net/proxy/proxy_resolver_request_context.h"
20 #include "net/proxy/sync_host_resolver.h"
22 namespace net {
24 namespace {
26 // TTL for the per-request DNS cache. Applies to both successful and failed
27 // DNS resolutions.
28 const unsigned kCacheEntryTTLSeconds = 5 * 60;
30 // Returns event parameters for a PAC error message (line number + message).
31 Value* NetLogErrorCallback(int line_number,
32 const string16* message,
33 NetLog::LogLevel /* log_level */) {
34 DictionaryValue* dict = new DictionaryValue();
35 dict->SetInteger("line_number", line_number);
36 dict->SetString("message", *message);
37 return dict;
40 // ProxyResolverJSBindings implementation.
41 class DefaultJSBindings : public ProxyResolverJSBindings {
42 public:
43 DefaultJSBindings(SyncHostResolver* host_resolver,
44 NetLog* net_log,
45 ProxyResolverErrorObserver* error_observer)
46 : host_resolver_(host_resolver),
47 net_log_(net_log),
48 error_observer_(error_observer) {
51 // Handler for "alert(message)".
52 virtual void Alert(const string16& message) OVERRIDE {
53 VLOG(1) << "PAC-alert: " << message;
55 // Send to the NetLog.
56 LogEventToCurrentRequestAndGlobally(
57 NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
58 NetLog::StringCallback("message", &message));
61 // Handler for "myIpAddress()".
62 // TODO(eroman): Perhaps enumerate the interfaces directly, using
63 // getifaddrs().
64 virtual bool MyIpAddress(std::string* first_ip_address) OVERRIDE {
65 LogEventToCurrentRequest(NetLog::PHASE_BEGIN,
66 NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS);
68 bool ok = MyIpAddressImpl(first_ip_address);
70 LogEventToCurrentRequest(NetLog::PHASE_END,
71 NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS);
72 return ok;
75 // Handler for "myIpAddressEx()".
76 virtual bool MyIpAddressEx(std::string* ip_address_list) OVERRIDE {
77 LogEventToCurrentRequest(NetLog::PHASE_BEGIN,
78 NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX);
80 bool ok = MyIpAddressExImpl(ip_address_list);
82 LogEventToCurrentRequest(NetLog::PHASE_END,
83 NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX);
84 return ok;
87 // Handler for "dnsResolve(host)".
88 virtual bool DnsResolve(const std::string& host,
89 std::string* first_ip_address) OVERRIDE {
90 LogEventToCurrentRequest(NetLog::PHASE_BEGIN,
91 NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE);
93 bool ok = DnsResolveImpl(host, first_ip_address);
95 LogEventToCurrentRequest(NetLog::PHASE_END,
96 NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE);
97 return ok;
100 // Handler for "dnsResolveEx(host)".
101 virtual bool DnsResolveEx(const std::string& host,
102 std::string* ip_address_list) OVERRIDE {
103 LogEventToCurrentRequest(NetLog::PHASE_BEGIN,
104 NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX);
106 bool ok = DnsResolveExImpl(host, ip_address_list);
108 LogEventToCurrentRequest(NetLog::PHASE_END,
109 NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX);
110 return ok;
113 // Handler for when an error is encountered. |line_number| may be -1.
114 virtual void OnError(int line_number, const string16& message) OVERRIDE {
115 // Send to the chrome log.
116 if (line_number == -1)
117 VLOG(1) << "PAC-error: " << message;
118 else
119 VLOG(1) << "PAC-error: " << "line: " << line_number << ": " << message;
121 // Send the error to the NetLog.
122 LogEventToCurrentRequestAndGlobally(
123 NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
124 base::Bind(&NetLogErrorCallback, line_number, &message));
126 if (error_observer_.get())
127 error_observer_->OnPACScriptError(line_number, message);
130 virtual void Shutdown() OVERRIDE {
131 host_resolver_->Shutdown();
134 private:
135 bool MyIpAddressImpl(std::string* first_ip_address) {
136 std::string my_hostname = GetHostName();
137 if (my_hostname.empty())
138 return false;
139 return DnsResolveImpl(my_hostname, first_ip_address);
142 bool MyIpAddressExImpl(std::string* ip_address_list) {
143 std::string my_hostname = GetHostName();
144 if (my_hostname.empty())
145 return false;
146 return DnsResolveExImpl(my_hostname, ip_address_list);
149 bool DnsResolveImpl(const std::string& host,
150 std::string* first_ip_address) {
151 // Do a sync resolve of the hostname (port doesn't matter).
152 // Disable IPv6 results. We do this because the PAC specification isn't
153 // really IPv6 friendly, and Internet Explorer also restricts to IPv4.
154 // Consequently a lot of existing PAC scripts assume they will only get
155 // IPv4 results, and will misbehave if they get an IPv6 result.
156 // See http://crbug.com/24641 for more details.
157 HostResolver::RequestInfo info(HostPortPair(host, 80));
158 info.set_address_family(ADDRESS_FAMILY_IPV4);
159 AddressList address_list;
161 int result = DnsResolveHelper(info, &address_list);
162 if (result != OK)
163 return false;
165 // There may be multiple results; we will just use the first one.
166 // This returns empty string on failure.
167 *first_ip_address = address_list.front().ToStringWithoutPort();
168 if (first_ip_address->empty())
169 return false;
171 return true;
174 bool DnsResolveExImpl(const std::string& host,
175 std::string* ip_address_list) {
176 // Do a sync resolve of the hostname (port doesn't matter).
177 HostResolver::RequestInfo info(HostPortPair(host, 80));
178 AddressList address_list;
179 int result = DnsResolveHelper(info, &address_list);
181 if (result != OK)
182 return false;
184 // Stringify all of the addresses in the address list, separated
185 // by semicolons.
186 std::string address_list_str;
187 for (AddressList::const_iterator iter = address_list.begin();
188 iter != address_list.end(); ++iter) {
189 if (!address_list_str.empty())
190 address_list_str += ";";
191 const std::string address_string = iter->ToStringWithoutPort();
192 if (address_string.empty())
193 return false;
194 address_list_str += address_string;
197 *ip_address_list = address_list_str;
198 return true;
201 // Helper to execute a synchronous DNS resolve, using the per-request
202 // DNS cache if there is one.
203 int DnsResolveHelper(const HostResolver::RequestInfo& info,
204 AddressList* address_list) {
205 HostCache::Key cache_key(info.hostname(),
206 info.address_family(),
207 info.host_resolver_flags());
209 HostCache* host_cache = current_request_context() ?
210 current_request_context()->host_cache : NULL;
212 // First try to service this request from the per-request DNS cache.
213 // (we cache DNS failures much more aggressively within the context
214 // of a FindProxyForURL() request).
215 if (host_cache) {
216 const HostCache::Entry* entry =
217 host_cache->Lookup(cache_key, base::TimeTicks::Now());
218 if (entry) {
219 if (entry->error == OK)
220 *address_list = entry->addrlist;
221 return entry->error;
225 // Otherwise ask the host resolver.
226 const BoundNetLog* net_log = GetNetLogForCurrentRequest();
227 int result = host_resolver_->Resolve(info,
228 address_list,
229 net_log ? *net_log : BoundNetLog());
231 // Save the result back to the per-request DNS cache.
232 if (host_cache) {
233 host_cache->Set(cache_key, HostCache::Entry(result, *address_list),
234 base::TimeTicks::Now(),
235 base::TimeDelta::FromSeconds(kCacheEntryTTLSeconds));
238 return result;
241 // May return NULL.
242 const BoundNetLog* GetNetLogForCurrentRequest() {
243 if (!current_request_context())
244 return NULL;
245 return current_request_context()->net_log;
248 void LogEventToCurrentRequest(
249 NetLog::EventPhase phase,
250 NetLog::EventType type) {
251 const BoundNetLog* net_log = GetNetLogForCurrentRequest();
252 if (net_log)
253 net_log->AddEntry(type, phase);
256 void LogEventToCurrentRequest(
257 NetLog::EventPhase phase,
258 NetLog::EventType type,
259 const NetLog::ParametersCallback& parameters_callback) {
260 const BoundNetLog* net_log = GetNetLogForCurrentRequest();
261 if (net_log)
262 net_log->AddEntry(type, phase, parameters_callback);
265 void LogEventToCurrentRequestAndGlobally(
266 NetLog::EventType type,
267 const NetLog::ParametersCallback& parameters_callback) {
268 LogEventToCurrentRequest(NetLog::PHASE_NONE, type, parameters_callback);
270 // Emit to the global NetLog event stream.
271 if (net_log_)
272 net_log_->AddGlobalEntry(type, parameters_callback);
275 scoped_ptr<SyncHostResolver> host_resolver_;
276 NetLog* net_log_;
277 scoped_ptr<ProxyResolverErrorObserver> error_observer_;
278 DISALLOW_COPY_AND_ASSIGN(DefaultJSBindings);
281 } // namespace
283 // static
284 ProxyResolverJSBindings* ProxyResolverJSBindings::CreateDefault(
285 SyncHostResolver* host_resolver,
286 NetLog* net_log,
287 ProxyResolverErrorObserver* error_observer) {
288 return new DefaultJSBindings(host_resolver, net_log, error_observer);
291 } // namespace net