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