blob: e0527e622ab652e96cccc94c49c1b15cde900eae [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/net/chrome_mojo_proxy_resolver_win.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/time/time.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/browser/service_process_host.h"
#include "content/public/test/browser_test.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/proxy_resolution/proxy_list.h"
#include "net/proxy_resolution/win/winhttp_status.h"
#include "services/proxy_resolver_win/public/mojom/proxy_resolver_win.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace {
constexpr char kTestUrl[] = "https://example.test/";
class ProxyResolverProcessObserver
: public content::ServiceProcessHost::Observer {
public:
ProxyResolverProcessObserver() {
content::ServiceProcessHost::AddObserver(this);
}
ProxyResolverProcessObserver(const ProxyResolverProcessObserver&) = delete;
ProxyResolverProcessObserver& operator=(const ProxyResolverProcessObserver&) =
delete;
~ProxyResolverProcessObserver() override {
content::ServiceProcessHost::RemoveObserver(this);
}
bool is_service_running() const { return is_service_running_; }
void WaitForLaunch() { launch_loop_.Run(); }
void WaitForDeath() { death_loop_.Run(); }
private:
// content::ServiceProcessHost::Observer:
void OnServiceProcessLaunched(
const content::ServiceProcessInfo& info) override {
if (!info.IsService<
proxy_resolver_win::mojom::WindowsSystemProxyResolver>()) {
return;
}
EXPECT_FALSE(is_service_running_);
is_service_running_ = true;
launch_loop_.Quit();
}
void OnServiceProcessTerminatedNormally(
const content::ServiceProcessInfo& info) override {
if (!info.IsService<
proxy_resolver_win::mojom::WindowsSystemProxyResolver>()) {
return;
}
EXPECT_TRUE(is_service_running_);
is_service_running_ = false;
death_loop_.Quit();
}
private:
bool is_service_running_ = false;
base::RunLoop launch_loop_;
base::RunLoop death_loop_;
};
using ChromeMojoProxyResolverWinBrowserTest = InProcessBrowserTest;
// Ensures the proxy resolver service is started correctly and stopped when no
// resolvers are open.
IN_PROC_BROWSER_TEST_F(ChromeMojoProxyResolverWinBrowserTest,
ServiceLifecycle) {
// Set up the ProxyResolverFactory.
mojo::Remote<proxy_resolver_win::mojom::WindowsSystemProxyResolver>
proxy_resolver_win(
ChromeMojoProxyResolverWin::CreateWithSelfOwnedReceiverForTesting(
base::TimeDelta()));
ProxyResolverProcessObserver observer;
// Attempt to resolve a proxy. This should create and start the service.
base::RunLoop proxy_resolution_1;
proxy_resolver_win->GetProxyForUrl(
GURL(kTestUrl),
base::BindLambdaForTesting(
[&](const net::ProxyList& proxy_list,
net::WinHttpStatus winhttp_status,
int windows_error) { proxy_resolution_1.Quit(); }));
observer.WaitForLaunch();
// Resolve another proxy. No new service should be created (the listener will
// assert if that's the case).
base::RunLoop proxy_resolution_2;
proxy_resolver_win->GetProxyForUrl(
GURL(kTestUrl),
base::BindLambdaForTesting(
[&](const net::ProxyList& proxy_list,
net::WinHttpStatus winhttp_status,
int windows_error) { proxy_resolution_2.Quit(); }));
EXPECT_TRUE(observer.is_service_running());
// Wait for proxy resolution to complete. Once that's done, the service should
// go away.
proxy_resolution_1.Run();
proxy_resolution_2.Run();
observer.WaitForDeath();
}
// Same as above, but destroys the WindowsSystemProxyResolver, which should have
// no impact on service lifetime.
IN_PROC_BROWSER_TEST_F(ChromeMojoProxyResolverWinBrowserTest, DestroyResolver) {
mojo::Remote<proxy_resolver_win::mojom::WindowsSystemProxyResolver>
proxy_resolver_win(
ChromeMojoProxyResolverWin::CreateWithSelfOwnedReceiverForTesting(
base::TimeDelta()));
ProxyResolverProcessObserver observer;
// Attempt to resolve a proxy. This should create and start the service.
proxy_resolver_win->GetProxyForUrl(
GURL(kTestUrl),
base::BindLambdaForTesting([&](const net::ProxyList& proxy_list,
net::WinHttpStatus winhttp_status,
int windows_error) {
ADD_FAILURE() << "The GetProxyForURL callback should be dropped";
}));
observer.WaitForLaunch();
// Destroy the resolver. The callback will never hit and the service should
// eventually go away.
proxy_resolver_win.reset();
EXPECT_TRUE(observer.is_service_running());
observer.WaitForDeath();
}
// Make sure the service can be started again after it's been stopped.
IN_PROC_BROWSER_TEST_F(ChromeMojoProxyResolverWinBrowserTest,
DestroyAndCreateService) {
mojo::Remote<proxy_resolver_win::mojom::WindowsSystemProxyResolver>
proxy_resolver_win(
ChromeMojoProxyResolverWin::CreateWithSelfOwnedReceiverForTesting(
base::TimeDelta()));
ProxyResolverProcessObserver observer;
// Attempt to resolve a proxy. This should create and start the service.
base::RunLoop proxy_resolution_1;
proxy_resolver_win->GetProxyForUrl(
GURL(kTestUrl),
base::BindLambdaForTesting(
[&](const net::ProxyList& proxy_list,
net::WinHttpStatus winhttp_status,
int windows_error) { proxy_resolution_1.Quit(); }));
observer.WaitForLaunch();
// Wait for proxy resolution to complete. Once that's done, the service should
// go away.
proxy_resolution_1.Run();
observer.WaitForDeath();
ProxyResolverProcessObserver observer2;
// Attempt to resolve another proxy. This should recreate and start the
// service.
base::RunLoop proxy_resolution_2;
proxy_resolver_win->GetProxyForUrl(
GURL(kTestUrl),
base::BindLambdaForTesting(
[&](const net::ProxyList& proxy_list,
net::WinHttpStatus winhttp_status,
int windows_error) { proxy_resolution_2.Quit(); }));
observer2.WaitForLaunch();
// Wait for proxy resolution to complete again. Once that's done, the service
// should go away.
proxy_resolution_2.Run();
observer2.WaitForDeath();
}
} // namespace