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

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