| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <algorithm> | 5 #include <algorithm> |
| 6 #include <cstdio> | 6 #include <cstdio> |
| 7 | 7 |
| 8 #include "net/proxy/proxy_resolver_v8.h" | 8 #include "net/proxy/proxy_resolver_v8.h" |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/string_tokenizer.h" | 13 #include "base/string_tokenizer.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/synchronization/lock.h" |
| 15 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 16 #include "googleurl/src/gurl.h" | 17 #include "googleurl/src/gurl.h" |
| 17 #include "googleurl/src/url_canon.h" | 18 #include "googleurl/src/url_canon.h" |
| 18 #include "net/base/host_cache.h" | 19 #include "net/base/host_cache.h" |
| 19 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
| 20 #include "net/base/net_log.h" | 21 #include "net/base/net_log.h" |
| 21 #include "net/base/net_util.h" | 22 #include "net/base/net_util.h" |
| 22 #include "net/proxy/proxy_info.h" | 23 #include "net/proxy/proxy_info.h" |
| 23 #include "net/proxy/proxy_resolver_js_bindings.h" | 24 #include "net/proxy/proxy_resolver_js_bindings.h" |
| 24 #include "net/proxy/proxy_resolver_request_context.h" | 25 #include "net/proxy/proxy_resolver_request_context.h" |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits); | 329 return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits); |
| 329 } | 330 } |
| 330 | 331 |
| 331 } // namespace | 332 } // namespace |
| 332 | 333 |
| 333 // ProxyResolverV8::Context --------------------------------------------------- | 334 // ProxyResolverV8::Context --------------------------------------------------- |
| 334 | 335 |
| 335 class ProxyResolverV8::Context { | 336 class ProxyResolverV8::Context { |
| 336 public: | 337 public: |
| 337 explicit Context(ProxyResolverJSBindings* js_bindings) | 338 explicit Context(ProxyResolverJSBindings* js_bindings) |
| 338 : js_bindings_(js_bindings) { | 339 : is_resolving_host_(false), |
| 340 js_bindings_(js_bindings) { |
| 339 DCHECK(js_bindings != NULL); | 341 DCHECK(js_bindings != NULL); |
| 340 } | 342 } |
| 341 | 343 |
| 342 ~Context() { | 344 ~Context() { |
| 343 v8::Locker locked; | 345 v8::Locker locked; |
| 344 | 346 |
| 345 v8_this_.Dispose(); | 347 v8_this_.Dispose(); |
| 346 v8_context_.Dispose(); | 348 v8_context_.Dispose(); |
| 347 | 349 |
| 348 // Run the V8 garbage collector. We do this to be sure the | 350 // Run the V8 garbage collector. We do this to be sure the |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 void PurgeMemory() { | 490 void PurgeMemory() { |
| 489 v8::Locker locked; | 491 v8::Locker locked; |
| 490 // Repeatedly call the V8 idle notification until it returns true ("nothing | 492 // Repeatedly call the V8 idle notification until it returns true ("nothing |
| 491 // more to free"). Note that it makes more sense to do this than to | 493 // more to free"). Note that it makes more sense to do this than to |
| 492 // implement a new "delete everything" pass because object references make | 494 // implement a new "delete everything" pass because object references make |
| 493 // it difficult to free everything possible in just one pass. | 495 // it difficult to free everything possible in just one pass. |
| 494 while (!v8::V8::IdleNotification()) | 496 while (!v8::V8::IdleNotification()) |
| 495 ; | 497 ; |
| 496 } | 498 } |
| 497 | 499 |
| 500 bool is_resolving_host() const { |
| 501 base::AutoLock auto_lock(lock_); |
| 502 return is_resolving_host_; |
| 503 } |
| 504 |
| 498 private: | 505 private: |
| 506 class ScopedHostResolve { |
| 507 public: |
| 508 explicit ScopedHostResolve(Context* context) |
| 509 : context_(context) { |
| 510 context_->BeginHostResolve(); |
| 511 } |
| 512 |
| 513 ~ScopedHostResolve() { |
| 514 context_->EndHostResolve(); |
| 515 } |
| 516 |
| 517 private: |
| 518 Context* const context_; |
| 519 DISALLOW_COPY_AND_ASSIGN(ScopedHostResolve); |
| 520 }; |
| 521 |
| 522 void BeginHostResolve() { |
| 523 base::AutoLock auto_lock(lock_); |
| 524 DCHECK(!is_resolving_host_); |
| 525 is_resolving_host_ = true; |
| 526 } |
| 527 |
| 528 void EndHostResolve() { |
| 529 base::AutoLock auto_lock(lock_); |
| 530 DCHECK(is_resolving_host_); |
| 531 is_resolving_host_ = false; |
| 532 } |
| 533 |
| 499 bool GetFindProxyForURL(v8::Local<v8::Value>* function) { | 534 bool GetFindProxyForURL(v8::Local<v8::Value>* function) { |
| 500 *function = v8_context_->Global()->Get( | 535 *function = v8_context_->Global()->Get( |
| 501 ASCIILiteralToV8String("FindProxyForURL")); | 536 ASCIILiteralToV8String("FindProxyForURL")); |
| 502 return (*function)->IsFunction(); | 537 return (*function)->IsFunction(); |
| 503 } | 538 } |
| 504 | 539 |
| 505 // Handle an exception thrown by V8. | 540 // Handle an exception thrown by V8. |
| 506 void HandleError(v8::Handle<v8::Message> message) { | 541 void HandleError(v8::Handle<v8::Message> message) { |
| 507 if (message.IsEmpty()) | 542 if (message.IsEmpty()) |
| 508 return; | 543 return; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 // V8 callback for when "myIpAddress()" is invoked by the PAC script. | 594 // V8 callback for when "myIpAddress()" is invoked by the PAC script. |
| 560 static v8::Handle<v8::Value> MyIpAddressCallback(const v8::Arguments& args) { | 595 static v8::Handle<v8::Value> MyIpAddressCallback(const v8::Arguments& args) { |
| 561 Context* context = | 596 Context* context = |
| 562 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 597 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 563 | 598 |
| 564 std::string result; | 599 std::string result; |
| 565 bool success; | 600 bool success; |
| 566 | 601 |
| 567 { | 602 { |
| 568 v8::Unlocker unlocker; | 603 v8::Unlocker unlocker; |
| 604 ScopedHostResolve scoped_host_resolve(context); |
| 569 | 605 |
| 570 // We shouldn't be called with any arguments, but will not complain if | 606 // We shouldn't be called with any arguments, but will not complain if |
| 571 // we are. | 607 // we are. |
| 572 success = context->js_bindings_->MyIpAddress(&result); | 608 success = context->js_bindings_->MyIpAddress(&result); |
| 573 } | 609 } |
| 574 | 610 |
| 575 if (!success) | 611 if (!success) |
| 576 return ASCIILiteralToV8String("127.0.0.1"); | 612 return ASCIILiteralToV8String("127.0.0.1"); |
| 577 return ASCIIStringToV8String(result); | 613 return ASCIIStringToV8String(result); |
| 578 } | 614 } |
| 579 | 615 |
| 580 // V8 callback for when "myIpAddressEx()" is invoked by the PAC script. | 616 // V8 callback for when "myIpAddressEx()" is invoked by the PAC script. |
| 581 static v8::Handle<v8::Value> MyIpAddressExCallback( | 617 static v8::Handle<v8::Value> MyIpAddressExCallback( |
| 582 const v8::Arguments& args) { | 618 const v8::Arguments& args) { |
| 583 Context* context = | 619 Context* context = |
| 584 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 620 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 585 | 621 |
| 586 std::string ip_address_list; | 622 std::string ip_address_list; |
| 587 bool success; | 623 bool success; |
| 588 | 624 |
| 589 { | 625 { |
| 590 v8::Unlocker unlocker; | 626 v8::Unlocker unlocker; |
| 627 ScopedHostResolve scoped_host_resolve(context); |
| 591 | 628 |
| 592 // We shouldn't be called with any arguments, but will not complain if | 629 // We shouldn't be called with any arguments, but will not complain if |
| 593 // we are. | 630 // we are. |
| 594 success = context->js_bindings_->MyIpAddressEx(&ip_address_list); | 631 success = context->js_bindings_->MyIpAddressEx(&ip_address_list); |
| 595 } | 632 } |
| 596 | 633 |
| 597 if (!success) | 634 if (!success) |
| 598 ip_address_list = std::string(); | 635 ip_address_list = std::string(); |
| 599 return ASCIIStringToV8String(ip_address_list); | 636 return ASCIIStringToV8String(ip_address_list); |
| 600 } | 637 } |
| 601 | 638 |
| 602 // V8 callback for when "dnsResolve()" is invoked by the PAC script. | 639 // V8 callback for when "dnsResolve()" is invoked by the PAC script. |
| 603 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { | 640 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { |
| 604 Context* context = | 641 Context* context = |
| 605 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 642 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 606 | 643 |
| 607 // We need at least one string argument. | 644 // We need at least one string argument. |
| 608 std::string hostname; | 645 std::string hostname; |
| 609 if (!GetHostnameArgument(args, &hostname)) | 646 if (!GetHostnameArgument(args, &hostname)) |
| 610 return v8::Null(); | 647 return v8::Null(); |
| 611 | 648 |
| 612 std::string ip_address; | 649 std::string ip_address; |
| 613 bool success; | 650 bool success; |
| 614 | 651 |
| 615 { | 652 { |
| 616 v8::Unlocker unlocker; | 653 v8::Unlocker unlocker; |
| 654 ScopedHostResolve scoped_host_resolve(context); |
| 617 success = context->js_bindings_->DnsResolve(hostname, &ip_address); | 655 success = context->js_bindings_->DnsResolve(hostname, &ip_address); |
| 618 } | 656 } |
| 619 | 657 |
| 620 return success ? ASCIIStringToV8String(ip_address) : v8::Null(); | 658 return success ? ASCIIStringToV8String(ip_address) : v8::Null(); |
| 621 } | 659 } |
| 622 | 660 |
| 623 // V8 callback for when "dnsResolveEx()" is invoked by the PAC script. | 661 // V8 callback for when "dnsResolveEx()" is invoked by the PAC script. |
| 624 static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) { | 662 static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) { |
| 625 Context* context = | 663 Context* context = |
| 626 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); | 664 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); |
| 627 | 665 |
| 628 // We need at least one string argument. | 666 // We need at least one string argument. |
| 629 std::string hostname; | 667 std::string hostname; |
| 630 if (!GetHostnameArgument(args, &hostname)) | 668 if (!GetHostnameArgument(args, &hostname)) |
| 631 return v8::Undefined(); | 669 return v8::Undefined(); |
| 632 | 670 |
| 633 std::string ip_address_list; | 671 std::string ip_address_list; |
| 634 bool success; | 672 bool success; |
| 635 | 673 |
| 636 { | 674 { |
| 637 v8::Unlocker unlocker; | 675 v8::Unlocker unlocker; |
| 676 ScopedHostResolve scoped_host_resolve(context); |
| 638 success = context->js_bindings_->DnsResolveEx(hostname, &ip_address_list); | 677 success = context->js_bindings_->DnsResolveEx(hostname, &ip_address_list); |
| 639 } | 678 } |
| 640 | 679 |
| 641 if (!success) | 680 if (!success) |
| 642 ip_address_list = std::string(); | 681 ip_address_list = std::string(); |
| 643 | 682 |
| 644 return ASCIIStringToV8String(ip_address_list); | 683 return ASCIIStringToV8String(ip_address_list); |
| 645 } | 684 } |
| 646 | 685 |
| 647 // V8 callback for when "sortIpAddressList()" is invoked by the PAC script. | 686 // V8 callback for when "sortIpAddressList()" is invoked by the PAC script. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 670 | 709 |
| 671 std::string ip_address = V8StringToUTF8(args[0]->ToString()); | 710 std::string ip_address = V8StringToUTF8(args[0]->ToString()); |
| 672 if (!IsStringASCII(ip_address)) | 711 if (!IsStringASCII(ip_address)) |
| 673 return v8::False(); | 712 return v8::False(); |
| 674 std::string ip_prefix = V8StringToUTF8(args[1]->ToString()); | 713 std::string ip_prefix = V8StringToUTF8(args[1]->ToString()); |
| 675 if (!IsStringASCII(ip_prefix)) | 714 if (!IsStringASCII(ip_prefix)) |
| 676 return v8::False(); | 715 return v8::False(); |
| 677 return IsInNetEx(ip_address, ip_prefix) ? v8::True() : v8::False(); | 716 return IsInNetEx(ip_address, ip_prefix) ? v8::True() : v8::False(); |
| 678 } | 717 } |
| 679 | 718 |
| 719 mutable base::Lock lock_; |
| 720 bool is_resolving_host_; |
| 680 ProxyResolverJSBindings* js_bindings_; | 721 ProxyResolverJSBindings* js_bindings_; |
| 681 v8::Persistent<v8::External> v8_this_; | 722 v8::Persistent<v8::External> v8_this_; |
| 682 v8::Persistent<v8::Context> v8_context_; | 723 v8::Persistent<v8::Context> v8_context_; |
| 683 }; | 724 }; |
| 684 | 725 |
| 685 // ProxyResolverV8 ------------------------------------------------------------ | 726 // ProxyResolverV8 ------------------------------------------------------------ |
| 686 | 727 |
| 687 ProxyResolverV8::ProxyResolverV8( | 728 ProxyResolverV8::ProxyResolverV8( |
| 688 ProxyResolverJSBindings* custom_js_bindings) | 729 ProxyResolverJSBindings* custom_js_bindings) |
| 689 : ProxyResolver(true /*expects_pac_bytes*/), | 730 : ProxyResolver(true /*expects_pac_bytes*/), |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 721 context_->SetCurrentRequestContext(NULL); | 762 context_->SetCurrentRequestContext(NULL); |
| 722 | 763 |
| 723 return rv; | 764 return rv; |
| 724 } | 765 } |
| 725 | 766 |
| 726 void ProxyResolverV8::CancelRequest(RequestHandle request) { | 767 void ProxyResolverV8::CancelRequest(RequestHandle request) { |
| 727 // This is a synchronous ProxyResolver; no possibility for async requests. | 768 // This is a synchronous ProxyResolver; no possibility for async requests. |
| 728 NOTREACHED(); | 769 NOTREACHED(); |
| 729 } | 770 } |
| 730 | 771 |
| 772 LoadState ProxyResolverV8::GetLoadState(RequestHandle request) const { |
| 773 NOTREACHED(); |
| 774 return LOAD_STATE_IDLE; |
| 775 } |
| 776 |
| 777 LoadState ProxyResolverV8::GetLoadStateThreadSafe(RequestHandle request) const { |
| 778 if (context_->is_resolving_host()) |
| 779 return LOAD_STATE_RESOLVING_HOST_IN_PROXY_SCRIPT; |
| 780 return LOAD_STATE_RESOLVING_PROXY_FOR_URL; |
| 781 } |
| 782 |
| 731 void ProxyResolverV8::CancelSetPacScript() { | 783 void ProxyResolverV8::CancelSetPacScript() { |
| 732 NOTREACHED(); | 784 NOTREACHED(); |
| 733 } | 785 } |
| 734 | 786 |
| 735 void ProxyResolverV8::PurgeMemory() { | 787 void ProxyResolverV8::PurgeMemory() { |
| 736 context_->PurgeMemory(); | 788 context_->PurgeMemory(); |
| 737 } | 789 } |
| 738 | 790 |
| 739 void ProxyResolverV8::Shutdown() { | 791 void ProxyResolverV8::Shutdown() { |
| 740 js_bindings_->Shutdown(); | 792 js_bindings_->Shutdown(); |
| 741 } | 793 } |
| 742 | 794 |
| 743 int ProxyResolverV8::SetPacScript( | 795 int ProxyResolverV8::SetPacScript( |
| 744 const scoped_refptr<ProxyResolverScriptData>& script_data, | 796 const scoped_refptr<ProxyResolverScriptData>& script_data, |
| 745 OldCompletionCallback* /*callback*/) { | 797 OldCompletionCallback* /*callback*/) { |
| 746 DCHECK(script_data.get()); | 798 DCHECK(script_data.get()); |
| 747 context_.reset(); | 799 context_.reset(); |
| 748 if (script_data->utf16().empty()) | 800 if (script_data->utf16().empty()) |
| 749 return ERR_PAC_SCRIPT_FAILED; | 801 return ERR_PAC_SCRIPT_FAILED; |
| 750 | 802 |
| 751 // Try parsing the PAC script. | 803 // Try parsing the PAC script. |
| 752 scoped_ptr<Context> context(new Context(js_bindings_.get())); | 804 scoped_ptr<Context> context(new Context(js_bindings_.get())); |
| 753 int rv = context->InitV8(script_data); | 805 int rv = context->InitV8(script_data); |
| 754 if (rv == OK) | 806 if (rv == OK) |
| 755 context_.reset(context.release()); | 807 context_.reset(context.release()); |
| 756 return rv; | 808 return rv; |
| 757 } | 809 } |
| 758 | 810 |
| 759 } // namespace net | 811 } // namespace net |
| OLD | NEW |