Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(598)

Side by Side Diff: net/detector.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/detector.h ('k') | net/detector_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2007-2010 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15
16 // TODO(omaha): move EnclosePath and UnenclosePath functions from path.h to
17 // string.h
18 // TODO(omaha): Firefox detector does not handle proxy bypass.
19
20 #include "omaha/net/detector.h"
21
22 #include "base/scoped_ptr.h"
23 #include "omaha/base/atl_regexp.h"
24 #include "omaha/base/browser_utils.h"
25 #include "omaha/base/constants.h"
26 #include "omaha/base/debug.h"
27 #include "omaha/base/file_reader.h"
28 #include "omaha/base/path.h"
29 #include "omaha/base/reg_key.h"
30 #include "omaha/base/safe_format.h"
31 #include "omaha/base/string.h"
32 #include "omaha/base/user_info.h"
33 #include "omaha/base/utils.h"
34 #include "omaha/base/time.h"
35 #include "omaha/net/http_client.h"
36 #include "omaha/net/network_config.h"
37
38 namespace omaha {
39
40 HRESULT RegistryOverrideProxyDetector::Detect(ProxyConfig* config) {
41 ASSERT1(config);
42 RegKey reg_key;
43 HRESULT hr = reg_key.Open(reg_path_, KEY_READ);
44 if (FAILED(hr)) {
45 return hr;
46 }
47 CString proxy_host;
48 hr = reg_key.GetValue(kRegValueProxyHost, &proxy_host);
49 if (FAILED(hr)) {
50 return hr;
51 }
52 DWORD proxy_port(0);
53 hr = reg_key.GetValue(kRegValueProxyPort, &proxy_port);
54 if (FAILED(hr)) {
55 return hr;
56 }
57 *config = ProxyConfig();
58 SafeCStringFormat(&config->proxy, _T("%s:%d"), proxy_host, proxy_port);
59 config->source = source();
60 config->priority = ProxyConfig::PROXY_PRIORITY_OVERRIDE;
61 return S_OK;
62 }
63
64 UpdateDevProxyDetector::UpdateDevProxyDetector()
65 : registry_detector_(MACHINE_REG_UPDATE_DEV) {
66 }
67
68 FirefoxProxyDetector::FirefoxProxyDetector()
69 : cached_prefs_last_modified_(0),
70 cached_config_(new ProxyConfig) {
71 }
72
73 HRESULT FirefoxProxyDetector::Detect(ProxyConfig* config) {
74 ASSERT1(config);
75
76 // The Firefox profile is not available when running as a local system.
77 if (user_info::IsRunningAsSystem()) {
78 return E_FAIL;
79 }
80
81 const TCHAR* const kFirefoxPrefsJsFile = _T("\\prefs.js");
82
83 CString name, path;
84 HRESULT hr = GetFirefoxDefaultProfile(&name, &path);
85 if (FAILED(hr)) {
86 return hr;
87 }
88 path.Append(kFirefoxPrefsJsFile);
89
90 // Has the current profile been modified? Check the name, path, and
91 // last modified time of the profile are the same as their cached values.
92 FILETIME filetime_last_modified = {0};
93 int64 last_modified = 0;
94 if (SUCCEEDED(File::GetFileTime(path,
95 NULL,
96 NULL,
97 &filetime_last_modified))) {
98 last_modified = FileTimeToInt64(filetime_last_modified);
99 }
100 if (name.CompareNoCase(cached_prefs_name_) == 0 &&
101 path.CompareNoCase(cached_prefs_file_path_) == 0 &&
102 last_modified == cached_prefs_last_modified_ &&
103 last_modified) {
104 NET_LOG(L4, (_T("[using FF cached profile][%s]"), path));
105 *config = *cached_config_;
106 return S_OK;
107 }
108
109 hr = ParsePrefsFile(name, path, config);
110 if (SUCCEEDED(hr) && last_modified) {
111 // If FireFox is the default brower, promotes its proxy priority.
112 BrowserType browser_type(BROWSER_UNKNOWN);
113 if (SUCCEEDED(GetDefaultBrowserType(&browser_type)) &&
114 browser_type == BROWSER_FIREFOX) {
115 config->priority = ProxyConfig::PROXY_PRIORITY_DEFAULT_BROWSER;
116 }
117 NET_LOG(L4, (_T("[cache FF profile][%s]"), path));
118 cached_prefs_name_ = name;
119 cached_prefs_file_path_ = path;
120 cached_prefs_last_modified_ = last_modified;
121 *cached_config_ = *config;
122 }
123 return hr;
124 }
125
126 // This is what the proxy configuration in Firefox looks like:
127 // user_pref("network.proxy.autoconfig_url", "http://wpad/wpad.dat");
128 // user_pref("network.proxy.ftp", "127.0.0.1");
129 // user_pref("network.proxy.ftp_port", 8888);
130 // user_pref("network.proxy.gopher", "127.0.0.1");
131 // user_pref("network.proxy.gopher_port", 8888);
132 // user_pref("network.proxy.http", "127.0.0.1");
133 // user_pref("network.proxy.http_port", 8888);
134 // user_pref("network.proxy.share_proxy_settings", true);
135 // user_pref("network.proxy.socks", "127.0.0.1");
136 // user_pref("network.proxy.socks_port", 8888);
137 // user_pref("network.proxy.ssl", "127.0.0.1");
138 // user_pref("network.proxy.ssl_port", 8888);
139 // user_pref("network.proxy.type", 4);
140 HRESULT FirefoxProxyDetector::ParsePrefsFile(const TCHAR* name,
141 const TCHAR* file_path,
142 ProxyConfig* config) {
143 ASSERT1(name);
144 ASSERT1(file_path);
145 ASSERT1(config);
146
147 *config = ProxyConfig();
148 config->source = source();
149
150 // TODO(omaha): implement optimization not to parse the file again if it
151 // did not change.
152 UNREFERENCED_PARAMETER(name);
153
154 // There were issues in production where the code fails to allocate
155 // the 1MB memory buffer as it had been initially requested by a previous
156 // version of the code.
157 //
158 // The assert below is somehow flaky but useful to detect the unlikely cases
159 // when the prefs file can't be opened.
160 FileReader prefs_file;
161 const size_t kBufferSize = 0x10000; // 64KB buffer.
162 HRESULT hr = prefs_file.Init(file_path, kBufferSize);
163 ASSERT1(SUCCEEDED(hr));
164 if (FAILED(hr)) {
165 return hr;
166 }
167
168 CString proxy_type;
169 CString proxy_config_url;
170 CString proxy_http_host;
171 CString proxy_http_port;
172 CString proxy_ssl_host;
173 CString proxy_ssl_port;
174
175 // For each line in the prefs.js, try to parse the proxy information out.
176 char line[1024] = {0};
177 while (SUCCEEDED(prefs_file.ReadLineAnsi(arraysize(line), line))) {
178 ParsePrefsLine(line,
179 &proxy_type,
180 &proxy_config_url,
181 &proxy_http_host,
182 &proxy_http_port,
183 &proxy_ssl_host,
184 &proxy_ssl_port);
185 }
186
187 // The default in FireFox is direct connection so it may be that the
188 // network.proxy.type is missing.
189 int type = PROXY_TYPE_NO_PROXY;
190 if (!proxy_type.IsEmpty() &&
191 !String_StringToDecimalIntChecked(proxy_type, &type)) {
192 return E_UNEXPECTED;
193 }
194
195 // Direct connection.
196 if (type == PROXY_TYPE_NO_PROXY) {
197 return S_OK;
198 }
199
200 // We look for both proxy auto-detect and proxy config url, to emulate
201 // the IE behavior, where when the auto-detect fails it defaults to the
202 // auto config url. Firefox remembers the auto config url even if not used,
203 // so it might not hurt to try it out.
204 if (type & PROXY_TYPE_AUTO_DETECT) {
205 config->auto_detect = true;
206 }
207 if ((type & PROXY_TYPE_AUTO_CONFIG_URL) && !proxy_config_url.IsEmpty()) {
208 UnenclosePath(&proxy_config_url);
209 config->auto_config_url = proxy_config_url;
210 }
211
212 // Named proxy.
213 if (!(type & PROXY_TYPE_NAMED_PROXY)) {
214 return S_OK;
215 }
216
217 CString proxy;
218 hr = BuildProxyString(proxy_http_host,
219 proxy_http_port,
220 proxy_ssl_host,
221 proxy_ssl_port,
222 &proxy);
223 if (FAILED(hr)) {
224 return hr;
225 }
226
227 config->proxy = proxy;
228 return S_OK;
229 }
230
231 HRESULT FirefoxProxyDetector::BuildProxyString(const CString& proxy_http_host,
232 const CString& http_port,
233 const CString& proxy_ssl_host,
234 const CString& ssl_port,
235 CString* proxy) {
236 ASSERT1(proxy);
237
238 CString http_host = proxy_http_host;
239 CString ssl_host = proxy_ssl_host;
240
241 // The host names in the prefs file are strings literals.
242 UnenclosePath(&http_host);
243 UnenclosePath(&ssl_host);
244
245 // Validate the port values.
246 if (!http_port.IsEmpty()) {
247 int http_port_num = 0;
248 if (!String_StringToDecimalIntChecked(http_port, &http_port_num) ||
249 http_port_num <= 0 &&
250 http_port_num > INTERNET_MAX_PORT_NUMBER_VALUE) {
251 return E_INVALIDARG;
252 }
253 }
254 if (!ssl_port.IsEmpty()) {
255 int ssl_port_num = 0;
256 if (!String_StringToDecimalIntChecked(ssl_port, &ssl_port_num) ||
257 ssl_port_num <= 0 ||
258 ssl_port_num > INTERNET_MAX_PORT_NUMBER_VALUE) {
259 return E_INVALIDARG;
260 }
261 }
262
263 // Format the proxy string.
264 CString str;
265 if (!http_host.IsEmpty()) {
266 SafeCStringAppendFormat(&str, _T("http=%s"), http_host);
267 if (!http_port.IsEmpty()) {
268 SafeCStringAppendFormat(&str, _T(":%s"), http_port);
269 }
270 }
271 if (!ssl_host.IsEmpty()) {
272 // Append a separator if needed.
273 if (!str.IsEmpty()) {
274 str += _T(';');
275 }
276 SafeCStringAppendFormat(&str, _T("https=%s"), ssl_host);
277 if (!ssl_port.IsEmpty()) {
278 SafeCStringAppendFormat(&str, _T(":%s"), ssl_port);
279 }
280 }
281
282 *proxy = str;
283 return S_OK;
284 }
285
286 // Parses a line from the prefs.js. An example of line to parse is:
287 // user_pref("network.proxy.http", "foo");
288 void FirefoxProxyDetector::ParsePrefsLine(const char* ansi_line,
289 CString* proxy_type,
290 CString* proxy_config_url,
291 CString* proxy_http_host,
292 CString* proxy_http_port,
293 CString* proxy_ssl_host,
294 CString* proxy_ssl_port) {
295 // Skip the lines that do not contain "network.proxy" to speed up the
296 // parsing. This is important for large prefs files.
297 if (strstr(ansi_line, "network.proxy.") == NULL) {
298 return;
299 }
300
301 AtlRE proxy_type_regex(_T("^\\b*user_pref\\b*\\(\\b*\\\"network\\.proxy\\.type \\\"\\b*,\\b*{\\d+}\\)"), false); // NOLINT
302 AtlRE proxy_config_url_regex(_T("^\\b*user_pref\\b*\\(\\b*\\\"network\\.proxy\ \.autoconfig_url\\\"\\b*,\\b*{\\q}\\)"), false); // NOLINT
303 AtlRE proxy_http_host_regex(_T("^\\b*user_pref\\b*\\(\\b*\\\"network\\.proxy\\ .http\\\"\\b*,\\b*{\\q}\\)"), false); // NOLINT
304 AtlRE proxy_http_port_regex(_T("^\\b*user_pref\\b*\\(\\b*\\\"network\\.proxy\\ .http_port\\\"\\b*,\\b*{\\d+}\\)"), false); // NOLINT
305 AtlRE proxy_ssl_host_regex(_T("^\\b*user_pref\\b*\\(\\b*\\\"network\\.proxy\\. ssl\\\"\\b*,\\b*{\\q}\\)"), false); // NOLINT
306 AtlRE proxy_ssl_port_regex(_T("^\\b*user_pref\\b*\\(\\b*\\\"network\\.proxy\\. ssl_port\\\"\\b*,\\b*{\\d+}\\)"), false); // NOLINT
307
308 CString line(ansi_line);
309 if (AtlRE::PartialMatch(line, proxy_type_regex, proxy_type)) {
310 return;
311 }
312 if (AtlRE::PartialMatch(line, proxy_config_url_regex, proxy_config_url)) {
313 return;
314 }
315 if (AtlRE::PartialMatch(line, proxy_http_host_regex, proxy_http_host)) {
316 return;
317 }
318 if (AtlRE::PartialMatch(line, proxy_http_port_regex, proxy_http_port)) {
319 return;
320 }
321 if (AtlRE::PartialMatch(line, proxy_ssl_host_regex, proxy_ssl_host)) {
322 return;
323 }
324 if (AtlRE::PartialMatch(line, proxy_ssl_port_regex, proxy_ssl_port)) {
325 return;
326 }
327 }
328
329 HRESULT DefaultProxyDetector::Detect(ProxyConfig* config) {
330 ASSERT1(config);
331
332 scoped_ptr<HttpClient> http_client(CreateHttpClient());
333
334 // We expect to be able to instantiate either of the http clients.
335 ASSERT1(http_client.get());
336 if (!http_client.get()) {
337 return E_UNEXPECTED;
338 }
339 HRESULT hr = http_client->Initialize();
340 if (FAILED(hr)) {
341 return hr;
342 }
343 HttpClient::ProxyInfo proxy_info = {0};
344 hr = http_client->GetDefaultProxyConfiguration(&proxy_info);
345 if (FAILED(hr)) {
346 return hr;
347 }
348 if (proxy_info.access_type == WINHTTP_ACCESS_TYPE_NAMED_PROXY) {
349 ProxyConfig proxy_config;
350 proxy_config.source = source();
351 proxy_config.proxy = proxy_info.proxy;
352 proxy_config.proxy_bypass = proxy_info.proxy_bypass;
353 *config = proxy_config;
354 return S_OK;
355 } else {
356 return E_FAIL;
357 }
358 }
359
360 HRESULT IEProxyDetector::Detect(ProxyConfig* config) {
361 ASSERT1(config);
362
363 // Internet Explorer proxy configuration is not available when running as
364 // local system.
365 if (user_info::IsRunningAsSystem()) {
366 return E_FAIL;
367 }
368
369 scoped_ptr<HttpClient> http_client(CreateHttpClient());
370
371 // We expect to be able to instantiate either of the http clients.
372 ASSERT1(http_client.get());
373 if (!http_client.get()) {
374 return E_UNEXPECTED;
375 }
376 HRESULT hr = http_client->Initialize();
377 if (FAILED(hr)) {
378 return hr;
379 }
380 HttpClient::CurrentUserIEProxyConfig ie_proxy_config = {0};
381 hr = http_client->GetIEProxyConfiguration(&ie_proxy_config);
382 if (FAILED(hr)) {
383 return hr;
384 }
385 config->source = source();
386 config->auto_detect = ie_proxy_config.auto_detect;
387 config->auto_config_url = ie_proxy_config.auto_config_url;
388 config->proxy = ie_proxy_config.proxy;
389 config->proxy_bypass = ie_proxy_config.proxy_bypass;
390
391 // If IE is the default brower, promotes its proxy priority.
392 BrowserType browser_type(BROWSER_UNKNOWN);
393 if (SUCCEEDED(GetDefaultBrowserType(&browser_type)) &&
394 browser_type == BROWSER_IE) {
395 config->priority = ProxyConfig::PROXY_PRIORITY_DEFAULT_BROWSER;
396 }
397
398 ::GlobalFree(const_cast<TCHAR*>(ie_proxy_config.auto_config_url));
399 ::GlobalFree(const_cast<TCHAR*>(ie_proxy_config.proxy));
400 ::GlobalFree(const_cast<TCHAR*>(ie_proxy_config.proxy_bypass));
401
402 return S_OK;
403 };
404
405 } // namespace omaha
406
OLDNEW
« no previous file with comments | « net/detector.h ('k') | net/detector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698