This is an automated email from the git hooks/post-receive script.
pierov pushed a commit to branch geckoview-99.0.1-11.0-1 in repository tor-browser.
commit fff38e7acb7916c7e9113eae5b52d2ab816a21db Author: Kershaw Chang kershaw@mozilla.com AuthorDate: Thu Jan 13 01:24:49 2022 +0000
Bug 1749501 - Revert bug 1392272, r=dragana a=RyanVM,dsmith
Differential Revision: https://phabricator.services.mozilla.com/D135702 --- .../windowsproxy/nsWindowsSystemProxySettings.cpp | 475 ++++----------------- 1 file changed, 93 insertions(+), 382 deletions(-)
diff --git a/toolkit/system/windowsproxy/nsWindowsSystemProxySettings.cpp b/toolkit/system/windowsproxy/nsWindowsSystemProxySettings.cpp index 8ac245f09ee8e..7921cb60a242f 100644 --- a/toolkit/system/windowsproxy/nsWindowsSystemProxySettings.cpp +++ b/toolkit/system/windowsproxy/nsWindowsSystemProxySettings.cpp @@ -6,52 +6,30 @@ #include <windows.h> #include <ras.h> #include <wininet.h> -#include <functional>
#include "mozilla/ArrayUtils.h" #include "mozilla/Attributes.h" -#include "mozilla/Atomics.h" #include "nsISystemProxySettings.h" #include "mozilla/Components.h" -#include "mozilla/Mutex.h" -#include "mozilla/Services.h" #include "mozilla/ProfilerLabels.h" -#include "mozilla/StaticPrefs_network.h" -#include "mozilla/Tokenizer.h" -#include "mozilla/Unused.h" -#include "nsComponentManagerUtils.h" -#include "nsIObserver.h" -#include "nsIObserverService.h" -#include "nsIWindowsRegKey.h" #include "nsPrintfCString.h" #include "nsNetCID.h" #include "nsThreadUtils.h" #include "prnetdb.h" #include "ProxyUtils.h" -#include "ProxyConfig.h"
-using namespace mozilla::net; - -class nsWindowsSystemProxySettings : public nsISystemProxySettings { +class nsWindowsSystemProxySettings final : public nsISystemProxySettings { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSISYSTEMPROXYSETTINGS
nsWindowsSystemProxySettings(){}; - virtual nsresult Init() { return NS_OK; }
- protected: - virtual ~nsWindowsSystemProxySettings() = default; + private: + ~nsWindowsSystemProxySettings(){};
bool MatchOverride(const nsACString& aHost); - bool MatchOverrideInternal(const nsACString& aHost, - const nsACString& aOverrideRule); bool PatternMatch(const nsACString& aHost, const nsACString& aOverride); - nsresult ReadProxyRules( - uint32_t aOptions, - const std::function<bool(uint32_t aFlags)>& aFlagsHandler, - const std::function<void(const nsACString& aRule, bool& aContinue)>& - aRuleHandler); };
NS_IMPL_ISUPPORTS(nsWindowsSystemProxySettings, nsISystemProxySettings) @@ -65,6 +43,18 @@ nsWindowsSystemProxySettings::GetMainThreadOnly(bool* aMainThreadOnly) { return NS_OK; }
+static void SetProxyResult(const char* aType, const nsACString& aHostPort, + nsACString& aResult) { + aResult.AssignASCII(aType); + aResult.Append(' '); + aResult.Append(aHostPort); +} + +static void SetProxyResultDirect(nsACString& aResult) { + // For whatever reason, a proxy is not to be used. + aResult.AssignLiteral("DIRECT"); +} + static nsresult ReadInternetOption(uint32_t aOption, uint32_t& aFlags, nsAString& aValue) { // Bug 1366133: InternetGetConnectedStateExW() may cause hangs @@ -103,82 +93,47 @@ static nsresult ReadInternetOption(uint32_t aOption, uint32_t& aFlags, return NS_OK; }
-bool nsWindowsSystemProxySettings::MatchOverrideInternal( - const nsACString& aHost, const nsACString& aOverrideRule) { - // Windows formats its proxy override list in the form: - // server;server;server where 'server' is a server name pattern or IP - // address, or "<local>". "<local>" must be translated to - // "localhost;127.0.0.1". - // In a server name pattern, a '*' character matches any substring and - // all other characters must match themselves; the whole pattern must match - // the whole hostname. - nsAutoCString host(aHost); - if (aOverrideRule.EqualsLiteral("<local>")) { - PRNetAddr addr; - bool isIpAddr = (PR_StringToNetAddr(host.get(), &addr) == PR_SUCCESS); - - // Don't use proxy for local hosts (plain hostname, no dots) - if (!isIpAddr && !host.Contains('.')) { - return true; - } - - if (host.EqualsLiteral("127.0.0.1") || host.EqualsLiteral("::1")) { - return true; - } - } else if (PatternMatch(host, aOverrideRule)) { - return true; - } - - return false; -} - bool nsWindowsSystemProxySettings::MatchOverride(const nsACString& aHost) { - nsAutoCString host(aHost); - bool foundMatch = false; - - auto flagHandler = [](uint32_t aFlags) { return true; }; - auto ruleHandler = [&](const nsACString& aOverrideRule, bool& aContinue) { - foundMatch = MatchOverrideInternal(aHost, aOverrideRule); - if (foundMatch) { - aContinue = false; - } - }; - - ReadProxyRules(INTERNET_PER_CONN_PROXY_BYPASS, flagHandler, ruleHandler); - return foundMatch; -} - -nsresult nsWindowsSystemProxySettings::ReadProxyRules( - uint32_t aOptions, - const std::function<bool(uint32_t aFlags)>& aFlagsHandler, - const std::function<void(const nsACString& aRule, bool& aContinue)>& - aRuleHandler) { + nsresult rv; uint32_t flags = 0; nsAutoString buf;
- nsresult rv = ReadInternetOption(aOptions, flags, buf); - if (NS_FAILED(rv)) { - return rv; - } - - if (!aFlagsHandler(flags)) { - return NS_ERROR_FAILURE; - } + rv = ReadInternetOption(INTERNET_PER_CONN_PROXY_BYPASS, flags, buf); + if (NS_FAILED(rv)) return false;
NS_ConvertUTF16toUTF8 cbuf(buf);
+ nsAutoCString host(aHost); int32_t start = 0; int32_t end = cbuf.Length(); + + // Windows formats its proxy override list in the form: + // server;server;server where 'server' is a server name pattern or IP + // address, or "<local>". "<local>" must be translated to + // "localhost;127.0.0.1". + // In a server name pattern, a '*' character matches any substring and + // all other characters must match themselves; the whole pattern must match + // the whole hostname. while (true) { int32_t delimiter = cbuf.FindCharInSet(" ;", start); if (delimiter == -1) delimiter = end;
if (delimiter != start) { - const nsAutoCString rule(Substring(cbuf, start, delimiter - start)); - bool continueProcessing = false; - aRuleHandler(rule, continueProcessing); - if (!continueProcessing) { - return NS_OK; + const nsAutoCString override(Substring(cbuf, start, delimiter - start)); + if (override.EqualsLiteral("<local>")) { + PRNetAddr addr; + bool isIpAddr = (PR_StringToNetAddr(host.get(), &addr) == PR_SUCCESS); + + // Don't use proxy for local hosts (plain hostname, no dots) + if (!isIpAddr && !host.Contains('.')) { + return true; + } + + if (host.EqualsLiteral("127.0.0.1") || host.EqualsLiteral("::1")) { + return true; + } + } else if (PatternMatch(host, override)) { + return true; } }
@@ -186,7 +141,7 @@ nsresult nsWindowsSystemProxySettings::ReadProxyRules( start = ++delimiter; }
- return NS_OK; + return false; }
bool nsWindowsSystemProxySettings::PatternMatch(const nsACString& aHost, @@ -215,322 +170,78 @@ nsresult nsWindowsSystemProxySettings::GetProxyForURI(const nsACString& aSpec, const nsACString& aHost, const int32_t aPort, nsACString& aResult) { - auto flagHandler = [&](uint32_t aFlags) { - if (!(aFlags & PROXY_TYPE_PROXY)) { - ProxyConfig::SetProxyResultDirect(aResult); - return false; - } + nsresult rv; + uint32_t flags = 0; + nsAutoString buf;
- if (MatchOverride(aHost)) { - ProxyConfig::SetProxyResultDirect(aResult); - return false; - } + rv = ReadInternetOption(INTERNET_PER_CONN_PROXY_SERVER, flags, buf); + if (NS_FAILED(rv) || !(flags & PROXY_TYPE_PROXY)) { + SetProxyResultDirect(aResult); + return NS_OK; + }
- return true; - }; + if (MatchOverride(aHost)) { + SetProxyResultDirect(aResult); + return NS_OK; + } + + NS_ConvertUTF16toUTF8 cbuf(buf);
constexpr auto kSocksPrefix = "socks="_ns; nsAutoCString prefix; ToLowerCase(aScheme, prefix); + prefix.Append('=');
nsAutoCString specificProxy; nsAutoCString defaultProxy; nsAutoCString socksProxy; + int32_t start = 0; + int32_t end = cbuf.Length();
- auto ruleHandler = [&](const nsACString& aRule, bool& aContinue) { - const nsCString proxy(aRule); - aContinue = true; - if (proxy.FindChar('=') == -1) { - // If a proxy name is listed by itself, it is used as the - // default proxy for any protocols that do not have a specific - // proxy specified. - // (http://msdn.microsoft.com/en-us/library/aa383996%28VS.85%29.aspx) - defaultProxy = proxy; - } else if (proxy.Find(prefix) == 0) { - // To list a proxy for a specific protocol, the string must - // follow the format "<protocol>=<protocol>://<proxy_name>". - // (http://msdn.microsoft.com/en-us/library/aa383996%28VS.85%29.aspx) - specificProxy = Substring(proxy, prefix.Length()); - aContinue = false; - } else if (proxy.Find(kSocksPrefix) == 0) { - // SOCKS proxy. - socksProxy = Substring(proxy, kSocksPrefix.Length()); // "socks=" length. - } - }; - - nsresult rv = - ReadProxyRules(INTERNET_PER_CONN_PROXY_SERVER, flagHandler, ruleHandler); - if (NS_FAILED(rv)) { - ProxyConfig::SetProxyResultDirect(aResult); - return rv; - } - - ProxyConfig::ProxyStrToResult(specificProxy, defaultProxy, socksProxy, - aResult); - return NS_OK; -} - -class WindowsSystemProxySettingsAsync final - : public nsWindowsSystemProxySettings, - public nsIObserver { - public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSISYSTEMPROXYSETTINGS - NS_DECL_NSIOBSERVER - - WindowsSystemProxySettingsAsync(); - nsresult Init() override; - - private: - virtual ~WindowsSystemProxySettingsAsync(); - void ThreadFunc(); - void OnProxyConfigChangedInternal(); - - ProxyConfig mConfig; - nsCOMPtr<nsIThread> mBackgroundThread; - mozilla::Mutex mLock{"WindowsSystemProxySettingsAsync"}; - mozilla::Atomic<bool> mInited{false}; - mozilla::Atomic<bool> mTerminated{false}; -}; - -NS_IMPL_ISUPPORTS_INHERITED(WindowsSystemProxySettingsAsync, - nsWindowsSystemProxySettings, nsIObserver); - -WindowsSystemProxySettingsAsync::WindowsSystemProxySettingsAsync() = default; - -WindowsSystemProxySettingsAsync::~WindowsSystemProxySettingsAsync() = default; - -nsresult WindowsSystemProxySettingsAsync::Init() { - nsCOMPtr<nsIObserverService> observerService = - mozilla::services::GetObserverService(); - if (!observerService) { - return NS_ERROR_FAILURE; - } - observerService->AddObserver(this, "xpcom-shutdown-threads", false); - - nsCOMPtr<nsIThread> thread; - if (NS_FAILED(NS_NewNamedThread("System Proxy", getter_AddRefs(thread)))) { - NS_WARNING("NS_NewNamedThread failed!"); - return NS_ERROR_FAILURE; - } - - mBackgroundThread = std::move(thread); - - nsCOMPtr<nsIRunnable> event = mozilla::NewRunnableMethod( - "WindowsSystemProxySettingsAsync::ThreadFunc", this, - &WindowsSystemProxySettingsAsync::ThreadFunc); - return mBackgroundThread->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL); -} - -NS_IMETHODIMP -WindowsSystemProxySettingsAsync::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) { - if (!strcmp(aTopic, "xpcom-shutdown-threads")) { - if (mBackgroundThread) { - mTerminated = true; - nsCOMPtr<nsIThread> thread; - { - mozilla::MutexAutoLock lock(mLock); - thread = mBackgroundThread.get(); - mBackgroundThread = nullptr; - } - MOZ_ALWAYS_SUCCEEDS(thread->Shutdown()); - } - } - return NS_OK; -} - -void WindowsSystemProxySettingsAsync::ThreadFunc() { - nsresult rv; - nsCOMPtr<nsIWindowsRegKey> regKey = - do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv); - if (NS_FAILED(rv)) { - return; - } - - rv = regKey->Open( - nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, - u"SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings"_ns, - nsIWindowsRegKey::ACCESS_READ); - if (NS_FAILED(rv)) { - return; - } - - OnProxyConfigChangedInternal(); - - rv = regKey->StartWatching(true); - if (NS_FAILED(rv)) { - return; - } - - mInited = true; - - while (!mTerminated) { - bool changed = false; - regKey->HasChanged(&changed); - if (changed) { - OnProxyConfigChangedInternal(); - } - } -} - -void WindowsSystemProxySettingsAsync::OnProxyConfigChangedInternal() { - ProxyConfig config; - - // PAC - nsAutoCString pacUrl; - if (NS_SUCCEEDED(GetPACURI(pacUrl))) { - config.SetPACUrl(pacUrl); - } + while (true) { + int32_t delimiter = cbuf.FindCharInSet(" ;", start); + if (delimiter == -1) delimiter = end;
- // proxies - auto flagHandler = [&](uint32_t aFlags) { - if (!(aFlags & PROXY_TYPE_PROXY)) { - return false; - } - return true; - }; - - // The format of input string is like: scheme=host:port, e.g. - // "http=127.0.0.1:3128". - auto processProxyStr = [](const nsCString& aInput, - ProxyServer::ProxyType& aOutType, - nsACString& aOutHost, int32_t& aOutPort) { - aOutType = ProxyServer::ProxyType::DEFAULT; - aOutHost = EmptyCString(); - aOutPort = -1; - - mozilla::Tokenizer t(aInput); - mozilla::Tokenizer::Token token; - // skip over spaces - t.SkipWhites(); - t.Record(); - - bool parsingIPv6 = false; - bool parsingPort = false; - while (t.Next(token)) { - if (token.Equals(mozilla::Tokenizer::Token::EndOfFile())) { - if (aOutHost.IsEmpty()) { - t.Claim(aOutHost); - } + if (delimiter != start) { + const nsAutoCString proxy(Substring(cbuf, start, delimiter - start)); + if (proxy.FindChar('=') == -1) { + // If a proxy name is listed by itself, it is used as the + // default proxy for any protocols that do not have a specific + // proxy specified. + // (http://msdn.microsoft.com/en-us/library/aa383996%28VS.85%29.aspx) + defaultProxy = proxy; + } else if (proxy.Find(prefix) == 0) { + // To list a proxy for a specific protocol, the string must + // follow the format "<protocol>=<protocol>://<proxy_name>". + // (http://msdn.microsoft.com/en-us/library/aa383996%28VS.85%29.aspx) + specificProxy = Substring(proxy, prefix.Length()); break; - } - - if (token.Equals(mozilla::Tokenizer::Token::Char('='))) { - nsAutoCString typeStr; - t.Claim(typeStr); - aOutType = ProxyConfig::ToProxyType(typeStr.get()); - t.Record(); - } - - if (token.Equals(mozilla::Tokenizer::Token::Char('['))) { - parsingIPv6 = true; - continue; - } - - if (!parsingIPv6 && token.Equals(mozilla::Tokenizer::Token::Char(':'))) { - // Port is starting. Claim the previous as host. - t.Claim(aOutHost); - t.Record(); - parsingPort = true; - continue; - } - - if (token.Equals(mozilla::Tokenizer::Token::Char(']'))) { - parsingIPv6 = false; - continue; + } else if (proxy.Find(kSocksPrefix) == 0) { + // SOCKS proxy. + socksProxy = + Substring(proxy, kSocksPrefix.Length()); // "socks=" length. } }
- if (parsingPort) { - nsAutoCString portStr; - t.Claim(portStr); - nsresult rv = NS_OK; - aOutPort = portStr.ToInteger(&rv); - if (NS_FAILED(rv)) { - aOutPort = -1; - } - } - }; - - auto ruleHandler = [&](const nsACString& aRule, bool& aContinue) { - const nsCString proxy(aRule); - aContinue = true; - ProxyServer::ProxyType type; - nsCString host; - int32_t port = -1; - processProxyStr(proxy, type, host, port); - if (!host.IsEmpty()) { - ProxyServer server(type, host, port); - config.Rules().mProxyServers[server.Type()] = std::move(server); - } - }; - - // Note that reading the proxy settings from registry directly is not - // documented by Microsoft, so doing it could be risky. We still use system - // API to read proxy settings for safe. - ReadProxyRules(INTERNET_PER_CONN_PROXY_SERVER, flagHandler, ruleHandler); - - auto bypassRuleHandler = [&](const nsACString& aOverrideRule, - bool& aContinue) { - aContinue = true; - config.ByPassRules().mExceptions.AppendElement(aOverrideRule); - }; - - auto dummyHandler = [](uint32_t aFlags) { return true; }; - ReadProxyRules(INTERNET_PER_CONN_PROXY_BYPASS, dummyHandler, - bypassRuleHandler); - - { - mozilla::MutexAutoLock lock(mLock); - mConfig = std::move(config); - } -} - -NS_IMETHODIMP -WindowsSystemProxySettingsAsync::GetMainThreadOnly(bool* aMainThreadOnly) { - return nsWindowsSystemProxySettings::GetMainThreadOnly(aMainThreadOnly); -} - -NS_IMETHODIMP WindowsSystemProxySettingsAsync::GetPACURI(nsACString& aResult) { - AUTO_PROFILER_LABEL("WindowsSystemProxySettingsAsync::GetPACURI", OTHER); - mozilla::MutexAutoLock lock(mLock); - aResult.Assign(mConfig.PACUrl()); - return NS_OK; -} - -NS_IMETHODIMP WindowsSystemProxySettingsAsync::GetProxyForURI( - const nsACString& aSpec, const nsACString& aScheme, const nsACString& aHost, - const int32_t aPort, nsACString& aResult) { - // Fallback to nsWindowsSystemProxySettings::GetProxyForURI if we failed to - // monitor the change of registry keys. - if (!mInited) { - return nsWindowsSystemProxySettings::GetProxyForURI(aSpec, aScheme, aHost, - aPort, aResult); + if (delimiter == end) break; + start = ++delimiter; }
- mozilla::MutexAutoLock lock(mLock); + if (!specificProxy.IsEmpty()) + SetProxyResult("PROXY", specificProxy, + aResult); // Protocol-specific proxy. + else if (!defaultProxy.IsEmpty()) + SetProxyResult("PROXY", defaultProxy, aResult); // Default proxy. + else if (!socksProxy.IsEmpty()) + SetProxyResult("SOCKS", socksProxy, aResult); // SOCKS proxy. + else + SetProxyResultDirect(aResult); // Direct connection.
- for (const auto& bypassRule : mConfig.ByPassRules().mExceptions) { - if (MatchOverrideInternal(aHost, bypassRule)) { - ProxyConfig::SetProxyResultDirect(aResult); - return NS_OK; - } - } - - mConfig.GetProxyString(aScheme, aResult); return NS_OK; }
NS_IMPL_COMPONENT_FACTORY(nsWindowsSystemProxySettings) { - auto settings = - mozilla::StaticPrefs::network_proxy_detect_system_proxy_changes() - ? mozilla::MakeRefPtr<WindowsSystemProxySettingsAsync>() - : mozilla::MakeRefPtr<nsWindowsSystemProxySettings>(); - if (NS_SUCCEEDED(settings->Init())) { - return settings.forget().downcast<nsISupports>(); - } - return nullptr; + return mozilla::MakeAndAddRef<nsWindowsSystemProxySettings>() + .downcast<nsISupports>(); }