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

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