OLD | NEW |
---|---|
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this |
2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
3 // LICENSE file. | 3 // LICENSE file. |
4 | 4 |
5 #include "net/proxy/proxy_resolver_v8.h" | 5 #include "net/proxy/proxy_resolver_v8.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "googleurl/src/gurl.h" | 9 #include "googleurl/src/gurl.h" |
10 #include "net/base/load_log.h" | 10 #include "net/base/load_log.h" |
11 #include "net/base/net_errors.h" | 11 #include "net/base/net_errors.h" |
12 #include "net/proxy/proxy_info.h" | 12 #include "net/proxy/proxy_info.h" |
13 #include "net/proxy/proxy_resolver_js_bindings.h" | 13 #include "net/proxy/proxy_resolver_js_bindings.h" |
14 #include "net/proxy/proxy_resolver_script.h" | 14 #include "net/proxy/proxy_resolver_script.h" |
15 #include "v8/include/v8.h" | 15 #include "v8/include/v8.h" |
16 | 16 |
17 // Notes on the javascript environment: | |
wtc
2009/10/24 04:40:59
Very nice! Thanks.
| |
18 // | |
19 // For the majority of the PAC utility functions, we use the same code | |
20 // as Firefox. See the javascript library that proxy_resolver_scipt.h | |
21 // pulls in. | |
22 // | |
23 // In addition, we implement a subset of Microsoft's extensions to PAC. | |
24 // TODO(eroman): Implement the rest. | |
25 // | |
26 // - myIpAddressEx() | |
27 // - dnsResolveEx() | |
28 // - isResolvableEx() | |
29 // | |
30 // It is worth noting that the original PAC specification does not describe | |
31 // the return values on failure. Consequently, there are compatibility | |
32 // differences between browsers on what to return on failure, which are | |
33 // illustrated below: | |
34 // | |
35 // ----------------+-------------+-------------------+-------------- | |
36 // | Firefox3 | InternetExplorer8 | --> Us <--- | |
37 // ----------------+-------------+-------------------+-------------- | |
38 // myIpAddress() | "127.0.0.1" | ??? | "127.0.0.1" | |
39 // dnsResolve() | null | false | null | |
40 // myIpAddressEx() | N/A | "" | "" | |
41 // dnsResolveEx() | N/A | "" | "" | |
42 // ----------------+-------------+-------------------+-------------- | |
43 // | |
44 // TODO(eroman): The cell above reading ??? means I didn't test it. | |
45 // | |
46 // Another difference is in how dnsResolve() and myIpAddress() are | |
47 // implemented -- whether they should restrict to IPv4 results, or | |
48 // include both IPv4 and IPv6. The following table illustrates the | |
49 // differences: | |
50 // | |
51 // -----------------+-------------+-------------------+-------------- | |
52 // | Firefox3 | InternetExplorer8 | --> Us <--- | |
53 // -----------------+-------------+-------------------+-------------- | |
54 // myIpAddress() | IPv4/IPv6 | IPv4 | IPv4 | |
55 // dnsResolve() | IPv4/IPv6 | IPv4 | IPv4 | |
wtc
2009/10/24 04:40:59
It's possible that Firefox's dnsResolve returns IP
| |
56 // isResolvable() | IPv4/IPv6 | IPv4 | IPv4 | |
57 // myIpAddressEx() | N/A | IPv4/IPv6 | IPv4/IPv6 | |
58 // dnsResolveEx() | N/A | IPv4/IPv6 | IPv4/IPv6 | |
59 // isResolvableEx() | N/A | IPv4/IPv6 | IPv4/IPv6 | |
60 // -----------------+-------------+-------------------+-------------- | |
61 | |
17 namespace net { | 62 namespace net { |
18 | 63 |
19 namespace { | 64 namespace { |
20 | 65 |
21 // Pseudo-name for the PAC script. | 66 // Pseudo-name for the PAC script. |
22 const char kPacResourceName[] = "proxy-pac-script.js"; | 67 const char kPacResourceName[] = "proxy-pac-script.js"; |
23 // Pseudo-name for the PAC utility script. | 68 // Pseudo-name for the PAC utility script. |
24 const char kPacUtilityResourceName[] = "proxy-pac-utility-script.js"; | 69 const char kPacUtilityResourceName[] = "proxy-pac-utility-script.js"; |
25 | 70 |
26 // Convert a V8 String to a std::string. | 71 // Convert a V8 String to a std::string. |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 v8::Local<v8::FunctionTemplate> my_ip_address_template = | 166 v8::Local<v8::FunctionTemplate> my_ip_address_template = |
122 v8::FunctionTemplate::New(&MyIpAddressCallback, v8_this_); | 167 v8::FunctionTemplate::New(&MyIpAddressCallback, v8_this_); |
123 global_template->Set(v8::String::New("myIpAddress"), | 168 global_template->Set(v8::String::New("myIpAddress"), |
124 my_ip_address_template); | 169 my_ip_address_template); |
125 | 170 |
126 v8::Local<v8::FunctionTemplate> dns_resolve_template = | 171 v8::Local<v8::FunctionTemplate> dns_resolve_template = |
127 v8::FunctionTemplate::New(&DnsResolveCallback, v8_this_); | 172 v8::FunctionTemplate::New(&DnsResolveCallback, v8_this_); |
128 global_template->Set(v8::String::New("dnsResolve"), | 173 global_template->Set(v8::String::New("dnsResolve"), |
129 dns_resolve_template); | 174 dns_resolve_template); |
130 | 175 |
176 // Microsoft's PAC extensions (incomplete): | |
177 | |
178 v8::Local<v8::FunctionTemplate> dns_resolve_ex_template = | |
179 v8::FunctionTemplate::New(&DnsResolveExCallback, v8_this_); | |
180 global_template->Set(v8::String::New("dnsResolveEx"), | |
181 dns_resolve_ex_template); | |
182 | |
183 v8::Local<v8::FunctionTemplate> my_ip_address_ex_template = | |
184 v8::FunctionTemplate::New(&MyIpAddressExCallback, v8_this_); | |
185 global_template->Set(v8::String::New("myIpAddressEx"), | |
186 my_ip_address_ex_template); | |
187 | |
131 v8_context_ = v8::Context::New(NULL, global_template); | 188 v8_context_ = v8::Context::New(NULL, global_template); |
132 | 189 |
133 v8::Context::Scope ctx(v8_context_); | 190 v8::Context::Scope ctx(v8_context_); |
134 | 191 |
135 // Add the PAC utility functions to the environment. | 192 // Add the PAC utility functions to the environment. |
136 // (This script should never fail, as it is a string literal!) | 193 // (This script should never fail, as it is a string literal!) |
137 int rv = RunScript(PROXY_RESOLVER_SCRIPT, kPacUtilityResourceName); | 194 // Note that the two string literals are concatenated. |
195 int rv = RunScript(PROXY_RESOLVER_SCRIPT | |
196 PROXY_RESOLVER_SCRIPT_EX, | |
197 kPacUtilityResourceName); | |
138 if (rv != OK) { | 198 if (rv != OK) { |
139 NOTREACHED(); | 199 NOTREACHED(); |
140 return rv; | 200 return rv; |
141 } | 201 } |
142 | 202 |
143 // Add the user's PAC code to the environment. | 203 // Add the user's PAC code to the environment. |
144 rv = RunScript(pac_data_utf8, kPacResourceName); | 204 rv = RunScript(pac_data_utf8, kPacResourceName); |
145 if (rv != OK) | 205 if (rv != OK) |
146 return rv; | 206 return rv; |
147 | 207 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 std::string result = context->js_bindings_->MyIpAddress(); | 301 std::string result = context->js_bindings_->MyIpAddress(); |
242 | 302 |
243 LoadLog::EndEvent(context->current_request_load_log_, | 303 LoadLog::EndEvent(context->current_request_load_log_, |
244 LoadLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS); | 304 LoadLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS); |
245 | 305 |
246 if (result.empty()) | 306 if (result.empty()) |
247 result = "127.0.0.1"; | 307 result = "127.0.0.1"; |
248 return StdStringToV8String(result); | 308 return StdStringToV8String(result); |
249 } | 309 } |
250 | 310 |
311 // V8 callback for when "myIpAddressEx()" is invoked by the PAC script. | |
312 static v8::Handle<v8::Value> MyIpAddressExCallback( | |
313 const v8::Arguments& args) { | |
314 Context* context = | |
315 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | |
316 | |
317 LoadLog::BeginEvent(context->current_request_load_log_, | |
318 LoadLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX); | |
319 | |
320 // We shouldn't be called with any arguments, but will not complain if | |
321 // we are. | |
322 std::string result = context->js_bindings_->MyIpAddressEx(); | |
323 | |
324 LoadLog::EndEvent(context->current_request_load_log_, | |
325 LoadLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX); | |
326 | |
327 return StdStringToV8String(result); | |
328 } | |
329 | |
251 // V8 callback for when "dnsResolve()" is invoked by the PAC script. | 330 // V8 callback for when "dnsResolve()" is invoked by the PAC script. |
252 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { | 331 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { |
253 Context* context = | 332 Context* context = |
254 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 333 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
255 | 334 |
256 // We need at least one argument. | 335 // We need at least one argument. |
257 std::string host; | 336 std::string host; |
258 if (args.Length() == 0) { | 337 if (args.Length() == 0) { |
259 host = "undefined"; | 338 host = "undefined"; |
260 } else { | 339 } else { |
261 if (!V8ObjectToString(args[0], &host)) | 340 if (!V8ObjectToString(args[0], &host)) |
262 return v8::Undefined(); | 341 return v8::Undefined(); |
263 } | 342 } |
264 | 343 |
265 LoadLog::BeginEvent(context->current_request_load_log_, | 344 LoadLog::BeginEvent(context->current_request_load_log_, |
266 LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE); | 345 LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE); |
267 | 346 |
268 std::string result = context->js_bindings_->DnsResolve(host); | 347 std::string result = context->js_bindings_->DnsResolve(host); |
269 | 348 |
270 LoadLog::EndEvent(context->current_request_load_log_, | 349 LoadLog::EndEvent(context->current_request_load_log_, |
271 LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE); | 350 LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE); |
272 | 351 |
273 // DoDnsResolve() returns empty string on failure. | 352 // DnsResolve() returns empty string on failure. |
274 return result.empty() ? v8::Null() : StdStringToV8String(result); | 353 return result.empty() ? v8::Null() : StdStringToV8String(result); |
275 } | 354 } |
276 | 355 |
356 // V8 callback for when "dnsResolveEx()" is invoked by the PAC script. | |
357 static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) { | |
358 Context* context = | |
359 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | |
360 | |
361 // We need at least one argument. | |
362 std::string host; | |
363 if (args.Length() == 0) { | |
364 host = "undefined"; | |
365 } else { | |
366 if (!V8ObjectToString(args[0], &host)) | |
367 return v8::Undefined(); | |
368 } | |
369 | |
370 LoadLog::BeginEvent(context->current_request_load_log_, | |
371 LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX); | |
372 | |
373 std::string result = context->js_bindings_->DnsResolveEx(host); | |
374 | |
375 LoadLog::EndEvent(context->current_request_load_log_, | |
376 LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX); | |
377 | |
378 return StdStringToV8String(result); | |
379 } | |
380 | |
277 ProxyResolverJSBindings* js_bindings_; | 381 ProxyResolverJSBindings* js_bindings_; |
278 LoadLog* current_request_load_log_; | 382 LoadLog* current_request_load_log_; |
279 v8::Persistent<v8::External> v8_this_; | 383 v8::Persistent<v8::External> v8_this_; |
280 v8::Persistent<v8::Context> v8_context_; | 384 v8::Persistent<v8::Context> v8_context_; |
281 }; | 385 }; |
282 | 386 |
283 // ProxyResolverV8 ------------------------------------------------------------ | 387 // ProxyResolverV8 ------------------------------------------------------------ |
284 | 388 |
285 ProxyResolverV8::ProxyResolverV8( | 389 ProxyResolverV8::ProxyResolverV8( |
286 ProxyResolverJSBindings* custom_js_bindings) | 390 ProxyResolverJSBindings* custom_js_bindings) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
326 | 430 |
327 // Try parsing the PAC script. | 431 // Try parsing the PAC script. |
328 scoped_ptr<Context> context(new Context(js_bindings_.get())); | 432 scoped_ptr<Context> context(new Context(js_bindings_.get())); |
329 int rv = context->InitV8(bytes_utf8); | 433 int rv = context->InitV8(bytes_utf8); |
330 if (rv == OK) | 434 if (rv == OK) |
331 context_.reset(context.release()); | 435 context_.reset(context.release()); |
332 return rv; | 436 return rv; |
333 } | 437 } |
334 | 438 |
335 } // namespace net | 439 } // namespace net |
OLD | NEW |