| 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/debug/leak_annotations.h" | 12 #include "base/debug/leak_annotations.h" |
| 13 #include "base/lazy_instance.h" |
| 13 #include "base/logging.h" | 14 #include "base/logging.h" |
| 14 #include "base/strings/string_tokenizer.h" | 15 #include "base/strings/string_tokenizer.h" |
| 15 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
| 17 #include "base/synchronization/lock.h" | 18 #include "base/synchronization/lock.h" |
| 18 #include "gin/array_buffer.h" | 19 #include "gin/array_buffer.h" |
| 19 #include "gin/public/isolate_holder.h" | 20 #include "gin/public/isolate_holder.h" |
| 20 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
| 21 #include "net/base/net_log.h" | 22 #include "net/base/net_log.h" |
| 22 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 bool IsPlainHostName(const std::string& hostname_utf8) { | 339 bool IsPlainHostName(const std::string& hostname_utf8) { |
| 339 if (hostname_utf8.find('.') != std::string::npos) | 340 if (hostname_utf8.find('.') != std::string::npos) |
| 340 return false; | 341 return false; |
| 341 | 342 |
| 342 // IPv6 literals might not contain any periods, however are not considered | 343 // IPv6 literals might not contain any periods, however are not considered |
| 343 // plain host names. | 344 // plain host names. |
| 344 IPAddressNumber unused; | 345 IPAddressNumber unused; |
| 345 return !ParseIPLiteralToNumber(hostname_utf8, &unused); | 346 return !ParseIPLiteralToNumber(hostname_utf8, &unused); |
| 346 } | 347 } |
| 347 | 348 |
| 349 // All instances of ProxyResolverV8 share the same v8::Isolate. This isolate is |
| 350 // created lazily the first time it is needed and lives until process shutdown. |
| 351 // This creation might happen from any thread, as ProxyResolverV8 is typically |
| 352 // run in a threadpool. |
| 353 // |
| 354 // TODO(eroman): The lazily created isolate is never freed. Instead it should be |
| 355 // disposed once there are no longer any ProxyResolverV8 referencing it. |
| 356 class SharedIsolateFactory { |
| 357 public: |
| 358 SharedIsolateFactory() : has_initialized_v8_(false) {} |
| 359 |
| 360 // Lazily creates a v8::Isolate, or returns the already created instance. |
| 361 v8::Isolate* GetSharedIsolate() { |
| 362 base::AutoLock l(lock_); |
| 363 |
| 364 if (!holder_) { |
| 365 // Do one-time initialization for V8. |
| 366 if (!has_initialized_v8_) { |
| 367 #ifdef V8_USE_EXTERNAL_STARTUP_DATA |
| 368 gin::IsolateHolder::LoadV8Snapshot(); |
| 369 #endif |
| 370 |
| 371 gin::IsolateHolder::Initialize( |
| 372 gin::IsolateHolder::kNonStrictMode, |
| 373 gin::ArrayBufferAllocator::SharedInstance()); |
| 374 |
| 375 has_initialized_v8_ = true; |
| 376 } |
| 377 |
| 378 holder_.reset(new gin::IsolateHolder); |
| 379 } |
| 380 |
| 381 return holder_->isolate(); |
| 382 } |
| 383 |
| 384 v8::Isolate* GetSharedIsolateWithoutCreating() { |
| 385 base::AutoLock l(lock_); |
| 386 return holder_ ? holder_->isolate() : NULL; |
| 387 } |
| 388 |
| 389 private: |
| 390 base::Lock lock_; |
| 391 scoped_ptr<gin::IsolateHolder> holder_; |
| 392 bool has_initialized_v8_; |
| 393 |
| 394 DISALLOW_COPY_AND_ASSIGN(SharedIsolateFactory); |
| 395 }; |
| 396 |
| 397 base::LazyInstance<SharedIsolateFactory>::Leaky g_isolate_factory = |
| 398 LAZY_INSTANCE_INITIALIZER; |
| 399 |
| 348 } // namespace | 400 } // namespace |
| 349 | 401 |
| 350 // ProxyResolverV8::Context --------------------------------------------------- | 402 // ProxyResolverV8::Context --------------------------------------------------- |
| 351 | 403 |
| 352 class ProxyResolverV8::Context { | 404 class ProxyResolverV8::Context { |
| 353 public: | 405 public: |
| 354 Context(ProxyResolverV8* parent, v8::Isolate* isolate) | 406 Context(ProxyResolverV8* parent, v8::Isolate* isolate) |
| 355 : parent_(parent), | 407 : parent_(parent), |
| 356 isolate_(isolate) { | 408 isolate_(isolate) { |
| 357 DCHECK(isolate); | 409 DCHECK(isolate); |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 const scoped_refptr<ProxyResolverScriptData>& script_data, | 834 const scoped_refptr<ProxyResolverScriptData>& script_data, |
| 783 const CompletionCallback& /*callback*/) { | 835 const CompletionCallback& /*callback*/) { |
| 784 DCHECK(script_data.get()); | 836 DCHECK(script_data.get()); |
| 785 DCHECK(js_bindings_); | 837 DCHECK(js_bindings_); |
| 786 | 838 |
| 787 context_.reset(); | 839 context_.reset(); |
| 788 if (script_data->utf16().empty()) | 840 if (script_data->utf16().empty()) |
| 789 return ERR_PAC_SCRIPT_FAILED; | 841 return ERR_PAC_SCRIPT_FAILED; |
| 790 | 842 |
| 791 // Try parsing the PAC script. | 843 // Try parsing the PAC script. |
| 792 scoped_ptr<Context> context(new Context(this, GetDefaultIsolate())); | 844 scoped_ptr<Context> context( |
| 845 new Context(this, g_isolate_factory.Get().GetSharedIsolate())); |
| 793 int rv = context->InitV8(script_data); | 846 int rv = context->InitV8(script_data); |
| 794 if (rv == OK) | 847 if (rv == OK) |
| 795 context_.reset(context.release()); | 848 context_.reset(context.release()); |
| 796 return rv; | 849 return rv; |
| 797 } | 850 } |
| 798 | 851 |
| 799 // static | 852 // static |
| 800 void ProxyResolverV8::EnsureIsolateCreated() { | |
| 801 if (g_proxy_resolver_isolate_) | |
| 802 return; | |
| 803 gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, | |
| 804 gin::ArrayBufferAllocator::SharedInstance()); | |
| 805 g_proxy_resolver_isolate_ = new gin::IsolateHolder; | |
| 806 ANNOTATE_LEAKING_OBJECT_PTR(g_proxy_resolver_isolate_); | |
| 807 } | |
| 808 | |
| 809 // static | |
| 810 v8::Isolate* ProxyResolverV8::GetDefaultIsolate() { | |
| 811 DCHECK(g_proxy_resolver_isolate_) | |
| 812 << "Must call ProxyResolverV8::EnsureIsolateCreated() first"; | |
| 813 return g_proxy_resolver_isolate_->isolate(); | |
| 814 } | |
| 815 | |
| 816 gin::IsolateHolder* ProxyResolverV8::g_proxy_resolver_isolate_ = NULL; | |
| 817 | |
| 818 // static | |
| 819 size_t ProxyResolverV8::GetTotalHeapSize() { | 853 size_t ProxyResolverV8::GetTotalHeapSize() { |
| 820 if (!g_proxy_resolver_isolate_) | 854 v8::Isolate* isolate = |
| 855 g_isolate_factory.Get().GetSharedIsolateWithoutCreating(); |
| 856 if (!isolate) |
| 821 return 0; | 857 return 0; |
| 822 | 858 |
| 823 v8::Locker locked(g_proxy_resolver_isolate_->isolate()); | 859 v8::Locker locked(isolate); |
| 824 v8::Isolate::Scope isolate_scope(g_proxy_resolver_isolate_->isolate()); | 860 v8::Isolate::Scope isolate_scope(isolate); |
| 825 v8::HeapStatistics heap_statistics; | 861 v8::HeapStatistics heap_statistics; |
| 826 g_proxy_resolver_isolate_->isolate()->GetHeapStatistics(&heap_statistics); | 862 isolate->GetHeapStatistics(&heap_statistics); |
| 827 return heap_statistics.total_heap_size(); | 863 return heap_statistics.total_heap_size(); |
| 828 } | 864 } |
| 829 | 865 |
| 830 // static | 866 // static |
| 831 size_t ProxyResolverV8::GetUsedHeapSize() { | 867 size_t ProxyResolverV8::GetUsedHeapSize() { |
| 832 if (!g_proxy_resolver_isolate_) | 868 v8::Isolate* isolate = |
| 869 g_isolate_factory.Get().GetSharedIsolateWithoutCreating(); |
| 870 if (!isolate) |
| 833 return 0; | 871 return 0; |
| 834 | 872 |
| 835 v8::Locker locked(g_proxy_resolver_isolate_->isolate()); | 873 v8::Locker locked(isolate); |
| 836 v8::Isolate::Scope isolate_scope(g_proxy_resolver_isolate_->isolate()); | 874 v8::Isolate::Scope isolate_scope(isolate); |
| 837 v8::HeapStatistics heap_statistics; | 875 v8::HeapStatistics heap_statistics; |
| 838 g_proxy_resolver_isolate_->isolate()->GetHeapStatistics(&heap_statistics); | 876 isolate->GetHeapStatistics(&heap_statistics); |
| 839 return heap_statistics.used_heap_size(); | 877 return heap_statistics.used_heap_size(); |
| 840 } | 878 } |
| 841 | 879 |
| 842 } // namespace net | 880 } // namespace net |
| OLD | NEW |