Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(363)

Side by Side Diff: net/proxy/proxy_resolver_v8.cc

Issue 2833021: Add an additional per-request DNS cache when executing FindProxyForURL() from... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Address wtc's comments Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the 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/host_cache.h"
10 #include "net/base/net_errors.h" 11 #include "net/base/net_errors.h"
11 #include "net/base/net_log.h" 12 #include "net/base/net_log.h"
12 #include "net/proxy/proxy_info.h" 13 #include "net/proxy/proxy_info.h"
13 #include "net/proxy/proxy_resolver_js_bindings.h" 14 #include "net/proxy/proxy_resolver_js_bindings.h"
15 #include "net/proxy/proxy_resolver_request_context.h"
14 #include "net/proxy/proxy_resolver_script.h" 16 #include "net/proxy/proxy_resolver_script.h"
15 #include "v8/include/v8.h" 17 #include "v8/include/v8.h"
16 18
17 // Notes on the javascript environment: 19 // Notes on the javascript environment:
18 // 20 //
19 // For the majority of the PAC utility functions, we use the same code 21 // 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 22 // as Firefox. See the javascript library that proxy_resolver_scipt.h
21 // pulls in. 23 // pulls in.
22 // 24 //
23 // In addition, we implement a subset of Microsoft's extensions to PAC. 25 // In addition, we implement a subset of Microsoft's extensions to PAC.
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 209
208 // At a minimum, the FindProxyForURL() function must be defined for this 210 // At a minimum, the FindProxyForURL() function must be defined for this
209 // to be a legitimiate PAC script. 211 // to be a legitimiate PAC script.
210 v8::Local<v8::Value> function; 212 v8::Local<v8::Value> function;
211 if (!GetFindProxyForURL(&function)) 213 if (!GetFindProxyForURL(&function))
212 return ERR_PAC_SCRIPT_FAILED; 214 return ERR_PAC_SCRIPT_FAILED;
213 215
214 return OK; 216 return OK;
215 } 217 }
216 218
217 void SetCurrentRequestNetLog(const BoundNetLog& net_log) { 219 void SetCurrentRequestContext(ProxyResolverRequestContext* context) {
218 current_request_net_log_ = net_log; 220 js_bindings_->set_current_request_context(context);
219 } 221 }
220 222
221 void PurgeMemory() { 223 void PurgeMemory() {
222 v8::Locker locked; 224 v8::Locker locked;
223 // Repeatedly call the V8 idle notification until it returns true ("nothing 225 // Repeatedly call the V8 idle notification until it returns true ("nothing
224 // more to free"). Note that it makes more sense to do this than to 226 // more to free"). Note that it makes more sense to do this than to
225 // implement a new "delete everything" pass because object references make 227 // implement a new "delete everything" pass because object references make
226 // it difficult to free everything possible in just one pass. 228 // it difficult to free everything possible in just one pass.
227 while (!v8::V8::IdleNotification()) 229 while (!v8::V8::IdleNotification())
228 ; 230 ;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 // V8 callback for when "myIpAddress()" is invoked by the PAC script. 293 // V8 callback for when "myIpAddress()" is invoked by the PAC script.
292 static v8::Handle<v8::Value> MyIpAddressCallback(const v8::Arguments& args) { 294 static v8::Handle<v8::Value> MyIpAddressCallback(const v8::Arguments& args) {
293 Context* context = 295 Context* context =
294 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 296 static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
295 297
296 std::string result; 298 std::string result;
297 299
298 { 300 {
299 v8::Unlocker unlocker; 301 v8::Unlocker unlocker;
300 302
301 context->current_request_net_log_.BeginEvent( 303 LogEventToCurrentRequest(context,
302 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS, NULL); 304 NetLog::PHASE_BEGIN,
305 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS,
306 NULL);
303 307
304 // We shouldn't be called with any arguments, but will not complain if 308 // We shouldn't be called with any arguments, but will not complain if
305 // we are. 309 // we are.
306 result = context->js_bindings_->MyIpAddress(); 310 result = context->js_bindings_->MyIpAddress();
307 311
308 context->current_request_net_log_.EndEvent( 312 LogEventToCurrentRequest(context,
309 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS, NULL); 313 NetLog::PHASE_END,
314 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS,
315 NULL);
310 } 316 }
311 317
312 if (result.empty()) 318 if (result.empty())
313 result = "127.0.0.1"; 319 result = "127.0.0.1";
314 return StdStringToV8String(result); 320 return StdStringToV8String(result);
315 } 321 }
316 322
317 // V8 callback for when "myIpAddressEx()" is invoked by the PAC script. 323 // V8 callback for when "myIpAddressEx()" is invoked by the PAC script.
318 static v8::Handle<v8::Value> MyIpAddressExCallback( 324 static v8::Handle<v8::Value> MyIpAddressExCallback(
319 const v8::Arguments& args) { 325 const v8::Arguments& args) {
320 Context* context = 326 Context* context =
321 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 327 static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
322 328
323 std::string result; 329 std::string result;
324 330
325 { 331 {
326 v8::Unlocker unlocker; 332 v8::Unlocker unlocker;
327 333
328 context->current_request_net_log_.BeginEvent( 334 LogEventToCurrentRequest(context,
329 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX, NULL); 335 NetLog::PHASE_BEGIN,
336 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX,
337 NULL);
330 338
331 // We shouldn't be called with any arguments, but will not complain if 339 // We shouldn't be called with any arguments, but will not complain if
332 // we are. 340 // we are.
333 context->js_bindings_->MyIpAddressEx(); 341 context->js_bindings_->MyIpAddressEx();
334 342
335 context->current_request_net_log_.EndEvent( 343 LogEventToCurrentRequest(context,
336 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX, NULL); 344 NetLog::PHASE_END,
345 NetLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX,
346 NULL);
337 } 347 }
338 348
339 return StdStringToV8String(result); 349 return StdStringToV8String(result);
340 } 350 }
341 351
342 // V8 callback for when "dnsResolve()" is invoked by the PAC script. 352 // V8 callback for when "dnsResolve()" is invoked by the PAC script.
343 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { 353 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) {
344 Context* context = 354 Context* context =
345 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 355 static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
346 356
347 // We need at least one string argument. 357 // We need at least one string argument.
348 if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) 358 if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString())
349 return v8::Null(); 359 return v8::Null();
350 std::string host = V8StringToStdString(args[0]->ToString()); 360 std::string host = V8StringToStdString(args[0]->ToString());
351 361
352 std::string result; 362 std::string result;
353 363
354 { 364 {
355 v8::Unlocker unlocker; 365 v8::Unlocker unlocker;
356 366
357 context->current_request_net_log_.BeginEvent( 367 LogEventToCurrentRequest(context,
358 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE, NULL); 368 NetLog::PHASE_BEGIN,
369 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE,
370 NULL);
359 371
360 result = context->js_bindings_->DnsResolve(host); 372 result = context->js_bindings_->DnsResolve(host);
361 373
362 context->current_request_net_log_.EndEvent( 374 LogEventToCurrentRequest(context,
363 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE, NULL); 375 NetLog::PHASE_END,
376 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE,
377 NULL);
364 } 378 }
365 379
366 // DnsResolve() returns empty string on failure. 380 // DnsResolve() returns empty string on failure.
367 return result.empty() ? v8::Null() : StdStringToV8String(result); 381 return result.empty() ? v8::Null() : StdStringToV8String(result);
368 } 382 }
369 383
370 // V8 callback for when "dnsResolveEx()" is invoked by the PAC script. 384 // V8 callback for when "dnsResolveEx()" is invoked by the PAC script.
371 static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) { 385 static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) {
372 Context* context = 386 Context* context =
373 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 387 static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
374 388
375 // We need at least one string argument. 389 // We need at least one string argument.
376 if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) 390 if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString())
377 return v8::Undefined(); 391 return v8::Undefined();
378 std::string host = V8StringToStdString(args[0]->ToString()); 392 std::string host = V8StringToStdString(args[0]->ToString());
379 393
380 std::string result; 394 std::string result;
381 395
382 { 396 {
383 v8::Unlocker unlocker; 397 v8::Unlocker unlocker;
384 398
385 context->current_request_net_log_.BeginEvent( 399 LogEventToCurrentRequest(context,
386 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX, NULL); 400 NetLog::PHASE_BEGIN,
401 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX,
402 NULL);
387 403
388 result = context->js_bindings_->DnsResolveEx(host); 404 result = context->js_bindings_->DnsResolveEx(host);
389 405
390 context->current_request_net_log_.EndEvent( 406 LogEventToCurrentRequest(context,
391 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX, NULL); 407 NetLog::PHASE_END,
408 NetLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX,
409 NULL);
392 } 410 }
393 411
394 return StdStringToV8String(result); 412 return StdStringToV8String(result);
395 } 413 }
396 414
415 static void LogEventToCurrentRequest(Context* context,
416 NetLog::EventPhase phase,
417 NetLog::EventType type,
418 NetLog::EventParameters* params) {
419 if (context->js_bindings_->current_request_context()) {
420 context->js_bindings_->current_request_context()->net_log->AddEntry(
421 type, phase, params);
422 }
423 }
424
397 ProxyResolverJSBindings* js_bindings_; 425 ProxyResolverJSBindings* js_bindings_;
398 BoundNetLog current_request_net_log_;
399 v8::Persistent<v8::External> v8_this_; 426 v8::Persistent<v8::External> v8_this_;
400 v8::Persistent<v8::Context> v8_context_; 427 v8::Persistent<v8::Context> v8_context_;
401 }; 428 };
402 429
403 // ProxyResolverV8 ------------------------------------------------------------ 430 // ProxyResolverV8 ------------------------------------------------------------
404 431
405 ProxyResolverV8::ProxyResolverV8( 432 ProxyResolverV8::ProxyResolverV8(
406 ProxyResolverJSBindings* custom_js_bindings) 433 ProxyResolverJSBindings* custom_js_bindings)
407 : ProxyResolver(true /*expects_pac_bytes*/), 434 : ProxyResolver(true /*expects_pac_bytes*/),
408 js_bindings_(custom_js_bindings) { 435 js_bindings_(custom_js_bindings) {
409 } 436 }
410 437
411 ProxyResolverV8::~ProxyResolverV8() {} 438 ProxyResolverV8::~ProxyResolverV8() {}
412 439
413 int ProxyResolverV8::GetProxyForURL(const GURL& query_url, 440 int ProxyResolverV8::GetProxyForURL(const GURL& query_url,
414 ProxyInfo* results, 441 ProxyInfo* results,
415 CompletionCallback* /*callback*/, 442 CompletionCallback* /*callback*/,
416 RequestHandle* /*request*/, 443 RequestHandle* /*request*/,
417 const BoundNetLog& net_log) { 444 const BoundNetLog& net_log) {
418 // If the V8 instance has not been initialized (either because 445 // If the V8 instance has not been initialized (either because
419 // SetPacScript() wasn't called yet, or because it failed. 446 // SetPacScript() wasn't called yet, or because it failed.
420 if (!context_.get()) 447 if (!context_.get())
421 return ERR_FAILED; 448 return ERR_FAILED;
422 449
450 // Associate some short-lived context with this request. This context will be
451 // available to any of the javascript "bindings" that are subsequently invoked
452 // from the javascript.
453 //
454 // In particular, we create a HostCache that is aggressive about caching
455 // failed DNS resolves.
456 HostCache host_cache(
457 50,
458 base::TimeDelta::FromMinutes(5),
459 base::TimeDelta::FromMinutes(5));
460
461 ProxyResolverRequestContext request_context(
462 &query_url, &net_log, &host_cache);
463
423 // Otherwise call into V8. 464 // Otherwise call into V8.
424 context_->SetCurrentRequestNetLog(net_log); 465 context_->SetCurrentRequestContext(&request_context);
425 int rv = context_->ResolveProxy(query_url, results); 466 int rv = context_->ResolveProxy(query_url, results);
426 context_->SetCurrentRequestNetLog(BoundNetLog()); 467 context_->SetCurrentRequestContext(NULL);
427 468
428 return rv; 469 return rv;
429 } 470 }
430 471
431 void ProxyResolverV8::CancelRequest(RequestHandle request) { 472 void ProxyResolverV8::CancelRequest(RequestHandle request) {
432 // This is a synchronous ProxyResolver; no possibility for async requests. 473 // This is a synchronous ProxyResolver; no possibility for async requests.
433 NOTREACHED(); 474 NOTREACHED();
434 } 475 }
435 476
436 void ProxyResolverV8::PurgeMemory() { 477 void ProxyResolverV8::PurgeMemory() {
437 context_->PurgeMemory(); 478 context_->PurgeMemory();
438 } 479 }
439 480
440 int ProxyResolverV8::SetPacScript(const GURL& /*url*/, 481 int ProxyResolverV8::SetPacScript(const GURL& /*url*/,
441 const std::string& bytes_utf8, 482 const std::string& bytes_utf8,
442 CompletionCallback* /*callback*/) { 483 CompletionCallback* /*callback*/) {
443 context_.reset(); 484 context_.reset();
444 if (bytes_utf8.empty()) 485 if (bytes_utf8.empty())
445 return ERR_PAC_SCRIPT_FAILED; 486 return ERR_PAC_SCRIPT_FAILED;
446 487
447 // Try parsing the PAC script. 488 // Try parsing the PAC script.
448 scoped_ptr<Context> context(new Context(js_bindings_.get())); 489 scoped_ptr<Context> context(new Context(js_bindings_.get()));
449 int rv = context->InitV8(bytes_utf8); 490 int rv = context->InitV8(bytes_utf8);
450 if (rv == OK) 491 if (rv == OK)
451 context_.reset(context.release()); 492 context_.reset(context.release());
452 return rv; 493 return rv;
453 } 494 }
454 495
455 } // namespace net 496 } // namespace net
OLDNEW
« net/proxy/proxy_resolver_request_context.h ('K') | « net/proxy/proxy_resolver_request_context.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698