| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/lacros/net/lacros_extension_proxy_tracker.h" |
| |
| #include "chrome/browser/extensions/settings_api_helpers.h" |
| #include "chrome/browser/lacros/net/network_settings_translation.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chromeos/crosapi/mojom/network_settings_service.mojom.h" |
| #include "chromeos/lacros/lacros_service.h" |
| #include "components/proxy_config/pref_proxy_config_tracker_impl.h" |
| #include "components/proxy_config/proxy_config_pref_names.h" |
| #include "components/proxy_config/proxy_prefs.h" |
| #include "extensions/browser/extension_system.h" |
| #include "extensions/browser/management_policy.h" |
| #include "extensions/common/extension.h" |
| #include "net/proxy_resolution/proxy_config_with_annotation.h" |
| |
| namespace lacros { |
| namespace { |
| crosapi::mojom::NetworkSettingsService* GetNetworkSettingsApi() { |
| auto* lacros_service = chromeos::LacrosService::Get(); |
| return lacros_service->GetRemote<crosapi::mojom::NetworkSettingsService>() |
| .get(); |
| } |
| } // namespace |
| namespace net { |
| |
| LacrosExtensionProxyTracker::LacrosExtensionProxyTracker(Profile* profile) |
| : profile_(profile) { |
| DCHECK(profile_->IsMainProfile()); |
| proxy_prefs_registrar_.Init(profile_->GetPrefs()); |
| proxy_prefs_registrar_.Add( |
| proxy_config::prefs::kProxy, |
| base::BindRepeating(&LacrosExtensionProxyTracker::OnProxyPrefChanged, |
| base::Unretained(this))); |
| OnProxyPrefChanged(proxy_config::prefs::kProxy); |
| extension_observation_.Observe(extensions::ExtensionRegistry::Get(profile)); |
| } |
| |
| LacrosExtensionProxyTracker::~LacrosExtensionProxyTracker() = default; |
| |
| void LacrosExtensionProxyTracker::OnProxyPrefChanged( |
| const std::string& pref_name) { |
| DCHECK(profile_->IsMainProfile()); |
| DCHECK(pref_name == proxy_config::prefs::kProxy); |
| ::net::ProxyConfigWithAnnotation config; |
| ProxyPrefs::ConfigState config_state = |
| PrefProxyConfigTrackerImpl::ReadPrefConfig(profile_->GetPrefs(), &config); |
| |
| if (config_state != ProxyPrefs::ConfigState::CONFIG_EXTENSION) { |
| if (extension_proxy_active_) { |
| extension_proxy_active_ = false; |
| if (AshVersionSupportsExtensionMetadata()) { |
| GetNetworkSettingsApi()->ClearExtensionControllingProxyMetadata(); |
| } else { |
| // TODO(acostinas,b/267719988) Remove this deprecated call in 118. |
| GetNetworkSettingsApi()->ClearExtensionProxy(); |
| } |
| } |
| return; |
| } |
| extension_proxy_active_ = true; |
| const extensions::Extension* extension = |
| extensions::GetExtensionOverridingProxy(profile_); |
| |
| // The the extension-set proxy pref update is received before the extension is |
| // enabled. This happens when the extension store where the pref is stored is |
| // loaded before the extension, in one of the following cases: |
| // - A new Chrome session is started, where the extension has set the proxy |
| // pref in a previous session; |
| // - Ash to Lacros migration; |
| // - Disabling and then enabling an extension which is controlling the proxy. |
| // It's safe to ignore the update here because this case is handled by |
| // listening to the ExtensionRegistry events and re-sending the proxy config |
| // to Ash when the extension which is controlling the proxy is loaded. |
| if (!extension) { |
| return; |
| } |
| |
| auto extension_info = crosapi::mojom::ExtensionControllingProxy::New(); |
| extension_info->name = extension->name(); |
| extension_info->id = extension->id(); |
| extension_info->can_be_disabled = |
| !extensions::ExtensionSystem::Get(profile_) |
| ->management_policy() |
| ->MustRemainEnabled(extension, nullptr); |
| |
| if (AshVersionSupportsExtensionMetadata()) { |
| GetNetworkSettingsApi()->SetExtensionControllingProxyMetadata( |
| std::move(extension_info)); |
| return; |
| } |
| auto proxy_config = chromeos::NetProxyToCrosapiProxy(config); |
| proxy_config->extension = std::move(extension_info); |
| // TODO(acostinas, b/267719988) Remove this deprecated call in 118. |
| GetNetworkSettingsApi()->SetExtensionProxy(std::move(proxy_config)); |
| } |
| |
| void LacrosExtensionProxyTracker::OnExtensionReady( |
| content::BrowserContext* browser_context, |
| const extensions::Extension* extension) { |
| if (!extension_proxy_active_) { |
| return; |
| } |
| if (profile_ != Profile::FromBrowserContext(browser_context)) { |
| return; |
| } |
| if (extensions::GetExtensionOverridingProxy(profile_) != extension) { |
| return; |
| } |
| |
| OnProxyPrefChanged(proxy_config::prefs::kProxy); |
| } |
| |
| // static |
| bool LacrosExtensionProxyTracker::AshVersionSupportsExtensionMetadata() { |
| chromeos::LacrosService* service = chromeos::LacrosService::Get(); |
| if (!service->IsAvailable<crosapi::mojom::NetworkSettingsService>()) { |
| LOG(ERROR) << "Ash NetworkSettingsService not available"; |
| return false; |
| } |
| |
| int network_settings_version = |
| service->GetInterfaceVersion<crosapi::mojom::NetworkSettingsService>(); |
| if (network_settings_version < |
| int{crosapi::mojom::NetworkSettingsService::MethodMinVersions:: |
| kSetExtensionControllingProxyMetadataMinVersion}) { |
| LOG(WARNING) << "Ash NetworkSettingsService version " |
| << network_settings_version |
| << " does not support extension set proxies."; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| } // namespace net |
| } // namespace lacros |