1417 lines
58 KiB
Diff
1417 lines
58 KiB
Diff
From: csagan5 <32685696+csagan5@users.noreply.github.com>
|
||
Date: Thu, 29 Mar 2018 00:43:32 +0200
|
||
Subject: Add a proxy configuration page
|
||
|
||
Accessible from proxy settings and chrome://proxy
|
||
Allows to use a PAC script URL, automatic configuration and explicit proxy settings.
|
||
Offer auto-complete for the proxy page URL.
|
||
Store proxy settings in LocalState instead of Profile, so that proxy is used for SimpleURLLoaders as well;
|
||
this implementation is the same as the one in ChromeOS which gets proxy information from the LocalState
|
||
for the system network context; this is strictly not correct on Android because the network context is
|
||
never connected to any user profile and only gets proxy information from the system.
|
||
Existing settings on Profile are migrated to LocalState on startup.
|
||
|
||
Credits to @uazo for the LocalState integration.
|
||
|
||
License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
|
||
---
|
||
chrome/android/java/res/values/values.xml | 3 +
|
||
.../java/res/xml/privacy_preferences.xml | 4 +
|
||
.../privacy/settings/PrivacySettings.java | 1 +
|
||
.../chrome_autocomplete_provider_client.cc | 2 +
|
||
chrome/browser/browser_resources.grd | 3 +
|
||
.../extensions/api/proxy/proxy_api_helpers.cc | 2 +-
|
||
chrome/browser/net/proxy_service_factory.cc | 24 +-
|
||
chrome/browser/net/proxy_service_factory.h | 3 +
|
||
chrome/browser/prefs/browser_prefs.cc | 4 +
|
||
.../prefs/chrome_command_line_pref_store.cc | 2 +-
|
||
chrome/browser/resources/proxy_config.css | 61 +++
|
||
chrome/browser/resources/proxy_config.html | 77 ++++
|
||
chrome/browser/resources/proxy_config.js | 278 +++++++++++++
|
||
chrome/browser/ui/BUILD.gn | 2 +
|
||
.../webui/chrome_web_ui_controller_factory.cc | 3 +
|
||
chrome/browser/ui/webui/proxy_config_ui.cc | 393 ++++++++++++++++++
|
||
chrome/browser/ui/webui/proxy_config_ui.h | 31 ++
|
||
chrome/common/webui_url_constants.cc | 4 +
|
||
chrome/common/webui_url_constants.h | 2 +
|
||
.../pref_proxy_config_tracker_impl.cc | 5 +-
|
||
.../proxy_config/proxy_config_dictionary.cc | 30 +-
|
||
.../proxy_config/proxy_config_dictionary.h | 7 +-
|
||
.../proxy_config/proxy_policy_handler.cc | 2 +-
|
||
net/proxy_resolution/proxy_config.cc | 52 ++-
|
||
net/proxy_resolution/proxy_config.h | 3 +
|
||
25 files changed, 981 insertions(+), 17 deletions(-)
|
||
create mode 100644 chrome/browser/resources/proxy_config.css
|
||
create mode 100644 chrome/browser/resources/proxy_config.html
|
||
create mode 100644 chrome/browser/resources/proxy_config.js
|
||
create mode 100644 chrome/browser/ui/webui/proxy_config_ui.cc
|
||
create mode 100644 chrome/browser/ui/webui/proxy_config_ui.h
|
||
|
||
diff --git a/chrome/android/java/res/values/values.xml b/chrome/android/java/res/values/values.xml
|
||
--- a/chrome/android/java/res/values/values.xml
|
||
+++ b/chrome/android/java/res/values/values.xml
|
||
@@ -27,6 +27,9 @@ found in the LICENSE file.
|
||
<!-- Compositor Tab Title Text -->
|
||
<bool name="compositor_tab_title_fake_bold_text">true</bool>
|
||
|
||
+ <string name="proxy_title">Proxy configuration</string>
|
||
+ <string name="proxy_url">chrome://proxy</string>
|
||
+
|
||
<!-- Download InfoBar animation. -->
|
||
<integer name="download_infobar_fill_in_delay">1200</integer>
|
||
<integer name="download_infobar_fill_out_delay">200</integer>
|
||
diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/android/java/res/xml/privacy_preferences.xml
|
||
--- a/chrome/android/java/res/xml/privacy_preferences.xml
|
||
+++ b/chrome/android/java/res/xml/privacy_preferences.xml
|
||
@@ -9,6 +9,10 @@ found in the LICENSE file.
|
||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||
|
||
+ <org.chromium.chrome.browser.about_settings.HyperlinkPreference
|
||
+ android:key="proxy"
|
||
+ android:title="@string/proxy_title"
|
||
+ app:url="@string/proxy_url" />
|
||
<Preference
|
||
android:key="clear_browsing_data"
|
||
android:title="@string/clear_browsing_data_title"
|
||
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
|
||
--- a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
|
||
+++ b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
|
||
@@ -77,6 +77,7 @@ public class PrivacySettings
|
||
private static final String PREF_SAFE_BROWSING = "safe_browsing";
|
||
private static final String PREF_SYNC_AND_SERVICES_LINK = "sync_and_services_link";
|
||
private static final String PREF_PRIVACY_SANDBOX = "privacy_sandbox";
|
||
+ private static final String PREF_PROXY_OPTIONS = "proxy";
|
||
private static final String PREF_PRIVACY_GUIDE = "privacy_guide";
|
||
private static final String PREF_INCOGNITO_LOCK = "incognito_lock";
|
||
private static final String PREF_THIRD_PARTY_COOKIES = "third_party_cookies";
|
||
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
|
||
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
|
||
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
|
||
@@ -304,6 +304,8 @@ ChromeAutocompleteProviderClient::GetBuiltinsToProvideAsUserTypes() {
|
||
builtins_to_provide.push_back(
|
||
base::ASCIIToUTF16(chrome::kChromeUISettingsURL));
|
||
#endif
|
||
+ builtins_to_provide.push_back(
|
||
+ base::ASCIIToUTF16(chrome::kChromeUIProxyConfigURL));
|
||
builtins_to_provide.push_back(
|
||
base::ASCIIToUTF16(chrome::kChromeUIVersionURL));
|
||
return builtins_to_provide;
|
||
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
|
||
--- a/chrome/browser/browser_resources.grd
|
||
+++ b/chrome/browser/browser_resources.grd
|
||
@@ -252,6 +252,9 @@
|
||
<include name="IDR_PREF_HASH_SEED_BIN" file="resources\settings_internal\pref_hash_seed.bin" type="BINDATA" />
|
||
<include name="IDR_ADDITIONAL_MODULE_IDS" file="${additional_modules_list_file}" use_base_dir="false" type="BINDATA" />
|
||
</if>
|
||
+ <!-- Bromite Proxy Configuration UI -->
|
||
+ <include name="IDR_PROXY_CONFIG_HTML" file="resources\proxy_config.html" flattenhtml="true" type="BINDATA" compress="gzip" />
|
||
+ <include name="IDR_PROXY_CONFIG_JS" file="resources\proxy_config.js" type="BINDATA" compress="gzip" />
|
||
<if expr="not is_android">
|
||
<!-- Page not available for guest. -->
|
||
<include name="IDR_PAGE_NOT_AVAILABLE_FOR_GUEST_APP_HTML" file="resources\page_not_available_for_guest\app.html" type="BINDATA" />
|
||
diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
|
||
--- a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
|
||
+++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
|
||
@@ -388,7 +388,7 @@ absl::optional<base::Value::Dict> CreateProxyConfigDict(
|
||
return absl::nullopt;
|
||
}
|
||
return ProxyConfigDictionary::CreateFixedServers(proxy_rules_string,
|
||
- bypass_list);
|
||
+ bypass_list, /*reverse_bypass*/false);
|
||
}
|
||
case ProxyPrefs::MODE_SYSTEM:
|
||
return ProxyConfigDictionary::CreateSystem();
|
||
diff --git a/chrome/browser/net/proxy_service_factory.cc b/chrome/browser/net/proxy_service_factory.cc
|
||
--- a/chrome/browser/net/proxy_service_factory.cc
|
||
+++ b/chrome/browser/net/proxy_service_factory.cc
|
||
@@ -6,6 +6,7 @@
|
||
|
||
#include <utility>
|
||
|
||
+#include "base/logging.h"
|
||
#include "base/task/single_thread_task_runner.h"
|
||
#include "build/build_config.h"
|
||
#include "build/chromeos_buildflags.h"
|
||
@@ -13,6 +14,9 @@
|
||
#include "content/public/browser/browser_task_traits.h"
|
||
#include "content/public/browser/browser_thread.h"
|
||
#include "net/proxy_resolution/proxy_config_service.h"
|
||
+#include "components/proxy_config/proxy_config_pref_names.h"
|
||
+#include "components/prefs/pref_service.h"
|
||
+#include "components/prefs/pref_registry_simple.h"
|
||
|
||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||
#include "chromeos/ash/components/network/proxy/proxy_config_service_impl.h"
|
||
@@ -70,7 +74,20 @@ ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(
|
||
return std::make_unique<ash::ProxyConfigServiceImpl>(
|
||
profile_prefs, local_state_prefs, nullptr);
|
||
#else
|
||
- return std::make_unique<PrefProxyConfigTrackerImpl>(profile_prefs, nullptr);
|
||
+ // Migrate from profile_prefs to local_state_prefs
|
||
+ if (local_state_prefs->GetBoolean("proxy_migrated") == false) {
|
||
+ const base::Value::Dict& dict =
|
||
+ profile_prefs->GetDict(proxy_config::prefs::kProxy);
|
||
+
|
||
+ LOG(INFO) << "CreatePrefProxyConfigTrackerOfProfile: Migration from profile to local state";
|
||
+
|
||
+ const base::Value /*ProxyConfigDictionary*/ proxy_dict(dict.Clone());
|
||
+ local_state_prefs->Set(proxy_config::prefs::kProxy, proxy_dict);
|
||
+
|
||
+ local_state_prefs->SetBoolean("proxy_migrated", true);
|
||
+ local_state_prefs->CommitPendingWrite();
|
||
+ }
|
||
+ return std::make_unique<PrefProxyConfigTrackerImpl>(local_state_prefs, nullptr);
|
||
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
||
}
|
||
|
||
@@ -86,3 +103,8 @@ ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
|
||
nullptr);
|
||
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
|
||
}
|
||
+
|
||
+// static
|
||
+void ProxyServiceFactory::RegisterPrefs(PrefRegistrySimple* registry) {
|
||
+ registry->RegisterBooleanPref("proxy_migrated", false);
|
||
+}
|
||
diff --git a/chrome/browser/net/proxy_service_factory.h b/chrome/browser/net/proxy_service_factory.h
|
||
--- a/chrome/browser/net/proxy_service_factory.h
|
||
+++ b/chrome/browser/net/proxy_service_factory.h
|
||
@@ -6,6 +6,7 @@
|
||
#define CHROME_BROWSER_NET_PROXY_SERVICE_FACTORY_H_
|
||
|
||
#include <memory>
|
||
+#include "components/prefs/pref_registry_simple.h"
|
||
|
||
class PrefProxyConfigTracker;
|
||
class PrefService;
|
||
@@ -35,6 +36,8 @@ class ProxyServiceFactory {
|
||
CreatePrefProxyConfigTrackerOfProfile(PrefService* profile_prefs,
|
||
PrefService* local_state_prefs);
|
||
|
||
+ static void RegisterPrefs(PrefRegistrySimple* registry);
|
||
+
|
||
// Creates a PrefProxyConfigTracker that tracks local state only. This tracker
|
||
// should be used for the system request context and the signin screen
|
||
// (ChromeOS only).
|
||
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
|
||
--- a/chrome/browser/prefs/browser_prefs.cc
|
||
+++ b/chrome/browser/prefs/browser_prefs.cc
|
||
@@ -185,6 +185,8 @@
|
||
#include "rlz/buildflags/buildflags.h"
|
||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||
|
||
+#include "chrome/browser/net/proxy_service_factory.h"
|
||
+
|
||
#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
|
||
#include "chrome/browser/background/background_mode_manager.h"
|
||
#endif
|
||
@@ -1389,6 +1391,8 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
|
||
component_updater::RegisterPrefs(registry);
|
||
domain_reliability::RegisterPrefs(registry);
|
||
embedder_support::OriginTrialPrefs::RegisterPrefs(registry);
|
||
+ ProxyServiceFactory::RegisterPrefs(registry);
|
||
+
|
||
enterprise_reporting::RegisterLocalStatePrefs(registry);
|
||
ExternalProtocolHandler::RegisterPrefs(registry);
|
||
flags_ui::PrefServiceFlagsStorage::RegisterPrefs(registry);
|
||
diff --git a/chrome/browser/prefs/chrome_command_line_pref_store.cc b/chrome/browser/prefs/chrome_command_line_pref_store.cc
|
||
--- a/chrome/browser/prefs/chrome_command_line_pref_store.cc
|
||
+++ b/chrome/browser/prefs/chrome_command_line_pref_store.cc
|
||
@@ -156,7 +156,7 @@ void ChromeCommandLinePrefStore::ApplyProxyMode() {
|
||
command_line()->GetSwitchValueASCII(switches::kProxyBypassList);
|
||
SetValue(proxy_config::prefs::kProxy,
|
||
base::Value(ProxyConfigDictionary::CreateFixedServers(
|
||
- proxy_server, bypass_list)),
|
||
+ proxy_server, bypass_list, false)),
|
||
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
|
||
}
|
||
}
|
||
diff --git a/chrome/browser/resources/proxy_config.css b/chrome/browser/resources/proxy_config.css
|
||
new file mode 100644
|
||
--- /dev/null
|
||
+++ b/chrome/browser/resources/proxy_config.css
|
||
@@ -0,0 +1,61 @@
|
||
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||
+ * Use of this source code is governed by a BSD-style license that can be
|
||
+ * found in the LICENSE file.
|
||
+ */
|
||
+
|
||
+body {
|
||
+ font-size: 80%;
|
||
+ margin: 1em;
|
||
+}
|
||
+
|
||
+#main-container {
|
||
+ max-width: 60em;
|
||
+ margin-left: auto;
|
||
+ margin-right: auto;
|
||
+}
|
||
+
|
||
+button {
|
||
+ display: block;
|
||
+ font-size: 110%;
|
||
+ font-weight: bold;
|
||
+ margin: 10px auto;
|
||
+ padding: 1em;
|
||
+ width: 15em;
|
||
+}
|
||
+
|
||
+h2 {
|
||
+ color: #546E7A;
|
||
+ font-weight: normal;
|
||
+ font-size: 170%;
|
||
+ margin-bottom: 1.5em;
|
||
+}
|
||
+
|
||
+.radio-button-div {
|
||
+ margin: 7px auto;
|
||
+}
|
||
+
|
||
+.warning {
|
||
+ color: red;
|
||
+ font-size: 90%;
|
||
+}
|
||
+
|
||
+.section-container {
|
||
+ margin-top: 2em;
|
||
+}
|
||
+
|
||
+#file-path-logging,
|
||
+#file-path-stopped {
|
||
+ font-family: monospace;
|
||
+}
|
||
+
|
||
+.outline-box {
|
||
+ margin-top: 2em;
|
||
+ border: 1px solid #ababab;
|
||
+ padding: 0.5em;
|
||
+ line-height: 1.5em;
|
||
+}
|
||
+
|
||
+textarea {
|
||
+ width: 95%;
|
||
+ height: 4em;
|
||
+}
|
||
diff --git a/chrome/browser/resources/proxy_config.html b/chrome/browser/resources/proxy_config.html
|
||
new file mode 100644
|
||
--- /dev/null
|
||
+++ b/chrome/browser/resources/proxy_config.html
|
||
@@ -0,0 +1,77 @@
|
||
+<!doctype html>
|
||
+<html>
|
||
+<head>
|
||
+<meta charset="utf-8">
|
||
+<if expr="is_android">
|
||
+<meta name="viewport" content="width=device-width">
|
||
+</if>
|
||
+
|
||
+<if expr="is_ios">
|
||
+<!-- TODO(crbug.com/487000): Remove this once injected by web. -->
|
||
+<script src="chrome://resources/js/ios/web_ui.js"></script>
|
||
+</if>
|
||
+
|
||
+<script type="module" src="chrome://proxy/proxy_config.js"></script>
|
||
+<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
|
||
+<link rel="stylesheet" href="proxy_config.css">
|
||
+<title>Proxy configuration</title>
|
||
+</head>
|
||
+<body>
|
||
+ <div id="main-container">
|
||
+ <!--
|
||
+ =========================================================================
|
||
+ View for "pending" state.
|
||
+ * Only visible briefly, if at all
|
||
+ =========================================================================
|
||
+ -->
|
||
+ <div id="state-pending">
|
||
+ <h2>Proxy configuration</h2>
|
||
+ Loading...
|
||
+ </div>
|
||
+
|
||
+ <!--
|
||
+ =========================================================================
|
||
+ View for "available" and "unset" states.
|
||
+ * Has controls to change or reset proxy configuration.
|
||
+ =========================================================================
|
||
+ -->
|
||
+ <div id="state-main" hidden>
|
||
+ <h2>Proxy configuration</h2>
|
||
+ <button id="reset">Reset</button>
|
||
+ <div class="section-container">
|
||
+ Reset will update the displayed configuration to match the one currently in use.
|
||
+ </div>
|
||
+ <div class="section-container">
|
||
+ <input type="radio" id="empty" name="mode" value="empty"><label for="empty">System Default</label><br/>
|
||
+ <input type="radio" id="direct" name="mode" value="direct"><label for="direct">Direct</label><br/>
|
||
+ <input type="radio" id="auto-detect" name="mode" value="auto-detect"><label for="auto-detect">Auto-detect (WPAD DHCP/DNS)</label><br/>
|
||
+ <input type="radio" id="use-pac-url" name="mode" value="use-pac-url"><label for="use-pac-url">Use PAC URL: <input id='pac-url' value="" size="40" /></label>
|
||
+ <p><input type="checkbox" id="pac-mandatory" name="pac-mandatory"><label for="pac-mandatory">Do not allow fallback to direct connection in case PAC script fails</label></p>
|
||
+ <input type="radio" id="use-single-list" name="mode" value="use-single-list"><label for="use-single-list">Use a single proxy list for all schemes (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_(PAC)_file#Description">PAC format</a>):
|
||
+ <textarea id="single-proxies"></textarea>
|
||
+ </label><br/>
|
||
+ <input type="radio" id="use-list-per-scheme" name="mode" value="use-list-per-scheme"><label for="use-list-per-scheme">Use a proxy list per scheme:</label><br/>
|
||
+ <label for="use-list-per-scheme">HTTP (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_(PAC)_file#Description">PAC format</a>):<br/>
|
||
+ <textarea id="http-proxies"></textarea></label><br/>
|
||
+ <label for="use-list-per-scheme">HTTPS (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_(PAC)_file#Description">PAC format</a>):<br/>
|
||
+ <textarea id="https-proxies"></textarea></label><br/>
|
||
+ <label for="use-list-per-scheme">FTP (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_(PAC)_file#Description">PAC format</a>):<br/>
|
||
+ <textarea id="ftp-proxies"></textarea></label><br/>
|
||
+ <label for="use-list-per-scheme">Fallback (used when the URL does not match any of the standard schemes, <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_(PAC)_file#Description">PAC format</a>):<br/>
|
||
+ <textarea id="fallback-proxies"></textarea></label>
|
||
+ <div class="outline-box">
|
||
+ Bypass rules (a list of matching expressions for the hostname separated by comma or semicolon, can use asterisk; matches against port numbers and IPv4/IPv6); in use only with single or per-scheme proxy lists.<br/>
|
||
+ <textarea id="bypass-rules"></textarea><br/>
|
||
+ <input type="checkbox" id="reverse-bypass" name="reverse-bypass"><label for="reverse-bypass">Reverse the meaning of bypass rules</label>
|
||
+ </div>
|
||
+ </div>
|
||
+ <button id="apply">Apply</button>
|
||
+ <button id="clear">Clear</button>
|
||
+ <div class="section-container">
|
||
+ Clicking on Clear will remove any proxy configuration preference currently in effect.
|
||
+ </div>
|
||
+ </div>
|
||
+
|
||
+ </div>
|
||
+</body>
|
||
+</html>
|
||
diff --git a/chrome/browser/resources/proxy_config.js b/chrome/browser/resources/proxy_config.js
|
||
new file mode 100644
|
||
--- /dev/null
|
||
+++ b/chrome/browser/resources/proxy_config.js
|
||
@@ -0,0 +1,278 @@
|
||
+/*
|
||
+ This file is part of Bromite.
|
||
+
|
||
+ Bromite is free software: you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation, either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ Bromite is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
|
||
+*/
|
||
+
|
||
+import {$} from 'chrome://resources/js/util_ts.js';
|
||
+
|
||
+/**
|
||
+ * Main entry point called once the page has loaded.
|
||
+ */
|
||
+function onLoad() {
|
||
+ ProxyConfigView.getInstance();
|
||
+}
|
||
+
|
||
+document.addEventListener('DOMContentLoaded', onLoad);
|
||
+
|
||
+/**
|
||
+ * This class handles the presentation of the proxy-config view. Used as a
|
||
+ * singleton.
|
||
+ */
|
||
+var ProxyConfigView = (function() {
|
||
+ 'use strict';
|
||
+
|
||
+ // --------------------------------------------------------------------------
|
||
+
|
||
+ var kIdStateDivUninitialized = 'state-pending';
|
||
+ var kIdStateDivMain = 'state-main';
|
||
+ var kIdApplyButton = 'apply';
|
||
+ var kIdResetButton = 'reset';
|
||
+ var kIdClearButton = 'clear';
|
||
+
|
||
+ var kIdModeEmpty = 'empty';
|
||
+ var kIdModeDirect = 'direct';
|
||
+ var kIdModeAutoDetect = 'auto-detect';
|
||
+ var kIdModeUsePacURL = 'use-pac-url';
|
||
+
|
||
+ var kIdModeUseSingleList = 'use-single-list';
|
||
+ var kIdModeUseListPerScheme = 'use-list-per-scheme';
|
||
+
|
||
+ var kIdPacURL = 'pac-url';
|
||
+ var kIdPacMandatory = 'pac-mandatory';
|
||
+ var kIdBypassRules = 'bypass-rules';
|
||
+ var kIdReverseBypass = 'reverse-bypass';
|
||
+ var kIdSingleProxies = 'single-proxies';
|
||
+ var kIdHttpProxies = 'http-proxies';
|
||
+ var kIdHttpsProxies = 'https-proxies';
|
||
+ var kIdFtpProxies = 'ftp-proxies';
|
||
+ var kIdFallbackProxies = 'fallback-proxies';
|
||
+
|
||
+ /**
|
||
+ * Adds a {@code getInstance} static method that always return the same
|
||
+ * instance object.
|
||
+ * @param {!Function} ctor The constructor for the class to add the static
|
||
+ * method to.
|
||
+ */
|
||
+ function addSingletonGetter(ctor) {
|
||
+ ctor.getInstance = function() {
|
||
+ return ctor.instance_ || (ctor.instance_ = new ctor());
|
||
+ };
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * @constructor
|
||
+ */
|
||
+ function ProxyConfigView() {
|
||
+ this.currentConfig = null;
|
||
+
|
||
+ $(kIdResetButton).onclick = this.onReset_.bind(this);
|
||
+ $(kIdApplyButton).onclick = this.onApply_.bind(this);
|
||
+ $(kIdClearButton).onclick = this.onClear_.bind(this);
|
||
+
|
||
+ // Tell ProxyConfigMessageHandler to notify the UI of future state changes
|
||
+ // from this point on.
|
||
+ chrome.send('enableNotifyUIWithState');
|
||
+ }
|
||
+
|
||
+ addSingletonGetter(ProxyConfigView);
|
||
+ window.ProxyConfigView = ProxyConfigView;
|
||
+
|
||
+ ProxyConfigView.prototype = {
|
||
+ /**
|
||
+ * Updates the UI to reflect the current state. The state transitions are
|
||
+ * sent by the browser controller (ProxyConfigMessageHandler):
|
||
+ *
|
||
+ * * PENDING - This is the initial state when proxy configuration is opened
|
||
+ * for the first time, or there was an error during initialization.
|
||
+ * This state is short-lived and likely not observed; will
|
||
+ * immediately transition to AVAILABLE).
|
||
+ *
|
||
+ * * AVAILABLE - The reported proxy configuration is active; this state is entered
|
||
+ * on first page load (or right after PENDING if configuration was not
|
||
+ * available on page load) and every time some configuration change was applied.
|
||
+ * It can transition to either AVAILABLE or UNSET.
|
||
+ *
|
||
+ * * UNSET - Proxy configuration is reported to be currently not set.
|
||
+ *
|
||
+ */
|
||
+ onProxyConfigChanged: function(state) {
|
||
+ // may happen only on first load; leave the loading page as another update is expected
|
||
+ // when proxy configuration has finished loading
|
||
+ if (state.pending) {
|
||
+ $(kIdStateDivMain).hidden = true;
|
||
+ $(kIdStateDivUninitialized).hidden = false;
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if (!state.hasOwnProperty('config')) {
|
||
+ // configuration has been unset, use an empty one
|
||
+ this.eraseCurrentConfig_();
|
||
+ } else {
|
||
+ // save the configuration as current and reset all controls to it
|
||
+ this.currentConfig = state.config;
|
||
+ }
|
||
+
|
||
+ this.renderConfig_();
|
||
+
|
||
+ this.toggleButtons_(false);
|
||
+ $(kIdStateDivUninitialized).hidden = true;
|
||
+ $(kIdStateDivMain).hidden = false;
|
||
+ },
|
||
+
|
||
+ /**
|
||
+ * Set current configuration to an empty (default) one.
|
||
+ */
|
||
+ eraseCurrentConfig_: function() {
|
||
+ this.currentConfig = {
|
||
+ "auto_detect": false,
|
||
+ "pending": false,
|
||
+ "rules": {
|
||
+ "bypass_rules": "",
|
||
+ "reverse_bypass": false,
|
||
+ "type": "none"
|
||
+ }
|
||
+ };
|
||
+ },
|
||
+
|
||
+ /**
|
||
+ * Serialize the user-selected configuration in an object.
|
||
+ */
|
||
+ serializeConfig_: function() {
|
||
+ if ($(kIdModeEmpty).checked) {
|
||
+ return {
|
||
+ "auto_detect": false,
|
||
+ "rules": {
|
||
+ "type": "none"
|
||
+ }
|
||
+ };
|
||
+ } else if ($(kIdModeDirect).checked) {
|
||
+ return {
|
||
+ "auto_detect": false,
|
||
+ "rules": {
|
||
+ "type": "direct"
|
||
+ }
|
||
+ };
|
||
+ } else if ($(kIdModeAutoDetect).checked) {
|
||
+ return {
|
||
+ "auto_detect": true
|
||
+ };
|
||
+ } else if ($(kIdModeUsePacURL).checked) {
|
||
+ return {
|
||
+ "auto_detect": false,
|
||
+ "pac_url": $(kIdPacURL).value.trim(),
|
||
+ "pac_mandatory": $(kIdPacMandatory).checked,
|
||
+ "rules": {}
|
||
+ };
|
||
+ } else if ($(kIdModeUseListPerScheme).checked || $(kIdModeUseSingleList).checked) {
|
||
+ var config = {
|
||
+ "auto_detect": false,
|
||
+ "rules": {
|
||
+ "bypass_rules": $(kIdBypassRules).value.trim(),
|
||
+ "reverse_bypass": $(kIdReverseBypass).checked,
|
||
+ "type": "list"
|
||
+ }
|
||
+ };
|
||
+
|
||
+ if ($(kIdModeUseListPerScheme).checked) {
|
||
+ config.rules.type = "list_per_scheme";
|
||
+
|
||
+ config.rules.proxies_for_http = $(kIdHttpProxies).value.trim();
|
||
+ config.rules.proxies_for_https = $(kIdHttpsProxies).value.trim();
|
||
+ config.rules.proxies_for_ftp = $(kIdFtpProxies).value.trim();
|
||
+ config.rules.fallback_proxies = $(kIdFallbackProxies).value.trim();
|
||
+ } else {
|
||
+ config.rules.single_proxies = $(kIdSingleProxies).value.trim();
|
||
+ }
|
||
+
|
||
+ return config;
|
||
+ }
|
||
+
|
||
+ throw new Error('unexpected mode');
|
||
+ },
|
||
+
|
||
+ /**
|
||
+ * Updates the UI to display the current proxy configuration.
|
||
+ */
|
||
+ renderConfig_: function() {
|
||
+ if (this.currentConfig.auto_detect) {
|
||
+ $(kIdModeAutoDetect).checked = true;
|
||
+ } else if (this.currentConfig.hasOwnProperty('pac_url')) {
|
||
+ $(kIdPacURL).value = this.currentConfig.pac_url;
|
||
+ $(kIdPacMandatory).checked = this.currentConfig.pac_mandatory;
|
||
+ $(kIdModeUsePacURL).checked = true;
|
||
+ } else if (this.currentConfig.rules.type == "none") {
|
||
+ $(kIdModeEmpty).checked = true;
|
||
+ } else if (this.currentConfig.rules.type == "direct") {
|
||
+ $(kIdModeDirect).checked = true;
|
||
+ } else {
|
||
+ $(kIdBypassRules).value = this.currentConfig.rules.bypass_rules;
|
||
+ $(kIdReverseBypass).checked = this.currentConfig.rules.reverse_bypass;
|
||
+
|
||
+ switch (this.currentConfig.rules.type) {
|
||
+ case "list":
|
||
+ $(kIdModeUseSingleList).checked = true;
|
||
+ $(kIdSingleProxies).value = this.currentConfig.rules.single_proxies;
|
||
+ break;
|
||
+ case "list_per_scheme":
|
||
+ $(kIdModeUseListPerScheme).checked = true;
|
||
+ $(kIdHttpProxies).value = this.currentConfig.rules.proxies_for_http;
|
||
+ $(kIdHttpsProxies).value = this.currentConfig.rules.proxies_for_https;
|
||
+ $(kIdFtpProxies).value = this.currentConfig.rules.proxies_for_ftp;
|
||
+ $(kIdFallbackProxies).value = this.currentConfig.rules.fallback_proxies;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ },
|
||
+
|
||
+ /**
|
||
+ * Apply the configuration currently displayed.
|
||
+ */
|
||
+ onApply_: function() {
|
||
+ var config = this.serializeConfig_();
|
||
+
|
||
+ // disable buttons; will be enabled back when UI receives a state update
|
||
+ this.toggleButtons_(true);
|
||
+ chrome.send('apply', [config]);
|
||
+ },
|
||
+
|
||
+ /**
|
||
+ * Apply the configuration currently displayed.
|
||
+ */
|
||
+ onClear_: function() {
|
||
+ // disable buttons; will be enabled back when UI receives a state update
|
||
+ this.toggleButtons_(true);
|
||
+ this.eraseCurrentConfig_();
|
||
+ chrome.send('clear', []);
|
||
+ },
|
||
+
|
||
+ /**
|
||
+ * Toggle the disabled status of the action buttons.
|
||
+ */
|
||
+ toggleButtons_: function(disabled) {
|
||
+ $(kIdApplyButton).disabled = disabled;
|
||
+ $(kIdResetButton).disabled = disabled;
|
||
+ $(kIdClearButton).disabled = disabled;
|
||
+ },
|
||
+
|
||
+ /**
|
||
+ * Reset currently displayed configuration to the last known configuration in use.
|
||
+ */
|
||
+ onReset_: function() {
|
||
+ this.renderConfig_();
|
||
+ }
|
||
+ };
|
||
+
|
||
+ return ProxyConfigView;
|
||
+})();
|
||
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
|
||
--- a/chrome/browser/ui/BUILD.gn
|
||
+++ b/chrome/browser/ui/BUILD.gn
|
||
@@ -301,6 +301,8 @@ static_library("ui") {
|
||
"webui/metrics_internals/metrics_internals_ui.h",
|
||
"webui/net_export_ui.cc",
|
||
"webui/net_export_ui.h",
|
||
+ "webui/proxy_config_ui.cc",
|
||
+ "webui/proxy_config_ui.h",
|
||
"webui/net_internals/net_internals_ui.cc",
|
||
"webui/net_internals/net_internals_ui.h",
|
||
"webui/ntp_tiles_internals_ui.cc",
|
||
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
|
||
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
|
||
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
|
||
@@ -63,6 +63,7 @@
|
||
#include "chrome/browser/ui/webui/ntp_tiles_internals_ui.h"
|
||
#include "chrome/browser/ui/webui/omnibox/omnibox_ui.h"
|
||
#include "chrome/browser/ui/webui/policy/policy_ui.h"
|
||
+#include "chrome/browser/ui/webui/proxy_config_ui.h"
|
||
#include "chrome/browser/ui/webui/predictors/predictors_ui.h"
|
||
#include "chrome/browser/ui/webui/segmentation_internals/segmentation_internals_ui.h"
|
||
#include "chrome/browser/ui/webui/signin_internals_ui.h"
|
||
@@ -496,6 +497,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
|
||
return &NewWebUI<MetricsInternalsUI>;
|
||
if (url.host_piece() == chrome::kChromeUINetExportHost)
|
||
return &NewWebUI<NetExportUI>;
|
||
+ if (url.host_piece() == chrome::kChromeUIProxyConfigHost)
|
||
+ return &NewWebUI<ProxyConfigUI>;
|
||
if (url.host_piece() == chrome::kChromeUINetInternalsHost)
|
||
return &NewWebUI<NetInternalsUI>;
|
||
if (url.host_piece() == chrome::kChromeUINTPTilesInternalsHost)
|
||
diff --git a/chrome/browser/ui/webui/proxy_config_ui.cc b/chrome/browser/ui/webui/proxy_config_ui.cc
|
||
new file mode 100644
|
||
--- /dev/null
|
||
+++ b/chrome/browser/ui/webui/proxy_config_ui.cc
|
||
@@ -0,0 +1,393 @@
|
||
+/*
|
||
+ This file is part of Bromite.
|
||
+
|
||
+ Bromite is free software: you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation, either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ Bromite is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
|
||
+*/
|
||
+
|
||
+#include "chrome/browser/ui/webui/proxy_config_ui.h"
|
||
+
|
||
+#include <stdint.h>
|
||
+
|
||
+#include <memory>
|
||
+#include <string>
|
||
+#include <vector>
|
||
+
|
||
+#include "base/command_line.h"
|
||
+#include "base/lazy_instance.h"
|
||
+#include "base/memory/ref_counted.h"
|
||
+#include "base/strings/string_util.h"
|
||
+#include "base/strings/utf_string_conversions.h"
|
||
+#include "base/values.h"
|
||
+#include "chrome/browser/browser_process.h"
|
||
+#include "chrome/browser/net/proxy_service_factory.h"
|
||
+#include "chrome/browser/platform_util.h"
|
||
+#include "chrome/browser/profiles/profile.h"
|
||
+#include "chrome/common/url_constants.h"
|
||
+#include "chrome/grit/browser_resources.h"
|
||
+#include "components/prefs/pref_service.h"
|
||
+#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
|
||
+#include "components/proxy_config/proxy_config_pref_names.h"
|
||
+#include "components/grit/components_resources.h"
|
||
+#include "content/public/browser/browser_thread.h"
|
||
+#include "content/public/browser/url_data_source.h"
|
||
+#include "content/public/browser/web_contents.h"
|
||
+#include "content/public/browser/web_ui.h"
|
||
+#include "content/public/browser/web_ui_data_source.h"
|
||
+#include "content/public/browser/web_ui_message_handler.h"
|
||
+
|
||
+#include "url/gurl.h"
|
||
+
|
||
+using content::BrowserThread;
|
||
+using content::WebContents;
|
||
+using content::WebUIMessageHandler;
|
||
+
|
||
+namespace {
|
||
+
|
||
+// This class receives javascript messages from the renderer.
|
||
+// Note that the WebUI infrastructure runs on the UI thread, therefore all of
|
||
+// this class's public methods are expected to run on the UI thread.
|
||
+class ProxyConfigMessageHandler
|
||
+ : public WebUIMessageHandler,
|
||
+ public base::SupportsWeakPtr<ProxyConfigMessageHandler>,
|
||
+ public net::ProxyConfigService::Observer {
|
||
+ public:
|
||
+ ProxyConfigMessageHandler(const ProxyConfigMessageHandler&) = delete;
|
||
+ ProxyConfigMessageHandler& operator=(const ProxyConfigMessageHandler&) = delete;
|
||
+ // Creates a ProxyConfigMessageHandler that handles message exchanges with the Javascript
|
||
+ // side of the UI and gets proxy settings from the Web UI associated profile to watch for changes.
|
||
+ // The created ProxyConfigMessageHandler must be destroyed before |profile|.
|
||
+ ProxyConfigMessageHandler(Profile *profile);
|
||
+ ~ProxyConfigMessageHandler() override;
|
||
+
|
||
+ // WebUIMessageHandler implementation.
|
||
+ void RegisterMessages() override;
|
||
+
|
||
+ // Messages
|
||
+ void OnEnableNotifyUIWithState(const base::Value::List& args);
|
||
+ void OnApply(const base::Value::List& args);
|
||
+ void OnClear(const base::Value::List& args);
|
||
+
|
||
+ // net::ProxyConfigService::Observer implementation:
|
||
+ // Calls ProxyConfigView.onProxyConfigChanged JavaScript function in the
|
||
+ // renderer.
|
||
+ void OnProxyConfigChanged(
|
||
+ const net::ProxyConfigWithAnnotation& config,
|
||
+ net::ProxyConfigService::ConfigAvailability availability) override;
|
||
+
|
||
+ private:
|
||
+ // Not owned.
|
||
+ raw_ptr<PrefService> pref_service_;
|
||
+ std::unique_ptr<net::ProxyConfigService> proxy_config_service_;
|
||
+ // Monitors global and Profile prefs related to proxy configuration.
|
||
+ std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
|
||
+ bool is_observing_;
|
||
+
|
||
+ void encodeConfig(const net::ProxyConfig& config, base::Value::Dict& state);
|
||
+
|
||
+ void apply(const net::ProxyConfig& config);
|
||
+
|
||
+ base::WeakPtrFactory<ProxyConfigMessageHandler> weak_ptr_factory_;
|
||
+};
|
||
+
|
||
+ProxyConfigMessageHandler::ProxyConfigMessageHandler(Profile *profile)
|
||
+ :
|
||
+ weak_ptr_factory_(this) {
|
||
+
|
||
+ // used to set new configuration preferences
|
||
+ pref_service_ = g_browser_process->local_state();
|
||
+ // observer is explicitly added only later in enableNotifyUIWithState
|
||
+ is_observing_ = false;
|
||
+
|
||
+// If this is the ChromeOS sign-in profile, just create the tracker from global
|
||
+// state.
|
||
+#if defined(OS_CHROMEOS)
|
||
+ if (chromeos::ProfileHelper::IsSigninProfile(profile)) {
|
||
+ pref_proxy_config_tracker_.reset(
|
||
+ ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
|
||
+ g_browser_process->local_state()));
|
||
+ }
|
||
+#endif // defined(OS_CHROMEOS)
|
||
+
|
||
+ if (!pref_proxy_config_tracker_) {
|
||
+ pref_proxy_config_tracker_ =
|
||
+ ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(
|
||
+ profile->GetPrefs(), g_browser_process->local_state());
|
||
+ }
|
||
+
|
||
+ proxy_config_service_ = ProxyServiceFactory::CreateProxyConfigService(
|
||
+ pref_proxy_config_tracker_.get(), nullptr);
|
||
+}
|
||
+
|
||
+void ProxyConfigMessageHandler::OnProxyConfigChanged(
|
||
+ const net::ProxyConfigWithAnnotation& config,
|
||
+ net::ProxyConfigService::ConfigAvailability availability) {
|
||
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
|
||
+ !BrowserThread::IsThreadInitialized(BrowserThread::UI));
|
||
+
|
||
+ base::Value::Dict state;
|
||
+ bool pending = false;
|
||
+ switch (availability) {
|
||
+ case net::ProxyConfigService::CONFIG_VALID:
|
||
+ encodeConfig(config.value(), state);
|
||
+ break;
|
||
+ case net::ProxyConfigService::CONFIG_UNSET:
|
||
+ state.SetByDottedPath("config.rules.type", base::Value("none"));
|
||
+ break;
|
||
+ case net::ProxyConfigService::CONFIG_PENDING:
|
||
+ //NOTE: this can only happen when triggered manually first time
|
||
+ pending = true;
|
||
+ break;
|
||
+ }
|
||
+ state.Set("pending", base::Value(pending));
|
||
+
|
||
+ // call Javascript function
|
||
+ web_ui()->CallJavascriptFunctionUnsafe("ProxyConfigView.getInstance().onProxyConfigChanged",
|
||
+ state.Clone());
|
||
+}
|
||
+
|
||
+const std::string omitDirect(const std::string pacString) {
|
||
+ if (pacString == "DIRECT") {
|
||
+ return "";
|
||
+ }
|
||
+ return pacString;
|
||
+}
|
||
+
|
||
+void ProxyConfigMessageHandler::encodeConfig(const net::ProxyConfig& config, base::Value::Dict& state) {
|
||
+ // when automatic settings are enabled they take precedence over manual settings
|
||
+ // automatic settings are either the "auto-detect" flag or the existance of a PAC URL
|
||
+
|
||
+ state.SetByDottedPath("config.auto_detect", base::Value(config.auto_detect()));
|
||
+
|
||
+ auto rules = config.proxy_rules();
|
||
+ if (config.has_pac_url()) {
|
||
+ state.SetByDottedPath("config.pac_url", base::Value(config.pac_url().spec()));
|
||
+ state.SetByDottedPath("config.pac_mandatory", base::Value(config.pac_mandatory()));
|
||
+ state.SetByDottedPath("config.rules.type", base::Value("none"));
|
||
+ state.SetByDottedPath("config.rules.bypass_rules", base::Value(rules.bypass_rules.ToString()));
|
||
+ state.SetByDottedPath("config.rules.reverse_bypass", base::Value(rules.reverse_bypass));
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ const char *type;
|
||
+ switch (rules.type) {
|
||
+ case net::ProxyConfig::ProxyRules::Type::EMPTY:
|
||
+ type = "direct";
|
||
+ break;
|
||
+ case net::ProxyConfig::ProxyRules::Type::PROXY_LIST:
|
||
+ type = "list";
|
||
+
|
||
+ state.SetByDottedPath("config.rules.single_proxies", base::Value(omitDirect(rules.single_proxies.ToPacString())));
|
||
+ break;
|
||
+ case net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME:
|
||
+ type = "list_per_scheme";
|
||
+
|
||
+ state.SetByDottedPath("config.rules.proxies_for_http", base::Value(omitDirect(rules.proxies_for_http.ToPacString())));
|
||
+ state.SetByDottedPath("config.rules.proxies_for_https", base::Value(omitDirect(rules.proxies_for_https.ToPacString())));
|
||
+ state.SetByDottedPath("config.rules.proxies_for_ftp", base::Value(omitDirect(rules.proxies_for_ftp.ToPacString())));
|
||
+ state.SetByDottedPath("config.rules.fallback_proxies", base::Value(omitDirect(rules.fallback_proxies.ToPacString())));
|
||
+ break;
|
||
+ default:
|
||
+ NOTREACHED();
|
||
+ break;
|
||
+ }
|
||
+ state.SetByDottedPath("config.rules.type", base::Value(type));
|
||
+ state.SetByDottedPath("config.rules.bypass_rules", base::Value(rules.bypass_rules.ToString()));
|
||
+ state.SetByDottedPath("config.rules.reverse_bypass", base::Value(rules.reverse_bypass));
|
||
+}
|
||
+
|
||
+ProxyConfigMessageHandler::~ProxyConfigMessageHandler() {
|
||
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
|
||
+ !BrowserThread::IsThreadInitialized(BrowserThread::UI));
|
||
+ if (is_observing_) {
|
||
+ proxy_config_service_->RemoveObserver(this);
|
||
+ }
|
||
+ pref_proxy_config_tracker_->DetachFromPrefService();
|
||
+}
|
||
+
|
||
+void ProxyConfigMessageHandler::RegisterMessages() {
|
||
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||
+
|
||
+ web_ui()->RegisterMessageCallback(
|
||
+ "enableNotifyUIWithState",
|
||
+ base::BindRepeating(&ProxyConfigMessageHandler::OnEnableNotifyUIWithState,
|
||
+ base::Unretained(this)));
|
||
+ web_ui()->RegisterMessageCallback(
|
||
+ "apply",
|
||
+ base::BindRepeating(&ProxyConfigMessageHandler::OnApply,
|
||
+ base::Unretained(this)));
|
||
+ web_ui()->RegisterMessageCallback(
|
||
+ "clear",
|
||
+ base::BindRepeating(&ProxyConfigMessageHandler::OnClear,
|
||
+ base::Unretained(this)));
|
||
+}
|
||
+
|
||
+// The proxy configuration UI is not notified of state changes until this function runs.
|
||
+// After this function, OnProxyConfigChanged() will be called on all proxy state changes.
|
||
+void ProxyConfigMessageHandler::OnEnableNotifyUIWithState(
|
||
+ const base::Value::List& list) {
|
||
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||
+
|
||
+ if (!is_observing_) {
|
||
+ is_observing_ = true;
|
||
+ proxy_config_service_->AddObserver(this);
|
||
+ }
|
||
+
|
||
+ net::ProxyConfigWithAnnotation config;
|
||
+ auto availability = proxy_config_service_->GetLatestProxyConfig(&config);
|
||
+
|
||
+ const PrefService::Preference* const pref =
|
||
+ pref_service_->FindPreference(proxy_config::prefs::kProxy);
|
||
+ ProxyConfigDictionary proxy_dict(pref->GetValue()->GetDict().Clone());
|
||
+ ProxyPrefs::ProxyMode mode;
|
||
+ if (!proxy_dict.GetMode(&mode) || mode == ProxyPrefs::MODE_SYSTEM) {
|
||
+ availability = net::ProxyConfigService::CONFIG_UNSET;
|
||
+ }
|
||
+
|
||
+ OnProxyConfigChanged(config, availability);
|
||
+}
|
||
+
|
||
+void ProxyConfigMessageHandler::OnClear(const base::Value::List& list) {
|
||
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||
+
|
||
+ const base::Value::Dict cfg = ProxyConfigDictionary::CreateSystem();
|
||
+ pref_service_->SetDict(proxy_config::prefs::kProxy, cfg.Clone());
|
||
+ pref_service_->CommitPendingWrite();
|
||
+ OnEnableNotifyUIWithState(list);
|
||
+}
|
||
+
|
||
+void ProxyConfigMessageHandler::OnApply(const base::Value::List& list) {
|
||
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||
+
|
||
+ if ((list.size() != 1) || !list[0].is_dict()) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ const base::Value::Dict& config = list[0].GetDict();
|
||
+
|
||
+ if (config.FindBool("auto_detect").value_or(false)) {
|
||
+ apply(net::ProxyConfig::CreateAutoDetect());
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ if (const std::string* pacURL = config.FindString("pac_url")) {
|
||
+ absl::optional<bool> pacMandatory = config.FindBool("pac_mandatory");
|
||
+ auto proxyConfig = net::ProxyConfig::CreateFromCustomPacURL(
|
||
+ GURL(*pacURL));
|
||
+ proxyConfig.set_pac_mandatory(pacMandatory.value_or(false));
|
||
+ apply(proxyConfig);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ const base::Value::Dict* rules = config.FindDict("rules");
|
||
+ if (rules == nullptr)
|
||
+ return;
|
||
+
|
||
+ net::ProxyConfig proxyConfig;
|
||
+ bool readBypass = false;
|
||
+
|
||
+ const std::string* type = rules->FindString("type");
|
||
+ if (type == nullptr)
|
||
+ return;
|
||
+
|
||
+ if (*type == "list") {
|
||
+ const std::string* single_proxies = rules->FindString("single_proxies");
|
||
+ if (single_proxies == nullptr)
|
||
+ return;
|
||
+ proxyConfig.proxy_rules().type = net::ProxyConfig::ProxyRules::Type::PROXY_LIST;
|
||
+ proxyConfig.proxy_rules().single_proxies.SetFromPacString(*single_proxies);
|
||
+ readBypass = true;
|
||
+ } else if (*type == "list_per_scheme") {
|
||
+ const std::string* http = rules->FindString("proxies_for_http");
|
||
+ const std::string* https = rules->FindString("proxies_for_https");
|
||
+ const std::string* ftp = rules->FindString("proxies_for_ftp");
|
||
+ const std::string* fallback = rules->FindString("fallback_proxies");
|
||
+
|
||
+ proxyConfig.proxy_rules().type = net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
|
||
+ if (http)
|
||
+ proxyConfig.proxy_rules().proxies_for_http.SetFromPacString(*http);
|
||
+ if (https)
|
||
+ proxyConfig.proxy_rules().proxies_for_https.SetFromPacString(*https);
|
||
+ if (ftp)
|
||
+ proxyConfig.proxy_rules().proxies_for_ftp.SetFromPacString(*ftp);
|
||
+ if (fallback)
|
||
+ proxyConfig.proxy_rules().fallback_proxies.SetFromPacString(*fallback);
|
||
+ readBypass = true;
|
||
+ } else if (*type == "direct") {
|
||
+ proxyConfig.proxy_rules().type = net::ProxyConfig::ProxyRules::Type::EMPTY;
|
||
+ } else if (*type == "none") {
|
||
+ base::Value::List empty;
|
||
+ OnClear(empty);
|
||
+ return;
|
||
+ } else {
|
||
+ // invalid type
|
||
+ LOG(WARNING) << "invalid proxy configuration type";
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ // bypass rules and reverse flag are common to both list types of proxy rules
|
||
+ if (readBypass) {
|
||
+ const std::string* bypass_rules = rules->FindString("bypass_rules");
|
||
+ if (bypass_rules == nullptr)
|
||
+ return;
|
||
+
|
||
+ absl::optional<bool> reverse_bypass = rules->FindBool("reverse_bypass");
|
||
+
|
||
+ proxyConfig.proxy_rules().bypass_rules.ParseFromString(*bypass_rules);
|
||
+ proxyConfig.proxy_rules().reverse_bypass = reverse_bypass.value_or(false);
|
||
+ }
|
||
+
|
||
+ apply(proxyConfig);
|
||
+}
|
||
+
|
||
+void ProxyConfigMessageHandler::apply(const net::ProxyConfig& proxyConfig) {
|
||
+ if (proxyConfig.auto_detect()) {
|
||
+ const base::Value::Dict cfg = ProxyConfigDictionary::CreateAutoDetect();
|
||
+ pref_service_->SetDict(proxy_config::prefs::kProxy, cfg.Clone());
|
||
+ } else if (proxyConfig.has_pac_url()) {
|
||
+ const base::Value::Dict cfg = ProxyConfigDictionary::CreatePacScript(proxyConfig.pac_url().spec(), proxyConfig.pac_mandatory());
|
||
+ pref_service_->SetDict(proxy_config::prefs::kProxy, cfg.Clone());
|
||
+ } else if (proxyConfig.proxy_rules().type == net::ProxyConfig::ProxyRules::Type::EMPTY) {
|
||
+ const base::Value::Dict cfg = ProxyConfigDictionary::CreateDirect();
|
||
+ pref_service_->SetDict(proxy_config::prefs::kProxy, cfg.Clone());
|
||
+ } else {
|
||
+ auto proxyRulesAsString = proxyConfig.proxy_rules().ToString();
|
||
+ auto bypassRulesAsString = proxyConfig.proxy_rules().bypass_rules.ToString();
|
||
+
|
||
+ // fixed servers
|
||
+ const base::Value::Dict cfg = ProxyConfigDictionary::CreateFixedServers(proxyRulesAsString,
|
||
+ bypassRulesAsString, proxyConfig.proxy_rules().reverse_bypass);
|
||
+ pref_service_->SetDict(proxy_config::prefs::kProxy, cfg.Clone());
|
||
+ }
|
||
+ pref_service_->CommitPendingWrite();
|
||
+
|
||
+ base::Value::List empty;
|
||
+ OnEnableNotifyUIWithState(empty);
|
||
+}
|
||
+
|
||
+} // namespace
|
||
+
|
||
+ProxyConfigUI::ProxyConfigUI(content::WebUI* web_ui) : WebUIController(web_ui) {
|
||
+ Profile* profile = Profile::FromWebUI(web_ui);
|
||
+
|
||
+ web_ui->AddMessageHandler(std::make_unique<ProxyConfigMessageHandler>(profile));
|
||
+
|
||
+ // Set up the chrome://proxy/ source.
|
||
+ content::WebUIDataSource* source =
|
||
+ content::WebUIDataSource::CreateAndAdd(web_ui->GetWebContents()->GetBrowserContext(),
|
||
+ chrome::kChromeUIProxyConfigHost);
|
||
+
|
||
+ source->UseStringsJs();
|
||
+ source->AddResourcePath("proxy_config.js", IDR_PROXY_CONFIG_JS);
|
||
+ source->SetDefaultResource(IDR_PROXY_CONFIG_HTML);
|
||
+}
|
||
diff --git a/chrome/browser/ui/webui/proxy_config_ui.h b/chrome/browser/ui/webui/proxy_config_ui.h
|
||
new file mode 100644
|
||
--- /dev/null
|
||
+++ b/chrome/browser/ui/webui/proxy_config_ui.h
|
||
@@ -0,0 +1,31 @@
|
||
+/*
|
||
+ This file is part of Bromite.
|
||
+
|
||
+ Bromite is free software: you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation, either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ Bromite is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
|
||
+*/
|
||
+
|
||
+#ifndef CHROME_BROWSER_UI_WEBUI_PROXY_CONFIG_UI_H_
|
||
+#define CHROME_BROWSER_UI_WEBUI_PROXY_CONFIG_UI_H_
|
||
+
|
||
+#include "content/public/browser/web_ui_controller.h"
|
||
+
|
||
+// The WebUI for chrome://proxy/.
|
||
+class ProxyConfigUI : public content::WebUIController {
|
||
+ public:
|
||
+ ProxyConfigUI(const ProxyConfigUI&) = delete;
|
||
+ ProxyConfigUI& operator=(const ProxyConfigUI&) = delete;
|
||
+ explicit ProxyConfigUI(content::WebUI* web_ui);
|
||
+};
|
||
+
|
||
+#endif // CHROME_BROWSER_UI_WEBUI_PROXY_CONFIG_UI_H_
|
||
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
|
||
--- a/chrome/common/webui_url_constants.cc
|
||
+++ b/chrome/common/webui_url_constants.cc
|
||
@@ -56,6 +56,8 @@ const char kChromeUICertificateViewerHost[] = "view-cert";
|
||
const char kChromeUICertificateViewerURL[] = "chrome://view-cert/";
|
||
const char kChromeUIChromeSigninHost[] = "chrome-signin";
|
||
const char kChromeUIChromeSigninURL[] = "chrome://chrome-signin/";
|
||
+const char kChromeUIProxyConfigHost[] = "proxy";
|
||
+const char kChromeUIProxyConfigURL[] = "chrome://proxy/";
|
||
const char kChromeUIChromeURLsHost[] = "chrome-urls";
|
||
const char kChromeUIChromeURLsURL[] = "chrome://chrome-urls/";
|
||
const char kChromeUIComponentsHost[] = "components";
|
||
@@ -450,6 +452,7 @@ bool IsSystemWebUIHost(base::StringPiece host) {
|
||
kChromeUILockScreenNetworkHost,
|
||
kChromeUILockScreenStartReauthHost,
|
||
kChromeUIMobileSetupHost,
|
||
+ kChromeUIProxyConfigHost,
|
||
kChromeUIMultiDeviceSetupHost,
|
||
kChromeUINetworkHost,
|
||
kChromeUINotificationTesterHost,
|
||
@@ -759,6 +762,7 @@ const char* const kChromeHostURLs[] = {
|
||
#if !BUILDFLAG(IS_ANDROID)
|
||
#if !BUILDFLAG(IS_CHROMEOS)
|
||
kChromeUIAppLauncherPageHost,
|
||
+ kChromeUIProxyConfigHost,
|
||
#endif
|
||
kChromeUIBookmarksHost,
|
||
kChromeUIDownloadsHost,
|
||
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
|
||
--- a/chrome/common/webui_url_constants.h
|
||
+++ b/chrome/common/webui_url_constants.h
|
||
@@ -142,6 +142,8 @@ extern const char kChromeUINTPTilesInternalsHost[];
|
||
extern const char kChromeUINaClHost[];
|
||
extern const char kChromeUINetExportHost[];
|
||
extern const char kChromeUINetExportURL[];
|
||
+extern const char kChromeUIProxyConfigHost[];
|
||
+extern const char kChromeUIProxyConfigURL[];
|
||
extern const char kChromeUINetInternalsHost[];
|
||
extern const char kChromeUINetInternalsURL[];
|
||
extern const char kChromeUINewTabHost[];
|
||
diff --git a/components/proxy_config/pref_proxy_config_tracker_impl.cc b/components/proxy_config/pref_proxy_config_tracker_impl.cc
|
||
--- a/components/proxy_config/pref_proxy_config_tracker_impl.cc
|
||
+++ b/components/proxy_config/pref_proxy_config_tracker_impl.cc
|
||
@@ -244,14 +244,14 @@ PrefProxyConfigTrackerImpl::GetEffectiveProxyConfig(
|
||
// static
|
||
void PrefProxyConfigTrackerImpl::RegisterPrefs(PrefRegistrySimple* registry) {
|
||
registry->RegisterDictionaryPref(proxy_config::prefs::kProxy,
|
||
- ProxyConfigDictionary::CreateSystem());
|
||
+ ProxyConfigDictionary::CreateDirect());
|
||
}
|
||
|
||
// static
|
||
void PrefProxyConfigTrackerImpl::RegisterProfilePrefs(
|
||
PrefRegistrySimple* registry) {
|
||
registry->RegisterDictionaryPref(proxy_config::prefs::kProxy,
|
||
- ProxyConfigDictionary::CreateSystem());
|
||
+ ProxyConfigDictionary::CreateDirect());
|
||
registry->RegisterBooleanPref(proxy_config::prefs::kUseSharedProxies, false);
|
||
}
|
||
|
||
@@ -388,6 +388,7 @@ bool PrefProxyConfigTrackerImpl::PrefConfigToNetConfig(
|
||
if (proxy_dict.GetBypassList(&proxy_bypass)) {
|
||
proxy_config.proxy_rules().bypass_rules.ParseFromString(proxy_bypass);
|
||
}
|
||
+ proxy_config.proxy_rules().reverse_bypass = proxy_dict.HasReverseBypass();
|
||
*config = net::ProxyConfigWithAnnotation(
|
||
proxy_config, kSettingsProxyConfigTrafficAnnotation);
|
||
return true;
|
||
diff --git a/components/proxy_config/proxy_config_dictionary.cc b/components/proxy_config/proxy_config_dictionary.cc
|
||
--- a/components/proxy_config/proxy_config_dictionary.cc
|
||
+++ b/components/proxy_config/proxy_config_dictionary.cc
|
||
@@ -30,6 +30,8 @@ const char kProxyPacMandatory[] = "pac_mandatory";
|
||
// String containing proxy bypass rules. For a specification of the
|
||
// expected syntax see net::ProxyBypassRules::ParseFromString().
|
||
const char kProxyBypassList[] = "bypass_list";
|
||
+// Boolean telling whether to reverse the meaning of the bypass list.
|
||
+const char kProxyReverseBypass[] = "reverse_bypass";
|
||
|
||
} // namespace
|
||
|
||
@@ -76,6 +78,14 @@ bool ProxyConfigDictionary::HasBypassList() const {
|
||
return dict_.Find(kProxyBypassList);
|
||
}
|
||
|
||
+bool ProxyConfigDictionary::HasReverseBypass() const {
|
||
+ const base::Value* value = dict_.Find(kProxyReverseBypass);
|
||
+ if (!value || !value->is_bool()) {
|
||
+ return false;
|
||
+ }
|
||
+ return value->GetBool();
|
||
+}
|
||
+
|
||
const base::Value::Dict& ProxyConfigDictionary::GetDictionary() const {
|
||
return dict_;
|
||
}
|
||
@@ -83,13 +93,13 @@ const base::Value::Dict& ProxyConfigDictionary::GetDictionary() const {
|
||
// static
|
||
base::Value::Dict ProxyConfigDictionary::CreateDirect() {
|
||
return CreateDictionary(ProxyPrefs::MODE_DIRECT, std::string(), false,
|
||
- std::string(), std::string());
|
||
+ std::string(), std::string(), false);
|
||
}
|
||
|
||
// static
|
||
base::Value::Dict ProxyConfigDictionary::CreateAutoDetect() {
|
||
return CreateDictionary(ProxyPrefs::MODE_AUTO_DETECT, std::string(), false,
|
||
- std::string(), std::string());
|
||
+ std::string(), std::string(), false);
|
||
}
|
||
|
||
// static
|
||
@@ -97,16 +107,17 @@ base::Value::Dict ProxyConfigDictionary::CreatePacScript(
|
||
const std::string& pac_url,
|
||
bool pac_mandatory) {
|
||
return CreateDictionary(ProxyPrefs::MODE_PAC_SCRIPT, pac_url, pac_mandatory,
|
||
- std::string(), std::string());
|
||
+ std::string(), std::string(), false);
|
||
}
|
||
|
||
// static
|
||
base::Value::Dict ProxyConfigDictionary::CreateFixedServers(
|
||
const std::string& proxy_server,
|
||
- const std::string& bypass_list) {
|
||
+ const std::string& bypass_list,
|
||
+ bool reverse_bypass) {
|
||
if (!proxy_server.empty()) {
|
||
return CreateDictionary(ProxyPrefs::MODE_FIXED_SERVERS, std::string(),
|
||
- false, proxy_server, bypass_list);
|
||
+ false, proxy_server, bypass_list, reverse_bypass);
|
||
} else {
|
||
return CreateDirect();
|
||
}
|
||
@@ -115,7 +126,7 @@ base::Value::Dict ProxyConfigDictionary::CreateFixedServers(
|
||
// static
|
||
base::Value::Dict ProxyConfigDictionary::CreateSystem() {
|
||
return CreateDictionary(ProxyPrefs::MODE_SYSTEM, std::string(), false,
|
||
- std::string(), std::string());
|
||
+ std::string(), std::string(), false);
|
||
}
|
||
|
||
// static
|
||
@@ -124,7 +135,8 @@ base::Value::Dict ProxyConfigDictionary::CreateDictionary(
|
||
const std::string& pac_url,
|
||
bool pac_mandatory,
|
||
const std::string& proxy_server,
|
||
- const std::string& bypass_list) {
|
||
+ const std::string& bypass_list,
|
||
+ bool reverse_bypass) {
|
||
base::Value::Dict dict;
|
||
dict.Set(kProxyMode, base::Value(ProxyModeToString(mode)));
|
||
if (!pac_url.empty()) {
|
||
@@ -133,8 +145,10 @@ base::Value::Dict ProxyConfigDictionary::CreateDictionary(
|
||
}
|
||
if (!proxy_server.empty())
|
||
dict.Set(kProxyServer, base::Value(proxy_server));
|
||
- if (!bypass_list.empty())
|
||
+ if (!bypass_list.empty()) {
|
||
dict.Set(kProxyBypassList, base::Value(bypass_list));
|
||
+ dict.Set(kProxyReverseBypass, base::Value(reverse_bypass));
|
||
+ }
|
||
return dict;
|
||
}
|
||
|
||
diff --git a/components/proxy_config/proxy_config_dictionary.h b/components/proxy_config/proxy_config_dictionary.h
|
||
--- a/components/proxy_config/proxy_config_dictionary.h
|
||
+++ b/components/proxy_config/proxy_config_dictionary.h
|
||
@@ -42,6 +42,7 @@ class PROXY_CONFIG_EXPORT ProxyConfigDictionary {
|
||
bool GetProxyServer(std::string* out) const;
|
||
bool GetBypassList(std::string* out) const;
|
||
bool HasBypassList() const;
|
||
+ bool HasReverseBypass() const;
|
||
|
||
const base::Value::Dict& GetDictionary() const;
|
||
|
||
@@ -50,7 +51,8 @@ class PROXY_CONFIG_EXPORT ProxyConfigDictionary {
|
||
static base::Value::Dict CreatePacScript(const std::string& pac_url,
|
||
bool pac_mandatory);
|
||
static base::Value::Dict CreateFixedServers(const std::string& proxy_server,
|
||
- const std::string& bypass_list);
|
||
+ const std::string& bypass_list,
|
||
+ bool reverse_bypass);
|
||
static base::Value::Dict CreateSystem();
|
||
|
||
// Encodes the proxy server as "<url-scheme>=<proxy-scheme>://<proxy>".
|
||
@@ -66,7 +68,8 @@ class PROXY_CONFIG_EXPORT ProxyConfigDictionary {
|
||
const std::string& pac_url,
|
||
bool pac_mandatory,
|
||
const std::string& proxy_server,
|
||
- const std::string& bypass_list);
|
||
+ const std::string& bypass_list,
|
||
+ bool reverse_bypass);
|
||
|
||
base::Value::Dict dict_;
|
||
};
|
||
diff --git a/components/proxy_config/proxy_policy_handler.cc b/components/proxy_config/proxy_policy_handler.cc
|
||
--- a/components/proxy_config/proxy_policy_handler.cc
|
||
+++ b/components/proxy_config/proxy_policy_handler.cc
|
||
@@ -262,7 +262,7 @@ void ProxyPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
|
||
set_proxy_pref_value(ProxyConfigDictionary::CreateFixedServers(
|
||
server->GetString(), bypass_list && bypass_list->is_string()
|
||
? bypass_list->GetString()
|
||
- : std::string()));
|
||
+ : std::string(), false));
|
||
}
|
||
break;
|
||
}
|
||
diff --git a/net/proxy_resolution/proxy_config.cc b/net/proxy_resolution/proxy_config.cc
|
||
--- a/net/proxy_resolution/proxy_config.cc
|
||
+++ b/net/proxy_resolution/proxy_config.cc
|
||
@@ -112,7 +112,7 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
|
||
&single_proxies,
|
||
ProxyServer::SCHEME_HTTP);
|
||
type = Type::PROXY_LIST;
|
||
- return;
|
||
+ continue;
|
||
}
|
||
|
||
// Trim whitespace off the url scheme.
|
||
@@ -143,6 +143,56 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
|
||
}
|
||
}
|
||
|
||
+std::string ProxyConfig::ProxyRules::ToString() const {
|
||
+ if (type == Type::EMPTY) {
|
||
+ return "";
|
||
+ }
|
||
+
|
||
+ // special case: a single proxy servers list specified
|
||
+ if (type == Type::PROXY_LIST) {
|
||
+ std::string proxy_list;
|
||
+ for (const ProxyServer& proxy_server :
|
||
+ single_proxies.GetAll()) {
|
||
+ proxy_list += ProxyServerToProxyUri(proxy_server) + ";";
|
||
+ }
|
||
+ // remove last semicolon
|
||
+ if (proxy_list.length() != 0 ) {
|
||
+ proxy_list.pop_back();
|
||
+ }
|
||
+ return proxy_list;
|
||
+ }
|
||
+
|
||
+ if (type != Type::PROXY_LIST_PER_SCHEME) {
|
||
+ NOTREACHED();
|
||
+ // Unexpected LIST with fallback, or other type values
|
||
+ return "";
|
||
+ }
|
||
+
|
||
+ // start to build a per-scheme list
|
||
+ std::string list;
|
||
+ for (const ProxyServer& proxy_server :
|
||
+ proxies_for_http.GetAll()) {
|
||
+ list += "http=" + ProxyServerToProxyUri(proxy_server) + ";";
|
||
+ }
|
||
+ for (const ProxyServer& proxy_server :
|
||
+ proxies_for_https.GetAll()) {
|
||
+ list += "https=" + ProxyServerToProxyUri(proxy_server) + ";";
|
||
+ }
|
||
+ for (const ProxyServer& proxy_server :
|
||
+ proxies_for_ftp.GetAll()) {
|
||
+ list += "ftp=" + ProxyServerToProxyUri(proxy_server) + ";";
|
||
+ }
|
||
+ for (const ProxyServer& proxy_server :
|
||
+ fallback_proxies.GetAll()) {
|
||
+ list += "socks=" + ProxyServerToProxyUri(proxy_server) + ";";
|
||
+ }
|
||
+ if (list.length() != 0 ) {
|
||
+ // remove last semicolon
|
||
+ list.pop_back();
|
||
+ }
|
||
+ return list;
|
||
+}
|
||
+
|
||
const ProxyList* ProxyConfig::ProxyRules::MapUrlSchemeToProxyList(
|
||
const std::string& url_scheme) const {
|
||
const ProxyList* proxy_server_list = const_cast<ProxyRules*>(this)->
|
||
diff --git a/net/proxy_resolution/proxy_config.h b/net/proxy_resolution/proxy_config.h
|
||
--- a/net/proxy_resolution/proxy_config.h
|
||
+++ b/net/proxy_resolution/proxy_config.h
|
||
@@ -103,6 +103,9 @@ class NET_EXPORT ProxyConfig {
|
||
// and use socks4://foopy2 for all other
|
||
// URLs.
|
||
void ParseFromString(const std::string& proxy_rules);
|
||
+ // Returns the proxy rules in a format that can be parsed by ParseFromString;
|
||
+ // all information except bypass rules is used.
|
||
+ std::string ToString() const;
|
||
|
||
// Returns one of {&proxies_for_http, &proxies_for_https, &proxies_for_ftp,
|
||
// &fallback_proxies}, or NULL if there is no proxy to use.
|
||
--
|
||
2.25.1
|