Add-a-proxy-configuration-page.patch 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303
  1. From: csagan5 <32685696+csagan5@users.noreply.github.com>
  2. Date: Thu, 29 Mar 2018 00:43:32 +0200
  3. Subject: Add a proxy configuration page
  4. Accessible from proxy settings and chrome://proxy
  5. Allows to use a PAC script URL, automatic configuration and explicit proxy
  6. settings.
  7. Offer auto-complete for the proxy page URL.
  8. ---
  9. chrome/android/java/res/values/values.xml | 3 +
  10. .../java/res/xml/privacy_preferences.xml | 4 +
  11. .../privacy/settings/PrivacySettings.java | 5 +-
  12. .../chrome_autocomplete_provider_client.cc | 2 +
  13. chrome/browser/browser_resources.grd | 6 +
  14. .../prefs/chrome_command_line_pref_store.cc | 2 +-
  15. chrome/browser/resources/proxy_config.css | 61 +++
  16. chrome/browser/resources/proxy_config.html | 80 ++++
  17. chrome/browser/resources/proxy_config.js | 262 +++++++++++
  18. chrome/browser/ui/BUILD.gn | 2 +
  19. .../webui/chrome_web_ui_controller_factory.cc | 3 +
  20. chrome/browser/ui/webui/proxy_config_ui.cc | 413 ++++++++++++++++++
  21. chrome/browser/ui/webui/proxy_config_ui.h | 33 ++
  22. chrome/common/webui_url_constants.cc | 4 +
  23. chrome/common/webui_url_constants.h | 2 +
  24. .../core/browser/proxy_policy_handler.cc | 2 +-
  25. .../pref_proxy_config_tracker_impl.cc | 1 +
  26. .../proxy_config/proxy_config_dictionary.cc | 30 +-
  27. .../proxy_config/proxy_config_dictionary.h | 7 +-
  28. net/proxy_resolution/proxy_config.cc | 52 ++-
  29. net/proxy_resolution/proxy_config.h | 3 +
  30. 21 files changed, 963 insertions(+), 14 deletions(-)
  31. create mode 100644 chrome/browser/resources/proxy_config.css
  32. create mode 100644 chrome/browser/resources/proxy_config.html
  33. create mode 100644 chrome/browser/resources/proxy_config.js
  34. create mode 100644 chrome/browser/ui/webui/proxy_config_ui.cc
  35. create mode 100644 chrome/browser/ui/webui/proxy_config_ui.h
  36. diff --git a/chrome/android/java/res/values/values.xml b/chrome/android/java/res/values/values.xml
  37. --- a/chrome/android/java/res/values/values.xml
  38. +++ b/chrome/android/java/res/values/values.xml
  39. @@ -32,6 +32,9 @@
  40. <integer name="reload_button_level_reload">0</integer>
  41. <integer name="reload_button_level_stop">1</integer>
  42. + <string name="proxy_title">Proxy configuration</string>
  43. + <string name="proxy_url">chrome://proxy</string>
  44. +
  45. <!-- Download InfoBar animation. -->
  46. <integer name="download_infobar_sweep_up_delay">500</integer>
  47. <integer name="download_infobar_sweep_down_delay">800</integer>
  48. diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/android/java/res/xml/privacy_preferences.xml
  49. --- a/chrome/android/java/res/xml/privacy_preferences.xml
  50. +++ b/chrome/android/java/res/xml/privacy_preferences.xml
  51. @@ -7,6 +7,10 @@
  52. xmlns:app="http://schemas.android.com/apk/res-auto"
  53. android:orderingFromXml="false">
  54. + <org.chromium.chrome.browser.about_settings.HyperlinkPreference
  55. + android:key="proxy"
  56. + android:title="@string/proxy_title"
  57. + app:url="@string/proxy_url" />
  58. <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
  59. android:key="can_make_payment"
  60. android:title="@string/can_make_payment_title"
  61. 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
  62. --- a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
  63. +++ b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
  64. @@ -51,12 +51,15 @@ public class PrivacySettings
  65. private static final String PREF_CLEAR_BROWSING_DATA = "clear_browsing_data";
  66. private static final String PREF_ALWAYS_INCOGNITO = "always_incognito";
  67. public static final String PREF_ALLOW_CUSTOM_TAB_INTENTS = "allow_custom_tab_intents";
  68. + private static final String PREF_PROXY_OPTIONS = "proxy";
  69. +
  70. private static final String[] NEW_PRIVACY_PREFERENCE_ORDER = {PREF_CLEAR_BROWSING_DATA,
  71. PREF_CAN_MAKE_PAYMENT, PREF_NETWORK_PREDICTIONS,
  72. PREF_SECURE_DNS, PREF_DO_NOT_TRACK,
  73. PREF_ALWAYS_INCOGNITO,
  74. PREF_ALLOW_CUSTOM_TAB_INTENTS,
  75. - PREF_CLOSE_TABS_ON_EXIT
  76. + PREF_CLOSE_TABS_ON_EXIT,
  77. + PREF_PROXY_OPTIONS
  78. };
  79. private ManagedPreferenceDelegate mManagedPreferenceDelegate;
  80. diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
  81. --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
  82. +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
  83. @@ -331,6 +331,8 @@ ChromeAutocompleteProviderClient::GetBuiltinsToProvideAsUserTypes() {
  84. std::vector<base::string16> builtins_to_provide;
  85. builtins_to_provide.push_back(
  86. base::ASCIIToUTF16(chrome::kChromeUIFlagsURL));
  87. + builtins_to_provide.push_back(
  88. + base::ASCIIToUTF16(chrome::kChromeUIProxyConfigURL));
  89. builtins_to_provide.push_back(
  90. base::ASCIIToUTF16(chrome::kChromeUIChromeURLsURL));
  91. #if !defined(OS_ANDROID)
  92. diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
  93. --- a/chrome/browser/browser_resources.grd
  94. +++ b/chrome/browser/browser_resources.grd
  95. @@ -128,6 +128,12 @@
  96. <include name="IDR_VIDEO_PLAYER_JS" file="resources\video_tutorials\video_player.js" type="BINDATA" />
  97. </if>
  98. + <!-- Bromite Proxy Configuration UI -->
  99. + <if expr="is_android">
  100. + <include name="IDR_PROXY_CONFIG_HTML" file="resources\proxy_config.html" flattenhtml="true" type="BINDATA" compress="gzip" />
  101. + <include name="IDR_PROXY_CONFIG_JS" file="resources\proxy_config.js" type="BINDATA" compress="gzip" />
  102. + </if>
  103. +
  104. <if expr="not is_android">
  105. <!-- New Tab Page -->
  106. <part file="resources/local_ntp/icons.grdp" />
  107. diff --git a/chrome/browser/prefs/chrome_command_line_pref_store.cc b/chrome/browser/prefs/chrome_command_line_pref_store.cc
  108. --- a/chrome/browser/prefs/chrome_command_line_pref_store.cc
  109. +++ b/chrome/browser/prefs/chrome_command_line_pref_store.cc
  110. @@ -155,7 +155,7 @@ void ChromeCommandLinePrefStore::ApplyProxyMode() {
  111. SetValue(
  112. proxy_config::prefs::kProxy,
  113. std::make_unique<base::Value>(ProxyConfigDictionary::CreateFixedServers(
  114. - proxy_server, bypass_list)),
  115. + proxy_server, bypass_list, false)),
  116. WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
  117. }
  118. }
  119. diff --git a/chrome/browser/resources/proxy_config.css b/chrome/browser/resources/proxy_config.css
  120. new file mode 100644
  121. --- /dev/null
  122. +++ b/chrome/browser/resources/proxy_config.css
  123. @@ -0,0 +1,61 @@
  124. +/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
  125. + * Use of this source code is governed by a BSD-style license that can be
  126. + * found in the LICENSE file.
  127. + */
  128. +
  129. +body {
  130. + font-size: 80%;
  131. + margin: 1em;
  132. +}
  133. +
  134. +#main-container {
  135. + max-width: 60em;
  136. + margin-left: auto;
  137. + margin-right: auto;
  138. +}
  139. +
  140. +button {
  141. + display: block;
  142. + font-size: 110%;
  143. + font-weight: bold;
  144. + margin: 10px auto;
  145. + padding: 1em;
  146. + width: 15em;
  147. +}
  148. +
  149. +h2 {
  150. + color: #546E7A;
  151. + font-weight: normal;
  152. + font-size: 170%;
  153. + margin-bottom: 1.5em;
  154. +}
  155. +
  156. +.radio-button-div {
  157. + margin: 7px auto;
  158. +}
  159. +
  160. +.warning {
  161. + color: red;
  162. + font-size: 90%;
  163. +}
  164. +
  165. +.section-container {
  166. + margin-top: 2em;
  167. +}
  168. +
  169. +#file-path-logging,
  170. +#file-path-stopped {
  171. + font-family: monospace;
  172. +}
  173. +
  174. +.outline-box {
  175. + margin-top: 2em;
  176. + border: 1px solid #ababab;
  177. + padding: 0.5em;
  178. + line-height: 1.5em;
  179. +}
  180. +
  181. +textarea {
  182. + width: 95%;
  183. + height: 4em;
  184. +}
  185. diff --git a/chrome/browser/resources/proxy_config.html b/chrome/browser/resources/proxy_config.html
  186. new file mode 100644
  187. --- /dev/null
  188. +++ b/chrome/browser/resources/proxy_config.html
  189. @@ -0,0 +1,80 @@
  190. +<!doctype html>
  191. +<html>
  192. +<head>
  193. +<meta charset="utf-8">
  194. +<if expr="is_android">
  195. +<meta name="viewport" content="width=device-width">
  196. +</if>
  197. +
  198. +<if expr="is_ios">
  199. +<!-- TODO(crbug.com/487000): Remove this once injected by web. -->
  200. +<script src="chrome://resources/js/ios/web_ui.js"></script>
  201. +</if>
  202. +
  203. +<script src="chrome://resources/js/assert.js"></script>
  204. +<script src="chrome://resources/js/util.js"></script>
  205. +<script src="chrome://resources/js/cr.js"></script>
  206. +<script src="chrome://proxy/proxy_config.js"></script>
  207. +<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
  208. +<link rel="stylesheet" href="proxy_config.css">
  209. +<title>Proxy configuration</title>
  210. +</head>
  211. +<body>
  212. + <div id="main-container">
  213. + <!--
  214. + =========================================================================
  215. + View for "pending" state.
  216. + * Only visible briefly, if at all
  217. + =========================================================================
  218. + -->
  219. + <div id="state-pending">
  220. + <h2>Proxy configuration</h2>
  221. + Loading...
  222. + </div>
  223. +
  224. + <!--
  225. + =========================================================================
  226. + View for "available" and "unset" states.
  227. + * Has controls to change or reset proxy configuration.
  228. + =========================================================================
  229. + -->
  230. + <div id="state-main" hidden>
  231. + <h2>Proxy configuration</h2>
  232. + <button id="reset">Reset</button>
  233. + <div class="section-container">
  234. + Reset will update the displayed configuration to match the one currently in use.
  235. + </div>
  236. + <div class="section-container">
  237. + <input type="radio" id="empty" name="mode" value="empty"><label for="empty">System Default</label><br/>
  238. + <input type="radio" id="direct" name="mode" value="direct"><label for="direct">Direct</label><br/>
  239. + <input type="radio" id="auto-detect" name="mode" value="auto-detect"><label for="auto-detect">Auto-detect (WPAD DHCP/DNS)</label><br/>
  240. + <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>
  241. + <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>
  242. + <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>):
  243. + <textarea id="single-proxies"></textarea>
  244. + </label><br/>
  245. + <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/>
  246. + <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/>
  247. + <textarea id="http-proxies"></textarea></label><br/>
  248. + <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/>
  249. + <textarea id="https-proxies"></textarea></label><br/>
  250. + <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/>
  251. + <textarea id="ftp-proxies"></textarea></label><br/>
  252. + <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/>
  253. + <textarea id="fallback-proxies"></textarea></label>
  254. + <div class="outline-box">
  255. + 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/>
  256. + <textarea id="bypass-rules"></textarea><br/>
  257. + <input type="checkbox" id="reverse-bypass" name="reverse-bypass"><label for="reverse-bypass">Reverse the meaning of bypass rules</label>
  258. + </div>
  259. + </div>
  260. + <button id="apply">Apply</button>
  261. + <button id="clear">Clear</button>
  262. + <div class="section-container">
  263. + Clicking on Clear will remove any proxy configuration preference currently in effect.
  264. + </div>
  265. + </div>
  266. +
  267. + </div>
  268. +</body>
  269. +</html>
  270. diff --git a/chrome/browser/resources/proxy_config.js b/chrome/browser/resources/proxy_config.js
  271. new file mode 100644
  272. --- /dev/null
  273. +++ b/chrome/browser/resources/proxy_config.js
  274. @@ -0,0 +1,262 @@
  275. +/*
  276. + This file is part of Bromite.
  277. +
  278. + Bromite is free software: you can redistribute it and/or modify
  279. + it under the terms of the GNU General Public License as published by
  280. + the Free Software Foundation, either version 3 of the License, or
  281. + (at your option) any later version.
  282. +
  283. + Bromite is distributed in the hope that it will be useful,
  284. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  285. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  286. + GNU General Public License for more details.
  287. +
  288. + You should have received a copy of the GNU General Public License
  289. + along with Bromite. If not, see <https://www.gnu.org/licenses/>.
  290. +*/
  291. +
  292. +/**
  293. + * Main entry point called once the page has loaded.
  294. + */
  295. +function onLoad() {
  296. + ProxyConfigView.getInstance();
  297. +}
  298. +
  299. +document.addEventListener('DOMContentLoaded', onLoad);
  300. +
  301. +/**
  302. + * This class handles the presentation of the proxy-config view. Used as a
  303. + * singleton.
  304. + */
  305. +var ProxyConfigView = (function() {
  306. + 'use strict';
  307. +
  308. + // --------------------------------------------------------------------------
  309. +
  310. + var kIdStateDivUninitialized = 'state-pending';
  311. + var kIdStateDivMain = 'state-main';
  312. + var kIdApplyButton = 'apply';
  313. + var kIdResetButton = 'reset';
  314. + var kIdClearButton = 'clear';
  315. +
  316. + var kIdModeEmpty = 'empty';
  317. + var kIdModeDirect = 'direct';
  318. + var kIdModeAutoDetect = 'auto-detect';
  319. + var kIdModeUsePacURL = 'use-pac-url';
  320. +
  321. + var kIdModeUseSingleList = 'use-single-list';
  322. + var kIdModeUseListPerScheme = 'use-list-per-scheme';
  323. +
  324. + var kIdPacURL = 'pac-url';
  325. + var kIdPacMandatory = 'pac-mandatory';
  326. + var kIdBypassRules = 'bypass-rules';
  327. + var kIdReverseBypass = 'reverse-bypass';
  328. + var kIdSingleProxies = 'single-proxies';
  329. + var kIdHttpProxies = 'http-proxies';
  330. + var kIdHttpsProxies = 'https-proxies';
  331. + var kIdFtpProxies = 'ftp-proxies';
  332. + var kIdFallbackProxies = 'fallback-proxies';
  333. +
  334. + /**
  335. + * @constructor
  336. + */
  337. + function ProxyConfigView() {
  338. + this.currentConfig = null;
  339. +
  340. + $(kIdResetButton).onclick = this.onReset_.bind(this);
  341. + $(kIdApplyButton).onclick = this.onApply_.bind(this);
  342. + $(kIdClearButton).onclick = this.onClear_.bind(this);
  343. +
  344. + // Tell ProxyConfigMessageHandler to notify the UI of future state changes
  345. + // from this point on.
  346. + chrome.send('enableNotifyUIWithState');
  347. + }
  348. +
  349. + cr.addSingletonGetter(ProxyConfigView);
  350. +
  351. + ProxyConfigView.prototype = {
  352. + /**
  353. + * Updates the UI to reflect the current state. The state transitions are
  354. + * sent by the browser controller (ProxyConfigMessageHandler):
  355. + *
  356. + * * PENDING - This is the initial state when proxy configuration is opened
  357. + * for the first time, or there was an error during initialization.
  358. + * This state is short-lived and likely not observed; will
  359. + * immediately transition to AVAILABLE).
  360. + *
  361. + * * AVAILABLE - The reported proxy configuration is active; this state is entered
  362. + * on first page load (or right after PENDING if configuration was not
  363. + * available on page load) and every time some configuration change was applied.
  364. + * It can transition to either AVAILABLE or UNSET.
  365. + *
  366. + * * UNSET - Proxy configuration is reported to be currently not set.
  367. + *
  368. + */
  369. + onProxyConfigChanged: function(state) {
  370. + // may happen only on first load; leave the loading page as another update is expected
  371. + // when proxy configuration has finished loading
  372. + if (state.pending) {
  373. + $(kIdStateDivMain).hidden = true;
  374. + $(kIdStateDivUninitialized).hidden = false;
  375. + return;
  376. + }
  377. +
  378. + if (!state.hasOwnProperty('config')) {
  379. + // configuration has been unset, use an empty one
  380. + this.eraseCurrentConfig_();
  381. + } else {
  382. + // save the configuration as current and reset all controls to it
  383. + this.currentConfig = state.config;
  384. + }
  385. +
  386. + this.renderConfig_();
  387. +
  388. + this.toggleButtons_(false);
  389. + $(kIdStateDivUninitialized).hidden = true;
  390. + $(kIdStateDivMain).hidden = false;
  391. + },
  392. +
  393. + /**
  394. + * Set current configuration to an empty (default) one.
  395. + */
  396. + eraseCurrentConfig_: function() {
  397. + this.currentConfig = {
  398. + "auto_detect": false,
  399. + "pending": false,
  400. + "rules": {
  401. + "bypass_rules": "",
  402. + "reverse_bypass": false,
  403. + "type": "none"
  404. + }
  405. + };
  406. + },
  407. +
  408. + /**
  409. + * Serialize the user-selected configuration in an object.
  410. + */
  411. + serializeConfig_: function() {
  412. + if ($(kIdModeEmpty).checked) {
  413. + return {
  414. + "auto_detect": false,
  415. + "rules": {
  416. + "type": "none"
  417. + }
  418. + };
  419. + } else if ($(kIdModeDirect).checked) {
  420. + return {
  421. + "auto_detect": false,
  422. + "rules": {
  423. + "type": "direct"
  424. + }
  425. + };
  426. + } else if ($(kIdModeAutoDetect).checked) {
  427. + return {
  428. + "auto_detect": true
  429. + };
  430. + } else if ($(kIdModeUsePacURL).checked) {
  431. + return {
  432. + "auto_detect": false,
  433. + "pac_url": $(kIdPacURL).value.trim(),
  434. + "pac_mandatory": $(kIdPacMandatory).checked
  435. + };
  436. + } else if ($(kIdModeUseListPerScheme).checked || $(kIdModeUseSingleList).checked) {
  437. + var config = {
  438. + "auto_detect": false,
  439. + "rules": {
  440. + "bypass_rules": $(kIdBypassRules).value.trim(),
  441. + "reverse_bypass": $(kIdReverseBypass).checked,
  442. + "type": "list"
  443. + }
  444. + };
  445. +
  446. + if ($(kIdModeUseListPerScheme).checked) {
  447. + config.rules.type = "list_per_scheme";
  448. +
  449. + config.rules.proxies_for_http = $(kIdHttpProxies).value.trim();
  450. + config.rules.proxies_for_https = $(kIdHttpsProxies).value.trim();
  451. + config.rules.proxies_for_ftp = $(kIdFtpProxies).value.trim();
  452. + config.rules.fallback_proxies = $(kIdFallbackProxies).value.trim();
  453. + } else {
  454. + config.rules.single_proxies = $(kIdSingleProxies).value.trim();
  455. + }
  456. +
  457. + return config;
  458. + }
  459. +
  460. + throw new Error('unexpected mode');
  461. + },
  462. +
  463. + /**
  464. + * Updates the UI to display the current proxy configuration.
  465. + */
  466. + renderConfig_: function() {
  467. + if (this.currentConfig.auto_detect) {
  468. + $(kIdModeAutoDetect).checked = true;
  469. + } else if (this.currentConfig.rules.type == "none") {
  470. + $(kIdModeEmpty).checked = true;
  471. + } else if (this.currentConfig.rules.type == "direct") {
  472. + $(kIdModeDirect).checked = true;
  473. + } else if (this.currentConfig.hasOwnProperty('pac_url')) {
  474. + $(kIdPacURL).value = this.currentConfig.pac_url;
  475. + $(kIdPacMandatory).checked = this.currentConfig.pac_mandatory;
  476. + $(kIdModeUsePacURL).checked = true;
  477. + } else {
  478. + $(kIdBypassRules).value = this.currentConfig.rules.bypass_rules;
  479. + $(kIdReverseBypass).checked = this.currentConfig.rules.reverse_bypass;
  480. +
  481. + switch (this.currentConfig.rules.type) {
  482. + case "list":
  483. + $(kIdModeUseSingleList).checked = true;
  484. + $(kIdSingleProxies).value = this.currentConfig.rules.single_proxies;
  485. + break;
  486. + case "list_per_scheme":
  487. + $(kIdModeUseListPerScheme).checked = true;
  488. + $(kIdHttpProxies).value = this.currentConfig.rules.proxies_for_http;
  489. + $(kIdHttpsProxies).value = this.currentConfig.rules.proxies_for_https;
  490. + $(kIdFtpProxies).value = this.currentConfig.rules.proxies_for_ftp;
  491. + $(kIdFallbackProxies).value = this.currentConfig.rules.fallback_proxies;
  492. + break;
  493. + }
  494. + }
  495. + },
  496. +
  497. + /**
  498. + * Apply the configuration currently displayed.
  499. + */
  500. + onApply_: function() {
  501. + var config = this.serializeConfig_();
  502. +
  503. + // disable buttons; will be enabled back when UI receives a state update
  504. + this.toggleButtons_(true);
  505. + chrome.send('apply', [config]);
  506. + },
  507. +
  508. + /**
  509. + * Apply the configuration currently displayed.
  510. + */
  511. + onClear_: function() {
  512. + // disable buttons; will be enabled back when UI receives a state update
  513. + this.toggleButtons_(true);
  514. + this.eraseCurrentConfig_();
  515. + chrome.send('clear', []);
  516. + },
  517. +
  518. + /**
  519. + * Toggle the disabled status of the action buttons.
  520. + */
  521. + toggleButtons_: function(disabled) {
  522. + $(kIdApplyButton).disabled = disabled;
  523. + $(kIdResetButton).disabled = disabled;
  524. + $(kIdClearButton).disabled = disabled;
  525. + },
  526. +
  527. + /**
  528. + * Reset currently displayed configuration to the last known configuration in use.
  529. + */
  530. + onReset_: function() {
  531. + this.renderConfig_();
  532. + }
  533. + };
  534. +
  535. + return ProxyConfigView;
  536. +})();
  537. diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
  538. --- a/chrome/browser/ui/BUILD.gn
  539. +++ b/chrome/browser/ui/BUILD.gn
  540. @@ -250,6 +250,8 @@ static_library("ui") {
  541. "webui/metrics_handler.h",
  542. "webui/net_export_ui.cc",
  543. "webui/net_export_ui.h",
  544. + "webui/proxy_config_ui.cc",
  545. + "webui/proxy_config_ui.h",
  546. "webui/net_internals/net_internals_ui.cc",
  547. "webui/net_internals/net_internals_ui.h",
  548. "webui/ntp_tiles_internals_ui.cc",
  549. diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
  550. --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
  551. +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
  552. @@ -63,6 +63,7 @@
  553. #include "chrome/browser/ui/webui/omnibox/omnibox_ui.h"
  554. #include "chrome/browser/ui/webui/policy_ui.h"
  555. #include "chrome/browser/ui/webui/predictors/predictors_ui.h"
  556. +#include "chrome/browser/ui/webui/proxy_config_ui.h"
  557. #include "chrome/browser/ui/webui/quota_internals/quota_internals_ui.h"
  558. #include "chrome/browser/ui/webui/settings/settings_ui.h"
  559. #include "chrome/browser/ui/webui/settings_utils.h"
  560. @@ -555,6 +556,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
  561. return &NewWebUI<MemoryInternalsUI>;
  562. if (url.host_piece() == chrome::kChromeUINetExportHost)
  563. return &NewWebUI<NetExportUI>;
  564. + if (url.host_piece() == chrome::kChromeUIProxyConfigHost)
  565. + return &NewWebUI<ProxyConfigUI>;
  566. if (url.host_piece() == chrome::kChromeUINetInternalsHost)
  567. return &NewWebUI<NetInternalsUI>;
  568. if (url.host_piece() == chrome::kChromeUINTPTilesInternalsHost)
  569. diff --git a/chrome/browser/ui/webui/proxy_config_ui.cc b/chrome/browser/ui/webui/proxy_config_ui.cc
  570. new file mode 100644
  571. --- /dev/null
  572. +++ b/chrome/browser/ui/webui/proxy_config_ui.cc
  573. @@ -0,0 +1,413 @@
  574. +/*
  575. + This file is part of Bromite.
  576. +
  577. + Bromite is free software: you can redistribute it and/or modify
  578. + it under the terms of the GNU General Public License as published by
  579. + the Free Software Foundation, either version 3 of the License, or
  580. + (at your option) any later version.
  581. +
  582. + Bromite is distributed in the hope that it will be useful,
  583. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  584. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  585. + GNU General Public License for more details.
  586. +
  587. + You should have received a copy of the GNU General Public License
  588. + along with Bromite. If not, see <https://www.gnu.org/licenses/>.
  589. +*/
  590. +
  591. +#include "chrome/browser/ui/webui/proxy_config_ui.h"
  592. +
  593. +#include <stdint.h>
  594. +
  595. +#include <memory>
  596. +#include <string>
  597. +#include <vector>
  598. +
  599. +#include "base/bind.h"
  600. +#include "base/command_line.h"
  601. +#include "base/lazy_instance.h"
  602. +#include "base/macros.h"
  603. +#include "base/memory/ref_counted.h"
  604. +#include "base/scoped_observer.h"
  605. +#include "base/strings/string_util.h"
  606. +#include "base/strings/utf_string_conversions.h"
  607. +#include "base/values.h"
  608. +#include "chrome/browser/browser_process.h"
  609. +#include "chrome/browser/net/proxy_service_factory.h"
  610. +#include "chrome/browser/platform_util.h"
  611. +#include "chrome/browser/profiles/profile.h"
  612. +#include "chrome/common/url_constants.h"
  613. +#include "chrome/grit/browser_resources.h"
  614. +#include "components/prefs/pref_service.h"
  615. +#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
  616. +#include "components/proxy_config/proxy_config_pref_names.h"
  617. +#include "components/grit/components_resources.h"
  618. +#include "content/public/browser/browser_thread.h"
  619. +#include "content/public/browser/url_data_source.h"
  620. +#include "content/public/browser/web_contents.h"
  621. +#include "content/public/browser/web_ui.h"
  622. +#include "content/public/browser/web_ui_data_source.h"
  623. +#include "content/public/browser/web_ui_message_handler.h"
  624. +
  625. +#include "url/gurl.h"
  626. +
  627. +using content::BrowserThread;
  628. +using content::WebContents;
  629. +using content::WebUIMessageHandler;
  630. +
  631. +namespace {
  632. +
  633. +content::WebUIDataSource* CreateProxyConfigHTMLSource() {
  634. + content::WebUIDataSource* source =
  635. + content::WebUIDataSource::Create(chrome::kChromeUIProxyConfigHost);
  636. +
  637. + source->UseStringsJs();
  638. + source->AddResourcePath("proxy_config.js", IDR_PROXY_CONFIG_JS);
  639. + source->SetDefaultResource(IDR_PROXY_CONFIG_HTML);
  640. + return source;
  641. +}
  642. +
  643. +// This class receives javascript messages from the renderer.
  644. +// Note that the WebUI infrastructure runs on the UI thread, therefore all of
  645. +// this class's public methods are expected to run on the UI thread.
  646. +class ProxyConfigMessageHandler
  647. + : public WebUIMessageHandler,
  648. + public base::SupportsWeakPtr<ProxyConfigMessageHandler>,
  649. + public net::ProxyConfigService::Observer {
  650. + public:
  651. + // Creates a ProxyConfigMessageHandler that handles message exchanges with the Javascript
  652. + // side of the UI and gets proxy settings from the Web UI associated profile to watch for changes.
  653. + // The created ProxyConfigMessageHandler must be destroyed before |profile|.
  654. + ProxyConfigMessageHandler(Profile *profile);
  655. + ~ProxyConfigMessageHandler() override;
  656. +
  657. + // WebUIMessageHandler implementation.
  658. + void RegisterMessages() override;
  659. +
  660. + // Messages
  661. + void OnEnableNotifyUIWithState(const base::ListValue* list);
  662. + void OnApply(const base::ListValue* config);
  663. + void OnClear(const base::ListValue* config);
  664. +
  665. + // net::ProxyConfigService::Observer implementation:
  666. + // Calls ProxyConfigView.onProxyConfigChanged JavaScript function in the
  667. + // renderer.
  668. + void OnProxyConfigChanged(
  669. + const net::ProxyConfigWithAnnotation& config,
  670. + net::ProxyConfigService::ConfigAvailability availability) override;
  671. +
  672. + private:
  673. + // Not owned.
  674. + Profile *profile_;
  675. + std::unique_ptr<net::ProxyConfigService> proxy_config_service_;
  676. + // Monitors global and Profile prefs related to proxy configuration.
  677. + std::unique_ptr<PrefProxyConfigTracker> pref_proxy_config_tracker_;
  678. + bool is_observing_;
  679. +
  680. + void encodeConfig(const net::ProxyConfig& config, base::DictionaryValue& state);
  681. +
  682. + void apply(const net::ProxyConfig& config);
  683. +
  684. + base::WeakPtrFactory<ProxyConfigMessageHandler> weak_ptr_factory_;
  685. +
  686. + DISALLOW_COPY_AND_ASSIGN(ProxyConfigMessageHandler);
  687. +};
  688. +
  689. +ProxyConfigMessageHandler::ProxyConfigMessageHandler(Profile *profile)
  690. + :
  691. + weak_ptr_factory_(this) {
  692. +
  693. + // used to set new configuration preferences
  694. + profile_ = profile->GetOriginalProfile();
  695. + // observer is explicitly added only later in enableNotifyUIWithState
  696. + is_observing_ = false;
  697. +
  698. +// If this is the ChromeOS sign-in profile, just create the tracker from global
  699. +// state.
  700. +#if defined(OS_CHROMEOS)
  701. + if (chromeos::ProfileHelper::IsSigninProfile(profile)) {
  702. + pref_proxy_config_tracker_.reset(
  703. + ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
  704. + g_browser_process->local_state()));
  705. + }
  706. +#endif // defined(OS_CHROMEOS)
  707. +
  708. + if (!pref_proxy_config_tracker_) {
  709. + pref_proxy_config_tracker_ =
  710. + ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(
  711. + profile->GetPrefs(), g_browser_process->local_state());
  712. + }
  713. +
  714. + proxy_config_service_ = ProxyServiceFactory::CreateProxyConfigService(
  715. + pref_proxy_config_tracker_.get());
  716. +}
  717. +
  718. +void ProxyConfigMessageHandler::OnProxyConfigChanged(
  719. + const net::ProxyConfigWithAnnotation& config,
  720. + net::ProxyConfigService::ConfigAvailability availability) {
  721. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
  722. + !BrowserThread::IsThreadInitialized(BrowserThread::UI));
  723. +
  724. + base::DictionaryValue state;
  725. + bool pending = false;
  726. + switch (availability) {
  727. + case net::ProxyConfigService::CONFIG_VALID:
  728. + encodeConfig(config.value(), state);
  729. + break;
  730. + case net::ProxyConfigService::CONFIG_UNSET:
  731. + state.SetPath({"config", "rules", "type"}, base::Value("none"));
  732. + break;
  733. + case net::ProxyConfigService::CONFIG_PENDING:
  734. + //NOTE: this can only happen when triggered manually first time
  735. + pending = true;
  736. + break;
  737. + }
  738. + state.SetKey("pending", base::Value(pending));
  739. +
  740. + // call Javascript function
  741. + web_ui()->CallJavascriptFunctionUnsafe("ProxyConfigView.getInstance().onProxyConfigChanged",
  742. + *state.CreateDeepCopy());
  743. +}
  744. +
  745. +const std::string omitDirect(const std::string pacString) {
  746. + if (pacString == "DIRECT") {
  747. + return "";
  748. + }
  749. + return pacString;
  750. +}
  751. +
  752. +void ProxyConfigMessageHandler::encodeConfig(const net::ProxyConfig& config, base::DictionaryValue& state) {
  753. + // when automatic settings are enabled they take precedence over manual settings
  754. + // automatic settings are either the "auto-detect" flag or the existance of a PAC URL
  755. +
  756. + state.SetPath({"config", "auto_detect"}, base::Value(config.auto_detect()));
  757. +
  758. + if (config.has_pac_url()) {
  759. + state.SetPath({"config", "pac_url"}, base::Value(config.pac_url().spec()));
  760. + state.SetPath({"config", "pac_mandatory"}, base::Value(config.pac_mandatory()));
  761. + }
  762. +
  763. + auto rules = config.proxy_rules();
  764. + const char *type;
  765. + switch (rules.type) {
  766. + case net::ProxyConfig::ProxyRules::Type::EMPTY:
  767. + type = "direct";
  768. + break;
  769. + case net::ProxyConfig::ProxyRules::Type::PROXY_LIST:
  770. + type = "list";
  771. +
  772. + state.SetPath({"config", "rules", "single_proxies"}, base::Value(omitDirect(rules.single_proxies.ToPacString())));
  773. + break;
  774. + case net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME:
  775. + type = "list_per_scheme";
  776. +
  777. + state.SetPath({"config", "rules", "proxies_for_http"}, base::Value(omitDirect(rules.proxies_for_http.ToPacString())));
  778. + state.SetPath({"config", "rules", "proxies_for_https"}, base::Value(omitDirect(rules.proxies_for_https.ToPacString())));
  779. + state.SetPath({"config", "rules", "proxies_for_ftp"}, base::Value(omitDirect(rules.proxies_for_ftp.ToPacString())));
  780. + state.SetPath({"config", "rules", "fallback_proxies"}, base::Value(omitDirect(rules.fallback_proxies.ToPacString())));
  781. + break;
  782. + default:
  783. + NOTREACHED();
  784. + break;
  785. + }
  786. + state.SetPath({"config", "rules", "type"}, base::Value(type));
  787. + state.SetPath({"config", "rules", "bypass_rules"}, base::Value(rules.bypass_rules.ToString()));
  788. + state.SetPath({"config", "rules", "reverse_bypass"}, base::Value(rules.reverse_bypass));
  789. +}
  790. +
  791. +ProxyConfigMessageHandler::~ProxyConfigMessageHandler() {
  792. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
  793. + !BrowserThread::IsThreadInitialized(BrowserThread::UI));
  794. + if (is_observing_) {
  795. + proxy_config_service_->RemoveObserver(this);
  796. + }
  797. + pref_proxy_config_tracker_->DetachFromPrefService();
  798. +}
  799. +
  800. +void ProxyConfigMessageHandler::RegisterMessages() {
  801. + DCHECK_CURRENTLY_ON(BrowserThread::UI);
  802. +
  803. + web_ui()->RegisterMessageCallback(
  804. + "enableNotifyUIWithState",
  805. + base::BindRepeating(&ProxyConfigMessageHandler::OnEnableNotifyUIWithState,
  806. + base::Unretained(this)));
  807. + web_ui()->RegisterMessageCallback(
  808. + "apply",
  809. + base::BindRepeating(&ProxyConfigMessageHandler::OnApply,
  810. + base::Unretained(this)));
  811. + web_ui()->RegisterMessageCallback(
  812. + "clear",
  813. + base::BindRepeating(&ProxyConfigMessageHandler::OnClear,
  814. + base::Unretained(this)));
  815. +}
  816. +
  817. +// The proxy configuration UI is not notified of state changes until this function runs.
  818. +// After this function, OnProxyConfigChanged() will be called on all proxy state changes.
  819. +void ProxyConfigMessageHandler::OnEnableNotifyUIWithState(
  820. + const base::ListValue* list) {
  821. + DCHECK_CURRENTLY_ON(BrowserThread::UI);
  822. +
  823. + if (!is_observing_) {
  824. + is_observing_ = true;
  825. + proxy_config_service_->AddObserver(this);
  826. + }
  827. +
  828. + net::ProxyConfigWithAnnotation config;
  829. + auto availability = proxy_config_service_->GetLatestProxyConfig(&config);
  830. +
  831. + const base::DictionaryValue* dict =
  832. + profile_->GetPrefs()->GetDictionary(proxy_config::prefs::kProxy);
  833. + ProxyConfigDictionary proxy_dict(dict->Clone());
  834. + ProxyPrefs::ProxyMode mode;
  835. + if (!proxy_dict.GetMode(&mode) || mode == ProxyPrefs::MODE_SYSTEM) {
  836. + availability = net::ProxyConfigService::CONFIG_UNSET;
  837. + }
  838. +
  839. + OnProxyConfigChanged(config, availability);
  840. +}
  841. +
  842. +void ProxyConfigMessageHandler::OnClear(const base::ListValue* list) {
  843. + DCHECK_CURRENTLY_ON(BrowserThread::UI);
  844. +
  845. + const base::Value cfg = ProxyConfigDictionary::CreateSystem();
  846. + profile_->GetPrefs()->Set(proxy_config::prefs::kProxy, cfg);
  847. + profile_->GetPrefs()->CommitPendingWrite();
  848. + OnEnableNotifyUIWithState(nullptr);
  849. +}
  850. +
  851. +void ProxyConfigMessageHandler::OnApply(const base::ListValue* list) {
  852. + DCHECK_CURRENTLY_ON(BrowserThread::UI);
  853. +
  854. + if ((list->GetList().size() != 1) || !list->GetList()[0].is_dict()) {
  855. + return;
  856. + }
  857. +
  858. + const base::DictionaryValue* config = nullptr;
  859. + if (!list->GetDictionary(0, &config))
  860. + return;
  861. +
  862. + const base::Value *autoDetect = config->FindKeyOfType("auto_detect", base::Value::Type::BOOLEAN);
  863. + if (autoDetect == nullptr)
  864. + return;
  865. +
  866. + if (autoDetect->GetBool()) {
  867. + apply(net::ProxyConfig::CreateAutoDetect());
  868. + return;
  869. + }
  870. +
  871. + const base::Value *pacURL = config->FindKeyOfType("pac_url", base::Value::Type::STRING);
  872. + if (pacURL != nullptr) {
  873. + const base::Value *pacMandatory = config->FindKeyOfType("pac_mandatory", base::Value::Type::BOOLEAN);
  874. + if (pacMandatory == nullptr)
  875. + return;
  876. + auto proxyConfig = net::ProxyConfig::CreateFromCustomPacURL(GURL(pacURL->GetString()));
  877. + proxyConfig.set_pac_mandatory(pacMandatory->GetBool());
  878. +
  879. + apply(proxyConfig);
  880. + return;
  881. + }
  882. +
  883. + const base::Value *rules = config->FindKeyOfType("rules", base::Value::Type::DICTIONARY);
  884. + if (rules == nullptr)
  885. + return;
  886. +
  887. + const base::Value *type = rules->FindKeyOfType("type", base::Value::Type::STRING);
  888. + if (type == nullptr)
  889. + return;
  890. +
  891. + net::ProxyConfig proxyConfig;
  892. +
  893. + bool readBypass = false;
  894. +
  895. + auto t = type->GetString();
  896. + if (t == "list") {
  897. + const base::Value *single_proxies = rules->FindKeyOfType("single_proxies", base::Value::Type::STRING);
  898. + if (single_proxies == nullptr)
  899. + return;
  900. + proxyConfig.proxy_rules().type = net::ProxyConfig::ProxyRules::Type::PROXY_LIST;
  901. + proxyConfig.proxy_rules().single_proxies.SetFromPacString(single_proxies->GetString());
  902. + readBypass = true;
  903. + } else if (t == "list_per_scheme") {
  904. + const base::Value *http = rules->FindKeyOfType("proxies_for_http", base::Value::Type::STRING);
  905. + if (http == nullptr)
  906. + return;
  907. +
  908. + const base::Value *https = rules->FindKeyOfType("proxies_for_https", base::Value::Type::STRING);
  909. + if (https == nullptr)
  910. + return;
  911. +
  912. + const base::Value *ftp = rules->FindKeyOfType("proxies_for_ftp", base::Value::Type::STRING);
  913. + if (ftp == nullptr)
  914. + return;
  915. +
  916. + const base::Value *fallback = rules->FindKeyOfType("fallback_proxies", base::Value::Type::STRING);
  917. + if (fallback == nullptr)
  918. + return;
  919. +
  920. + proxyConfig.proxy_rules().type = net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME;
  921. + proxyConfig.proxy_rules().proxies_for_http.SetFromPacString(http->GetString());
  922. + proxyConfig.proxy_rules().proxies_for_https.SetFromPacString(https->GetString());
  923. + proxyConfig.proxy_rules().proxies_for_ftp.SetFromPacString(ftp->GetString());
  924. + proxyConfig.proxy_rules().fallback_proxies.SetFromPacString(fallback->GetString());
  925. + readBypass = true;
  926. + } else if (t == "direct") {
  927. + proxyConfig.proxy_rules().type = net::ProxyConfig::ProxyRules::Type::EMPTY;
  928. + } else if (t == "none") {
  929. + OnClear(nullptr);
  930. + return;
  931. + } else {
  932. + // invalid type
  933. + LOG(WARNING) << "invalid proxy configuration type";
  934. + return;
  935. + }
  936. +
  937. + // bypass rules and reverse flag are common to both list types of proxy rules
  938. + if (readBypass) {
  939. + const base::Value *bypass_rules = rules->FindKeyOfType("bypass_rules", base::Value::Type::STRING);
  940. + if (bypass_rules == nullptr)
  941. + return;
  942. +
  943. + const base::Value *reverse_bypass = rules->FindKeyOfType("reverse_bypass", base::Value::Type::BOOLEAN);
  944. + if (reverse_bypass == nullptr)
  945. + return;
  946. +
  947. + proxyConfig.proxy_rules().bypass_rules.ParseFromString(bypass_rules->GetString());
  948. + proxyConfig.proxy_rules().reverse_bypass = reverse_bypass->GetBool();
  949. + }
  950. +
  951. + apply(proxyConfig);
  952. +}
  953. +
  954. +void ProxyConfigMessageHandler::apply(const net::ProxyConfig& proxyConfig) {
  955. + if (proxyConfig.auto_detect()) {
  956. + const base::Value cfg = ProxyConfigDictionary::CreateAutoDetect();
  957. + profile_->GetPrefs()->Set(proxy_config::prefs::kProxy, cfg);
  958. + } else if (proxyConfig.has_pac_url()) {
  959. + const base::Value cfg = ProxyConfigDictionary::CreatePacScript(proxyConfig.pac_url().spec(), proxyConfig.pac_mandatory());
  960. + profile_->GetPrefs()->Set(proxy_config::prefs::kProxy, cfg);
  961. + } else if (proxyConfig.proxy_rules().type == net::ProxyConfig::ProxyRules::Type::EMPTY) {
  962. + const base::Value cfg = ProxyConfigDictionary::CreateDirect();
  963. + profile_->GetPrefs()->Set(proxy_config::prefs::kProxy, cfg);
  964. + } else {
  965. + auto proxyRulesAsString = proxyConfig.proxy_rules().ToString();
  966. + auto bypassRulesAsString = proxyConfig.proxy_rules().bypass_rules.ToString();
  967. +
  968. + // fixed servers
  969. + const base::Value cfg = ProxyConfigDictionary::CreateFixedServers(proxyRulesAsString,
  970. + bypassRulesAsString, proxyConfig.proxy_rules().reverse_bypass);
  971. + profile_->GetPrefs()->Set(proxy_config::prefs::kProxy, cfg);
  972. + }
  973. + profile_->GetPrefs()->CommitPendingWrite();
  974. + OnEnableNotifyUIWithState(nullptr);
  975. +}
  976. +
  977. +} // namespace
  978. +
  979. +ProxyConfigUI::ProxyConfigUI(content::WebUI* web_ui) : WebUIController(web_ui) {
  980. + Profile* profile = Profile::FromWebUI(web_ui);
  981. +
  982. + web_ui->AddMessageHandler(std::make_unique<ProxyConfigMessageHandler>(profile));
  983. +
  984. + // Set up the chrome://proxy/ source.
  985. + content::WebUIDataSource::Add(profile, CreateProxyConfigHTMLSource());
  986. +}
  987. diff --git a/chrome/browser/ui/webui/proxy_config_ui.h b/chrome/browser/ui/webui/proxy_config_ui.h
  988. new file mode 100644
  989. --- /dev/null
  990. +++ b/chrome/browser/ui/webui/proxy_config_ui.h
  991. @@ -0,0 +1,33 @@
  992. +/*
  993. + This file is part of Bromite.
  994. +
  995. + Bromite is free software: you can redistribute it and/or modify
  996. + it under the terms of the GNU General Public License as published by
  997. + the Free Software Foundation, either version 3 of the License, or
  998. + (at your option) any later version.
  999. +
  1000. + Bromite is distributed in the hope that it will be useful,
  1001. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  1002. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  1003. + GNU General Public License for more details.
  1004. +
  1005. + You should have received a copy of the GNU General Public License
  1006. + along with Bromite. If not, see <https://www.gnu.org/licenses/>.
  1007. +*/
  1008. +
  1009. +#ifndef CHROME_BROWSER_UI_WEBUI_PROXY_CONFIG_UI_H_
  1010. +#define CHROME_BROWSER_UI_WEBUI_PROXY_CONFIG_UI_H_
  1011. +
  1012. +#include "base/macros.h"
  1013. +#include "content/public/browser/web_ui_controller.h"
  1014. +
  1015. +// The WebUI for chrome://proxy/.
  1016. +class ProxyConfigUI : public content::WebUIController {
  1017. + public:
  1018. + explicit ProxyConfigUI(content::WebUI* web_ui);
  1019. +
  1020. + private:
  1021. + DISALLOW_COPY_AND_ASSIGN(ProxyConfigUI);
  1022. +};
  1023. +
  1024. +#endif // CHROME_BROWSER_UI_WEBUI_PROXY_CONFIG_UI_H_
  1025. diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
  1026. --- a/chrome/common/webui_url_constants.cc
  1027. +++ b/chrome/common/webui_url_constants.cc
  1028. @@ -32,6 +32,8 @@ const char kChromeUICertificateViewerHost[] = "view-cert";
  1029. const char kChromeUICertificateViewerURL[] = "chrome://view-cert/";
  1030. const char kChromeUIChromeSigninHost[] = "chrome-signin";
  1031. const char kChromeUIChromeSigninURL[] = "chrome://chrome-signin/";
  1032. +const char kChromeUIProxyConfigHost[] = "proxy";
  1033. +const char kChromeUIProxyConfigURL[] = "chrome://proxy/";
  1034. const char kChromeUIChromeURLsHost[] = "chrome-urls";
  1035. const char kChromeUIChromeURLsURL[] = "chrome://chrome-urls/";
  1036. const char kChromeUIComponentsHost[] = "components";
  1037. @@ -322,6 +324,7 @@ bool IsSystemWebUIHost(base::StringPiece host) {
  1038. kChromeUIMobileSetupHost,
  1039. kChromeUIMultiDeviceSetupHost,
  1040. kChromeUINetworkHost,
  1041. + kChromeUIProxyConfigHost,
  1042. kChromeUIOobeHost,
  1043. kChromeUIOSCreditsHost,
  1044. kChromeUIOSSettingsHost,
  1045. @@ -518,6 +521,7 @@ const char* const kChromeHostURLs[] = {
  1046. #if !defined(OS_ANDROID)
  1047. #if !defined(OS_CHROMEOS)
  1048. kChromeUIAppLauncherPageHost,
  1049. + kChromeUIProxyConfigHost,
  1050. #endif
  1051. kChromeUIBookmarksHost,
  1052. kChromeUIDownloadsHost,
  1053. diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
  1054. --- a/chrome/common/webui_url_constants.h
  1055. +++ b/chrome/common/webui_url_constants.h
  1056. @@ -117,6 +117,8 @@ extern const char kChromeUIMemoryInternalsHost[];
  1057. extern const char kChromeUINTPTilesInternalsHost[];
  1058. extern const char kChromeUINaClHost[];
  1059. extern const char kChromeUINetExportHost[];
  1060. +extern const char kChromeUIProxyConfigHost[];
  1061. +extern const char kChromeUIProxyConfigURL[];
  1062. extern const char kChromeUINetInternalsHost[];
  1063. extern const char kChromeUINetInternalsURL[];
  1064. extern const char kChromeUINewTabHost[];
  1065. diff --git a/components/policy/core/browser/proxy_policy_handler.cc b/components/policy/core/browser/proxy_policy_handler.cc
  1066. --- a/components/policy/core/browser/proxy_policy_handler.cc
  1067. +++ b/components/policy/core/browser/proxy_policy_handler.cc
  1068. @@ -200,7 +200,7 @@ void ProxyPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
  1069. bypass_list->GetAsString(&bypass_list_string);
  1070. prefs->SetValue(proxy_config::prefs::kProxy,
  1071. ProxyConfigDictionary::CreateFixedServers(
  1072. - proxy_server, bypass_list_string));
  1073. + proxy_server, bypass_list_string, false));
  1074. }
  1075. break;
  1076. }
  1077. diff --git a/components/proxy_config/pref_proxy_config_tracker_impl.cc b/components/proxy_config/pref_proxy_config_tracker_impl.cc
  1078. --- a/components/proxy_config/pref_proxy_config_tracker_impl.cc
  1079. +++ b/components/proxy_config/pref_proxy_config_tracker_impl.cc
  1080. @@ -380,6 +380,7 @@ bool PrefProxyConfigTrackerImpl::PrefConfigToNetConfig(
  1081. if (proxy_dict.GetBypassList(&proxy_bypass)) {
  1082. proxy_config.proxy_rules().bypass_rules.ParseFromString(proxy_bypass);
  1083. }
  1084. + proxy_config.proxy_rules().reverse_bypass = proxy_dict.HasReverseBypass();
  1085. *config = net::ProxyConfigWithAnnotation(
  1086. proxy_config, kSettingsProxyConfigTrafficAnnotation);
  1087. return true;
  1088. diff --git a/components/proxy_config/proxy_config_dictionary.cc b/components/proxy_config/proxy_config_dictionary.cc
  1089. --- a/components/proxy_config/proxy_config_dictionary.cc
  1090. +++ b/components/proxy_config/proxy_config_dictionary.cc
  1091. @@ -28,6 +28,8 @@ const char kProxyPacMandatory[] = "pac_mandatory";
  1092. // String containing proxy bypass rules. For a specification of the
  1093. // expected syntax see net::ProxyBypassRules::ParseFromString().
  1094. const char kProxyBypassList[] = "bypass_list";
  1095. +// Boolean telling whether to reverse the meaning of the bypass list.
  1096. +const char kProxyReverseBypass[] = "reverse_bypass";
  1097. } // namespace
  1098. @@ -72,6 +74,14 @@ bool ProxyConfigDictionary::HasBypassList() const {
  1099. return dict_.FindKey(kProxyBypassList);
  1100. }
  1101. +bool ProxyConfigDictionary::HasReverseBypass() const {
  1102. + const base::Value* value = dict_.FindKey(kProxyReverseBypass);
  1103. + if (!value || !value->is_bool()) {
  1104. + return false;
  1105. + }
  1106. + return value->GetBool();
  1107. +}
  1108. +
  1109. const base::Value& ProxyConfigDictionary::GetDictionary() const {
  1110. return dict_;
  1111. }
  1112. @@ -79,29 +89,30 @@ const base::Value& ProxyConfigDictionary::GetDictionary() const {
  1113. // static
  1114. base::Value ProxyConfigDictionary::CreateDirect() {
  1115. return CreateDictionary(ProxyPrefs::MODE_DIRECT, std::string(), false,
  1116. - std::string(), std::string());
  1117. + std::string(), std::string(), false);
  1118. }
  1119. // static
  1120. base::Value ProxyConfigDictionary::CreateAutoDetect() {
  1121. return CreateDictionary(ProxyPrefs::MODE_AUTO_DETECT, std::string(), false,
  1122. - std::string(), std::string());
  1123. + std::string(), std::string(), false);
  1124. }
  1125. // static
  1126. base::Value ProxyConfigDictionary::CreatePacScript(const std::string& pac_url,
  1127. bool pac_mandatory) {
  1128. return CreateDictionary(ProxyPrefs::MODE_PAC_SCRIPT, pac_url, pac_mandatory,
  1129. - std::string(), std::string());
  1130. + std::string(), std::string(), false);
  1131. }
  1132. // static
  1133. base::Value ProxyConfigDictionary::CreateFixedServers(
  1134. const std::string& proxy_server,
  1135. - const std::string& bypass_list) {
  1136. + const std::string& bypass_list,
  1137. + bool reverse_bypass) {
  1138. if (!proxy_server.empty()) {
  1139. return CreateDictionary(ProxyPrefs::MODE_FIXED_SERVERS, std::string(),
  1140. - false, proxy_server, bypass_list);
  1141. + false, proxy_server, bypass_list, reverse_bypass);
  1142. } else {
  1143. return CreateDirect();
  1144. }
  1145. @@ -110,7 +121,7 @@ base::Value ProxyConfigDictionary::CreateFixedServers(
  1146. // static
  1147. base::Value ProxyConfigDictionary::CreateSystem() {
  1148. return CreateDictionary(ProxyPrefs::MODE_SYSTEM, std::string(), false,
  1149. - std::string(), std::string());
  1150. + std::string(), std::string(), false);
  1151. }
  1152. // static
  1153. @@ -119,7 +130,8 @@ base::Value ProxyConfigDictionary::CreateDictionary(
  1154. const std::string& pac_url,
  1155. bool pac_mandatory,
  1156. const std::string& proxy_server,
  1157. - const std::string& bypass_list) {
  1158. + const std::string& bypass_list,
  1159. + bool reverse_bypass) {
  1160. base::Value dict(base::Value::Type::DICTIONARY);
  1161. dict.SetKey(kProxyMode, base::Value(ProxyModeToString(mode)));
  1162. if (!pac_url.empty()) {
  1163. @@ -128,8 +140,10 @@ base::Value ProxyConfigDictionary::CreateDictionary(
  1164. }
  1165. if (!proxy_server.empty())
  1166. dict.SetKey(kProxyServer, base::Value(proxy_server));
  1167. - if (!bypass_list.empty())
  1168. + if (!bypass_list.empty()) {
  1169. dict.SetKey(kProxyBypassList, base::Value(bypass_list));
  1170. + dict.SetKey(kProxyReverseBypass, base::Value(reverse_bypass));
  1171. + }
  1172. return dict;
  1173. }
  1174. diff --git a/components/proxy_config/proxy_config_dictionary.h b/components/proxy_config/proxy_config_dictionary.h
  1175. --- a/components/proxy_config/proxy_config_dictionary.h
  1176. +++ b/components/proxy_config/proxy_config_dictionary.h
  1177. @@ -38,6 +38,7 @@ class PROXY_CONFIG_EXPORT ProxyConfigDictionary {
  1178. bool GetProxyServer(std::string* out) const;
  1179. bool GetBypassList(std::string* out) const;
  1180. bool HasBypassList() const;
  1181. + bool HasReverseBypass() const;
  1182. const base::Value& GetDictionary() const;
  1183. @@ -46,7 +47,8 @@ class PROXY_CONFIG_EXPORT ProxyConfigDictionary {
  1184. static base::Value CreatePacScript(const std::string& pac_url,
  1185. bool pac_mandatory);
  1186. static base::Value CreateFixedServers(const std::string& proxy_server,
  1187. - const std::string& bypass_list);
  1188. + const std::string& bypass_list,
  1189. + bool reverse_bypass);
  1190. static base::Value CreateSystem();
  1191. // Encodes the proxy server as "<url-scheme>=<proxy-scheme>://<proxy>".
  1192. @@ -62,7 +64,8 @@ class PROXY_CONFIG_EXPORT ProxyConfigDictionary {
  1193. const std::string& pac_url,
  1194. bool pac_mandatory,
  1195. const std::string& proxy_server,
  1196. - const std::string& bypass_list);
  1197. + const std::string& bypass_list,
  1198. + bool reverse_bypass);
  1199. base::Value dict_;
  1200. diff --git a/net/proxy_resolution/proxy_config.cc b/net/proxy_resolution/proxy_config.cc
  1201. --- a/net/proxy_resolution/proxy_config.cc
  1202. +++ b/net/proxy_resolution/proxy_config.cc
  1203. @@ -110,7 +110,7 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
  1204. &single_proxies,
  1205. ProxyServer::SCHEME_HTTP);
  1206. type = Type::PROXY_LIST;
  1207. - return;
  1208. + continue;
  1209. }
  1210. // Trim whitespace off the url scheme.
  1211. @@ -141,6 +141,56 @@ void ProxyConfig::ProxyRules::ParseFromString(const std::string& proxy_rules) {
  1212. }
  1213. }
  1214. +std::string ProxyConfig::ProxyRules::ToString() const {
  1215. + if (type == Type::EMPTY) {
  1216. + return "";
  1217. + }
  1218. +
  1219. + // special case: a single proxy servers list specified
  1220. + if (type == Type::PROXY_LIST) {
  1221. + std::string proxy_list;
  1222. + for (const ProxyServer& proxy_server :
  1223. + single_proxies.GetAll()) {
  1224. + proxy_list += proxy_server.ToURI() + ";";
  1225. + }
  1226. + // remove last semicolon
  1227. + if (proxy_list.length() != 0 ) {
  1228. + proxy_list.pop_back();
  1229. + }
  1230. + return proxy_list;
  1231. + }
  1232. +
  1233. + if (type != Type::PROXY_LIST_PER_SCHEME) {
  1234. + NOTREACHED();
  1235. + // Unexpected LIST with fallback, or other type values
  1236. + return "";
  1237. + }
  1238. +
  1239. + // start to build a per-scheme list
  1240. + std::string list;
  1241. + for (const ProxyServer& proxy_server :
  1242. + proxies_for_http.GetAll()) {
  1243. + list += "http=" + proxy_server.ToURI() + ";";
  1244. + }
  1245. + for (const ProxyServer& proxy_server :
  1246. + proxies_for_https.GetAll()) {
  1247. + list += "https=" + proxy_server.ToURI() + ";";
  1248. + }
  1249. + for (const ProxyServer& proxy_server :
  1250. + proxies_for_ftp.GetAll()) {
  1251. + list += "ftp=" + proxy_server.ToURI() + ";";
  1252. + }
  1253. + for (const ProxyServer& proxy_server :
  1254. + fallback_proxies.GetAll()) {
  1255. + list += "socks=" + proxy_server.ToURI() + ";";
  1256. + }
  1257. + if (list.length() != 0 ) {
  1258. + // remove last semicolon
  1259. + list.pop_back();
  1260. + }
  1261. + return list;
  1262. +}
  1263. +
  1264. const ProxyList* ProxyConfig::ProxyRules::MapUrlSchemeToProxyList(
  1265. const std::string& url_scheme) const {
  1266. const ProxyList* proxy_server_list = const_cast<ProxyRules*>(this)->
  1267. diff --git a/net/proxy_resolution/proxy_config.h b/net/proxy_resolution/proxy_config.h
  1268. --- a/net/proxy_resolution/proxy_config.h
  1269. +++ b/net/proxy_resolution/proxy_config.h
  1270. @@ -103,6 +103,9 @@ class NET_EXPORT ProxyConfig {
  1271. // and use socks4://foopy2 for all other
  1272. // URLs.
  1273. void ParseFromString(const std::string& proxy_rules);
  1274. + // Returns the proxy rules in a format that can be parsed by ParseFromString;
  1275. + // all information except bypass rules is used.
  1276. + std::string ToString() const;
  1277. // Returns one of {&proxies_for_http, &proxies_for_https, &proxies_for_ftp,
  1278. // &fallback_proxies}, or NULL if there is no proxy to use.
  1279. --
  1280. 2.17.1