1 // Copyright (c) 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/policy/system_proxy_manager.h"
6
7 #include "base/bind.h"
8 #include "base/strings/string16.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
13 #include "chrome/browser/chromeos/profiles/profile_helper.h"
14 #include "chrome/browser/chromeos/ui/request_system_proxy_credentials_view.h"
15 #include "chrome/browser/chromeos/ui/system_proxy_notification.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_finder.h"
19 #include "chrome/browser/ui/browser_window.h"
20 #include "chrome/common/pref_names.h"
21 #include "chromeos/dbus/system_proxy/system_proxy_client.h"
22 #include "chromeos/network/network_event_log.h"
23 #include "chromeos/network/network_state.h"
24 #include "chromeos/network/network_state_handler.h"
25 #include "chromeos/network/proxy/proxy_config_service_impl.h"
26 #include "chromeos/network/proxy/ui_proxy_config_service.h"
27 #include "chromeos/settings/cros_settings_names.h"
28 #include "chromeos/settings/cros_settings_provider.h"
29 #include "components/arc/arc_prefs.h"
30 #include "components/prefs/pref_change_registrar.h"
31 #include "components/prefs/pref_registry_simple.h"
32 #include "components/prefs/pref_service.h"
33 #include "components/proxy_config/proxy_config_pref_names.h"
34 #include "components/user_manager/user.h"
35 #include "components/user_manager/user_manager.h"
36 #include "content/public/browser/storage_partition.h"
37 #include "net/base/host_port_pair.h"
38 #include "net/base/proxy_server.h"
39 #include "net/http/http_auth_scheme.h"
40 #include "net/http/http_util.h"
41 #include "services/network/public/mojom/network_context.mojom.h"
42 #include "ui/aura/window.h"
43 #include "ui/gfx/native_widget_types.h"
44 #include "ui/views/widget/widget.h"
45 #include "ui/views/window/dialog_delegate.h"
46
47 namespace {
48 const char kSystemProxyService[] = "system-proxy-service";
49 } // namespace
50
51 namespace policy {
52
SystemProxyManager(chromeos::CrosSettings * cros_settings,PrefService * local_state)53 SystemProxyManager::SystemProxyManager(chromeos::CrosSettings* cros_settings,
54 PrefService* local_state)
55 : cros_settings_(cros_settings),
56 system_proxy_subscription_(cros_settings_->AddSettingsObserver(
57 chromeos::kSystemProxySettings,
58 base::BindRepeating(
59 &SystemProxyManager::OnSystemProxySettingsPolicyChanged,
60 base::Unretained(this)))) {
61 // Connect to System-proxy signals.
62 chromeos::SystemProxyClient::Get()->SetWorkerActiveSignalCallback(
63 base::BindRepeating(&SystemProxyManager::OnWorkerActive,
64 weak_factory_.GetWeakPtr()));
65 chromeos::SystemProxyClient::Get()->SetAuthenticationRequiredSignalCallback(
66 base::BindRepeating(&SystemProxyManager::OnAuthenticationRequired,
67 weak_factory_.GetWeakPtr()));
68 chromeos::SystemProxyClient::Get()->ConnectToWorkerSignals();
69 local_state_ = local_state;
70
71 // Listen to pref changes.
72 local_state_pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
73 local_state_pref_change_registrar_->Init(local_state_);
74 local_state_pref_change_registrar_->Add(
75 prefs::kKerberosEnabled,
76 base::BindRepeating(&SystemProxyManager::OnKerberosEnabledChanged,
77 weak_factory_.GetWeakPtr()));
78 DCHECK(chromeos::NetworkHandler::IsInitialized());
79 chromeos::NetworkHandler::Get()->network_state_handler()->AddObserver(
80 this, FROM_HERE);
81 // Fire it once so we're sure we get an invocation on startup.
82 OnSystemProxySettingsPolicyChanged();
83 }
84
~SystemProxyManager()85 SystemProxyManager::~SystemProxyManager() {
86 DCHECK(chromeos::NetworkHandler::IsInitialized());
87 chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
88 this, FROM_HERE);
89 }
90
SystemServicesProxyPacString() const91 std::string SystemProxyManager::SystemServicesProxyPacString() const {
92 return system_proxy_enabled_ && !system_services_address_.empty()
93 ? "PROXY " + system_services_address_
94 : std::string();
95 }
96
StartObservingPrimaryProfilePrefs(Profile * profile)97 void SystemProxyManager::StartObservingPrimaryProfilePrefs(Profile* profile) {
98 primary_profile_ = profile;
99 extension_prefs_util_ = std::make_unique<extensions::PrefsUtil>(profile);
100 // Listen to pref changes.
101 profile_pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
102 profile_pref_change_registrar_->Init(primary_profile_->GetPrefs());
103 profile_pref_change_registrar_->Add(
104 prefs::kKerberosActivePrincipalName,
105 base::BindRepeating(&SystemProxyManager::OnKerberosAccountChanged,
106 base::Unretained(this)));
107 profile_pref_change_registrar_->Add(
108 arc::prefs::kArcEnabled,
109 base::BindRepeating(&SystemProxyManager::OnArcEnabledChanged,
110 weak_factory_.GetWeakPtr()));
111 profile_pref_change_registrar_->Add(
112 proxy_config::prefs::kProxy,
113 base::BindRepeating(&SystemProxyManager::OnProxyConfigChanged,
114 base::Unretained(this)));
115 if (system_proxy_enabled_) {
116 OnProxyConfigChanged();
117 OnKerberosAccountChanged();
118 OnArcEnabledChanged();
119 }
120 }
121
StopObservingPrimaryProfilePrefs()122 void SystemProxyManager::StopObservingPrimaryProfilePrefs() {
123 profile_pref_change_registrar_->RemoveAll();
124 profile_pref_change_registrar_.reset();
125 extension_prefs_util_.reset();
126 primary_profile_ = nullptr;
127 }
128
ClearUserCredentials()129 void SystemProxyManager::ClearUserCredentials() {
130 if (!system_proxy_enabled_) {
131 return;
132 }
133
134 system_proxy::ClearUserCredentialsRequest request;
135 chromeos::SystemProxyClient::Get()->ClearUserCredentials(
136 request, base::BindOnce(&SystemProxyManager::OnClearUserCredentials,
137 weak_factory_.GetWeakPtr()));
138 }
139
OnSystemProxySettingsPolicyChanged()140 void SystemProxyManager::OnSystemProxySettingsPolicyChanged() {
141 chromeos::CrosSettingsProvider::TrustedStatus status =
142 cros_settings_->PrepareTrustedValues(base::BindOnce(
143 &SystemProxyManager::OnSystemProxySettingsPolicyChanged,
144 base::Unretained(this)));
145 if (status != chromeos::CrosSettingsProvider::TRUSTED)
146 return;
147
148 const base::Value* proxy_settings =
149 cros_settings_->GetPref(chromeos::kSystemProxySettings);
150
151 if (!proxy_settings)
152 return;
153
154 system_proxy_enabled_ =
155 proxy_settings->FindBoolKey(chromeos::kSystemProxySettingsKeyEnabled)
156 .value_or(false);
157 // System-proxy is inactive by default.
158 if (!system_proxy_enabled_) {
159 // Send a shut-down command to the daemon. Since System-proxy is started via
160 // dbus activation, if the daemon is inactive, this command will start the
161 // daemon and tell it to exit.
162 // TODO(crbug.com/1055245,acostinas): Do not send shut-down command if
163 // System-proxy is inactive.
164 system_proxy::ShutDownRequest request;
165 request.set_traffic_type(system_proxy::TrafficOrigin::ALL);
166 chromeos::SystemProxyClient::Get()->ShutDownProcess(
167 request, base::BindOnce(&SystemProxyManager::OnShutDownProcess,
168 weak_factory_.GetWeakPtr()));
169 system_services_address_.clear();
170 SetUserTrafficProxyPref(std::string());
171 CloseAuthenticationUI();
172 return;
173 }
174 const std::string* username = proxy_settings->FindStringKey(
175 chromeos::kSystemProxySettingsKeySystemServicesUsername);
176
177 const std::string* password = proxy_settings->FindStringKey(
178 chromeos::kSystemProxySettingsKeySystemServicesPassword);
179
180 const base::Value* auth_schemes =
181 proxy_settings->FindListKey(chromeos::kSystemProxySettingsKeyAuthSchemes);
182
183 policy_credentials_auth_schemes_.clear();
184 if (auth_schemes) {
185 for (const auto& auth_scheme : auth_schemes->GetList())
186 policy_credentials_auth_schemes_.push_back(auth_scheme.GetString());
187 }
188
189 if (!username || username->empty() || !password || password->empty()) {
190 NET_LOG(DEBUG) << "Proxy credentials for system traffic not set: "
191 << kSystemProxyService;
192 } else {
193 system_services_username_ = *username;
194 system_services_password_ = *password;
195 }
196 if (IsManagedProxyConfigured()) {
197 // Force send the configuration in case the credentials hand't changed, but
198 // `policy_credentials_auth_schemes_` has.
199 SendPolicyAuthenticationCredentials(system_services_username_,
200 system_services_password_,
201 /*force_send=*/true);
202 } else {
203 // To avoid leaking the policy set credentials, don't send them to
204 // System-proxy if there's no managed proxy on the network.
205 // Note: When SystemProxyManager is starting, the credentials are empty and
206 // they were never sent before. We need to force send them, otherwise
207 // `SendPolicyAuthenticationCredentials` will detect that no change to the
208 // credentials occurred and will not trigger a D-Bus request. This means the
209 // worker service for Chrome OS system services will not be started.
210 SendPolicyAuthenticationCredentials(/*username=*/"",
211 /*password=*/"",
212 /*force_send=*/true);
213 }
214
215 // Fire once to cover the case where the SystemProxySetting policy is set
216 // during a user session.
217 if (IsArcEnabled()) {
218 OnArcEnabledChanged();
219 }
220 }
221
OnKerberosEnabledChanged()222 void SystemProxyManager::OnKerberosEnabledChanged() {
223 SendKerberosAuthenticationDetails();
224 }
225
OnKerberosAccountChanged()226 void SystemProxyManager::OnKerberosAccountChanged() {
227 if (!local_state_->GetBoolean(prefs::kKerberosEnabled)) {
228 return;
229 }
230 SendKerberosAuthenticationDetails();
231 }
232
OnArcEnabledChanged()233 void SystemProxyManager::OnArcEnabledChanged() {
234 if (!system_proxy_enabled_) {
235 return;
236 }
237
238 if (!IsArcEnabled()) {
239 system_proxy::ShutDownRequest request;
240 request.set_traffic_type(system_proxy::TrafficOrigin::USER);
241 chromeos::SystemProxyClient::Get()->ShutDownProcess(
242 request, base::BindOnce(&SystemProxyManager::OnShutDownProcess,
243 weak_factory_.GetWeakPtr()));
244 return;
245 }
246
247 if (local_state_->GetBoolean(prefs::kKerberosEnabled)) {
248 SendKerberosAuthenticationDetails();
249 return;
250 }
251
252 system_proxy::SetAuthenticationDetailsRequest request;
253 request.set_traffic_type(system_proxy::TrafficOrigin::USER);
254 chromeos::SystemProxyClient::Get()->SetAuthenticationDetails(
255 request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails,
256 weak_factory_.GetWeakPtr()));
257 }
258
IsArcEnabled() const259 bool SystemProxyManager::IsArcEnabled() const {
260 return primary_profile_ &&
261 primary_profile_->GetPrefs()->GetBoolean(arc::prefs::kArcEnabled);
262 }
263
SendUserAuthenticationCredentials(const system_proxy::ProtectionSpace & protection_space,const std::string & username,const std::string & password)264 void SystemProxyManager::SendUserAuthenticationCredentials(
265 const system_proxy::ProtectionSpace& protection_space,
266 const std::string& username,
267 const std::string& password) {
268 // System-proxy is started via d-bus activation, meaning the first d-bus call
269 // will start the daemon. Check that System-proxy was not disabled by policy
270 // while looking for credentials so we don't accidentally restart it.
271 if (!system_proxy_enabled_) {
272 return;
273 }
274
275 system_proxy::Credentials user_credentials;
276 user_credentials.set_username(username);
277 user_credentials.set_password(password);
278
279 system_proxy::SetAuthenticationDetailsRequest request;
280 request.set_traffic_type(IsArcEnabled()
281 ? system_proxy::TrafficOrigin::ALL
282 : system_proxy::TrafficOrigin::SYSTEM);
283 *request.mutable_credentials() = user_credentials;
284 *request.mutable_protection_space() = protection_space;
285
286 chromeos::SystemProxyClient::Get()->SetAuthenticationDetails(
287 request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails,
288 weak_factory_.GetWeakPtr()));
289 }
290
SendPolicyAuthenticationCredentials(const std::string & username,const std::string & password,bool force_send)291 void SystemProxyManager::SendPolicyAuthenticationCredentials(
292 const std::string& username,
293 const std::string& password,
294 bool force_send) {
295 if (!system_proxy_enabled_)
296 return;
297
298 if (!force_send &&
299 (last_sent_username_ == username && last_sent_password_ == password)) {
300 // Credentials were already sent.
301 return;
302 }
303
304 last_sent_username_ = username;
305 last_sent_password_ = password;
306
307 system_proxy::SetAuthenticationDetailsRequest request;
308 system_proxy::Credentials credentials;
309 credentials.set_username(username);
310 credentials.set_password(password);
311 for (const auto& auth_scheme : policy_credentials_auth_schemes_) {
312 credentials.add_policy_credentials_auth_schemes(auth_scheme);
313 }
314 *request.mutable_credentials() = credentials;
315
316 request.set_traffic_type(system_proxy::TrafficOrigin::SYSTEM);
317
318 chromeos::SystemProxyClient::Get()->SetAuthenticationDetails(
319 request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails,
320 weak_factory_.GetWeakPtr()));
321 }
322
SendKerberosAuthenticationDetails()323 void SystemProxyManager::SendKerberosAuthenticationDetails() {
324 if (!system_proxy_enabled_) {
325 return;
326 }
327
328 system_proxy::SetAuthenticationDetailsRequest request;
329 request.set_traffic_type(IsArcEnabled()
330 ? system_proxy::TrafficOrigin::ALL
331 : system_proxy::TrafficOrigin::SYSTEM);
332 request.set_kerberos_enabled(
333 local_state_->GetBoolean(prefs::kKerberosEnabled));
334 if (primary_profile_) {
335 request.set_active_principal_name(
336 primary_profile_->GetPrefs()
337 ->Get(prefs::kKerberosActivePrincipalName)
338 ->GetString());
339 }
340 chromeos::SystemProxyClient::Get()->SetAuthenticationDetails(
341 request, base::BindOnce(&SystemProxyManager::OnSetAuthenticationDetails,
342 weak_factory_.GetWeakPtr()));
343 }
344
SendEmptyCredentials(const system_proxy::ProtectionSpace & protection_space)345 void SystemProxyManager::SendEmptyCredentials(
346 const system_proxy::ProtectionSpace& protection_space) {
347 SendUserAuthenticationCredentials(protection_space,
348 /*username=*/std::string(),
349 /*password=*/std::string());
350 }
351
SetSystemProxyEnabledForTest(bool enabled)352 void SystemProxyManager::SetSystemProxyEnabledForTest(bool enabled) {
353 system_proxy_enabled_ = enabled;
354 }
355
SetSystemServicesProxyUrlForTest(const std::string & local_proxy_url)356 void SystemProxyManager::SetSystemServicesProxyUrlForTest(
357 const std::string& local_proxy_url) {
358 system_proxy_enabled_ = true;
359 system_services_address_ = local_proxy_url;
360 }
361
SetSendAuthDetailsClosureForTest(base::RepeatingClosure closure)362 void SystemProxyManager::SetSendAuthDetailsClosureForTest(
363 base::RepeatingClosure closure) {
364 send_auth_details_closure_for_test_ = closure;
365 }
366
367 chromeos::RequestSystemProxyCredentialsView*
GetActiveAuthDialogForTest()368 SystemProxyManager::GetActiveAuthDialogForTest() {
369 return active_auth_dialog_;
370 }
371
CloseAuthDialogForTest()372 void SystemProxyManager::CloseAuthDialogForTest() {
373 DCHECK(auth_widget_);
374 auth_widget_->CloseNow();
375 }
376
377 // static
RegisterProfilePrefs(PrefRegistrySimple * registry)378 void SystemProxyManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
379 registry->RegisterStringPref(prefs::kSystemProxyUserTrafficHostAndPort,
380 /*default_value=*/std::string());
381 }
382
OnSetAuthenticationDetails(const system_proxy::SetAuthenticationDetailsResponse & response)383 void SystemProxyManager::OnSetAuthenticationDetails(
384 const system_proxy::SetAuthenticationDetailsResponse& response) {
385 if (response.has_error_message()) {
386 NET_LOG(ERROR)
387 << "Failed to set system traffic credentials for system proxy: "
388 << kSystemProxyService << ", Error: " << response.error_message();
389 }
390 if (send_auth_details_closure_for_test_)
391 send_auth_details_closure_for_test_.Run();
392 }
393
394 // This function is called when the default network changes or when any of its
395 // properties change.
DefaultNetworkChanged(const chromeos::NetworkState * network)396 void SystemProxyManager::DefaultNetworkChanged(
397 const chromeos::NetworkState* network) {
398 if (!network)
399 return;
400 OnProxyConfigChanged();
401 }
402
OnProxyConfigChanged()403 void SystemProxyManager::OnProxyConfigChanged() {
404 if (!IsManagedProxyConfigured()) {
405 SendPolicyAuthenticationCredentials(/*username=*/"", /*password=*/"",
406 /*force_send=*/false);
407 return;
408 }
409 SendPolicyAuthenticationCredentials(system_services_username_,
410 system_services_password_,
411 /*force_send=*/false);
412 }
413
IsManagedProxyConfigured()414 bool SystemProxyManager::IsManagedProxyConfigured() {
415 DCHECK(chromeos::NetworkHandler::IsInitialized());
416 chromeos::NetworkHandler* network_handler = chromeos::NetworkHandler::Get();
417 base::Value proxy_settings(base::Value::Type::DICTIONARY);
418
419 // |ui_proxy_config_service| may be missing in tests. If the device is offline
420 // (no network connected) the |DefaultNetwork| is null.
421 if (chromeos::NetworkHandler::HasUiProxyConfigService() &&
422 network_handler->network_state_handler()->DefaultNetwork()) {
423 // Check if proxy is enforced by user policy, force installed extension or
424 // ONC policies. This will only read managed settings.
425 chromeos::NetworkHandler::GetUiProxyConfigService()
426 ->MergeEnforcedProxyConfig(
427 network_handler->network_state_handler()->DefaultNetwork()->guid(),
428 &proxy_settings);
429 }
430 if (proxy_settings.DictEmpty())
431 return false; // no managed proxy set
432
433 if (IsProxyConfiguredByUserViaExtension())
434 return false;
435
436 // Proxy was configured by the admin
437 return true;
438 }
439
IsProxyConfiguredByUserViaExtension()440 bool SystemProxyManager::IsProxyConfiguredByUserViaExtension() {
441 if (!extension_prefs_util_)
442 return false;
443
444 std::unique_ptr<extensions::api::settings_private::PrefObject> pref =
445 extension_prefs_util_->GetPref(proxy_config::prefs::kProxy);
446 return pref && pref->extension_can_be_disabled &&
447 *pref->extension_can_be_disabled;
448 }
449
OnShutDownProcess(const system_proxy::ShutDownResponse & response)450 void SystemProxyManager::OnShutDownProcess(
451 const system_proxy::ShutDownResponse& response) {
452 if (response.has_error_message() && !response.error_message().empty()) {
453 NET_LOG(ERROR) << "Failed to shutdown system proxy process: "
454 << kSystemProxyService
455 << ", error: " << response.error_message();
456 }
457 }
458
OnClearUserCredentials(const system_proxy::ClearUserCredentialsResponse & response)459 void SystemProxyManager::OnClearUserCredentials(
460 const system_proxy::ClearUserCredentialsResponse& response) {
461 if (response.has_error_message() && !response.error_message().empty()) {
462 NET_LOG(ERROR) << "Failed to clear user credentials: "
463 << kSystemProxyService
464 << ", error: " << response.error_message();
465 }
466 }
467
OnWorkerActive(const system_proxy::WorkerActiveSignalDetails & details)468 void SystemProxyManager::OnWorkerActive(
469 const system_proxy::WorkerActiveSignalDetails& details) {
470 if (details.traffic_origin() == system_proxy::TrafficOrigin::SYSTEM) {
471 system_services_address_ = details.local_proxy_url();
472 return;
473 }
474 SetUserTrafficProxyPref(details.local_proxy_url());
475 }
476
SetUserTrafficProxyPref(const std::string & user_traffic_address)477 void SystemProxyManager::SetUserTrafficProxyPref(
478 const std::string& user_traffic_address) {
479 if (!primary_profile_) {
480 return;
481 }
482 primary_profile_->GetPrefs()->SetString(
483 prefs::kSystemProxyUserTrafficHostAndPort, user_traffic_address);
484 }
485
OnAuthenticationRequired(const system_proxy::AuthenticationRequiredDetails & details)486 void SystemProxyManager::OnAuthenticationRequired(
487 const system_proxy::AuthenticationRequiredDetails& details) {
488 system_proxy::ProtectionSpace protection_space =
489 details.proxy_protection_space();
490
491 if (!primary_profile_) {
492 SendEmptyCredentials(protection_space);
493 return;
494 }
495
496 // The previous authentication attempt failed.
497 if (details.has_bad_cached_credentials() &&
498 details.bad_cached_credentials()) {
499 ShowAuthenticationNotification(protection_space,
500 details.bad_cached_credentials());
501 return;
502 }
503
504 // TODO(acostinas,chromium:1104818) |protection_space.origin()| is in a
505 // URI-like format which may be incompatible between Chrome and libcurl, which
506 // is used on the Chrome OS side. We should change |origin()| to be a PAC
507 // string (a more "standard" way of representing proxies) and call
508 // |FromPacString()| to create |proxy_server|.
509 net::ProxyServer proxy_server = net::ProxyServer::FromURI(
510 protection_space.origin(), net::ProxyServer::Scheme::SCHEME_HTTP);
511
512 if (!proxy_server.is_valid()) {
513 SendEmptyCredentials(protection_space);
514 return;
515 }
516 content::BrowserContext::GetDefaultStoragePartition(primary_profile_)
517 ->GetNetworkContext()
518 ->LookupProxyAuthCredentials(
519 proxy_server, protection_space.scheme(),
520 net::HttpUtil::Unquote(protection_space.realm()),
521 base::BindOnce(
522 &SystemProxyManager::LookupProxyAuthCredentialsCallback,
523 weak_factory_.GetWeakPtr(), protection_space));
524 }
525
LookupProxyAuthCredentialsCallback(const system_proxy::ProtectionSpace & protection_space,const base::Optional<net::AuthCredentials> & credentials)526 void SystemProxyManager::LookupProxyAuthCredentialsCallback(
527 const system_proxy::ProtectionSpace& protection_space,
528 const base::Optional<net::AuthCredentials>& credentials) {
529 if (!credentials) {
530 // Ask the user for credentials
531 ShowAuthenticationNotification(protection_space, /*show_error=*/false);
532 return;
533 }
534
535 std::string username;
536 std::string password;
537 if (credentials) {
538 username = base::UTF16ToUTF8(credentials->username());
539 password = base::UTF16ToUTF8(credentials->password());
540
541 // If there's a dialog requesting credentials for this proxy, close it.
542 if (notification_handler_ ||
543 (active_auth_dialog_ &&
544 active_auth_dialog_->GetProxyServer() == protection_space.origin())) {
545 CloseAuthenticationUI();
546 }
547 }
548 SendUserAuthenticationCredentials(protection_space, username, password);
549 }
550
ShowAuthenticationNotification(const system_proxy::ProtectionSpace & protection_space,bool show_error)551 void SystemProxyManager::ShowAuthenticationNotification(
552 const system_proxy::ProtectionSpace& protection_space,
553 bool show_error) {
554 if (active_auth_dialog_)
555 return;
556 notification_handler_ = std::make_unique<chromeos::SystemProxyNotification>(
557 protection_space, show_error,
558 base::BindOnce(&SystemProxyManager::ShowAuthenticationDialog,
559 weak_factory_.GetWeakPtr()));
560 notification_handler_->Show();
561 }
562
ShowAuthenticationDialog(const system_proxy::ProtectionSpace & protection_space,bool show_error_label)563 void SystemProxyManager::ShowAuthenticationDialog(
564 const system_proxy::ProtectionSpace& protection_space,
565 bool show_error_label) {
566 if (active_auth_dialog_)
567 return;
568
569 if (notification_handler_)
570 notification_handler_->Close();
571
572 active_auth_dialog_ = new chromeos::RequestSystemProxyCredentialsView(
573 protection_space.origin(), show_error_label,
574 base::BindOnce(&SystemProxyManager::OnDialogClosed,
575 weak_factory_.GetWeakPtr(), protection_space));
576
577 active_auth_dialog_->SetAcceptCallback(
578 base::BindRepeating(&SystemProxyManager::OnDialogAccepted,
579 weak_factory_.GetWeakPtr(), protection_space));
580 active_auth_dialog_->SetCancelCallback(
581 base::BindRepeating(&SystemProxyManager::OnDialogCanceled,
582 weak_factory_.GetWeakPtr(), protection_space));
583
584 auth_widget_ = views::DialogDelegate::CreateDialogWidget(
585 active_auth_dialog_, /*context=*/nullptr, /*parent=*/nullptr);
586 auth_widget_->Show();
587 }
588
OnDialogAccepted(const system_proxy::ProtectionSpace & protection_space)589 void SystemProxyManager::OnDialogAccepted(
590 const system_proxy::ProtectionSpace& protection_space) {
591 SendUserAuthenticationCredentials(
592 protection_space, base::UTF16ToUTF8(active_auth_dialog_->GetUsername()),
593 base::UTF16ToUTF8(active_auth_dialog_->GetPassword()));
594 }
595
OnDialogCanceled(const system_proxy::ProtectionSpace & protection_space)596 void SystemProxyManager::OnDialogCanceled(
597 const system_proxy::ProtectionSpace& protection_space) {
598 SendEmptyCredentials(protection_space);
599 }
600
OnDialogClosed(const system_proxy::ProtectionSpace & protection_space)601 void SystemProxyManager::OnDialogClosed(
602 const system_proxy::ProtectionSpace& protection_space) {
603 active_auth_dialog_ = nullptr;
604 auth_widget_ = nullptr;
605 }
606
CloseAuthenticationUI()607 void SystemProxyManager::CloseAuthenticationUI() {
608 // Closes the notification if shown.
609 if (notification_handler_) {
610 notification_handler_->Close();
611 notification_handler_.reset();
612 }
613 if (!auth_widget_)
614 return;
615 // Also deletes the |auth_widget_| instance.
616 auth_widget_->CloseWithReason(views::Widget::ClosedReason::kUnspecified);
617 }
618
619 } // namespace policy
620