1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/base64.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "chrome/browser/ash/dbus/proxy_resolution_service_provider.h"
#include "chrome/browser/ash/login/login_manager_test.h"
#include "chrome/browser/ash/login/test/login_manager_mixin.h"
#include "chrome/browser/ash/net/system_proxy_manager.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/mixin_based_in_process_browser_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
namespace ash {
namespace {
constexpr char kLocalProxyUrl[] = "localhost:3128";
// Encode the PAC script as a data: URL.
std::string GetPacUrl(const char* pac_data) {
std::string b64_encoded = base::Base64Encode(pac_data);
return "data:application/x-javascript-config;base64," + b64_encoded;
}
} // namespace
// Helper for calling ProxyResolutionServiceProvider's |ResolveProxyInternal()|
// method. Unlike the unit-tests which mock the network setup, this uses the
// default dependencies from the running browser.
class ProxyResolutionServiceProviderTestWrapper {
public:
ProxyResolutionServiceProviderTestWrapper() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
ProxyResolutionServiceProviderTestWrapper(
const ProxyResolutionServiceProviderTestWrapper&) = delete;
ProxyResolutionServiceProviderTestWrapper& operator=(
const ProxyResolutionServiceProviderTestWrapper&) = delete;
~ProxyResolutionServiceProviderTestWrapper() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
// Calls ResolveProxyInternal() and returns its result synchronously as a
// single string (which may be prefixed by "ERROR: " if it is an error message
// as opposed to a proxy result).
std::string ResolveProxyAndWait(const std::string& url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
base::RunLoop run_loop;
std::string result;
impl_.ResolveProxyInternal(
url,
base::BindOnce(
&ProxyResolutionServiceProviderTestWrapper::OnResolveProxyComplete,
&result, run_loop.QuitClosure()),
chromeos::SystemProxyOverride::kDefault);
run_loop.Run();
return result;
}
private:
static void OnResolveProxyComplete(std::string* result,
base::RepeatingClosure quit_closure,
const std::string& error,
const std::string& pac_string) {
if (!error.empty()) {
*result = "ERROR: " + error;
} else {
*result = pac_string;
}
std::move(quit_closure).Run();
}
ProxyResolutionServiceProvider impl_;
};
// Base test fixture that exposes a way to invoke ProxyResolutionServiceProvider
// synchronously from the UI thread.
class ProxyResolutionServiceProviderBaseBrowserTest
: public MixinBasedInProcessBrowserTest {
public:
void SetUpOnMainThread() override {
MixinBasedInProcessBrowserTest::SetUpOnMainThread();
proxy_service_ =
std::make_unique<ProxyResolutionServiceProviderTestWrapper>();
}
void TearDownOnMainThread() override {
proxy_service_.reset();
MixinBasedInProcessBrowserTest::TearDownOnMainThread();
}
std::string ResolveProxyAndWait(const std::string& source_url) {
return proxy_service_->ResolveProxyAndWait(source_url);
}
private:
std::unique_ptr<ProxyResolutionServiceProviderTestWrapper> proxy_service_;
};
// Fixture that launches the browser with --proxy-server="https://proxy.test".
class ProxyResolutionServiceProviderManualProxyBrowserTest
: public ProxyResolutionServiceProviderBaseBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kProxyServer,
"https://proxy.test");
}
};
// Tests that the D-Bus proxy resolver returns the correct result when using
// --proxy-server flag. These resolutions will happen synchronously at the //net
// layer.
IN_PROC_BROWSER_TEST_F(ProxyResolutionServiceProviderManualProxyBrowserTest,
ResolveProxy) {
EXPECT_EQ("HTTPS proxy.test:443",
ResolveProxyAndWait("http://www.google.com"));
}
// Simple PAC script that returns the same two proxies for all requests.
const char kPacData[] =
"function FindProxyForURL(url, host) {\n"
" return 'PROXY foo1; PROXY foo2';\n"
"}\n";
// Fixture that launches the browser with --proxy-pac-url="data:...".
class ProxyResolutionServiceProviderPacBrowserTest
: public ProxyResolutionServiceProviderBaseBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kProxyPacUrl,
GetPacUrl(kPacData));
}
};
// Tests that the D-Bus proxy resolver returns the correct result when using
// --proxy-pac-url flag. These resolutions will happen asynchronously at the
// //net layer, as they need to query a PAC script.
IN_PROC_BROWSER_TEST_F(ProxyResolutionServiceProviderPacBrowserTest,
ResolveProxy) {
EXPECT_EQ("PROXY foo1:80;PROXY foo2:80",
ResolveProxyAndWait("http://www.google.com"));
}
// PAC script that returns a proxy for all url except for a whitelisted domain.
const char kPacDataWithWhitelistedDomain[] =
"function FindProxyForURL(url, host) {\n"
" if (dnsDomainIs(host, '.direct.com'))\n"
" return 'DIRECT';\n"
" return 'PROXY foo1';\n"
"}\n";
// Fixture that launches the browser with --proxy-pac-url="data:..." and
// System-proxy enabled. With System-proxy enabled and configured, all system
// service connections going trough an http web proxy will be connected through
// a local proxy that will perform the proxy authentication and connection
// setup.
class ProxyResolutionServiceProviderSystemProxyPolicyTest
: public ProxyResolutionServiceProviderBaseBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kProxyPacUrl,
GetPacUrl(kPacDataWithWhitelistedDomain));
}
protected:
void SetLocalProxyAddress(const std::string& local_proxy_url) {
SystemProxyManager::Get()->SetSystemProxyEnabledForTest(true);
SystemProxyManager::Get()->SetSystemServicesProxyUrlForTest(
local_proxy_url);
}
};
// Tests that the proxy resolver returns the address of the local proxy when
// set.
IN_PROC_BROWSER_TEST_F(ProxyResolutionServiceProviderSystemProxyPolicyTest,
ResolveProxyLocalProxySet) {
SetLocalProxyAddress(kLocalProxyUrl);
EXPECT_EQ("PROXY localhost:3128; PROXY foo1:80",
ResolveProxyAndWait("http://www.google.com"));
}
// Tests that the proxy list semicolon separator is not appended if the local
// proxy is not set.
IN_PROC_BROWSER_TEST_F(ProxyResolutionServiceProviderSystemProxyPolicyTest,
ResolveProxyNoSeparator) {
SetLocalProxyAddress(/* local_proxy_url= */ std::string());
EXPECT_EQ("PROXY foo1:80", ResolveProxyAndWait("http://www.google.com"));
}
// Tests that the proxy resolver doesn't return the local proxy address for
// DIRECT connections.
IN_PROC_BROWSER_TEST_F(ProxyResolutionServiceProviderSystemProxyPolicyTest,
ResolveProxyDirect) {
SetLocalProxyAddress(kLocalProxyUrl);
EXPECT_EQ("DIRECT", ResolveProxyAndWait("http://www.test.direct.com"));
}
class ProxyResolutionServiceAtLoginScreen
: public ProxyResolutionServiceProviderBaseBrowserTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kProxyPacUrl,
GetPacUrl(kPacData));
}
protected:
LoginManagerMixin login_manager_{&mixin_host_};
};
// Tests that the D-Bus proxy resolver returns the proxy configured at the
// sign-in screen.
IN_PROC_BROWSER_TEST_F(ProxyResolutionServiceAtLoginScreen, ResolveProxy) {
EXPECT_EQ("PROXY foo1:80;PROXY foo2:80",
ResolveProxyAndWait("http://www.google.com"));
}
} // namespace ash
|