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 "chrome/browser/profiles/profile_impl_io_data.h" | 5 #include "chrome/browser/profiles/profile_impl_io_data.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/metrics/field_trial.h" | 10 #include "base/metrics/field_trial.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "chrome/browser/net/quota_policy_channel_id_store.h" | 30 #include "chrome/browser/net/quota_policy_channel_id_store.h" |
31 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_configurator.
h" | 31 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_configurator.
h" |
32 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" | 32 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" |
33 #include "chrome/browser/profiles/profile.h" | 33 #include "chrome/browser/profiles/profile.h" |
34 #include "chrome/common/chrome_constants.h" | 34 #include "chrome/common/chrome_constants.h" |
35 #include "chrome/common/chrome_switches.h" | 35 #include "chrome/common/chrome_switches.h" |
36 #include "chrome/common/pref_names.h" | 36 #include "chrome/common/pref_names.h" |
37 #include "chrome/common/url_constants.h" | 37 #include "chrome/common/url_constants.h" |
38 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth
_request_handler.h" | 38 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth
_request_handler.h" |
39 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_inte
rceptor.h" | 39 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_inte
rceptor.h" |
| 40 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_netw
ork_delegate.h" |
40 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prot
ocol.h" | 41 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prot
ocol.h" |
41 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_stat
istics_prefs.h" | 42 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_stat
istics_prefs.h" |
42 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usag
e_stats.h" | 43 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usag
e_stats.h" |
43 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_param
s.h" | 44 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_param
s.h" |
44 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_
names.h" | 45 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_
names.h" |
45 #include "components/domain_reliability/monitor.h" | 46 #include "components/domain_reliability/monitor.h" |
46 #include "content/public/browser/browser_thread.h" | 47 #include "content/public/browser/browser_thread.h" |
47 #include "content/public/browser/cookie_store_factory.h" | 48 #include "content/public/browser/cookie_store_factory.h" |
48 #include "content/public/browser/notification_service.h" | 49 #include "content/public/browser/notification_service.h" |
49 #include "content/public/browser/resource_context.h" | 50 #include "content/public/browser/resource_context.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 save_prefs = !chromeos::ProfileHelper::IsSigninProfile(profile_); | 111 save_prefs = !chromeos::ProfileHelper::IsSigninProfile(profile_); |
111 #endif | 112 #endif |
112 if (save_prefs) | 113 if (save_prefs) |
113 io_data_->predictor_->SaveStateForNextStartupAndTrim(); | 114 io_data_->predictor_->SaveStateForNextStartupAndTrim(); |
114 io_data_->predictor_->ShutdownOnUIThread(); | 115 io_data_->predictor_->ShutdownOnUIThread(); |
115 } | 116 } |
116 | 117 |
117 if (io_data_->http_server_properties_manager_) | 118 if (io_data_->http_server_properties_manager_) |
118 io_data_->http_server_properties_manager_->ShutdownOnPrefThread(); | 119 io_data_->http_server_properties_manager_->ShutdownOnPrefThread(); |
119 | 120 |
120 io_data_->data_reduction_proxy_enabled()->Destroy(); | 121 io_data_->data_reduction_proxy_enabled_.Destroy(); |
121 io_data_->ShutdownOnUIThread(GetAllContextGetters().Pass()); | 122 io_data_->ShutdownOnUIThread(GetAllContextGetters().Pass()); |
122 } | 123 } |
123 | 124 |
124 void ProfileImplIOData::Handle::Init( | 125 void ProfileImplIOData::Handle::Init( |
125 const base::FilePath& cookie_path, | 126 const base::FilePath& cookie_path, |
126 const base::FilePath& channel_id_path, | 127 const base::FilePath& channel_id_path, |
127 const base::FilePath& cache_path, | 128 const base::FilePath& cache_path, |
128 int cache_max_size, | 129 int cache_max_size, |
129 const base::FilePath& media_cache_path, | 130 const base::FilePath& media_cache_path, |
130 int media_cache_max_size, | 131 int media_cache_max_size, |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 io_data_->session_startup_pref()->Init( | 359 io_data_->session_startup_pref()->Init( |
359 prefs::kRestoreOnStartup, pref_service); | 360 prefs::kRestoreOnStartup, pref_service); |
360 io_data_->session_startup_pref()->MoveToThread( | 361 io_data_->session_startup_pref()->MoveToThread( |
361 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); | 362 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); |
362 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING) | 363 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING) |
363 io_data_->safe_browsing_enabled()->Init(prefs::kSafeBrowsingEnabled, | 364 io_data_->safe_browsing_enabled()->Init(prefs::kSafeBrowsingEnabled, |
364 pref_service); | 365 pref_service); |
365 io_data_->safe_browsing_enabled()->MoveToThread( | 366 io_data_->safe_browsing_enabled()->MoveToThread( |
366 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); | 367 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); |
367 #endif | 368 #endif |
368 io_data_->data_reduction_proxy_enabled()->Init( | 369 io_data_->data_reduction_proxy_enabled_.Init( |
369 data_reduction_proxy::prefs::kDataReductionProxyEnabled, pref_service); | 370 data_reduction_proxy::prefs::kDataReductionProxyEnabled, pref_service); |
370 io_data_->data_reduction_proxy_enabled()->MoveToThread( | 371 io_data_->data_reduction_proxy_enabled_.MoveToThread( |
371 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); | 372 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); |
372 io_data_->InitializeOnUIThread(profile_); | 373 io_data_->InitializeOnUIThread(profile_); |
373 } | 374 } |
374 | 375 |
375 scoped_ptr<ProfileIOData::ChromeURLRequestContextGetterVector> | 376 scoped_ptr<ProfileIOData::ChromeURLRequestContextGetterVector> |
376 ProfileImplIOData::Handle::GetAllContextGetters() { | 377 ProfileImplIOData::Handle::GetAllContextGetters() { |
377 ChromeURLRequestContextGetterMap::iterator iter; | 378 ChromeURLRequestContextGetterMap::iterator iter; |
378 scoped_ptr<ChromeURLRequestContextGetterVector> context_getters( | 379 scoped_ptr<ChromeURLRequestContextGetterVector> context_getters( |
379 new ChromeURLRequestContextGetterVector()); | 380 new ChromeURLRequestContextGetterVector()); |
380 | 381 |
(...skipping 26 matching lines...) Expand all Loading... |
407 ProfileImplIOData::LazyParams::~LazyParams() {} | 408 ProfileImplIOData::LazyParams::~LazyParams() {} |
408 | 409 |
409 ProfileImplIOData::ProfileImplIOData() | 410 ProfileImplIOData::ProfileImplIOData() |
410 : ProfileIOData(Profile::REGULAR_PROFILE), | 411 : ProfileIOData(Profile::REGULAR_PROFILE), |
411 http_server_properties_manager_(NULL), | 412 http_server_properties_manager_(NULL), |
412 app_cache_max_size_(0), | 413 app_cache_max_size_(0), |
413 app_media_cache_max_size_(0) { | 414 app_media_cache_max_size_(0) { |
414 } | 415 } |
415 | 416 |
416 ProfileImplIOData::~ProfileImplIOData() { | 417 ProfileImplIOData::~ProfileImplIOData() { |
417 if (initialized()) | |
418 network_delegate()->set_domain_reliability_monitor(NULL); | |
419 | |
420 DestroyResourceContext(); | 418 DestroyResourceContext(); |
421 | 419 |
422 if (media_request_context_) | 420 if (media_request_context_) |
423 media_request_context_->AssertNoURLRequests(); | 421 media_request_context_->AssertNoURLRequests(); |
424 } | 422 } |
425 | 423 |
426 void ProfileImplIOData::InitializeInternal( | 424 void ProfileImplIOData::InitializeInternal( |
| 425 scoped_ptr<ChromeNetworkDelegate> chrome_network_delegate, |
427 ProfileParams* profile_params, | 426 ProfileParams* profile_params, |
428 content::ProtocolHandlerMap* protocol_handlers, | 427 content::ProtocolHandlerMap* protocol_handlers, |
429 content::URLRequestInterceptorScopedVector request_interceptors) const { | 428 content::URLRequestInterceptorScopedVector request_interceptors) const { |
430 net::URLRequestContext* main_context = main_request_context(); | 429 net::URLRequestContext* main_context = main_request_context(); |
431 | 430 |
432 IOThread* const io_thread = profile_params->io_thread; | 431 IOThread* const io_thread = profile_params->io_thread; |
433 IOThread::Globals* const io_thread_globals = io_thread->globals(); | 432 IOThread::Globals* const io_thread_globals = io_thread->globals(); |
434 | 433 |
| 434 chrome_network_delegate->set_predictor(predictor_.get()); |
| 435 |
| 436 if (domain_reliability_monitor_) { |
| 437 domain_reliability::DomainReliabilityMonitor* monitor = |
| 438 domain_reliability_monitor_.get(); |
| 439 monitor->InitURLRequestContext(main_context); |
| 440 monitor->AddBakedInConfigs(); |
| 441 monitor->SetDiscardUploads(!GetMetricsEnabledStateOnIOThread()); |
| 442 chrome_network_delegate->set_domain_reliability_monitor(monitor); |
| 443 } |
| 444 |
435 set_data_reduction_proxy_auth_request_handler( | 445 set_data_reduction_proxy_auth_request_handler( |
436 scoped_ptr<data_reduction_proxy::DataReductionProxyAuthRequestHandler> | 446 scoped_ptr<data_reduction_proxy::DataReductionProxyAuthRequestHandler> |
437 (new data_reduction_proxy::DataReductionProxyAuthRequestHandler( | 447 (new data_reduction_proxy::DataReductionProxyAuthRequestHandler( |
438 DataReductionProxyChromeSettings::GetClient(), | 448 DataReductionProxyChromeSettings::GetClient(), |
439 data_reduction_proxy_params(), | 449 data_reduction_proxy_params(), |
440 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)))); | 450 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)))); |
441 set_data_reduction_proxy_usage_stats( | 451 set_data_reduction_proxy_usage_stats( |
442 scoped_ptr<data_reduction_proxy::DataReductionProxyUsageStats> | 452 scoped_ptr<data_reduction_proxy::DataReductionProxyUsageStats> |
443 (new data_reduction_proxy::DataReductionProxyUsageStats( | 453 (new data_reduction_proxy::DataReductionProxyUsageStats( |
444 data_reduction_proxy_params(), | 454 data_reduction_proxy_params(), |
445 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI) | 455 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI) |
446 .get()))); | 456 .get()))); |
447 data_reduction_proxy_usage_stats()->set_unavailable_callback( | 457 data_reduction_proxy_usage_stats()->set_unavailable_callback( |
448 data_reduction_proxy_unavailable_callback()); | 458 data_reduction_proxy_unavailable_callback()); |
449 | 459 |
450 network_delegate()->set_data_reduction_proxy_enabled_pref( | 460 scoped_ptr<data_reduction_proxy::DataReductionProxyNetworkDelegate> |
451 &data_reduction_proxy_enabled_); | 461 data_reduction_proxy_network_delegate( |
452 network_delegate()->set_data_reduction_proxy_params( | 462 new data_reduction_proxy::DataReductionProxyNetworkDelegate( |
453 data_reduction_proxy_params()); | 463 chrome_network_delegate.Pass(), |
454 network_delegate()->set_data_reduction_proxy_usage_stats( | 464 data_reduction_proxy_params(), |
| 465 data_reduction_proxy_auth_request_handler(), |
| 466 base::Bind( |
| 467 &DataReductionProxyChromeConfigurator::GetProxyConfigOnIOThread, |
| 468 base::Unretained(data_reduction_proxy_chrome_configurator())))); |
| 469 data_reduction_proxy_network_delegate->InitProxyConfigOverrider( |
| 470 base::Bind(data_reduction_proxy::OnResolveProxyHandler)); |
| 471 data_reduction_proxy_network_delegate->InitStatisticsPrefsAndUMA( |
| 472 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), |
| 473 data_reduction_proxy_statistics_prefs(), |
| 474 &data_reduction_proxy_enabled_, |
455 data_reduction_proxy_usage_stats()); | 475 data_reduction_proxy_usage_stats()); |
456 network_delegate()->set_data_reduction_proxy_auth_request_handler( | 476 network_delegate_ = data_reduction_proxy_network_delegate.Pass(); |
457 data_reduction_proxy_auth_request_handler()); | |
458 network_delegate()->set_data_reduction_proxy_statistics_prefs( | |
459 data_reduction_proxy_statistics_prefs()); | |
460 network_delegate()->set_on_resolve_proxy_handler( | |
461 base::Bind(data_reduction_proxy::OnResolveProxyHandler)); | |
462 network_delegate()->set_proxy_config_getter( | |
463 base::Bind( | |
464 &DataReductionProxyChromeConfigurator::GetProxyConfigOnIOThread, | |
465 base::Unretained(data_reduction_proxy_chrome_configurator()))); | |
466 network_delegate()->set_predictor(predictor_.get()); | |
467 | 477 |
468 // Initialize context members. | 478 // Initialize context members. |
469 | 479 |
470 ApplyProfileParamsToContext(main_context); | 480 ApplyProfileParamsToContext(main_context); |
471 | 481 |
472 if (http_server_properties_manager_) | 482 if (http_server_properties_manager_) |
473 http_server_properties_manager_->InitializeOnNetworkThread(); | 483 http_server_properties_manager_->InitializeOnNetworkThread(); |
474 | 484 |
475 main_context->set_transport_security_state(transport_security_state()); | 485 main_context->set_transport_security_state(transport_security_state()); |
476 | 486 |
477 main_context->set_net_log(io_thread->net_log()); | 487 main_context->set_net_log(io_thread->net_log()); |
478 | 488 |
479 main_context->set_network_delegate(network_delegate()); | 489 main_context->set_network_delegate(network_delegate_.get()); |
480 | 490 |
481 main_context->set_http_server_properties(http_server_properties()); | 491 main_context->set_http_server_properties(http_server_properties()); |
482 | 492 |
483 main_context->set_host_resolver( | 493 main_context->set_host_resolver( |
484 io_thread_globals->host_resolver.get()); | 494 io_thread_globals->host_resolver.get()); |
485 main_context->set_cert_transparency_verifier( | 495 main_context->set_cert_transparency_verifier( |
486 io_thread_globals->cert_transparency_verifier.get()); | 496 io_thread_globals->cert_transparency_verifier.get()); |
487 main_context->set_http_auth_handler_factory( | 497 main_context->set_http_auth_handler_factory( |
488 io_thread_globals->http_auth_handler_factory.get()); | 498 io_thread_globals->http_auth_handler_factory.get()); |
489 | 499 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 request_interceptors.insert( | 589 request_interceptors.insert( |
580 request_interceptors.begin(), | 590 request_interceptors.begin(), |
581 new data_reduction_proxy::DataReductionProxyInterceptor( | 591 new data_reduction_proxy::DataReductionProxyInterceptor( |
582 data_reduction_proxy_params(), | 592 data_reduction_proxy_params(), |
583 data_reduction_proxy_usage_stats(), | 593 data_reduction_proxy_usage_stats(), |
584 data_reduction_proxy_event_store())); | 594 data_reduction_proxy_event_store())); |
585 main_job_factory_ = SetUpJobFactoryDefaults( | 595 main_job_factory_ = SetUpJobFactoryDefaults( |
586 main_job_factory.Pass(), | 596 main_job_factory.Pass(), |
587 request_interceptors.Pass(), | 597 request_interceptors.Pass(), |
588 profile_params->protocol_handler_interceptor.Pass(), | 598 profile_params->protocol_handler_interceptor.Pass(), |
589 network_delegate(), | 599 main_context->network_delegate(), |
590 ftp_factory_.get()); | 600 ftp_factory_.get()); |
591 main_context->set_job_factory(main_job_factory_.get()); | 601 main_context->set_job_factory(main_job_factory_.get()); |
592 | 602 |
593 #if defined(ENABLE_EXTENSIONS) | 603 #if defined(ENABLE_EXTENSIONS) |
594 InitializeExtensionsRequestContext(profile_params); | 604 InitializeExtensionsRequestContext(profile_params); |
595 #endif | 605 #endif |
596 | 606 |
597 // Setup SDCH for this profile. | 607 // Setup SDCH for this profile. |
598 sdch_manager_.reset(new net::SdchManager); | 608 sdch_manager_.reset(new net::SdchManager); |
599 sdch_policy_.reset(new ChromeSdchPolicy(sdch_manager_.get(), main_context)); | 609 sdch_policy_.reset(new ChromeSdchPolicy(sdch_manager_.get(), main_context)); |
600 main_context->set_sdch_manager(sdch_manager_.get()); | 610 main_context->set_sdch_manager(sdch_manager_.get()); |
601 | 611 |
602 // Create a media request context based on the main context, but using a | 612 // Create a media request context based on the main context, but using a |
603 // media cache. It shares the same job factory as the main context. | 613 // media cache. It shares the same job factory as the main context. |
604 StoragePartitionDescriptor details(profile_path_, false); | 614 StoragePartitionDescriptor details(profile_path_, false); |
605 media_request_context_.reset(InitializeMediaRequestContext(main_context, | 615 media_request_context_.reset(InitializeMediaRequestContext(main_context, |
606 details)); | 616 details)); |
607 | 617 |
608 if (domain_reliability_monitor_) { | |
609 domain_reliability::DomainReliabilityMonitor* monitor = | |
610 domain_reliability_monitor_.get(); | |
611 monitor->InitURLRequestContext(main_context); | |
612 monitor->AddBakedInConfigs(); | |
613 monitor->SetDiscardUploads(!GetMetricsEnabledStateOnIOThread()); | |
614 network_delegate()->set_domain_reliability_monitor(monitor); | |
615 } | |
616 | |
617 lazy_params_.reset(); | 618 lazy_params_.reset(); |
618 } | 619 } |
619 | 620 |
620 void ProfileImplIOData:: | 621 void ProfileImplIOData:: |
621 InitializeExtensionsRequestContext(ProfileParams* profile_params) const { | 622 InitializeExtensionsRequestContext(ProfileParams* profile_params) const { |
622 net::URLRequestContext* extensions_context = extensions_request_context(); | 623 net::URLRequestContext* extensions_context = extensions_request_context(); |
623 IOThread* const io_thread = profile_params->io_thread; | 624 IOThread* const io_thread = profile_params->io_thread; |
624 IOThread::Globals* const io_thread_globals = io_thread->globals(); | 625 IOThread::Globals* const io_thread_globals = io_thread->globals(); |
625 ApplyProfileParamsToContext(extensions_context); | 626 ApplyProfileParamsToContext(extensions_context); |
626 | 627 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 request_interceptors.insert( | 741 request_interceptors.insert( |
741 request_interceptors.begin(), | 742 request_interceptors.begin(), |
742 new data_reduction_proxy::DataReductionProxyInterceptor( | 743 new data_reduction_proxy::DataReductionProxyInterceptor( |
743 data_reduction_proxy_params(), | 744 data_reduction_proxy_params(), |
744 data_reduction_proxy_usage_stats(), | 745 data_reduction_proxy_usage_stats(), |
745 data_reduction_proxy_event_store())); | 746 data_reduction_proxy_event_store())); |
746 scoped_ptr<net::URLRequestJobFactory> top_job_factory( | 747 scoped_ptr<net::URLRequestJobFactory> top_job_factory( |
747 SetUpJobFactoryDefaults(job_factory.Pass(), | 748 SetUpJobFactoryDefaults(job_factory.Pass(), |
748 request_interceptors.Pass(), | 749 request_interceptors.Pass(), |
749 protocol_handler_interceptor.Pass(), | 750 protocol_handler_interceptor.Pass(), |
750 network_delegate(), | 751 main_context->network_delegate(), |
751 ftp_factory_.get())); | 752 ftp_factory_.get())); |
752 context->SetJobFactory(top_job_factory.Pass()); | 753 context->SetJobFactory(top_job_factory.Pass()); |
753 | 754 |
754 return context; | 755 return context; |
755 } | 756 } |
756 | 757 |
757 net::URLRequestContext* | 758 net::URLRequestContext* |
758 ProfileImplIOData::InitializeMediaRequestContext( | 759 ProfileImplIOData::InitializeMediaRequestContext( |
759 net::URLRequestContext* original_context, | 760 net::URLRequestContext* original_context, |
760 const StoragePartitionDescriptor& partition_descriptor) const { | 761 const StoragePartitionDescriptor& partition_descriptor) const { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 transport_security_state()->DeleteAllDynamicDataSince(time); | 852 transport_security_state()->DeleteAllDynamicDataSince(time); |
852 DCHECK(http_server_properties_manager_); | 853 DCHECK(http_server_properties_manager_); |
853 http_server_properties_manager_->Clear(completion); | 854 http_server_properties_manager_->Clear(completion); |
854 } | 855 } |
855 | 856 |
856 bool ProfileImplIOData::IsDataReductionProxyEnabled() const { | 857 bool ProfileImplIOData::IsDataReductionProxyEnabled() const { |
857 return data_reduction_proxy_enabled_.GetValue() || | 858 return data_reduction_proxy_enabled_.GetValue() || |
858 CommandLine::ForCurrentProcess()->HasSwitch( | 859 CommandLine::ForCurrentProcess()->HasSwitch( |
859 data_reduction_proxy::switches::kEnableDataReductionProxy); | 860 data_reduction_proxy::switches::kEnableDataReductionProxy); |
860 } | 861 } |
OLD | NEW |