910e62b5创建于 1月15日历史提交
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/common/webid/identity_url_loader_throttle.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "content/common/features.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/web_identity.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/webid/federated_auth_request.mojom.h"
#include "url/origin.h"

using blink::mojom::IdpSigninStatus;

namespace content {

class IdentityUrlLoaderThrottleTest : public testing::Test {
 protected:
  SetIdpStatusCallback CreateCallback() {
    return base::BindRepeating(&IdentityUrlLoaderThrottleTest::SetIdpStatus,
                               base::Unretained(this));
  }

  void SetIdpStatus(const url::Origin& origin, IdpSigninStatus status) {
    ++cb_num_calls_;
    cb_origin_ = origin;
    cb_signin_status_ = status;
  }

  base::HistogramTester histogram_tester_;
  int cb_num_calls_ = 0;
  url::Origin cb_origin_;
  IdpSigninStatus cb_signin_status_ = IdpSigninStatus::kSignedOut;
};

class IdentityUrlLoaderThrottleTestParameterized
    : public IdentityUrlLoaderThrottleTest,
      public testing::WithParamInterface<std::tuple<IdpSigninStatus, bool>> {};

TEST_P(IdentityUrlLoaderThrottleTestParameterized, Headers) {
  IdpSigninStatus signin_status = std::get<0>(GetParam());
  bool has_user_gesture = std::get<1>(GetParam());

  std::unique_ptr<blink::URLLoaderThrottle> throttle =
      MaybeCreateIdentityUrlLoaderThrottle(CreateCallback());
  ASSERT_NE(nullptr, throttle);

  network::ResourceRequest request;
  request.url = GURL("https://accounts.idp.example/");
  request.has_user_gesture = has_user_gesture;
  bool defer = false;

  throttle->WillStartRequest(&request, &defer);
  EXPECT_FALSE(defer);

  std::string header = base::StringPrintf(
      "set-login: logged-%s; foo=bar",
      signin_status == IdpSigninStatus::kSignedIn ? "in" : "out");

  network::mojom::URLResponseHead response_head;
  response_head.headers = net::HttpResponseHeaders::TryToCreate(
      base::StringPrintf("HTTP/1.1 200 OK\n%s\n", header.c_str()));
  throttle->WillProcessResponse(request.url, &response_head, &defer);
  EXPECT_FALSE(defer);

  EXPECT_EQ(1, cb_num_calls_);
  EXPECT_EQ(signin_status, cb_signin_status_);
  EXPECT_EQ(url::Origin::Create(GURL("https://accounts.idp.example/")),
            cb_origin_);
  if (signin_status == IdpSigninStatus::kSignedIn) {
    histogram_tester_.ExpectUniqueSample(
        "Blink.FedCm.IdpSigninRequestInitiatedByUser", has_user_gesture, 1);
  } else {
    histogram_tester_.ExpectUniqueSample(
        "Blink.FedCm.IdpSignoutRequestInitiatedByUser", has_user_gesture, 1);
  }
}

INSTANTIATE_TEST_SUITE_P(
    SignInOutAndUserGesture,
    IdentityUrlLoaderThrottleTestParameterized,
    testing::Combine(testing::Values(IdpSigninStatus::kSignedIn,
                                     IdpSigninStatus::kSignedOut),
                     testing::Values(false, true)));

TEST_F(IdentityUrlLoaderThrottleTest, NoRelevantHeader) {
  std::unique_ptr<blink::URLLoaderThrottle> throttle =
      MaybeCreateIdentityUrlLoaderThrottle(CreateCallback());
  ASSERT_NE(nullptr, throttle);

  network::ResourceRequest request;
  request.url = GURL("https://accounts.idp.example/");
  request.has_user_gesture = true;
  bool defer = false;

  throttle->WillStartRequest(&request, &defer);
  EXPECT_FALSE(defer);

  network::mojom::URLResponseHead response_head;
  response_head.headers =
      net::HttpResponseHeaders::TryToCreate("HTTP/1.1 200 OK\n");
  throttle->WillProcessResponse(request.url, &response_head, &defer);
  EXPECT_FALSE(defer);

  EXPECT_EQ(0, cb_num_calls_);
}

TEST_F(IdentityUrlLoaderThrottleTest, HeaderHasToken) {
  scoped_refptr<net::HttpResponseHeaders> headers =
      net::HttpResponseHeaders::TryToCreate("HTTP/1.1 200 OK\n");
  EXPECT_FALSE(
      IdentityUrlLoaderThrottle::HeaderHasToken(*headers, "Signin", "val"));

  headers =
      net::HttpResponseHeaders::TryToCreate("HTTP/1.1 200 OK\nSignin: val");
  EXPECT_TRUE(
      IdentityUrlLoaderThrottle::HeaderHasToken(*headers, "Signin", "val"));

  headers = net::HttpResponseHeaders::TryToCreate(
      "HTTP/1.1 200 OK\nSignIn: val; foo=bar");
  EXPECT_TRUE(
      IdentityUrlLoaderThrottle::HeaderHasToken(*headers, "Signin", "val"));

  headers = net::HttpResponseHeaders::TryToCreate(
      "HTTP/1.1 200 OK\nSignin:  val ; foo=bar");
  EXPECT_TRUE(
      IdentityUrlLoaderThrottle::HeaderHasToken(*headers, "Signin", "val"));

  headers = net::HttpResponseHeaders::TryToCreate(
      "HTTP/1.1 200 OK\nSignin:  val ; type=idp; foo=bar");
  EXPECT_TRUE(IdentityUrlLoaderThrottle::HeaderHasToken(*headers, "Signin",
                                                        "type=idp"));
}

}  // namespace content