blob: f80f360d0cabc89053a07a3fc0bdabd0732b7774 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/strings/strcat.h"
#include "components/signin/core/browser/signin_header_helper.h"
#include "google_apis/gaia/gaia_switches.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/escape.h"
#include "net/base/url_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "weblayer/browser/browser_impl.h"
#include "weblayer/browser/profile_impl.h"
#include "weblayer/browser/signin_url_loader_throttle.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/public/google_accounts_delegate.h"
#include "weblayer/public/navigation_controller.h"
#include "weblayer/shell/browser/shell.h"
#include "weblayer/test/test_navigation_observer.h"
#include "weblayer/test/weblayer_browser_test.h"
#include "weblayer/test/weblayer_browser_test_utils.h"
namespace weblayer {
namespace {
constexpr char kGaiaDomain[] = "fakegaia.com";
constexpr char kGoogleAccountsPath[] = "/manageaccounts";
constexpr char kGoogleAccountsRedirectPath[] = "/manageaccounts-redirect";
} // namespace
class GoogleAccountsBrowserTest : public WebLayerBrowserTest,
public GoogleAccountsDelegate {
public:
// WebLayerBrowserTest:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
shell()->tab()->SetGoogleAccountsDelegate(this);
}
void SetUpCommandLine(base::CommandLine* command_line) override {
https_server_.RegisterRequestHandler(base::BindRepeating(
&GoogleAccountsBrowserTest::HandleGoogleAccountsRequest,
base::Unretained(this)));
net::test_server::RegisterDefaultHandlers(&https_server_);
ASSERT_TRUE(https_server_.Start());
command_line->AppendSwitchASCII(switches::kGaiaUrl, GetGaiaURL("/").spec());
command_line->AppendSwitch("ignore-certificate-errors");
}
// GoogleAccountsDelegate:
void OnGoogleAccountsRequest(
const signin::ManageAccountsParams& params) override {
params_ = params;
if (run_loop_)
run_loop_->Quit();
}
std::string GetGaiaId() override { return ""; }
const signin::ManageAccountsParams& WaitForGoogleAccounts() {
if (!params_) {
run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
}
EXPECT_TRUE(params_.has_value());
return params_.value();
}
GURL GetGaiaURL(const std::string& path) {
return https_server_.GetURL(kGaiaDomain, path);
}
GURL GetNonGaiaURL(const std::string& path) {
return https_server_.GetURL(path);
}
bool HasReceivedGoogleAccountsResponse() { return params_.has_value(); }
std::string GetBody() {
return ExecuteScript(shell(), "document.body.innerText", true).GetString();
}
protected:
std::string response_header_;
private:
std::unique_ptr<net::test_server::HttpResponse> HandleGoogleAccountsRequest(
const net::test_server::HttpRequest& request) {
std::string path = request.GetURL().path();
if (path != kSignOutPath && path != kGoogleAccountsPath &&
path != kGoogleAccountsRedirectPath) {
return nullptr;
}
auto http_response =
std::make_unique<net::test_server::BasicHttpResponse>();
if (path == kGoogleAccountsRedirectPath) {
http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response->AddCustomHeader(
"Location",
net::UnescapeBinaryURLComponent(request.GetURL().query_piece()));
} else {
http_response->set_code(net::HTTP_OK);
}
if (base::Contains(request.headers, signin::kChromeConnectedHeader)) {
http_response->AddCustomHeader(signin::kChromeManageAccountsHeader,
response_header_);
}
http_response->set_content("");
return http_response;
}
net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
base::Optional<signin::ManageAccountsParams> params_;
std::unique_ptr<base::RunLoop> run_loop_;
};
IN_PROC_BROWSER_TEST_F(GoogleAccountsBrowserTest, Basic) {
response_header_ =
"action=ADDSESSION,email=foo@bar.com,"
"continue_url=https://blah.com,is_same_tab=true";
NavigateAndWaitForCompletion(GetGaiaURL(kGoogleAccountsPath), shell());
const signin::ManageAccountsParams& params = WaitForGoogleAccounts();
EXPECT_EQ(params.service_type, signin::GAIA_SERVICE_TYPE_ADDSESSION);
EXPECT_EQ(params.email, "foo@bar.com");
EXPECT_EQ(params.continue_url, "https://blah.com");
EXPECT_TRUE(params.is_same_tab);
}
IN_PROC_BROWSER_TEST_F(GoogleAccountsBrowserTest, NonGaiaUrl) {
response_header_ = "action=ADDSESSION";
NavigateAndWaitForCompletion(GetNonGaiaURL(kGoogleAccountsPath), shell());
// Navigate again to make sure the manage accounts response would have been
// received.
NavigateAndWaitForCompletion(GetNonGaiaURL("/echo"), shell());
EXPECT_FALSE(HasReceivedGoogleAccountsResponse());
}
IN_PROC_BROWSER_TEST_F(GoogleAccountsBrowserTest, RedirectFromGaiaURL) {
response_header_ = "action=SIGNUP";
GURL final_url = GetGaiaURL(kGoogleAccountsPath);
TestNavigationObserver test_observer(
final_url, TestNavigationObserver::NavigationEvent::kCompletion,
shell()->tab());
shell()->tab()->GetNavigationController()->Navigate(GetNonGaiaURL(
base::StrCat({kGoogleAccountsRedirectPath, "?", final_url.spec()})));
test_observer.Wait();
const signin::ManageAccountsParams& params = WaitForGoogleAccounts();
EXPECT_EQ(params.service_type, signin::GAIA_SERVICE_TYPE_SIGNUP);
}
IN_PROC_BROWSER_TEST_F(GoogleAccountsBrowserTest, RedirectToGaiaURL) {
response_header_ = "action=SIGNUP";
GURL final_url = GetNonGaiaURL(kGoogleAccountsPath);
TestNavigationObserver test_observer(
final_url, TestNavigationObserver::NavigationEvent::kCompletion,
shell()->tab());
shell()->tab()->GetNavigationController()->Navigate(GetGaiaURL(
base::StrCat({kGoogleAccountsRedirectPath, "?", final_url.spec()})));
test_observer.Wait();
const signin::ManageAccountsParams& params = WaitForGoogleAccounts();
EXPECT_EQ(params.service_type, signin::GAIA_SERVICE_TYPE_SIGNUP);
}
IN_PROC_BROWSER_TEST_F(GoogleAccountsBrowserTest, AddsQueryParamsToSignoutURL) {
response_header_ = "action=SIGNUP";
// Sign out URL on the GAIA domain will get a query param added to it.
GURL sign_out_url = GetGaiaURL(kSignOutPath);
GURL sign_out_url_with_params =
net::AppendQueryParameter(sign_out_url, "manage", "true");
{
TestNavigationObserver test_observer(
sign_out_url_with_params,
TestNavigationObserver::NavigationEvent::kCompletion, shell()->tab());
shell()->tab()->GetNavigationController()->Navigate(sign_out_url);
test_observer.Wait();
}
// Other URLs will not have query param added.
NavigateAndWaitForCompletion(GetGaiaURL(kGoogleAccountsPath), shell());
NavigateAndWaitForCompletion(GetNonGaiaURL(kSignOutPath), shell());
// Redirecting to sign out URL will also add params.
{
TestNavigationObserver test_observer(
sign_out_url_with_params,
TestNavigationObserver::NavigationEvent::kCompletion, shell()->tab());
shell()->tab()->GetNavigationController()->Navigate(
GetNonGaiaURL("/server-redirect?" + sign_out_url.spec()));
test_observer.Wait();
}
}
IN_PROC_BROWSER_TEST_F(GoogleAccountsBrowserTest, AddsRequestHeaderToGaiaURLs) {
const std::string path =
base::StrCat({"/echoheader?", signin::kChromeConnectedHeader});
NavigateAndWaitForCompletion(GetGaiaURL(path), shell());
EXPECT_EQ(GetBody(),
"source=WebLayer,mode=3,enable_account_consistency=true,"
"consistency_enabled_by_default=false");
// Non GAIA URL should not get the header.
NavigateAndWaitForCompletion(GetNonGaiaURL(path), shell());
EXPECT_EQ(GetBody(), "None");
}
class IncognitoGoogleAccountsBrowserTest : public GoogleAccountsBrowserTest {
public:
IncognitoGoogleAccountsBrowserTest() { SetShellStartsInIncognitoMode(); }
};
IN_PROC_BROWSER_TEST_F(IncognitoGoogleAccountsBrowserTest,
HeaderAddedForIncognitoBrowser) {
const std::string path =
base::StrCat({"/echoheader?", signin::kChromeConnectedHeader});
NavigateAndWaitForCompletion(GetGaiaURL(path), shell());
EXPECT_EQ(GetBody(),
"source=WebLayer,mode=3,enable_account_consistency=true,"
"consistency_enabled_by_default=false");
}
} // namespace weblayer