File: client_hints_preferences.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (143 lines) | stat: -rw-r--r-- 5,176 bytes parent folder | download | duplicates (9)
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
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"

#include "base/command_line.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/client_hints.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/switches.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "url/origin.h"

namespace blink {

ClientHintsPreferences::ClientHintsPreferences() {
  DCHECK_LE(
      network::GetClientHintToNameMap().size(),
      static_cast<size_t>(network::mojom::WebClientHintsType::kMaxValue) + 1);
}

void ClientHintsPreferences::UpdateFrom(
    const ClientHintsPreferences& preferences) {
  for (const auto& elem : network::GetClientHintToNameMap()) {
    const auto& type = elem.first;
    enabled_hints_.SetIsEnabled(type, preferences.ShouldSend(type));
  }
}

void ClientHintsPreferences::CombineWith(
    const ClientHintsPreferences& preferences) {
  for (const auto& elem : network::GetClientHintToNameMap()) {
    const auto& type = elem.first;
    if (preferences.ShouldSend(type))
      SetShouldSend(type);
  }
}

bool ClientHintsPreferences::UpdateFromMetaCH(const String& header_value,
                                              const KURL& url,
                                              Context* context,
                                              network::MetaCHType type,
                                              bool is_doc_preloader,
                                              bool is_sync_parser) {
  // Client hints should be allowed only on secure URLs.
  if (!IsClientHintsAllowed(url))
    return false;

  // 8-bit conversions from String can turn non-ASCII characters into ?,
  // turning syntax errors into "correct" syntax, so reject those first.
  // (.Utf8() doesn't have this problem, but it does a lot of expensive
  //  work that would be wasted feeding to an ASCII-only syntax).
  if (!header_value.ContainsOnlyASCIIOrEmpty())
    return false;

  switch (type) {
    case network::MetaCHType::HttpEquivAcceptCH: {
      // Note: .Ascii() would convert tab to ?, which is undesirable.
      std::optional<std::vector<network::mojom::WebClientHintsType>> parsed_ch =
          network::ParseClientHintsHeader(header_value.Latin1());

      if (!parsed_ch.has_value())
        return false;

      // Update first-party permissions for each client hint.
      for (network::mojom::WebClientHintsType newly_enabled :
           parsed_ch.value()) {
        enabled_hints_.SetIsEnabled(newly_enabled, true);
        if (context && !is_doc_preloader) {
          ukm::builders::ClientHints_AcceptCHMetaUsage(
              context->GetUkmSourceId())
              .SetType(static_cast<int64_t>(newly_enabled))
              .Record(context->GetUkmRecorder());
        }
      }
      break;
    }
    case network::MetaCHType::HttpEquivDelegateCH: {
      if (!is_doc_preloader && !is_sync_parser) {
        break;
      }

      // Note: .Ascii() would convert tab to ?, which is undesirable.
      network::ClientHintToDelegatedThirdPartiesHeader parsed_ch =
          network::ParseClientHintToDelegatedThirdPartiesHeader(
              header_value.Latin1(), type);

      if (parsed_ch.map.empty())
        return false;

      // Update first-party permissions for each client hint.
      for (const auto& pair : parsed_ch.map) {
        enabled_hints_.SetIsEnabled(pair.first, true);
        if (context && !is_doc_preloader) {
          ukm::builders::ClientHints_DelegateCHMetaUsage(
              context->GetUkmSourceId())
              .SetType(static_cast<int64_t>(pair.first))
              .Record(context->GetUkmRecorder());
        }
      }
      break;
    }
  }

  if (context) {
    for (const auto& elem : network::GetClientHintToNameMap()) {
      const auto& hint_type = elem.first;
      if (enabled_hints_.IsEnabled(hint_type))
        context->CountClientHints(hint_type);
    }
  }
  return true;
}

// static
bool ClientHintsPreferences::IsClientHintsAllowed(const KURL& url) {
  // TODO(crbug.com/862940): This should probably be using
  // network::IsUrlPotentiallyTrustworthy() instead of coercing the URL to an
  // origin first.
  return (url.ProtocolIs("http") || url.ProtocolIs("https")) &&
         network::IsOriginPotentiallyTrustworthy(
             url::Origin::Create(GURL(url)));
}

EnabledClientHints ClientHintsPreferences::GetEnabledClientHints() const {
  return enabled_hints_;
}

bool ClientHintsPreferences::ShouldSend(
    network::mojom::WebClientHintsType type) const {
  return enabled_hints_.IsEnabled(type);
}

void ClientHintsPreferences::SetShouldSend(
    network::mojom::WebClientHintsType type) {
  enabled_hints_.SetIsEnabled(type, true);
}

}  // namespace blink