Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 #define V8_DISABLE_DEPRECATIONS 1 | 5 #define V8_DISABLE_DEPRECATIONS 1 |
| 6 | 6 |
| 7 #include "net/proxy/proxy_resolver_v8.h" | 7 #include "net/proxy/proxy_resolver_v8.h" |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <cstdio> | 10 #include <cstdio> |
| 11 | 11 |
| 12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/string_tokenizer.h" | 15 #include "base/string_tokenizer.h" |
| 16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 17 #include "base/synchronization/lock.h" | 17 #include "base/synchronization/lock.h" |
| 18 #include "base/utf_string_conversions.h" | 18 #include "base/utf_string_conversions.h" |
| 19 #include "googleurl/src/gurl.h" | 19 #include "googleurl/src/gurl.h" |
| 20 #include "googleurl/src/url_canon.h" | 20 #include "googleurl/src/url_canon.h" |
| 21 #include "net/base/host_cache.h" | |
| 22 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
| 23 #include "net/base/net_log.h" | 22 #include "net/base/net_log.h" |
| 24 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
| 25 #include "net/proxy/proxy_info.h" | 24 #include "net/proxy/proxy_info.h" |
| 26 #include "net/proxy/proxy_resolver_js_bindings.h" | |
| 27 #include "net/proxy/proxy_resolver_request_context.h" | |
| 28 #include "net/proxy/proxy_resolver_script.h" | 25 #include "net/proxy/proxy_resolver_script.h" |
| 29 #include "v8/include/v8.h" | 26 #include "v8/include/v8.h" |
| 30 | 27 |
| 31 // Notes on the javascript environment: | 28 // Notes on the javascript environment: |
| 32 // | 29 // |
| 33 // For the majority of the PAC utility functions, we use the same code | 30 // For the majority of the PAC utility functions, we use the same code |
| 34 // as Firefox. See the javascript library that proxy_resolver_scipt.h | 31 // as Firefox. See the javascript library that proxy_resolver_scipt.h |
| 35 // pulls in. | 32 // pulls in. |
| 36 // | 33 // |
| 37 // In addition, we implement a subset of Microsoft's extensions to PAC. | 34 // In addition, we implement a subset of Microsoft's extensions to PAC. |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 330 | 327 |
| 331 return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits); | 328 return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits); |
| 332 } | 329 } |
| 333 | 330 |
| 334 } // namespace | 331 } // namespace |
| 335 | 332 |
| 336 // ProxyResolverV8::Context --------------------------------------------------- | 333 // ProxyResolverV8::Context --------------------------------------------------- |
| 337 | 334 |
| 338 class ProxyResolverV8::Context { | 335 class ProxyResolverV8::Context { |
| 339 public: | 336 public: |
| 340 explicit Context(ProxyResolverJSBindings* js_bindings) | 337 explicit Context(ProxyResolverV8* parent) |
| 341 : is_resolving_host_(false), | 338 : parent_(parent) { |
| 342 js_bindings_(js_bindings) { | |
| 343 DCHECK(js_bindings != NULL); | |
| 344 } | 339 } |
| 345 | 340 |
| 346 ~Context() { | 341 ~Context() { |
| 347 v8::Locker locked; | 342 v8::Locker locked; |
| 348 | 343 |
| 349 v8_this_.Dispose(); | 344 v8_this_.Dispose(); |
| 350 v8_context_.Dispose(); | 345 v8_context_.Dispose(); |
| 351 | 346 |
| 352 // Run the V8 garbage collector. We do this to be sure the | 347 // Run the V8 garbage collector. We do this to be sure the |
| 353 // ExternalStringResource objects we allocated get properly disposed. | 348 // ExternalStringResource objects we allocated get properly disposed. |
| 354 // Otherwise when running the unit-tests they may get leaked. | 349 // Otherwise when running the unit-tests they may get leaked. |
| 355 // See crbug.com/48145. | 350 // See crbug.com/48145. |
| 356 PurgeMemory(); | 351 PurgeMemory(); |
| 357 } | 352 } |
| 358 | 353 |
| 354 JSBindings* js_bindings() { | |
| 355 return parent_->js_bindings_; | |
| 356 } | |
| 357 | |
| 359 int ResolveProxy(const GURL& query_url, ProxyInfo* results) { | 358 int ResolveProxy(const GURL& query_url, ProxyInfo* results) { |
| 360 v8::Locker locked; | 359 v8::Locker locked; |
| 361 v8::HandleScope scope; | 360 v8::HandleScope scope; |
| 362 | 361 |
| 363 v8::Context::Scope function_scope(v8_context_); | 362 v8::Context::Scope function_scope(v8_context_); |
| 364 | 363 |
| 365 v8::Local<v8::Value> function; | 364 v8::Local<v8::Value> function; |
| 366 if (!GetFindProxyForURL(&function)) { | 365 if (!GetFindProxyForURL(&function)) { |
| 367 js_bindings_->OnError( | 366 js_bindings()->OnError( |
| 368 -1, ASCIIToUTF16("FindProxyForURL() is undefined.")); | 367 -1, ASCIIToUTF16("FindProxyForURL() is undefined.")); |
| 369 return ERR_PAC_SCRIPT_FAILED; | 368 return ERR_PAC_SCRIPT_FAILED; |
| 370 } | 369 } |
| 371 | 370 |
| 372 v8::Handle<v8::Value> argv[] = { | 371 v8::Handle<v8::Value> argv[] = { |
| 373 ASCIIStringToV8String(query_url.spec()), | 372 ASCIIStringToV8String(query_url.spec()), |
| 374 ASCIIStringToV8String(query_url.HostNoBrackets()), | 373 ASCIIStringToV8String(query_url.HostNoBrackets()), |
| 375 }; | 374 }; |
| 376 | 375 |
| 377 v8::TryCatch try_catch; | 376 v8::TryCatch try_catch; |
| 378 v8::Local<v8::Value> ret = v8::Function::Cast(*function)->Call( | 377 v8::Local<v8::Value> ret = v8::Function::Cast(*function)->Call( |
| 379 v8_context_->Global(), arraysize(argv), argv); | 378 v8_context_->Global(), arraysize(argv), argv); |
| 380 | 379 |
| 381 if (try_catch.HasCaught()) { | 380 if (try_catch.HasCaught()) { |
| 382 HandleError(try_catch.Message()); | 381 HandleError(try_catch.Message()); |
| 383 return ERR_PAC_SCRIPT_FAILED; | 382 return ERR_PAC_SCRIPT_FAILED; |
| 384 } | 383 } |
| 385 | 384 |
| 386 if (!ret->IsString()) { | 385 if (!ret->IsString()) { |
| 387 js_bindings_->OnError( | 386 js_bindings()->OnError( |
| 388 -1, ASCIIToUTF16("FindProxyForURL() did not return a string.")); | 387 -1, ASCIIToUTF16("FindProxyForURL() did not return a string.")); |
| 389 return ERR_PAC_SCRIPT_FAILED; | 388 return ERR_PAC_SCRIPT_FAILED; |
| 390 } | 389 } |
| 391 | 390 |
| 392 string16 ret_str = V8StringToUTF16(ret->ToString()); | 391 string16 ret_str = V8StringToUTF16(ret->ToString()); |
| 393 | 392 |
| 394 if (!IsStringASCII(ret_str)) { | 393 if (!IsStringASCII(ret_str)) { |
| 395 // TODO(eroman): Rather than failing when a wide string is returned, we | 394 // TODO(eroman): Rather than failing when a wide string is returned, we |
| 396 // could extend the parsing to handle IDNA hostnames by | 395 // could extend the parsing to handle IDNA hostnames by |
| 397 // converting them to ASCII punycode. | 396 // converting them to ASCII punycode. |
| 398 // crbug.com/47234 | 397 // crbug.com/47234 |
| 399 string16 error_message = | 398 string16 error_message = |
| 400 ASCIIToUTF16("FindProxyForURL() returned a non-ASCII string " | 399 ASCIIToUTF16("FindProxyForURL() returned a non-ASCII string " |
| 401 "(crbug.com/47234): ") + ret_str; | 400 "(crbug.com/47234): ") + ret_str; |
| 402 js_bindings_->OnError(-1, error_message); | 401 js_bindings()->OnError(-1, error_message); |
| 403 return ERR_PAC_SCRIPT_FAILED; | 402 return ERR_PAC_SCRIPT_FAILED; |
| 404 } | 403 } |
| 405 | 404 |
| 406 results->UsePacString(UTF16ToASCII(ret_str)); | 405 results->UsePacString(UTF16ToASCII(ret_str)); |
| 407 return OK; | 406 return OK; |
| 408 } | 407 } |
| 409 | 408 |
| 410 int InitV8(const scoped_refptr<ProxyResolverScriptData>& pac_script) { | 409 int InitV8(const scoped_refptr<ProxyResolverScriptData>& pac_script) { |
| 411 v8::Locker locked; | 410 v8::Locker locked; |
| 412 v8::HandleScope scope; | 411 v8::HandleScope scope; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 470 | 469 |
| 471 // Add the user's PAC code to the environment. | 470 // Add the user's PAC code to the environment. |
| 472 rv = RunScript(ScriptDataToV8String(pac_script), kPacResourceName); | 471 rv = RunScript(ScriptDataToV8String(pac_script), kPacResourceName); |
| 473 if (rv != OK) | 472 if (rv != OK) |
| 474 return rv; | 473 return rv; |
| 475 | 474 |
| 476 // At a minimum, the FindProxyForURL() function must be defined for this | 475 // At a minimum, the FindProxyForURL() function must be defined for this |
| 477 // to be a legitimiate PAC script. | 476 // to be a legitimiate PAC script. |
| 478 v8::Local<v8::Value> function; | 477 v8::Local<v8::Value> function; |
| 479 if (!GetFindProxyForURL(&function)) { | 478 if (!GetFindProxyForURL(&function)) { |
| 480 js_bindings_->OnError( | 479 js_bindings()->OnError( |
| 481 -1, ASCIIToUTF16("FindProxyForURL() is undefined.")); | 480 -1, ASCIIToUTF16("FindProxyForURL() is undefined.")); |
| 482 return ERR_PAC_SCRIPT_FAILED; | 481 return ERR_PAC_SCRIPT_FAILED; |
| 483 } | 482 } |
| 484 | 483 |
| 485 return OK; | 484 return OK; |
| 486 } | 485 } |
| 487 | 486 |
| 488 void SetCurrentRequestContext(ProxyResolverRequestContext* context) { | |
| 489 js_bindings_->set_current_request_context(context); | |
| 490 } | |
| 491 | |
| 492 void PurgeMemory() { | 487 void PurgeMemory() { |
| 493 v8::Locker locked; | 488 v8::Locker locked; |
| 494 v8::V8::LowMemoryNotification(); | 489 v8::V8::LowMemoryNotification(); |
| 495 } | 490 } |
| 496 | 491 |
| 497 bool is_resolving_host() const { | |
| 498 base::AutoLock auto_lock(lock_); | |
| 499 return is_resolving_host_; | |
| 500 } | |
| 501 | |
| 502 private: | 492 private: |
| 503 class ScopedHostResolve { | |
| 504 public: | |
| 505 explicit ScopedHostResolve(Context* context) | |
| 506 : context_(context) { | |
| 507 context_->BeginHostResolve(); | |
| 508 } | |
| 509 | |
| 510 ~ScopedHostResolve() { | |
| 511 context_->EndHostResolve(); | |
| 512 } | |
| 513 | |
| 514 private: | |
| 515 Context* const context_; | |
| 516 DISALLOW_COPY_AND_ASSIGN(ScopedHostResolve); | |
| 517 }; | |
| 518 | |
| 519 void BeginHostResolve() { | |
| 520 base::AutoLock auto_lock(lock_); | |
| 521 DCHECK(!is_resolving_host_); | |
| 522 is_resolving_host_ = true; | |
| 523 } | |
| 524 | |
| 525 void EndHostResolve() { | |
| 526 base::AutoLock auto_lock(lock_); | |
| 527 DCHECK(is_resolving_host_); | |
| 528 is_resolving_host_ = false; | |
| 529 } | |
| 530 | |
| 531 bool GetFindProxyForURL(v8::Local<v8::Value>* function) { | 493 bool GetFindProxyForURL(v8::Local<v8::Value>* function) { |
| 532 *function = v8_context_->Global()->Get( | 494 *function = v8_context_->Global()->Get( |
| 533 ASCIILiteralToV8String("FindProxyForURL")); | 495 ASCIILiteralToV8String("FindProxyForURL")); |
| 534 return (*function)->IsFunction(); | 496 return (*function)->IsFunction(); |
| 535 } | 497 } |
| 536 | 498 |
| 537 // Handle an exception thrown by V8. | 499 // Handle an exception thrown by V8. |
| 538 void HandleError(v8::Handle<v8::Message> message) { | 500 void HandleError(v8::Handle<v8::Message> message) { |
| 539 if (message.IsEmpty()) | 501 if (message.IsEmpty()) |
| 540 return; | 502 return; |
| 541 | 503 |
| 542 // Otherwise dispatch to the bindings. | 504 // Otherwise dispatch to the bindings. |
| 543 int line_number = message->GetLineNumber(); | 505 int line_number = message->GetLineNumber(); |
| 544 string16 error_message; | 506 string16 error_message; |
| 545 V8ObjectToUTF16String(message->Get(), &error_message); | 507 V8ObjectToUTF16String(message->Get(), &error_message); |
| 546 js_bindings_->OnError(line_number, error_message); | 508 js_bindings()->OnError(line_number, error_message); |
| 547 } | 509 } |
| 548 | 510 |
| 549 // Compiles and runs |script| in the current V8 context. | 511 // Compiles and runs |script| in the current V8 context. |
| 550 // Returns OK on success, otherwise an error code. | 512 // Returns OK on success, otherwise an error code. |
| 551 int RunScript(v8::Handle<v8::String> script, const char* script_name) { | 513 int RunScript(v8::Handle<v8::String> script, const char* script_name) { |
| 552 v8::TryCatch try_catch; | 514 v8::TryCatch try_catch; |
| 553 | 515 |
| 554 // Compile the script. | 516 // Compile the script. |
| 555 v8::ScriptOrigin origin = | 517 v8::ScriptOrigin origin = |
| 556 v8::ScriptOrigin(ASCIILiteralToV8String(script_name)); | 518 v8::ScriptOrigin(ASCIILiteralToV8String(script_name)); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 577 // Like firefox we assume "undefined" if no argument was specified, and | 539 // Like firefox we assume "undefined" if no argument was specified, and |
| 578 // disregard any arguments beyond the first. | 540 // disregard any arguments beyond the first. |
| 579 string16 message; | 541 string16 message; |
| 580 if (args.Length() == 0) { | 542 if (args.Length() == 0) { |
| 581 message = ASCIIToUTF16("undefined"); | 543 message = ASCIIToUTF16("undefined"); |
| 582 } else { | 544 } else { |
| 583 if (!V8ObjectToUTF16String(args[0], &message)) | 545 if (!V8ObjectToUTF16String(args[0], &message)) |
| 584 return v8::Undefined(); // toString() threw an exception. | 546 return v8::Undefined(); // toString() threw an exception. |
| 585 } | 547 } |
| 586 | 548 |
| 587 context->js_bindings_->Alert(message); | 549 context->js_bindings()->Alert(message); |
| 588 return v8::Undefined(); | 550 return v8::Undefined(); |
| 589 } | 551 } |
| 590 | 552 |
| 591 // V8 callback for when "myIpAddress()" is invoked by the PAC script. | 553 // V8 callback for when "myIpAddress()" is invoked by the PAC script. |
| 592 static v8::Handle<v8::Value> MyIpAddressCallback(const v8::Arguments& args) { | 554 static v8::Handle<v8::Value> MyIpAddressCallback(const v8::Arguments& args) { |
| 593 Context* context = | 555 Context* context = |
| 594 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 556 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 595 | 557 |
| 596 std::string result; | 558 std::string result; |
| 597 bool success; | 559 bool success; |
| 598 | 560 |
| 599 { | 561 { |
| 600 v8::Unlocker unlocker(args.GetIsolate()); | 562 v8::Unlocker unlocker(args.GetIsolate()); |
| 601 ScopedHostResolve scoped_host_resolve(context); | |
| 602 | |
| 603 // We shouldn't be called with any arguments, but will not complain if | 563 // We shouldn't be called with any arguments, but will not complain if |
| 604 // we are. | 564 // we are. |
| 605 success = context->js_bindings_->MyIpAddress(&result); | 565 success = context->js_bindings()->ResolveDns( |
| 566 "", JSBindings::MY_IP_ADDRESS, &result); | |
| 606 } | 567 } |
| 607 | 568 |
| 608 if (!success) | 569 if (!success) |
| 609 return ASCIILiteralToV8String("127.0.0.1"); | 570 return ASCIILiteralToV8String("127.0.0.1"); |
| 610 return ASCIIStringToV8String(result); | 571 return ASCIIStringToV8String(result); |
| 611 } | 572 } |
| 612 | 573 |
| 613 // V8 callback for when "myIpAddressEx()" is invoked by the PAC script. | 574 // V8 callback for when "myIpAddressEx()" is invoked by the PAC script. |
| 614 static v8::Handle<v8::Value> MyIpAddressExCallback( | 575 static v8::Handle<v8::Value> MyIpAddressExCallback( |
| 615 const v8::Arguments& args) { | 576 const v8::Arguments& args) { |
| 616 Context* context = | 577 Context* context = |
| 617 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 578 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 618 | 579 |
| 619 std::string ip_address_list; | 580 std::string ip_address_list; |
| 620 bool success; | 581 bool success; |
| 621 | 582 |
| 622 { | 583 { |
| 623 v8::Unlocker unlocker(args.GetIsolate()); | 584 v8::Unlocker unlocker(args.GetIsolate()); |
| 624 ScopedHostResolve scoped_host_resolve(context); | |
| 625 | |
| 626 // We shouldn't be called with any arguments, but will not complain if | 585 // We shouldn't be called with any arguments, but will not complain if |
| 627 // we are. | 586 // we are. |
| 628 success = context->js_bindings_->MyIpAddressEx(&ip_address_list); | 587 success = context->js_bindings()->ResolveDns( |
| 588 "", JSBindings::MY_IP_ADDRESS_EX, &ip_address_list); | |
| 629 } | 589 } |
| 630 | 590 |
| 631 if (!success) | 591 if (!success) |
| 632 ip_address_list = std::string(); | 592 ip_address_list = std::string(); |
| 633 return ASCIIStringToV8String(ip_address_list); | 593 return ASCIIStringToV8String(ip_address_list); |
| 634 } | 594 } |
| 635 | 595 |
| 636 // V8 callback for when "dnsResolve()" is invoked by the PAC script. | 596 // V8 callback for when "dnsResolve()" is invoked by the PAC script. |
| 637 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { | 597 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { |
| 638 Context* context = | 598 Context* context = |
| 639 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 599 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 640 | 600 |
| 641 // We need at least one string argument. | 601 // We need at least one string argument. |
| 642 std::string hostname; | 602 std::string hostname; |
| 643 if (!GetHostnameArgument(args, &hostname)) | 603 if (!GetHostnameArgument(args, &hostname)) |
| 644 return v8::Null(); | 604 return v8::Null(); |
| 645 | 605 |
| 646 std::string ip_address; | 606 std::string ip_address; |
| 647 bool success; | 607 bool success; |
| 648 | 608 |
| 649 { | 609 { |
| 650 v8::Unlocker unlocker(args.GetIsolate()); | 610 v8::Unlocker unlocker(args.GetIsolate()); |
| 651 ScopedHostResolve scoped_host_resolve(context); | 611 success = context->js_bindings()->ResolveDns( |
| 652 success = context->js_bindings_->DnsResolve(hostname, &ip_address); | 612 hostname, JSBindings::DNS_RESOLVE, &ip_address); |
| 653 } | 613 } |
| 654 | 614 |
| 655 return success ? ASCIIStringToV8String(ip_address) : v8::Null(); | 615 return success ? ASCIIStringToV8String(ip_address) : v8::Null(); |
| 656 } | 616 } |
| 657 | 617 |
| 658 // V8 callback for when "dnsResolveEx()" is invoked by the PAC script. | 618 // V8 callback for when "dnsResolveEx()" is invoked by the PAC script. |
| 659 static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) { | 619 static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) { |
| 660 Context* context = | 620 Context* context = |
| 661 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 621 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 662 | 622 |
| 663 // We need at least one string argument. | 623 // We need at least one string argument. |
| 664 std::string hostname; | 624 std::string hostname; |
| 665 if (!GetHostnameArgument(args, &hostname)) | 625 if (!GetHostnameArgument(args, &hostname)) |
| 666 return v8::Undefined(); | 626 return v8::Undefined(); |
| 667 | 627 |
| 668 std::string ip_address_list; | 628 std::string ip_address_list; |
| 669 bool success; | 629 bool success; |
| 670 | 630 |
| 671 { | 631 { |
| 672 v8::Unlocker unlocker(args.GetIsolate()); | 632 v8::Unlocker unlocker(args.GetIsolate()); |
|
mmenke
2013/01/29 20:19:08
If we're running v8 on only one thread...This is s
eroman
2013/01/29 22:51:23
Note that we disable v8-proxy resolver in --single
| |
| 673 ScopedHostResolve scoped_host_resolve(context); | 633 success = context->js_bindings()->ResolveDns( |
| 674 success = context->js_bindings_->DnsResolveEx(hostname, &ip_address_list); | 634 hostname, JSBindings::DNS_RESOLVE_EX, &ip_address_list); |
| 675 } | 635 } |
| 676 | 636 |
| 677 if (!success) | 637 if (!success) |
| 678 ip_address_list = std::string(); | 638 ip_address_list = std::string(); |
| 679 | 639 |
| 680 return ASCIIStringToV8String(ip_address_list); | 640 return ASCIIStringToV8String(ip_address_list); |
| 681 } | 641 } |
| 682 | 642 |
| 683 // V8 callback for when "sortIpAddressList()" is invoked by the PAC script. | 643 // V8 callback for when "sortIpAddressList()" is invoked by the PAC script. |
| 684 static v8::Handle<v8::Value> SortIpAddressListCallback( | 644 static v8::Handle<v8::Value> SortIpAddressListCallback( |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 707 std::string ip_address = V8StringToUTF8(args[0]->ToString()); | 667 std::string ip_address = V8StringToUTF8(args[0]->ToString()); |
| 708 if (!IsStringASCII(ip_address)) | 668 if (!IsStringASCII(ip_address)) |
| 709 return v8::False(); | 669 return v8::False(); |
| 710 std::string ip_prefix = V8StringToUTF8(args[1]->ToString()); | 670 std::string ip_prefix = V8StringToUTF8(args[1]->ToString()); |
| 711 if (!IsStringASCII(ip_prefix)) | 671 if (!IsStringASCII(ip_prefix)) |
| 712 return v8::False(); | 672 return v8::False(); |
| 713 return IsInNetEx(ip_address, ip_prefix) ? v8::True() : v8::False(); | 673 return IsInNetEx(ip_address, ip_prefix) ? v8::True() : v8::False(); |
| 714 } | 674 } |
| 715 | 675 |
| 716 mutable base::Lock lock_; | 676 mutable base::Lock lock_; |
| 717 bool is_resolving_host_; | 677 ProxyResolverV8* parent_; |
| 718 ProxyResolverJSBindings* js_bindings_; | |
| 719 v8::Persistent<v8::External> v8_this_; | 678 v8::Persistent<v8::External> v8_this_; |
| 720 v8::Persistent<v8::Context> v8_context_; | 679 v8::Persistent<v8::Context> v8_context_; |
| 721 }; | 680 }; |
| 722 | 681 |
| 723 // ProxyResolverV8 ------------------------------------------------------------ | 682 // ProxyResolverV8 ------------------------------------------------------------ |
| 724 | 683 |
| 725 ProxyResolverV8::ProxyResolverV8( | 684 ProxyResolverV8::ProxyResolverV8() |
| 726 ProxyResolverJSBindings* custom_js_bindings) | |
| 727 : ProxyResolver(true /*expects_pac_bytes*/), | 685 : ProxyResolver(true /*expects_pac_bytes*/), |
| 728 js_bindings_(custom_js_bindings) { | 686 js_bindings_(NULL) { |
| 729 } | 687 } |
| 730 | 688 |
| 731 ProxyResolverV8::~ProxyResolverV8() {} | 689 ProxyResolverV8::~ProxyResolverV8() {} |
| 732 | 690 |
| 733 int ProxyResolverV8::GetProxyForURL( | 691 int ProxyResolverV8::GetProxyForURL( |
| 734 const GURL& query_url, ProxyInfo* results, | 692 const GURL& query_url, ProxyInfo* results, |
| 735 const CompletionCallback& /*callback*/, | 693 const CompletionCallback& /*callback*/, |
| 736 RequestHandle* /*request*/, | 694 RequestHandle* /*request*/, |
| 737 const BoundNetLog& net_log) { | 695 const BoundNetLog& net_log) { |
| 696 DCHECK(js_bindings_); | |
| 697 | |
| 738 // If the V8 instance has not been initialized (either because | 698 // If the V8 instance has not been initialized (either because |
| 739 // SetPacScript() wasn't called yet, or because it failed. | 699 // SetPacScript() wasn't called yet, or because it failed. |
| 740 if (!context_.get()) | 700 if (!context_.get()) |
| 741 return ERR_FAILED; | 701 return ERR_FAILED; |
| 742 | 702 |
| 743 // Associate some short-lived context with this request. This context will be | |
| 744 // available to any of the javascript "bindings" that are subsequently invoked | |
| 745 // from the javascript. | |
| 746 // | |
| 747 // In particular, we create a HostCache to aggressively cache failed DNS | |
| 748 // resolves. | |
| 749 const unsigned kMaxCacheEntries = 50; | |
| 750 HostCache host_cache(kMaxCacheEntries); | |
| 751 | |
| 752 ProxyResolverRequestContext request_context(&net_log, &host_cache); | |
| 753 | |
| 754 // Otherwise call into V8. | 703 // Otherwise call into V8. |
| 755 context_->SetCurrentRequestContext(&request_context); | |
| 756 int rv = context_->ResolveProxy(query_url, results); | 704 int rv = context_->ResolveProxy(query_url, results); |
| 757 context_->SetCurrentRequestContext(NULL); | |
| 758 | 705 |
| 759 return rv; | 706 return rv; |
| 760 } | 707 } |
| 761 | 708 |
| 762 void ProxyResolverV8::CancelRequest(RequestHandle request) { | 709 void ProxyResolverV8::CancelRequest(RequestHandle request) { |
| 763 // This is a synchronous ProxyResolver; no possibility for async requests. | 710 // This is a synchronous ProxyResolver; no possibility for async requests. |
| 764 NOTREACHED(); | 711 NOTREACHED(); |
| 765 } | 712 } |
| 766 | 713 |
| 767 LoadState ProxyResolverV8::GetLoadState(RequestHandle request) const { | 714 LoadState ProxyResolverV8::GetLoadState(RequestHandle request) const { |
| 768 NOTREACHED(); | 715 NOTREACHED(); |
| 769 return LOAD_STATE_IDLE; | 716 return LOAD_STATE_IDLE; |
| 770 } | 717 } |
| 771 | 718 |
| 772 LoadState ProxyResolverV8::GetLoadStateThreadSafe(RequestHandle request) const { | |
| 773 if (context_->is_resolving_host()) | |
| 774 return LOAD_STATE_RESOLVING_HOST_IN_PROXY_SCRIPT; | |
| 775 return LOAD_STATE_RESOLVING_PROXY_FOR_URL; | |
| 776 } | |
| 777 | |
| 778 void ProxyResolverV8::CancelSetPacScript() { | 719 void ProxyResolverV8::CancelSetPacScript() { |
| 779 NOTREACHED(); | 720 NOTREACHED(); |
| 780 } | 721 } |
| 781 | 722 |
| 782 void ProxyResolverV8::PurgeMemory() { | 723 void ProxyResolverV8::PurgeMemory() { |
| 783 context_->PurgeMemory(); | 724 context_->PurgeMemory(); |
| 784 } | 725 } |
| 785 | 726 |
| 786 void ProxyResolverV8::Shutdown() { | |
| 787 js_bindings_->Shutdown(); | |
| 788 } | |
| 789 | |
| 790 int ProxyResolverV8::SetPacScript( | 727 int ProxyResolverV8::SetPacScript( |
| 791 const scoped_refptr<ProxyResolverScriptData>& script_data, | 728 const scoped_refptr<ProxyResolverScriptData>& script_data, |
| 792 const CompletionCallback& /*callback*/) { | 729 const CompletionCallback& /*callback*/) { |
| 793 DCHECK(script_data.get()); | 730 DCHECK(script_data.get()); |
| 731 DCHECK(js_bindings_); | |
| 732 | |
| 794 context_.reset(); | 733 context_.reset(); |
| 795 if (script_data->utf16().empty()) | 734 if (script_data->utf16().empty()) |
| 796 return ERR_PAC_SCRIPT_FAILED; | 735 return ERR_PAC_SCRIPT_FAILED; |
| 797 | 736 |
| 798 // Try parsing the PAC script. | 737 // Try parsing the PAC script. |
| 799 scoped_ptr<Context> context(new Context(js_bindings_.get())); | 738 scoped_ptr<Context> context(new Context(this)); |
| 800 int rv = context->InitV8(script_data); | 739 int rv = context->InitV8(script_data); |
| 801 if (rv == OK) | 740 if (rv == OK) |
| 802 context_.reset(context.release()); | 741 context_.reset(context.release()); |
| 803 return rv; | 742 return rv; |
| 804 } | 743 } |
| 805 | 744 |
| 806 } // namespace net | 745 } // namespace net |
| OLD | NEW |