diff --git a/src/components/cronet/android/cronet_library_loader.cc b/src/components/cronet/android/cronet_library_loader.cc index cec35b8af6..f6716e8f44 100644 --- a/src/components/cronet/android/cronet_library_loader.cc +++ b/src/components/cronet/android/cronet_library_loader.cc @@ -146,7 +146,8 @@ void PostTaskToInitThread(const base::Location& posted_from, g_init_task_executor->task_runner()->PostTask(posted_from, std::move(task)); } -void EnsureInitialized() { +void EnsureInitialized(const char* /*enable_features*/, + const char* /*disable_features*/) { if (g_init_task_executor) { // Ensure that init is done on the init thread. g_init_thread_init_done.Wait(); diff --git a/src/components/cronet/cronet_global_state.h b/src/components/cronet/cronet_global_state.h index 10003b0be1..a8f8b2b79c 100644 --- a/src/components/cronet/cronet_global_state.h +++ b/src/components/cronet/cronet_global_state.h @@ -31,7 +31,8 @@ void PostTaskToInitThread(const base::Location& posted_from, // or binding to an existing thread, to run initialization and process // network notifications on. The implementation must be thread-safe and // idempotent, and must complete initialization before returning. -void EnsureInitialized(); +void EnsureInitialized(const char* enable_features = nullptr, + const char* disable_features = nullptr); // Creates a proxy config service appropriate for this platform that fetches the // system proxy settings. Cronet will call this API only after a prior call diff --git a/src/components/cronet/cronet_global_state_stubs.cc b/src/components/cronet/cronet_global_state_stubs.cc index ff55b51348..0aab153bb2 100644 --- a/src/components/cronet/cronet_global_state_stubs.cc +++ b/src/components/cronet/cronet_global_state_stubs.cc @@ -21,14 +21,18 @@ namespace cronet { namespace { -scoped_refptr InitializeAndCreateTaskRunner() { +scoped_refptr InitializeAndCreateTaskRunner( + const char* enable_features, + const char* disable_features) { // Cronet tests sets AtExitManager as part of TestSuite, so statically linked // library is not allowed to set its own. #if !defined(CRONET_TESTS_IMPLEMENTATION) std::ignore = new base::AtExitManager; #endif - base::FeatureList::InitializeInstance(std::string(), std::string()); + base::FeatureList::InitializeInstance( + enable_features ? enable_features : "", + disable_features ? disable_features : ""); // Note that in component builds this ThreadPoolInstance will be shared with // the calling process, if it also depends on //base. In particular this means @@ -39,16 +43,19 @@ scoped_refptr InitializeAndCreateTaskRunner() { return base::ThreadPool::CreateSingleThreadTaskRunner({}); } -base::SingleThreadTaskRunner* InitTaskRunner() { +base::SingleThreadTaskRunner* InitTaskRunner( + const char* enable_features = nullptr, + const char* disable_features = nullptr) { static scoped_refptr init_task_runner = - InitializeAndCreateTaskRunner(); + InitializeAndCreateTaskRunner(enable_features, disable_features); return init_task_runner.get(); } } // namespace -void EnsureInitialized() { - std::ignore = InitTaskRunner(); +void EnsureInitialized(const char* enable_features, + const char* disable_features) { + std::ignore = InitTaskRunner(enable_features, disable_features); } bool OnInitThread() { diff --git a/src/components/cronet/native/engine.cc b/src/components/cronet/native/engine.cc index 8c110870a0..2d7a7911c9 100644 --- a/src/components/cronet/native/engine.cc +++ b/src/components/cronet/native/engine.cc @@ -7,6 +7,7 @@ #include #include +#include "base/base_switches.h" #include "base/bind.h" #include "base/callback_helpers.h" #include "base/files/file_path.h" @@ -102,6 +103,25 @@ Cronet_EngineImpl::~Cronet_EngineImpl() { Cronet_RESULT Cronet_EngineImpl::StartWithParams( Cronet_EngineParamsPtr params) { + absl::optional experimental_options = + URLRequestContextConfig::ParseExperimentalOptions( + params->experimental_options); + if (experimental_options) { + const auto& iter = experimental_options->find("feature_list"); + if (iter != experimental_options->end()) { + const base::Value& feature_list = iter->second; + if (feature_list.is_dict()) { + const std::string* enable_features = + feature_list.GetDict().FindString(switches::kEnableFeatures); + const std::string* disable_features = + feature_list.GetDict().FindString(switches::kDisableFeatures); + cronet::EnsureInitialized( + enable_features ? enable_features->c_str() : nullptr, + disable_features ? disable_features->c_str() : nullptr); + } + } + } + cronet::EnsureInitialized(); base::AutoLock lock(lock_); diff --git a/src/components/cronet/url_request_context_config.cc b/src/components/cronet/url_request_context_config.cc index f19226f5de..2b735ef9aa 100644 --- a/src/components/cronet/url_request_context_config.cc +++ b/src/components/cronet/url_request_context_config.cc @@ -761,6 +761,15 @@ void URLRequestContextConfig::SetContextBuilderExperimentalOptions( continue; } // Handled in CronetContext::NetworkTasks::BuildDefaultURLRequestContext. + } else if (iter.first == "feature_list") { + if (!iter.second.is_dict()) { + LOG(ERROR) << "\"" << iter.first << "\" config params \"" << iter.second + << "\" is not a dictionary value"; + effective_experimental_options.erase(iter.first); + continue; + } + // Already handled in Cronet_EngineImpl::StartWithParams. + // Only checks and reports errors here. } else { LOG(WARNING) << "Unrecognized Cronet experimental option \"" << iter.first << "\" with params \"" << iter.second; diff --git a/src/components/cronet/url_request_context_config.h b/src/components/cronet/url_request_context_config.h index 6537dcd491..8bf6064dd2 100644 --- a/src/components/cronet/url_request_context_config.h +++ b/src/components/cronet/url_request_context_config.h @@ -216,6 +216,12 @@ struct URLRequestContextConfig { // not specify for other targets. absl::optional network_thread_priority); + // Parses experimental options from their JSON format to the format used + // internally. + // Returns an empty optional if the operation was unsuccessful. + static absl::optional ParseExperimentalOptions( + std::string unparsed_experimental_options); + private: URLRequestContextConfig( // Enable QUIC. @@ -253,12 +259,6 @@ struct URLRequestContextConfig { // not specify for other targets. absl::optional network_thread_priority); - // Parses experimental options from their JSON format to the format used - // internally. - // Returns an empty optional if the operation was unsuccessful. - static absl::optional ParseExperimentalOptions( - std::string unparsed_experimental_options); - // Makes appropriate changes to settings in |this|. void SetContextConfigExperimentalOptions();